summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/acorn/block/mfmhd.c36
-rw-r--r--drivers/acorn/char/i2c.c1
-rw-r--r--drivers/acpi/Kconfig3
-rw-r--r--drivers/acpi/asus_acpi.c35
-rw-r--r--drivers/acpi/ec.c289
-rw-r--r--drivers/acpi/osl.c4
-rw-r--r--drivers/acpi/pci_irq.c7
-rw-r--r--drivers/acpi/processor_core.c30
-rw-r--r--drivers/acpi/processor_idle.c148
-rw-r--r--drivers/acpi/processor_perflib.c4
-rw-r--r--drivers/acpi/processor_thermal.c7
-rw-r--r--drivers/acpi/processor_throttling.c7
-rw-r--r--drivers/acpi/scan.c27
-rw-r--r--drivers/acpi/sleep/poweroff.c15
-rw-r--r--drivers/acpi/sleep/sleep.h2
-rw-r--r--drivers/acpi/sleep/wakeup.c6
-rw-r--r--drivers/acpi/tables.c4
-rw-r--r--drivers/acpi/video.c8
-rw-r--r--drivers/amba/Makefile2
-rw-r--r--drivers/amba/bus.c358
-rw-r--r--drivers/atm/nicstar.c5
-rw-r--r--drivers/atm/zatm.c12
-rw-r--r--drivers/base/core.c4
-rw-r--r--drivers/base/cpu.c30
-rw-r--r--drivers/base/dd.c12
-rw-r--r--drivers/base/driver.c5
-rw-r--r--drivers/base/firmware_class.c3
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power/shutdown.c9
-rw-r--r--drivers/block/DAC960.c39
-rw-r--r--drivers/block/acsi.c26
-rw-r--r--drivers/block/amiflop.c55
-rw-r--r--drivers/block/aoe/aoeblk.c26
-rw-r--r--drivers/block/ataflop.c29
-rw-r--r--drivers/block/cciss.c198
-rw-r--r--drivers/block/cciss.h10
-rw-r--r--drivers/block/cciss_scsi.c2
-rw-r--r--drivers/block/cpqarray.c40
-rw-r--r--drivers/block/floppy.c45
-rw-r--r--drivers/block/loop.c33
-rw-r--r--drivers/block/nbd.c1
-rw-r--r--drivers/block/paride/pd.c34
-rw-r--r--drivers/block/paride/pf.c50
-rw-r--r--drivers/block/pktcdvd.c16
-rw-r--r--drivers/block/ps2esdi.c26
-rw-r--r--drivers/block/swim3.c38
-rw-r--r--drivers/block/sx8.c49
-rw-r--r--drivers/block/umem.c43
-rw-r--r--drivers/block/viodasd.c76
-rw-r--r--drivers/block/xd.c31
-rw-r--r--drivers/bluetooth/hci_bcsp.c2
-rw-r--r--drivers/bluetooth/hci_ldisc.c16
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/cdrom/cm206.c2
-rw-r--r--drivers/cdrom/viocd.c6
-rw-r--r--drivers/char/Kconfig39
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/sworks-agp.c1
-rw-r--r--drivers/char/amiserial.c56
-rw-r--r--drivers/char/cs5535_gpio.c250
-rw-r--r--drivers/char/cyclades.c91
-rw-r--r--drivers/char/drm/Makefile4
-rw-r--r--drivers/char/drm/ati_pcigart.c23
-rw-r--r--drivers/char/drm/drm.h4
-rw-r--r--drivers/char/drm/drmP.h122
-rw-r--r--drivers/char/drm/drm_agpsupport.c133
-rw-r--r--drivers/char/drm/drm_bufs.c49
-rw-r--r--drivers/char/drm/drm_context.c2
-rw-r--r--drivers/char/drm/drm_core.h4
-rw-r--r--drivers/char/drm/drm_drv.c152
-rw-r--r--drivers/char/drm/drm_fops.c317
-rw-r--r--drivers/char/drm/drm_init.c53
-rw-r--r--drivers/char/drm/drm_ioc32.c1
-rw-r--r--drivers/char/drm/drm_ioctl.c27
-rw-r--r--drivers/char/drm/drm_lock.c1
-rw-r--r--drivers/char/drm/drm_memory.c8
-rw-r--r--drivers/char/drm/drm_memory_debug.h269
-rw-r--r--drivers/char/drm/drm_os_linux.h1
-rw-r--r--drivers/char/drm/drm_pciids.h12
-rw-r--r--drivers/char/drm/drm_proc.c16
-rw-r--r--drivers/char/drm/drm_stub.c63
-rw-r--r--drivers/char/drm/drm_sysfs.c68
-rw-r--r--drivers/char/drm/i810_dma.c49
-rw-r--r--drivers/char/drm/i810_drv.c60
-rw-r--r--drivers/char/drm/i810_drv.h10
-rw-r--r--drivers/char/drm/i830_dma.c47
-rw-r--r--drivers/char/drm/i830_drv.c57
-rw-r--r--drivers/char/drm/i830_drv.h8
-rw-r--r--drivers/char/drm/i915_dma.c52
-rw-r--r--drivers/char/drm/i915_drm.h6
-rw-r--r--drivers/char/drm/i915_drv.c66
-rw-r--r--drivers/char/drm/i915_drv.h44
-rw-r--r--drivers/char/drm/i915_ioc32.c1
-rw-r--r--drivers/char/drm/i915_irq.c48
-rw-r--r--drivers/char/drm/i915_mem.c5
-rw-r--r--drivers/char/drm/mga_dma.c158
-rw-r--r--drivers/char/drm/mga_drv.c58
-rw-r--r--drivers/char/drm/mga_drv.h14
-rw-r--r--drivers/char/drm/mga_ioc32.c1
-rw-r--r--drivers/char/drm/mga_state.c26
-rw-r--r--drivers/char/drm/r128_cce.c15
-rw-r--r--drivers/char/drm/r128_drm.h4
-rw-r--r--drivers/char/drm/r128_drv.c48
-rw-r--r--drivers/char/drm/r128_drv.h8
-rw-r--r--drivers/char/drm/r128_ioc32.c1
-rw-r--r--drivers/char/drm/r128_irq.c4
-rw-r--r--drivers/char/drm/r128_state.c44
-rw-r--r--drivers/char/drm/r300_cmdbuf.c38
-rw-r--r--drivers/char/drm/r300_reg.h1
-rw-r--r--drivers/char/drm/radeon_cp.c106
-rw-r--r--drivers/char/drm/radeon_drm.h6
-rw-r--r--drivers/char/drm/radeon_drv.c62
-rw-r--r--drivers/char/drm/radeon_drv.h41
-rw-r--r--drivers/char/drm/radeon_ioc32.c1
-rw-r--r--drivers/char/drm/radeon_state.c246
-rw-r--r--drivers/char/drm/savage_bci.c81
-rw-r--r--drivers/char/drm/savage_drv.c50
-rw-r--r--drivers/char/drm/savage_drv.h29
-rw-r--r--drivers/char/drm/savage_state.c324
-rw-r--r--drivers/char/drm/sis_drm.h25
-rw-r--r--drivers/char/drm/sis_drv.c42
-rw-r--r--drivers/char/drm/sis_drv.h4
-rw-r--r--drivers/char/drm/sis_ds.h7
-rw-r--r--drivers/char/drm/sis_mm.c30
-rw-r--r--drivers/char/drm/tdfx_drv.c42
-rw-r--r--drivers/char/drm/tdfx_drv.h7
-rw-r--r--drivers/char/drm/via_dma.c38
-rw-r--r--drivers/char/drm/via_dmablit.c805
-rw-r--r--drivers/char/drm/via_dmablit.h140
-rw-r--r--drivers/char/drm/via_drm.h60
-rw-r--r--drivers/char/drm/via_drv.c63
-rw-r--r--drivers/char/drm/via_drv.h56
-rw-r--r--drivers/char/drm/via_ds.c9
-rw-r--r--drivers/char/drm/via_irq.c53
-rw-r--r--drivers/char/drm/via_map.c47
-rw-r--r--drivers/char/drm/via_mm.c20
-rw-r--r--drivers/char/drm/via_verifier.c6
-rw-r--r--drivers/char/drm/via_verifier.h4
-rw-r--r--drivers/char/drm/via_video.c7
-rw-r--r--drivers/char/dsp56k.c29
-rw-r--r--drivers/char/epca.c17
-rw-r--r--drivers/char/esp.c70
-rw-r--r--drivers/char/ftape/Kconfig12
-rw-r--r--drivers/char/generic_serial.c1
-rw-r--r--drivers/char/hvc_console.c6
-rw-r--r--drivers/char/hvcs.c10
-rw-r--r--drivers/char/hvsi.c2
-rw-r--r--drivers/char/hw_random.c1
-rw-r--r--drivers/char/ip2/i2lib.c2
-rw-r--r--drivers/char/ip2main.c26
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c2
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c3
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c10
-rw-r--r--drivers/char/isicom.c2084
-rw-r--r--drivers/char/istallion.c45
-rw-r--r--drivers/char/mem.c54
-rw-r--r--drivers/char/moxa.c77
-rw-r--r--drivers/char/mxser.c4
-rw-r--r--drivers/char/n_hdlc.c19
-rw-r--r--drivers/char/n_r3964.c10
-rw-r--r--drivers/char/n_tty.c66
-rw-r--r--drivers/char/nvram.c12
-rw-r--r--drivers/char/pcmcia/synclink_cs.c32
-rw-r--r--drivers/char/pty.c4
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/rio/board.h83
-rw-r--r--drivers/char/rio/bootpkt.h11
-rw-r--r--drivers/char/rio/brates.h107
-rw-r--r--drivers/char/rio/chan.h33
-rw-r--r--drivers/char/rio/cirrus.h178
-rw-r--r--drivers/char/rio/cmd.h84
-rw-r--r--drivers/char/rio/cmdblk.h19
-rw-r--r--drivers/char/rio/cmdpkt.h213
-rw-r--r--drivers/char/rio/control.h7
-rw-r--r--drivers/char/rio/daemon.h162
-rw-r--r--drivers/char/rio/data.h40
-rw-r--r--drivers/char/rio/debug.h39
-rw-r--r--drivers/char/rio/defaults.h7
-rw-r--r--drivers/char/rio/eisa.h104
-rw-r--r--drivers/char/rio/enable.h50
-rw-r--r--drivers/char/rio/error.h3
-rw-r--r--drivers/char/rio/errors.h2
-rw-r--r--drivers/char/rio/formpkt.h154
-rw-r--r--drivers/char/rio/func.h51
-rw-r--r--drivers/char/rio/host.h93
-rw-r--r--drivers/char/rio/hosthw.h57
-rw-r--r--drivers/char/rio/link.h152
-rw-r--r--drivers/char/rio/linux_compat.h46
-rw-r--r--drivers/char/rio/list.h6
-rw-r--r--drivers/char/rio/lrt.h55
-rw-r--r--drivers/char/rio/ltt.h55
-rw-r--r--drivers/char/rio/lttwake.h53
-rw-r--r--drivers/char/rio/map.h27
-rw-r--r--drivers/char/rio/mca.h73
-rw-r--r--drivers/char/rio/mesg.h41
-rw-r--r--drivers/char/rio/param.h27
-rw-r--r--drivers/char/rio/parmmap.h79
-rw-r--r--drivers/char/rio/pci.h2
-rw-r--r--drivers/char/rio/phb.h285
-rw-r--r--drivers/char/rio/pkt.h72
-rw-r--r--drivers/char/rio/poll.h76
-rw-r--r--drivers/char/rio/port.h294
-rw-r--r--drivers/char/rio/proto.h244
-rw-r--r--drivers/char/rio/protsts.h2
-rw-r--r--drivers/char/rio/qbuf.h15
-rw-r--r--drivers/char/rio/rio.h15
-rw-r--r--drivers/char/rio/rio_linux.c1498
-rw-r--r--drivers/char/rio/rio_linux.h57
-rw-r--r--drivers/char/rio/rioboard.h204
-rw-r--r--drivers/char/rio/rioboot.c61
-rw-r--r--drivers/char/rio/riocmd.c900
-rw-r--r--drivers/char/rio/rioctrl.c3064
-rw-r--r--drivers/char/rio/riodrvr.h128
-rw-r--r--drivers/char/rio/rioinfo.h30
-rw-r--r--drivers/char/rio/rioinit.c1152
-rw-r--r--drivers/char/rio/riointr.c1510
-rw-r--r--drivers/char/rio/rioioctl.h18
-rw-r--r--drivers/char/rio/riolocks.h43
-rw-r--r--drivers/char/rio/rioparam.c578
-rw-r--r--drivers/char/rio/riopcicopy.c6
-rw-r--r--drivers/char/rio/rioroute.c1574
-rw-r--r--drivers/char/rio/riospace.h31
-rw-r--r--drivers/char/rio/riotable.c1021
-rw-r--r--drivers/char/rio/riotime.h63
-rw-r--r--drivers/char/rio/riotty.c1217
-rw-r--r--drivers/char/rio/riotypes.h71
-rw-r--r--drivers/char/rio/riowinif.h1335
-rw-r--r--drivers/char/rio/riscos.h63
-rw-r--r--drivers/char/rio/rom.h22
-rw-r--r--drivers/char/rio/route.h61
-rw-r--r--drivers/char/rio/rtahw.h75
-rw-r--r--drivers/char/rio/rup.h39
-rw-r--r--drivers/char/rio/rupstat.h51
-rw-r--r--drivers/char/rio/sam.h13
-rw-r--r--drivers/char/rio/selftest.h73
-rw-r--r--drivers/char/rio/space.h2
-rw-r--r--drivers/char/rio/sysmap.h63
-rw-r--r--drivers/char/rio/timeouts.h51
-rw-r--r--drivers/char/rio/top.h9
-rw-r--r--drivers/char/rio/typdef.h36
-rw-r--r--drivers/char/rio/unixrup.h21
-rw-r--r--drivers/char/riscom8.c48
-rw-r--r--drivers/char/rocket.c19
-rw-r--r--drivers/char/rtc.c14
-rw-r--r--drivers/char/s3c2410-rtc.c2
-rw-r--r--drivers/char/scc.h2
-rw-r--r--drivers/char/selection.c5
-rw-r--r--drivers/char/ser_a2232.c8
-rw-r--r--drivers/char/serial167.c38
-rw-r--r--drivers/char/sonypi.c381
-rw-r--r--drivers/char/specialix.c41
-rw-r--r--drivers/char/stallion.c193
-rw-r--r--drivers/char/sx.c19
-rw-r--r--drivers/char/synclink.c52
-rw-r--r--drivers/char/synclink_gt.c4491
-rw-r--r--drivers/char/synclinkmp.c38
-rw-r--r--drivers/char/sysrq.c19
-rw-r--r--drivers/char/tb0219.c4
-rw-r--r--drivers/char/tlclk.c108
-rw-r--r--drivers/char/tpm/Makefile3
-rw-r--r--drivers/char/tpm/tpm.c3
-rw-r--r--drivers/char/tpm/tpm.h15
-rw-r--r--drivers/char/tpm/tpm_bios.c540
-rw-r--r--drivers/char/tty_io.c266
-rw-r--r--drivers/char/viocons.c45
-rw-r--r--drivers/char/vme_scc.c20
-rw-r--r--drivers/char/vr41xx_giu.c8
-rw-r--r--drivers/char/vr41xx_rtc.c9
-rw-r--r--drivers/char/vt.c33
-rw-r--r--drivers/char/watchdog/Kconfig26
-rw-r--r--drivers/char/watchdog/Makefile2
-rw-r--r--drivers/char/watchdog/cpu5wdt.c9
-rw-r--r--drivers/char/watchdog/mpc83xx_wdt.c229
-rw-r--r--drivers/char/watchdog/mpc8xx_wdt.c20
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c4
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c12
-rw-r--r--drivers/char/watchdog/sbc_epx_c3.c216
-rw-r--r--drivers/char/watchdog/wdt977.c216
-rw-r--r--drivers/connector/cn_proc.c15
-rw-r--r--drivers/cpufreq/cpufreq.c7
-rw-r--r--drivers/crypto/padlock-aes.c26
-rw-r--r--drivers/crypto/padlock.h2
-rw-r--r--drivers/dio/dio-driver.c4
-rw-r--r--drivers/edac/Kconfig102
-rw-r--r--drivers/edac/Makefile18
-rw-r--r--drivers/edac/amd76x_edac.c356
-rw-r--r--drivers/edac/e752x_edac.c1071
-rw-r--r--drivers/edac/e7xxx_edac.c558
-rw-r--r--drivers/edac/edac_mc.c2209
-rw-r--r--drivers/edac/edac_mc.h448
-rw-r--r--drivers/edac/i82860_edac.c299
-rw-r--r--drivers/edac/i82875p_edac.c532
-rw-r--r--drivers/edac/r82600_edac.c407
-rw-r--r--drivers/firmware/dell_rbu.c26
-rw-r--r--drivers/firmware/efivars.c2
-rw-r--r--drivers/hwmon/vt8231.c2
-rw-r--r--drivers/i2c/busses/Kconfig24
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-keywest.c751
-rw-r--r--drivers/i2c/busses/i2c-keywest.h108
-rw-r--r--drivers/i2c/busses/i2c-pmac-smu.c315
-rw-r--r--drivers/i2c/busses/i2c-powermac.c290
-rw-r--r--drivers/i2c/busses/i2c-pxa.c10
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c4
-rw-r--r--drivers/i2c/chips/tps65010.c11
-rw-r--r--drivers/i2c/i2c-core.c20
-rw-r--r--drivers/ide/ide-cd.c30
-rw-r--r--drivers/ide/ide-disk.c36
-rw-r--r--drivers/ide/ide-floppy.c26
-rw-r--r--drivers/ide/ide-io.c9
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide-tape.c18
-rw-r--r--drivers/ide/ide-taskfile.c2
-rw-r--r--drivers/ide/ide.c52
-rw-r--r--drivers/ide/legacy/hd.c24
-rw-r--r--drivers/ide/pci/pdc202xx_new.c2
-rw-r--r--drivers/ide/pci/serverworks.c2
-rw-r--r--drivers/ide/pci/via82cxxx.c2
-rw-r--r--drivers/ide/ppc/pmac.c6
-rw-r--r--drivers/ieee1394/amdtp.c1298
-rw-r--r--drivers/ieee1394/amdtp.h84
-rw-r--r--drivers/ieee1394/cmp.c311
-rw-r--r--drivers/ieee1394/cmp.h31
-rw-r--r--drivers/ieee1394/dv1394.c1
-rw-r--r--drivers/ieee1394/video1394.c1
-rw-r--r--drivers/infiniband/core/cm.c49
-rw-r--r--drivers/infiniband/core/device.c23
-rw-r--r--drivers/infiniband/core/sysfs.c22
-rw-r--r--drivers/infiniband/core/ucm.c23
-rw-r--r--drivers/infiniband/core/user_mad.c4
-rw-r--r--drivers/infiniband/core/uverbs.h5
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c173
-rw-r--r--drivers/infiniband/core/uverbs_main.c8
-rw-r--r--drivers/infiniband/core/verbs.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c19
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c23
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c32
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c54
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c132
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c267
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c31
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c12
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c105
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c10
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c24
-rw-r--r--drivers/input/evdev.c499
-rw-r--r--drivers/input/gameport/Kconfig7
-rw-r--r--drivers/input/gameport/gameport.c12
-rw-r--r--drivers/input/input.c57
-rw-r--r--drivers/input/joystick/amijoy.c4
-rw-r--r--drivers/input/joystick/grip_mp.c9
-rw-r--r--drivers/input/keyboard/Kconfig10
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/atkbd.c2
-rw-r--r--drivers/input/keyboard/corgikbd.c6
-rw-r--r--drivers/input/keyboard/spitzkbd.c27
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c9
-rw-r--r--drivers/input/misc/m68kspkr.c102
-rw-r--r--drivers/input/misc/pcspkr.c86
-rw-r--r--drivers/input/misc/sparcspkr.c162
-rw-r--r--drivers/input/misc/wistron_btns.c139
-rw-r--r--drivers/input/mouse/Kconfig10
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/alps.c39
-rw-r--r--drivers/input/mouse/amimouse.c6
-rw-r--r--drivers/input/mouse/lifebook.c7
-rw-r--r--drivers/input/mouse/logips2pp.c4
-rw-r--r--drivers/input/mouse/maplemouse.c101
-rw-r--r--drivers/input/mouse/psmouse-base.c331
-rw-r--r--drivers/input/mouse/psmouse.h9
-rw-r--r--drivers/input/mouse/synaptics.c2
-rw-r--r--drivers/input/mousedev.c10
-rw-r--r--drivers/input/serio/ambakmi.c15
-rw-r--r--drivers/input/serio/ct82c710.c89
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h22
-rw-r--r--drivers/input/serio/i8042.c116
-rw-r--r--drivers/input/serio/maceps2.c68
-rw-r--r--drivers/input/serio/q40kbd.c89
-rw-r--r--drivers/input/serio/sa1111ps2.c1
-rw-r--r--drivers/input/serio/serio.c12
-rw-r--r--drivers/input/serio/serport.c13
-rw-r--r--drivers/input/touchscreen/Kconfig15
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c625
-rw-r--r--drivers/isdn/act2000/act2000.h6
-rw-r--r--drivers/isdn/act2000/capi.h90
-rw-r--r--drivers/isdn/capi/capi.c3
-rw-r--r--drivers/isdn/capi/capifs.c8
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.c3
-rw-r--r--drivers/isdn/hardware/eicon/os_bri.c1
-rw-r--r--drivers/isdn/hardware/eicon/os_pri.c1
-rw-r--r--drivers/isdn/hisax/Kconfig10
-rw-r--r--drivers/isdn/hisax/avm_pci.c2
-rw-r--r--drivers/isdn/hisax/diva.c2
-rw-r--r--drivers/isdn/hisax/hisax.h18
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.h18
-rw-r--r--drivers/isdn/hisax/hscx_irq.c4
-rw-r--r--drivers/isdn/hisax/jade_irq.c2
-rw-r--r--drivers/isdn/i4l/isdn_common.c112
-rw-r--r--drivers/isdn/i4l/isdn_common.h1
-rw-r--r--drivers/isdn/i4l/isdn_tty.c75
-rw-r--r--drivers/isdn/sc/command.c1
-rw-r--r--drivers/macintosh/Kconfig10
-rw-r--r--drivers/macintosh/adb-iop.c2
-rw-r--r--drivers/macintosh/macio-adb.c13
-rw-r--r--drivers/macintosh/macio_asic.c260
-rw-r--r--drivers/macintosh/mediabay.c8
-rw-r--r--drivers/macintosh/smu.c50
-rw-r--r--drivers/macintosh/therm_pm72.c4
-rw-r--r--drivers/macintosh/via-cuda.c52
-rw-r--r--drivers/macintosh/via-macii.c4
-rw-r--r--drivers/macintosh/via-maciisi.c22
-rw-r--r--drivers/macintosh/via-pmu.c364
-rw-r--r--drivers/macintosh/via-pmu68k.c4
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c50
-rw-r--r--drivers/macintosh/windfarm_pm81.c2
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c1
-rw-r--r--drivers/macintosh/windfarm_smu_sensors.c1
-rw-r--r--drivers/md/bitmap.c2
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/dm-ioctl.c4
-rw-r--r--drivers/md/dm-snap.c2
-rw-r--r--drivers/md/dm.c7
-rw-r--r--drivers/md/kcopyd.c1
-rw-r--r--drivers/md/md.c42
-rw-r--r--drivers/md/multipath.c7
-rw-r--r--drivers/md/raid0.c6
-rw-r--r--drivers/md/raid1.c4
-rw-r--r--drivers/md/raid10.c4
-rw-r--r--drivers/md/raid5.c10
-rw-r--r--drivers/md/raid6main.c8
-rw-r--r--drivers/media/common/saa7146_core.c9
-rw-r--r--drivers/media/common/saa7146_fops.c44
-rw-r--r--drivers/media/common/saa7146_hlp.c13
-rw-r--r--drivers/media/common/saa7146_vbi.c6
-rw-r--r--drivers/media/common/saa7146_video.c9
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c33
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h4
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c6
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c2
-rw-r--r--drivers/media/dvb/bt8xx/dst.c52
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c3
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c44
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig20
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c82
-rw-r--r--drivers/media/dvb/dvb-core/Kconfig2
-rw-r--r--drivers/media/dvb/dvb-core/Makefile2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_filter.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c318
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c6
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c32
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.h8
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c44
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig24
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c444
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c46
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c3
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c6
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.h31
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-common.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c154
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h14
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c57
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c9
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h29
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c7
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c5
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h43
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c3
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig46
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c9
-rw-r--r--drivers/media/dvb/frontends/cx22702.c22
-rw-r--r--drivers/media/dvb/frontends/cx24110.c23
-rw-r--r--drivers/media/dvb/frontends/cx24123.c889
-rw-r--r--drivers/media/dvb/frontends/cx24123.h51
-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.c34
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h3
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c6
-rw-r--r--drivers/media/dvb/frontends/mt312.c3
-rw-r--r--drivers/media/dvb/frontends/mt352.c3
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c3
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c3
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c10
-rw-r--r--drivers/media/dvb/frontends/or51211.c5
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c4
-rw-r--r--drivers/media/dvb/frontends/sp8870.c3
-rw-r--r--drivers/media/dvb/frontends/sp887x.c5
-rw-r--r--drivers/media/dvb/frontends/stv0299.c12
-rw-r--r--drivers/media/dvb/frontends/stv0299.h1
-rw-r--r--drivers/media/dvb/frontends/tda10021.c4
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c141
-rw-r--r--drivers/media/dvb/pluto2/Kconfig2
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c3
-rw-r--r--drivers/media/dvb/ttpci/Kconfig7
-rw-r--r--drivers/media/dvb/ttpci/Makefile2
-rw-r--r--drivers/media/dvb/ttpci/av7110.c141
-rw-r--r--drivers/media/dvb/ttpci/av7110.h17
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c12
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c47
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h15
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c14
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c118
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c313
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c4
-rw-r--r--drivers/media/dvb/ttpci/budget.c13
-rw-r--r--drivers/media/dvb/ttpci/budget.h1
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.c2
-rw-r--r--drivers/media/dvb/ttusb-budget/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c4
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig13
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c24
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c53
-rw-r--r--drivers/media/radio/miropcm20-radio.c1
-rw-r--r--drivers/media/radio/radio-aimslab.c1
-rw-r--r--drivers/media/radio/radio-aztech.c1
-rw-r--r--drivers/media/radio/radio-cadet.c1
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c6
-rw-r--r--drivers/media/radio/radio-gemtek.c1
-rw-r--r--drivers/media/radio/radio-maestro.c391
-rw-r--r--drivers/media/radio/radio-maxiradio.c3
-rw-r--r--drivers/media/radio/radio-rtrack2.c1
-rw-r--r--drivers/media/radio/radio-sf16fmi.c1
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c3
-rw-r--r--drivers/media/radio/radio-terratec.c1
-rw-r--r--drivers/media/radio/radio-trust.c1
-rw-r--r--drivers/media/radio/radio-typhoon.c1
-rw-r--r--drivers/media/radio/radio-zoltrix.c1
-rw-r--r--drivers/media/video/Kconfig13
-rw-r--r--drivers/media/video/Makefile13
-rw-r--r--drivers/media/video/adv7170.c6
-rw-r--r--drivers/media/video/adv7175.c6
-rw-r--r--drivers/media/video/arv.c7
-rw-r--r--drivers/media/video/bt819.c7
-rw-r--r--drivers/media/video/bt832.c73
-rw-r--r--drivers/media/video/bt856.c6
-rw-r--r--drivers/media/video/btcx-risc.c2
-rw-r--r--drivers/media/video/bttv-cards.c365
-rw-r--r--drivers/media/video/bttv-driver.c155
-rw-r--r--drivers/media/video/bttv-gpio.c45
-rw-r--r--drivers/media/video/bttv-i2c.c21
-rw-r--r--drivers/media/video/bttv-input.c (renamed from drivers/media/video/ir-kbd-gpio.c)262
-rw-r--r--drivers/media/video/bttv-vbi.c57
-rw-r--r--drivers/media/video/bttv.h40
-rw-r--r--drivers/media/video/bttvp.h18
-rw-r--r--drivers/media/video/bw-qcam.c1
-rw-r--r--drivers/media/video/c-qcam.c1
-rw-r--r--drivers/media/video/compat_ioctl32.c879
-rw-r--r--drivers/media/video/cpia.c1
-rw-r--r--drivers/media/video/cpia_pp.c3
-rw-r--r--drivers/media/video/cpia_usb.c4
-rw-r--r--drivers/media/video/cs53l32a.c95
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c91
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c391
-rw-r--r--drivers/media/video/cx25840/cx25840-firmware.c36
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c4
-rw-r--r--drivers/media/video/cx25840/cx25840.h81
-rw-r--r--drivers/media/video/cx88/Kconfig24
-rw-r--r--drivers/media/video/cx88/Makefile5
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c847
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c24
-rw-r--r--drivers/media/video/cx88/cx88-cards.c232
-rw-r--r--drivers/media/video/cx88/cx88-core.c85
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c218
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c13
-rw-r--r--drivers/media/video/cx88/cx88-input.c143
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c5
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c18
-rw-r--r--drivers/media/video/cx88/cx88-video.c100
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c177
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.h35
-rw-r--r--drivers/media/video/cx88/cx88.h17
-rw-r--r--drivers/media/video/dpc7146.c3
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c8
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c61
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c3
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c77
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c177
-rw-r--r--drivers/media/video/em28xx/em28xx.h6
-rw-r--r--drivers/media/video/hexium_gemini.c3
-rw-r--r--drivers/media/video/hexium_orion.c3
-rw-r--r--drivers/media/video/indycam.c7
-rw-r--r--drivers/media/video/ir-kbd-i2c.c18
-rw-r--r--drivers/media/video/meye.c1
-rw-r--r--drivers/media/video/msp3400-driver.c1274
-rw-r--r--drivers/media/video/msp3400-kthreads.c1010
-rw-r--r--drivers/media/video/msp3400.c2229
-rw-r--r--drivers/media/video/msp3400.h106
-rw-r--r--drivers/media/video/mt20xx.c22
-rw-r--r--drivers/media/video/mxb.c4
-rw-r--r--drivers/media/video/ovcamchip/ov6x20.c3
-rw-r--r--drivers/media/video/ovcamchip/ov6x30.c3
-rw-r--r--drivers/media/video/ovcamchip/ov76be.c3
-rw-r--r--drivers/media/video/ovcamchip/ov7x10.c3
-rw-r--r--drivers/media/video/ovcamchip/ov7x20.c3
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c3
-rw-r--r--drivers/media/video/planb.c4
-rw-r--r--drivers/media/video/pms.c1
-rw-r--r--drivers/media/video/saa5246a.c3
-rw-r--r--drivers/media/video/saa5249.c6
-rw-r--r--drivers/media/video/saa6588.c22
-rw-r--r--drivers/media/video/saa7110.c6
-rw-r--r--drivers/media/video/saa7111.c6
-rw-r--r--drivers/media/video/saa7114.c6
-rw-r--r--drivers/media/video/saa7115.c325
-rw-r--r--drivers/media/video/saa711x.c10
-rw-r--r--drivers/media/video/saa7127.c88
-rw-r--r--drivers/media/video/saa7134/Kconfig2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c91
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c158
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c3
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c3
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c39
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c40
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c10
-rw-r--r--drivers/media/video/saa7134/saa7134.h10
-rw-r--r--drivers/media/video/saa7146.h1
-rw-r--r--drivers/media/video/saa7185.c6
-rw-r--r--drivers/media/video/saa7191.c7
-rw-r--r--drivers/media/video/stradis.c1137
-rw-r--r--drivers/media/video/tda7432.c46
-rw-r--r--drivers/media/video/tda8290.c10
-rw-r--r--drivers/media/video/tda9875.c10
-rw-r--r--drivers/media/video/tda9887.c231
-rw-r--r--drivers/media/video/tea5767.c23
-rw-r--r--drivers/media/video/tea6420.c3
-rw-r--r--drivers/media/video/tuner-3036.c3
-rw-r--r--drivers/media/video/tuner-core.c216
-rw-r--r--drivers/media/video/tuner-simple.c309
-rw-r--r--drivers/media/video/tuner-types.c1406
-rw-r--r--drivers/media/video/tvaudio.c180
-rw-r--r--drivers/media/video/tveeprom.c51
-rw-r--r--drivers/media/video/tvmixer.c20
-rw-r--r--drivers/media/video/tvp5150.c540
-rw-r--r--drivers/media/video/v4l1-compat.c35
-rw-r--r--drivers/media/video/v4l2-common.c220
-rw-r--r--drivers/media/video/video-buf.c9
-rw-r--r--drivers/media/video/videocodec.c11
-rw-r--r--drivers/media/video/videodev.c40
-rw-r--r--drivers/media/video/vino.c4
-rw-r--r--drivers/media/video/vpx3220.c7
-rw-r--r--drivers/media/video/w9966.c1
-rw-r--r--drivers/media/video/wm8775.c91
-rw-r--r--drivers/media/video/zoran_card.c9
-rw-r--r--drivers/media/video/zoran_driver.c4
-rw-r--r--drivers/media/video/zr36016.c3
-rw-r--r--drivers/media/video/zr36050.c3
-rw-r--r--drivers/media/video/zr36060.c3
-rw-r--r--drivers/media/video/zr36120.c1
-rw-r--r--drivers/message/fusion/Kconfig1
-rw-r--r--drivers/message/fusion/lsi/mpi.h10
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h158
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt77
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h8
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h122
-rw-r--r--drivers/message/fusion/lsi/mpi_log_fc.h89
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h162
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h30
-rw-r--r--drivers/message/fusion/mptbase.c48
-rw-r--r--drivers/message/fusion/mptbase.h34
-rw-r--r--drivers/message/fusion/mptctl.c14
-rw-r--r--drivers/message/fusion/mptfc.c579
-rw-r--r--drivers/message/fusion/mptlan.c18
-rw-r--r--drivers/message/fusion/mptsas.c404
-rw-r--r--drivers/message/fusion/mptscsih.c34
-rw-r--r--drivers/message/fusion/mptspi.c26
-rw-r--r--drivers/message/i2o/README.ioctl2
-rw-r--r--drivers/message/i2o/i2o_block.c18
-rw-r--r--drivers/message/i2o/pci.c10
-rw-r--r--drivers/mfd/mcp-core.c4
-rw-r--r--drivers/mfd/ucb1x00-core.c32
-rw-r--r--drivers/mfd/ucb1x00-ts.c1
-rw-r--r--drivers/misc/ibmasm/ibmasm.h6
-rw-r--r--drivers/misc/ibmasm/remote.c77
-rw-r--r--drivers/mmc/mmc.c11
-rw-r--r--drivers/mmc/mmc_block.c222
-rw-r--r--drivers/mmc/mmc_sysfs.c26
-rw-r--r--drivers/mmc/mmci.c30
-rw-r--r--drivers/mmc/mmci.h4
-rw-r--r--drivers/mmc/wbsd.c552
-rw-r--r--drivers/mtd/chips/Kconfig7
-rw-r--r--drivers/mtd/devices/Kconfig17
-rw-r--r--drivers/mtd/devices/Makefile2
-rw-r--r--drivers/mtd/devices/doc2000.c2
-rw-r--r--drivers/mtd/devices/doc2001.c2
-rw-r--r--drivers/mtd/devices/doc2001plus.c2
-rw-r--r--drivers/mtd/devices/m25p80.c582
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c629
-rw-r--r--drivers/mtd/maps/Kconfig8
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/epxa10db-flash.c179
-rw-r--r--drivers/mtd/mtd_blkdevs.c25
-rw-r--r--drivers/mtd/nand/au1550nd.c2
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/mtd/nand/rtc_from4.c2
-rw-r--r--drivers/mtd/nand/s3c2410.c4
-rw-r--r--drivers/mtd/nand/spia.c2
-rw-r--r--drivers/mtd/onenand/generic.c1
-rw-r--r--drivers/mtd/rfd_ftl.c1
-rw-r--r--drivers/net/3c503.c16
-rw-r--r--drivers/net/3c527.h50
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/Kconfig37
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/ac3200.c16
-rw-r--r--drivers/net/arm/Kconfig13
-rw-r--r--drivers/net/arm/Makefile1
-rw-r--r--drivers/net/arm/am79c961a.c12
-rw-r--r--drivers/net/arm/ether00.c1017
-rw-r--r--drivers/net/arm/ether3.c1
-rw-r--r--drivers/net/arm/etherh.c1
-rw-r--r--drivers/net/b44.c2
-rw-r--r--drivers/net/bonding/bond_alb.c4
-rw-r--r--drivers/net/bonding/bonding.h12
-rw-r--r--drivers/net/cassini.c40
-rw-r--r--drivers/net/cs89x0.c171
-rw-r--r--drivers/net/cs89x0.h19
-rw-r--r--drivers/net/e100.c192
-rw-r--r--drivers/net/e1000/e1000.h51
-rw-r--r--drivers/net/e1000/e1000_ethtool.c474
-rw-r--r--drivers/net/e1000/e1000_hw.c71
-rw-r--r--drivers/net/e1000/e1000_hw.h45
-rw-r--r--drivers/net/e1000/e1000_main.c1612
-rw-r--r--drivers/net/e1000/e1000_osdep.h2
-rw-r--r--drivers/net/e1000/e1000_param.c68
-rw-r--r--drivers/net/e2100.c14
-rw-r--r--drivers/net/es3210.c14
-rw-r--r--drivers/net/forcedeth.c164
-rw-r--r--drivers/net/gianfar.c6
-rw-r--r--drivers/net/gianfar.h4
-rw-r--r--drivers/net/gianfar_mii.c5
-rw-r--r--drivers/net/gianfar_sysfs.c2
-rw-r--r--drivers/net/hamradio/6pack.c7
-rw-r--r--drivers/net/hamradio/mkiss.c8
-rw-r--r--drivers/net/hp-plus.c12
-rw-r--r--drivers/net/hp.c12
-rw-r--r--drivers/net/hp100.c2
-rw-r--r--drivers/net/hplance.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac.h3
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c2
-rw-r--r--drivers/net/ifb.c294
-rw-r--r--drivers/net/irda/Kconfig3
-rw-r--r--drivers/net/irda/Makefile2
-rw-r--r--drivers/net/irda/irport.c15
-rw-r--r--drivers/net/irda/irtty-sir.c18
-rw-r--r--drivers/net/irda/sir-dev.h2
-rw-r--r--drivers/net/irda/sir_core.c56
-rw-r--r--drivers/net/irda/sir_dev.c10
-rw-r--r--drivers/net/irda/sir_dongle.c2
-rw-r--r--drivers/net/irda/sir_kthread.c11
-rw-r--r--drivers/net/irda/vlsi_ir.h4
-rw-r--r--drivers/net/iseries_veth.c4
-rw-r--r--drivers/net/lance.c22
-rw-r--r--drivers/net/lne390.c14
-rw-r--r--drivers/net/mac8390.c31
-rw-r--r--drivers/net/mv643xx_eth.c682
-rw-r--r--drivers/net/ne.c18
-rw-r--r--drivers/net/ne2.c16
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c2
-rw-r--r--drivers/net/phy/mdio_bus.c2
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/ppp_async.c9
-rw-r--r--drivers/net/ppp_synctty.c9
-rw-r--r--drivers/net/r8169.c2
-rw-r--r--drivers/net/sb1000.c4
-rw-r--r--drivers/net/sis190.c2
-rw-r--r--drivers/net/sk98lin/skdim.c2
-rw-r--r--drivers/net/sk98lin/skge.c131
-rw-r--r--drivers/net/sk98lin/skgepnmi.c8
-rw-r--r--drivers/net/skge.c20
-rw-r--r--drivers/net/sky2.c219
-rw-r--r--drivers/net/slip.c11
-rw-r--r--drivers/net/smc-ultra.c24
-rw-r--r--drivers/net/smc91x.c5
-rw-r--r--drivers/net/smc91x.h18
-rw-r--r--drivers/net/spider_net.c512
-rw-r--r--drivers/net/spider_net.h75
-rw-r--r--drivers/net/spider_net_ethtool.c19
-rw-r--r--drivers/net/sun3lance.c2
-rw-r--r--drivers/net/tg3.c82
-rw-r--r--drivers/net/tg3.h1
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/tulip/uli526x.c6
-rw-r--r--drivers/net/via-velocity.c2
-rw-r--r--drivers/net/wan/lmc/lmc_main.c2
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/sdla.c6
-rw-r--r--drivers/net/wan/x25_asy.c7
-rw-r--r--drivers/net/wd.c14
-rw-r--r--drivers/net/wireless/Kconfig10
-rw-r--r--drivers/net/wireless/airo.c21
-rw-r--r--drivers/net/wireless/atmel.c231
-rw-r--r--drivers/net/wireless/hostap/Kconfig22
-rw-r--r--drivers/net/wireless/hostap/Makefile3
-rw-r--r--drivers/net/wireless/hostap/hostap.h37
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c21
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c15
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c36
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h13
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c8
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c3
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c12
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c60
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c7
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h4
-rw-r--r--drivers/net/wireless/ipw2100.c465
-rw-r--r--drivers/net/wireless/ipw2200.c56
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c2
-rw-r--r--drivers/net/wireless/ray_cs.c2
-rw-r--r--drivers/net/wireless/strip.c10
-rw-r--r--drivers/net/wireless/wavelan.c38
-rw-r--r--drivers/net/wireless/wavelan_cs.c2
-rw-r--r--drivers/oprofile/buffer_sync.c30
-rw-r--r--drivers/oprofile/cpu_buffer.c3
-rw-r--r--drivers/oprofile/event_buffer.c1
-rw-r--r--drivers/parisc/dino.c30
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/eisa_eeprom.c2
-rw-r--r--drivers/parisc/lasi.c2
-rw-r--r--drivers/parisc/lba_pci.c115
-rw-r--r--drivers/parisc/led.c21
-rw-r--r--drivers/parisc/pdc_stable.c46
-rw-r--r--drivers/parisc/power.c12
-rw-r--r--drivers/parport/Kconfig3
-rw-r--r--drivers/parport/parport_pc.c6
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c6
-rw-r--r--drivers/pci/hotplug/cpqphp.h8
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c127
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c28
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c138
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_core.c92
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c22
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c52
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c13
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c27
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c47
-rw-r--r--drivers/pci/hotplug/shpchp.h4
-rw-r--r--drivers/pci/hotplug/shpchp_core.c16
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c37
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c138
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c19
-rw-r--r--drivers/pci/pci-driver.c4
-rw-r--r--drivers/pci/pci.c7
-rw-r--r--drivers/pci/pci.h5
-rw-r--r--drivers/pci/pcie/portdrv_core.c4
-rw-r--r--drivers/pci/probe.c49
-rw-r--r--drivers/pci/proc.c7
-rw-r--r--drivers/pci/quirks.c31
-rw-r--r--drivers/pci/remove.c3
-rw-r--r--drivers/pcmcia/ds.c41
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c15
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c43
-rw-r--r--drivers/pcmcia/socket_sysfs.c25
-rw-r--r--drivers/pcmcia/vrc4171_card.c4
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c6
-rw-r--r--drivers/pcmcia/vrc4173_cardu.h2
-rw-r--r--drivers/pnp/driver.c4
-rw-r--r--drivers/pnp/pnpacpi/core.c14
-rw-r--r--drivers/rapidio/rio-driver.c6
-rw-r--r--drivers/rapidio/rio-scan.c2
-rw-r--r--drivers/rapidio/rio-sysfs.c1
-rw-r--r--drivers/rapidio/rio.c1
-rw-r--r--drivers/s390/block/dasd.c26
-rw-r--r--drivers/s390/block/dasd_int.h1
-rw-r--r--drivers/s390/block/dasd_ioctl.c40
-rw-r--r--drivers/s390/block/xpram.c18
-rw-r--r--drivers/s390/char/con3215.c25
-rw-r--r--drivers/s390/char/fs3270.c20
-rw-r--r--drivers/s390/char/sclp_tty.c21
-rw-r--r--drivers/s390/char/sclp_vt220.c12
-rw-r--r--drivers/s390/char/tape_char.c20
-rw-r--r--drivers/s390/cio/airq.c4
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/cio/ccwgroup.c20
-rw-r--r--drivers/s390/cio/chsc.c4
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/css.c40
-rw-r--r--drivers/s390/cio/css.h6
-rw-r--r--drivers/s390/cio/device.c54
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/device_id.c2
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/device_pgid.c2
-rw-r--r--drivers/s390/cio/device_status.c2
-rw-r--r--drivers/s390/cio/qdio.c4
-rw-r--r--drivers/s390/crypto/z90main.c1
-rw-r--r--drivers/s390/net/ctcmain.c8
-rw-r--r--drivers/s390/net/ctctty.c28
-rw-r--r--drivers/s390/net/cu3088.c4
-rw-r--r--drivers/s390/net/netiucv.c9
-rw-r--r--drivers/s390/s390_rdev.c4
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_def.h4
-rw-r--r--drivers/s390/scsi/zfcp_erp.c4
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c84
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h13
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c188
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c15
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c4
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c2
-rw-r--r--drivers/sbus/char/aurora.c1
-rw-r--r--drivers/scsi/3w-9xxx.c7
-rw-r--r--drivers/scsi/3w-9xxx.h2
-rw-r--r--drivers/scsi/3w-xxxx.c7
-rw-r--r--drivers/scsi/3w-xxxx.h2
-rw-r--r--drivers/scsi/BusLogic.c3
-rw-r--r--drivers/scsi/FlashPoint.c2
-rw-r--r--drivers/scsi/Makefile5
-rw-r--r--drivers/scsi/NCR53C9x.c5
-rw-r--r--drivers/scsi/aacraid/README74
-rw-r--r--drivers/scsi/aacraid/aacraid.h7
-rw-r--r--drivers/scsi/aacraid/commctrl.c4
-rw-r--r--drivers/scsi/aacraid/linit.c36
-rw-r--r--drivers/scsi/ahci.c10
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h39
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.reg60
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.seq241
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c771
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_inline.h38
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c62
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c24
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.h5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg.h_shipped646
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped507
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_seq.h_shipped1250
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c28
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h25
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c24
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.h1
-rw-r--r--drivers/scsi/aic7xxx_old.c4
-rw-r--r--drivers/scsi/arm/acornscsi.c1
-rw-r--r--drivers/scsi/arm/arxescsi.c1
-rw-r--r--drivers/scsi/arm/cumana_1.c1
-rw-r--r--drivers/scsi/arm/cumana_2.c1
-rw-r--r--drivers/scsi/arm/eesox.c1
-rw-r--r--drivers/scsi/arm/powertec.c1
-rw-r--r--drivers/scsi/ata_piix.c3
-rw-r--r--drivers/scsi/blz1230.c4
-rw-r--r--drivers/scsi/blz2060.c4
-rw-r--r--drivers/scsi/ch.c34
-rw-r--r--drivers/scsi/cyberstorm.c4
-rw-r--r--drivers/scsi/cyberstormII.c4
-rw-r--r--drivers/scsi/dpt_i2o.c45
-rw-r--r--drivers/scsi/fastlane.c4
-rw-r--r--drivers/scsi/gdth.c2
-rw-r--r--drivers/scsi/hosts.c8
-rw-r--r--drivers/scsi/ips.c3
-rw-r--r--drivers/scsi/iscsi_tcp.c305
-rw-r--r--drivers/scsi/iscsi_tcp.h6
-rw-r--r--drivers/scsi/libata-core.c75
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c2
-rw-r--r--drivers/scsi/mac53c94.c22
-rw-r--r--drivers/scsi/megaraid.c6
-rw-r--r--drivers/scsi/megaraid.h4
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c10
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.h1
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c25
-rw-r--r--drivers/scsi/mesh.c3
-rw-r--r--drivers/scsi/oktagon_esp.c2
-rw-r--r--drivers/scsi/qla2xxx/Kconfig24
-rw-r--r--drivers/scsi/qla2xxx/Makefile2
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c105
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c24
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c107
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/raid_class.c2
-rw-r--r--drivers/scsi/sata_nv.c30
-rw-r--r--drivers/scsi/sata_promise.c16
-rw-r--r--drivers/scsi/sata_svw.c1
-rw-r--r--drivers/scsi/scsi.c122
-rw-r--r--drivers/scsi/scsi_debug.c4
-rw-r--r--drivers/scsi/scsi_lib.c52
-rw-r--r--drivers/scsi/scsi_priv.h7
-rw-r--r--drivers/scsi/scsi_proc.c17
-rw-r--r--drivers/scsi/scsi_scan.c32
-rw-r--r--drivers/scsi/scsi_sysfs.c9
-rw-r--r--drivers/scsi/scsi_transport_fc.c26
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c859
-rw-r--r--drivers/scsi/scsi_transport_sas.c58
-rw-r--r--drivers/scsi/scsi_transport_spi.c12
-rw-r--r--drivers/scsi/sd.c84
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/sr.c45
-rw-r--r--drivers/scsi/sr_ioctl.c202
-rw-r--r--drivers/scsi/st.c42
-rw-r--r--drivers/scsi/wd33c93.c4
-rw-r--r--drivers/serial/21285.c9
-rw-r--r--drivers/serial/68328serial.c19
-rw-r--r--drivers/serial/68360serial.c54
-rw-r--r--drivers/serial/8250.c133
-rw-r--r--drivers/serial/8250.h6
-rw-r--r--drivers/serial/8250_pci.c134
-rw-r--r--drivers/serial/Kconfig80
-rw-r--r--drivers/serial/Makefile3
-rw-r--r--drivers/serial/amba-pl010.c13
-rw-r--r--drivers/serial/amba-pl011.c22
-rw-r--r--drivers/serial/at91_serial.c892
-rw-r--r--drivers/serial/au1x00_uart.c31
-rw-r--r--drivers/serial/clps711x.c2
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c2
-rw-r--r--drivers/serial/crisv10.c11
-rw-r--r--drivers/serial/dz.c2
-rw-r--r--drivers/serial/icom.c57
-rw-r--r--drivers/serial/imx.c5
-rw-r--r--drivers/serial/ioc3_serial.c2197
-rw-r--r--drivers/serial/ioc4_serial.c10
-rw-r--r--drivers/serial/ip22zilog.c34
-rw-r--r--drivers/serial/m32r_sio.c31
-rw-r--r--drivers/serial/mcfserial.c25
-rw-r--r--drivers/serial/mpc52xx_uart.c46
-rw-r--r--drivers/serial/mpsc.c6
-rw-r--r--drivers/serial/mux.c9
-rw-r--r--drivers/serial/pmac_zilog.c86
-rw-r--r--drivers/serial/pxa.c8
-rw-r--r--drivers/serial/s3c2410.c17
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_core.c78
-rw-r--r--drivers/serial/serial_cs.c2
-rw-r--r--drivers/serial/serial_lh7a40x.c9
-rw-r--r--drivers/serial/serial_txx9.c24
-rw-r--r--drivers/serial/sh-sci.c81
-rw-r--r--drivers/serial/sn_console.c135
-rw-r--r--drivers/serial/suncore.c34
-rw-r--r--drivers/serial/sunsab.c45
-rw-r--r--drivers/serial/sunsu.c32
-rw-r--r--drivers/serial/sunzilog.c34
-rw-r--r--drivers/serial/uart00.c782
-rw-r--r--drivers/serial/vr41xx_siu.c7
-rw-r--r--drivers/sh/superhyway/superhyway.c4
-rw-r--r--drivers/sn/Kconfig14
-rw-r--r--drivers/sn/Makefile1
-rw-r--r--drivers/sn/ioc3.c851
-rw-r--r--drivers/spi/Kconfig109
-rw-r--r--drivers/spi/Makefile25
-rw-r--r--drivers/spi/spi.c642
-rw-r--r--drivers/spi/spi_bitbang.c472
-rw-r--r--drivers/spi/spi_butterfly.c423
-rw-r--r--drivers/usb/atm/speedtch.c4
-rw-r--r--drivers/usb/atm/usbatm.c4
-rw-r--r--drivers/usb/class/cdc-acm.c11
-rw-r--r--drivers/usb/core/inode.c34
-rw-r--r--drivers/usb/gadget/ether.c3
-rw-r--r--drivers/usb/gadget/file_storage.c4
-rw-r--r--drivers/usb/gadget/inode.c7
-rw-r--r--drivers/usb/gadget/serial.c22
-rw-r--r--drivers/usb/gadget/zero.c3
-rw-r--r--drivers/usb/host/Kconfig10
-rw-r--r--drivers/usb/host/ohci-au1xxx.c1
-rw-r--r--drivers/usb/host/ohci-lh7a404.c1
-rw-r--r--drivers/usb/host/ohci-omap.c2
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ohci-s3c2410.c4
-rw-r--r--drivers/usb/image/microtek.c2
-rw-r--r--drivers/usb/input/Kconfig10
-rw-r--r--drivers/usb/input/appletouch.c145
-rw-r--r--drivers/usb/input/hid-core.c30
-rw-r--r--drivers/usb/input/hid-debug.h15
-rw-r--r--drivers/usb/input/hid-input.c179
-rw-r--r--drivers/usb/input/hid.h30
-rw-r--r--drivers/usb/input/pid.c2
-rw-r--r--drivers/usb/input/wacom.c14
-rw-r--r--drivers/usb/media/dsbr100.c1
-rw-r--r--drivers/usb/media/ov511.c1
-rw-r--r--drivers/usb/media/pwc/pwc-if.c1
-rw-r--r--drivers/usb/media/se401.c1
-rw-r--r--drivers/usb/media/stv680.c1
-rw-r--r--drivers/usb/media/usbvideo.c1
-rw-r--r--drivers/usb/media/vicam.c1
-rw-r--r--drivers/usb/media/w9968cf.c1
-rw-r--r--drivers/usb/serial/Kconfig2
-rw-r--r--drivers/usb/serial/bus.c15
-rw-r--r--drivers/usb/serial/cyberjack.c11
-rw-r--r--drivers/usb/serial/cypress_m8.c6
-rw-r--r--drivers/usb/serial/digi_acceleport.c28
-rw-r--r--drivers/usb/serial/empeg.c16
-rw-r--r--drivers/usb/serial/ftdi_sio.c15
-rw-r--r--drivers/usb/serial/garmin_gps.c13
-rw-r--r--drivers/usb/serial/generic.c11
-rw-r--r--drivers/usb/serial/io_edgeport.c20
-rw-r--r--drivers/usb/serial/io_ti.c20
-rw-r--r--drivers/usb/serial/ipaq.c12
-rw-r--r--drivers/usb/serial/ipw.c11
-rw-r--r--drivers/usb/serial/kl5kusb105.c13
-rw-r--r--drivers/usb/serial/kobil_sct.c11
-rw-r--r--drivers/usb/serial/option.c9
-rw-r--r--drivers/usb/serial/pl2303.c10
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c20
-rw-r--r--drivers/usb/serial/usb-serial.c2
-rw-r--r--drivers/usb/serial/visor.c11
-rw-r--r--drivers/usb/serial/whiteheat.c11
-rw-r--r--drivers/video/68328fb.c6
-rw-r--r--drivers/video/Kconfig12
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/amba-clcd.c18
-rw-r--r--drivers/video/amifb.c45
-rw-r--r--drivers/video/arcfb.c13
-rw-r--r--drivers/video/asiliantfb.c2
-rw-r--r--drivers/video/atafb.c3
-rw-r--r--drivers/video/aty/Makefile1
-rw-r--r--drivers/video/aty/aty128fb.c6
-rw-r--r--drivers/video/aty/atyfb.h2
-rw-r--r--drivers/video/aty/atyfb_base.c257
-rw-r--r--drivers/video/aty/mach64_ct.c17
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/aty/radeon_monitor.c2
-rw-r--r--drivers/video/aty/radeon_pm.c6
-rw-r--r--drivers/video/aty/xlinit.c359
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/backlight/corgi_bl.c1
-rw-r--r--drivers/video/bw2.c10
-rw-r--r--drivers/video/cg14.c10
-rw-r--r--drivers/video/cg3.c10
-rw-r--r--drivers/video/cg6.c10
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/bitblit.c14
-rw-r--r--drivers/video/console/fbcon.c83
-rw-r--r--drivers/video/console/fbcon.h11
-rw-r--r--drivers/video/console/fbcon_ccw.c17
-rw-r--r--drivers/video/console/fbcon_cw.c17
-rw-r--r--drivers/video/console/fbcon_rotate.c9
-rw-r--r--drivers/video/console/fbcon_rotate.h2
-rw-r--r--drivers/video/console/fbcon_ud.c19
-rw-r--r--drivers/video/console/softcursor.c2
-rw-r--r--drivers/video/console/tileblit.c17
-rw-r--r--drivers/video/console/vgacon.c36
-rw-r--r--drivers/video/controlfb.c118
-rw-r--r--drivers/video/cyber2000fb.c1
-rw-r--r--drivers/video/cyblafb.c1524
-rw-r--r--drivers/video/fbcvt.c3
-rw-r--r--drivers/video/fbmem.c43
-rw-r--r--drivers/video/fbmon.c129
-rw-r--r--drivers/video/fbsysfs.c81
-rw-r--r--drivers/video/ffb.c10
-rw-r--r--drivers/video/gbefb.c3
-rw-r--r--drivers/video/geode/gx1fb_core.c11
-rw-r--r--drivers/video/hgafb.c107
-rw-r--r--drivers/video/i810/i810-i2c.c3
-rw-r--r--drivers/video/i810/i810_accel.c27
-rw-r--r--drivers/video/i810/i810_gtf.c1
-rw-r--r--drivers/video/i810/i810_main.c137
-rw-r--r--drivers/video/i810/i810_main.h56
-rw-r--r--drivers/video/igafb.c2
-rw-r--r--drivers/video/imsttfb.c59
-rw-r--r--drivers/video/imxfb.c6
-rw-r--r--drivers/video/intelfb/intelfbdrv.c8
-rw-r--r--drivers/video/kyro/STG4000InitDevice.c1
-rw-r--r--drivers/video/kyro/STG4000Interface.h3
-rw-r--r--drivers/video/kyro/STG4000OverlayDevice.c1
-rw-r--r--drivers/video/kyro/fbdev.c37
-rw-r--r--drivers/video/leo.c10
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/macfb.c15
-rw-r--r--drivers/video/matrox/matroxfb_base.c5
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c9
-rw-r--r--drivers/video/matrox/matroxfb_g450.c2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c2
-rw-r--r--drivers/video/matrox/matroxfb_misc.c8
-rw-r--r--drivers/video/neofb.c38
-rw-r--r--drivers/video/nvidia/nv_hw.c82
-rw-r--r--drivers/video/nvidia/nv_i2c.c12
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nv_setup.c37
-rw-r--r--drivers/video/nvidia/nvidia.c117
-rw-r--r--drivers/video/offb.c122
-rw-r--r--drivers/video/p9100.c11
-rw-r--r--drivers/video/platinumfb.c98
-rw-r--r--drivers/video/platinumfb.h4
-rw-r--r--drivers/video/pm2fb.c21
-rw-r--r--drivers/video/pm3fb.c8
-rw-r--r--drivers/video/pmag-aa-fb.c3
-rw-r--r--drivers/video/pxafb.c2
-rw-r--r--drivers/video/radeonfb.c4
-rw-r--r--drivers/video/riva/fbdev.c68
-rw-r--r--drivers/video/riva/rivafb-i2c.c8
-rw-r--r--drivers/video/s3c2410fb.c15
-rw-r--r--drivers/video/sa1100fb.c17
-rw-r--r--drivers/video/savage/savagefb-i2c.c44
-rw-r--r--drivers/video/savage/savagefb_accel.c8
-rw-r--r--drivers/video/savage/savagefb_driver.c53
-rw-r--r--drivers/video/sbuslib.c25
-rw-r--r--drivers/video/sbuslib.h4
-rw-r--r--drivers/video/sgivwfb.c5
-rw-r--r--drivers/video/sis/sis_main.c28
-rw-r--r--drivers/video/sis/sis_main.h5
-rw-r--r--drivers/video/skeletonfb.c482
-rw-r--r--drivers/video/sstfb.c63
-rw-r--r--drivers/video/stifb.c65
-rw-r--r--drivers/video/tcx.c11
-rw-r--r--drivers/video/tdfxfb.c59
-rw-r--r--drivers/video/valkyriefb.c12
-rw-r--r--drivers/video/vesafb.c47
-rw-r--r--drivers/video/vfb.c4
-rw-r--r--drivers/video/vga16fb.c8
-rw-r--r--drivers/video/vgastate.c5
-rw-r--r--drivers/w1/Kconfig2
-rw-r--r--drivers/zorro/proc.c2
-rw-r--r--drivers/zorro/zorro-driver.c4
1238 files changed, 62181 insertions, 40871 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 48f446d3c671..bddf431bbb72 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -44,6 +44,8 @@ source "drivers/char/Kconfig"
source "drivers/i2c/Kconfig"
+source "drivers/spi/Kconfig"
+
source "drivers/w1/Kconfig"
source "drivers/hwmon/Kconfig"
@@ -66,4 +68,6 @@ source "drivers/infiniband/Kconfig"
source "drivers/sn/Kconfig"
+source "drivers/edac/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ea410b6b7644..619dd964c51c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -13,6 +13,7 @@ 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/
+obj-$(CONFIG_ARM_AMBA) += amba/
# char/ comes before serial/ etc so that the VT console is the boot-time
# default.
@@ -40,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/
obj-$(CONFIG_IEEE1394) += ieee1394/
obj-y += cdrom/
obj-$(CONFIG_MTD) += mtd/
+obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_PCCARD) += pcmcia/
obj-$(CONFIG_DIO) += dio/
obj-$(CONFIG_SBUS) += sbus/
@@ -61,6 +63,7 @@ obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_ISDN) += isdn/
+obj-$(CONFIG_EDAC) += edac/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 4b65f74d66b1..ce074f6f3369 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock);
#define MAJOR_NR MFM_ACORN_MAJOR
#define QUEUE (mfm_queue)
#define CURRENT elv_next_request(mfm_queue)
-/*
- * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
- */
-#ifndef HDIO_GETGEO
-#define HDIO_GETGEO 0x301
-struct hd_geometry {
- unsigned char heads;
- unsigned char sectors;
- unsigned short cylinders;
- unsigned long start;
-};
-#endif
-
/*
* Configuration section
@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void)
* The 'front' end of the mfm driver follows...
*/
-static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
+static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry *geo = (struct hd_geometry *) arg;
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- if (!arg)
- return -EINVAL;
- if (put_user (p->heads, &geo->heads))
- return -EFAULT;
- if (put_user (p->sectors, &geo->sectors))
- return -EFAULT;
- if (put_user (p->cylinders, &geo->cylinders))
- return -EFAULT;
- if (put_user (get_start_sect(inode->i_bdev), &geo->start))
- return -EFAULT;
+ struct mfm_info *p = bdev->bd_disk->private_data;
+
+ geo->heads = p->heads;
+ geo->sectors = p->sectors;
+ geo->cylinders = p->cylinders;
return 0;
}
@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
static struct block_device_operations mfm_fops =
{
.owner = THIS_MODULE,
- .ioctl = mfm_ioctl,
+ .getgeo = mfm_getgeo,
};
/*
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index c22bb9dca1ec..c26c08b36829 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -12,6 +12,7 @@
* On Acorn machines, the following i2c devices are on the bus:
* - PCF8583 real time clock & static RAM
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/time.h>
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index fce21c257523..0cce28c4025b 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -168,7 +168,6 @@ config ACPI_NUMA
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
- 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 +208,6 @@ config ACPI_IBM
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
- default y
---help---
This driver adds support for access to certain system settings
on "legacy free" Toshiba laptops. These laptops can be recognized by
@@ -269,7 +267,6 @@ config ACPI_DEBUG
config ACPI_EC
bool
- depends on X86
default y
help
This driver is required on some systems for the proper operation of
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index fec895af6ae6..f4c87750dbf2 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -78,9 +78,9 @@ MODULE_LICENSE("GPL");
static uid_t asus_uid;
static gid_t asus_gid;
module_param(asus_uid, uint, 0);
-MODULE_PARM_DESC(uid, "UID for entries in /proc/acpi/asus.\n");
+MODULE_PARM_DESC(asus_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");
+MODULE_PARM_DESC(asus_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 */
@@ -302,7 +302,7 @@ static struct model_data model_conf[END_MODEL] = {
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
- .display_get = "\\SSTE"},
+ .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
{
.name = "M6R",
.mt_mled = "MLED",
@@ -851,6 +851,8 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
mode = S_IFREG | S_IRUGO | S_IWUGO;
} else {
mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
+ printk(KERN_WARNING " asus_uid and asus_gid parameters are "
+ "deprecated, use chown and chmod instead!\n");
}
acpi_device_dir(device) = asus_proc_dir;
@@ -987,9 +989,21 @@ static int __init asus_hotk_get_info(void)
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) {
+ /* This is unlikely with implicit return */
+ if (buffer.pointer == NULL)
+ return -EINVAL;
+
+ model = (union acpi_object *) buffer.pointer;
+ /*
+ * Samsung P30 has a device with a valid _HID whose INIT does not
+ * return anything. It used to be possible to catch this exception,
+ * but the implicit return code will now happily confuse the
+ * driver. We assume that every ACPI_TYPE_STRING is a valid model
+ * identifier but it's still possible to get completely bogus data.
+ */
+ if (model->type == ACPI_TYPE_STRING) {
+ printk(KERN_NOTICE " %s model detected, ", model->string.pointer);
+ } else {
if (asus_info && /* Samsung P30 */
strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
hotk->model = P30;
@@ -1002,13 +1016,10 @@ static int __init asus_hotk_get_info(void)
"the developers with your DSDT\n");
}
hotk->methods = &model_conf[hotk->model];
- return AE_OK;
- }
+
+ acpi_os_free(model);
- model = (union acpi_object *)buffer.pointer;
- if (model->type == ACPI_TYPE_STRING) {
- printk(KERN_NOTICE " %s model detected, ",
- model->string.pointer);
+ return AE_OK;
}
hotk->model = END_MODEL;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 0ecbfa5db1ba..79b09d76c180 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -60,20 +60,20 @@ ACPI_MODULE_NAME("acpi_ec")
#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
+#define EC_POLL 0xFF
+#define EC_INTR 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_intr_add(struct acpi_device *device);
+static int acpi_ec_poll_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,
+ .add = acpi_ec_intr_add,
.remove = acpi_ec_remove,
.start = acpi_ec_start,
.stop = acpi_ec_stop,
@@ -105,7 +105,7 @@ union acpi_ec {
atomic_t pending_gpe;
struct semaphore sem;
wait_queue_head_t wait;
- } burst;
+ } intr;
struct {
u32 mode;
@@ -117,43 +117,43 @@ union acpi_ec {
struct acpi_generic_address data_addr;
unsigned long global_lock;
spinlock_t lock;
- } polling;
+ } poll;
};
-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_poll_wait(union acpi_ec *ec, u8 event);
+static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event);
+static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data);
+static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data);
+static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data);
+static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data);
+static void acpi_ec_gpe_poll_query(void *ec_cxt);
+static void acpi_ec_gpe_intr_query(void *ec_cxt);
+static u32 acpi_ec_gpe_poll_handler(void *data);
+static u32 acpi_ec_gpe_intr_handler(void *data);
static acpi_status __init
-acpi_fake_ecdt_polling_callback(acpi_handle handle,
+acpi_fake_ecdt_poll_callback(acpi_handle handle,
u32 Level, void *context, void **retval);
static acpi_status __init
-acpi_fake_ecdt_burst_callback(acpi_handle handle,
+acpi_fake_ecdt_intr_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);
+static int __init acpi_ec_poll_get_real_ecdt(void);
+static int __init acpi_ec_intr_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;
/* External interfaces use first EC only, so remember */
static struct acpi_device *first_ec;
-static int acpi_ec_polling_mode = EC_POLLING;
+static int acpi_ec_poll_mode = EC_INTR;
/* --------------------------------------------------------------------------
Transaction Management
-------------------------------------------------------------------------- */
-static inline u32 acpi_ec_read_status(union acpi_ec *ec)
+static u32 acpi_ec_read_status(union acpi_ec *ec)
{
u32 status = 0;
@@ -163,13 +163,13 @@ static inline u32 acpi_ec_read_status(union acpi_ec *ec)
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_poll_mode)
+ return acpi_ec_poll_wait(ec, event);
else
- return acpi_ec_burst_wait(ec, event);
+ return acpi_ec_intr_wait(ec, event);
}
-static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
+static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event)
{
u32 acpi_ec_status = 0;
u32 i = ACPI_EC_UDELAY_COUNT;
@@ -203,36 +203,31 @@ static int acpi_ec_polling_wait(union acpi_ec *ec, u8 event)
return -ETIME;
}
-static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
+static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event)
{
int result = 0;
ACPI_FUNCTION_TRACE("acpi_ec_wait");
- ec->burst.expect_event = event;
+ ec->intr.expect_event = event;
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;
-
case ACPI_EC_EVENT_IBE:
if (~acpi_ec_read_status(ec) & event) {
- ec->burst.expect_event = 0;
+ ec->intr.expect_event = 0;
return_VALUE(0);
}
break;
+ default:
+ break;
}
- result = wait_event_timeout(ec->burst.wait,
- !ec->burst.expect_event,
+ result = wait_event_timeout(ec->intr.wait,
+ !ec->intr.expect_event,
msecs_to_jiffies(ACPI_EC_DELAY));
- ec->burst.expect_event = 0;
+ ec->intr.expect_event = 0;
smp_mb();
/*
@@ -255,7 +250,12 @@ 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)
+#ifdef ACPI_FUTURE_USAGE
+/*
+ * Note: samsung nv5000 doesn't work with ec burst mode.
+ * http://bugzilla.kernel.org/show_bug.cgi?id=4980
+ */
+int acpi_ec_enter_burst_mode(union acpi_ec *ec)
{
u32 tmp = 0;
int status = 0;
@@ -270,45 +270,56 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
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)
- return_VALUE(-EINVAL);
acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
if (tmp != 0x90) { /* Burst ACK byte */
return_VALUE(-EINVAL);
}
}
- atomic_set(&ec->burst.leaving_burst, 0);
+ atomic_set(&ec->intr.leaving_burst, 0);
return_VALUE(0);
end:
- printk("Error in acpi_ec_wait\n");
+ printk(KERN_WARNING PREFIX "Error in acpi_ec_wait\n");
return_VALUE(-1);
}
-static int acpi_ec_leave_burst_mode(union acpi_ec *ec)
+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)){
+ status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+ if(status)
+ goto end;
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
+ acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+ }
+ atomic_set(&ec->intr.leaving_burst, 1);
return_VALUE(0);
+end:
+ printk(KERN_WARNING PREFIX "leave burst_mode:error\n");
+ return_VALUE(-1);
}
+#endif /* ACPI_FUTURE_USAGE */
static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_read(ec, address, data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_read(ec, address, data);
else
- return acpi_ec_burst_read(ec, address, data);
+ return acpi_ec_intr_read(ec, address, data);
}
static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_write(ec, address, data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_write(ec, address, data);
else
- return acpi_ec_burst_write(ec, address, data);
+ return acpi_ec_intr_write(ec, address, data);
}
-static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data)
{
acpi_status status = AE_OK;
int result = 0;
@@ -328,7 +339,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
return_VALUE(-ENODEV);
}
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
&ec->common.command_addr);
@@ -347,7 +358,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
*data, address));
end:
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -355,7 +366,7 @@ static int acpi_ec_polling_read(union acpi_ec *ec, u8 address, u32 * data)
return_VALUE(result);
}
-static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data)
{
int result = 0;
acpi_status status = AE_OK;
@@ -373,7 +384,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
return_VALUE(-ENODEV);
}
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
&ec->common.command_addr);
@@ -395,7 +406,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
data, address));
end:
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -403,7 +414,7 @@ static int acpi_ec_polling_write(union acpi_ec *ec, u8 address, u8 data)
return_VALUE(result);
}
-static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data)
{
int status = 0;
u32 glk;
@@ -422,25 +433,24 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
}
WARN_ON(in_interrupt());
- down(&ec->burst.sem);
+ down(&ec->intr.sem);
- acpi_ec_enter_burst_mode(ec);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("read EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "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");
+ printk(KERN_DEBUG PREFIX "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) {
- printk("read EC, OB not full\n");
+ printk(KERN_DEBUG PREFIX "read EC, OB not full\n");
goto end;
}
acpi_hw_low_level_read(8, data, &ec->common.data_addr);
@@ -448,8 +458,7 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
*data, address));
end:
- acpi_ec_leave_burst_mode(ec);
- up(&ec->burst.sem);
+ up(&ec->intr.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -457,7 +466,7 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
return_VALUE(status);
}
-static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data)
{
int status = 0;
u32 glk;
@@ -474,25 +483,23 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
}
WARN_ON(in_interrupt());
- down(&ec->burst.sem);
-
- acpi_ec_enter_burst_mode(ec);
+ down(&ec->intr.sem);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("write EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("write EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "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) {
- printk("write EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
}
acpi_hw_low_level_write(8, data, &ec->common.data_addr);
@@ -500,8 +507,7 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
data, address));
- acpi_ec_leave_burst_mode(ec);
- up(&ec->burst.sem);
+ up(&ec->intr.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -553,12 +559,12 @@ EXPORT_SYMBOL(ec_write);
static int acpi_ec_query(union acpi_ec *ec, u32 * data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_query(ec, data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_query(ec, data);
else
- return acpi_ec_burst_query(ec, data);
+ return acpi_ec_intr_query(ec, data);
}
-static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
+static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data)
{
int result = 0;
acpi_status status = AE_OK;
@@ -583,7 +589,7 @@ static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
* Note that successful completion of the query causes the ACPI_EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
&ec->common.command_addr);
@@ -596,14 +602,14 @@ static int acpi_ec_polling_query(union acpi_ec *ec, u32 * data)
result = -ENODATA;
end:
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
return_VALUE(result);
}
-static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
+static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data)
{
int status = 0;
u32 glk;
@@ -620,11 +626,11 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
return_VALUE(-ENODEV);
}
- down(&ec->burst.sem);
+ down(&ec->intr.sem);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
- printk("query EC, IB not empty\n");
+ printk(KERN_DEBUG PREFIX "query EC, IB not empty\n");
goto end;
}
/*
@@ -636,7 +642,7 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
if (status) {
- printk("query EC, OB not full\n");
+ printk(KERN_DEBUG PREFIX "query EC, OB not full\n");
goto end;
}
@@ -645,7 +651,7 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data)
status = -ENODATA;
end:
- up(&ec->burst.sem);
+ up(&ec->intr.sem);
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -664,13 +670,13 @@ union acpi_ec_query_data {
static void acpi_ec_gpe_query(void *ec_cxt)
{
- if (acpi_ec_polling_mode)
- acpi_ec_gpe_polling_query(ec_cxt);
+ if (acpi_ec_poll_mode)
+ acpi_ec_gpe_poll_query(ec_cxt);
else
- acpi_ec_gpe_burst_query(ec_cxt);
+ acpi_ec_gpe_intr_query(ec_cxt);
}
-static void acpi_ec_gpe_polling_query(void *ec_cxt)
+static void acpi_ec_gpe_poll_query(void *ec_cxt)
{
union acpi_ec *ec = (union acpi_ec *)ec_cxt;
u32 value = 0;
@@ -685,9 +691,9 @@ static void acpi_ec_gpe_polling_query(void *ec_cxt)
if (!ec_cxt)
goto end;
- spin_lock_irqsave(&ec->polling.lock, flags);
+ spin_lock_irqsave(&ec->poll.lock, flags);
acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
- spin_unlock_irqrestore(&ec->polling.lock, flags);
+ spin_unlock_irqrestore(&ec->poll.lock, flags);
/* TBD: Implement asynch events!
* NOTE: All we care about are EC-SCI's. Other EC events are
@@ -711,7 +717,7 @@ static void acpi_ec_gpe_polling_query(void *ec_cxt)
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_intr_query(void *ec_cxt)
{
union acpi_ec *ec = (union acpi_ec *)ec_cxt;
u32 value;
@@ -736,18 +742,18 @@ static void acpi_ec_gpe_burst_query(void *ec_cxt)
acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
end:
- atomic_dec(&ec->burst.pending_gpe);
+ atomic_dec(&ec->intr.pending_gpe);
return;
}
static u32 acpi_ec_gpe_handler(void *data)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_gpe_polling_handler(data);
+ if (acpi_ec_poll_mode)
+ return acpi_ec_gpe_poll_handler(data);
else
- return acpi_ec_gpe_burst_handler(data);
+ return acpi_ec_gpe_intr_handler(data);
}
-static u32 acpi_ec_gpe_polling_handler(void *data)
+static u32 acpi_ec_gpe_poll_handler(void *data)
{
acpi_status status = AE_OK;
union acpi_ec *ec = (union acpi_ec *)data;
@@ -765,7 +771,7 @@ static u32 acpi_ec_gpe_polling_handler(void *data)
else
return ACPI_INTERRUPT_NOT_HANDLED;
}
-static u32 acpi_ec_gpe_burst_handler(void *data)
+static u32 acpi_ec_gpe_intr_handler(void *data)
{
acpi_status status = AE_OK;
u32 value;
@@ -777,22 +783,22 @@ static u32 acpi_ec_gpe_burst_handler(void *data)
acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
value = acpi_ec_read_status(ec);
- switch (ec->burst.expect_event) {
+ switch (ec->intr.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);
+ ec->intr.expect_event = 0;
+ wake_up(&ec->intr.wait);
return ACPI_INTERRUPT_HANDLED;
default:
break;
}
if (value & ACPI_EC_FLAG_SCI) {
- atomic_add(1, &ec->burst.pending_gpe);
+ atomic_add(1, &ec->intr.pending_gpe);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
acpi_ec_gpe_query, ec);
return status == AE_OK ?
@@ -980,7 +986,7 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
Driver Interface
-------------------------------------------------------------------------- */
-static int acpi_ec_polling_add(struct acpi_device *device)
+static int acpi_ec_poll_add(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
@@ -999,7 +1005,7 @@ static int acpi_ec_polling_add(struct acpi_device *device)
ec->common.handle = device->handle;
ec->common.uid = -1;
- spin_lock_init(&ec->polling.lock);
+ spin_lock_init(&ec->poll.lock);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
@@ -1038,7 +1044,7 @@ static int acpi_ec_polling_add(struct acpi_device *device)
if (result)
goto end;
- printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+ printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n",
acpi_device_name(device), acpi_device_bid(device),
(u32) ec->common.gpe_bit);
@@ -1051,7 +1057,7 @@ static int acpi_ec_polling_add(struct acpi_device *device)
return_VALUE(result);
}
-static int acpi_ec_burst_add(struct acpi_device *device)
+static int acpi_ec_intr_add(struct acpi_device *device)
{
int result = 0;
acpi_status status = AE_OK;
@@ -1070,10 +1076,10 @@ static int acpi_ec_burst_add(struct acpi_device *device)
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->intr.pending_gpe, 0);
+ atomic_set(&ec->intr.leaving_burst, 1);
+ init_MUTEX(&ec->intr.sem);
+ init_waitqueue_head(&ec->intr.wait);
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_EC_CLASS);
acpi_driver_data(device) = ec;
@@ -1112,8 +1118,7 @@ static int acpi_ec_burst_add(struct acpi_device *device)
if (result)
goto end;
- printk("burst-mode-ec-10-Aug\n");
- printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n",
+ printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n",
acpi_device_name(device), acpi_device_bid(device),
(u32) ec->common.gpe_bit);
@@ -1267,16 +1272,16 @@ 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,
+ if (acpi_ec_poll_mode)
+ return acpi_fake_ecdt_poll_callback(handle,
Level, context, retval);
else
- return acpi_fake_ecdt_burst_callback(handle,
+ return acpi_fake_ecdt_intr_callback(handle,
Level, context, retval);
}
static acpi_status __init
-acpi_fake_ecdt_polling_callback(acpi_handle handle,
+acpi_fake_ecdt_poll_callback(acpi_handle handle,
u32 Level, void *context, void **retval)
{
acpi_status status;
@@ -1295,7 +1300,7 @@ acpi_fake_ecdt_polling_callback(acpi_handle handle,
&ec_ecdt->common.gpe_bit);
if (ACPI_FAILURE(status))
return status;
- spin_lock_init(&ec_ecdt->polling.lock);
+ spin_lock_init(&ec_ecdt->poll.lock);
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.handle = handle;
@@ -1308,13 +1313,13 @@ acpi_fake_ecdt_polling_callback(acpi_handle handle,
}
static acpi_status __init
-acpi_fake_ecdt_burst_callback(acpi_handle handle,
+acpi_fake_ecdt_intr_callback(acpi_handle handle,
u32 Level, void *context, void **retval)
{
acpi_status status;
- init_MUTEX(&ec_ecdt->burst.sem);
- init_waitqueue_head(&ec_ecdt->burst.wait);
+ init_MUTEX(&ec_ecdt->intr.sem);
+ init_waitqueue_head(&ec_ecdt->intr.wait);
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
acpi_ec_io_ports, ec_ecdt);
if (ACPI_FAILURE(status))
@@ -1380,13 +1385,13 @@ static int __init acpi_ec_fake_ecdt(void)
static int __init acpi_ec_get_real_ecdt(void)
{
- if (acpi_ec_polling_mode)
- return acpi_ec_polling_get_real_ecdt();
+ if (acpi_ec_poll_mode)
+ return acpi_ec_poll_get_real_ecdt();
else
- return acpi_ec_burst_get_real_ecdt();
+ return acpi_ec_intr_get_real_ecdt();
}
-static int __init acpi_ec_polling_get_real_ecdt(void)
+static int __init acpi_ec_poll_get_real_ecdt(void)
{
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
@@ -1411,7 +1416,7 @@ static int __init acpi_ec_polling_get_real_ecdt(void)
ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
- spin_lock_init(&ec_ecdt->polling.lock);
+ spin_lock_init(&ec_ecdt->poll.lock);
/* use the GL just to be safe */
ec_ecdt->common.global_lock = TRUE;
ec_ecdt->common.uid = ecdt_ptr->uid;
@@ -1431,7 +1436,7 @@ static int __init acpi_ec_polling_get_real_ecdt(void)
return -ENODEV;
}
-static int __init acpi_ec_burst_get_real_ecdt(void)
+static int __init acpi_ec_intr_get_real_ecdt(void)
{
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
@@ -1452,8 +1457,8 @@ static int __init 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->intr.sem);
+ init_waitqueue_head(&ec_ecdt->intr.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;
@@ -1571,22 +1576,22 @@ static int __init acpi_fake_ecdt_setup(char *str)
}
__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
-static int __init acpi_ec_set_polling_mode(char *str)
+static int __init acpi_ec_set_intr_mode(char *str)
{
- int burst;
+ int intr;
- if (!get_option(&str, &burst))
+ if (!get_option(&str, &intr))
return 0;
- if (burst) {
- acpi_ec_polling_mode = EC_BURST;
- acpi_ec_driver.ops.add = acpi_ec_burst_add;
+ if (intr) {
+ acpi_ec_poll_mode = EC_INTR;
+ acpi_ec_driver.ops.add = acpi_ec_intr_add;
} else {
- acpi_ec_polling_mode = EC_POLLING;
- acpi_ec_driver.ops.add = acpi_ec_polling_add;
+ acpi_ec_poll_mode = EC_POLL;
+ acpi_ec_driver.ops.add = acpi_ec_poll_add;
}
- printk(KERN_INFO PREFIX "EC %s mode.\n", burst ? "burst" : "polling");
+ printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
return 0;
}
-__setup("ec_burst=", acpi_ec_set_polling_mode);
+__setup("ec_intr=", acpi_ec_set_intr_mode);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 58e7c47354ee..cc4a4903842a 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -204,11 +204,13 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
return AE_OK;
}
+EXPORT_SYMBOL_GPL(acpi_os_map_memory);
void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
{
iounmap(virt);
}
+EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
#ifdef ACPI_FUTURE_USAGE
acpi_status
@@ -836,7 +838,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
static const int quantum_ms = 1000 / HZ;
ret = down_trylock(sem);
- for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
+ for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
schedule_timeout_interruptible(1);
ret = down_trylock(sem);
}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 726dda1fce1c..65aee79b3971 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -361,8 +361,7 @@ acpi_pci_irq_derive(struct pci_dev *dev,
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);
+ bridge_pin = bridge->pin;
if (!bridge_pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
@@ -412,7 +411,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
if (!dev)
return_VALUE(-EINVAL);
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
@@ -503,7 +502,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (!dev || !dev->bus)
return_VOID;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin)
return_VOID;
pin--;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 1278aca96fe3..99a3a28594da 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -253,31 +253,21 @@ static int acpi_processor_errata(struct acpi_processor *pr)
* _PDC is required for a BIOS-OS handshake for most of the newer
* ACPI processor features.
*/
-
-int acpi_processor_set_pdc(struct acpi_processor *pr,
- struct acpi_object_list *pdc_in)
+static int acpi_processor_set_pdc(struct acpi_processor *pr)
{
+ struct acpi_object_list *pdc_in = pr->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");
- arg0.buffer.length = 12;
- arg0.buffer.pointer = (u8 *) arg0_buf;
- arg0_buf[0] = ACPI_PDC_REVISION_ID;
- arg0_buf[1] = 0;
- arg0_buf[2] = 0;
-
- pdc = (pdc_in) ? pdc_in : &no_object;
+ if (!pdc_in)
+ return_VALUE(status);
- status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
+ status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);
- if ((ACPI_FAILURE(status)) && (pdc_in))
+ if (ACPI_FAILURE(status))
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Error evaluating _PDC, using legacy perf. control...\n"));
+ "Could not evaluate _PDC, using legacy perf. control...\n"));
return_VALUE(status);
}
@@ -357,7 +347,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
ACPI_PROCESSOR_FILE_THROTTLING));
else {
entry->proc_fops = &acpi_processor_throttling_fops;
- entry->proc_fops->write = acpi_processor_write_throttling;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -372,7 +361,6 @@ static int acpi_processor_add_fs(struct acpi_device *device)
ACPI_PROCESSOR_FILE_LIMIT));
else {
entry->proc_fops = &acpi_processor_limit_fops;
- entry->proc_fops->write = acpi_processor_write_limit;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -589,6 +577,10 @@ static int acpi_processor_start(struct acpi_device *device)
"Error installing device notify handler\n"));
}
+ /* _PDC call should be done before doing anything else (if reqd.). */
+ arch_acpi_processor_init_pdc(pr);
+ acpi_processor_set_pdc(pr);
+
acpi_processor_power_init(pr, device);
if (pr->flags.throttling) {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 807b0df308f1..be2dae52f6fa 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -95,22 +95,57 @@ static int set_max_cstate(struct dmi_system_id *id)
}
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")},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1},
+ { set_max_cstate, "IBM ThinkPad R40e", {
+ DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
+ DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (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},
{},
};
@@ -550,18 +585,10 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
if (!pr->pblk)
return_VALUE(-ENODEV);
- memset(pr->power.states, 0, sizeof(pr->power.states));
-
/* if info is obtained from pblk/fadt, type equals state */
- pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
- /* the C0 state only exists as a filler in our array,
- * and all processors need to support C1 */
- pr->power.states[ACPI_STATE_C0].valid = 1;
- pr->power.states[ACPI_STATE_C1].valid = 1;
-
#ifndef CONFIG_HOTPLUG_CPU
/*
* Check for P_LVL2_UP flag before entering C2 and above on
@@ -591,12 +618,11 @@ static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr)
{
ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
+ /* Zero initialize all the C-states info. */
memset(pr->power.states, 0, sizeof(pr->power.states));
- /* if info is obtained from pblk/fadt, type equals state */
+ /* set the first C-State to C1 */
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
- pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
- pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
/* the C0 state only exists as a filler in our array,
* and all processors need to support C1 */
@@ -610,6 +636,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
{
acpi_status status = 0;
acpi_integer count;
+ int current_count;
int i;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *cst;
@@ -619,10 +646,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
if (nocst)
return_VALUE(-ENODEV);
- pr->power.count = 0;
- for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
- memset(&(pr->power.states[i]), 0,
- sizeof(struct acpi_processor_cx));
+ current_count = 1;
+
+ /* Zero initialize C2 onwards and prepare for fresh CST lookup */
+ for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++)
+ memset(&(pr->power.states[i]), 0,
+ sizeof(struct acpi_processor_cx));
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
if (ACPI_FAILURE(status)) {
@@ -650,16 +679,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
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");
- count = ACPI_PROCESSOR_MAX_POWER;
- }
-
/* Tell driver that at least _CST is supported. */
pr->flags.has_cst = 1;
@@ -703,7 +722,7 @@ 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_C2) || (cx.type > ACPI_STATE_C3))
continue;
obj = (union acpi_object *)&(element->package.elements[2]);
@@ -718,15 +737,28 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
cx.power = obj->integer.value;
- (pr->power.count)++;
- memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx));
+ current_count++;
+ memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
+
+ /*
+ * We support total ACPI_PROCESSOR_MAX_POWER - 1
+ * (From 1 through ACPI_PROCESSOR_MAX_POWER - 1)
+ */
+ if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) {
+ 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");
+ break;
+ }
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
- pr->power.count));
+ current_count));
/* Validate number of power states discovered */
- if (pr->power.count < 2)
+ if (current_count < 2)
status = -EFAULT;
end:
@@ -843,6 +875,15 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
unsigned int i;
unsigned int working = 0;
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+ struct cpuinfo_x86 *c = cpu_data + pr->id;
+ cpumask_t mask = cpumask_of_cpu(pr->id);
+
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
+ on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
+ }
+#endif
+
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -857,6 +898,12 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
case ACPI_STATE_C3:
acpi_processor_power_verify_c3(pr, cx);
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
+ on_each_cpu(switch_APIC_timer_to_ipi,
+ &mask, 1, 1);
+ }
+#endif
break;
}
@@ -877,12 +924,13 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
/* NOTE: the idle thread may not be running while calling
* this function */
+ /* Adding C1 state */
+ acpi_processor_get_power_info_default_c1(pr);
result = acpi_processor_get_power_info_cst(pr);
if (result == -ENODEV)
- result = acpi_processor_get_power_info_fadt(pr);
+ acpi_processor_get_power_info_fadt(pr);
- if ((result) || (acpi_processor_power_verify(pr) < 2))
- result = acpi_processor_get_power_info_default_c1(pr);
+ pr->power.count = acpi_processor_power_verify(pr);
/*
* Set Default Policy
@@ -1051,8 +1099,6 @@ int acpi_processor_power_init(struct acpi_processor *pr,
}
}
- acpi_processor_power_init_pdc(&(pr->power), pr->id);
- acpi_processor_set_pdc(pr, pr->power.pdc);
acpi_processor_get_power_info(pr);
/*
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 22c7bb66c200..abbdb37a7f5f 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -315,8 +315,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
if (!pr || !pr->performance || !pr->handle)
return_VALUE(-EINVAL);
- acpi_processor_set_pdc(pr, pr->performance->pdc);
-
status = acpi_get_handle(pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -520,8 +518,8 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr)
"Unable to create '%s' fs entry\n",
ACPI_PROCESSOR_FILE_PERFORMANCE));
else {
+ acpi_processor_perf_fops.write = acpi_processor_write_performance;
entry->proc_fops = &acpi_processor_perf_fops;
- entry->proc_fops->write = acpi_processor_write_performance;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index dc9817cfb882..f99ad05cd6a2 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -348,9 +348,9 @@ static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
PDE(inode)->data);
}
-ssize_t acpi_processor_write_limit(struct file * file,
- const char __user * buffer,
- size_t count, loff_t * data)
+static 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;
@@ -394,6 +394,7 @@ ssize_t acpi_processor_write_limit(struct file * file,
struct file_operations acpi_processor_limit_fops = {
.open = acpi_processor_limit_open_fs,
.read = seq_read,
+ .write = acpi_processor_write_limit,
.llseek = seq_lseek,
.release = single_release,
};
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 74a52d4e79ae..b966549ec000 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -306,9 +306,9 @@ static int acpi_processor_throttling_open_fs(struct inode *inode,
PDE(inode)->data);
}
-ssize_t acpi_processor_write_throttling(struct file * file,
- const char __user * buffer,
- size_t count, loff_t * data)
+static 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;
@@ -337,6 +337,7 @@ ssize_t acpi_processor_write_throttling(struct file * file,
struct file_operations acpi_processor_throttling_fops = {
.open = acpi_processor_throttling_open_fs,
.read = seq_read,
+ .write = acpi_processor_write_throttling,
.llseek = seq_lseek,
.release = single_release,
};
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index c60516d0f66b..9271e5209ac1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -475,8 +475,10 @@ static LIST_HEAD(acpi_bus_drivers);
static DECLARE_MUTEX(acpi_bus_drivers_lock);
/**
- * acpi_bus_match
- * --------------
+ * acpi_bus_match - match device IDs to driver's supported IDs
+ * @device: the device that we are trying to match to a driver
+ * @driver: driver whose device id table is being checked
+ *
* Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
* matches the specified driver's criteria.
*/
@@ -489,8 +491,10 @@ acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
}
/**
- * acpi_bus_driver_init
- * --------------------
+ * acpi_bus_driver_init - add a device to a driver
+ * @device: the device to add and initialize
+ * @driver: driver for the device
+ *
* Used to initialize a device via its device driver. Called whenever a
* driver is bound to a device. Invokes the driver's add() and start() ops.
*/
@@ -603,8 +607,9 @@ static int acpi_driver_detach(struct acpi_driver *drv)
}
/**
- * acpi_bus_register_driver
- * ------------------------
+ * acpi_bus_register_driver - register a driver with the ACPI bus
+ * @driver: driver being registered
+ *
* Registers a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and binds. Returns the
* number of devices that were claimed by the driver, or a negative
@@ -633,8 +638,9 @@ int acpi_bus_register_driver(struct acpi_driver *driver)
EXPORT_SYMBOL(acpi_bus_register_driver);
/**
- * acpi_bus_unregister_driver
- * --------------------------
+ * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
+ * @driver: driver to unregister
+ *
* Unregisters a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and unbinds.
*/
@@ -660,8 +666,9 @@ int acpi_bus_unregister_driver(struct acpi_driver *driver)
EXPORT_SYMBOL(acpi_bus_unregister_driver);
/**
- * acpi_bus_find_driver
- * --------------------
+ * acpi_bus_find_driver - check if there is a driver installed for the device
+ * @device: device that we are trying to find a supporting driver for
+ *
* Parses the list of registered drivers looking for a driver applicable for
* the specified device.
*/
diff --git a/drivers/acpi/sleep/poweroff.c b/drivers/acpi/sleep/poweroff.c
index af7935a95bcc..47fb4b394eec 100644
--- a/drivers/acpi/sleep/poweroff.c
+++ b/drivers/acpi/sleep/poweroff.c
@@ -33,9 +33,7 @@ int acpi_sleep_prepare(u32 acpi_state)
ACPI_FLUSH_CPU_CACHE();
acpi_enable_wakeup_device_prep(acpi_state);
#endif
- if (acpi_state == ACPI_STATE_S5) {
- acpi_wakeup_gpe_poweroff_prepare();
- }
+ acpi_gpe_sleep_prepare(acpi_state);
acpi_enter_sleep_state_prep(acpi_state);
return 0;
}
@@ -53,11 +51,16 @@ void acpi_power_off(void)
static int acpi_shutdown(struct sys_device *x)
{
- if (system_state == SYSTEM_POWER_OFF) {
- /* Prepare if we are going to power off the system */
+ switch (system_state) {
+ case SYSTEM_POWER_OFF:
+ /* Prepare to power off the system */
return acpi_sleep_prepare(ACPI_STATE_S5);
+ case SYSTEM_SUSPEND_DISK:
+ /* Prepare to suspend the system to disk */
+ return acpi_sleep_prepare(ACPI_STATE_S4);
+ default:
+ return 0;
}
- return 0;
}
static struct sysdev_class acpi_sysclass = {
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index efd0001c6f05..f3e70397a7d6 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -5,4 +5,4 @@ extern int acpi_suspend (u32 state);
extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
extern void acpi_enable_wakeup_device(u8 sleep_state);
extern void acpi_disable_wakeup_device(u8 sleep_state);
-extern void acpi_wakeup_gpe_poweroff_prepare(void);
+extern void acpi_gpe_sleep_prepare(u32 sleep_state);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 4134ed43d026..85df0ceda2a9 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -192,7 +192,7 @@ late_initcall(acpi_wakeup_device_init);
* RUNTIME GPEs, we simply mark all GPES that
* are not enabled for wakeup from S5 as RUNTIME.
*/
-void acpi_wakeup_gpe_poweroff_prepare(void)
+void acpi_gpe_sleep_prepare(u32 sleep_state)
{
struct list_head *node, *next;
@@ -201,8 +201,8 @@ void acpi_wakeup_gpe_poweroff_prepare(void)
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)
+ /* The GPE can wakeup system from this state, don't touch it */
+ if ((u32) dev->wakeup.sleep_state >= sleep_state)
continue;
/* acpi_set_gpe_type will automatically disable GPE */
acpi_set_gpe_type(dev->wakeup.gpe_device,
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index a2bf25b05e1c..31d4f3ffc265 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -37,7 +37,7 @@
#define PREFIX "ACPI: "
-#define ACPI_MAX_TABLES 256
+#define ACPI_MAX_TABLES 128
static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
[ACPI_TABLE_UNKNOWN] = "????",
@@ -74,7 +74,7 @@ struct acpi_table_sdt {
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] __initdata;
void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr)
{
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index d10668f14699..bd4887518373 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -920,8 +920,8 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'state' fs entry\n"));
else {
+ acpi_video_device_state_fops.write = acpi_video_device_write_state;
entry->proc_fops = &acpi_video_device_state_fops;
- entry->proc_fops->write = acpi_video_device_write_state;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -934,8 +934,8 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'brightness' fs entry\n"));
else {
+ acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
entry->proc_fops = &acpi_video_device_brightness_fops;
- entry->proc_fops->write = acpi_video_device_write_brightness;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -1239,8 +1239,8 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'POST' fs entry\n"));
else {
+ acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
entry->proc_fops = &acpi_video_bus_POST_fops;
- entry->proc_fops->write = acpi_video_bus_write_POST;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
@@ -1253,8 +1253,8 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to create 'DOS' fs entry\n"));
else {
+ acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
entry->proc_fops = &acpi_video_bus_DOS_fops;
- entry->proc_fops->write = acpi_video_bus_write_DOS;
entry->data = acpi_driver_data(device);
entry->owner = THIS_MODULE;
}
diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile
new file mode 100644
index 000000000000..40fe74097be2
--- /dev/null
+++ b/drivers/amba/Makefile
@@ -0,0 +1,2 @@
+obj-y += bus.o
+
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
new file mode 100644
index 000000000000..889855d8d9f9
--- /dev/null
+++ b/drivers/amba/bus.c
@@ -0,0 +1,358 @@
+/*
+ * linux/arch/arm/common/amba.c
+ *
+ * Copyright (C) 2003 Deep Blue Solutions Ltd, 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.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/amba/bus.h>
+
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#define to_amba_device(d) container_of(d, struct amba_device, dev)
+#define to_amba_driver(d) container_of(d, struct amba_driver, drv)
+
+static struct amba_id *
+amba_lookup(struct amba_id *table, struct amba_device *dev)
+{
+ int ret = 0;
+
+ while (table->mask) {
+ ret = (dev->periphid & table->mask) == table->id;
+ if (ret)
+ break;
+ table++;
+ }
+
+ return ret ? table : NULL;
+}
+
+static int amba_match(struct device *dev, struct device_driver *drv)
+{
+ struct amba_device *pcdev = to_amba_device(dev);
+ struct amba_driver *pcdrv = to_amba_driver(drv);
+
+ return amba_lookup(pcdrv->id_table, pcdev) != NULL;
+}
+
+#ifdef CONFIG_HOTPLUG
+static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
+{
+ struct amba_device *pcdev = to_amba_device(dev);
+
+ if (nr_env < 2)
+ return -ENOMEM;
+
+ snprintf(buf, bufsz, "AMBA_ID=%08x", pcdev->periphid);
+ *envp++ = buf;
+ *envp++ = NULL;
+ return 0;
+}
+#else
+#define amba_uevent NULL
+#endif
+
+static int amba_suspend(struct device *dev, pm_message_t state)
+{
+ struct amba_driver *drv = to_amba_driver(dev->driver);
+ int ret = 0;
+
+ if (dev->driver && drv->suspend)
+ ret = drv->suspend(to_amba_device(dev), state);
+ return ret;
+}
+
+static int amba_resume(struct device *dev)
+{
+ struct amba_driver *drv = to_amba_driver(dev->driver);
+ int ret = 0;
+
+ if (dev->driver && drv->resume)
+ ret = drv->resume(to_amba_device(dev));
+ return ret;
+}
+
+/*
+ * Primecells are part of the Advanced Microcontroller Bus Architecture,
+ * so we call the bus "amba".
+ */
+static struct bus_type amba_bustype = {
+ .name = "amba",
+ .match = amba_match,
+ .uevent = amba_uevent,
+ .suspend = amba_suspend,
+ .resume = amba_resume,
+};
+
+static int __init amba_init(void)
+{
+ return bus_register(&amba_bustype);
+}
+
+postcore_initcall(amba_init);
+
+/*
+ * These are the device model conversion veneers; they convert the
+ * device model structures to our more specific structures.
+ */
+static int amba_probe(struct device *dev)
+{
+ struct amba_device *pcdev = to_amba_device(dev);
+ struct amba_driver *pcdrv = to_amba_driver(dev->driver);
+ struct amba_id *id;
+
+ id = amba_lookup(pcdrv->id_table, pcdev);
+
+ return pcdrv->probe(pcdev, id);
+}
+
+static int amba_remove(struct device *dev)
+{
+ struct amba_driver *drv = to_amba_driver(dev->driver);
+ return drv->remove(to_amba_device(dev));
+}
+
+static void amba_shutdown(struct device *dev)
+{
+ struct amba_driver *drv = to_amba_driver(dev->driver);
+ drv->shutdown(to_amba_device(dev));
+}
+
+/**
+ * amba_driver_register - register an AMBA device driver
+ * @drv: amba device driver structure
+ *
+ * Register an AMBA device driver with the Linux device model
+ * core. If devices pre-exist, the drivers probe function will
+ * be called.
+ */
+int amba_driver_register(struct amba_driver *drv)
+{
+ drv->drv.bus = &amba_bustype;
+
+#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn
+ SETFN(probe);
+ SETFN(remove);
+ SETFN(shutdown);
+
+ return driver_register(&drv->drv);
+}
+
+/**
+ * amba_driver_unregister - remove an AMBA device driver
+ * @drv: AMBA device driver structure to remove
+ *
+ * Unregister an AMBA device driver from the Linux device
+ * model. The device model will call the drivers remove function
+ * for each device the device driver is currently handling.
+ */
+void amba_driver_unregister(struct amba_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+
+static void amba_device_release(struct device *dev)
+{
+ struct amba_device *d = to_amba_device(dev);
+
+ if (d->res.parent)
+ release_resource(&d->res);
+ kfree(d);
+}
+
+#define amba_attr(name,fmt,arg...) \
+static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct amba_device *dev = to_amba_device(_dev); \
+ return sprintf(buf, fmt, arg); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+amba_attr(id, "%08x\n", dev->periphid);
+amba_attr(irq0, "%u\n", dev->irq[0]);
+amba_attr(irq1, "%u\n", dev->irq[1]);
+amba_attr(resource, "\t%08lx\t%08lx\t%08lx\n",
+ dev->res.start, dev->res.end, dev->res.flags);
+
+/**
+ * amba_device_register - register an AMBA device
+ * @dev: AMBA device to register
+ * @parent: parent memory resource
+ *
+ * Setup the AMBA device, reading the cell ID if present.
+ * Claim the resource, and register the AMBA device with
+ * the Linux device manager.
+ */
+int amba_device_register(struct amba_device *dev, struct resource *parent)
+{
+ u32 pid, cid;
+ void __iomem *tmp;
+ int i, ret;
+
+ dev->dev.release = amba_device_release;
+ dev->dev.bus = &amba_bustype;
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->res.name = dev->dev.bus_id;
+
+ if (!dev->dev.coherent_dma_mask && dev->dma_mask)
+ dev_warn(&dev->dev, "coherent dma mask is unset\n");
+
+ ret = request_resource(parent, &dev->res);
+ if (ret == 0) {
+ tmp = ioremap(dev->res.start, SZ_4K);
+ if (!tmp) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (pid = 0, i = 0; i < 4; i++)
+ pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8);
+ for (cid = 0, i = 0; i < 4; i++)
+ cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8);
+
+ iounmap(tmp);
+
+ if (cid == 0xb105f00d)
+ dev->periphid = pid;
+
+ if (dev->periphid)
+ ret = device_register(&dev->dev);
+ else
+ ret = -ENODEV;
+
+ if (ret == 0) {
+ device_create_file(&dev->dev, &dev_attr_id);
+ if (dev->irq[0] != NO_IRQ)
+ device_create_file(&dev->dev, &dev_attr_irq0);
+ if (dev->irq[1] != NO_IRQ)
+ device_create_file(&dev->dev, &dev_attr_irq1);
+ device_create_file(&dev->dev, &dev_attr_resource);
+ } else {
+ out:
+ release_resource(&dev->res);
+ }
+ }
+ return ret;
+}
+
+/**
+ * amba_device_unregister - unregister an AMBA device
+ * @dev: AMBA device to remove
+ *
+ * Remove the specified AMBA device from the Linux device
+ * manager. All files associated with this object will be
+ * destroyed, and device drivers notified that the device has
+ * been removed. The AMBA device's resources including
+ * the amba_device structure will be freed once all
+ * references to it have been dropped.
+ */
+void amba_device_unregister(struct amba_device *dev)
+{
+ device_unregister(&dev->dev);
+}
+
+
+struct find_data {
+ struct amba_device *dev;
+ struct device *parent;
+ const char *busid;
+ unsigned int id;
+ unsigned int mask;
+};
+
+static int amba_find_match(struct device *dev, void *data)
+{
+ struct find_data *d = data;
+ struct amba_device *pcdev = to_amba_device(dev);
+ int r;
+
+ r = (pcdev->periphid & d->mask) == d->id;
+ if (d->parent)
+ r &= d->parent == dev->parent;
+ if (d->busid)
+ r &= strcmp(dev->bus_id, d->busid) == 0;
+
+ if (r) {
+ get_device(dev);
+ d->dev = pcdev;
+ }
+
+ return r;
+}
+
+/**
+ * amba_find_device - locate an AMBA device given a bus id
+ * @busid: bus id for device (or NULL)
+ * @parent: parent device (or NULL)
+ * @id: peripheral ID (or 0)
+ * @mask: peripheral ID mask (or 0)
+ *
+ * Return the AMBA device corresponding to the supplied parameters.
+ * If no device matches, returns NULL.
+ *
+ * NOTE: When a valid device is found, its refcount is
+ * incremented, and must be decremented before the returned
+ * reference.
+ */
+struct amba_device *
+amba_find_device(const char *busid, struct device *parent, unsigned int id,
+ unsigned int mask)
+{
+ struct find_data data;
+
+ data.dev = NULL;
+ data.parent = parent;
+ data.busid = busid;
+ data.id = id;
+ data.mask = mask;
+
+ bus_for_each_dev(&amba_bustype, NULL, &data, amba_find_match);
+
+ return data.dev;
+}
+
+/**
+ * amba_request_regions - request all mem regions associated with device
+ * @dev: amba_device structure for device
+ * @name: name, or NULL to use driver name
+ */
+int amba_request_regions(struct amba_device *dev, const char *name)
+{
+ int ret = 0;
+
+ if (!name)
+ name = dev->dev.driver->name;
+
+ if (!request_mem_region(dev->res.start, SZ_4K, name))
+ ret = -EBUSY;
+
+ return ret;
+}
+
+/**
+ * amba_release_regions - release mem regions assoicated with device
+ * @dev: amba_device structure for device
+ *
+ * Release regions claimed by a successful call to amba_request_regions.
+ */
+void amba_release_regions(struct amba_device *dev)
+{
+ release_mem_region(dev->res.start, SZ_4K);
+}
+
+EXPORT_SYMBOL(amba_driver_register);
+EXPORT_SYMBOL(amba_driver_unregister);
+EXPORT_SYMBOL(amba_device_register);
+EXPORT_SYMBOL(amba_device_unregister);
+EXPORT_SYMBOL(amba_find_device);
+EXPORT_SYMBOL(amba_request_regions);
+EXPORT_SYMBOL(amba_release_regions);
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index c57e20dcb0f8..074abc81ec3d 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -2126,8 +2126,7 @@ static void process_rsq(ns_dev *card)
if (!ns_rsqe_valid(card->rsq.next))
return;
- while (ns_rsqe_valid(card->rsq.next))
- {
+ do {
dequeue_rx(card, card->rsq.next);
ns_rsqe_init(card->rsq.next);
previous = card->rsq.next;
@@ -2135,7 +2134,7 @@ static void process_rsq(ns_dev *card)
card->rsq.next = card->rsq.base;
else
card->rsq.next++;
- }
+ } while (ns_rsqe_valid(card->rsq.next));
writel((((u32) previous) - ((u32) card->rsq.base)),
card->membase + RSQH);
}
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 55959e4d1cb7..f484747f255e 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -669,11 +669,13 @@ printk("NONONONOO!!!!\n");
u32 *put;
int i;
- dsc = (u32 *) kmalloc(uPD98401_TXPD_SIZE*2+
- uPD98401_TXBD_SIZE*ATM_SKB(skb)->iovcnt,GFP_ATOMIC);
+ dsc = kmalloc(uPD98401_TXPD_SIZE * 2 +
+ uPD98401_TXBD_SIZE * ATM_SKB(skb)->iovcnt, GFP_ATOMIC);
if (!dsc) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb_irq(skb);
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_irq(skb);
return -EAGAIN;
}
/* @@@ should check alignment */
@@ -683,7 +685,7 @@ printk("NONONONOO!!!!\n");
(ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ?
uPD98401_CLPM_1 : uPD98401_CLPM_0));
dsc[1] = 0;
- dsc[2] = ATM_SKB(skb)->iovcnt*uPD98401_TXBD_SIZE;
+ dsc[2] = ATM_SKB(skb)->iovcnt * uPD98401_TXBD_SIZE;
dsc[3] = virt_to_bus(put);
for (i = 0; i < ATM_SKB(skb)->iovcnt; i++) {
*put++ = ((struct iovec *) skb->data)[i].iov_len;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index fd8059920dbf..6b355bd7816d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -161,8 +161,8 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
return count;
}
-/**
- * device_subsys - structure to be registered with kobject core.
+/*
+ * devices_subsys - structure to be registered with kobject core.
*/
decl_subsys(devices, &ktype_device, &device_uevent_ops);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 281d26784d25..07a7f97e1de9 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -83,6 +83,31 @@ static inline void register_cpu_control(struct cpu *cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
+#ifdef CONFIG_KEXEC
+#include <linux/kexec.h>
+
+static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+ ssize_t rc;
+ unsigned long long addr;
+ int cpunum;
+
+ cpunum = cpu->sysdev.id;
+
+ /*
+ * Might be reading other cpu's data based on which cpu read thread
+ * has been scheduled. But cpu data (memory) is allocated once during
+ * boot up and this data does not change there after. Hence this
+ * operation should be safe. No locking required.
+ */
+ addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+ rc = sprintf(buf, "%Lx\n", addr);
+ return rc;
+}
+static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+#endif
+
/*
* register_cpu - Setup a driverfs device for a CPU.
* @cpu - Callers can set the cpu->no_control field to 1, to indicate not to
@@ -108,6 +133,11 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
register_cpu_control(cpu);
if (!error)
cpu_sys_devices[num] = &cpu->sysdev;
+
+#ifdef CONFIG_KEXEC
+ if (!error)
+ error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
+#endif
return error;
}
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 2b905016664d..730a9ce0a14a 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -78,7 +78,13 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
pr_debug("%s: Matched Device %s with Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
dev->driver = drv;
- if (drv->probe) {
+ if (dev->bus->probe) {
+ ret = dev->bus->probe(dev);
+ if (ret) {
+ dev->driver = NULL;
+ goto ProbeFailed;
+ }
+ } else if (drv->probe) {
ret = drv->probe(dev);
if (ret) {
dev->driver = NULL;
@@ -203,7 +209,9 @@ static void __device_release_driver(struct device * dev)
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
- if (drv->remove)
+ if (dev->bus->remove)
+ dev->bus->remove(dev);
+ else if (drv->remove)
drv->remove(dev);
dev->driver = NULL;
put_driver(drv);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 161f3a390d90..b400314e1c62 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -171,6 +171,11 @@ static void klist_devices_put(struct klist_node *n)
*/
int driver_register(struct device_driver * drv)
{
+ if ((drv->bus->probe && drv->probe) ||
+ (drv->bus->remove && drv->remove) ||
+ (drv->bus->shutdown && drv->shutdown)) {
+ printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
+ }
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_class.c b/drivers/base/firmware_class.c
index 5b3d5e9ddcb6..e97e911ebf7a 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -7,6 +7,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -47,7 +48,7 @@ struct firmware_priv {
struct timer_list timeout;
};
-static inline void
+static void
fw_load_abort(struct firmware_priv *fw_priv)
{
set_bit(FW_STATUS_ABORT, &fw_priv->status);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 58801d718cc2..d1a05224627e 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -13,8 +13,8 @@
#include <linux/sysdev.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/sched.h> /* capable() */
#include <linux/topology.h>
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/memory.h>
#include <linux/kobject.h>
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 0f81731bdfa8..461554a02517 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -327,7 +327,7 @@ EXPORT_SYMBOL_GPL(platform_device_register);
* @pdev: platform device we're unregistering
*
* Unregistration is done in 2 steps. Fisrt we release all resources
- * and remove it from the sybsystem, then we drop reference count by
+ * and remove it from the subsystem, then we drop reference count by
* calling platform_device_put().
*/
void platform_device_unregister(struct platform_device * pdev)
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index f50a08be424b..c2475f3134ea 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -35,12 +35,15 @@ extern int sysdev_shutdown(void);
*/
void device_shutdown(void)
{
- struct device * dev;
+ struct device * dev, *devn;
down_write(&devices_subsys.rwsem);
- list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
+ list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
kobj.entry) {
- if (dev->driver && dev->driver->shutdown) {
+ if (dev->bus && dev->bus->shutdown) {
+ dev_dbg(dev, "shutdown\n");
+ dev->bus->shutdown(dev);
+ } else if (dev->driver && dev->driver->shutdown) {
dev_dbg(dev, "shutdown\n");
dev->driver->shutdown(dev);
}
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 21097a39a057..6ede1f352c29 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
return 0;
}
-static int DAC960_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
DAC960_Controller_T *p = disk->queue->queuedata;
int drive_nr = (long)disk->private_data;
- struct hd_geometry g;
- struct hd_geometry __user *loc = (struct hd_geometry __user *)arg;
-
- if (cmd != HDIO_GETGEO || !loc)
- return -EINVAL;
if (p->FirmwareType == DAC960_V1_Controller) {
- g.heads = p->V1.GeometryTranslationHeads;
- g.sectors = p->V1.GeometryTranslationSectors;
- g.cylinders = p->V1.LogicalDriveInformation[drive_nr].
- LogicalDriveSize / (g.heads * g.sectors);
+ geo->heads = p->V1.GeometryTranslationHeads;
+ geo->sectors = p->V1.GeometryTranslationSectors;
+ geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
+ LogicalDriveSize / (geo->heads * geo->sectors);
} else {
DAC960_V2_LogicalDeviceInfo_T *i =
p->V2.LogicalDeviceInformation[drive_nr];
switch (i->DriveGeometry) {
case DAC960_V2_Geometry_128_32:
- g.heads = 128;
- g.sectors = 32;
+ geo->heads = 128;
+ geo->sectors = 32;
break;
case DAC960_V2_Geometry_255_63:
- g.heads = 255;
- g.sectors = 63;
+ geo->heads = 255;
+ geo->sectors = 63;
break;
default:
DAC960_Error("Illegal Logical Device Geometry %d\n",
@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
- g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors);
+ geo->cylinders = i->ConfigurableDeviceSize /
+ (geo->heads * geo->sectors);
}
- g.start = get_start_sect(inode->i_bdev);
-
- return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ return 0;
}
static int DAC960_media_changed(struct gendisk *disk)
@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
static struct block_device_operations DAC960_BlockDeviceOperations = {
.owner = THIS_MODULE,
.open = DAC960_open,
- .ioctl = DAC960_ioctl,
+ .getgeo = DAC960_getgeo,
.media_changed = DAC960_media_changed,
.revalidate_disk = DAC960_revalidate_disk,
};
@@ -3767,7 +3760,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
if (SenseKey == DAC960_SenseKey_VendorSpecific &&
AdditionalSenseCode == 0x80 &&
AdditionalSenseCodeQualifier <
- sizeof(DAC960_EventMessages) / sizeof(char *))
+ ARRAY_SIZE(DAC960_EventMessages))
DAC960_Critical("Physical Device %d:%d %s\n", Controller,
EventLogEntry->Channel,
EventLogEntry->TargetID,
@@ -7186,7 +7179,7 @@ static int DAC960_init_module(void)
{
int ret;
- ret = pci_module_init(&DAC960_pci_driver);
+ ret = pci_register_driver(&DAC960_pci_driver);
#ifdef DAC960_GAM_MINOR
if (!ret)
DAC960_gam_init();
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 5d2d649f7e8d..196c0ec9cd54 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void )
*
***********************************************************************/
+static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct acsi_info_struct *aip = bdev->bd_disk->private_data;
+
+ /*
+ * Just fake some geometry here, it's nonsense anyway
+ * To make it easy, use Adaptec's usual 64/32 mapping
+ */
+ geo->heads = 64;
+ geo->sectors = 32;
+ geo->cylinders = aip->size >> 11;
+ return 0;
+}
static int acsi_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
struct gendisk *disk = inode->i_bdev->bd_disk;
struct acsi_info_struct *aip = disk->private_data;
switch (cmd) {
- case HDIO_GETGEO:
- /* HDIO_GETGEO is supported more for getting the partition's
- * start sector... */
- { struct hd_geometry *geo = (struct hd_geometry *)arg;
- /* just fake some geometry here, it's nonsense anyway; to make it
- * easy, use Adaptec's usual 64/32 mapping */
- put_user( 64, &geo->heads );
- put_user( 32, &geo->sectors );
- put_user( aip->size >> 11, &geo->cylinders );
- put_user(get_start_sect(inode->i_bdev), &geo->start);
- return 0;
- }
case SCSI_IOCTL_GET_IDLUN:
/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
put_user( aip->target | (aip->lun << 8),
@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = {
.open = acsi_open,
.release = acsi_release,
.ioctl = acsi_ioctl,
+ .getgeo = acsi_getgeo,
.media_changed = acsi_media_change,
.revalidate_disk= acsi_revalidate,
};
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 0acbfff8ad28..b6e290956214 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -131,7 +131,7 @@ static struct fd_drive_type drive_types[] = {
{ FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2},
{ FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
-static int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]);
+static int num_dr_types = ARRAY_SIZE(drive_types);
static int amiga_read(int), dos_read(int);
static void amiga_write(int), dos_write(int);
@@ -194,6 +194,8 @@ static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
*/
#define MAX_ERRORS 12
+#define custom amiga_custom
+
/* Prevent "aliased" accesses. */
static int fd_ref[4] = { 0,0,0,0 };
static int fd_device[4] = { 0, 0, 0, 0 };
@@ -1424,25 +1426,24 @@ static void do_fd_request(request_queue_t * q)
redo_fd_request();
}
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ int drive = MINOR(bdev->bd_dev) & 3;
+
+ geo->heads = unit[drive].type->heads;
+ geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
+ geo->cylinders = unit[drive].type->tracks;
+ return 0;
+}
+
static int fd_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param)
{
int drive = iminor(inode) & 3;
static struct floppy_struct getprm;
+ void __user *argp = (void __user *)param;
switch(cmd){
- case HDIO_GETGEO:
- {
- struct hd_geometry loc;
- loc.heads = unit[drive].type->heads;
- loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
- loc.cylinders = unit[drive].type->tracks;
- loc.start = 0;
- if (copy_to_user((void *)param, (void *)&loc,
- sizeof(struct hd_geometry)))
- return -EFAULT;
- break;
- }
case FDFMTBEG:
get_fdc(drive);
if (fd_ref[drive] > 1) {
@@ -1486,9 +1487,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
getprm.head=unit[drive].type->heads;
getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult;
getprm.size=unit[drive].blocks;
- if (copy_to_user((void *)param,
- (void *)&getprm,
- sizeof(struct floppy_struct)))
+ if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct)))
return -EFAULT;
break;
case FDSETPRM:
@@ -1500,8 +1499,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
break;
#ifdef RAW_IOCTL
case IOCTL_RAW_TRACK:
- if (copy_to_user((void *)param, raw_buf,
- unit[drive].type->read_size))
+ if (copy_to_user(argp, raw_buf, unit[drive].type->read_size))
return -EFAULT;
else
return unit[drive].type->read_size;
@@ -1652,15 +1650,10 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
.media_changed = amiga_floppy_change,
};
-void __init amiga_floppy_setup (char *str, int *ints)
-{
- printk (KERN_INFO "amiflop: Setting default df0 to %x\n", ints[1]);
- fd_def_df0 = ints[1];
-}
-
static int __init fd_probe_drives(void)
{
int drive,drives,nomem;
@@ -1846,4 +1839,18 @@ void cleanup_module(void)
unregister_blkdev(FLOPPY_MAJOR, "fd");
}
#endif
+
+#else
+static int __init amiga_floppy_setup (char *str)
+{
+ int n;
+ if (!MACH_IS_AMIGA)
+ return 0;
+ if (!get_option(&str, &n))
+ return 0;
+ printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n);
+ fd_def_df0 = n;
+}
+
+__setup("floppy=", amiga_floppy_setup);
#endif
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 0e97fcb9f3a1..c05ee8bffd97 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
return 0;
}
-/* This ioctl implementation expects userland to have the device node
- * permissions set so that only priviledged users can open an aoe
- * block device directly.
- */
static int
-aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg)
+aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct aoedev *d;
-
- if (!arg)
- return -EINVAL;
+ struct aoedev *d = bdev->bd_disk->private_data;
- d = inode->i_bdev->bd_disk->private_data;
if ((d->flags & DEVFL_UP) == 0) {
printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
return -ENODEV;
}
- if (cmd == HDIO_GETGEO) {
- d->geo.start = get_start_sect(inode->i_bdev);
- if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo))
- return 0;
- return -EFAULT;
- }
- printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
- return -EINVAL;
+ geo->cylinders = d->geo.cylinders;
+ geo->heads = d->geo.heads;
+ geo->sectors = d->geo.sectors;
+ return 0;
}
static struct block_device_operations aoe_bdops = {
.open = aoeblk_open,
.release = aoeblk_release,
- .ioctl = aoeblk_ioctl,
+ .getgeo = aoeblk_getgeo,
.owner = THIS_MODULE,
};
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 22bda05fc693..f8ce235ccfc3 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -181,7 +181,7 @@ static struct {
{ 6, TYPE_HD }, /* 31: H1640 <- was H1600 == h1600 for PC */
};
-#define NUM_DISK_MINORS (sizeof(minor2disktype)/sizeof(*minor2disktype))
+#define NUM_DISK_MINORS ARRAY_SIZE(minor2disktype)
/*
* Maximum disk size (in kilobytes). This default is used whenever the
@@ -1361,7 +1361,7 @@ static int floppy_revalidate(struct gendisk *disk)
formats, for 'permanent user-defined' parameter:
restore default_params[] here if flagged valid! */
if (default_params[drive].blocks == 0)
- UDT = 0;
+ UDT = NULL;
else
UDT = &default_params[drive];
}
@@ -1495,6 +1495,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
struct floppy_struct getprm;
int settype;
struct floppy_struct setprm;
+ void __user *argp = (void __user *)param;
switch (cmd) {
case FDGETPRM:
@@ -1521,7 +1522,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
getprm.head = 2;
getprm.track = dtp->blocks/dtp->spt/2;
getprm.stretch = dtp->stretch;
- if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
+ if (copy_to_user(argp, &getprm, sizeof(getprm)))
return -EFAULT;
return 0;
}
@@ -1540,7 +1541,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
/* get the parameters from user space */
if (floppy->ref != 1 && floppy->ref != -1)
return -EBUSY;
- if (copy_from_user(&setprm, (void *) param, sizeof(setprm)))
+ if (copy_from_user(&setprm, argp, sizeof(setprm)))
return -EFAULT;
/*
* first of all: check for floppy change and revalidate,
@@ -1647,7 +1648,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
case FDFMTTRK:
if (floppy->ref != 1 && floppy->ref != -1)
return -EBUSY;
- if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
+ if (copy_from_user(&fmt_desc, argp, sizeof(fmt_desc)))
return -EFAULT;
return do_format(drive, type, &fmt_desc);
case FDCLRPRM:
@@ -1950,14 +1951,20 @@ Enomem:
return -ENOMEM;
}
-
-void __init atari_floppy_setup( char *str, int *ints )
+#ifndef MODULE
+static int __init atari_floppy_setup(char *str)
{
+ int ints[3 + FD_MAX_UNITS];
int i;
+
+ if (!MACH_IS_ATARI)
+ return 0;
+
+ str = get_options(str, 3 + FD_MAX_UNITS, ints);
if (ints[0] < 1) {
printk(KERN_ERR "ataflop_setup: no arguments!\n" );
- return;
+ return 0;
}
else if (ints[0] > 2+FD_MAX_UNITS) {
printk(KERN_ERR "ataflop_setup: too many arguments\n" );
@@ -1977,9 +1984,13 @@ void __init atari_floppy_setup( char *str, int *ints )
else
UserSteprate[i-3] = ints[i];
}
+ return 1;
}
-static void atari_floppy_exit(void)
+__setup("floppy=", atari_floppy_setup);
+#endif
+
+static void __exit atari_floppy_exit(void)
{
int i;
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index d2815b7a9150..12d7b9bdfa93 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1,6 +1,6 @@
/*
* Disk Array driver for HP SA 5xxx and 6xxx Controllers
- * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,12 +47,12 @@
#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.8)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.10)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,10)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.10");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
" SA6i P600 P800 P400 P400i E200 E200i");
MODULE_LICENSE("GPL");
@@ -103,7 +103,7 @@ static const struct pci_device_id cciss_pci_device_id[] = {
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
-#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
+#define NR_PRODUCTS ARRAY_SIZE(products)
/* board_id = Subsystem Device ID & Vendor ID
* product = Marketing Name for the board
@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep);
static int cciss_release(struct inode *inode, struct file *filep);
static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg);
+static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
@@ -166,7 +167,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
-
+static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32);
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,
@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = {
.open = cciss_open,
.release = cciss_release,
.ioctl = cciss_ioctl,
+ .getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = cciss_compat_ioctl,
#endif
@@ -282,7 +284,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
h->product_name,
(unsigned long)h->board_id,
h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3],
- (unsigned int)h->intr,
+ (unsigned int)h->intr[SIMPLE_MODE_INT],
h->num_luns,
h->Qdepth, h->commands_outstanding,
h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
return err;
}
#endif
+
+static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ drive_info_struct *drv = get_drv(bdev->bd_disk);
+
+ if (!drv->cylinders)
+ return -ENXIO;
+
+ geo->heads = drv->heads;
+ geo->sectors = drv->sectors;
+ geo->cylinders = drv->cylinders;
+ return 0;
+}
+
/*
* ioctl
*/
@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
#endif /* CCISS_DEBUG */
switch(cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry driver_geo;
- if (drv->cylinders) {
- driver_geo.heads = drv->heads;
- driver_geo.sectors = drv->sectors;
- driver_geo.cylinders = drv->cylinders;
- } else
- return -ENXIO;
- driver_geo.start= get_start_sect(inode->i_bdev);
- if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry)))
- return -EFAULT;
- return(0);
- }
-
case CCISS_GETPCIINFO:
{
cciss_pci_info_struct pciinfo;
@@ -2177,16 +2178,48 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
start_io(h);
}
+
+static void cciss_softirq_done(struct request *rq)
+{
+ CommandList_struct *cmd = rq->completion_data;
+ ctlr_info_t *h = hba[cmd->ctlr];
+ u64bit temp64;
+ int i, ddir;
+
+ if (cmd->Request.Type.Direction == XFER_READ)
+ ddir = PCI_DMA_FROMDEVICE;
+ else
+ ddir = PCI_DMA_TODEVICE;
+
+ /* command did not need to be retried */
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->Header.SGList; i++) {
+ temp64.val32.lower = cmd->SG[i].Addr.lower;
+ temp64.val32.upper = cmd->SG[i].Addr.upper;
+ pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+ }
+
+ complete_buffers(rq->bio, rq->errors);
+
+#ifdef CCISS_DEBUG
+ printk("Done with %p\n", rq);
+#endif /* CCISS_DEBUG */
+
+ spin_lock_irq(&h->lock);
+ end_that_request_last(rq, rq->errors);
+ cmd_free(h, cmd,1);
+ spin_unlock_irq(&h->lock);
+}
+
/* checks the status of the job and calls complete buffers to mark all
- * buffers for the completed job.
+ * buffers for the completed job. Note that this function does not need
+ * to hold the hba/queue lock.
*/
static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
int timeout)
{
int status = 1;
- int i;
int retry_cmd = 0;
- u64bit temp64;
if (timeout)
status = 0;
@@ -2294,24 +2327,10 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
resend_cciss_cmd(h,cmd);
return;
}
- /* command did not need to be retried */
- /* unmap the DMA mapping for all the scatter gather elements */
- for(i=0; i<cmd->Header.SGList; i++) {
- temp64.val32.lower = cmd->SG[i].Addr.lower;
- temp64.val32.upper = cmd->SG[i].Addr.upper;
- pci_unmap_page(hba[cmd->ctlr]->pdev,
- temp64.val, cmd->SG[i].Len,
- (cmd->Request.Type.Direction == XFER_READ) ?
- PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
- }
- complete_buffers(cmd->rq->bio, status);
-#ifdef CCISS_DEBUG
- printk("Done with %p\n", cmd->rq);
-#endif /* CCISS_DEBUG */
-
- end_that_request_last(cmd->rq, status ? 1 : -EIO);
- cmd_free(h,cmd,1);
+ cmd->rq->completion_data = cmd;
+ cmd->rq->errors = status;
+ blk_complete_request(cmd->rq);
}
/*
@@ -2661,6 +2680,60 @@ static int find_PCI_BAR_index(struct pci_dev *pdev,
return -1;
}
+/* If MSI/MSI-X is supported by the kernel we will try to enable it on
+ * controllers that are capable. If not, we use IO-APIC mode.
+ */
+
+static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, __u32 board_id)
+{
+#ifdef CONFIG_PCI_MSI
+ int err;
+ struct msix_entry cciss_msix_entries[4] = {{0,0}, {0,1},
+ {0,2}, {0,3}};
+
+ /* Some boards advertise MSI but don't really support it */
+ if ((board_id == 0x40700E11) ||
+ (board_id == 0x40800E11) ||
+ (board_id == 0x40820E11) ||
+ (board_id == 0x40830E11))
+ goto default_int_mode;
+
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+ err = pci_enable_msix(pdev, cciss_msix_entries, 4);
+ if (!err) {
+ c->intr[0] = cciss_msix_entries[0].vector;
+ c->intr[1] = cciss_msix_entries[1].vector;
+ c->intr[2] = cciss_msix_entries[2].vector;
+ c->intr[3] = cciss_msix_entries[3].vector;
+ c->msix_vector = 1;
+ return;
+ }
+ if (err > 0) {
+ printk(KERN_WARNING "cciss: only %d MSI-X vectors "
+ "available\n", err);
+ } else {
+ printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
+ err);
+ }
+ }
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
+ if (!pci_enable_msi(pdev)) {
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ c->msi_vector = 1;
+ return;
+ } else {
+ printk(KERN_WARNING "cciss: MSI init failed\n");
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ return;
+ }
+ }
+#endif /* CONFIG_PCI_MSI */
+ /* if we get here we're going to use the default interrupt mode */
+default_int_mode:
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ return;
+}
+
static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
{
ushort subsystem_vendor_id, subsystem_device_id, command;
@@ -2721,7 +2794,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
printk("board_id = %x\n", board_id);
#endif /* CCISS_DEBUG */
- c->intr = pdev->irq;
+/* If the kernel supports MSI/MSI-X we will try to enable that functionality,
+ * else we use the IO-APIC interrupt assigned to us by system ROM.
+ */
+ cciss_interrupt_mode(c, pdev, board_id);
/*
* Memory base addr is first addr , the second points to the config
@@ -2775,7 +2851,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
c->board_id = board_id;
#ifdef CCISS_DEBUG
- print_cfg_table(c->cfgtable);
+ print_cfg_table(c->cfgtable);
#endif /* CCISS_DEBUG */
for(i=0; i<NR_PRODUCTS; i++) {
@@ -3060,7 +3136,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
* 8 controller support.
*/
if (i < MAX_CTLR_ORIG)
- hba[i]->major = MAJOR_NR + i;
+ hba[i]->major = COMPAQ_CISS_MAJOR + i;
rc = register_blkdev(hba[i]->major, hba[i]->devname);
if(rc == -EBUSY || rc == -EINVAL) {
printk(KERN_ERR
@@ -3075,11 +3151,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* make sure the board interrupts are off */
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
- if( request_irq(hba[i]->intr, do_cciss_intr,
+ if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr,
SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
hba[i]->devname, hba[i])) {
printk(KERN_ERR "cciss: Unable to get irq %d for %s\n",
- hba[i]->intr, hba[i]->devname);
+ hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname);
goto clean2;
}
hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL);
@@ -3141,15 +3217,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
drv->queue = q;
q->backing_dev_info.ra_pages = READ_AHEAD;
- blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+ blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
- /* This is a hardware imposed limit. */
- blk_queue_max_hw_segments(q, MAXSGENTRIES);
+ /* This is a hardware imposed limit. */
+ blk_queue_max_hw_segments(q, MAXSGENTRIES);
- /* This is a limit in the driver and could be eliminated. */
- blk_queue_max_phys_segments(q, MAXSGENTRIES);
+ /* This is a limit in the driver and could be eliminated. */
+ blk_queue_max_phys_segments(q, MAXSGENTRIES);
- blk_queue_max_sectors(q, 512);
+ blk_queue_max_sectors(q, 512);
+
+ blk_queue_softirq_done(q, cciss_softirq_done);
q->queuedata = hba[i];
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
@@ -3185,7 +3263,7 @@ clean4:
NR_CMDS * sizeof( ErrorInfo_struct),
hba[i]->errinfo_pool,
hba[i]->errinfo_pool_dhandle);
- free_irq(hba[i]->intr, hba[i]);
+ free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
clean2:
unregister_blkdev(hba[i]->major, hba[i]->devname);
clean1:
@@ -3226,7 +3304,15 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
printk(KERN_WARNING "Error Flushing cache on controller %d\n",
i);
}
- free_irq(hba[i]->intr, hba[i]);
+ free_irq(hba[i]->intr[2], hba[i]);
+
+#ifdef CONFIG_PCI_MSI
+ if (hba[i]->msix_vector)
+ pci_disable_msix(hba[i]->pdev);
+ else if (hba[i]->msi_vector)
+ pci_disable_msi(hba[i]->pdev);
+#endif /* CONFIG_PCI_MSI */
+
pci_set_drvdata(pdev, NULL);
iounmap(hba[i]->vaddr);
cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
@@ -3274,7 +3360,7 @@ static int __init cciss_init(void)
printk(KERN_INFO DRIVER_NAME "\n");
/* Register for our PCI devices */
- return pci_module_init(&cciss_pci_driver);
+ return pci_register_driver(&cciss_pci_driver);
}
static void __exit cciss_cleanup(void)
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 3b0858c83897..b24fc0553ccf 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -13,8 +13,6 @@
#define IO_OK 0
#define IO_ERROR 1
-#define MAJOR_NR COMPAQ_CISS_MAJOR
-
struct ctlr_info;
typedef struct ctlr_info ctlr_info_t;
@@ -65,7 +63,6 @@ struct ctlr_info
unsigned long io_mem_addr;
unsigned long io_mem_length;
CfgTable_struct __iomem *cfgtable;
- unsigned int intr;
int interrupts_enabled;
int major;
int max_commands;
@@ -74,6 +71,13 @@ struct ctlr_info
int num_luns;
int highest_lun;
int usage_count; /* number of opens all all minor devices */
+# define DOORBELL_INT 0
+# define PERF_MODE_INT 1
+# define SIMPLE_MODE_INT 2
+# define MEMQ_MODE_INT 3
+ unsigned int intr[4];
+ unsigned int msix_vector;
+ unsigned int msi_vector;
// information about each logical volume
drive_info_struct drv[CISS_MAX_LUN];
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 2942d32280a5..9e35de05d5c5 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -714,7 +714,7 @@ cciss_scsi_detect(int ctlr)
((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh;
sh->hostdata[0] = (unsigned long) hba[ctlr];
- sh->irq = hba[ctlr]->intr;
+ sh->irq = hba[ctlr]->intr[SIMPLE_MODE_INT];
sh->unique_id = sh->irq;
error = scsi_add_host(sh, &hba[ctlr]->pdev->dev);
if (error)
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 9bddb6874873..862b9abac0ae 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -72,11 +72,11 @@ static ctlr_info_t *hba[MAX_CTLR];
static int eisa[8];
-#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
+#define NR_PRODUCTS ARRAY_SIZE(products)
/* board_id = Subsystem Device ID & Vendor ID
* product = Marketing Name for the board
- * access = Address of the struct of function pointers
+ * access = Address of the struct of function pointers
*/
static struct board_type products[] = {
{ 0x0040110E, "IDA", &smart1_access },
@@ -160,6 +160,7 @@ static int sendcmd(
static int ida_open(struct inode *inode, struct file *filep);
static int ida_release(struct inode *inode, struct file *filep);
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
+static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
static void do_ida_request(request_queue_t *q);
@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = {
.open = ida_open,
.release = ida_release,
.ioctl = ida_ioctl,
+ .getgeo = ida_getgeo,
.revalidate_disk= ida_revalidate,
};
@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata)
h->misc_tflags = 0;
}
+static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ drv_info_t *drv = get_drv(bdev->bd_disk);
+
+ if (drv->cylinders) {
+ geo->heads = drv->heads;
+ geo->sectors = drv->sectors;
+ geo->cylinders = drv->cylinders;
+ } else {
+ geo->heads = 0xff;
+ geo->sectors = 0x3f;
+ geo->cylinders = drv->nr_blks / (0xff*0x3f);
+ }
+
+ return 0;
+}
+
/*
* ida_ioctl does some miscellaneous stuff like reporting drive geometry,
* setting readahead and submitting commands from userspace to the controller.
@@ -1133,27 +1152,10 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
int error;
- int diskinfo[4];
- struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
ida_ioctl_t *my_io;
switch(cmd) {
- case HDIO_GETGEO:
- if (drv->cylinders) {
- diskinfo[0] = drv->heads;
- diskinfo[1] = drv->sectors;
- diskinfo[2] = drv->cylinders;
- } else {
- diskinfo[0] = 0xff;
- diskinfo[1] = 0x3f;
- diskinfo[2] = drv->nr_blks / (0xff*0x3f);
- }
- put_user(diskinfo[0], &geo->heads);
- put_user(diskinfo[1], &geo->sectors);
- put_user(diskinfo[2], &geo->cylinders);
- put_user(get_start_sect(inode->i_bdev), &geo->start);
- return 0;
case IDAGETDRVINFO:
if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
return -EFAULT;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index a5b857c5c4b8..d23b54332d7e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -242,7 +242,6 @@ static int allowed_drive_mask = 0x33;
static int irqdma_allocated;
-#define LOCAL_END_REQUEST
#define DEVICE_NAME "floppy"
#include <linux/blkdev.h>
@@ -479,7 +478,6 @@ static struct floppy_struct floppy_type[32] = {
{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
};
-#define NUMBER(x) (sizeof(x) / sizeof(*(x)))
#define SECTSIZE (_FD_SECTSIZE(*floppy))
/* Auto-detection: Disk type used until the next media change occurs. */
@@ -3445,6 +3443,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
return 0;
}
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ int drive = (long)bdev->bd_disk->private_data;
+ int type = ITYPE(drive_state[drive].fd_device);
+ struct floppy_struct *g;
+ int ret;
+
+ ret = get_floppy_geometry(drive, type, &g);
+ if (ret)
+ return ret;
+
+ geo->heads = g->head;
+ geo->sectors = g->sect;
+ geo->cylinders = g->track;
+ return 0;
+}
+
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param)
{
@@ -3474,23 +3489,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
cmd = FDEJECT;
}
- /* generic block device ioctls */
- switch (cmd) {
- /* the following have been inspired by the corresponding
- * code for other block devices. */
- struct floppy_struct *g;
- case HDIO_GETGEO:
- {
- struct hd_geometry loc;
- ECALL(get_floppy_geometry(drive, type, &g));
- loc.heads = g->head;
- loc.sectors = g->sect;
- loc.cylinders = g->track;
- loc.start = 0;
- return _COPYOUT(loc);
- }
- }
-
/* convert the old style command into a new style command */
if ((cmd & 0xff00) == 0x0200) {
ECALL(normalize_ioctl(&cmd, &size));
@@ -3645,7 +3643,7 @@ static void __init config_types(void)
const char *name = NULL;
static char temparea[32];
- if (type < NUMBER(default_drive_params)) {
+ if (type < ARRAY_SIZE(default_drive_params)) {
params = &default_drive_params[type].params;
if (type) {
name = default_drive_params[type].name;
@@ -3938,6 +3936,7 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
.media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate,
};
@@ -3960,7 +3959,7 @@ static void __init register_devfs_entries(int drive)
{
int base_minor = (drive < 4) ? drive : (124 + drive);
- if (UDP->cmos < NUMBER(default_drive_params)) {
+ if (UDP->cmos < ARRAY_SIZE(default_drive_params)) {
int i = 0;
do {
int minor = base_minor + (table_sup[UDP->cmos][i] << 2);
@@ -4218,7 +4217,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
- if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
+ if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
return NULL;
*part = 0;
return get_disk(disks[drive]);
@@ -4570,7 +4569,7 @@ static void unregister_devfs_entries(int drive)
{
int i;
- if (UDP->cmos < NUMBER(default_drive_params)) {
+ if (UDP->cmos < ARRAY_SIZE(default_drive_params)) {
i = 0;
do {
devfs_remove("floppy/%d%s", drive,
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index a452b13620a2..5f6d1a5cce11 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -215,7 +215,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
unsigned offset, bv_offs;
int len, ret;
- down(&mapping->host->i_sem);
+ mutex_lock(&mapping->host->i_mutex);
index = pos >> PAGE_CACHE_SHIFT;
offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
bv_offs = bvec->bv_offset;
@@ -278,7 +278,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
}
ret = 0;
out:
- up(&mapping->host->i_sem);
+ mutex_unlock(&mapping->host->i_mutex);
return ret;
unlock:
unlock_page(page);
@@ -294,7 +294,7 @@ fail:
* This helper just factors out common code between do_lo_send_direct_write()
* and do_lo_send_write().
*/
-static inline int __do_lo_send_write(struct file *file,
+static int __do_lo_send_write(struct file *file,
u8 __user *buf, const int len, loff_t pos)
{
ssize_t bw;
@@ -527,12 +527,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
lo->lo_pending++;
loop_add_bio(lo, old_bio);
spin_unlock_irq(&lo->lo_lock);
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
return 0;
out:
if (lo->lo_pending == 0)
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
@@ -593,23 +593,20 @@ static int loop_thread(void *data)
lo->lo_pending = 1;
/*
- * up sem, we are running
+ * complete it, we are running
*/
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
for (;;) {
int pending;
- /*
- * interruptible just to not contribute to load avg
- */
- if (down_interruptible(&lo->lo_bh_mutex))
+ if (wait_for_completion_interruptible(&lo->lo_bh_done))
continue;
spin_lock_irq(&lo->lo_lock);
/*
- * could be upped because of tear-down, not pending work
+ * could be completed because of tear-down, not pending work
*/
if (unlikely(!lo->lo_pending)) {
spin_unlock_irq(&lo->lo_lock);
@@ -632,7 +629,7 @@ static int loop_thread(void *data)
break;
}
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
return 0;
}
@@ -843,7 +840,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
set_blocksize(bdev, lo_blocksize);
kernel_thread(loop_thread, lo, CLONE_KERNEL);
- down(&lo->lo_sem);
+ wait_for_completion(&lo->lo_done);
return 0;
out_putf:
@@ -909,10 +906,10 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->lo_state = Lo_rundown;
lo->lo_pending--;
if (!lo->lo_pending)
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- down(&lo->lo_sem);
+ wait_for_completion(&lo->lo_done);
lo->lo_backing_file = NULL;
@@ -1289,8 +1286,8 @@ static int __init loop_init(void)
if (!lo->lo_queue)
goto out_mem4;
init_MUTEX(&lo->lo_ctl_mutex);
- init_MUTEX_LOCKED(&lo->lo_sem);
- init_MUTEX_LOCKED(&lo->lo_bh_mutex);
+ init_completion(&lo->lo_done);
+ init_completion(&lo->lo_bh_done);
lo->lo_number = i;
spin_lock_init(&lo->lo_lock);
disk->major = LOOP_MAJOR;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 33d6f237b2ed..6997d8e6bfb5 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -174,7 +174,6 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
- msg.msg_namelen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
if (send)
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index fa49d62626ba..62d2464c12f2 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file)
return 0;
}
+static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct pd_unit *disk = bdev->bd_disk->private_data;
+
+ if (disk->alt_geom) {
+ geo->heads = PD_LOG_HEADS;
+ geo->sectors = PD_LOG_SECTS;
+ geo->cylinders = disk->capacity / (geo->heads * geo->sectors);
+ } else {
+ geo->heads = disk->heads;
+ geo->sectors = disk->sectors;
+ geo->cylinders = disk->cylinders;
+ }
+
+ return 0;
+}
+
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
- struct hd_geometry g;
switch (cmd) {
case CDROMEJECT:
if (disk->access == 1)
pd_special_command(disk, pd_eject);
return 0;
- case HDIO_GETGEO:
- if (disk->alt_geom) {
- g.heads = PD_LOG_HEADS;
- g.sectors = PD_LOG_SECTS;
- g.cylinders = disk->capacity / (g.heads * g.sectors);
- } else {
- g.heads = disk->heads;
- g.sectors = disk->sectors;
- g.cylinders = disk->cylinders;
- }
- g.start = get_start_sect(inode->i_bdev);
- if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
- return -EFAULT;
- return 0;
default:
return -EINVAL;
}
@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = {
.open = pd_open,
.release = pd_release,
.ioctl = pd_ioctl,
+ .getgeo = pd_getgeo,
.media_changed = pd_check_media,
.revalidate_disk= pd_revalidate
};
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index e9746af29b9f..852b564e903a 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file);
static void do_pf_request(request_queue_t * q);
static int pf_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
+static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int pf_release(struct inode *inode, struct file *file);
@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = {
.open = pf_open,
.release = pf_release,
.ioctl = pf_ioctl,
+ .getgeo = pf_getgeo,
.media_changed = pf_check_media,
};
@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file)
return 0;
}
-static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
- struct hd_geometry g;
- sector_t capacity;
-
- if (cmd == CDROMEJECT) {
- if (pf->access == 1) {
- pf_eject(pf);
- return 0;
- }
- return -EBUSY;
- }
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- capacity = get_capacity(pf->disk);
+ struct pf_unit *pf = bdev->bd_disk->private_data;
+ sector_t capacity = get_capacity(pf->disk);
+
if (capacity < PF_FD_MAX) {
- g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
- g.heads = PF_FD_HDS;
- g.sectors = PF_FD_SPT;
+ geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
+ geo->heads = PF_FD_HDS;
+ geo->sectors = PF_FD_SPT;
} else {
- g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
- g.heads = PF_HD_HDS;
- g.sectors = PF_HD_SPT;
+ geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
+ geo->heads = PF_HD_HDS;
+ geo->sectors = PF_HD_SPT;
}
- if (copy_to_user(geo, &g, sizeof(g)))
- return -EFAULT;
+
+ return 0;
+}
+
+static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
+
+ if (cmd != CDROMEJECT)
+ return -EINVAL;
+
+ if (pf->access != 1)
+ return -EBUSY;
+ pf_eject(pf);
return 0;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index c0233efabeba..93affeeef7bd 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -247,7 +247,7 @@ static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node)
return rb_entry(n, struct pkt_rb_node, rb_node);
}
-static inline void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node)
+static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node)
{
rb_erase(&node->rb_node, &pd->bio_queue);
mempool_free(node, pd->rb_pool);
@@ -315,7 +315,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
/*
* Add a bio to a single linked list defined by its head and tail pointers.
*/
-static inline void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
+static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
{
bio->bi_next = NULL;
if (*list_tail) {
@@ -1955,9 +1955,12 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
if ((ret = blkdev_get(pd->bdev, FMODE_READ, O_RDONLY)))
goto out;
+ if ((ret = bd_claim(pd->bdev, pd)))
+ goto out_putdev;
+
if ((ret = pkt_get_last_written(pd, &lba))) {
printk("pktcdvd: pkt_get_last_written failed\n");
- goto out_putdev;
+ goto out_unclaim;
}
set_capacity(pd->disk, lba << 2);
@@ -1967,7 +1970,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
q = bdev_get_queue(pd->bdev);
if (write) {
if ((ret = pkt_open_write(pd)))
- goto out_putdev;
+ goto out_unclaim;
/*
* Some CDRW drives can not handle writes larger than one packet,
* even if the size is a multiple of the packet size.
@@ -1982,13 +1985,15 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
}
if ((ret = pkt_set_segment_merging(pd, q)))
- goto out_putdev;
+ goto out_unclaim;
if (write)
printk("pktcdvd: %lukB available on disc\n", lba << 1);
return 0;
+out_unclaim:
+ bd_release(pd->bdev);
out_putdev:
blkdev_put(pd->bdev);
out:
@@ -2007,6 +2012,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
pkt_lock_door(pd, 0);
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
+ bd_release(pd->bdev);
blkdev_put(pd->bdev);
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 29d1518be72a..bea75f2cb211 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -43,6 +43,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/module.h>
+#include <linux/hdreg.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -81,8 +82,7 @@ static void (*current_int_handler) (u_int) = NULL;
static void ps2esdi_normal_interrupt_handler(u_int);
static void ps2esdi_initial_reset_int_handler(u_int);
static void ps2esdi_geometry_int_handler(u_int);
-static int ps2esdi_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg);
+static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
@@ -132,7 +132,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
static struct block_device_operations ps2esdi_fops =
{
.owner = THIS_MODULE,
- .ioctl = ps2esdi_ioctl,
+ .getgeo = ps2esdi_getgeo,
};
static struct gendisk *ps2esdi_gendisk[2];
@@ -1058,21 +1058,13 @@ static void dump_cmd_complete_status(u_int int_ret_code)
}
-static int ps2esdi_ioctl(struct inode *inode,
- struct file *file, u_int cmd, u_long arg)
+static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
- struct ps2esdi_geometry geom;
-
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- memset(&geom, 0, sizeof(geom));
- geom.heads = p->head;
- geom.sectors = p->sect;
- geom.cylinders = p->cyl;
- geom.start = get_start_sect(inode->i_bdev);
- if (copy_to_user((void __user *)arg, &geom, sizeof(geom)))
- return -EFAULT;
+ struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
+
+ geo->heads = p->head;
+ geo->sectors = p->sect;
+ geo->cylinders = p->cyl;
return 0;
}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index af7cb2bfd670..01f042f6f1c4 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1083,23 +1083,33 @@ static int swim3_add_device(struct device_node *swim)
{
struct device_node *mediabay;
struct floppy_state *fs = &floppy_states[floppy_count];
+ struct resource res_reg, res_dma;
- if (swim->n_addrs < 2)
- {
- printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n",
- swim->n_addrs, swim->n_intrs);
+ if (of_address_to_resource(swim, 0, &res_reg) ||
+ of_address_to_resource(swim, 1, &res_dma)) {
+ printk(KERN_ERR "swim3: Can't get addresses\n");
return -EINVAL;
}
-
- if (swim->n_intrs < 2)
- {
- printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n",
- swim->n_addrs, swim->n_intrs);
+ if (request_mem_region(res_reg.start, res_reg.end - res_reg.start + 1,
+ " (reg)") == NULL) {
+ printk(KERN_ERR "swim3: Can't request register space\n");
+ return -EINVAL;
+ }
+ if (request_mem_region(res_dma.start, res_dma.end - res_dma.start + 1,
+ " (dma)") == NULL) {
+ release_mem_region(res_reg.start,
+ res_reg.end - res_reg.start + 1);
+ printk(KERN_ERR "swim3: Can't request DMA space\n");
return -EINVAL;
}
- if (!request_OF_resource(swim, 0, NULL)) {
- printk(KERN_INFO "swim3: can't request IO resource !\n");
+ if (swim->n_intrs < 2) {
+ printk(KERN_INFO "swim3: expecting 2 intrs (n_intrs:%d)\n",
+ swim->n_intrs);
+ release_mem_region(res_reg.start,
+ res_reg.end - res_reg.start + 1);
+ release_mem_region(res_dma.start,
+ res_dma.end - res_dma.start + 1);
return -EINVAL;
}
@@ -1110,10 +1120,8 @@ static int swim3_add_device(struct device_node *swim)
memset(fs, 0, sizeof(*fs));
spin_lock_init(&fs->lock);
fs->state = idle;
- fs->swim3 = (struct swim3 __iomem *)
- ioremap(swim->addrs[0].address, 0x200);
- fs->dma = (struct dbdma_regs __iomem *)
- ioremap(swim->addrs[1].address, 0x200);
+ fs->swim3 = (struct swim3 __iomem *)ioremap(res_reg.start, 0x200);
+ fs->dma = (struct dbdma_regs __iomem *)ioremap(res_dma.start, 0x200);
fs->swim3_intr = swim->intrs[0].line;
fs->dma_intr = swim->intrs[1].line;
fs->cur_cyl = -1;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 9251f4131b53..2ae08b343b93 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -27,8 +27,8 @@
#include <linux/time.h>
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
+#include <linux/completion.h>
#include <asm/io.h>
-#include <asm/semaphore.h>
#include <asm/uaccess.h>
#if 0
@@ -303,7 +303,7 @@ struct carm_host {
struct work_struct fsm_task;
- struct semaphore probe_sem;
+ struct completion probe_comp;
};
struct carm_response {
@@ -407,8 +407,7 @@ struct carm_array_info {
static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static void carm_remove_one (struct pci_dev *pdev);
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
- unsigned int cmd, unsigned long arg);
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static struct pci_device_id carm_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = {
static struct block_device_operations carm_bd_ops = {
.owner = THIS_MODULE,
- .ioctl = carm_bdev_ioctl,
+ .getgeo = carm_bdev_getgeo,
};
static unsigned int carm_host_id;
@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc;
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
- unsigned int cmd, unsigned long arg)
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- void __user *usermem = (void __user *) arg;
- struct carm_port *port = ino->i_bdev->bd_disk->private_data;
- struct hd_geometry geom;
+ struct carm_port *port = bdev->bd_disk->private_data;
- switch (cmd) {
- case HDIO_GETGEO:
- if (!usermem)
- return -EINVAL;
-
- geom.heads = (u8) port->dev_geom_head;
- geom.sectors = (u8) port->dev_geom_sect;
- geom.cylinders = port->dev_geom_cyl;
- geom.start = get_start_sect(ino->i_bdev);
-
- if (copy_to_user(usermem, &geom, sizeof(geom)))
- return -EFAULT;
- return 0;
-
- default:
- break;
- }
-
- return -EOPNOTSUPP;
+ geo->heads = (u8) port->dev_geom_head;
+ geo->sectors = (u8) port->dev_geom_sect;
+ geo->cylinders = port->dev_geom_cyl;
+ return 0;
}
static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
@@ -1365,7 +1346,7 @@ static void carm_fsm_task (void *_data)
}
case HST_PROBE_FINISHED:
- up(&host->probe_sem);
+ complete(&host->probe_comp);
break;
case HST_ERROR:
@@ -1641,7 +1622,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
host->flags = pci_dac ? FL_DAC : 0;
spin_lock_init(&host->lock);
INIT_WORK(&host->fsm_task, carm_fsm_task, host);
- init_MUTEX_LOCKED(&host->probe_sem);
+ init_completion(&host->probe_comp);
for (i = 0; i < ARRAY_SIZE(host->req); i++)
host->req[i].tag = i;
@@ -1710,8 +1691,8 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_free_irq;
- DPRINTK("waiting for probe_sem\n");
- down(&host->probe_sem);
+ DPRINTK("waiting for probe_comp\n");
+ wait_for_completion(&host->probe_comp);
printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n",
host->name, pci_name(pdev), (int) CARM_MAX_PORTS,
@@ -1774,7 +1755,7 @@ static void carm_remove_one (struct pci_dev *pdev)
static int __init carm_init(void)
{
- return pci_module_init(&carm_driver);
+ return pci_register_driver(&carm_driver);
}
static void __exit carm_exit(void)
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 0f48301342da..a3614e6a68d0 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk)
set_capacity(disk, card->mm_size << 1);
return 0;
}
-/*
------------------------------------------------------------------------------------
--- mm_ioctl
------------------------------------------------------------------------------------
-*/
-static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
+
+static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- if (cmd == HDIO_GETGEO) {
- struct cardinfo *card = i->i_bdev->bd_disk->private_data;
- int size = card->mm_size * (1024 / MM_HARDSECT);
- struct hd_geometry geo;
- /*
- * get geometry: we have to fake one... trim the size to a
- * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
- * whatever cylinders.
- */
- geo.heads = 64;
- geo.sectors = 32;
- geo.start = get_start_sect(i->i_bdev);
- geo.cylinders = size / (geo.heads * geo.sectors);
-
- if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
- return -EFAULT;
- return 0;
- }
+ struct cardinfo *card = bdev->bd_disk->private_data;
+ int size = card->mm_size * (1024 / MM_HARDSECT);
- return -EINVAL;
+ /*
+ * get geometry: we have to fake one... trim the size to a
+ * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
+ * whatever cylinders.
+ */
+ geo->heads = 64;
+ geo->sectors = 32;
+ geo->cylinders = size / (geo->heads * geo->sectors);
+ return 0;
}
+
/*
-----------------------------------------------------------------------------------
-- mm_check_change
@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk)
*/
static struct block_device_operations mm_fops = {
.owner = THIS_MODULE,
- .ioctl = mm_ioctl,
+ .getgeo = mm_getgeo,
.revalidate_disk= mm_revalidate,
.media_changed = mm_check_change,
};
@@ -1185,7 +1174,7 @@ static int __init mm_init(void)
printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n");
- retval = pci_module_init(&mm_pci_driver);
+ retval = pci_register_driver(&mm_pci_driver);
if (retval)
return -ENOMEM;
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 063f0304a163..f63e07bd9f9c 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil)
/* External ioctl entry point.
*/
-static int viodasd_ioctl(struct inode *ino, struct file *fil,
- unsigned int cmd, unsigned long arg)
+static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- unsigned char sectors;
- unsigned char heads;
- unsigned short cylinders;
- struct hd_geometry *geo;
- struct gendisk *gendisk;
- struct viodasd_device *d;
+ struct gendisk *disk = bdev->bd_disk;
+ struct viodasd_device *d = disk->private_data;
- switch (cmd) {
- case HDIO_GETGEO:
- geo = (struct hd_geometry *)arg;
- if (geo == NULL)
- return -EINVAL;
- if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo)))
- return -EFAULT;
- gendisk = ino->i_bdev->bd_disk;
- d = gendisk->private_data;
- sectors = d->sectors;
- if (sectors == 0)
- sectors = 32;
- heads = d->tracks;
- if (heads == 0)
- heads = 64;
- cylinders = d->cylinders;
- if (cylinders == 0)
- cylinders = get_capacity(gendisk) / (sectors * heads);
- if (__put_user(sectors, &geo->sectors) ||
- __put_user(heads, &geo->heads) ||
- __put_user(cylinders, &geo->cylinders) ||
- __put_user(get_start_sect(ino->i_bdev), &geo->start))
- return -EFAULT;
- return 0;
- }
+ geo->sectors = d->sectors ? d->sectors : 0;
+ geo->heads = d->tracks ? d->tracks : 64;
+ geo->cylinders = d->cylinders ? d->cylinders :
+ get_capacity(disk) / (geo->cylinders * geo->heads);
- return -EINVAL;
+ return 0;
}
/*
@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = {
.owner = THIS_MODULE,
.open = viodasd_open,
.release = viodasd_release,
- .ioctl = viodasd_ioctl,
+ .getgeo = viodasd_getgeo,
};
/*
@@ -319,6 +293,7 @@ static int send_request(struct request *req)
u16 viocmd;
HvLpEvent_Rc hvrc;
struct vioblocklpevent *bevent;
+ struct HvLpEvent *hev;
struct scatterlist sg[VIOMAXBLOCKDMA];
int sgindex;
int statindex;
@@ -373,22 +348,19 @@ static int send_request(struct request *req)
* token so we can match the response up later
*/
memset(bevent, 0, sizeof(struct vioblocklpevent));
- bevent->event.xFlags.xValid = 1;
- bevent->event.xFlags.xFunction = HvLpEvent_Function_Int;
- bevent->event.xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
- bevent->event.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
- bevent->event.xType = HvLpEvent_Type_VirtualIo;
- bevent->event.xSubtype = viocmd;
- bevent->event.xSourceLp = HvLpConfig_getLpIndex();
- bevent->event.xTargetLp = viopath_hostLp;
- bevent->event.xSizeMinus1 =
+ hev = &bevent->event;
+ hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK |
+ HV_LP_EVENT_INT;
+ hev->xType = HvLpEvent_Type_VirtualIo;
+ hev->xSubtype = viocmd;
+ hev->xSourceLp = HvLpConfig_getLpIndex();
+ hev->xTargetLp = viopath_hostLp;
+ hev->xSizeMinus1 =
offsetof(struct vioblocklpevent, u.rw_data.dma_info) +
(sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1;
- bevent->event.xSourceInstanceId =
- viopath_sourceinst(viopath_hostLp);
- bevent->event.xTargetInstanceId =
- viopath_targetinst(viopath_hostLp);
- bevent->event.xCorrelationToken = (u64)req;
+ hev->xSourceInstanceId = viopath_sourceinst(viopath_hostLp);
+ hev->xTargetInstanceId = viopath_targetinst(viopath_hostLp);
+ hev->xCorrelationToken = (u64)req;
bevent->version = VIOVERSION;
bevent->disk = DEVICE_NO(d);
bevent->u.rw_data.offset = start;
@@ -675,10 +647,10 @@ static void handle_block_event(struct HvLpEvent *event)
/* Notification that a partition went away! */
return;
/* First, we should NEVER get an int here...only acks */
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
printk(VIOD_KERN_WARNING
"Yikes! got an int in viodasd event handler!\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
@@ -721,7 +693,7 @@ static void handle_block_event(struct HvLpEvent *event)
default:
printk(VIOD_KERN_WARNING "invalid subtype!");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 68b6d7b154cf..cbce7c5e9445 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock);
static struct gendisk *xd_gendisk[2];
+static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
+
static struct block_device_operations xd_fops = {
.owner = THIS_MODULE,
.ioctl = xd_ioctl,
+ .getgeo = xd_getgeo,
};
static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
@@ -276,11 +279,11 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address)
return(1);
}
- for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])); i++) {
+ for (i = 0; i < ARRAY_SIZE(xd_bases); i++) {
void __iomem *p = ioremap(xd_bases[i], 0x2000);
if (!p)
continue;
- for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])); j++) {
+ for (j = 1; j < ARRAY_SIZE(xd_sigs); j++) {
const char *s = xd_sigs[j].string;
if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) {
*controller = j;
@@ -330,22 +333,20 @@ static void do_xd_request (request_queue_t * q)
}
}
+static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ XD_INFO *p = bdev->bd_disk->private_data;
+
+ geo->heads = p->heads;
+ geo->sectors = p->sectors;
+ geo->cylinders = p->cylinders;
+ return 0;
+}
+
/* xd_ioctl: handle device ioctl's */
static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
{
- XD_INFO *p = inode->i_bdev->bd_disk->private_data;
-
switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry g;
- struct hd_geometry __user *geom= (void __user *)arg;
- g.heads = p->heads;
- g.sectors = p->sectors;
- g.cylinders = p->cylinders;
- g.start = get_start_sect(inode->i_bdev);
- return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0;
- }
case HDIO_SET_DMA:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (xdc_busy) return -EBUSY;
@@ -1017,7 +1018,7 @@ static void __init do_xd_setup (int *integers)
case 2: if ((integers[2] > 0) && (integers[2] < 16))
xd_irq = integers[2];
case 1: xd_override = 1;
- if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0]))))
+ if ((integers[1] >= 0) && (integers[1] < ARRAY_SIZE(xd_sigs)))
xd_type = integers[1];
case 0: break;
default:printk("xd: too many parameters for xd\n");
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 8fddfdfd0fbd..7bd4ef904115 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -494,7 +494,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char
}
}
-static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
+static void bcsp_complete_rx_pkt(struct hci_uart *hu)
{
struct bcsp_struct *bcsp = hu->priv;
int pass_up;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 573ff6c1be5f..613673b12fa6 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -279,6 +279,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->disc_data = hu;
hu->tty = tty;
+ tty->receive_room = 65536;
spin_lock_init(&hu->rx_lock);
@@ -348,20 +349,6 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
hci_uart_tx_wakeup(hu);
}
-/* hci_uart_tty_room()
- *
- * Callback function from tty driver. Return the amount of
- * space left in the receiver's buffer to decide if remote
- * transmitter is to be throttled.
- *
- * Arguments: tty pointer to associated tty instance data
- * Return Value: number of bytes left in receive buffer
- */
-static int hci_uart_tty_room (struct tty_struct *tty)
-{
- return 65536;
-}
-
/* hci_uart_tty_receive()
*
* Called by tty low level driver when receive data is
@@ -544,7 +531,6 @@ static int __init hci_uart_init(void)
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;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 153960348414..879bbc26ce96 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1131,7 +1131,7 @@ int open_for_data(struct cdrom_device_info * cdi)
This ensures that the drive gets unlocked after a mount fails. This
is a goto to avoid bloating the driver with redundant code. */
clean_up_and_return:
- cdinfo(CD_WARNING, "open failed.\n");
+ cdinfo(CD_OPEN, "open failed.\n");
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
cdo->lock_door(cdi, 0);
cdinfo(CD_OPEN, "door unlocked.\n");
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index 01f035173328..ce127f7ec0f6 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -32,7 +32,7 @@ History:
18 mrt 1995: 0.24 Working background read-ahead. (still problems)
26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
Statistics implemented, though separate stats206.h.
- Accessible trough ioctl 0x1000 (just a number).
+ Accessible through ioctl 0x1000 (just a number).
Hard to choose between v1.2 development and 1.1.75.
Bottom-half doesn't work with 1.2...
0.25a: fixed... typo. Still problems...
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index b5191780ecca..193446e6a08a 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -542,10 +542,10 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
/* Notification that a partition went away! */
return;
/* First, we should NEVER get an int here...only acks */
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
printk(VIOCD_KERN_WARNING
"Yikes! got an int in viocd event handler!\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
@@ -616,7 +616,7 @@ return_complete:
printk(VIOCD_KERN_WARNING
"message with invalid subtype %0x04X!\n",
event->xSubtype & VIOMINOR_SUBTYPE_MASK);
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5ebd06b1b4ca..4135d8c5bcae 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -80,7 +80,7 @@ config SERIAL_NONSTANDARD
config COMPUTONE
tristate "Computone IntelliPort Plus serial support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
---help---
This driver supports the entire family of Intelliport II/Plus
controllers with the exception of the MicroChannel controllers and
@@ -153,7 +153,7 @@ config DIGIEPCA
config ESPSERIAL
tristate "Hayes ESP serial port support"
- depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP && ISA_DMA_API
+ depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API
help
This is a driver which supports Hayes ESP serial ports. Both single
port cards and multiport cards are supported. Make sure to read
@@ -166,7 +166,7 @@ config ESPSERIAL
config MOXA_INTELLIO
tristate "Moxa Intellio support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
Say Y here if you have a Moxa Intellio multiport serial card.
@@ -220,6 +220,14 @@ config SYNCLINKMP
The module will be called synclinkmp. If you want to do that, say M
here.
+config SYNCLINK_GT
+ tristate "SyncLink GT/AC support"
+ depends on SERIAL_NONSTANDARD
+ help
+ Support for SyncLink GT and SyncLink AC families of
+ synchronous and asynchronous serial adapters
+ manufactured by Microgate Systems, Ltd. (www.microgate.com)
+
config N_HDLC
tristate "HDLC line discipline support"
depends on SERIAL_NONSTANDARD
@@ -282,7 +290,7 @@ config SX
config RIO
tristate "Specialix RIO system support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && !64BIT
help
This is a driver for the Specialix RIO, a smart serial card which
drives an outboard box that can support up to 128 ports. Product
@@ -687,7 +695,7 @@ config NVRAM
config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI)
+ depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV
---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
@@ -735,7 +743,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV
---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
@@ -873,16 +881,6 @@ config FTAPE
module. To compile this driver as a module, choose M here: the
module will be called ftape.
- Note that the Ftape-HOWTO is out of date (sorry) and documents the
- older version 2.08 of this software but still contains useful
- information. There is a web page with more recent documentation at
- <http://www.instmath.rwth-aachen.de/~heine/ftape/>. This page
- always contains the latest release of the ftape driver and useful
- information (backup software, ftape related patches and
- documentation, FAQ). Note that the file system interface has
- changed quite a bit compared to previous versions of ftape. Please
- read <file:Documentation/ftape.txt>.
-
source "drivers/char/ftape/Kconfig"
endmenu
@@ -928,6 +926,15 @@ config SCx200_GPIO
If compiled as a module, it will be called scx200_gpio.
+config CS5535_GPIO
+ tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
+ depends on X86_32
+ help
+ Give userspace access to the GPIO pins on the AMD CS5535 and
+ CS5536 Geode companion devices.
+
+ If compiled as a module, it will be called cs5535_gpio.
+
config GPIO_VR41XX
tristate "NEC VR4100 series General-purpose I/O Unit support"
depends on CPU_VR41XX
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 4aeae687e88a..503dd901d406 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_RISCOM8) += riscom8.o
obj-$(CONFIG_ISI) += isicom.o
obj-$(CONFIG_SYNCLINK) += synclink.o
obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o
+obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
@@ -80,6 +81,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 3f8f7fa6b0ff..268f78d926d3 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/agp_backend.h>
#include "agp.h"
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a124f8c5d062..7ac365b5d9ec 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -99,6 +99,7 @@ static char *serial_version = "4.30";
#define _INLINE_ inline
#endif
+#define custom amiga_custom
static char *serial_name = "Amiga-builtin serial driver";
static struct tty_driver *serial_driver;
@@ -116,7 +117,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
static struct serial_state rs_table[1];
-#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
+#define NR_PORTS ARRAY_SIZE(rs_table)
/*
* tmp_buf is used as a temporary buffer by serial_write. We need to
@@ -128,7 +129,6 @@ static struct serial_state rs_table[1];
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
#include <asm/uaccess.h>
@@ -265,8 +265,9 @@ static _INLINE_ void receive_chars(struct async_struct *info)
int status;
int serdatr;
struct tty_struct *tty = info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
struct async_icount *icount;
+ int oe = 0;
icount = &info->state->icount;
@@ -282,15 +283,12 @@ static _INLINE_ void receive_chars(struct async_struct *info)
status |= UART_LSR_OE;
ch = serdatr & 0xff;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
- *tty->flip.char_buf_ptr = ch;
icount->rx++;
#ifdef SERIAL_DEBUG_INTR
printk("DR%02x:%02x...", ch, status);
#endif
- *tty->flip.flag_buf_ptr = 0;
+ flag = TTY_NORMAL;
/*
* We don't handle parity or frame errors - but I have left
@@ -319,7 +317,7 @@ static _INLINE_ void receive_chars(struct async_struct *info)
* should be ignored.
*/
if (status & info->ignore_status_mask)
- goto ignore_char;
+ goto out;
status &= info->read_status_mask;
@@ -327,33 +325,28 @@ static _INLINE_ void receive_chars(struct async_struct *info)
#ifdef SERIAL_DEBUG_INTR
printk("handling break....");
#endif
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
if (status & UART_LSR_OE) {
/*
* Overrun is special, since it's
* reported immediately, and doesn't
* affect the current character
*/
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
+ oe = 1;
}
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- ignore_char:
-
+ tty_insert_flip_char(tty, ch, flag);
+ if (oe == 1)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
tty_flip_buffer_push(tty);
+out:
+ return;
}
static _INLINE_ void transmit_chars(struct async_struct *info)
@@ -1095,7 +1088,7 @@ static void rs_unthrottle(struct tty_struct * tty)
*/
static int get_serial_info(struct async_struct * info,
- struct serial_struct * retinfo)
+ struct serial_struct __user * retinfo)
{
struct serial_struct tmp;
struct serial_state *state = info->state;
@@ -1119,7 +1112,7 @@ static int get_serial_info(struct async_struct * info,
}
static int set_serial_info(struct async_struct * info,
- struct serial_struct * new_info)
+ struct serial_struct __user * new_info)
{
struct serial_struct new_serial;
struct serial_state old_state, *state;
@@ -1200,7 +1193,7 @@ check_and_exit:
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
+static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
{
unsigned char status;
unsigned int result;
@@ -1291,6 +1284,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct icount;
+ void __user *argp = (void __user *)arg;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
@@ -1305,19 +1299,17 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
switch (cmd) {
case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
+ return get_serial_info(info, argp);
case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
+ return set_serial_info(info, argp);
case TIOCSERCONFIG:
return 0;
case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
+ return get_lsr_info(info, argp);
case TIOCSERGSTRUCT:
- if (copy_to_user((struct async_struct *) arg,
+ if (copy_to_user(argp,
info, sizeof(struct async_struct)))
return -EFAULT;
return 0;
@@ -1376,7 +1368,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;
- if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+ if (copy_to_user(argp, &icount, sizeof(icount)))
return -EFAULT;
return 0;
case TIOCSERGWILD:
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
new file mode 100644
index 000000000000..5d72f50de1ac
--- /dev/null
+++ b/drivers/char/cs5535_gpio.c
@@ -0,0 +1,250 @@
+/*
+ * AMD CS5535/CS5536 GPIO driver.
+ * Allows a user space process to play with the GPIO pins.
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+
+#define NAME "cs5535_gpio"
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO Pin Driver");
+MODULE_LICENSE("GPL");
+
+static int major;
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static ulong mask;
+module_param(mask, ulong, 0);
+MODULE_PARM_DESC(mask, "GPIO channel mask");
+
+#define MSR_LBAR_GPIO 0x5140000C
+
+static u32 gpio_base;
+
+static struct pci_device_id divil_pci[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+ { } /* NULL entry */
+};
+
+static struct cdev cs5535_gpio_cdev;
+
+/* reserve 32 entries even though some aren't usable */
+#define CS5535_GPIO_COUNT 32
+
+/* IO block size */
+#define CS5535_GPIO_SIZE 256
+
+struct gpio_regmap {
+ u32 rd_offset;
+ u32 wr_offset;
+ char on;
+ char off;
+};
+static struct gpio_regmap rm[] =
+{
+ { 0x30, 0x00, '1', '0' }, /* GPIOx_READ_BACK / GPIOx_OUT_VAL */
+ { 0x20, 0x20, 'I', 'i' }, /* GPIOx_IN_EN */
+ { 0x04, 0x04, 'O', 'o' }, /* GPIOx_OUT_EN */
+ { 0x08, 0x08, 't', 'T' }, /* GPIOx_OUT_OD_EN */
+ { 0x18, 0x18, 'P', 'p' }, /* GPIOx_OUT_PU_EN */
+ { 0x1c, 0x1c, 'D', 'd' }, /* GPIOx_OUT_PD_EN */
+};
+
+
+/**
+ * Gets the register offset for the GPIO bank.
+ * Low (0-15) starts at 0x00, high (16-31) starts at 0x80
+ */
+static inline u32 cs5535_lowhigh_base(int reg)
+{
+ return (reg & 0x10) << 3;
+}
+
+static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ u32 m = iminor(file->f_dentry->d_inode);
+ int i, j;
+ u32 base = gpio_base + cs5535_lowhigh_base(m);
+ u32 m0, m1;
+ char c;
+
+ /**
+ * Creates the mask for atomic bit programming.
+ * The high 16 bits and the low 16 bits are used to set the mask.
+ * For example, GPIO 15 maps to 31,15: 0,1 => On; 1,0=> Off
+ */
+ m1 = 1 << (m & 0x0F);
+ m0 = m1 << 16;
+
+ for (i = 0; i < len; ++i) {
+ if (get_user(c, data+i))
+ return -EFAULT;
+
+ for (j = 0; j < ARRAY_SIZE(rm); j++) {
+ if (c == rm[j].on) {
+ outl(m1, base + rm[j].wr_offset);
+ break;
+ } else if (c == rm[j].off) {
+ outl(m0, base + rm[j].wr_offset);
+ break;
+ }
+ }
+ }
+ *ppos = 0;
+ return len;
+}
+
+static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ u32 m = iminor(file->f_dentry->d_inode);
+ u32 base = gpio_base + cs5535_lowhigh_base(m);
+ int rd_bit = 1 << (m & 0x0f);
+ int i;
+ char ch;
+ ssize_t count = 0;
+
+ if (*ppos >= ARRAY_SIZE(rm))
+ return 0;
+
+ for (i = *ppos; (i < (*ppos + len)) && (i < ARRAY_SIZE(rm)); i++) {
+ ch = (inl(base + rm[i].rd_offset) & rd_bit) ?
+ rm[i].on : rm[i].off;
+
+ if (put_user(ch, buf+count))
+ return -EFAULT;
+
+ count++;
+ }
+
+ /* add a line-feed if there is room */
+ if ((i == ARRAY_SIZE(rm)) && (count < len)) {
+ put_user('\n', buf + count);
+ count++;
+ }
+
+ *ppos += count;
+ return count;
+}
+
+static int cs5535_gpio_open(struct inode *inode, struct file *file)
+{
+ u32 m = iminor(inode);
+
+ /* the mask says which pins are usable by this driver */
+ if ((mask & (1 << m)) == 0)
+ return -EINVAL;
+
+ return nonseekable_open(inode, file);
+}
+
+static struct file_operations cs5535_gpio_fops = {
+ .owner = THIS_MODULE,
+ .write = cs5535_gpio_write,
+ .read = cs5535_gpio_read,
+ .open = cs5535_gpio_open
+};
+
+static int __init cs5535_gpio_init(void)
+{
+ dev_t dev_id;
+ u32 low, hi;
+ int retval;
+
+ if (pci_dev_present(divil_pci) == 0) {
+ printk(KERN_WARNING NAME ": DIVIL not found\n");
+ return -ENODEV;
+ }
+
+ /* Grab the GPIO I/O range */
+ rdmsr(MSR_LBAR_GPIO, low, hi);
+
+ /* Check the mask and whether GPIO is enabled (sanity check) */
+ if (hi != 0x0000f001) {
+ printk(KERN_WARNING NAME ": GPIO not enabled\n");
+ return -ENODEV;
+ }
+
+ /* Mask off the IO base address */
+ gpio_base = low & 0x0000ff00;
+
+ /**
+ * Some GPIO pins
+ * 31-29,23 : reserved (always mask out)
+ * 28 : Power Button
+ * 26 : PME#
+ * 22-16 : LPC
+ * 14,15 : SMBus
+ * 9,8 : UART1
+ * 7 : PCI INTB
+ * 3,4 : UART2/DDC
+ * 2 : IDE_IRQ0
+ * 0 : PCI INTA
+ *
+ * If a mask was not specified, be conservative and only allow:
+ * 1,2,5,6,10-13,24,25,27
+ */
+ if (mask != 0)
+ mask &= 0x1f7fffff;
+ else
+ mask = 0x0b003c66;
+
+ if (request_region(gpio_base, CS5535_GPIO_SIZE, NAME) == 0) {
+ printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n");
+ return -ENODEV;
+ }
+
+ if (major) {
+ dev_id = MKDEV(major, 0);
+ retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,
+ NAME);
+ } else {
+ retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT,
+ NAME);
+ major = MAJOR(dev_id);
+ }
+
+ if (retval) {
+ release_region(gpio_base, CS5535_GPIO_SIZE);
+ return -1;
+ }
+
+ printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
+ gpio_base, mask, major);
+
+ cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
+ cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
+
+ return 0;
+}
+
+static void __exit cs5535_gpio_cleanup(void)
+{
+ dev_t dev_id = MKDEV(major, 0);
+ unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
+ if (gpio_base != 0)
+ release_region(gpio_base, CS5535_GPIO_SIZE);
+}
+
+module_init(cs5535_gpio_init);
+module_exit(cs5535_gpio_cleanup);
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index c7f818cd7b02..39c61a71176e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -641,6 +641,7 @@ static char rcsid[] =
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/major.h>
#include <linux/string.h>
@@ -723,7 +724,7 @@ static unsigned int cy_isa_addresses[] = {
0xDE000,
0,0,0,0,0,0,0,0
};
-#define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
+#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
#ifdef MODULE
static long maddr[NR_CARDS] = { 0, };
@@ -1086,7 +1087,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int had_work;
int mdm_change;
int mdm_status;
-
+ int len;
if((cinfo = (struct cyclades_card *)dev_id) == 0){
#ifdef CY_DEBUG_INTERRUPTS
printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
@@ -1163,63 +1164,43 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
info->icount.rx++;
continue;
}
- if (tty->flip.count < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
+ if (tty_buffer_request_room(tty, 1)) {
if (data & info->read_status_mask){
if(data & CyBREAK){
- *tty->flip.flag_buf_ptr++ =
- TTY_BREAK;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_BREAK);
info->icount.rx++;
if (info->flags & ASYNC_SAK){
do_SAK(tty);
}
}else if(data & CyFRAME){
- *tty->flip.flag_buf_ptr++ =
- TTY_FRAME;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
info->icount.rx++;
info->idle_stats.frame_errs++;
}else if(data & CyPARITY){
- *tty->flip.flag_buf_ptr++ =
- TTY_PARITY;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
+ /* Pieces of seven... */
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_PARITY);
info->icount.rx++;
info->idle_stats.parity_errs++;
}else if(data & CyOVERRUN){
- *tty->flip.flag_buf_ptr++ =
- TTY_OVERRUN;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
info->icount.rx++;
/* If the flip buffer itself is
overflowing, we still lose
the next incoming character.
*/
- if(tty->flip.count
- < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ =
- TTY_NORMAL;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
- info->icount.rx++;
- }
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
+ info->icount.rx++;
info->idle_stats.overruns++;
/* These two conditions may imply */
/* a normal read should be done. */
/* }else if(data & CyTIMEOUT){ */
/* }else if(data & CySPECHAR){ */
- }else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
- info->icount.rx++;
+ }else {
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
+ info->icount.rx++;
}
}else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
info->icount.rx++;
}
}else{
@@ -1240,14 +1221,10 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
info->mon.char_max = char_count;
info->mon.char_last = char_count;
#endif
- while(char_count--){
- if (tty->flip.count >= TTY_FLIPBUF_SIZE){
- break;
- }
- tty->flip.count++;
+ len = tty_buffer_request_room(tty, char_count);
+ while(len--){
data = cy_readb(base_addr+(CyRDSR<<index));
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
info->idle_stats.recv_bytes++;
info->icount.rx++;
#ifdef CY_16Y_HACK
@@ -1256,7 +1233,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
info->idle_stats.recv_idle = jiffies;
}
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
/* end of service */
cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
@@ -1551,6 +1528,7 @@ cyz_handle_rx(struct cyclades_port *info,
struct cyclades_card *cinfo = &cy_card[info->card];
struct tty_struct *tty = info->tty;
volatile int char_count;
+ int len;
#ifdef BLOCKMOVE
int small_count;
#else
@@ -1606,18 +1584,11 @@ cyz_handle_rx(struct cyclades_port *info,
tty->flip.count += small_count;
}
#else
- while(char_count--){
- if (tty->flip.count >= N_TTY_BUF_SIZE - tty->read_cnt)
- break;
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
+ len = tty_buffer_request_room(tty, char_count);
+ while(len--){
data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
info->idle_stats.recv_bytes++;
info->icount.rx++;
}
@@ -1635,7 +1606,7 @@ cyz_handle_rx(struct cyclades_port *info,
}
#endif
info->idle_stats.recv_idle = jiffies;
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
/* Update rx_get */
cy_writel(&buf_ctrl->rx_get, new_rx_get);
@@ -1763,23 +1734,17 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
switch(cmd) {
case C_CM_PR_ERROR:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_PARITY);
info->icount.rx++;
special_count++;
break;
case C_CM_FR_ERROR:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_FRAME);
info->icount.rx++;
special_count++;
break;
case C_CM_RXBRK:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
info->icount.rx++;
special_count++;
break;
@@ -1844,7 +1809,7 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
if(delta_count)
cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
if(special_count)
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
}
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index e41060c76226..9d180c42816c 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
- drm_drv.o drm_fops.o drm_init.o drm_ioctl.o drm_irq.o \
+ drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
drm_sysfs.o
@@ -18,7 +18,7 @@ radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.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
+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 via_dmablit.o
ifeq ($(CONFIG_COMPAT),y)
drm-objs += drm_ioc32.o
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index efff0eec618c..5485382cadec 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -52,7 +52,7 @@
# 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 void *drm_ati_alloc_pcigart_table(void)
{
unsigned long address;
struct page *page;
@@ -72,27 +72,26 @@ static unsigned long drm_ati_alloc_pcigart_table(void)
}
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
- return address;
+ return (void *)address;
}
-static void drm_ati_free_pcigart_table(unsigned long address)
+static void drm_ati_free_pcigart_table(void *address)
{
struct page *page;
int i;
DRM_DEBUG("%s\n", __FUNCTION__);
- page = virt_to_page(address);
+ page = virt_to_page((unsigned long)address);
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
__put_page(page);
ClearPageReserved(page);
}
- free_pages(address, ATI_PCIGART_TABLE_ORDER);
+ free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER);
}
-int drm_ati_pcigart_cleanup(drm_device_t * dev,
- drm_ati_pcigart_info * gart_info)
+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;
@@ -136,10 +135,10 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev,
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
+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;
+ void *address = NULL;
unsigned long pages;
u32 *pci_gart, page_base, bus_address = 0;
int i, j, ret = 0;
@@ -163,7 +162,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
goto done;
}
- bus_address = pci_map_single(dev->pdev, (void *)address,
+ bus_address = pci_map_single(dev->pdev, address,
ATI_PCIGART_TABLE_PAGES *
PAGE_SIZE, PCI_DMA_TODEVICE);
if (bus_address == 0) {
@@ -176,7 +175,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
address = gart_info->addr;
bus_address = gart_info->bus_addr;
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
- bus_address, address);
+ bus_address, (unsigned long)address);
}
pci_gart = (u32 *) address;
@@ -195,7 +194,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
if (entry->busaddr[i] == 0) {
DRM_ERROR("unable to map PCIGART pages!\n");
drm_ati_pcigart_cleanup(dev, gart_info);
- address = 0;
+ address = NULL;
bus_address = 0;
goto done;
}
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 64d6237fdd0b..9da0ddb892b5 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -90,8 +90,8 @@
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
-#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
-#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
+#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 3dc3c9d79ae4..54b561e69486 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -144,20 +144,6 @@
/** \name Backward compatibility section */
/*@{*/
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(x)
-#endif
-
-#ifndef preempt_disable
-#define preempt_disable()
-#define preempt_enable()
-#endif
-
-#ifndef pte_offset_map
-#define pte_offset_map pte_offset
-#define pte_unmap(pte)
-#endif
-
#define DRM_RPR_ARG(vma) vma,
#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
@@ -286,10 +272,13 @@ typedef int drm_ioctl_t(struct inode *inode, struct file *filp,
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
unsigned long arg);
+#define DRM_AUTH 0x1
+#define DRM_MASTER 0x2
+#define DRM_ROOT_ONLY 0x4
+
typedef struct drm_ioctl_desc {
drm_ioctl_t *func;
- int auth_needed;
- int root_only;
+ int flags;
} drm_ioctl_desc_t;
typedef struct drm_devstate {
@@ -384,6 +373,7 @@ typedef struct drm_buf_entry {
/** File private data */
typedef struct drm_file {
int authenticated;
+ int master;
int minor;
pid_t pid;
uid_t uid;
@@ -532,8 +522,9 @@ typedef struct drm_vbl_sig {
typedef struct ati_pcigart_info {
int gart_table_location;
int is_pcie;
- unsigned long addr;
+ void *addr;
dma_addr_t bus_addr;
+ drm_local_map_t mapping;
} drm_ati_pcigart_info;
/**
@@ -544,16 +535,14 @@ typedef struct ati_pcigart_info {
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 (*load) (struct drm_device *, unsigned long flags);
+ int (*firstopen) (struct drm_device *);
+ int (*open) (struct drm_device *, drm_file_t *);
+ void (*preclose) (struct drm_device *, struct file * filp);
+ void (*postclose) (struct drm_device *, drm_file_t *);
+ void (*lastclose) (struct drm_device *);
+ int (*unload) (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);
@@ -561,8 +550,9 @@ struct drm_driver {
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);
+ drm_lock_t *lock);
int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
+ int (*dri_library_name) (struct drm_device *dev, char *buf);
/**
* Called by \c drm_device_is_agp. Typically used to determine if a
@@ -579,16 +569,24 @@ struct drm_driver {
/* these have to be filled in */
- int (*postinit) (struct drm_device *, unsigned long flags);
- irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+ 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);
+ void (*reclaim_buffers_locked) (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 major;
+ int minor;
+ int patchlevel;
+ char *name;
+ char *desc;
+ char *date;
+
u32 driver_features;
int dev_priv_size;
drm_ioctl_desc_t *ioctls;
@@ -752,19 +750,43 @@ static inline int drm_core_has_MTRR(struct drm_device *dev)
{
return drm_core_check_feature(dev, DRIVER_USE_MTRR);
}
+
+#define DRM_MTRR_WC MTRR_TYPE_WRCOMB
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+ unsigned int flags)
+{
+ return mtrr_add(offset, size, flags, 1);
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+ unsigned long size, unsigned int flags)
+{
+ return mtrr_del(handle, offset, size);
+}
+
#else
#define drm_core_has_MTRR(dev) (0)
+
+#define DRM_MTRR_WC 0
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+ unsigned int flags)
+{
+ return 0;
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+ unsigned long size, unsigned int flags)
+{
+ return 0;
+}
#endif
/******************************************************************/
/** \name Internal function definitions */
/*@{*/
- /* Misc. support (drm_init.h) */
-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);
@@ -772,12 +794,11 @@ 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_lastclose(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);
@@ -819,6 +840,8 @@ 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_noop(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,
@@ -857,10 +880,6 @@ extern int drm_getmagic(struct inode *inode, struct file *filp,
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);
-
/* Locking IOCTL support (drm_lock.h) */
extern int drm_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -873,6 +892,7 @@ extern int drm_lock_free(drm_device_t * dev,
/* Buffer management support (drm_bufs.h) */
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_addbufs_fb(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);
@@ -908,8 +928,8 @@ 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 int drm_irq_uninstall(drm_device_t * dev);
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);
@@ -933,13 +953,17 @@ extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
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,
+extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(struct inode *inode, struct file *filp,
+extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(struct inode *inode, struct file *filp,
+extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(struct inode *inode, struct file *filp,
+extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_bind_ioctl(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);
@@ -991,10 +1015,8 @@ extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
char *name);
extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
- dev_t dev,
- struct device *device,
- const char *fmt, ...);
-extern void drm_sysfs_device_remove(dev_t dev);
+ drm_head_t *head);
+extern void drm_sysfs_device_remove(struct class_device *class_dev);
/* Inline replacements for DRM_IOREMAP macros */
static __inline__ void drm_core_ioremap(struct drm_map *map,
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 2b6453a9ffce..fabc930c67a2 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -1,5 +1,5 @@
/**
- * \file drm_agpsupport.h
+ * \file drm_agpsupport.c
* DRM support for AGP/GART backend
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -91,7 +91,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
/**
* Acquire the AGP device.
*
- * \param dev DRM device that is to acquire AGP
+ * \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
@@ -134,7 +134,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
/**
* Release the AGP device.
*
- * \param dev DRM device that is to release AGP
+ * \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.
@@ -147,7 +147,6 @@ int drm_agp_release(drm_device_t * dev)
dev->agp->acquired = 0;
return 0;
}
-
EXPORT_SYMBOL(drm_agp_release);
int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
@@ -208,30 +207,22 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
* 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)
+int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
{
- 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_buffer_t __user *argp = (void __user *)arg;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&request, argp, sizeof(request)))
- return -EFAULT;
if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
return -ENOMEM;
memset(entry, 0, sizeof(*entry));
- pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
- type = (u32) request.type;
-
+ pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
+ type = (u32) request->type;
if (!(memory = drm_alloc_agp(dev, pages, type))) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -ENOMEM;
@@ -247,16 +238,39 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
dev->agp->memory->prev = entry;
dev->agp->memory = entry;
- request.handle = entry->handle;
- request.physical = memory->physical;
+ request->handle = entry->handle;
+ request->physical = memory->physical;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_agp_alloc);
+
+int drm_agp_alloc_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_buffer_t request;
+ drm_agp_buffer_t __user *argp = (void __user *)arg;
+ int err;
+
+ if (copy_from_user(&request, argp, sizeof(request)))
+ return -EFAULT;
+
+ err = drm_agp_alloc(dev, &request);
+ if (err)
+ return err;
if (copy_to_user(argp, &request, sizeof(request))) {
+ drm_agp_mem_t *entry = dev->agp->memory;
+
dev->agp->memory = entry->next;
dev->agp->memory->prev = NULL;
- drm_free_agp(memory, pages);
+ drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -EFAULT;
}
+
return 0;
}
@@ -293,21 +307,14 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
* Verifies the AGP device is present and acquired, looks-up the AGP memory
* 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)
+int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
{
- 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 ret;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user
- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
- return -EFAULT;
- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
return -EINVAL;
if (!entry->bound)
return -EINVAL;
@@ -316,6 +323,21 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
entry->bound = 0;
return ret;
}
+EXPORT_SYMBOL(drm_agp_unbind);
+
+int drm_agp_unbind_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_binding_t request;
+
+ if (copy_from_user
+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ return drm_agp_unbind(dev, &request);
+}
/**
* Bind AGP memory into the GATT (ioctl)
@@ -330,26 +352,19 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
* is currently bound into the GATT. Looks-up the AGP memory entry and passes
* it to bind_agp() function.
*/
-int drm_agp_bind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
{
- 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;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user
- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
- return -EFAULT;
- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
return -EINVAL;
if (entry->bound)
return -EINVAL;
- page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
+ page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
if ((retcode = drm_bind_agp(entry->memory, page)))
return retcode;
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
@@ -357,6 +372,21 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
dev->agp->base, entry->bound);
return 0;
}
+EXPORT_SYMBOL(drm_agp_bind);
+
+int drm_agp_bind_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_binding_t request;
+
+ if (copy_from_user
+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ return drm_agp_bind(dev, &request);
+}
/**
* Free AGP memory (ioctl).
@@ -372,20 +402,13 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
* unbind_agp(). Frees it via free_agp() as well as the entry itself
* 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)
+int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_buffer_t request;
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)))
- return -EFAULT;
- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
return -EINVAL;
if (entry->bound)
drm_unbind_agp(entry->memory);
@@ -402,12 +425,30 @@ int drm_agp_free(struct inode *inode, struct file *filp,
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return 0;
}
+EXPORT_SYMBOL(drm_agp_free);
+
+int drm_agp_free_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_buffer_t request;
+
+ if (copy_from_user
+ (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ return drm_agp_free(dev, &request);
+}
/**
* Initialize the AGP resources.
*
* \return pointer to a drm_agp_head structure.
*
+ * Gets the drm_agp_t structure which is made available by the agpgart module
+ * via the inter_module_* functions. Creates and initializes a drm_agp_head
+ * structure.
*/
drm_agp_head_t *drm_agp_init(drm_device_t * dev)
{
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 319bdea8de8a..1db12dcb6802 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -36,22 +36,21 @@
#include <linux/vmalloc.h>
#include "drmP.h"
-unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource)
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
{
return pci_resource_start(dev->pdev, resource);
}
-
EXPORT_SYMBOL(drm_get_resource_start);
-unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource)
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
{
return pci_resource_len(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_len);
-static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
- drm_local_map_t * map)
+static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
+ drm_local_map_t *map)
{
struct list_head *list;
@@ -74,7 +73,7 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
#ifdef _LP64
static __inline__ unsigned int HandleID(unsigned long lhandle,
- drm_device_t * dev)
+ drm_device_t *dev)
{
static unsigned int map32_handle = START_RANGE;
unsigned int hash;
@@ -155,7 +154,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
- if (map->offset + map->size < map->offset ||
+ if (map->offset + (map->size-1) < map->offset ||
map->offset < virt_to_phys(high_memory)) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
@@ -301,6 +300,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
}
+ if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))
+ return -EPERM;
+
err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
&maplist);
@@ -332,7 +334,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
*
* \sa drm_addmap
*/
-int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
+int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
{
struct list_head *list;
drm_map_list_t *r_list = NULL;
@@ -384,10 +386,9 @@ int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
return 0;
}
-
EXPORT_SYMBOL(drm_rmmap_locked);
-int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
+int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{
int ret;
@@ -397,7 +398,6 @@ int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
return ret;
}
-
EXPORT_SYMBOL(drm_rmmap);
/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
@@ -548,7 +548,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
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("agp_offset: %lx\n", agp_offset);
DRM_DEBUG("alignment: %d\n", alignment);
DRM_DEBUG("page_order: %d\n", page_order);
DRM_DEBUG("total: %d\n", total);
@@ -649,6 +649,8 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
@@ -664,7 +666,6 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
-
EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */
@@ -689,9 +690,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
return -EINVAL;
+
if (!dma)
return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
count = request->count;
order = drm_order(request->size);
size = 1 << order;
@@ -882,7 +887,6 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-
EXPORT_SYMBOL(drm_addbufs_pci);
static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
@@ -908,6 +912,9 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
if (!dma)
return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
count = request->count;
order = drm_order(request->size);
size = 1 << order;
@@ -1026,6 +1033,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
@@ -1042,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+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;
@@ -1065,6 +1074,9 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
if (!dma)
return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
count = request->count;
order = drm_order(request->size);
size = 1 << order;
@@ -1181,6 +1193,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
@@ -1196,6 +1210,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_fb);
+
/**
* Add buffers for DMA transfers (ioctl).
@@ -1577,5 +1593,6 @@ int drm_order(unsigned long size)
return order;
}
-
EXPORT_SYMBOL(drm_order);
+
+
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index bd958d69a2ac..f84254526949 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -433,7 +433,7 @@ int drm_addctx(struct inode *inode, struct file *filp,
if (ctx.handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_ctor)
if (!dev->driver->context_ctor(dev, ctx.handle)) {
- DRM_DEBUG( "Running out of ctxs or memory.\n");
+ DRM_DEBUG("Running out of ctxs or memory.\n");
return -ENOMEM;
}
}
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
index cc97bb906dda..f4f9db6c7ed4 100644
--- a/drivers/char/drm/drm_core.h
+++ b/drivers/char/drm/drm_core.h
@@ -24,11 +24,11 @@
#define CORE_NAME "drm"
#define CORE_DESC "DRM shared core routines"
-#define CORE_DATE "20040925"
+#define CORE_DATE "20051102"
#define DRM_IF_MAJOR 1
#define DRM_IF_MINOR 2
#define CORE_MAJOR 1
#define CORE_MINOR 0
-#define CORE_PATCHLEVEL 0
+#define CORE_PATCHLEVEL 1
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 4dff7554eb08..c4fa5a29582b 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -56,66 +56,66 @@ static int drm_version(struct inode *inode, struct file *filp,
/** 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_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},
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH},
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
#if __OS_HAS_AGP
- [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},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
#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, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
- [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
};
#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
@@ -129,7 +129,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
*
* \sa drm_device
*/
-int drm_takedown(drm_device_t * dev)
+int drm_lastclose(drm_device_t * dev)
{
drm_magic_entry_t *pt, *next;
drm_map_list_t *r_list;
@@ -138,9 +138,9 @@ int drm_takedown(drm_device_t * dev)
DRM_DEBUG("\n");
- if (dev->driver->pretakedown)
- dev->driver->pretakedown(dev);
- DRM_DEBUG("driver pretakedown completed\n");
+ if (dev->driver->lastclose)
+ dev->driver->lastclose(dev);
+ DRM_DEBUG("driver lastclose completed\n");
if (dev->unique) {
drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
@@ -233,7 +233,7 @@ int drm_takedown(drm_device_t * dev)
}
up(&dev->struct_sem);
- DRM_DEBUG("takedown completed\n");
+ DRM_DEBUG("lastclose completed\n");
return 0;
}
@@ -281,7 +281,7 @@ EXPORT_SYMBOL(drm_init);
/**
* Called via cleanup_module() at module unload time.
*
- * Cleans up all DRM device, calling takedown().
+ * Cleans up all DRM device, calling drm_lastclose().
*
* \sa drm_init
*/
@@ -294,7 +294,7 @@ static void drm_cleanup(drm_device_t * dev)
return;
}
- drm_takedown(dev);
+ drm_lastclose(dev);
if (dev->maplist) {
drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
@@ -317,8 +317,8 @@ static void drm_cleanup(drm_device_t * dev)
dev->agp = NULL;
}
- if (dev->driver->postcleanup)
- dev->driver->postcleanup(dev);
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
drm_put_head(&dev->primary);
if (drm_put_dev(dev))
@@ -342,12 +342,12 @@ void drm_exit(struct drm_driver *driver)
if (head->dev->driver != driver)
continue;
dev = head->dev;
- }
- if (dev) {
- /* release the pci driver */
- if (dev->pdev)
- pci_dev_put(dev->pdev);
- drm_cleanup(dev);
+ if (dev) {
+ /* release the pci driver */
+ if (dev->pdev)
+ pci_dev_put(dev->pdev);
+ drm_cleanup(dev);
+ }
}
DRM_INFO("Module unloaded\n");
}
@@ -432,14 +432,17 @@ static int drm_version(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->head->dev;
drm_version_t __user *argp = (void __user *)arg;
drm_version_t version;
- int ret;
+ int len;
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;
+ version.version_major = dev->driver->major;
+ version.version_minor = dev->driver->minor;
+ version.version_patchlevel = dev->driver->patchlevel;
+ DRM_COPY(version.name, dev->driver->name);
+ DRM_COPY(version.date, dev->driver->date);
+ DRM_COPY(version.desc, dev->driver->desc);
if (copy_to_user(argp, &version, sizeof(version)))
return -EFAULT;
@@ -493,8 +496,9 @@ int drm_ioctl(struct inode *inode, struct file *filp,
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->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
+ ((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
+ ((ioctl->flags & DRM_MASTER) && !priv->master)) {
retcode = -EACCES;
} else {
retcode = func(inode, filp, cmd, arg);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index bf0a740122bf..403f44a1bf01 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -35,6 +35,7 @@
*/
#include "drmP.h"
+#include "drm_sarea.h"
#include <linux/poll.h>
static int drm_open_helper(struct inode *inode, struct file *filp,
@@ -42,15 +43,21 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
static int drm_setup(drm_device_t * dev)
{
+ drm_local_map_t *map;
int i;
int ret;
- if (dev->driver->presetup) {
- ret = dev->driver->presetup(dev);
+ if (dev->driver->firstopen) {
+ ret = dev->driver->firstopen(dev);
if (ret != 0)
return ret;
}
+ /* prebuild the SAREA */
+ i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
+ if (i != 0)
+ return i;
+
atomic_set(&dev->ioctl_count, 0);
atomic_set(&dev->vma_count, 0);
dev->buf_use = 0;
@@ -109,8 +116,6 @@ static int drm_setup(drm_device_t * dev)
* drm_select_queue fails between the time the interrupt is
* initialized and the time the queues are initialized.
*/
- if (dev->driver->postsetup)
- dev->driver->postsetup(dev);
return 0;
}
@@ -154,10 +159,168 @@ int drm_open(struct inode *inode, struct file *filp)
return retcode;
}
-
EXPORT_SYMBOL(drm_open);
/**
+ * File \c open operation.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ *
+ * Puts the dev->fops corresponding to the device minor number into
+ * \p filp, call the \c open method, and restore the file operations.
+ */
+int drm_stub_open(struct inode *inode, struct file *filp)
+{
+ drm_device_t *dev = NULL;
+ int minor = iminor(inode);
+ int err = -ENODEV;
+ struct file_operations *old_fops;
+
+ DRM_DEBUG("\n");
+
+ if (!((minor >= 0) && (minor < drm_cards_limit)))
+ return -ENODEV;
+
+ if (!drm_heads[minor])
+ return -ENODEV;
+
+ if (!(dev = drm_heads[minor]->dev))
+ return -ENODEV;
+
+ old_fops = filp->f_op;
+ filp->f_op = fops_get(&dev->driver->fops);
+ if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
+ fops_put(filp->f_op);
+ filp->f_op = fops_get(old_fops);
+ }
+ fops_put(old_fops);
+
+ return err;
+}
+
+/**
+ * Check whether DRI will run on this CPU.
+ *
+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.
+ */
+static int drm_cpu_valid(void)
+{
+#if defined(__i386__)
+ 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. */
+#endif
+ return 1;
+}
+
+/**
+ * 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)
+{
+ 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;
+
+ DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
+
+ 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;
+ /* for compatibility root is always authenticated */
+ priv->authenticated = capable(CAP_SYS_ADMIN);
+ priv->lock_count = 0;
+
+ if (dev->driver->open) {
+ ret = dev->driver->open(dev, priv);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ down(&dev->struct_sem);
+ if (!dev->file_last) {
+ priv->next = NULL;
+ priv->prev = NULL;
+ dev->file_first = priv;
+ dev->file_last = priv;
+ /* first opener automatically becomes master */
+ priv->master = 1;
+ } else {
+ priv->next = NULL;
+ priv->prev = dev->file_last;
+ dev->file_last->next = priv;
+ dev->file_last = priv;
+ }
+ up(&dev->struct_sem);
+
+#ifdef __alpha__
+ /*
+ * Default the hose
+ */
+ if (!dev->hose) {
+ struct pci_dev *pci_dev;
+ pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+ if (pci_dev) {
+ dev->hose = pci_dev->sysdata;
+ pci_dev_put(pci_dev);
+ }
+ if (!dev->hose) {
+ struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+ if (b)
+ dev->hose = b->sysdata;
+ }
+ }
+#endif
+
+ return 0;
+ out_free:
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+ filp->private_data = NULL;
+ return ret;
+}
+
+/** 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_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;
+ return 0;
+}
+EXPORT_SYMBOL(drm_fasync);
+
+/**
* Release file.
*
* \param inode device inode
@@ -167,7 +330,7 @@ EXPORT_SYMBOL(drm_open);
* If the hardware lock is held then free it, and take it again for the kernel
* context since it's necessary to reclaim buffers. Unlink the file private
* data from its list and free it. Decreases the open count and if it reaches
- * zero calls takedown().
+ * zero calls drm_lastclose().
*/
int drm_release(struct inode *inode, struct file *filp)
{
@@ -180,8 +343,8 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count);
- if (dev->driver->prerelease)
- dev->driver->prerelease(dev, filp);
+ if (dev->driver->preclose)
+ dev->driver->preclose(dev, filp);
/* ========================================================
* Begin inline drm_release
@@ -197,8 +360,8 @@ int drm_release(struct inode *inode, struct file *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);
+ if (dev->driver->reclaim_buffers_locked)
+ dev->driver->reclaim_buffers_locked(dev, filp);
drm_lock_free(dev, &dev->lock.hw_lock->lock,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
@@ -207,7 +370,7 @@ int drm_release(struct inode *inode, struct file *filp)
hardware at this point, possibly
processed via a callback to the X
server. */
- } else if (dev->driver->release && priv->lock_count
+ } else if (dev->driver->reclaim_buffers_locked && priv->lock_count
&& dev->lock.hw_lock) {
/* The lock is required to reclaim buffers */
DECLARE_WAITQUEUE(entry, current);
@@ -237,15 +400,14 @@ int drm_release(struct inode *inode, struct file *filp)
__set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry);
if (!retcode) {
- if (dev->driver->release)
- dev->driver->release(dev, filp);
+ dev->driver->reclaim_buffers_locked(dev, filp);
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->reclaim_buffers_locked) {
dev->driver->reclaim_buffers(dev, filp);
}
@@ -292,9 +454,8 @@ int drm_release(struct inode *inode, struct file *filp)
}
up(&dev->struct_sem);
- if (dev->driver->free_filp_priv)
- dev->driver->free_filp_priv(dev, priv);
-
+ if (dev->driver->postclose)
+ dev->driver->postclose(dev, priv);
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
/* ========================================================
@@ -313,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp)
}
spin_unlock(&dev->count_lock);
unlock_kernel();
- return drm_takedown(dev);
+ return drm_lastclose(dev);
}
spin_unlock(&dev->count_lock);
@@ -321,129 +482,11 @@ int drm_release(struct inode *inode, struct file *filp)
return retcode;
}
-
EXPORT_SYMBOL(drm_release);
-/**
- * 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)
-{
- 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;
-
- DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
-
- 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;
- priv->authenticated = capable(CAP_SYS_ADMIN);
- priv->lock_count = 0;
-
- if (dev->driver->open_helper) {
- 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;
- dev->file_first = priv;
- dev->file_last = priv;
- } else {
- priv->next = NULL;
- priv->prev = dev->file_last;
- dev->file_last->next = priv;
- dev->file_last = priv;
- }
- up(&dev->struct_sem);
-
-#ifdef __alpha__
- /*
- * Default the hose
- */
- if (!dev->hose) {
- struct pci_dev *pci_dev;
- pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
- if (pci_dev) {
- dev->hose = pci_dev->sysdata;
- pci_dev_put(pci_dev);
- }
- if (!dev->hose) {
- struct pci_bus *b = pci_bus_b(pci_root_buses.next);
- if (b)
- dev->hose = b->sysdata;
- }
- }
-#endif
-
- return 0;
- out_free:
- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
- 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_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- 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_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;
- return 0;
-}
-
-EXPORT_SYMBOL(drm_fasync);
-
/** No-op. */
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{
return 0;
}
-
EXPORT_SYMBOL(drm_poll);
diff --git a/drivers/char/drm/drm_init.c b/drivers/char/drm/drm_init.c
deleted file mode 100644
index 754b934715c4..000000000000
--- a/drivers/char/drm/drm_init.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * \file drm_init.c
- * Setup/Cleanup for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan 4 08:58:31 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.
- */
-
-#include "drmP.h"
-
-/**
- * Check whether DRI will run on this CPU.
- *
- * \return non-zero if the DRI will run on this CPU, or zero otherwise.
- */
-int drm_cpu_valid(void)
-{
-#if defined(__i386__)
- 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. */
-#endif
- return 1;
-}
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index dd91ff6b474c..e9e2db18952d 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm_core.h"
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 9b0feba6b063..bcd4e604d3ec 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -137,17 +137,22 @@ int drm_setunique(struct inode *inode, struct file *filp,
static int drm_set_busid(drm_device_t * dev)
{
+ int len;
+
if (dev->unique != NULL)
return EBUSY;
- dev->unique_len = 20;
+ dev->unique_len = 40;
dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
if (dev->unique == NULL)
return ENOMEM;
- snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+ len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
+ if (len > dev->unique_len)
+ DRM_ERROR("Unique buffer overflowed\n");
+
dev->devname =
drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
2, DRM_MEM_DRIVER);
@@ -239,7 +244,7 @@ int drm_getclient(struct inode *inode, struct file *filp,
{
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 __user *argp = (drm_client_t __user *)arg;
drm_client_t client;
drm_file_t *pt;
int idx;
@@ -262,7 +267,7 @@ int drm_getclient(struct inode *inode, struct file *filp,
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(argp, &client, sizeof(client)))
return -EFAULT;
return 0;
}
@@ -325,17 +330,13 @@ int drm_setversion(DRM_IOCTL_ARGS)
drm_set_version_t retv;
int if_version;
drm_set_version_t __user *argp = (void __user *)data;
- drm_version_t version;
DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv));
- memset(&version, 0, sizeof(version));
-
- dev->driver->version(&version);
retv.drm_di_major = DRM_IF_MAJOR;
retv.drm_di_minor = DRM_IF_MINOR;
- retv.drm_dd_major = version.version_major;
- retv.drm_dd_minor = version.version_minor;
+ retv.drm_dd_major = dev->driver->major;
+ retv.drm_dd_minor = dev->driver->minor;
DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv));
@@ -343,7 +344,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
if (sv.drm_di_major != DRM_IF_MAJOR ||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
return EINVAL;
- if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+ if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor);
dev->if_version = DRM_MAX(if_version, dev->if_version);
if (sv.drm_di_minor >= 1) {
/*
@@ -354,9 +355,9 @@ int drm_setversion(DRM_IOCTL_ARGS)
}
if (sv.drm_dd_major != -1) {
- if (sv.drm_dd_major != version.version_major ||
+ if (sv.drm_dd_major != dev->driver->major ||
sv.drm_dd_minor < 0
- || sv.drm_dd_minor > version.version_minor)
+ || sv.drm_dd_minor > dev->driver->minor)
return EINVAL;
if (dev->driver->set_version)
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index b48a595d54ec..f9e45303498d 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -130,7 +130,6 @@ int drm_lock(struct inode *inode, struct file *filp,
/* 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 &&
dev->last_context != lock.context) {
dev->driver->kernel_context_switch(dev, dev->last_context,
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index abef2acf99f5..8074771e348f 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -145,30 +145,22 @@ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 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)
{
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)
{
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)
{
return drm_agp_unbind_memory(handle);
}
-
-EXPORT_SYMBOL(drm_unbind_agp);
#endif /* agp */
#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index b370aca718d2..e84605fc54af 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_debug.h
* Memory management wrappers for DRM.
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -43,42 +43,41 @@ typedef struct drm_mem_stats {
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)[] =
+static spinlock_t drm_mem_lock = SPIN_LOCK_UNLOCKED;
+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 */
+ [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;
- for (mem = DRM(mem_stats); mem->name; ++mem) {
+ for (mem = drm_mem_stats; mem->name; ++mem) {
mem->succeed_count = 0;
mem->free_count = 0;
mem->fail_count = 0;
@@ -87,13 +86,13 @@ void DRM(mem_init) (void) {
}
si_meminfo(&si);
- DRM(ram_available) = si.totalram;
- DRM(ram_used) = 0;
+ drm_ram_available = si.totalram;
+ 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,
+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;
@@ -112,11 +111,11 @@ static int DRM(_mem_info) (char *buf, char **start, off_t offset,
" | allocs bytes\n\n");
DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
"system", 0, 0, 0,
- DRM(ram_available) << (PAGE_SHIFT - 10));
+ drm_ram_available << (PAGE_SHIFT - 10));
DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
- "locked", 0, 0, 0, DRM(ram_used) >> 10);
+ "locked", 0, 0, 0, drm_ram_used >> 10);
DRM_PROC_PRINT("\n");
- for (pt = DRM(mem_stats); pt->name; pt++) {
+ for (pt = drm_mem_stats; pt->name; pt++) {
DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
pt->name,
pt->succeed_count,
@@ -135,17 +134,17 @@ static int DRM(_mem_info) (char *buf, char **start, off_t offset,
return len - offset;
}
-int DRM(mem_info) (char *buf, char **start, off_t offset,
+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);
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ 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) {
@@ -154,41 +153,41 @@ void *DRM(alloc) (size_t size, int area) {
}
if (!(pt = kmalloc(size, GFP_KERNEL))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].succeed_count;
- DRM(mem_stats)[area].bytes_allocated += size;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].succeed_count;
+ drm_mem_stats[area].bytes_allocated += size;
+ spin_unlock(&drm_mem_lock);
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)))
+ 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;
@@ -196,43 +195,43 @@ void DRM(free) (void *pt, size_t size, int area) {
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;
- spin_unlock(&DRM(mem_lock));
+ 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;
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
}
-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 addr;
unsigned int sz;
- spin_lock(&DRM(mem_lock));
- if ((DRM(ram_used) >> PAGE_SHIFT)
- > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ if ((drm_ram_used >> PAGE_SHIFT)
+ > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
+ spin_unlock(&drm_mem_lock);
return 0;
}
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
if (!address) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].fail_count;
+ spin_unlock(&drm_mem_lock);
return 0;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].succeed_count;
- DRM(mem_stats)[area].bytes_allocated += bytes;
- DRM(ram_used) += bytes;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].succeed_count;
+ drm_mem_stats[area].bytes_allocated += bytes;
+ drm_ram_used += bytes;
+ spin_unlock(&drm_mem_lock);
/* Zero outside the lock */
memset((void *)address, 0, bytes);
@@ -246,7 +245,7 @@ unsigned long DRM(alloc_pages) (int order, int area) {
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;
@@ -264,12 +263,12 @@ void DRM(free_pages) (unsigned long address, int order, int area) {
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;
- DRM(mem_stats)[area].bytes_freed += bytes;
- DRM(ram_used) -= bytes;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ 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;
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(area,
"Excess frees: %d frees, %d allocs\n",
@@ -277,7 +276,7 @@ void DRM(free_pages) (unsigned long address, int order, int area) {
}
}
-void *DRM(ioremap) (unsigned long offset, unsigned long size,
+void *drm_ioremap (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -288,19 +287,19 @@ void *DRM(ioremap) (unsigned long offset, unsigned long size,
}
if (!(pt = drm_ioremap(offset, size, dev))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ spin_unlock(&drm_mem_lock);
return pt;
}
-void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
+void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -311,19 +310,19 @@ void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
}
if (!(pt = drm_ioremap_nocache(offset, size, dev))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ spin_unlock(&drm_mem_lock);
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;
@@ -333,11 +332,11 @@ void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
else
drm_ioremapfree(pt, size, 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;
- spin_unlock(&DRM(mem_lock));
+ 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;
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Excess frees: %d frees, %d allocs\n",
@@ -347,7 +346,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 (drm_device_t *dev, int pages, u32 type) {
DRM_AGP_MEM *handle;
if (!pages) {
@@ -355,21 +354,21 @@ DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {
return NULL;
}
- 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
+ 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;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
return handle;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
-int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
+int drm_free_agp (DRM_AGP_MEM * handle, int pages) {
int alloc_count;
int free_count;
int retval = -EINVAL;
@@ -380,13 +379,13 @@ int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
return retval;
}
- 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;
- DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+ 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;
+ drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
+= pages << PAGE_SHIFT;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
"Excess frees: %d frees, %d allocs\n",
@@ -397,7 +396,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) {
@@ -406,21 +405,21 @@ int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {
return retcode;
}
- 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
+ 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;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
return retcode;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
+ spin_unlock(&drm_mem_lock);
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;
@@ -431,14 +430,14 @@ int DRM(unbind_agp) (DRM_AGP_MEM * handle) {
return retcode;
}
- if ((retcode = DRM(agp_unbind_memory) (handle)))
+ if ((retcode = drm_agp_unbind_memory (handle)))
return retcode;
- spin_lock(&DRM(mem_lock));
- 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
+ spin_lock(&drm_mem_lock);
+ 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;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Excess frees: %d frees, %d allocs\n",
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index d51aeb4966f4..695115d70382 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -13,6 +13,7 @@
#define DRM_ERR(d) -(d)
/** Current process ID */
#define DRM_CURRENTPID current->pid
+#define DRM_SUSER(p) capable(CAP_SYS_ADMIN)
#define DRM_UDELAY(d) udelay(d)
/** Read a byte from a MMIO region */
#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset))
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index d66dc55e29a0..5b1d3a04458d 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -46,6 +46,7 @@
{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, 0x4E56, 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}, \
@@ -69,6 +70,7 @@
{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, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{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}, \
@@ -82,10 +84,13 @@
{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
{0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
{0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
{0, 0, 0}
#define r128_PCI_IDS \
@@ -176,7 +181,7 @@
#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, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
{0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
@@ -196,6 +201,10 @@
{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, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
{0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
@@ -234,3 +243,4 @@
{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}
+
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 3f452f763f0f..6f943e3309ef 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -61,16 +61,14 @@ static struct drm_proc_list {
const char *name; /**< file name */
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
};
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 60b6f8e8bf69..42d766359caa 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -93,8 +93,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
dev->driver = driver;
- if (dev->driver->preinit)
- if ((retcode = dev->driver->preinit(dev, ent->driver_data)))
+ if (dev->driver->load)
+ if ((retcode = dev->driver->load(dev, ent->driver_data)))
goto error_out_unreg;
if (drm_core_has_AGP(dev)) {
@@ -124,47 +124,10 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
return 0;
error_out_unreg:
- drm_takedown(dev);
+ drm_lastclose(dev);
return retcode;
}
-/**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
- drm_device_t *dev = NULL;
- int minor = iminor(inode);
- int err = -ENODEV;
- struct file_operations *old_fops;
-
- DRM_DEBUG("\n");
-
- if (!((minor >= 0) && (minor < drm_cards_limit)))
- return -ENODEV;
-
- if (!drm_heads[minor])
- return -ENODEV;
-
- if (!(dev = drm_heads[minor]->dev))
- return -ENODEV;
-
- old_fops = filp->f_op;
- filp->f_op = fops_get(&dev->driver->fops);
- if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
- fops_put(filp->f_op);
- filp->f_op = fops_get(old_fops);
- }
- fops_put(old_fops);
-
- return err;
-}
/**
* Get a secondary minor number.
@@ -200,11 +163,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
goto err_g1;
}
- head->dev_class = drm_sysfs_device_add(drm_class,
- MKDEV(DRM_MAJOR,
- minor),
- &dev->pdev->dev,
- "card%d", minor);
+ head->dev_class = drm_sysfs_device_add(drm_class, head);
if (IS_ERR(head->dev_class)) {
printk(KERN_ERR
"DRM: Error sysfs_device_add.\n");
@@ -258,11 +217,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
}
if ((ret = drm_get_head(dev, &dev->primary)))
goto err_g1;
-
- /* postinit is a required function to display the signon banner */
- /* drivers add secondary heads here if needed */
- if ((ret = dev->driver->postinit(dev, ent->driver_data)))
- goto err_g1;
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ driver->name, driver->major, driver->minor, driver->patchlevel,
+ driver->date, dev->primary.minor);
return 0;
@@ -318,10 +276,9 @@ int drm_put_head(drm_head_t * head)
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));
+ drm_sysfs_device_remove(head->dev_class);
- *head = (drm_head_t) {
- .dev = NULL};
+ *head = (drm_head_t) {.dev = NULL};
drm_heads[minor] = NULL;
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 6d3449761914..68e43ddc16ae 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -15,8 +15,6 @@
#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"
@@ -28,15 +26,11 @@ struct drm_sysfs_class {
#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
struct simple_dev {
- struct list_head node;
dev_t dev;
struct class_device class_dev;
};
#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-static LIST_HEAD(simple_dev_list);
-static DEFINE_SPINLOCK(simple_dev_list_lock);
-
static void release_simple_dev(struct class_device *class_dev)
{
struct simple_dev *s_dev = to_simple_dev(class_dev);
@@ -124,6 +118,18 @@ void drm_sysfs_destroy(struct drm_sysfs_class *cs)
class_unregister(&cs->class);
}
+static ssize_t show_dri(struct class_device *class_device, char *buf)
+{
+ drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;
+ if (dev->driver->dri_library_name)
+ return dev->driver->dri_library_name(dev, buf);
+ return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
+}
+
+static struct class_device_attribute class_device_attrs[] = {
+ __ATTR(dri_library_name, S_IRUGO, show_dri, NULL),
+};
+
/**
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
* @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
@@ -138,13 +144,11 @@ void drm_sysfs_destroy(struct drm_sysfs_class *cs)
* Note: the struct drm_sysfs_class passed to this function must have previously been
* created with a call to drm_sysfs_create().
*/
-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
- struct device *device,
- const char *fmt, ...)
+struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
+ drm_head_t *head)
{
- va_list args;
struct simple_dev *s_dev = NULL;
- int retval;
+ int i, retval;
if ((cs == NULL) || (IS_ERR(cs))) {
retval = -ENODEV;
@@ -158,26 +162,23 @@ struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
}
memset(s_dev, 0x00, sizeof(*s_dev));
- s_dev->dev = dev;
- s_dev->class_dev.dev = device;
+ s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
+ s_dev->class_dev.dev = &(head->dev->pdev)->dev;
s_dev->class_dev.class = &cs->class;
- va_start(args, fmt);
- vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
- va_end(args);
+ snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
retval = class_device_register(&s_dev->class_dev);
if (retval)
goto error;
class_device_create_file(&s_dev->class_dev, &cs->attr);
+ class_set_devdata(&s_dev->class_dev, head);
- spin_lock(&simple_dev_list_lock);
- list_add(&s_dev->node, &simple_dev_list);
- spin_unlock(&simple_dev_list_lock);
-
+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+ class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
return &s_dev->class_dev;
- error:
+error:
kfree(s_dev);
return ERR_PTR(retval);
}
@@ -189,23 +190,12 @@ struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
* This call unregisters and cleans up a class device that was created with a
* call to drm_sysfs_device_add()
*/
-void drm_sysfs_device_remove(dev_t dev)
+void drm_sysfs_device_remove(struct class_device *class_dev)
{
- struct simple_dev *s_dev = NULL;
- int found = 0;
-
- spin_lock(&simple_dev_list_lock);
- list_for_each_entry(s_dev, &simple_dev_list, node) {
- if (s_dev->dev == dev) {
- found = 1;
- break;
- }
- }
- if (found) {
- list_del(&s_dev->node);
- spin_unlock(&simple_dev_list_lock);
- class_device_unregister(&s_dev->class_dev);
- } else {
- spin_unlock(&simple_dev_list_lock);
- }
+ struct simple_dev *s_dev = to_simple_dev(class_dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+ class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
+ class_device_unregister(&s_dev->class_dev);
}
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index dba502373da1..cc1b89086876 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -114,7 +114,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static struct file_operations i810_buffer_fops = {
.open = drm_open,
- .flush = drm_flush,
.release = drm_release,
.ioctl = drm_ioctl,
.mmap = i810_mmap_buffers,
@@ -1319,12 +1318,24 @@ static int i810_flip_bufs(struct inode *inode, struct file *filp,
return 0;
}
-void i810_driver_pretakedown(drm_device_t * dev)
+int i810_driver_load(drm_device_t *dev, unsigned long flags)
+{
+ /* i810 has 4 more counters */
+ 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;
+
+ return 0;
+}
+
+void i810_driver_lastclose(drm_device_t * dev)
{
i810_dma_cleanup(dev);
}
-void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1334,7 +1345,7 @@ void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void i810_driver_release(drm_device_t * dev, struct file *filp)
+void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
{
i810_reclaim_buffers(dev, filp);
}
@@ -1346,21 +1357,21 @@ int i810_driver_dma_quiescent(drm_device_t * dev)
}
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, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, DRM_AUTH}
};
int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
index 070cef6c2b46..dfe6ad2b6a6e 100644
--- a/drivers/char/drm/i810_drv.c
+++ b/drivers/char/drm/i810_drv.c
@@ -38,38 +38,6 @@
#include "drm_pciids.h"
-static int postinit(struct drm_device *dev, unsigned long flags)
-{
- /* i810 has 4 more counters */
- 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)
- );
- 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[] = {
i810_PCI_IDS
};
@@ -79,16 +47,14 @@ static struct drm_driver driver = {
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,
+ .load = i810_driver_load,
+ .lastclose = i810_driver_lastclose,
+ .preclose = i810_driver_preclose,
.device_is_agp = i810_driver_device_is_agp,
- .release = i810_driver_release,
+ .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
.dma_quiescent = i810_driver_dma_quiescent,
- .reclaim_buffers = i810_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = i810_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -98,13 +64,19 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
- ,
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init i810_init(void)
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index c78f36aaa2f0..a18b80d91920 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -116,9 +116,13 @@ typedef struct drm_i810_private {
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 void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+ struct file *filp);
+extern int i810_driver_load(struct drm_device *, unsigned long flags);
+extern void i810_driver_lastclose(drm_device_t * dev);
+extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+ struct file *filp);
extern int i810_driver_device_is_agp(drm_device_t * dev);
extern drm_ioctl_desc_t i810_ioctls[];
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index dc94f1914425..4fea32aed6d2 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -116,7 +116,6 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static struct file_operations i830_buffer_fops = {
.open = drm_open,
- .flush = drm_flush,
.release = drm_release,
.ioctl = drm_ioctl,
.mmap = i830_mmap_buffers,
@@ -1517,12 +1516,24 @@ static int i830_setparam(struct inode *inode, struct file *filp,
return 0;
}
-void i830_driver_pretakedown(drm_device_t * dev)
+int i830_driver_load(drm_device_t *dev, unsigned long flags)
+{
+ /* i830 has 4 more counters */
+ 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;
+
+ return 0;
+}
+
+void i830_driver_lastclose(drm_device_t * dev)
{
i830_dma_cleanup(dev);
}
-void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void i830_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1532,7 +1543,7 @@ void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void i830_driver_release(drm_device_t * dev, struct file *filp)
+void i830_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
{
i830_reclaim_buffers(dev, filp);
}
@@ -1544,20 +1555,20 @@ int i830_driver_dma_quiescent(drm_device_t * dev)
}
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, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, DRM_AUTH}
};
int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index acd821e8fe4d..722658188f5f 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -40,37 +40,6 @@
#include "drm_pciids.h"
-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)
- );
- 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[] = {
i830_PCI_IDS
};
@@ -83,12 +52,12 @@ static struct drm_driver driver = {
.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,
+ .load = i830_driver_load,
+ .lastclose = i830_driver_lastclose,
+ .preclose = i830_driver_preclose,
.device_is_agp = i830_driver_device_is_agp,
- .release = i830_driver_release,
+ .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked,
.dma_quiescent = i830_driver_dma_quiescent,
- .reclaim_buffers = i830_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
#if USE_IRQS
@@ -97,8 +66,6 @@ static struct drm_driver driver = {
.irq_uninstall = i830_driver_irq_uninstall,
.irq_handler = i830_driver_irq_handler,
#endif
- .postinit = postinit,
- .version = version,
.ioctls = i830_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -108,13 +75,19 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init i830_init(void)
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index bc4bd49fb0cc..bf9075b576bd 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -136,10 +136,12 @@ 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_load(struct drm_device *, unsigned long flags);
+extern void i830_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void i830_driver_lastclose(drm_device_t * dev);
+extern void i830_driver_reclaim_buffers_locked(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)
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index f3aa0c370127..9140703da1ba 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -1,7 +1,6 @@
/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
*/
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -25,7 +24,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#include "drmP.h"
#include "drm.h"
@@ -196,7 +195,7 @@ static int i915_initialize(drm_device_t * dev,
return 0;
}
-static int i915_resume(drm_device_t * dev)
+static int i915_dma_resume(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -253,7 +252,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
retcode = i915_dma_cleanup(dev);
break;
case I915_RESUME_DMA:
- retcode = i915_resume(dev);
+ retcode = i915_dma_resume(dev);
break;
default:
retcode = -EINVAL;
@@ -654,6 +653,9 @@ static int i915_getparam(DRM_IOCTL_ARGS)
case I915_PARAM_ALLOW_BATCHBUFFER:
value = dev_priv->allow_batchbuffer ? 1 : 0;
break;
+ case I915_PARAM_LAST_DISPATCH:
+ value = READ_BREADCRUMB(dev_priv);
+ break;
default:
DRM_ERROR("Unkown parameter %d\n", param.param);
return DRM_ERR(EINVAL);
@@ -699,7 +701,19 @@ static int i915_setparam(DRM_IOCTL_ARGS)
return 0;
}
-void i915_driver_pretakedown(drm_device_t * dev)
+int i915_driver_load(drm_device_t *dev, unsigned long flags)
+{
+ /* i915 has 4 more counters */
+ 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;
+
+ return 0;
+}
+
+void i915_driver_lastclose(drm_device_t * dev)
{
if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -708,7 +722,7 @@ void i915_driver_pretakedown(drm_device_t * dev)
i915_dma_cleanup(dev);
}
-void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -717,18 +731,18 @@ void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
drm_ioctl_desc_t i915_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
+ [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 23e027d29080..77412ddac007 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -1,5 +1,4 @@
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -23,7 +22,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#ifndef _I915_DRM_H_
#define _I915_DRM_H_
@@ -152,6 +151,7 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_IRQ_ACTIVE 1
#define I915_PARAM_ALLOW_BATCHBUFFER 2
+#define I915_PARAM_LAST_DISPATCH 3
typedef struct drm_i915_getparam {
int param;
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 0508240f4e3b..8e2e6095c4b3 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -1,6 +1,6 @@
/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
*/
-/**************************************************************************
+/*
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -25,7 +25,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#include "drmP.h"
#include "drm.h"
@@ -34,48 +34,22 @@
#include "drm_pciids.h"
-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)
- );
- 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[] = {
i915_PCI_IDS
};
static struct drm_driver driver = {
+ /* don't use mtrr's here, the Xserver or user space app should
+ * deal with them for intel hardware.
+ */
.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,
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .load = i915_driver_load,
+ .lastclose = i915_driver_lastclose,
+ .preclose = i915_driver_preclose,
.device_is_agp = i915_driver_device_is_agp,
+ .vblank_wait = i915_driver_vblank_wait,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
@@ -83,8 +57,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = i915_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -97,11 +69,19 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl,
#endif
- },
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init i915_init(void)
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 17e457c73dc7..c6c71b45f101 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -1,6 +1,6 @@
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
-/**************************************************************************
+/*
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -25,7 +25,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#ifndef _I915_DRV_H_
#define _I915_DRV_H_
@@ -37,21 +37,18 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20040405"
+#define DRIVER_DATE "20051209"
/* Interface history:
*
* 1.1: Original.
+ * 1.2: Add Power Management
+ * 1.3: Add vblank support
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 1
+#define DRIVER_MINOR 3
#define DRIVER_PATCHLEVEL 0
-/* We use our own dma mechanisms, not the drm template code. However,
- * the shared IRQ code is useful to us:
- */
-#define __HAVE_PM 1
-
typedef struct _drm_i915_ring_buffer {
int tail_mask;
unsigned long Start;
@@ -97,6 +94,7 @@ typedef struct drm_i915_private {
int tex_lru_log_granularity;
int allow_batchbuffer;
struct mem_block *agp_heap;
+ unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
} drm_i915_private_t;
extern drm_ioctl_desc_t i915_ioctls[];
@@ -104,14 +102,18 @@ 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 int i915_driver_load(struct drm_device *, unsigned long flags);
+extern void i915_driver_lastclose(drm_device_t * dev);
+extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
/* i915_irq.c */
extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
+extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
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);
@@ -125,13 +127,10 @@ extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(drm_device_t * dev,
DRMFILE filp, struct mem_block *heap);
-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)
-#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
+#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
+#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
+#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
+#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
#define I915_VERBOSE 0
@@ -195,6 +194,13 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define PPCR 0x61204
#define PPCR_ON (1<<0)
+#define DVOB 0x61140
+#define DVOB_ON (1<<31)
+#define DVOC 0x61160
+#define DVOC_ON (1<<31)
+#define LVDS 0x61180
+#define LVDS_ON (1<<31)
+
#define ADPA 0x61100
#define ADPA_DPMS_MASK (~(3<<10))
#define ADPA_DPMS_ON (0<<10)
@@ -258,4 +264,6 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define READ_BREADCRUMB(dev_priv) (((u32 *)(dev_priv->hw_status_page))[5])
+
#endif
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
index 2218a946ec87..296248cdc767 100644
--- a/drivers/char/drm/i915_ioc32.c
+++ b/drivers/char/drm/i915_ioc32.c
@@ -30,7 +30,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 4fa448ee846b..a1381c61aa63 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -1,7 +1,6 @@
-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
*/
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -25,16 +24,18 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
-#define USER_INT_FLAG 0x2
+#define USER_INT_FLAG (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+
#define MAX_NOPID ((u32)~0)
-#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
@@ -43,7 +44,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
u16 temp;
temp = I915_READ16(I915REG_INT_IDENTITY_R);
- temp &= USER_INT_FLAG;
+ temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG);
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
@@ -51,7 +52,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
- DRM_WAKEUP(&dev_priv->irq_queue);
+
+ if (temp & USER_INT_FLAG)
+ DRM_WAKEUP(&dev_priv->irq_queue);
+
+ if (temp & VSYNC_PIPEA_FLAG) {
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+ drm_vbl_send_signals(dev);
+ }
return IRQ_HANDLED;
}
@@ -102,6 +111,27 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
return ret;
}
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ 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 i915_irq_emit(DRM_IOCTL_ARGS)
@@ -165,7 +195,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
+ I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index 13176d136a99..ba87ff17ff64 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -1,7 +1,6 @@
/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
*/
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -25,7 +24,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 70dc7f64b7b9..c2a4bac14521 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -44,7 +44,9 @@
#define MGA_DEFAULT_USEC_TIMEOUT 10000
#define MGA_FREELIST_DEBUG 0
-static int mga_do_cleanup_dma(drm_device_t * dev);
+#define MINIMAL_CLEANUP 0
+#define FULL_CLEANUP 1
+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);
/* ================================================================
* Engine control
@@ -391,7 +393,7 @@ int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
* DMA initialization, cleanup
*/
-int mga_driver_preinit(drm_device_t * dev, unsigned long flags)
+int mga_driver_load(drm_device_t * dev, unsigned long flags)
{
drm_mga_private_t *dev_priv;
@@ -405,6 +407,14 @@ int mga_driver_preinit(drm_device_t * dev, unsigned long flags)
dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
dev_priv->chipset = flags;
+ dev_priv->mmio_base = drm_get_resource_start(dev, 1);
+ dev_priv->mmio_size = drm_get_resource_len(dev, 1);
+
+ dev->counters += 3;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+
return 0;
}
@@ -438,17 +448,19 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
drm_buf_desc_t req;
drm_agp_mode_t mode;
drm_agp_info_t info;
+ drm_agp_buffer_t agp_req;
+ drm_agp_binding_t bind_req;
/* Acquire AGP. */
err = drm_agp_acquire(dev);
if (err) {
- DRM_ERROR("Unable to acquire AGP\n");
+ DRM_ERROR("Unable to acquire AGP: %d\n", err);
return err;
}
err = drm_agp_info(dev, &info);
if (err) {
- DRM_ERROR("Unable to get AGP info\n");
+ DRM_ERROR("Unable to get AGP info: %d\n", err);
return err;
}
@@ -472,18 +484,24 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
}
/* 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;
+ agp_req.size = agp_size;
+ agp_req.type = 0;
+ err = drm_agp_alloc(dev, &agp_req);
+ if (err) {
+ dev_priv->agp_size = 0;
DRM_ERROR("Unable to allocate %uMB AGP memory\n",
dma_bs->agp_size);
- return DRM_ERR(ENOMEM);
+ return err;
}
+
+ dev_priv->agp_size = agp_size;
+ dev_priv->agp_handle = agp_req.handle;
- err = drm_bind_agp(dev_priv->agp_mem, 0);
+ bind_req.handle = agp_req.handle;
+ bind_req.offset = 0;
+ err = drm_agp_bind(dev, &bind_req);
if (err) {
- DRM_ERROR("Unable to bind AGP memory\n");
+ DRM_ERROR("Unable to bind AGP memory: %d\n", err);
return err;
}
@@ -497,7 +515,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map WARP microcode: %d\n", err);
return err;
}
@@ -505,7 +523,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map primary DMA region: %d\n", err);
return err;
}
@@ -513,7 +531,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
return err;
}
@@ -525,15 +543,29 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
err = drm_addbufs_agp(dev, &req);
if (err) {
- DRM_ERROR("Unable to add secondary DMA buffers\n");
+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
return err;
}
+ {
+ drm_map_list_t *_entry;
+ unsigned long agp_token = 0;
+
+ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->map == dev->agp_buffer_map)
+ agp_token = _entry->user_token;
+ }
+ if (!agp_token)
+ return -EFAULT;
+
+ dev->agp_buffer_token = agp_token;
+ }
+
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");
+ DRM_ERROR("Unable to map AGP texture region %d\n", err);
return err;
}
@@ -603,7 +635,8 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
+ err);
return err;
}
@@ -622,7 +655,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
}
if (err != 0) {
- DRM_ERROR("Unable to allocate primary DMA region\n");
+ DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
return DRM_ERR(ENOMEM);
}
@@ -646,7 +679,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
}
if (bin_count == 0) {
- DRM_ERROR("Unable to add secondary DMA buffers\n");
+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
return err;
}
@@ -682,7 +715,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map MMIO region: %d\n", err);
return err;
}
@@ -690,7 +723,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
_DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
&dev_priv->status);
if (err) {
- DRM_ERROR("Unable to map status region\n");
+ DRM_ERROR("Unable to map status region: %d\n", err);
return err;
}
@@ -708,7 +741,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
*/
if (err) {
- mga_do_cleanup_dma(dev);
+ mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
}
/* Not only do we want to try and initialized PCI cards for PCI DMA,
@@ -731,35 +764,32 @@ int mga_dma_bootstrap(DRM_IOCTL_ARGS)
DRM_DEVICE;
drm_mga_dma_bootstrap_t bootstrap;
int 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;
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;
- }
+ if (err) {
+ mga_do_cleanup_dma(dev, FULL_CLEANUP);
+ return err;
+ }
- bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
- if (DRM_COPY_TO_USER((void __user *)data, &bootstrap,
- sizeof(bootstrap))) {
- err = DRM_ERR(EFAULT);
- }
+ if (dev_priv->agp_textures != NULL) {
+ bootstrap.texture_handle = dev_priv->agp_textures->offset;
+ bootstrap.texture_size = dev_priv->agp_textures->size;
} else {
- mga_do_cleanup_dma(dev);
+ bootstrap.texture_handle = 0;
+ bootstrap.texture_size = 0;
}
+ bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
+ DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,
+ bootstrap, sizeof(bootstrap));
+
return err;
}
@@ -853,13 +883,13 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
ret = mga_warp_install_microcode(dev_priv);
if (ret < 0) {
- DRM_ERROR("failed to install WARP ucode!\n");
+ DRM_ERROR("failed to install WARP ucode!: %d\n", ret);
return ret;
}
ret = mga_warp_init(dev_priv);
if (ret < 0) {
- DRM_ERROR("failed to init WARP engine!\n");
+ DRM_ERROR("failed to init WARP engine!: %d\n", ret);
return ret;
}
@@ -904,7 +934,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
return 0;
}
-static int mga_do_cleanup_dma(drm_device_t * dev)
+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)
{
int err = 0;
DRM_DEBUG("\n");
@@ -932,31 +962,39 @@ static int mga_do_cleanup_dma(drm_device_t * 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);
+ if (dev_priv->agp_handle != 0) {
+ drm_agp_binding_t unbind_req;
+ drm_agp_buffer_t free_req;
+
+ unbind_req.handle = dev_priv->agp_handle;
+ drm_agp_unbind(dev, &unbind_req);
- drm_free_agp(dev_priv->agp_mem,
- dev_priv->agp_pages);
- dev_priv->agp_pages = 0;
- dev_priv->agp_mem = NULL;
+ free_req.handle = dev_priv->agp_handle;
+ drm_agp_free(dev, &free_req);
+
+ dev_priv->agp_textures = NULL;
+ dev_priv->agp_size = 0;
+ dev_priv->agp_handle = 0;
}
if ((dev->agp != NULL) && dev->agp->acquired) {
err = drm_agp_release(dev);
}
#endif
- dev_priv->used_new_dma_init = 0;
}
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;
+ if (full_cleanup) {
+ dev_priv->mmio = NULL;
+ dev_priv->status = NULL;
+ dev_priv->used_new_dma_init = 0;
+ }
+
memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
dev_priv->warp_pipe = 0;
memset(dev_priv->warp_pipe_phys, 0,
@@ -967,7 +1005,7 @@ static int mga_do_cleanup_dma(drm_device_t * dev)
}
}
- return err;
+ return 0;
}
int mga_dma_init(DRM_IOCTL_ARGS)
@@ -985,11 +1023,11 @@ int mga_dma_init(DRM_IOCTL_ARGS)
case MGA_INIT_DMA:
err = mga_do_init_dma(dev, &init);
if (err) {
- (void)mga_do_cleanup_dma(dev);
+ (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
return err;
case MGA_CLEANUP_DMA:
- return mga_do_cleanup_dma(dev);
+ return mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
return DRM_ERR(EINVAL);
@@ -1118,7 +1156,7 @@ int mga_dma_buffers(DRM_IOCTL_ARGS)
/**
* Called just before the module is unloaded.
*/
-int mga_driver_postcleanup(drm_device_t * dev)
+int mga_driver_unload(drm_device_t * dev)
{
drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
dev->dev_private = NULL;
@@ -1129,9 +1167,9 @@ int mga_driver_postcleanup(drm_device_t * dev)
/**
* Called when the last opener of the device is closed.
*/
-void mga_driver_pretakedown(drm_device_t * dev)
+void mga_driver_lastclose(drm_device_t * dev)
{
- mga_do_cleanup_dma(dev);
+ mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
int mga_driver_dma_quiescent(drm_device_t * dev)
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 1713451a5cc6..9f7ed0e0351b 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -38,41 +38,6 @@
#include "drm_pciids.h"
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)
- );
- 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[] = {
mga_PCI_IDS
@@ -80,12 +45,12 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = {
.driver_features =
- DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_IRQ_VBL,
- .preinit = mga_driver_preinit,
- .postcleanup = mga_driver_postcleanup,
- .pretakedown = mga_driver_pretakedown,
+ .load = mga_driver_load,
+ .unload = mga_driver_unload,
+ .lastclose = mga_driver_lastclose,
.dma_quiescent = mga_driver_dma_quiescent,
.device_is_agp = mga_driver_device_is_agp,
.vblank_wait = mga_driver_vblank_wait,
@@ -96,8 +61,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = mga_ioctls,
.dma_ioctl = mga_dma_buffers,
.fops = {
@@ -113,9 +76,16 @@ static struct drm_driver driver = {
#endif
},
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init mga_init(void)
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 461728e6a58a..6b0c53193506 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -38,11 +38,11 @@
#define DRIVER_NAME "mga"
#define DRIVER_DESC "Matrox G200/G400"
-#define DRIVER_DATE "20050607"
+#define DRIVER_DATE "20051102"
#define DRIVER_MAJOR 3
#define DRIVER_MINOR 2
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_PATCHLEVEL 1
typedef struct drm_mga_primary_buffer {
u8 *start;
@@ -144,22 +144,22 @@ typedef struct drm_mga_private {
drm_local_map_t *primary;
drm_local_map_t *agp_textures;
- DRM_AGP_MEM *agp_mem;
- unsigned int agp_pages;
+ unsigned long agp_handle;
+ unsigned int agp_size;
} drm_mga_private_t;
extern drm_ioctl_desc_t mga_ioctls[];
extern int mga_max_ioctl;
/* mga_dma.c */
-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_load(drm_device_t *dev, unsigned long flags);
+extern int mga_driver_unload(drm_device_t * dev);
+extern void mga_driver_lastclose(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);
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
index 24a9d4e86af0..54a18eb2fc04 100644
--- a/drivers/char/drm/mga_ioc32.c
+++ b/drivers/char/drm/mga_ioc32.c
@@ -31,7 +31,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 47f54b5ae956..2837e669183a 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -1127,19 +1127,19 @@ static int mga_wait_fence(DRM_IOCTL_ARGS)
}
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_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},
+ [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
};
int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 7452753d4d01..db5a60450e68 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -1,6 +1,7 @@
-/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
+/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
- *
+ */
+/*
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -559,7 +560,8 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
if (dev_priv->is_pci) {
#endif
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.addr = NULL;
+ 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");
@@ -601,15 +603,16 @@ int r128_do_cleanup_cce(drm_device_t * dev)
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)
+ if (dev->agp_buffer_map != NULL) {
drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ dev->agp_buffer_map = NULL;
+ }
} else
#endif
{
if (dev_priv->gart_info.bus_addr)
if (!drm_ati_pcigart_cleanup(dev,
- &dev_priv->
- gart_info))
+ &dev_priv->gart_info))
DRM_ERROR
("failed to cleanup PCI GART!\n");
}
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 5ddc03202411..5d835b006f55 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -1,7 +1,7 @@
/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ */
+/* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index 1661e7351402..e20450ae220e 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -37,31 +37,6 @@
#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[] = {
r128_PCI_IDS
};
@@ -72,8 +47,8 @@ static struct drm_driver driver = {
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,
+ .preclose = r128_driver_preclose,
+ .lastclose = r128_driver_lastclose,
.vblank_wait = r128_driver_vblank_wait,
.irq_preinstall = r128_driver_irq_preinstall,
.irq_postinstall = r128_driver_irq_postinstall,
@@ -82,8 +57,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = r128_ioctls,
.dma_ioctl = r128_cce_buffers,
.fops = {
@@ -97,12 +70,19 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = r128_compat_ioctl,
#endif
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init r128_init(void)
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 5c79e40eb88f..94abffb2cca5 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -1,7 +1,7 @@
/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
* Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ */
+/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
@@ -154,8 +154,8 @@ 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 void r128_driver_lastclose(drm_device_t * dev);
+extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
index 1e2e367b8b82..9dd6d4116e47 100644
--- a/drivers/char/drm/r128_ioc32.c
+++ b/drivers/char/drm/r128_ioc32.c
@@ -30,7 +30,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 27eb0e31bd3b..87f8ca2b0685 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -1,5 +1,5 @@
-/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
- *
+/* 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
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 14479cc08a57..a080cdd6081e 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -1,7 +1,7 @@
/* r128_state.c -- State support for r128 -*- linux-c -*-
* Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ */
+/* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -220,7 +220,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
ADVANCE_RING();
}
-static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv)
+static 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;
@@ -1674,7 +1674,7 @@ static int r128_getparam(DRM_IOCTL_ARGS)
return 0;
}
-void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1684,29 +1684,29 @@ void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void r128_driver_pretakedown(drm_device_t * dev)
+void r128_driver_lastclose(drm_device_t * 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, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH},
};
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
index 3a1ac5f78b43..291dbf4c8186 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -52,8 +52,8 @@ static const int r300_cliprect_cntl[4] = {
* 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)
+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;
@@ -216,6 +216,7 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_TX_UNK1_0, 16);
ADD_RANGE(R300_TX_SIZE_0, 16);
ADD_RANGE(R300_TX_FORMAT_0, 16);
+ ADD_RANGE(R300_TX_PITCH_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);
@@ -242,7 +243,7 @@ static __inline__ int r300_check_range(unsigned reg, int count)
/* 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,
+static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
u32 offset)
{
/* we realy want to check against end of video aperture
@@ -317,8 +318,8 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
*
* 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,
+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;
@@ -363,8 +364,8 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,
* 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,
+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;
@@ -400,8 +401,8 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,
* 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)
+static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
RING_LOCALS;
@@ -421,8 +422,8 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
- drm_radeon_kcmd_buffer_t * cmdbuf,
+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;
@@ -489,8 +490,8 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
u32 header;
int count;
@@ -554,8 +555,8 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
* 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,
+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;
@@ -623,7 +624,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,
/**
* Emit the sequence to pacify R300.
*/
-static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv)
+static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
{
RING_LOCALS;
@@ -657,9 +658,10 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
* commands on the DMA ring buffer.
* Called by the ioctl handler function radeon_cp_cmdbuf.
*/
-int r300_do_cp_cmdbuf(drm_device_t * dev,
+int r300_do_cp_cmdbuf(drm_device_t *dev,
DRMFILE filp,
- drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf)
+ 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;
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index e5b73c002394..a0ed20e25221 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -797,6 +797,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_FORMAT_YUV_MODE 0x00800000
+#define R300_TX_PITCH_0 0x4500
#define R300_TX_OFFSET_0 0x4540
/* BEGIN: Guess from R200 */
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 342302d46743..915665c7fe7c 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1,5 +1,5 @@
-/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
- *
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
+/*
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* All Rights Reserved.
@@ -824,7 +824,7 @@ 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)
+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);
@@ -1125,7 +1125,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
| (dev_priv->fb_location >> 16));
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
RADEON_WRITE(RADEON_MC_AGP_LOCATION,
(((dev_priv->gart_vm_start - 1 +
dev_priv->gart_size) & 0xffff0000) |
@@ -1152,7 +1152,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
dev_priv->ring.tail = cur_read_ptr;
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* 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,
@@ -1278,13 +1278,15 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
/* Enable or disable PCI GART on the chip */
static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
{
- u32 tmp = RADEON_READ(RADEON_AIC_CNTL);
+ u32 tmp;
if (dev_priv->flags & CHIP_IS_PCIE) {
radeon_set_pciegart(dev_priv, on);
return;
}
+ tmp = RADEON_READ(RADEON_AIC_CNTL);
+
if (on) {
RADEON_WRITE(RADEON_AIC_CNTL,
tmp | RADEON_PCIGART_TRANSLATE_EN);
@@ -1312,13 +1314,17 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
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");
- dev_priv->is_pci = init->is_pci;
+ if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
+ {
+ DRM_DEBUG("Forcing AGP card to PCI mode\n");
+ dev_priv->flags &= ~CHIP_IS_AGP;
+ }
- if (dev_priv->is_pci && !dev->sg) {
+ if ((!(dev_priv->flags & CHIP_IS_AGP)) && !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);
}
@@ -1327,12 +1333,11 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
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;
break;
@@ -1353,7 +1358,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
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);
}
@@ -1416,8 +1420,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
DRM_GETSAREA();
- dev_priv->fb_offset = init->fb_offset;
- dev_priv->mmio_offset = init->mmio_offset;
dev_priv->ring_offset = init->ring_offset;
dev_priv->ring_rptr_offset = init->ring_rptr_offset;
dev_priv->buffers_offset = init->buffers_offset;
@@ -1425,29 +1427,19 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
- 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) {
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) {
DRM_ERROR("could not find ring read pointer!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1455,7 +1447,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
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");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1465,7 +1456,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
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);
return DRM_ERR(EINVAL);
}
@@ -1476,7 +1466,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
init->sarea_priv_offset);
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
drm_core_ioremap(dev_priv->cp_ring, dev);
drm_core_ioremap(dev_priv->ring_rptr, dev);
drm_core_ioremap(dev->agp_buffer_map, dev);
@@ -1484,7 +1474,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
!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);
return DRM_ERR(EINVAL);
}
@@ -1525,7 +1514,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+ RADEON_READ(RADEON_CONFIG_APER_SIZE);
#if __OS_HAS_AGP
- if (!dev_priv->is_pci)
+ if (dev_priv->flags & CHIP_IS_AGP)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- dev->agp->base
+ dev_priv->gart_vm_start);
@@ -1551,7 +1540,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
} else
@@ -1561,25 +1550,28 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (dev_priv->pcigart_offset) {
dev_priv->gart_info.bus_addr =
dev_priv->pcigart_offset + dev_priv->fb_location;
+ dev_priv->gart_info.mapping.offset =
+ dev_priv->gart_info.bus_addr;
+ dev_priv->gart_info.mapping.size =
+ RADEON_PCIGART_TABLE_SIZE;
+
+ drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr =
- (unsigned long)drm_ioremap(dev_priv->gart_info.
- bus_addr,
- RADEON_PCIGART_TABLE_SIZE,
- dev);
+ dev_priv->gart_info.mapping.handle;
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",
+ DRM_DEBUG("Setting phys_pci_gart to %p %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;
+ dev_priv->gart_info.addr = NULL;
+ 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");
@@ -1590,7 +1582,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
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);
}
@@ -1604,8 +1595,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->last_buf = 0;
- dev->dev_private = (void *)dev_priv;
-
radeon_do_engine_reset(dev);
return 0;
@@ -1624,11 +1613,15 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
drm_irq_uninstall(dev);
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
- if (dev_priv->cp_ring != NULL)
+ if (dev_priv->flags & CHIP_IS_AGP) {
+ if (dev_priv->cp_ring != NULL) {
drm_core_ioremapfree(dev_priv->cp_ring, dev);
- if (dev_priv->ring_rptr != NULL)
+ dev_priv->cp_ring = NULL;
+ }
+ if (dev_priv->ring_rptr != NULL) {
drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+ dev_priv->ring_rptr = NULL;
+ }
if (dev->agp_buffer_map != NULL) {
drm_core_ioremapfree(dev->agp_buffer_map, dev);
dev->agp_buffer_map = NULL;
@@ -1636,17 +1629,20 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
} else
#endif
{
- if (dev_priv->gart_info.bus_addr)
+
+ if (dev_priv->gart_info.bus_addr) {
+ /* Turn off PCI GART */
+ radeon_set_pcigart(dev_priv, 0);
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);
+ if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
+ {
+ drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr = 0;
}
}
-
/* only clear to the start of flags */
memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
@@ -1672,7 +1668,7 @@ static int radeon_do_resume_cp(drm_device_t * dev)
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
} else
@@ -2103,7 +2099,7 @@ int radeon_cp_buffers(DRM_IOCTL_ARGS)
return ret;
}
-int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
+int radeon_driver_load(struct drm_device *dev, unsigned long flags)
{
drm_radeon_private_t *dev_priv;
int ret = 0;
@@ -2136,11 +2132,14 @@ int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
dev_priv->flags |= CHIP_IS_PCIE;
DRM_DEBUG("%s card detected\n",
- ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));
return ret;
}
-int radeon_presetup(struct drm_device *dev)
+/* Create mappings for registers and framebuffer so userland doesn't necessarily
+ * have to find them.
+ */
+int radeon_driver_firstopen(struct drm_device *dev)
{
int ret;
drm_local_map_t *map;
@@ -2161,12 +2160,11 @@ int radeon_presetup(struct drm_device *dev)
return 0;
}
-int radeon_driver_postcleanup(struct drm_device *dev)
+int radeon_driver_unload(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n");
-
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
dev->dev_private = NULL;
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 1cd81a671a36..9c177a6b2a4c 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -624,6 +624,11 @@ typedef struct drm_radeon_indirect {
int discard;
} drm_radeon_indirect_t;
+/* enum for card type parameters */
+#define RADEON_CARD_PCI 0
+#define RADEON_CARD_AGP 1
+#define RADEON_CARD_PCIE 2
+
/* 1.3: An ioctl to get parameters that aren't available to the 3d
* client any other way.
*/
@@ -640,6 +645,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_SAREA_HANDLE 9
#define RADEON_PARAM_GART_TEX_HANDLE 10
#define RADEON_PARAM_SCRATCH_OFFSET 11
+#define RADEON_PARAM_CARD_TYPE 12
typedef struct drm_radeon_getparam {
int param;
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index ee49670d8162..b04ed1b562b9 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -42,29 +42,15 @@ 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)
+static int dri_library_name(struct drm_device *dev, char *buf)
{
- 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;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int family = dev_priv->flags & CHIP_FAMILY_MASK;
- 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;
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ (family < CHIP_R200) ? "radeon" :
+ ((family < CHIP_R300) ? "r200" :
+ "r300"));
}
static struct pci_device_id pciidlist[] = {
@@ -77,23 +63,22 @@ static struct drm_driver driver = {
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,
- .open_helper = radeon_driver_open_helper,
+ .load = radeon_driver_load,
+ .firstopen = radeon_driver_firstopen,
+ .open = radeon_driver_open,
+ .preclose = radeon_driver_preclose,
+ .postclose = radeon_driver_postclose,
+ .lastclose = radeon_driver_lastclose,
+ .unload = radeon_driver_unload,
.vblank_wait = radeon_driver_vblank_wait,
+ .dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall,
.irq_uninstall = radeon_driver_irq_uninstall,
.irq_handler = radeon_driver_irq_handler,
- .free_filp_priv = radeon_driver_free_filp_priv,
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = radeon_ioctls,
.dma_ioctl = radeon_cp_buffers,
.fops = {
@@ -107,12 +92,19 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = radeon_compat_ioctl,
#endif
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init radeon_init(void)
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index d92ccee3e54c..498b19b1d641 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 "20050911"
+#define DRIVER_DATE "20051229"
/* Interface history:
*
@@ -73,7 +73,7 @@
* 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
* and GL_EXT_blend_[func|equation]_separate on r200
* 1.12- Add R300 CP microcode support - this just loads the CP on r300
- * (No 3D support yet - just microcode loading)
+ * (No 3D support yet - just microcode loading).
* 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
* - Add hyperz support, add hyperz flags to clear ioctl.
* 1.14- Add support for color tiling
@@ -88,14 +88,13 @@
* 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
+ * 1.20- Add support for r300 texrect
+ * 1.21- Add support for card type getparam
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 19
+#define DRIVER_MINOR 21
#define DRIVER_PATCHLEVEL 0
-#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
-#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
-
/*
* Radeon chip families
*/
@@ -103,8 +102,8 @@ enum radeon_family {
CHIP_R100,
CHIP_RS100,
CHIP_RV100,
- CHIP_R200,
CHIP_RV200,
+ CHIP_R200,
CHIP_RS200,
CHIP_R250,
CHIP_RS250,
@@ -138,6 +137,9 @@ enum radeon_chip_flags {
CHIP_IS_PCIE = 0x00200000UL,
};
+#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
+#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
+
typedef struct drm_radeon_freelist {
unsigned int age;
drm_buf_t *buf;
@@ -245,8 +247,6 @@ typedef struct drm_radeon_private {
drm_radeon_depth_clear_t depth_clear;
- unsigned long fb_offset;
- unsigned long mmio_offset;
unsigned long ring_offset;
unsigned long ring_rptr_offset;
unsigned long buffers_offset;
@@ -273,7 +273,6 @@ typedef struct drm_radeon_private {
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
- int is_pci;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
@@ -330,17 +329,14 @@ 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_driver_load(struct drm_device *dev, unsigned long flags);
+extern int radeon_driver_unload(struct drm_device *dev);
+extern int radeon_driver_firstopen(struct drm_device *dev);
+extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
+extern void radeon_driver_lastclose(drm_device_t * dev);
+extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@@ -364,6 +360,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
*/
#define RADEON_AGP_COMMAND 0x0f60
+#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */
+# define RADEON_AGP_ENABLE (1<<8)
#define RADEON_AUX_SCISSOR_CNTL 0x26f0
# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24)
# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25)
@@ -651,6 +649,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
#define RADEON_WAIT_UNTIL 0x1720
# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
+# define RADEON_WAIT_2D_IDLE (1 << 14)
+# define RADEON_WAIT_3D_IDLE (1 << 15)
# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
@@ -1105,7 +1105,6 @@ do { \
write = 0; \
_tab += _i; \
} \
- \
while (_size > 0) { \
*(ring + write) = *_tab++; \
write++; \
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index fef4a2b84c1e..0ccfd3618ff1 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 231ac1438c69..7bc27516d425 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -1,5 +1,5 @@
-/* radeon_state.c -- State support for Radeon -*- linux-c -*-
- *
+/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
+/*
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* All Rights Reserved.
*
@@ -72,10 +72,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case RADEON_EMIT_PP_MISC:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
- &data[(RADEON_RB3D_DEPTHOFFSET
- -
- RADEON_PP_MISC) /
- 4])) {
+ &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
DRM_ERROR("Invalid depth buffer offset\n");
return DRM_ERR(EINVAL);
}
@@ -83,10 +80,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case RADEON_EMIT_PP_CNTL:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
- &data[(RADEON_RB3D_COLOROFFSET
- -
- RADEON_PP_CNTL) /
- 4])) {
+ &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
DRM_ERROR("Invalid colour buffer offset\n");
return DRM_ERR(EINVAL);
}
@@ -109,10 +103,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
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])) {
+ &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
DRM_ERROR("Invalid R100 texture offset\n");
return DRM_ERR(EINVAL);
}
@@ -126,8 +117,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
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])) {
+ if (radeon_check_and_fixup_offset(dev_priv,
+ filp_priv,
+ &data[i])) {
DRM_ERROR
("Invalid R200 cubic texture offset\n");
return DRM_ERR(EINVAL);
@@ -239,8 +231,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
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,
+ drm_file_t *filp_priv,
+ drm_radeon_kcmd_buffer_t *
+ cmdbuf,
unsigned int *cmdsz)
{
u32 *cmd = (u32 *) cmdbuf->buf;
@@ -555,7 +548,8 @@ static struct {
{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_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"},
@@ -569,7 +563,7 @@ static struct {
{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_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"},
@@ -592,7 +586,7 @@ static struct {
{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_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"},
@@ -985,8 +979,8 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
* rendering a quad into just those buffers. Thus, we have to
* make sure the 3D engine is configured correctly.
*/
- if ((dev_priv->microcode_version == UCODE_R200) &&
- (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+ else if ((dev_priv->microcode_version == UCODE_R200) &&
+ (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
int tempPP_CNTL;
int tempRE_CNTL;
@@ -1637,6 +1631,14 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
(u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
dwords = size / 4;
+#define RADEON_COPY_MT(_buf, _data, _width) \
+ do { \
+ if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+ DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
+ return DRM_ERR(EFAULT); \
+ } \
+ } while(0)
+
if (microtile) {
/* texture micro tiling in use, minimum texture width is thus 16 bytes.
however, we cannot use blitter directly for texture width < 64 bytes,
@@ -1648,46 +1650,19 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
from user space. */
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);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data,
+ (int)(tex_width * sizeof(u32)));
} else if (tex_width == 32) {
- 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);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, 16);
+ RADEON_COPY_MT(buffer + 8,
+ data + 16, 16);
}
} else if (tex_width >= 64 || tex_width == 16) {
- if (DRM_COPY_FROM_USER(buffer, data,
- dwords * sizeof(u32))) {
- DRM_ERROR("EFAULT on data, %d dwords\n",
- dwords);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data,
+ (int)(dwords * sizeof(u32)));
} 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);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, tex_width);
buffer += 4;
data += tex_width;
}
@@ -1695,37 +1670,13 @@ 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);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, 16);
data += 16;
- if (DRM_COPY_FROM_USER
- (buffer + 8, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer + 8, data, 16);
data += 16;
- if (DRM_COPY_FROM_USER
- (buffer + 4, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer + 4, data, 16);
data += 16;
- if (DRM_COPY_FROM_USER
- (buffer + 12, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer + 12, data, 16);
data += 16;
buffer += 16;
}
@@ -1735,31 +1686,22 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
/* Texture image width is larger than the minimum, so we
* can upload it directly.
*/
- if (DRM_COPY_FROM_USER(buffer, data,
- dwords * sizeof(u32))) {
- DRM_ERROR("EFAULT on data, %d dwords\n",
- dwords);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data,
+ (int)(dwords * sizeof(u32)));
} else {
/* Texture image width is less than the minimum, so we
* 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);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, tex_width);
buffer += 8;
data += tex_width;
}
}
}
+#undef RADEON_COPY_MT
buf->filp = filp;
buf->used = size;
offset = dev_priv->gart_buffers_offset + buf->offset;
@@ -1821,7 +1763,7 @@ static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
}
static void radeon_apply_surface_regs(int surf_index,
- drm_radeon_private_t * dev_priv)
+ drm_radeon_private_t *dev_priv)
{
if (!dev_priv->mmio)
return;
@@ -1847,8 +1789,8 @@ static void radeon_apply_surface_regs(int surf_index,
* 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;
@@ -2158,6 +2100,11 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
+ 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_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
@@ -2596,9 +2543,9 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
drm_radeon_cmd_header_t header,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int sz = header.scalars.count;
int start = header.scalars.offset;
@@ -2618,9 +2565,9 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
/* God this is ugly
*/
-static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
drm_radeon_cmd_header_t header,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int sz = header.scalars.count;
int start = ((unsigned int)header.scalars.offset) + 0x100;
@@ -2638,9 +2585,9 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
drm_radeon_cmd_header_t header,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int sz = header.vectors.count;
int start = header.vectors.offset;
@@ -2685,8 +2632,8 @@ 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,
+static int radeon_emit_packet3_cliprect(drm_device_t *dev,
+ drm_file_t *filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf,
int orig_nbox)
{
@@ -2818,7 +2765,8 @@ 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, (void __user *)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);
}
@@ -2981,7 +2929,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
value = dev_priv->gart_vm_start;
break;
case RADEON_PARAM_REGISTER_HANDLE:
- value = dev_priv->mmio_offset;
+ value = dev_priv->mmio->offset;
break;
case RADEON_PARAM_STATUS_HANDLE:
value = dev_priv->ring_rptr_offset;
@@ -3004,6 +2952,15 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
case RADEON_PARAM_GART_TEX_HANDLE:
value = dev_priv->gart_textures_offset;
break;
+
+ case RADEON_PARAM_CARD_TYPE:
+ if (dev_priv->flags & CHIP_IS_PCIE)
+ value = RADEON_CARD_PCIE;
+ else if (dev_priv->flags & CHIP_IS_AGP)
+ value = RADEON_CARD_AGP;
+ else
+ value = RADEON_CARD_PCI;
+ break;
default:
return DRM_ERR(EINVAL);
}
@@ -3066,10 +3023,11 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
/* When a client dies:
* - Check for and clean up flipped page state
* - Free any alloced GART memory.
+ * - Free any alloced radeon surfaces.
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/
-void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3082,16 +3040,17 @@ void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void radeon_driver_pretakedown(drm_device_t * dev)
+void radeon_driver_lastclose(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(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;
+ DRM_DEBUG("\n");
radeon_priv =
(struct drm_radeon_driver_file_fields *)
drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
@@ -3100,6 +3059,7 @@ int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
return -ENOMEM;
filp_priv->driver_priv = radeon_priv;
+
if (dev_priv)
radeon_priv->radeon_fb_delta = dev_priv->fb_location;
else
@@ -3107,7 +3067,7 @@ int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
return 0;
}
-void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
{
struct drm_radeon_driver_file_fields *radeon_priv =
filp_priv->driver_priv;
@@ -3116,33 +3076,33 @@ void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
}
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, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH}
};
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
index 6d10515795cc..0d426deeefec 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -533,16 +533,32 @@ static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
}
+int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+ drm_savage_private_t *dev_priv;
+
+ 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;
+
+ return 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.
+ * in drm_addmap. Therefore we add them manually before the maps are
+ * initialized, and tear them down on last close.
*/
-int savage_preinit(drm_device_t * dev, unsigned long chipset)
+int savage_driver_firstopen(drm_device_t *dev)
{
- drm_savage_private_t *dev_priv;
+ drm_savage_private_t *dev_priv = dev->dev_private;
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
@@ -551,14 +567,6 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
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;
@@ -576,26 +584,24 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
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);
+ drm_mtrr_add(dev_priv->mtrr[0].base,
+ dev_priv->mtrr[0].size, DRM_MTRR_WC);
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);
+ drm_mtrr_add(dev_priv->mtrr[1].base,
+ dev_priv->mtrr[1].size, DRM_MTRR_WC);
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);
+ drm_mtrr_add(dev_priv->mtrr[2].base,
+ dev_priv->mtrr[2].size, DRM_MTRR_WC);
} else {
DRM_ERROR("strange pci_resource_len %08lx\n",
drm_get_resource_len(dev, 0));
}
- } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
+ } else if (dev_priv->chipset != S3_SUPERSAVAGE &&
+ dev_priv->chipset != S3_SAVAGE2000) {
mmio_base = drm_get_resource_start(dev, 0);
fb_rsrc = 1;
fb_base = drm_get_resource_start(dev, 1);
@@ -609,9 +615,8 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
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);
+ drm_mtrr_add(dev_priv->mtrr[0].base,
+ dev_priv->mtrr[0].size, DRM_MTRR_WC);
} else {
DRM_ERROR("strange pci_resource_len %08lx\n",
drm_get_resource_len(dev, 1));
@@ -648,16 +653,21 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
/*
* Delete MTRRs and free device-private data.
*/
-int savage_postcleanup(drm_device_t * dev)
+void savage_driver_lastclose(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,
+ drm_mtrr_del(dev_priv->mtrr[i].handle,
dev_priv->mtrr[i].base,
- dev_priv->mtrr[i].size);
+ dev_priv->mtrr[i].size, DRM_MTRR_WC);
+}
+
+int savage_driver_unload(drm_device_t *dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
@@ -994,8 +1004,7 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS)
* DMA buffer management
*/
-static int savage_bci_get_buffers(DRMFILE filp, drm_device_t * dev,
- drm_dma_t * d)
+static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
{
drm_buf_t *buf;
int i;
@@ -1057,7 +1066,7 @@ int savage_bci_buffers(DRM_IOCTL_ARGS)
return ret;
}
-void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp)
+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;
@@ -1090,10 +1099,10 @@ void savage_reclaim_buffers(drm_device_t * dev, DRMFILE 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},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH},
};
int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c
index 22d799cde41c..aa6c0d1a82f8 100644
--- a/drivers/char/drm/savage_drv.c
+++ b/drivers/char/drm/savage_drv.c
@@ -30,31 +30,6 @@
#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
};
@@ -63,13 +38,13 @@ 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,
+ .load = savage_driver_load,
+ .firstopen = savage_driver_firstopen,
+ .lastclose = savage_driver_lastclose,
+ .unload = savage_driver_unload,
.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 = {
@@ -80,12 +55,19 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init savage_init(void)
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index a4b0fa998a95..dd46cb85439c 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -1,5 +1,5 @@
-/* savage_drv.h -- Private header for the savage driver
- *
+/* savage_drv.h -- Private header for the savage driver */
+/*
* Copyright 2004 Felix Kuehling
* All Rights Reserved.
*
@@ -192,7 +192,7 @@ typedef struct drm_savage_private {
/* 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);
+ const drm_clip_rect_t * pbox);
void (*dma_flush) (struct drm_savage_private * dev_priv);
} drm_savage_private_t;
@@ -208,16 +208,18 @@ 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_driver_load(drm_device_t *dev, unsigned long chipset);
+extern int savage_driver_firstopen(drm_device_t *dev);
+extern void savage_driver_lastclose(drm_device_t *dev);
+extern int savage_driver_unload(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);
+ const drm_clip_rect_t * pbox);
extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
- drm_clip_rect_t * pbox);
+ const drm_clip_rect_t * pbox);
#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
@@ -500,15 +502,6 @@ extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
#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
*/
@@ -534,8 +527,8 @@ extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
#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); \
+#define DMA_COPY(src, n) do { \
+ memcpy(dma_ptr, (src), (n)*4); \
dma_ptr += n; \
} while(0)
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
index e87a5d59b99c..ef2581d16146 100644
--- a/drivers/char/drm/savage_state.c
+++ b/drivers/char/drm/savage_state.c
@@ -27,7 +27,7 @@
#include "savage_drv.h"
void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
- drm_clip_rect_t * pbox)
+ const drm_clip_rect_t * pbox)
{
uint32_t scstart = dev_priv->state.s3d.new_scstart;
uint32_t scend = dev_priv->state.s3d.new_scend;
@@ -53,7 +53,7 @@ void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
}
void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
- drm_clip_rect_t * pbox)
+ const drm_clip_rect_t * pbox)
{
uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
@@ -115,18 +115,19 @@ static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit,
#define SAVE_STATE(reg,where) \
if(start <= reg && start+count > reg) \
- DRM_GET_USER_UNCHECKED(dev_priv->state.where, &regs[reg-start])
+ 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]); \
+ 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)
+ const uint32_t *regs)
{
if (start < SAVAGE_TEXPALADDR_S3D ||
start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
@@ -148,8 +149,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
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);
+ dev_priv->state.s3d.texaddr);
}
return 0;
@@ -157,7 +157,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
unsigned int start, unsigned int count,
- const uint32_t __user * regs)
+ const uint32_t *regs)
{
int ret = 0;
@@ -174,19 +174,18 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
~SAVAGE_SCISSOR_MASK_S4);
/* if any texture regs were changed ... */
- if (start <= SAVAGE_TEXDESCR_S4 && start + count > SAVAGE_TEXPALADDR_S4) {
+ 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);
+ 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);
+ ret |= savage_verify_texaddr(dev_priv, 1,
+ dev_priv->state.s4.texaddr1);
}
return ret;
@@ -197,7 +196,7 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
static int savage_dispatch_state(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t * cmd_header,
- const uint32_t __user * regs)
+ const uint32_t *regs)
{
unsigned int count = cmd_header->state.count;
unsigned int start = cmd_header->state.start;
@@ -209,9 +208,6 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
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)
@@ -236,8 +232,8 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
/* 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);
+ count2 = count -
+ (SAVAGE_DRAWCTRL1_S4 + 1 - start);
if (start + count > SAVAGE_DRAWCTRL0_S4)
count = SAVAGE_DRAWCTRL0_S4 - start;
} else if (start <= SAVAGE_DRAWCTRL1_S4) {
@@ -263,7 +259,7 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
while (count > 0) {
unsigned int n = count < 255 ? count : 255;
DMA_SET_REGISTERS(start, n);
- DMA_COPY_FROM_USER(regs, n);
+ DMA_COPY(regs, n);
count -= n;
start += n;
regs += n;
@@ -421,8 +417,8 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
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)
+ const uint32_t *vtxbuf, unsigned int vb_size,
+ unsigned int vb_stride)
{
unsigned char reorder = 0;
unsigned int prim = cmd_header->prim.prim;
@@ -507,8 +503,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
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_COPY(&vtxbuf[vb_stride * j], vtx_size);
}
DMA_COMMIT();
@@ -517,13 +512,12 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
DMA_DRAW_PRIMITIVE(count, prim, skip);
if (vb_stride == vtx_size) {
- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start],
- vtx_size * count);
+ DMA_COPY(&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_COPY(&vtxbuf [vb_stride * i],
+ vtx_size);
}
}
@@ -541,7 +535,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
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 uint16_t *idx,
const drm_buf_t * dmabuf)
{
unsigned char reorder = 0;
@@ -628,11 +622,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
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);
+ /* check indices */
for (i = 0; i < count; ++i) {
if (idx[i] > dmabuf->total / 32) {
DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
@@ -652,8 +643,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
for (i = 1; i + 1 < count; i += 2)
BCI_WRITE(idx[i + reorder[i % 3]] |
- (idx[i + 1 + reorder[(i + 1) % 3]] <<
- 16));
+ (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)) {
@@ -674,7 +665,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
BCI_WRITE(idx[i]);
}
- usr_idx += count;
+ idx += count;
n -= count;
prim |= BCI_CMD_DRAW_CONT;
@@ -685,8 +676,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
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,
+ const uint16_t *idx,
+ const uint32_t *vtxbuf,
unsigned int vb_size, unsigned int vb_stride)
{
unsigned char reorder = 0;
@@ -751,11 +742,8 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
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);
+
+ /* Check indices */
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",
@@ -775,8 +763,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
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_COPY(&vtxbuf[vb_stride * j], vtx_size);
}
DMA_COMMIT();
@@ -786,14 +773,13 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
for (i = 0; i < count; ++i) {
unsigned int j = idx[i];
- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
- vtx_size);
+ DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
}
DMA_COMMIT();
}
- usr_idx += count;
+ idx += count;
n -= count;
prim |= BCI_CMD_DRAW_CONT;
@@ -804,11 +790,11 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
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,
+ const drm_savage_cmd_header_t *data,
unsigned int nbox,
- const drm_clip_rect_t __user * usr_boxes)
+ const drm_clip_rect_t *boxes)
{
- unsigned int flags = cmd_header->clear0.flags, mask, value;
+ unsigned int flags = cmd_header->clear0.flags;
unsigned int clear_cmd;
unsigned int i, nbufs;
DMA_LOCALS;
@@ -816,9 +802,6 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
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);
@@ -828,21 +811,19 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
if (nbufs == 0)
return 0;
- if (mask != 0xffffffff) {
+ if (data->clear1.mask != 0xffffffff) {
/* set mask */
BEGIN_DMA(2);
DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
- DMA_WRITE(mask);
+ DMA_WRITE(data->clear1.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;
+ x = boxes[i].x1, y = boxes[i].y1;
+ w = boxes[i].x2 - boxes[i].x1;
+ h = boxes[i].y2 - boxes[i].y1;
BEGIN_DMA(nbufs * 6);
for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
if (!(flags & buf))
@@ -862,13 +843,13 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
DMA_WRITE(dev_priv->depth_bd);
break;
}
- DMA_WRITE(value);
+ DMA_WRITE(data->clear1.value);
DMA_WRITE(BCI_X_Y(x, y));
DMA_WRITE(BCI_W_H(w, h));
}
DMA_COMMIT();
}
- if (mask != 0xffffffff) {
+ if (data->clear1.mask != 0xffffffff) {
/* reset mask */
BEGIN_DMA(2);
DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
@@ -880,8 +861,7 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
}
static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
- unsigned int nbox,
- const drm_clip_rect_t __user * usr_boxes)
+ unsigned int nbox, const drm_clip_rect_t *boxes)
{
unsigned int swap_cmd;
unsigned int i;
@@ -895,16 +875,14 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
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_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+ DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+ DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1,
+ boxes[i].y2 - boxes[i].y1));
DMA_COMMIT();
}
@@ -912,68 +890,52 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
}
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_savage_cmd_header_t *start,
+ const drm_savage_cmd_header_t *end,
const drm_buf_t * dmabuf,
- const unsigned int __user * usr_vtxbuf,
+ const unsigned int *vtxbuf,
unsigned int vb_size, unsigned int vb_stride,
unsigned int nbox,
- const drm_clip_rect_t __user * usr_boxes)
+ const drm_clip_rect_t *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);
+ const drm_savage_cmd_header_t *cmdbuf;
+ dev_priv->emit_clip_rect(dev_priv, &boxes[i]);
- usr_cmdbuf = start;
- while (usr_cmdbuf < end) {
+ cmdbuf = start;
+ while (cmdbuf < end) {
drm_savage_cmd_header_t cmd_header;
- DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,
- sizeof(cmd_header));
- usr_cmdbuf++;
+ cmd_header = *cmdbuf;
+ cmdbuf++;
switch (cmd_header.cmd.cmd) {
case SAVAGE_CMD_DMA_PRIM:
- ret =
- savage_dispatch_dma_prim(dev_priv,
- &cmd_header,
- dmabuf);
+ 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);
+ ret = savage_dispatch_vb_prim(
+ dev_priv, &cmd_header,
+ 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;
+ ret = savage_dispatch_dma_idx(dev_priv,
+ &cmd_header, (const uint16_t *)cmdbuf,
+ dmabuf);
+ 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;
+ ret = savage_dispatch_vb_idx(dev_priv,
+ &cmd_header, (const uint16_t *)cmdbuf,
+ (const uint32_t *)vtxbuf, vb_size,
+ vb_stride);
+ cmdbuf += j;
break;
default:
/* What's the best return code? EFAULT? */
@@ -998,10 +960,10 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
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;
+ drm_savage_cmd_header_t *kcmd_addr = NULL;
+ drm_savage_cmd_header_t *first_draw_cmd;
+ unsigned int *kvb_addr = NULL;
+ drm_clip_rect_t *kbox_addr = NULL;
unsigned int i, j;
int ret = 0;
@@ -1024,15 +986,53 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
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);
+ /* Copy the user buffers into kernel temporary areas. This hasn't been
+ * a performance loss compared to VERIFYAREA_READ/
+ * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct
+ * for locking on FreeBSD.
+ */
+ if (cmdbuf.size) {
+ kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER);
+ if (kcmd_addr == NULL)
+ return ENOMEM;
+
+ if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr,
+ cmdbuf.size * 8))
+ {
+ drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
+ return DRM_ERR(EFAULT);
+ }
+ cmdbuf.cmd_addr = kcmd_addr;
+ }
+ if (cmdbuf.vb_size) {
+ kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER);
+ if (kvb_addr == NULL) {
+ ret = DRM_ERR(ENOMEM);
+ goto done;
+ }
+
+ if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr,
+ cmdbuf.vb_size)) {
+ ret = DRM_ERR(EFAULT);
+ goto done;
+ }
+ cmdbuf.vb_addr = kvb_addr;
+ }
+ if (cmdbuf.nbox) {
+ kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
+ DRM_MEM_DRIVER);
+ if (kbox_addr == NULL) {
+ ret = DRM_ERR(ENOMEM);
+ goto done;
+ }
+
+ if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
+ cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
+ ret = DRM_ERR(EFAULT);
+ goto done;
+ }
+ cmdbuf.box_addr = kbox_addr;
+ }
/* Make sure writes to DMA buffers are finished before sending
* DMA commands to the graphics hardware. */
@@ -1046,9 +1046,8 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
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++;
+ cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr;
+ cmdbuf.cmd_addr++;
i++;
/* Group drawing commands with same state to minimize
@@ -1068,21 +1067,18 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
case SAVAGE_CMD_DMA_PRIM:
case SAVAGE_CMD_VB_PRIM:
if (!first_draw_cmd)
- first_draw_cmd = usr_cmdbuf - 1;
- usr_cmdbuf += j;
+ first_draw_cmd = cmdbuf.cmd_addr - 1;
+ cmdbuf.cmd_addr += 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);
+ ret = savage_dispatch_draw(
+ dev_priv, first_draw_cmd,
+ cmdbuf.cmd_addr - 1,
+ dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size,
+ cmdbuf.vb_stride,
+ cmdbuf.nbox, cmdbuf.box_addr);
if (ret != 0)
return ret;
first_draw_cmd = NULL;
@@ -1098,12 +1094,12 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
DRM_ERROR("command SAVAGE_CMD_STATE extends "
"beyond end of command buffer\n");
DMA_FLUSH();
- return DRM_ERR(EINVAL);
+ ret = DRM_ERR(EINVAL);
+ goto done;
}
ret = savage_dispatch_state(dev_priv, &cmd_header,
- (uint32_t __user *)
- usr_cmdbuf);
- usr_cmdbuf += j;
+ (const uint32_t *)cmdbuf.cmd_addr);
+ cmdbuf.cmd_addr += j;
i += j;
break;
case SAVAGE_CMD_CLEAR:
@@ -1111,39 +1107,40 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
"beyond end of command buffer\n");
DMA_FLUSH();
- return DRM_ERR(EINVAL);
+ ret = DRM_ERR(EINVAL);
+ goto done;
}
ret = savage_dispatch_clear(dev_priv, &cmd_header,
- usr_cmdbuf,
- cmdbuf.nbox, usr_boxes);
- usr_cmdbuf++;
+ cmdbuf.cmd_addr,
+ cmdbuf.nbox, cmdbuf.box_addr);
+ cmdbuf.cmd_addr++;
i++;
break;
case SAVAGE_CMD_SWAP:
- ret = savage_dispatch_swap(dev_priv,
- cmdbuf.nbox, usr_boxes);
+ ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox,
+ cmdbuf.box_addr);
break;
default:
DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);
DMA_FLUSH();
- return DRM_ERR(EINVAL);
+ ret = DRM_ERR(EINVAL);
+ goto done;
}
if (ret != 0) {
DMA_FLUSH();
- return ret;
+ goto done;
}
}
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);
+ ret = savage_dispatch_draw (
+ dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf,
+ cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride,
+ cmdbuf.nbox, cmdbuf.box_addr);
if (ret != 0) {
DMA_FLUSH();
- return ret;
+ goto done;
}
}
@@ -1157,5 +1154,12 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
savage_freelist_put(dev, dmabuf);
}
- return 0;
+done:
+ /* If we didn't need to allocate them, these'll be NULL */
+ drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
+ drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
+ drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+ DRM_MEM_DRIVER);
+
+ return ret;
}
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
index 8f273da76ddb..30f7b3827466 100644
--- a/drivers/char/drm/sis_drm.h
+++ b/drivers/char/drm/sis_drm.h
@@ -1,3 +1,28 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
+ * Copyright 2005 Eric Anholt
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
#ifndef __SIS_DRM_H__
#define __SIS_DRM_H__
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 3cef10643a8f..6f6d7d613ede 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -32,31 +32,6 @@
#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[] = {
sisdrv_PCI_IDS
};
@@ -68,8 +43,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = sis_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -79,11 +52,18 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init sis_init(void)
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index b1fddad83a93..e218e5269503 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -1,5 +1,5 @@
-/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
- *
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
index da850b4f5440..94f2b4728b63 100644
--- a/drivers/char/drm/sis_ds.h
+++ b/drivers/char/drm/sis_ds.h
@@ -1,6 +1,7 @@
-/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
* Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
- *
+ */
+/*
* Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
* All rights reserved.
*
@@ -35,7 +36,7 @@
#define SET_SIZE 5000
-typedef unsigned int ITEM_TYPE;
+typedef unsigned long ITEM_TYPE;
typedef struct {
ITEM_TYPE val;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index a8529728fa63..6774d2fe3452 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -86,7 +86,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
{
drm_sis_mem_t fb;
struct sis_memreq req;
- drm_sis_mem_t __user *argp = (void __user *)data;
+ drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
int retval = 0;
DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
@@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
- DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
+ DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
return retval;
}
@@ -127,9 +127,9 @@ static int sis_fb_free(DRM_IOCTL_ARGS)
if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
retval = DRM_ERR(EINVAL);
- sis_free((u32) fb.free);
+ sis_free(fb.free);
- DRM_DEBUG("free fb, offset = %lu\n", fb.free);
+ DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
return retval;
}
@@ -176,7 +176,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
- drm_sis_mem_t __user *argp = (void __user *)data;
+ drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
drm_sis_mem_t fb;
PMemBlock block;
int retval = 0;
@@ -267,7 +267,7 @@ static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
- drm_sis_mem_t __user *argp = (void __user *)data;
+ drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
drm_sis_mem_t agp;
PMemBlock block;
int retval = 0;
@@ -367,7 +367,7 @@ int sis_final_context(struct drm_device *dev, int context)
if (i < MAX_CONTEXT) {
set_t *set;
- unsigned int item;
+ ITEM_TYPE item;
int retval;
DRM_DEBUG("find socket %d, context = %d\n", i, context);
@@ -376,7 +376,7 @@ int sis_final_context(struct drm_device *dev, int context)
set = global_ppriv[i].sets[0];
retval = setFirst(set, &item);
while (retval) {
- DRM_DEBUG("free video memory 0x%x\n", item);
+ DRM_DEBUG("free video memory 0x%lx\n", item);
#if defined(__linux__) && defined(CONFIG_FB_SIS)
sis_free(item);
#else
@@ -390,7 +390,7 @@ int sis_final_context(struct drm_device *dev, int context)
set = global_ppriv[i].sets[1];
retval = setFirst(set, &item);
while (retval) {
- DRM_DEBUG("free agp memory 0x%x\n", item);
+ DRM_DEBUG("free agp memory 0x%lx\n", item);
mmFreeMem((PMemBlock) item);
retval = setNext(set, &item);
}
@@ -403,12 +403,12 @@ int sis_final_context(struct drm_device *dev, int context)
}
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, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
};
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 c275cbb6e9ce..baa4416032a8 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -36,31 +36,6 @@
#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[] = {
tdfx_PCI_IDS
};
@@ -70,8 +45,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -80,11 +53,18 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init tdfx_init(void)
diff --git a/drivers/char/drm/tdfx_drv.h b/drivers/char/drm/tdfx_drv.h
index a582a3db4c75..84204ec1b046 100644
--- a/drivers/char/drm/tdfx_drv.h
+++ b/drivers/char/drm/tdfx_drv.h
@@ -1,6 +1,7 @@
/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
* Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
- *
+ */
+/*
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
@@ -30,10 +31,6 @@
#ifndef __TDFX_H__
#define __TDFX_H__
-/* This remains constant for all DRM template files.
- */
-#define DRM(x) tdfx_##x
-
/* General customization:
*/
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index d4b1766608b0..593c0b8f650a 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -213,7 +213,9 @@ static int via_initialize(drm_device_t * dev,
dev_priv->dma_wrap = init->size;
dev_priv->dma_offset = init->offset;
dev_priv->last_pause_ptr = NULL;
- dev_priv->hw_addr_ptr = dev_priv->mmio->handle + init->reg_pause_addr;
+ dev_priv->hw_addr_ptr =
+ (volatile uint32_t *)((char *)dev_priv->mmio->handle +
+ init->reg_pause_addr);
via_cmdbuf_start(dev_priv);
@@ -232,13 +234,13 @@ int via_dma_init(DRM_IOCTL_ARGS)
switch (init.func) {
case VIA_INIT_DMA:
- if (!capable(CAP_SYS_ADMIN))
+ if (!DRM_SUSER(DRM_CURPROC))
retcode = DRM_ERR(EPERM);
else
retcode = via_initialize(dev, dev_priv, &init);
break;
case VIA_CLEANUP_DMA:
- if (!capable(CAP_SYS_ADMIN))
+ if (!DRM_SUSER(DRM_CURPROC))
retcode = DRM_ERR(EPERM);
else
retcode = via_dma_cleanup(dev);
@@ -349,9 +351,6 @@ 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);
static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
drm_via_cmdbuffer_t * cmd)
{
@@ -450,9 +449,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
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 = ((volatile 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, "
@@ -472,7 +471,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
&& count--) ;
rgtr = *(dev_priv->hw_addr_ptr);
- ptr = ((char *)paused_at - dev_priv->dma_ptr) +
+ ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
@@ -724,3 +723,22 @@ int via_cmdbuf_size(DRM_IOCTL_ARGS)
sizeof(d_siz));
return ret;
}
+
+drm_ioctl_desc_t via_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, DRM_AUTH|DRM_MASTER},
+ [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, DRM_AUTH|DRM_MASTER},
+ [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, DRM_AUTH|DRM_MASTER},
+ [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH}
+};
+
+int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
new file mode 100644
index 000000000000..9d5e027dae0e
--- /dev/null
+++ b/drivers/char/drm/via_dmablit.c
@@ -0,0 +1,805 @@
+/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro
+ *
+ * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Hellstrom.
+ * Partially based on code obtained from Digeo Inc.
+ */
+
+
+/*
+ * Unmaps the DMA mappings.
+ * FIXME: Is this a NoOp on x86? Also
+ * FIXME: What happens if this one is called and a pending blit has previously done
+ * the same DMA mappings?
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_dmablit.h"
+
+#include <linux/pagemap.h>
+
+#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK)
+#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK)
+#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT)
+
+typedef struct _drm_via_descriptor {
+ uint32_t mem_addr;
+ uint32_t dev_addr;
+ uint32_t size;
+ uint32_t next;
+} drm_via_descriptor_t;
+
+
+/*
+ * Unmap a DMA mapping.
+ */
+
+
+
+static void
+via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+ int num_desc = vsg->num_desc;
+ unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;
+ unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;
+ drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+ descriptor_this_page;
+ dma_addr_t next = vsg->chain_start;
+
+ while(num_desc--) {
+ if (descriptor_this_page-- == 0) {
+ cur_descriptor_page--;
+ descriptor_this_page = vsg->descriptors_per_page - 1;
+ desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+ descriptor_this_page;
+ }
+ dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);
+ dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);
+ next = (dma_addr_t) desc_ptr->next;
+ desc_ptr--;
+ }
+}
+
+/*
+ * If mode = 0, count how many descriptors are needed.
+ * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.
+ * Descriptors are run in reverse order by the hardware because we are not allowed to update the
+ * 'next' field without syncing calls when the descriptor is already mapped.
+ */
+
+static void
+via_map_blit_for_device(struct pci_dev *pdev,
+ const drm_via_dmablit_t *xfer,
+ drm_via_sg_info_t *vsg,
+ int mode)
+{
+ unsigned cur_descriptor_page = 0;
+ unsigned num_descriptors_this_page = 0;
+ unsigned char *mem_addr = xfer->mem_addr;
+ unsigned char *cur_mem;
+ unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);
+ uint32_t fb_addr = xfer->fb_addr;
+ uint32_t cur_fb;
+ unsigned long line_len;
+ unsigned remaining_len;
+ int num_desc = 0;
+ int cur_line;
+ dma_addr_t next = 0 | VIA_DMA_DPR_EC;
+ drm_via_descriptor_t *desc_ptr = 0;
+
+ if (mode == 1)
+ desc_ptr = vsg->desc_pages[cur_descriptor_page];
+
+ for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {
+
+ line_len = xfer->line_length;
+ cur_fb = fb_addr;
+ cur_mem = mem_addr;
+
+ while (line_len > 0) {
+
+ remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
+ line_len -= remaining_len;
+
+ if (mode == 1) {
+ desc_ptr->mem_addr =
+ dma_map_page(&pdev->dev,
+ vsg->pages[VIA_PFN(cur_mem) -
+ VIA_PFN(first_addr)],
+ VIA_PGOFF(cur_mem), remaining_len,
+ vsg->direction);
+ desc_ptr->dev_addr = cur_fb;
+
+ desc_ptr->size = remaining_len;
+ desc_ptr->next = (uint32_t) next;
+ next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
+ DMA_TO_DEVICE);
+ desc_ptr++;
+ if (++num_descriptors_this_page >= vsg->descriptors_per_page) {
+ num_descriptors_this_page = 0;
+ desc_ptr = vsg->desc_pages[++cur_descriptor_page];
+ }
+ }
+
+ num_desc++;
+ cur_mem += remaining_len;
+ cur_fb += remaining_len;
+ }
+
+ mem_addr += xfer->mem_stride;
+ fb_addr += xfer->fb_stride;
+ }
+
+ if (mode == 1) {
+ vsg->chain_start = next;
+ vsg->state = dr_via_device_mapped;
+ }
+ vsg->num_desc = num_desc;
+}
+
+/*
+ * Function that frees up all resources for a blit. It is usable even if the
+ * blit info has only be partially built as long as the status enum is consistent
+ * with the actual status of the used resources.
+ */
+
+
+void
+via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+ struct page *page;
+ int i;
+
+ switch(vsg->state) {
+ case dr_via_device_mapped:
+ via_unmap_blit_from_device(pdev, vsg);
+ case dr_via_desc_pages_alloc:
+ for (i=0; i<vsg->num_desc_pages; ++i) {
+ if (vsg->desc_pages[i] != NULL)
+ free_page((unsigned long)vsg->desc_pages[i]);
+ }
+ kfree(vsg->desc_pages);
+ case dr_via_pages_locked:
+ for (i=0; i<vsg->num_pages; ++i) {
+ if ( NULL != (page = vsg->pages[i])) {
+ if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction))
+ SetPageDirty(page);
+ page_cache_release(page);
+ }
+ }
+ case dr_via_pages_alloc:
+ vfree(vsg->pages);
+ default:
+ vsg->state = dr_via_sg_init;
+ }
+ if (vsg->bounce_buffer) {
+ vfree(vsg->bounce_buffer);
+ vsg->bounce_buffer = NULL;
+ }
+ vsg->free_on_sequence = 0;
+}
+
+/*
+ * Fire a blit engine.
+ */
+
+static void
+via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+ VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);
+ VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
+ VIA_DMA_CSR_DE);
+ VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
+ VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
+ VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
+}
+
+/*
+ * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will
+ * occur here if the calling user does not have access to the submitted address.
+ */
+
+static int
+via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+{
+ int ret;
+ unsigned long first_pfn = VIA_PFN(xfer->mem_addr);
+ vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) -
+ first_pfn + 1;
+
+ if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))
+ return DRM_ERR(ENOMEM);
+ memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr,
+ vsg->num_pages, vsg->direction, 0, vsg->pages, NULL);
+
+ up_read(&current->mm->mmap_sem);
+ if (ret != vsg->num_pages) {
+ if (ret < 0)
+ return ret;
+ vsg->state = dr_via_pages_locked;
+ return DRM_ERR(EINVAL);
+ }
+ vsg->state = dr_via_pages_locked;
+ DRM_DEBUG("DMA pages locked\n");
+ return 0;
+}
+
+/*
+ * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the
+ * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be
+ * quite large for some blits, and pages don't need to be contingous.
+ */
+
+static int
+via_alloc_desc_pages(drm_via_sg_info_t *vsg)
+{
+ int i;
+
+ vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t);
+ vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
+ vsg->descriptors_per_page;
+
+ if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL)))
+ return DRM_ERR(ENOMEM);
+
+ memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages);
+ vsg->state = dr_via_desc_pages_alloc;
+ for (i=0; i<vsg->num_desc_pages; ++i) {
+ if (NULL == (vsg->desc_pages[i] =
+ (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
+ return DRM_ERR(ENOMEM);
+ }
+ DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
+ vsg->num_desc);
+ return 0;
+}
+
+static void
+via_abort_dmablit(drm_device_t *dev, int engine)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
+}
+
+static void
+via_dmablit_engine_off(drm_device_t *dev, int engine)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
+}
+
+
+
+/*
+ * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.
+ * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue
+ * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while
+ * the workqueue task takes care of processing associated with the old blit.
+ */
+
+void
+via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+ int cur;
+ int done_transfer;
+ unsigned long irqsave=0;
+ uint32_t status = 0;
+
+ DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",
+ engine, from_irq, (unsigned long) blitq);
+
+ if (from_irq) {
+ spin_lock(&blitq->blit_lock);
+ } else {
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ }
+
+ done_transfer = blitq->is_active &&
+ (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
+ done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE));
+
+ cur = blitq->cur;
+ if (done_transfer) {
+
+ blitq->blits[cur]->aborted = blitq->aborting;
+ blitq->done_blit_handle++;
+ DRM_WAKEUP(blitq->blit_queue + cur);
+
+ cur++;
+ if (cur >= VIA_NUM_BLIT_SLOTS)
+ cur = 0;
+ blitq->cur = cur;
+
+ /*
+ * Clear transfer done flag.
+ */
+
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD);
+
+ blitq->is_active = 0;
+ blitq->aborting = 0;
+ schedule_work(&blitq->wq);
+
+ } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {
+
+ /*
+ * Abort transfer after one second.
+ */
+
+ via_abort_dmablit(dev, engine);
+ blitq->aborting = 1;
+ blitq->end = jiffies + DRM_HZ;
+ }
+
+ if (!blitq->is_active) {
+ if (blitq->num_outstanding) {
+ via_fire_dmablit(dev, blitq->blits[cur], engine);
+ blitq->is_active = 1;
+ blitq->cur = cur;
+ blitq->num_outstanding--;
+ blitq->end = jiffies + DRM_HZ;
+ if (!timer_pending(&blitq->poll_timer)) {
+ blitq->poll_timer.expires = jiffies+1;
+ add_timer(&blitq->poll_timer);
+ }
+ } else {
+ if (timer_pending(&blitq->poll_timer)) {
+ del_timer(&blitq->poll_timer);
+ }
+ via_dmablit_engine_off(dev, engine);
+ }
+ }
+
+ if (from_irq) {
+ spin_unlock(&blitq->blit_lock);
+ } else {
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+ }
+}
+
+
+
+/*
+ * Check whether this blit is still active, performing necessary locking.
+ */
+
+static int
+via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)
+{
+ unsigned long irqsave;
+ uint32_t slot;
+ int active;
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+ /*
+ * Allow for handle wraparounds.
+ */
+
+ active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&
+ ((blitq->cur_blit_handle - handle) <= (1 << 23));
+
+ if (queue && active) {
+ slot = handle - blitq->done_blit_handle + blitq->cur -1;
+ if (slot >= VIA_NUM_BLIT_SLOTS) {
+ slot -= VIA_NUM_BLIT_SLOTS;
+ }
+ *queue = blitq->blit_queue + slot;
+ }
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ return active;
+}
+
+/*
+ * Sync. Wait for at least three seconds for the blit to be performed.
+ */
+
+static int
+via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine)
+{
+
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+ wait_queue_head_t *queue;
+ int ret = 0;
+
+ if (via_dmablit_active(blitq, engine, handle, &queue)) {
+ DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ,
+ !via_dmablit_active(blitq, engine, handle, NULL));
+ }
+ DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
+ handle, engine, ret);
+
+ return ret;
+}
+
+
+/*
+ * A timer that regularly polls the blit engine in cases where we don't have interrupts:
+ * a) Broken hardware (typically those that don't have any video capture facility).
+ * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.
+ * The timer and hardware IRQ's can and do work in parallel. If the hardware has
+ * irqs, it will shorten the latency somewhat.
+ */
+
+
+
+static void
+via_dmablit_timer(unsigned long data)
+{
+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
+ drm_device_t *dev = blitq->dev;
+ int engine = (int)
+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
+
+ DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine,
+ (unsigned long) jiffies);
+
+ via_dmablit_handler(dev, engine, 0);
+
+ if (!timer_pending(&blitq->poll_timer)) {
+ blitq->poll_timer.expires = jiffies+1;
+ add_timer(&blitq->poll_timer);
+ }
+ via_dmablit_handler(dev, engine, 0);
+
+}
+
+
+
+
+/*
+ * Workqueue task that frees data and mappings associated with a blit.
+ * Also wakes up waiting processes. Each of these tasks handles one
+ * blit engine only and may not be called on each interrupt.
+ */
+
+
+static void
+via_dmablit_workqueue(void *data)
+{
+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
+ drm_device_t *dev = blitq->dev;
+ unsigned long irqsave;
+ drm_via_sg_info_t *cur_sg;
+ int cur_released;
+
+
+ DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long)
+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+ while(blitq->serviced != blitq->cur) {
+
+ cur_released = blitq->serviced++;
+
+ DRM_DEBUG("Releasing blit slot %d\n", cur_released);
+
+ if (blitq->serviced >= VIA_NUM_BLIT_SLOTS)
+ blitq->serviced = 0;
+
+ cur_sg = blitq->blits[cur_released];
+ blitq->num_free++;
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ DRM_WAKEUP(&blitq->busy_queue);
+
+ via_free_sg_info(dev->pdev, cur_sg);
+ kfree(cur_sg);
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ }
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+}
+
+
+/*
+ * Init all blit engines. Currently we use two, but some hardware have 4.
+ */
+
+
+void
+via_init_dmablit(drm_device_t *dev)
+{
+ int i,j;
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_blitq_t *blitq;
+
+ pci_set_master(dev->pdev);
+
+ for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) {
+ blitq = dev_priv->blit_queues + i;
+ blitq->dev = dev;
+ blitq->cur_blit_handle = 0;
+ blitq->done_blit_handle = 0;
+ blitq->head = 0;
+ blitq->cur = 0;
+ blitq->serviced = 0;
+ blitq->num_free = VIA_NUM_BLIT_SLOTS;
+ blitq->num_outstanding = 0;
+ blitq->is_active = 0;
+ blitq->aborting = 0;
+ blitq->blit_lock = SPIN_LOCK_UNLOCKED;
+ for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {
+ DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
+ }
+ DRM_INIT_WAITQUEUE(&blitq->busy_queue);
+ INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq);
+ init_timer(&blitq->poll_timer);
+ blitq->poll_timer.function = &via_dmablit_timer;
+ blitq->poll_timer.data = (unsigned long) blitq;
+ }
+}
+
+/*
+ * Build all info and do all mappings required for a blit.
+ */
+
+
+static int
+via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+{
+ int draw = xfer->to_fb;
+ int ret = 0;
+
+ vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ vsg->bounce_buffer = 0;
+
+ vsg->state = dr_via_sg_init;
+
+ if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
+ DRM_ERROR("Zero size bitblt.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ /*
+ * Below check is a driver limitation, not a hardware one. We
+ * don't want to lock unused pages, and don't want to incoporate the
+ * extra logic of avoiding them. Make sure there are no.
+ * (Not a big limitation anyway.)
+ */
+
+ if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) ||
+ (xfer->mem_stride > 2048*4)) {
+ DRM_ERROR("Too large system memory stride. Stride: %d, "
+ "Length: %d\n", xfer->mem_stride, xfer->line_length);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (xfer->num_lines > 2048) {
+ DRM_ERROR("Too many PCI DMA bitblt lines.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ /*
+ * we allow a negative fb stride to allow flipping of images in
+ * transfer.
+ */
+
+ if (xfer->mem_stride < xfer->line_length ||
+ abs(xfer->fb_stride) < xfer->line_length) {
+ DRM_ERROR("Invalid frame-buffer / memory stride.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ /*
+ * A hardware bug seems to be worked around if system memory addresses start on
+ * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted
+ * about this. Meanwhile, impose the following restrictions:
+ */
+
+#ifdef VIA_BUGFREE
+ if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
+ ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) {
+ DRM_ERROR("Invalid DRM bitblt alignment.\n");
+ return DRM_ERR(EINVAL);
+ }
+#else
+ if ((((unsigned long)xfer->mem_addr & 15) ||
+ ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) ||
+ (xfer->fb_stride & 3)) {
+ DRM_ERROR("Invalid DRM bitblt alignment.\n");
+ return DRM_ERR(EINVAL);
+ }
+#endif
+
+ if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {
+ DRM_ERROR("Could not lock DMA pages.\n");
+ via_free_sg_info(dev->pdev, vsg);
+ return ret;
+ }
+
+ via_map_blit_for_device(dev->pdev, xfer, vsg, 0);
+ if (0 != (ret = via_alloc_desc_pages(vsg))) {
+ DRM_ERROR("Could not allocate DMA descriptor pages.\n");
+ via_free_sg_info(dev->pdev, vsg);
+ return ret;
+ }
+ via_map_blit_for_device(dev->pdev, xfer, vsg, 1);
+
+ return 0;
+}
+
+
+/*
+ * Reserve one free slot in the blit queue. Will wait for one second for one
+ * to become available. Otherwise -EBUSY is returned.
+ */
+
+static int
+via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
+{
+ int ret=0;
+ unsigned long irqsave;
+
+ DRM_DEBUG("Num free is %d\n", blitq->num_free);
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ while(blitq->num_free == 0) {
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
+ if (ret) {
+ return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret;
+ }
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ }
+
+ blitq->num_free--;
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ return 0;
+}
+
+/*
+ * Hand back a free slot if we changed our mind.
+ */
+
+static void
+via_dmablit_release_slot(drm_via_blitq_t *blitq)
+{
+ unsigned long irqsave;
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ blitq->num_free++;
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+ DRM_WAKEUP( &blitq->busy_queue );
+}
+
+/*
+ * Grab a free slot. Build blit info and queue a blit.
+ */
+
+
+static int
+via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_sg_info_t *vsg;
+ drm_via_blitq_t *blitq;
+ int ret;
+ int engine;
+ unsigned long irqsave;
+
+ if (dev_priv == NULL) {
+ DRM_ERROR("Called without initialization.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ engine = (xfer->to_fb) ? 0 : 1;
+ blitq = dev_priv->blit_queues + engine;
+ if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) {
+ return ret;
+ }
+ if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
+ via_dmablit_release_slot(blitq);
+ return DRM_ERR(ENOMEM);
+ }
+ if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
+ via_dmablit_release_slot(blitq);
+ kfree(vsg);
+ return ret;
+ }
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+ blitq->blits[blitq->head++] = vsg;
+ if (blitq->head >= VIA_NUM_BLIT_SLOTS)
+ blitq->head = 0;
+ blitq->num_outstanding++;
+ xfer->sync.sync_handle = ++blitq->cur_blit_handle;
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+ xfer->sync.engine = engine;
+
+ via_dmablit_handler(dev, engine, 0);
+
+ return 0;
+}
+
+/*
+ * Sync on a previously submitted blit. Note that the X server use signals extensively, and
+ * that there is a very big proability that this IOCTL will be interrupted by a signal. In that
+ * case it returns with -EAGAIN for the signal to be delivered.
+ * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
+ */
+
+int
+via_dma_blit_sync( DRM_IOCTL_ARGS )
+{
+ drm_via_blitsync_t sync;
+ int err;
+ DRM_DEVICE;
+
+ DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync));
+
+ if (sync.engine >= VIA_NUM_BLIT_ENGINES)
+ return DRM_ERR(EINVAL);
+
+ err = via_dmablit_sync(dev, sync.sync_handle, sync.engine);
+
+ if (DRM_ERR(EINTR) == err)
+ err = DRM_ERR(EAGAIN);
+
+ return err;
+}
+
+
+/*
+ * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal
+ * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should
+ * be reissued. See the above IOCTL code.
+ */
+
+int
+via_dma_blit( DRM_IOCTL_ARGS )
+{
+ drm_via_dmablit_t xfer;
+ int err;
+ DRM_DEVICE;
+
+ DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer));
+
+ err = via_dmablit(dev, &xfer);
+
+ DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer));
+
+ return err;
+}
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h
new file mode 100644
index 000000000000..f4036cd5d0e0
--- /dev/null
+++ b/drivers/char/drm/via_dmablit.h
@@ -0,0 +1,140 @@
+/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro
+ *
+ * Copyright 2005 Thomas Hellstrom.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Hellstrom.
+ * Register info from Digeo Inc.
+ */
+
+#ifndef _VIA_DMABLIT_H
+#define _VIA_DMABLIT_H
+
+#include <linux/dma-mapping.h>
+
+#define VIA_NUM_BLIT_ENGINES 2
+#define VIA_NUM_BLIT_SLOTS 8
+
+struct _drm_via_descriptor;
+
+typedef struct _drm_via_sg_info {
+ struct page **pages;
+ unsigned long num_pages;
+ struct _drm_via_descriptor **desc_pages;
+ int num_desc_pages;
+ int num_desc;
+ enum dma_data_direction direction;
+ unsigned char *bounce_buffer;
+ dma_addr_t chain_start;
+ uint32_t free_on_sequence;
+ unsigned int descriptors_per_page;
+ int aborted;
+ enum {
+ dr_via_device_mapped,
+ dr_via_desc_pages_alloc,
+ dr_via_pages_locked,
+ dr_via_pages_alloc,
+ dr_via_sg_init
+ } state;
+} drm_via_sg_info_t;
+
+typedef struct _drm_via_blitq {
+ drm_device_t *dev;
+ uint32_t cur_blit_handle;
+ uint32_t done_blit_handle;
+ unsigned serviced;
+ unsigned head;
+ unsigned cur;
+ unsigned num_free;
+ unsigned num_outstanding;
+ unsigned long end;
+ int aborting;
+ int is_active;
+ drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];
+ spinlock_t blit_lock;
+ wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];
+ wait_queue_head_t busy_queue;
+ struct work_struct wq;
+ struct timer_list poll_timer;
+} drm_via_blitq_t;
+
+
+/*
+ * PCI DMA Registers
+ * Channels 2 & 3 don't seem to be implemented in hardware.
+ */
+
+#define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */
+#define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */
+#define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */
+#define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */
+
+#define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */
+#define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */
+#define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */
+#define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */
+
+#define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */
+#define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */
+#define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */
+#define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */
+
+#define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */
+#define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */
+#define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */
+#define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */
+
+#define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */
+#define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */
+#define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */
+#define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */
+
+#define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */
+#define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */
+#define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */
+#define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */
+
+#define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */
+
+/* Define for DMA engine */
+/* DPR */
+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */
+#define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */
+#define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */
+
+/* MR */
+#define VIA_DMA_MR_CM (1<<0) /* chaining mode */
+#define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */
+#define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */
+
+/* CSR */
+#define VIA_DMA_CSR_DE (1<<0) /* DMA enable */
+#define VIA_DMA_CSR_TS (1<<1) /* transfer start */
+#define VIA_DMA_CSR_TA (1<<2) /* transfer abort */
+#define VIA_DMA_CSR_TD (1<<3) /* transfer done */
+#define VIA_DMA_CSR_DD (1<<4) /* descriptor done */
+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */
+
+
+
+#endif
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index ebde9206115e..47f0b5b26379 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -75,6 +75,8 @@
#define DRM_VIA_CMDBUF_SIZE 0x0b
#define NOT_USED
#define DRM_VIA_WAIT_IRQ 0x0d
+#define DRM_VIA_DMA_BLIT 0x0e
+#define DRM_VIA_BLIT_SYNC 0x0f
#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
@@ -89,6 +91,8 @@
#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
drm_via_cmdbuf_size_t)
#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
+#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)
+#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)
/* 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,
@@ -103,8 +107,12 @@
#define VIA_BACK 0x2
#define VIA_DEPTH 0x4
#define VIA_STENCIL 0x8
-#define VIDEO 0
-#define AGP 1
+#define VIA_MEM_VIDEO 0 /* matches drm constant */
+#define VIA_MEM_AGP 1 /* matches drm constant */
+#define VIA_MEM_SYSTEM 2
+#define VIA_MEM_MIXED 3
+#define VIA_MEM_UNKNOWN 4
+
typedef struct {
uint32_t offset;
uint32_t size;
@@ -192,6 +200,9 @@ typedef struct _drm_via_sarea {
unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];
unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */
+ /* Used by the 3d driver only at this point, for pageflipping:
+ */
+ unsigned int pfCurrentOffset;
} drm_via_sarea_t;
typedef struct _drm_via_cmdbuf_size {
@@ -212,6 +223,16 @@ typedef enum {
#define VIA_IRQ_FLAGS_MASK 0xF0000000
+enum drm_via_irqs {
+ drm_via_irq_hqv0 = 0,
+ drm_via_irq_hqv1,
+ drm_via_irq_dma0_dd,
+ drm_via_irq_dma0_td,
+ drm_via_irq_dma1_dd,
+ drm_via_irq_dma1_td,
+ drm_via_irq_num
+};
+
struct drm_via_wait_irq_request {
unsigned irq;
via_irq_seq_type_t type;
@@ -224,20 +245,25 @@ typedef union drm_via_irqwait {
struct drm_wait_vblank_reply reply;
} drm_via_irqwait_t;
-#ifdef __KERNEL__
-
-int via_fb_init(DRM_IOCTL_ARGS);
-int via_mem_alloc(DRM_IOCTL_ARGS);
-int via_mem_free(DRM_IOCTL_ARGS);
-int via_agp_init(DRM_IOCTL_ARGS);
-int via_map_init(DRM_IOCTL_ARGS);
-int via_decoder_futex(DRM_IOCTL_ARGS);
-int via_dma_init(DRM_IOCTL_ARGS);
-int via_cmdbuffer(DRM_IOCTL_ARGS);
-int via_flush_ioctl(DRM_IOCTL_ARGS);
-int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
-int via_cmdbuf_size(DRM_IOCTL_ARGS);
-int via_wait_irq(DRM_IOCTL_ARGS);
+typedef struct drm_via_blitsync {
+ uint32_t sync_handle;
+ unsigned engine;
+} drm_via_blitsync_t;
+
+typedef struct drm_via_dmablit {
+ uint32_t num_lines;
+ uint32_t line_length;
+
+ uint32_t fb_addr;
+ uint32_t fb_stride;
+
+ unsigned char *mem_addr;
+ uint32_t mem_stride;
+
+ int bounce_buffer;
+ int to_fb;
+
+ drm_via_blitsync_t sync;
+} drm_via_dmablit_t;
-#endif
#endif /* _VIA_DRM_H_ */
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
index 016665e0c69f..3f012255d315 100644
--- a/drivers/char/drm/via_drv.c
+++ b/drivers/char/drm/via_drv.c
@@ -29,54 +29,21 @@
#include "drm_pciids.h"
-static int postinit(struct drm_device *dev, unsigned long flags)
+static int dri_library_name(struct drm_device *dev, char *buf)
{
- 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;
+ return snprintf(buf, PAGE_SIZE, "unichrome");
}
static struct pci_device_id pciidlist[] = {
viadrv_PCI_IDS
};
-static drm_ioctl_desc_t ioctls[] = {
- [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, 1, 0}
-};
-
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .load = via_driver_load,
+ .unload = via_driver_unload,
.context_ctor = via_init_context,
.context_dtor = via_final_context,
.vblank_wait = via_driver_vblank_wait,
@@ -85,13 +52,11 @@ static struct drm_driver driver = {
.irq_uninstall = via_driver_irq_uninstall,
.irq_handler = via_driver_irq_handler,
.dma_quiescent = via_driver_dma_quiescent,
+ .dri_library_name = dri_library_name,
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
- .ioctls = ioctls,
- .num_ioctls = DRM_ARRAY_SIZE(ioctls),
+ .ioctls = via_ioctls,
.fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -100,15 +65,23 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init via_init(void)
{
+ driver.num_ioctls = via_max_ioctl;
via_init_command_verifier();
return drm_init(&driver);
}
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index 7d5daf43797e..aad4f99f5405 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -24,24 +24,26 @@
#ifndef _VIA_DRV_H_
#define _VIA_DRV_H_
-#define DRIVER_AUTHOR "VIA"
+#define DRIVER_AUTHOR "Various"
#define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro"
-#define DRIVER_DATE "20050523"
+#define DRIVER_DATE "20051116"
#define DRIVER_MAJOR 2
-#define DRIVER_MINOR 6
-#define DRIVER_PATCHLEVEL 3
+#define DRIVER_MINOR 7
+#define DRIVER_PATCHLEVEL 4
#include "via_verifier.h"
+#include "via_dmablit.h"
+
#define VIA_PCI_BUF_SIZE 60000
#define VIA_FIRE_BUF_SIZE 1024
-#define VIA_NUM_IRQS 2
+#define VIA_NUM_IRQS 4
typedef struct drm_via_ring_buffer {
- drm_map_t map;
+ drm_local_map_t map;
char *virtual_start;
} drm_via_ring_buffer_t;
@@ -56,9 +58,9 @@ typedef struct drm_via_irq {
typedef struct drm_via_private {
drm_via_sarea_t *sarea_priv;
- drm_map_t *sarea;
- drm_map_t *fb;
- drm_map_t *mmio;
+ drm_local_map_t *sarea;
+ drm_local_map_t *fb;
+ drm_local_map_t *mmio;
unsigned long agpAddr;
wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
char *dma_ptr;
@@ -82,8 +84,15 @@ typedef struct drm_via_private {
maskarray_t *irq_masks;
uint32_t irq_enable_mask;
uint32_t irq_pending_mask;
+ int *irq_map;
+ drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
} drm_via_private_t;
+enum via_family {
+ VIA_OTHER = 0,
+ VIA_PRO_GROUP_A,
+};
+
/* VIA MMIO register access */
#define VIA_BASE ((dev_priv->mmio))
@@ -92,12 +101,31 @@ typedef struct drm_via_private {
#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)
#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)
+extern drm_ioctl_desc_t via_ioctls[];
+extern int via_max_ioctl;
+
+extern int via_fb_init(DRM_IOCTL_ARGS);
+extern int via_mem_alloc(DRM_IOCTL_ARGS);
+extern int via_mem_free(DRM_IOCTL_ARGS);
+extern int via_agp_init(DRM_IOCTL_ARGS);
+extern int via_map_init(DRM_IOCTL_ARGS);
+extern int via_decoder_futex(DRM_IOCTL_ARGS);
+extern int via_dma_init(DRM_IOCTL_ARGS);
+extern int via_cmdbuffer(DRM_IOCTL_ARGS);
+extern int via_flush_ioctl(DRM_IOCTL_ARGS);
+extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
+extern int via_cmdbuf_size(DRM_IOCTL_ARGS);
+extern int via_wait_irq(DRM_IOCTL_ARGS);
+extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
+extern int via_dma_blit( DRM_IOCTL_ARGS );
+
+extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
+extern int via_driver_unload(drm_device_t *dev);
+
extern int via_init_context(drm_device_t * dev, int context);
extern int via_final_context(drm_device_t * dev, int context);
extern int via_do_cleanup_map(drm_device_t * dev);
-extern int via_map_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
@@ -111,8 +139,10 @@ 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 int via_driver_irq_wait(drm_device_t * dev, unsigned int irq,
+ int force_sequence, unsigned int *sequence);
-extern int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
- unsigned int size);
+extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
+extern void via_init_dmablit(drm_device_t *dev);
#endif
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
index 5c71e089246c..9429736b3b96 100644
--- a/drivers/char/drm/via_ds.c
+++ b/drivers/char/drm/via_ds.c
@@ -22,14 +22,7 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/pci.h>
-#include <asm/io.h>
+#include "drmP.h"
#include "via_ds.h"
extern unsigned int VIA_DEBUG;
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index d023add1929b..56d7e3daea12 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -50,6 +50,15 @@
#define VIA_IRQ_HQV1_ENABLE (1 << 25)
#define VIA_IRQ_HQV0_PENDING (1 << 9)
#define VIA_IRQ_HQV1_PENDING (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
/*
* Device-specific IRQs go here. This type might need to be extended with
@@ -61,13 +70,24 @@ 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}
+ 0x00000000},
+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
};
static int via_num_pro_group_a =
sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
-static maskarray_t via_unichrome_irqs[] = { };
+static maskarray_t via_unichrome_irqs[] = {
+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
static unsigned time_diff(struct timeval *now, struct timeval *then)
{
@@ -113,6 +133,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
atomic_inc(&cur_irq->irq_received);
DRM_WAKEUP(&cur_irq->irq_queue);
handled = 1;
+ if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
+ via_dmablit_handler(dev, 0, 1);
+ } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
+ via_dmablit_handler(dev, 1, 1);
+ }
}
cur_irq++;
}
@@ -165,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-static int
+int
via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
unsigned int *sequence)
{
@@ -174,6 +199,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
drm_via_irq_t *cur_irq = dev_priv->via_irqs;
int ret = 0;
maskarray_t *masks = dev_priv->irq_masks;
+ int real_irq;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -182,15 +208,23 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
return DRM_ERR(EINVAL);
}
- if (irq >= dev_priv->num_irqs) {
+ if (irq >= drm_via_irq_num) {
DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
irq);
return DRM_ERR(EINVAL);
}
- cur_irq += irq;
+ real_irq = dev_priv->irq_map[irq];
+
+ if (real_irq < 0) {
+ DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",
+ __FUNCTION__, irq);
+ return DRM_ERR(EINVAL);
+ }
+
+ cur_irq += real_irq;
- if (masks[irq][2] && !force_sequence) {
+ if (masks[real_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]));
@@ -226,6 +260,8 @@ void via_driver_irq_preinstall(drm_device_t * dev)
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;
+ dev_priv->irq_map = (dev_priv->pro_group_a) ?
+ via_irqmap_pro_group_a : via_irqmap_unichrome;
for (i = 0; i < dev_priv->num_irqs; ++i) {
atomic_set(&cur_irq->irq_received, 0);
@@ -241,7 +277,7 @@ void via_driver_irq_preinstall(drm_device_t * dev)
dev_priv->last_vblank_valid = 0;
- // Clear VSync interrupt regs
+ /* Clear VSync interrupt regs */
status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status &
~(dev_priv->irq_enable_mask));
@@ -291,8 +327,7 @@ void via_driver_irq_uninstall(drm_device_t * dev)
int via_wait_irq(DRM_IOCTL_ARGS)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ DRM_DEVICE;
drm_via_irqwait_t __user *argp = (void __user *)data;
drm_via_irqwait_t irqwait;
struct timeval now;
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 6bd6ac52ad1b..c6a08e96285b 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -27,16 +27,10 @@
static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
{
- drm_via_private_t *dev_priv;
+ drm_via_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
- dev_priv = drm_alloc(sizeof(drm_via_private_t), DRM_MEM_DRIVER);
- if (dev_priv == NULL)
- return -ENOMEM;
-
- memset(dev_priv, 0, sizeof(drm_via_private_t));
-
DRM_GETSAREA();
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
@@ -67,7 +61,8 @@ 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);
- dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
+
+ via_init_dmablit(dev);
dev->dev_private = (void *)dev_priv;
return 0;
@@ -75,15 +70,7 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
int via_do_cleanup_map(drm_device_t * dev)
{
- if (dev->dev_private) {
-
- drm_via_private_t *dev_priv = dev->dev_private;
-
- via_dma_cleanup(dev);
-
- drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
- dev->dev_private = NULL;
- }
+ via_dma_cleanup(dev);
return 0;
}
@@ -107,3 +94,29 @@ int via_map_init(DRM_IOCTL_ARGS)
return -EINVAL;
}
+
+int via_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+ drm_via_private_t *dev_priv;
+
+ dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return DRM_ERR(ENOMEM);
+
+ dev->dev_private = (void *)dev_priv;
+
+ if (chipset == VIA_PRO_GROUP_A)
+ dev_priv->pro_group_a = 1;
+
+ return 0;
+}
+
+int via_driver_unload(drm_device_t *dev)
+{
+ drm_via_private_t *dev_priv = dev->dev_private;
+
+ drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+
+ return 0;
+}
+
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 3baddacdff26..33e0cb12e4c3 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -42,7 +42,7 @@ static int via_agp_free(drm_via_mem_t * mem);
static int via_fb_alloc(drm_via_mem_t * mem);
static int via_fb_free(drm_via_mem_t * mem);
-static int add_alloc_set(int context, int type, unsigned int val)
+static int add_alloc_set(int context, int type, unsigned long val)
{
int i, retval = 0;
@@ -56,7 +56,7 @@ static int add_alloc_set(int context, int type, unsigned int val)
return retval;
}
-static int del_alloc_set(int context, int type, unsigned int val)
+static int del_alloc_set(int context, int type, unsigned long val)
{
int i, retval = 0;
@@ -199,13 +199,13 @@ int via_mem_alloc(DRM_IOCTL_ARGS)
sizeof(mem));
switch (mem.type) {
- case VIDEO:
+ case VIA_MEM_VIDEO:
if (via_fb_alloc(&mem) < 0)
return -EFAULT;
DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
sizeof(mem));
return 0;
- case AGP:
+ case VIA_MEM_AGP:
if (via_agp_alloc(&mem) < 0)
return -EFAULT;
DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
@@ -232,7 +232,7 @@ static int via_fb_alloc(drm_via_mem_t * mem)
if (block) {
fb.offset = block->ofs;
fb.free = (unsigned long)block;
- if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
+ if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
DRM_DEBUG("adding to allocation set fails\n");
via_mmFreeMem((PMemBlock) fb.free);
retval = -1;
@@ -269,7 +269,7 @@ static int via_agp_alloc(drm_via_mem_t * mem)
if (block) {
agp.offset = block->ofs;
agp.free = (unsigned long)block;
- if (!add_alloc_set(agp.context, AGP, agp.free)) {
+ if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
DRM_DEBUG("adding to allocation set fails\n");
via_mmFreeMem((PMemBlock) agp.free);
retval = -1;
@@ -297,11 +297,11 @@ int via_mem_free(DRM_IOCTL_ARGS)
switch (mem.type) {
- case VIDEO:
+ case VIA_MEM_VIDEO:
if (via_fb_free(&mem) == 0)
return 0;
break;
- case AGP:
+ case VIA_MEM_AGP:
if (via_agp_free(&mem) == 0)
return 0;
break;
@@ -329,7 +329,7 @@ static int via_fb_free(drm_via_mem_t * mem)
via_mmFreeMem((PMemBlock) fb.free);
- if (!del_alloc_set(fb.context, VIDEO, fb.free)) {
+ if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
retval = -1;
}
@@ -352,7 +352,7 @@ static int via_agp_free(drm_via_mem_t * mem)
via_mmFreeMem((PMemBlock) agp.free);
- if (!del_alloc_set(agp.context, AGP, agp.free)) {
+ if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
retval = -1;
}
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 4ac495f297f7..70c897c88766 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -237,7 +237,7 @@ static hazard_t table3[256];
static __inline__ int
eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
{
- if ((*buf - buf_end) >= num_words) {
+ if ((buf_end - *buf) >= num_words) {
*buf += num_words;
return 0;
}
@@ -249,14 +249,14 @@ eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
* Partially stolen from drm_memory.h
*/
-static __inline__ drm_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
+static __inline__ drm_local_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;
+ drm_local_map_t *map = seq->map_cache;
if (map && map->offset <= offset
&& (offset + size) <= (map->offset + map->size)) {
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index eb4eda344345..256590fcc22a 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -47,7 +47,7 @@ typedef struct {
int agp_texture;
int multitex;
drm_device_t *dev;
- drm_map_t *map_cache;
+ drm_local_map_t *map_cache;
uint32_t vertex_count;
int agp;
const uint32_t *buf_start;
@@ -55,5 +55,7 @@ typedef struct {
extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
drm_device_t * dev, int agp);
+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_video.c b/drivers/char/drm/via_video.c
index 7fab9fbdf424..300ac61b09ed 100644
--- a/drivers/char/drm/via_video.c
+++ b/drivers/char/drm/via_video.c
@@ -50,8 +50,11 @@ void via_release_futex(drm_via_private_t * dev_priv, int context)
unsigned int i;
volatile int *lock;
+ if (!dev_priv->sarea_priv)
+ return;
+
for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
- lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
+ lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
if (_DRM_LOCK_IS_HELD(*lock)
&& (*lock & _DRM_LOCK_CONT)) {
@@ -79,7 +82,7 @@ int via_decoder_futex(DRM_IOCTL_ARGS)
if (fx.lock > VIA_NR_XVMC_LOCKS)
return -EFAULT;
- lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock);
+ lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock);
switch (fx.func) {
case VIA_FUTEX_WAIT:
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8693835cb2d5..e233cf280bc0 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -165,7 +165,7 @@ static int dsp56k_reset(void)
return 0;
}
-static int dsp56k_upload(u_char *bin, int len)
+static int dsp56k_upload(u_char __user *bin, int len)
{
int i;
u_char *p;
@@ -199,7 +199,7 @@ static int dsp56k_upload(u_char *bin, int len)
return 0;
}
-static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
@@ -225,10 +225,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
}
case 2: /* 16 bit */
{
- short *data;
+ short __user *data;
count /= 2;
- data = (short*) buf;
+ data = (short __user *) buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
put_user(dsp56k_host_interface.data.w[1], data+n++));
return 2*n;
@@ -244,10 +244,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
}
case 4: /* 32 bit */
{
- long *data;
+ long __user *data;
count /= 4;
- data = (long*) buf;
+ data = (long __user *) buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
put_user(dsp56k_host_interface.data.l, data+n++));
return 4*n;
@@ -262,7 +262,7 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
}
}
-static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
+static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
@@ -287,10 +287,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
}
case 2: /* 16 bit */
{
- const short *data;
+ const short __user *data;
count /= 2;
- data = (const short *)buf;
+ data = (const short __user *)buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
get_user(dsp56k_host_interface.data.w[1], data+n++));
return 2*n;
@@ -306,10 +306,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
}
case 4: /* 32 bit */
{
- const long *data;
+ const long __user *data;
count /= 4;
- data = (const long *)buf;
+ data = (const long __user *)buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
get_user(dsp56k_host_interface.data.l, data+n++));
return 4*n;
@@ -328,6 +328,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int dev = iminor(inode) & 0x0f;
+ void __user *argp = (void __user *)arg;
switch(dev)
{
@@ -336,9 +337,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
switch(cmd) {
case DSP56K_UPLOAD:
{
- char *bin;
+ char __user *bin;
int r, len;
- struct dsp56k_upload *binary = (struct dsp56k_upload *) arg;
+ struct dsp56k_upload __user *binary = argp;
if(get_user(len, &binary->len) < 0)
return -EFAULT;
@@ -372,7 +373,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
case DSP56K_HOST_FLAGS:
{
int dir, out, status;
- struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg;
+ struct dsp56k_host_flags __user *hf = argp;
if(get_user(dir, &hf->dir) < 0)
return -EFAULT;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 407708a001e4..765c5c108bf4 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1786,9 +1786,7 @@ static void doevent(int crd)
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_insert_flip_char(tty, 0, TTY_BREAK);
tty_schedule_flip(tty);
} else if (event & LOWTX_IND) { /* Begin LOWTX_IND */
if (ch->statusflags & LOWWAIT)
@@ -2124,7 +2122,6 @@ static void receive_data(struct channel *ch)
int dataToRead, wrapgap, bytesAvailable;
unsigned int tail, head;
unsigned int wrapmask;
- int rc;
/* ---------------------------------------------------------------
This routine is called by doint when a receive data event
@@ -2162,16 +2159,15 @@ static void receive_data(struct channel *ch)
return;
}
- if (tty->flip.count == TTY_FLIPBUF_SIZE)
+ if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
return;
if (readb(&bc->orun)) {
writeb(0, &bc->orun);
printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
rxwinon(ch);
- rptr = tty->flip.char_buf_ptr;
- rc = tty->flip.count;
while (bytesAvailable > 0) { /* Begin while there is data on the card */
wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
/* ---------------------------------------------------------------
@@ -2183,8 +2179,7 @@ static void receive_data(struct channel *ch)
/* --------------------------------------------------------------
Make sure we don't overflow the buffer
----------------------------------------------------------------- */
- if ((rc + dataToRead) > TTY_FLIPBUF_SIZE)
- dataToRead = TTY_FLIPBUF_SIZE - rc;
+ dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
if (dataToRead == 0)
break;
/* ---------------------------------------------------------------
@@ -2192,13 +2187,9 @@ static void receive_data(struct channel *ch)
for translation if necessary.
------------------------------------------------------------------ */
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);
writew(tail, &bc->rout);
/* Must be called with global data */
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 9f53d2fcc360..3f3ac039f4d9 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int);
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static inline int serial_paranoia_check(struct esp_struct *info,
char *name, const char *routine)
@@ -345,26 +344,22 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
for (i = 0; i < num_bytes; i++) {
if (!(err_buf->data[i] & status_mask)) {
- *(tty->flip.char_buf_ptr++) = pio_buf->data[i];
+ int flag = 0;
if (err_buf->data[i] & 0x04) {
- *(tty->flip.flag_buf_ptr++) = TTY_BREAK;
-
+ flag = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
}
else if (err_buf->data[i] & 0x02)
- *(tty->flip.flag_buf_ptr++) = TTY_FRAME;
+ flag = TTY_FRAME;
else if (err_buf->data[i] & 0x01)
- *(tty->flip.flag_buf_ptr++) = TTY_PARITY;
- else
- *(tty->flip.flag_buf_ptr++) = 0;
-
- tty->flip.count++;
+ flag = TTY_PARITY;
+ tty_insert_flip_char(tty, pio_buf->data[i], flag);
}
}
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
release_pio_buffer(pio_buf);
@@ -397,7 +392,6 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
int num_bytes;
unsigned long flags;
-
flags=claim_dma_lock();
disable_dma(dma);
clear_dma_ff(dma);
@@ -408,38 +402,31 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
info->icount.rx += num_bytes;
- memcpy(tty->flip.char_buf_ptr, dma_buffer, num_bytes);
- tty->flip.char_buf_ptr += num_bytes;
- tty->flip.count += num_bytes;
- memset(tty->flip.flag_buf_ptr, 0, num_bytes);
- tty->flip.flag_buf_ptr += num_bytes;
-
if (num_bytes > 0) {
- tty->flip.flag_buf_ptr--;
+ tty_insert_flip_string(tty, dma_buffer, num_bytes - 1);
status &= (0x1c & info->read_status_mask);
+
+ /* Is the status significant or do we throw the last byte ? */
+ if (!(status & info->ignore_status_mask)) {
+ int statflag = 0;
- if (status & info->ignore_status_mask) {
- tty->flip.count--;
- tty->flip.char_buf_ptr--;
- tty->flip.flag_buf_ptr--;
- } else if (status & 0x10) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- (info->icount.brk)++;
- if (info->flags & ASYNC_SAK)
- do_SAK(tty);
- } else if (status & 0x08) {
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- (info->icount.frame)++;
- }
- else if (status & 0x04) {
- *tty->flip.flag_buf_ptr = TTY_PARITY;
- (info->icount.parity)++;
+ if (status & 0x10) {
+ statflag = TTY_BREAK;
+ (info->icount.brk)++;
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (status & 0x08) {
+ statflag = TTY_FRAME;
+ (info->icount.frame)++;
+ }
+ else if (status & 0x04) {
+ statflag = TTY_PARITY;
+ (info->icount.parity)++;
+ }
+ tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
}
-
- tty->flip.flag_buf_ptr++;
-
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
if (dma_bytes != num_bytes) {
@@ -693,8 +680,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id,
num_bytes = serial_in(info, UART_ESI_STAT1) << 8;
num_bytes |= serial_in(info, UART_ESI_STAT2);
- if (num_bytes > (TTY_FLIPBUF_SIZE - info->tty->flip.count))
- num_bytes = TTY_FLIPBUF_SIZE - info->tty->flip.count;
+ num_bytes = tty_buffer_request_room(info->tty, num_bytes);
if (num_bytes) {
if (dma_bytes ||
@@ -2506,6 +2492,7 @@ static int __init espserial_init(void)
}
memset((void *)info, 0, sizeof(struct esp_struct));
+ spin_lock_init(&info->lock);
/* rx_trigger, tx_trigger are needed by autoconfig */
info->config.rx_trigger = rx_trigger;
info->config.tx_trigger = tx_trigger;
@@ -2542,7 +2529,6 @@ static int __init espserial_init(void)
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait);
- spin_lock_init(&info->lock);
ports = info;
printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
info->line, info->port, info->irq);
diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig
index 7d3ecb56a1bd..0d65189a7ae8 100644
--- a/drivers/char/ftape/Kconfig
+++ b/drivers/char/ftape/Kconfig
@@ -25,17 +25,7 @@ config ZFTAPE
support", above) then `zft-compressor' will be loaded
automatically by zftape when needed.
- Despite its name, zftape does NOT use compression by default. The
- file <file:Documentation/ftape.txt> contains a short description of
- the most important changes in the file system interface compared to
- previous versions of ftape. The ftape home page
- <http://www.instmath.rwth-aachen.de/~heine/ftape/> contains
- further information.
-
- IMPORTANT NOTE: zftape can read archives created by previous
- versions of ftape and provide file mark support (i.e. fast skipping
- between tape archives) but previous version of ftape will lack file
- mark support when reading archives produced by zftape.
+ Despite its name, zftape does NOT use compression by default.
config ZFT_DFLT_BLK_SZ
int "Default block size"
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 204a7302a4a9..e38a5f0e07bb 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -34,7 +34,6 @@
#define DEBUG
static char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static int gs_debug;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f92177634677..1994a92d4733 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -597,9 +597,7 @@ static int hvc_poll(struct hvc_struct *hp)
/* Read data if any */
for (;;) {
- int count = N_INBUF;
- if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
- count = TTY_FLIPBUF_SIZE - tty->flip.count;
+ int count = tty_buffer_request_room(tty, N_INBUF);
/* If flip is full, just reschedule a later read */
if (count == 0) {
@@ -635,7 +633,7 @@ static int hvc_poll(struct hvc_struct *hp)
tty_insert_flip_char(tty, buf[i], 0);
}
- if (tty->flip.count)
+ if (count)
tty_schedule_flip(tty);
/*
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 53dc77c760fc..831eb4e8d9d3 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -456,12 +456,11 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
/* remove the read masks */
hvcsd->todo_mask &= ~(HVCS_READ_MASK);
- if ((tty->flip.count + HVCS_BUFF_LEN) < TTY_FLIPBUF_SIZE) {
+ if (tty_buffer_request_room(tty, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
got = hvc_get_chars(unit_address,
&buf[0],
HVCS_BUFF_LEN);
- for (i=0;got && i<got;i++)
- tty_insert_flip_char(tty, buf[i], TTY_NORMAL);
+ tty_insert_flip_string(tty, buf, got);
}
/* Give the TTY time to process the data we just sent. */
@@ -469,10 +468,9 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
hvcsd->todo_mask |= HVCS_QUICK_READ;
spin_unlock_irqrestore(&hvcsd->lock, flags);
- if (tty->flip.count) {
- /* This is synch because tty->low_latency == 1 */
+ /* This is synch because tty->low_latency == 1 */
+ if(got)
tty_flip_buffer_push(tty);
- }
if (!got) {
/* Do this _after_ the flip_buffer_push */
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index a22aa940e01e..a9522189fc9e 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -197,7 +197,7 @@ static inline void print_state(struct hvsi_struct *hp)
};
const char *name = state_names[hp->state];
- if (hp->state > (sizeof(state_names)/sizeof(char*)))
+ if (hp->state > ARRAY_SIZE(state_names))
name = "UNKNOWN";
pr_debug("hvsi%i: state = %s\n", hp->index, name);
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 49769f59ea1b..b3bc2e37e616 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -169,6 +169,7 @@ static struct pci_device_id rng_pci_tbl[] = {
{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index ba85eb1b6ec7..fc944d375be7 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -854,7 +854,7 @@ i2Input(i2ChanStrPtr pCh)
count += IBUF_SIZE;
}
// Don't give more than can be taken by the line discipline
- amountToMove = pCh->pTTY->ldisc.receive_room( pCh->pTTY );
+ amountToMove = pCh->pTTY->receive_room;
if (count > amountToMove) {
count = amountToMove;
}
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index d815d197dc3e..56e93a5a1e24 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -172,7 +172,7 @@ static int Fip_firmware_size;
/* Private (static) functions */
static int ip2_open(PTTY, struct file *);
static void ip2_close(PTTY, struct file *);
-static int ip2_write(PTTY, int, const unsigned char *, int);
+static int ip2_write(PTTY, const unsigned char *, int);
static void ip2_putchar(PTTY, unsigned char);
static void ip2_flush_chars(PTTY);
static int ip2_write_room(PTTY);
@@ -1713,7 +1713,7 @@ ip2_hangup ( PTTY tty )
/* */
/******************************************************************************/
static int
-ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
+ip2_write( PTTY tty, const unsigned char *pData, int count)
{
i2ChanStrPtr pCh = tty->driver_data;
int bytesSent = 0;
@@ -1726,7 +1726,7 @@ ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
/* This is the actual move bit. Make sure it does what we need!!!!! */
WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
- bytesSent = i2Output( pCh, pData, count, user );
+ bytesSent = i2Output( pCh, pData, count, 0 );
WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
@@ -2001,7 +2001,9 @@ ip2_stop ( PTTY tty )
static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
{
i2ChanStrPtr pCh = DevTable[tty->index];
+#ifdef ENABLE_DSSNOW
wait_queue_t wait;
+#endif
if (pCh == NULL)
return -ENODEV;
@@ -2089,15 +2091,17 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
{
wait_queue_t wait;
i2ChanStrPtr pCh = DevTable[tty->index];
+ i2eBordStrPtr pB;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser;
int rc = 0;
unsigned long flags;
void __user *argp = (void __user *)arg;
- if ( pCh == NULL ) {
+ if ( pCh == NULL )
return -ENODEV;
- }
+
+ pB = pCh->pMyBord;
ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
@@ -2206,9 +2210,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
* for masking). Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
- save_flags(flags);cli();
+ WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
cprev = pCh->icount; /* note the counters on entry */
- restore_flags(flags);
+ WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4,
CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
init_waitqueue_entry(&wait, current);
@@ -2228,9 +2232,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
rc = -ERESTARTSYS;
break;
}
- save_flags(flags);cli();
+ WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
cnow = pCh->icount; /* atomic copy */
- restore_flags(flags);
+ WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
rc = -EIO; /* no change => rc */
@@ -2268,9 +2272,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
case TIOCGICOUNT:
ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
- save_flags(flags);cli();
+ WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
cnow = pCh->icount;
- restore_flags(flags);
+ WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
p_cuser = argp;
rc = put_user(cnow.cts, &p_cuser->cts);
rc = put_user(cnow.dsr, &p_cuser->dsr);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 561430ed94af..0097f06fa67b 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -57,6 +57,7 @@ static int initialized = 0;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_ipmi_root = NULL;
+EXPORT_SYMBOL(proc_ipmi_root);
#endif /* CONFIG_PROC_FS */
#define MAX_EVENTS_IN_QUEUE 25
@@ -3295,6 +3296,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
EXPORT_SYMBOL(ipmi_set_my_LUN);
EXPORT_SYMBOL(ipmi_get_my_LUN);
EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
-EXPORT_SYMBOL(proc_ipmi_root);
EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
EXPORT_SYMBOL(ipmi_free_recv_msg);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e053eade0366..49c09ae004bf 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -612,11 +612,14 @@ static int ipmi_poweroff_init (void)
#endif
rv = ipmi_smi_watcher_register(&smi_watcher);
+
+#ifdef CONFIG_PROC_FS
if (rv) {
unregister_sysctl_table(ipmi_table_header);
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
goto out_err;
}
+#endif
out_err:
return rv;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index beea450ee4b2..c67ef3e47ad5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1056,7 +1056,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) || defined(CONFIG_X86) || defined(CONFIG_PCI)
+#if defined(CONFIG_ACPI) || defined(CONFIG_DMI) || defined(CONFIG_PCI)
static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr)
{
int i;
@@ -1669,7 +1669,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
}
#endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_DMI
typedef struct dmi_ipmi_data
{
u8 type;
@@ -1829,7 +1829,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
ipmi_data->slave_addr);
return 0;
}
-#endif /* CONFIG_X86 */
+#endif /* CONFIG_DMI */
#ifdef CONFIG_PCI
@@ -2222,7 +2222,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
if (rv && si_trydefaults)
rv = try_init_acpi(intf_num, &new_smi);
#endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_DMI
if (rv && si_trydefaults)
rv = try_init_smbios(intf_num, &new_smi);
#endif
@@ -2433,7 +2433,7 @@ static __init int init_ipmi_si(void)
printk(KERN_INFO "IPMI System Interface driver.\n");
-#ifdef CONFIG_X86
+#ifdef CONFIG_DMI
dmi_find_bmc();
#endif
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 1bbf507adda5..e9ebabaf8cb0 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -20,7 +20,7 @@
* 3/9/99 sameer Added support for ISI4616 cards.
*
* 16/9/99 sameer We do not force RTS low anymore.
- * This is to prevent the firmware
+ * This is to prevent the firmware
* from getting confused.
*
* 26/10/99 sameer Cosmetic changes:The driver now
@@ -31,28 +31,28 @@
*
* 10/5/00 sameer Fixed isicom_shutdown_board()
* to not lower DTR on all the ports
- * when the last port on the card is
+ * when the last port on the card is
* closed.
*
* 10/5/00 sameer Signal mask setup command added
- * to isicom_setup_port and
+ * to isicom_setup_port and
* isicom_shutdown_port.
*
* 24/5/00 sameer The driver is now SMP aware.
- *
- *
+ *
+ *
* 27/11/00 Vinayak P Risbud Fixed the Driver Crash Problem
- *
- *
+ *
+ *
* 03/01/01 anil .s Added support for resetting the
* internal modems on ISI cards.
*
* 08/02/01 anil .s Upgraded the driver for kernel
* 2.4.x
*
- * 11/04/01 Kevin Fixed firmware load problem with
+ * 11/04/01 Kevin Fixed firmware load problem with
* ISIHP-4X card
- *
+ *
* 30/04/01 anil .s Fixed the remote login through
* ISI port problem. Now the link
* does not go down before password
@@ -62,9 +62,9 @@
* among ISI-PCI cards.
*
* 03/05/01 anil .s Added support to display the version
- * info during insmod as well as module
+ * info during insmod as well as module
* listing by lsmod.
- *
+ *
* 10/05/01 anil .s Done the modifications to the source
* file and Install script so that the
* same installation can be used for
@@ -73,19 +73,19 @@
* 06/06/01 anil .s Now we drop both dtr and rts during
* shutdown_port as well as raise them
* during isicom_config_port.
- *
+ *
* 09/06/01 acme@conectiva.com.br use capable, not suser, do
* restore_flags on failure in
* isicom_send_break, verify put_user
* result
*
- * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps
- * Baud index extended to 21
- *
- * 20/03/03 ranjeeth Made to work for Linux Advanced server.
- * Taken care of license warning.
- *
- * 10/12/03 Ravindra Made to work for Fedora Core 1 of
+ * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps
+ * Baud index extended to 21
+ *
+ * 20/03/03 ranjeeth Made to work for Linux Advanced server.
+ * Taken care of license warning.
+ *
+ * 10/12/03 Ravindra Made to work for Fedora Core 1 of
* Red Hat Distribution
*
* 06/01/05 Alan Cox Merged the ISI and base kernel strands
@@ -93,10 +93,10 @@
*
* ***********************************************************
*
- * To use this driver you also need the support package. You
+ * To use this driver you also need the support package. You
* can find this in RPM format on
* ftp://ftp.linux.org.uk/pub/linux/alan
- *
+ *
* You can find the original tools for this direct from Multitech
* ftp://ftp.multitech.com/ISI-Cards/
*
@@ -107,20 +107,20 @@
* Omit those entries for boards you don't have installed.
*
* TODO
- * Hotplug
* Merge testing
* 64-bit verification
*/
#include <linux/module.h>
+#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/termios.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/serial.h>
#include <linux/mm.h>
-#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/delay.h>
@@ -134,50 +134,62 @@
#include <linux/isicom.h>
+#define InterruptTheCard(base) outw(0, (base) + 0xc)
+#define ClearInterrupt(base) inw((base) + 0x0a)
+
+#ifdef DEBUG
+#define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str)
+#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
+#else
+#define pr_dbg(str...) do { } while (0)
+#define isicom_paranoia_check(a, b, c) 0
+#endif
+
+static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
+static void __devexit isicom_remove(struct pci_dev *);
+
static struct pci_device_id isicom_pci_tbl[] = {
- { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(VENDOR_ID, 0x2028) },
+ { PCI_DEVICE(VENDOR_ID, 0x2051) },
+ { PCI_DEVICE(VENDOR_ID, 0x2052) },
+ { PCI_DEVICE(VENDOR_ID, 0x2053) },
+ { PCI_DEVICE(VENDOR_ID, 0x2054) },
+ { PCI_DEVICE(VENDOR_ID, 0x2055) },
+ { PCI_DEVICE(VENDOR_ID, 0x2056) },
+ { PCI_DEVICE(VENDOR_ID, 0x2057) },
+ { PCI_DEVICE(VENDOR_ID, 0x2058) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
+static struct pci_driver isicom_driver = {
+ .name = "isicom",
+ .id_table = isicom_pci_tbl,
+ .probe = isicom_probe,
+ .remove = __devexit_p(isicom_remove)
+};
+
static int prev_card = 3; /* start servicing isi_card[0] */
static struct tty_driver *isicom_normal;
static struct timer_list tx;
static char re_schedule = 1;
-#ifdef ISICOM_DEBUG
-static unsigned long tx_count = 0;
-#endif
-
-static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static void isicom_tx(unsigned long _data);
-static void isicom_start(struct tty_struct * tty);
-
-static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
+static void isicom_start(struct tty_struct *tty);
/* baud index mappings from linux defns to isi */
static signed char linuxb_to_isib[] = {
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,
- 18, 19
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19
};
struct isi_board {
- unsigned short base;
+ unsigned long base;
unsigned char irq;
unsigned char port_count;
unsigned short status;
- unsigned short port_status; /* each bit represents a single port */
+ unsigned short port_status; /* each bit for each port */
unsigned short shift_count;
struct isi_port * ports;
signed char count;
@@ -192,9 +204,9 @@ struct isi_port {
int count;
int blocked_open;
int close_delay;
- unsigned short channel;
- unsigned short status;
- unsigned short closing_wait;
+ u16 channel;
+ u16 status;
+ u16 closing_wait;
struct isi_board * card;
struct tty_struct * tty;
wait_queue_head_t close_wait;
@@ -215,35 +227,37 @@ static struct isi_port isi_ports[PORT_COUNT];
* the kernel lock for the card and have the card in a position that
* it wants to talk.
*/
-
+
static int lock_card(struct isi_board *card)
{
char retries;
- unsigned short base = card->base;
+ unsigned long base = card->base;
for (retries = 0; retries < 100; retries++) {
spin_lock_irqsave(&card->card_lock, card->flags);
if (inw(base + 0xe) & 0x1) {
- return 1;
+ return 1;
} else {
spin_unlock_irqrestore(&card->card_lock, card->flags);
udelay(1000); /* 1ms */
}
}
- printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+ printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
+ card->base);
+
return 0; /* Failed to aquire the card! */
}
static int lock_card_at_interrupt(struct isi_board *card)
{
unsigned char retries;
- unsigned short base = card->base;
+ unsigned long base = card->base;
for (retries = 0; retries < 200; retries++) {
spin_lock_irqsave(&card->card_lock, card->flags);
if (inw(base + 0xe) & 0x1)
- return 1;
+ return 1;
else
spin_unlock_irqrestore(&card->card_lock, card->flags);
}
@@ -259,373 +273,141 @@ static void unlock_card(struct isi_board *card)
/*
* ISI Card specific ops ...
*/
-
-static void raise_dtr(struct isi_port * port)
+
+static void raise_dtr(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0504, base);
InterruptTheCard(base);
port->status |= ISI_DTR;
unlock_card(card);
}
-static inline void drop_dtr(struct isi_port * port)
-{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+static inline void drop_dtr(struct isi_port *port)
+{
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0404, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status &= ~ISI_DTR;
unlock_card(card);
}
-static inline void raise_rts(struct isi_port * port)
+static inline void raise_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0a04, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status |= ISI_RTS;
unlock_card(card);
}
-static inline void drop_rts(struct isi_port * port)
+static inline void drop_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0804, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status &= ~ISI_RTS;
unlock_card(card);
}
-static inline void raise_dtr_rts(struct isi_port * port)
+static inline void raise_dtr_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0f04, base);
InterruptTheCard(base);
port->status |= (ISI_DTR | ISI_RTS);
unlock_card(card);
}
-static void drop_dtr_rts(struct isi_port * port)
+static void drop_dtr_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0c04, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status &= ~(ISI_RTS | ISI_DTR);
unlock_card(card);
}
-static inline void kill_queue(struct isi_port * port, short queue)
+static inline void kill_queue(struct isi_port *port, short queue)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw((queue << 8) | 0x06, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
unlock_card(card);
}
-
-/*
- * Firmware loader driver specific routines. This needs to mostly die
- * and be replaced with request_firmware.
- */
-
-static struct file_operations ISILoad_fops = {
- .owner = THIS_MODULE,
- .ioctl = ISILoad_ioctl,
-};
-
-static struct miscdevice isiloader_device = {
- ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
-};
-
-
-static inline int WaitTillCardIsFree(unsigned short base)
-{
- unsigned long count=0;
- while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
- if (inw(base+0xe)&0x1)
- return 0;
- else
- return 1;
-}
-
-static int ISILoad_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- unsigned int card, i, j, signature, status, portcount = 0;
- unsigned long t;
- unsigned short word_count, base;
- bin_frame frame;
- void __user *argp = (void __user *)arg;
- /* exec_record exec_rec; */
-
- if(get_user(card, (int __user *)argp))
- return -EFAULT;
-
- if(card < 0 || card >= BOARD_COUNT)
- return -ENXIO;
-
- base=isi_card[card].base;
-
- if(base==0)
- return -ENXIO; /* disabled or not used */
-
- switch(cmd) {
- case MIOCTL_RESET_CARD:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
-
- inw(base+0x8);
-
- for(t=jiffies+HZ/100;time_before(jiffies, t););
-
- outw(0,base+0x8); /* Reset */
-
- for(j=1;j<=3;j++) {
- for(t=jiffies+HZ;time_before(jiffies, t););
- printk(".");
- }
- signature=(inw(base+0x4)) & 0xff;
- if (isi_card[card].isa) {
-
- if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
-#ifdef ISICOM_DEBUG
- printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif
- printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
- return -EIO;
- }
- }
- else {
- portcount = inw(base+0x2);
- if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {
-#ifdef ISICOM_DEBUG
- printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif
- printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
- return -EIO;
- }
- }
- switch(signature) {
- case 0xa5:
- case 0xbb:
- case 0xdd:
- if (isi_card[card].isa)
- isi_card[card].port_count = 8;
- else {
- if (portcount == 4)
- isi_card[card].port_count = 4;
- else
- isi_card[card].port_count = 8;
- }
- isi_card[card].shift_count = 12;
- break;
-
- case 0xcc: isi_card[card].port_count = 16;
- isi_card[card].shift_count = 11;
- break;
-
- default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-#ifdef ISICOM_DEBUG
- printk("Sig=0x%x\n",signature);
-#endif
- return -EIO;
- }
- printk("-Done\n");
- return put_user(signature,(unsigned __user *)argp);
-
- case MIOCTL_LOAD_FIRMWARE:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if(copy_from_user(&frame, argp, sizeof(bin_frame)))
- return -EFAULT;
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- outw(0xf0,base); /* start upload sequence */
- outw(0x00,base);
- outw((frame.addr), base);/* lsb of adderess */
-
- word_count=(frame.count >> 1) + frame.count % 2;
- outw(word_count, base);
- InterruptTheCard(base);
-
- for(i=0;i<=0x2f;i++); /* a wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
- card+1, frame.addr, frame.count, status);
- return -EIO;
- }
- outsw(base, (void *) frame.bin_data, word_count);
-
- InterruptTheCard(base);
-
- for(i=0;i<=0x0f;i++); /* another wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
- return -EIO;
- }
- return 0;
-
- case MIOCTL_READ_FIRMWARE:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if(copy_from_user(&frame, argp, sizeof(bin_header)))
- return -EFAULT;
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- outw(0xf1,base); /* start download sequence */
- outw(0x00,base);
- outw((frame.addr), base);/* lsb of adderess */
-
- word_count=(frame.count >> 1) + frame.count % 2;
- outw(word_count+1, base);
- InterruptTheCard(base);
-
- for(i=0;i<=0xf;i++); /* a wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
- card+1, frame.addr, frame.count, status);
- return -EIO;
- }
-
- inw(base);
- insw(base, frame.bin_data, word_count);
- InterruptTheCard(base);
-
- for(i=0;i<=0x0f;i++); /* another wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
- return -EIO;
- }
-
- if(copy_to_user(argp, &frame, sizeof(bin_frame)))
- return -EFAULT;
- return 0;
-
- case MIOCTL_XFER_CTRL:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- outw(0xf2, base);
- outw(0x800, base);
- outw(0x0, base);
- outw(0x0, base);
- InterruptTheCard(base);
- outw(0x0, base+0x4); /* for ISI4608 cards */
-
- isi_card[card].status |= FIRMWARE_LOADED;
- return 0;
-
- default:
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd);
-#endif
- return -ENOIOCTLCMD;
-
- }
-
-}
-
-
/*
* ISICOM Driver specific routines ...
*
*/
-
-static inline int isicom_paranoia_check(struct isi_port const * port, char *name,
- const char * routine)
+
+static inline int __isicom_paranoia_check(struct isi_port const *port,
+ char *name, const char *routine)
{
-#ifdef ISICOM_DEBUG
- static const char * badmagic =
- KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
- static const char * badport =
- KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";
if (!port) {
- printk(badport, name, routine);
+ printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
+ "dev %s in %s.\n", name, routine);
return 1;
}
if (port->magic != ISICOM_MAGIC) {
- printk(badmagic, name, routine);
+ printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
+ "dev %s in %s.\n", name, routine);
return 1;
- }
-#endif
+ }
+
return 0;
}
-
+
/*
- * Transmitter.
+ * Transmitter.
*
* We shovel data into the card buffers on a regular basis. The card
* will do the rest of the work for us.
@@ -635,25 +417,21 @@ static void isicom_tx(unsigned long _data)
{
short count = (BOARD_COUNT-1), card, base;
short txcount, wrd, residue, word_count, cnt;
- struct isi_port * port;
- struct tty_struct * tty;
-
-#ifdef ISICOM_DEBUG
- ++tx_count;
-#endif
-
+ struct isi_port *port;
+ struct tty_struct *tty;
+
/* find next active board */
card = (prev_card + 1) & 0x0003;
while(count-- > 0) {
- if (isi_card[card].status & BOARD_ACTIVE)
+ if (isi_card[card].status & BOARD_ACTIVE)
break;
- card = (card + 1) & 0x0003;
+ card = (card + 1) & 0x0003;
}
if (!(isi_card[card].status & BOARD_ACTIVE))
goto sched_again;
-
+
prev_card = card;
-
+
count = isi_card[card].port_count;
port = isi_card[card].ports;
base = isi_card[card].base;
@@ -662,18 +440,18 @@ static void isicom_tx(unsigned long _data)
continue;
/* port not active or tx disabled to force flow control */
if (!(port->flags & ASYNC_INITIALIZED) ||
- !(port->status & ISI_TXOK))
+ !(port->status & ISI_TXOK))
unlock_card(&isi_card[card]);
continue;
-
+
tty = port->tty;
-
-
- if(tty == NULL) {
+
+
+ if (tty == NULL) {
unlock_card(&isi_card[card]);
continue;
}
-
+
txcount = min_t(short, TX_SIZE, port->xmit_cnt);
if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
unlock_card(&isi_card[card]);
@@ -681,44 +459,45 @@ static void isicom_tx(unsigned long _data)
}
if (!(inw(base + 0x02) & (1 << port->channel))) {
unlock_card(&isi_card[card]);
- continue;
+ continue;
}
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n",
- txcount, port->channel+1);
-#endif
- outw((port->channel << isi_card[card].shift_count) | txcount
- , base);
+ pr_dbg("txing %d bytes, port%d.\n", txcount,
+ port->channel + 1);
+ outw((port->channel << isi_card[card].shift_count) | txcount,
+ base);
residue = NO;
- wrd = 0;
+ wrd = 0;
while (1) {
- cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+ cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
+ - port->xmit_tail));
if (residue == YES) {
residue = NO;
if (cnt > 0) {
- wrd |= (port->xmit_buf[port->xmit_tail] << 8);
- port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ wrd |= (port->xmit_buf[port->xmit_tail]
+ << 8);
+ port->xmit_tail = (port->xmit_tail + 1)
+ & (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt--;
txcount--;
cnt--;
- outw(wrd, base);
- }
- else {
+ outw(wrd, base);
+ } else {
outw(wrd, base);
break;
}
- }
+ }
if (cnt <= 0) break;
word_count = cnt >> 1;
- outsw(base, port->xmit_buf+port->xmit_tail, word_count);
- port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
- (SERIAL_XMIT_SIZE - 1);
+ outsw(base, port->xmit_buf+port->xmit_tail,word_count);
+ port->xmit_tail = (port->xmit_tail
+ + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
txcount -= (word_count << 1);
port->xmit_cnt -= (word_count << 1);
if (cnt & 0x0001) {
residue = YES;
wrd = port->xmit_buf[port->xmit_tail];
- port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_tail = (port->xmit_tail + 1)
+ & (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt--;
txcount--;
}
@@ -730,81 +509,82 @@ static void isicom_tx(unsigned long _data)
if (port->xmit_cnt <= WAKEUP_CHARS)
schedule_work(&port->bh_tqueue);
unlock_card(&isi_card[card]);
- }
+ }
+
+ /* schedule another tx for hopefully in about 10ms */
+sched_again:
+ if (!re_schedule) {
+ re_schedule = 2;
+ return;
+ }
- /* schedule another tx for hopefully in about 10ms */
-sched_again:
- if (!re_schedule)
- return;
init_timer(&tx);
tx.expires = jiffies + HZ/100;
tx.data = 0;
tx.function = isicom_tx;
add_timer(&tx);
-
- return;
-}
-
+
+ return;
+}
+
/* Interrupt handlers */
-
-static void isicom_bottomhalf(void * data)
+
+static void isicom_bottomhalf(void *data)
{
- struct isi_port * port = (struct isi_port *) data;
- struct tty_struct * tty = port->tty;
-
+ struct isi_port *port = (struct isi_port *) data;
+ struct tty_struct *tty = port->tty;
+
if (!tty)
return;
- tty_wakeup(tty);
+ tty_wakeup(tty);
wake_up_interruptible(&tty->write_wait);
-}
-
+}
+
/*
- * Main interrupt handler routine
+ * Main interrupt handler routine
*/
-
-static irqreturn_t isicom_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
+
+static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct isi_board * card;
- struct isi_port * port;
- struct tty_struct * tty;
- unsigned short base, header, word_count, count;
- unsigned char channel;
+ struct isi_board *card = dev_id;
+ struct isi_port *port;
+ struct tty_struct *tty;
+ unsigned long base;
+ u16 header, word_count, count, channel;
short byte_count;
-
- card = (struct isi_board *) dev_id;
+ unsigned char *rp;
if (!card || !(card->status & FIRMWARE_LOADED))
return IRQ_NONE;
-
+
base = card->base;
spin_lock(&card->card_lock);
-
+
if (card->isa == NO) {
/*
- * disable any interrupts from the PCI card and lower the
- * interrupt line
+ * disable any interrupts from the PCI card and lower the
+ * interrupt line
*/
outw(0x8000, base+0x04);
ClearInterrupt(base);
}
-
+
inw(base); /* get the dummy word out */
header = inw(base);
channel = (header & 0x7800) >> card->shift_count;
byte_count = header & 0xff;
if (channel + 1 > card->port_count) {
- printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
- base, channel+1);
+ printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
+ "%d(channel) > port_count.\n", base, channel+1);
if (card->isa)
ClearInterrupt(base);
else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
spin_unlock(&card->card_lock);
- return IRQ_HANDLED;
+ return IRQ_HANDLED;
}
port = card->ports + channel;
if (!(port->flags & ASYNC_INITIALIZED)) {
@@ -813,8 +593,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
else
outw(0x0000, base+0x04); /* enable interrupts */
return IRQ_HANDLED;
- }
-
+ }
+
tty = port->tty;
if (tty == NULL) {
word_count = byte_count >> 1;
@@ -831,224 +611,204 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
spin_unlock(&card->card_lock);
return IRQ_HANDLED;
}
-
+
if (header & 0x8000) { /* Status Packet */
header = inw(base);
switch(header & 0xff) {
- case 0: /* Change in EIA signals */
-
- if (port->flags & ASYNC_CHECK_CD) {
- if (port->status & ISI_DCD) {
- if (!(header & ISI_DCD)) {
- /* Carrier has been lost */
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
-#endif
- port->status &= ~ISI_DCD;
- schedule_work(&port->hangup_tq);
- }
- }
- else {
- if (header & ISI_DCD) {
- /* Carrier has been detected */
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
-#endif
- port->status |= ISI_DCD;
- wake_up_interruptible(&port->open_wait);
- }
- }
- }
- else {
- if (header & ISI_DCD)
- port->status |= ISI_DCD;
- else
+ case 0: /* Change in EIA signals */
+ if (port->flags & ASYNC_CHECK_CD) {
+ if (port->status & ISI_DCD) {
+ if (!(header & ISI_DCD)) {
+ /* Carrier has been lost */
+ pr_dbg("interrupt: DCD->low.\n"
+ );
port->status &= ~ISI_DCD;
- }
-
- if (port->flags & ASYNC_CTS_FLOW) {
- if (port->tty->hw_stopped) {
- if (header & ISI_CTS) {
- port->tty->hw_stopped = 0;
- /* start tx ing */
- port->status |= (ISI_TXOK | ISI_CTS);
- schedule_work(&port->bh_tqueue);
- }
- }
- else {
- if (!(header & ISI_CTS)) {
- port->tty->hw_stopped = 1;
- /* stop tx ing */
- port->status &= ~(ISI_TXOK | ISI_CTS);
- }
+ schedule_work(&port->hangup_tq);
}
+ } else if (header & ISI_DCD) {
+ /* Carrier has been detected */
+ pr_dbg("interrupt: DCD->high.\n");
+ port->status |= ISI_DCD;
+ wake_up_interruptible(&port->open_wait);
}
- else {
- if (header & ISI_CTS)
- port->status |= ISI_CTS;
- else
- port->status &= ~ISI_CTS;
- }
-
- if (header & ISI_DSR)
- port->status |= ISI_DSR;
+ } else {
+ if (header & ISI_DCD)
+ port->status |= ISI_DCD;
else
- port->status &= ~ISI_DSR;
-
- if (header & ISI_RI)
- port->status |= ISI_RI;
+ port->status &= ~ISI_DCD;
+ }
+
+ if (port->flags & ASYNC_CTS_FLOW) {
+ if (port->tty->hw_stopped) {
+ if (header & ISI_CTS) {
+ port->tty->hw_stopped = 0;
+ /* start tx ing */
+ port->status |= (ISI_TXOK
+ | ISI_CTS);
+ schedule_work(&port->bh_tqueue);
+ }
+ } else if (!(header & ISI_CTS)) {
+ port->tty->hw_stopped = 1;
+ /* stop tx ing */
+ port->status &= ~(ISI_TXOK | ISI_CTS);
+ }
+ } else {
+ if (header & ISI_CTS)
+ port->status |= ISI_CTS;
else
- port->status &= ~ISI_RI;
-
- break;
-
- case 1: /* Received Break !!! */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
- tty->flip.count++;
- if (port->flags & ASYNC_SAK)
- do_SAK(tty);
- schedule_delayed_work(&tty->flip.work, 1);
- break;
-
- case 2: /* Statistics */
- printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");
- break;
-
- default:
- printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
- break;
- }
- }
- else { /* Data Packet */
- count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n",
- count, byte_count);
-#endif
+ port->status &= ~ISI_CTS;
+ }
+
+ if (header & ISI_DSR)
+ port->status |= ISI_DSR;
+ else
+ port->status &= ~ISI_DSR;
+
+ if (header & ISI_RI)
+ port->status |= ISI_RI;
+ else
+ port->status &= ~ISI_RI;
+
+ break;
+
+ case 1: /* Received Break !!! */
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
+ if (port->flags & ASYNC_SAK)
+ do_SAK(tty);
+ tty_flip_buffer_push(tty);
+ break;
+
+ case 2: /* Statistics */
+ pr_dbg("isicom_interrupt: stats!!!.\n");
+ break;
+
+ default:
+ pr_dbg("Intr: Unknown code in status packet.\n");
+ break;
+ }
+ } else { /* Data Packet */
+
+ count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
+ pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
word_count = count >> 1;
- insw(base, tty->flip.char_buf_ptr, word_count);
- tty->flip.char_buf_ptr += (word_count << 1);
+ insw(base, rp, word_count);
byte_count -= (word_count << 1);
if (count & 0x0001) {
- *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
+ tty_insert_flip_char(tty, inw(base) & 0xff,
+ TTY_NORMAL);
byte_count -= 2;
- }
- memset(tty->flip.flag_buf_ptr, 0, count);
- tty->flip.flag_buf_ptr += count;
- tty->flip.count += count;
-
+ }
if (byte_count > 0) {
- printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
- base, channel+1);
+ pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
+ "bytes...\n", base, channel + 1);
while(byte_count > 0) { /* drain out unread xtra data */
inw(base);
byte_count -= 2;
}
}
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_flip_buffer_push(tty);
}
if (card->isa == YES)
ClearInterrupt(base);
else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
+
return IRQ_HANDLED;
-}
+}
-static void isicom_config_port(struct isi_port * port)
+static void isicom_config_port(struct isi_port *port)
{
- struct isi_board * card = port->card;
- struct tty_struct * tty;
+ struct isi_board *card = port->card;
+ struct tty_struct *tty;
unsigned long baud;
- unsigned short channel_setup, base = card->base;
- unsigned short channel = port->channel, shift_count = card->shift_count;
+ unsigned long base = card->base;
+ u16 channel_setup, channel = port->channel,
+ shift_count = card->shift_count;
unsigned char flow_ctrl;
-
+
if (!(tty = port->tty) || !tty->termios)
return;
baud = C_BAUD(tty);
if (baud & CBAUDEX) {
baud &= ~CBAUDEX;
-
+
/* if CBAUDEX bit is on and the baud is set to either 50 or 75
* then the card is programmed for 57.6Kbps or 115Kbps
* respectively.
- */
-
+ */
+
if (baud < 1 || baud > 2)
port->tty->termios->c_cflag &= ~CBAUDEX;
else
baud += 15;
- }
+ }
if (baud == 15) {
-
- /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
+
+ /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
* by the set_serial_info ioctl ... this is done by
* the 'setserial' utility.
- */
-
+ */
+
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- baud++; /* 57.6 Kbps */
+ baud++; /* 57.6 Kbps */
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- baud +=2; /* 115 Kbps */
+ baud +=2; /* 115 Kbps */
}
if (linuxb_to_isib[baud] == -1) {
/* hang up */
- drop_dtr(port);
- return;
- }
- else
+ drop_dtr(port);
+ return;
+ }
+ else
raise_dtr(port);
-
+
if (lock_card(card)) {
outw(0x8000 | (channel << shift_count) |0x03, base);
outw(linuxb_to_isib[baud] << 8 | 0x03, base);
channel_setup = 0;
switch(C_CSIZE(tty)) {
- case CS5:
- channel_setup |= ISICOM_CS5;
- break;
- case CS6:
- channel_setup |= ISICOM_CS6;
- break;
- case CS7:
- channel_setup |= ISICOM_CS7;
- break;
- case CS8:
- channel_setup |= ISICOM_CS8;
- break;
+ case CS5:
+ channel_setup |= ISICOM_CS5;
+ break;
+ case CS6:
+ channel_setup |= ISICOM_CS6;
+ break;
+ case CS7:
+ channel_setup |= ISICOM_CS7;
+ break;
+ case CS8:
+ channel_setup |= ISICOM_CS8;
+ break;
}
-
+
if (C_CSTOPB(tty))
channel_setup |= ISICOM_2SB;
if (C_PARENB(tty)) {
channel_setup |= ISICOM_EVPAR;
if (C_PARODD(tty))
- channel_setup |= ISICOM_ODPAR;
+ channel_setup |= ISICOM_ODPAR;
}
- outw(channel_setup, base);
+ outw(channel_setup, base);
InterruptTheCard(base);
- unlock_card(card);
- }
+ unlock_card(card);
+ }
if (C_CLOCAL(tty))
port->flags &= ~ASYNC_CHECK_CD;
else
- port->flags |= ASYNC_CHECK_CD;
-
+ port->flags |= ASYNC_CHECK_CD;
+
/* flow control settings ...*/
flow_ctrl = 0;
port->flags &= ~ASYNC_CTS_FLOW;
if (C_CRTSCTS(tty)) {
port->flags |= ASYNC_CTS_FLOW;
flow_ctrl |= ISICOM_CTSRTS;
- }
- if (I_IXON(tty))
+ }
+ if (I_IXON(tty))
flow_ctrl |= ISICOM_RESPOND_XONXOFF;
if (I_IXOFF(tty))
- flow_ctrl |= ISICOM_INITIATE_XONXOFF;
-
+ flow_ctrl |= ISICOM_INITIATE_XONXOFF;
+
if (lock_card(card)) {
outw(0x8000 | (channel << shift_count) |0x04, base);
outw(flow_ctrl << 8 | 0x05, base);
@@ -1056,22 +816,22 @@ static void isicom_config_port(struct isi_port * port)
InterruptTheCard(base);
unlock_card(card);
}
-
+
/* rx enabled -> enable port for rx on the card */
if (C_CREAD(tty)) {
card->port_status |= (1 << channel);
outw(card->port_status, base + 0x02);
}
}
-
-/* open et all */
-static inline void isicom_setup_board(struct isi_board * bp)
+/* open et all */
+
+static inline void isicom_setup_board(struct isi_board *bp)
{
int channel;
- struct isi_port * port;
+ struct isi_port *port;
unsigned long flags;
-
+
spin_lock_irqsave(&bp->card_lock, flags);
if (bp->status & BOARD_ACTIVE) {
spin_unlock_irqrestore(&bp->card_lock, flags);
@@ -1080,53 +840,54 @@ static inline void isicom_setup_board(struct isi_board * bp)
port = bp->ports;
bp->status |= BOARD_ACTIVE;
spin_unlock_irqrestore(&bp->card_lock, flags);
- for(channel = 0; channel < bp->port_count; channel++, port++)
+ for (channel = 0; channel < bp->port_count; channel++, port++)
drop_dtr_rts(port);
return;
}
-
-static int isicom_setup_port(struct isi_port * port)
+
+static int isicom_setup_port(struct isi_port *port)
{
- struct isi_board * card = port->card;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (port->flags & ASYNC_INITIALIZED) {
return 0;
}
if (!port->xmit_buf) {
unsigned long page;
-
+
if (!(page = get_zeroed_page(GFP_KERNEL)))
return -ENOMEM;
-
+
if (port->xmit_buf) {
free_page(page);
return -ERESTARTSYS;
}
- port->xmit_buf = (unsigned char *) page;
- }
+ port->xmit_buf = (unsigned char *) page;
+ }
spin_lock_irqsave(&card->card_lock, flags);
if (port->tty)
clear_bit(TTY_IO_ERROR, &port->tty->flags);
if (port->count == 1)
card->count++;
-
+
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
+
/* discard any residual data */
kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
-
+
isicom_config_port(port);
port->flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&card->card_lock, flags);
-
- return 0;
-}
-
-static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port)
+
+ return 0;
+}
+
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct isi_port *port)
{
- struct isi_board * card = port->card;
+ struct isi_board *card = port->card;
int do_clocal = 0, retval;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
@@ -1134,30 +895,27 @@ static int block_til_ready(struct tty_struct * tty, struct file * filp, struct i
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
-#endif
+ pr_dbg("block_til_ready: close in progress.\n");
interruptible_sleep_on(&port->close_wait);
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
}
-
+
/* if non-blocking mode is set ... */
-
- if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
-#endif
+
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ pr_dbg("block_til_ready: non-block mode.\n");
port->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
+ return 0;
+ }
+
if (C_CLOCAL(tty))
do_clocal = 1;
-
- /* block waiting for DCD to be asserted, and while
+
+ /* block waiting for DCD to be asserted, and while
callout dev is busy */
retval = 0;
add_wait_queue(&port->open_wait, &wait);
@@ -1167,27 +925,27 @@ static int block_til_ready(struct tty_struct * tty, struct file * filp, struct i
port->count--;
port->blocked_open++;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
while (1) {
raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
- }
+ }
if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || (port->status & ISI_DCD))) {
+ (do_clocal || (port->status & ISI_DCD))) {
break;
- }
+ }
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
- schedule();
+ schedule();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
@@ -1201,11 +959,11 @@ static int block_til_ready(struct tty_struct * tty, struct file * filp, struct i
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
-
-static int isicom_open(struct tty_struct * tty, struct file * filp)
+
+static int isicom_open(struct tty_struct *tty, struct file *filp)
{
- struct isi_port * port;
- struct isi_board * card;
+ struct isi_port *port;
+ struct isi_board *card;
unsigned int line, board;
int error;
@@ -1214,20 +972,20 @@ static int isicom_open(struct tty_struct * tty, struct file * filp)
return -ENODEV;
board = BOARD(line);
card = &isi_card[board];
-
+
if (!(card->status & FIRMWARE_LOADED))
return -ENODEV;
-
+
/* open on a port greater than the port count for the card !!! */
if (line > ((board * 16) + card->port_count - 1))
return -ENODEV;
- port = &isi_ports[line];
+ port = &isi_ports[line];
if (isicom_paranoia_check(port, tty->name, "isicom_open"))
return -ENODEV;
-
- isicom_setup_board(card);
-
+
+ isicom_setup_board(card);
+
port->count++;
tty->driver_data = port;
port->tty = tty;
@@ -1236,12 +994,12 @@ static int isicom_open(struct tty_struct * tty, struct file * filp)
if ((error = block_til_ready(tty, filp, port))!=0)
return error;
- return 0;
+ return 0;
}
-
+
/* close et all */
-static inline void isicom_shutdown_board(struct isi_board * bp)
+static inline void isicom_shutdown_board(struct isi_board *bp)
{
unsigned long flags;
@@ -1252,15 +1010,15 @@ static inline void isicom_shutdown_board(struct isi_board * bp)
spin_unlock_irqrestore(&bp->card_lock, flags);
}
-static void isicom_shutdown_port(struct isi_port * port)
+static void isicom_shutdown_port(struct isi_port *port)
{
- struct isi_board * card = port->card;
- struct tty_struct * tty;
+ struct isi_board *card = port->card;
+ struct tty_struct *tty;
unsigned long flags;
-
+
tty = port->tty;
- spin_lock_irqsave(&card->card_lock, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
if (!(port->flags & ASYNC_INITIALIZED)) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
@@ -1268,93 +1026,91 @@ static void isicom_shutdown_port(struct isi_port * port)
if (port->xmit_buf) {
free_page((unsigned long) port->xmit_buf);
port->xmit_buf = NULL;
- }
+ }
port->flags &= ~ASYNC_INITIALIZED;
/* 3rd October 2000 : Vinayak P Risbud */
port->tty = NULL;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
/*Fix done by Anil .S on 30-04-2001
remote login through isi port has dtr toggle problem
due to which the carrier drops before the password prompt
- appears on the remote end. Now we drop the dtr only if the
+ appears on the remote end. Now we drop the dtr only if the
HUPCL(Hangup on close) flag is set for the tty*/
-
- if (C_HUPCL(tty))
+
+ if (C_HUPCL(tty))
/* drop dtr on this port */
drop_dtr(port);
-
- /* any other port uninits */
+
+ /* any other port uninits */
if (tty)
set_bit(TTY_IO_ERROR, &tty->flags);
-
+
if (--card->count < 0) {
- printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
+ pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
card->base, card->count);
- card->count = 0;
+ card->count = 0;
}
-
- /* last port was closed , shutdown that boad too */
- if(C_HUPCL(tty)) {
+
+ /* last port was closed, shutdown that boad too */
+ if (C_HUPCL(tty)) {
if (!card->count)
isicom_shutdown_board(card);
}
}
-static void isicom_close(struct tty_struct * tty, struct file * filp)
+static void isicom_close(struct tty_struct *tty, struct file *filp)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (!port)
return;
if (isicom_paranoia_check(port, tty->name, "isicom_close"))
return;
-
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
-#endif
-
+
+ pr_dbg("Close start!!!.\n");
+
spin_lock_irqsave(&card->card_lock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
-
+
if (tty->count == 1 && port->count != 1) {
- printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
- "tty->count = 1 port count = %d.\n",
+ printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
+ "count tty->count = 1 port count = %d.\n",
card->base, port->count);
port->count = 1;
}
if (--port->count < 0) {
- printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
- "channel%d = %d", card->base, port->channel,
+ printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
+ "count for channel%d = %d", card->base, port->channel,
port->count);
- port->count = 0;
+ port->count = 0;
}
-
+
if (port->count) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
- }
+ }
port->flags |= ASYNC_CLOSING;
tty->closing = 1;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->closing_wait);
- /* indicate to the card that no more data can be received
+ /* indicate to the card that no more data can be received
on this port */
spin_lock_irqsave(&card->card_lock, flags);
- if (port->flags & ASYNC_INITIALIZED) {
+ if (port->flags & ASYNC_INITIALIZED) {
card->port_status &= ~(1 << port->channel);
outw(card->port_status, card->base + 0x02);
- }
+ }
isicom_shutdown_port(port);
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
@@ -1365,65 +1121,65 @@ static void isicom_close(struct tty_struct * tty, struct file * filp)
if (port->blocked_open) {
spin_unlock_irqrestore(&card->card_lock, flags);
if (port->close_delay) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
-#endif
- msleep_interruptible(jiffies_to_msecs(port->close_delay));
+ pr_dbg("scheduling until time out.\n");
+ msleep_interruptible(
+ jiffies_to_msecs(port->close_delay));
}
spin_lock_irqsave(&card->card_lock, flags);
wake_up_interruptible(&port->open_wait);
- }
+ }
port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
wake_up_interruptible(&port->close_wait);
spin_unlock_irqrestore(&card->card_lock, flags);
}
/* write et all */
-static int isicom_write(struct tty_struct * tty,
- const unsigned char * buf, int count)
+static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
+ int count)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
int cnt, total = 0;
if (isicom_paranoia_check(port, tty->name, "isicom_write"))
return 0;
-
- if (!tty || !port->xmit_buf || !tmp_buf)
+
+ if (!tty || !port->xmit_buf)
return 0;
-
+
spin_lock_irqsave(&card->card_lock, flags);
-
- while(1) {
- cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - port->xmit_head));
- if (cnt <= 0)
+
+ while(1) {
+ cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
+ - 1, SERIAL_XMIT_SIZE - port->xmit_head));
+ if (cnt <= 0)
break;
-
+
memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
- port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
+ - 1);
port->xmit_cnt += cnt;
buf += cnt;
count -= cnt;
total += cnt;
- }
+ }
if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
port->status |= ISI_TXOK;
spin_unlock_irqrestore(&card->card_lock, flags);
- return total;
+ return total;
}
/* put_char et all */
-static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
return;
-
+
if (!tty || !port->xmit_buf)
return;
@@ -1432,7 +1188,7 @@ static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
-
+
port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt++;
@@ -1440,30 +1196,31 @@ static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
}
/* flush_chars et all */
-static void isicom_flush_chars(struct tty_struct * tty)
+static void isicom_flush_chars(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
return;
-
- if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !port->xmit_buf)
+
+ if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+ !port->xmit_buf)
return;
-
+
/* this tells the transmitter to consider this port for
data output to the card ... that's the best we can do. */
- port->status |= ISI_TXOK;
+ port->status |= ISI_TXOK;
}
/* write_room et all */
-static int isicom_write_room(struct tty_struct * tty)
+static int isicom_write_room(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
int free;
if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
return 0;
-
+
free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
if (free < 0)
free = 0;
@@ -1471,23 +1228,24 @@ static int isicom_write_room(struct tty_struct * tty)
}
/* chars_in_buffer et all */
-static int isicom_chars_in_buffer(struct tty_struct * tty)
+static int isicom_chars_in_buffer(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
return 0;
return port->xmit_cnt;
}
/* ioctl et all */
-static inline void isicom_send_break(struct isi_port * port, unsigned long length)
+static inline void isicom_send_break(struct isi_port *port,
+ unsigned long length)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
-
- if(!lock_card(card))
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+
+ if (!lock_card(card))
return;
-
+
outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
outw((length & 0xff) << 8 | 0x00, base);
outw((length & 0xff00), base);
@@ -1498,13 +1256,13 @@ static inline void isicom_send_break(struct isi_port * port, unsigned long lengt
static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
/* just send the port status */
- unsigned short status = port->status;
+ u16 status = port->status;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
-
+
return ((status & ISI_RTS) ? TIOCM_RTS : 0) |
((status & ISI_DTR) ? TIOCM_DTR : 0) |
((status & ISI_DCD) ? TIOCM_CAR : 0) |
@@ -1514,13 +1272,13 @@ static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
}
static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
-
+
if (set & TIOCM_RTS)
raise_rts(port);
if (set & TIOCM_DTR)
@@ -1532,46 +1290,46 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
drop_dtr(port);
return 0;
-}
+}
-static int isicom_set_serial_info(struct isi_port * port,
- struct serial_struct __user *info)
+static int isicom_set_serial_info(struct isi_port *port,
+ struct serial_struct __user *info)
{
struct serial_struct newinfo;
int reconfig_port;
- if(copy_from_user(&newinfo, info, sizeof(newinfo)))
+ if (copy_from_user(&newinfo, info, sizeof(newinfo)))
return -EFAULT;
-
- reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
- (newinfo.flags & ASYNC_SPD_MASK));
-
+
+ reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
+ (newinfo.flags & ASYNC_SPD_MASK));
+
if (!capable(CAP_SYS_ADMIN)) {
if ((newinfo.close_delay != port->close_delay) ||
- (newinfo.closing_wait != port->closing_wait) ||
- ((newinfo.flags & ~ASYNC_USR_MASK) !=
- (port->flags & ~ASYNC_USR_MASK)))
+ (newinfo.closing_wait != port->closing_wait) ||
+ ((newinfo.flags & ~ASYNC_USR_MASK) !=
+ (port->flags & ~ASYNC_USR_MASK)))
return -EPERM;
port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
(newinfo.flags & ASYNC_USR_MASK));
- }
+ }
else {
port->close_delay = newinfo.close_delay;
- port->closing_wait = newinfo.closing_wait;
- port->flags = ((port->flags & ~ASYNC_FLAGS) |
+ port->closing_wait = newinfo.closing_wait;
+ port->flags = ((port->flags & ~ASYNC_FLAGS) |
(newinfo.flags & ASYNC_FLAGS));
}
if (reconfig_port) {
isicom_config_port(port);
}
- return 0;
-}
+ return 0;
+}
-static int isicom_get_serial_info(struct isi_port * port,
- struct serial_struct __user *info)
+static int isicom_get_serial_info(struct isi_port *port,
+ struct serial_struct __user *info)
{
struct serial_struct out_info;
-
+
memset(&out_info, 0, sizeof(out_info));
/* out_info.type = ? */
out_info.line = port - isi_ports;
@@ -1581,15 +1339,15 @@ static int isicom_get_serial_info(struct isi_port * port,
/* out_info.baud_base = ? */
out_info.close_delay = port->close_delay;
out_info.closing_wait = port->closing_wait;
- if(copy_to_user(info, &out_info, sizeof(out_info)))
+ if (copy_to_user(info, &out_info, sizeof(out_info)))
return -EFAULT;
return 0;
-}
+}
-static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
int retval;
@@ -1597,139 +1355,141 @@ static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
return -ENODEV;
switch(cmd) {
- case TCSBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- isicom_send_break(port, HZ/4);
- return 0;
-
- case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
- return 0;
-
- case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
-
- case TIOCSSOFTCAR:
- if(get_user(arg, (unsigned long __user *) argp))
- return -EFAULT;
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- return 0;
-
- case TIOCGSERIAL:
- return isicom_get_serial_info(port, argp);
-
- case TIOCSSERIAL:
- return isicom_set_serial_info(port, argp);
-
- default:
- return -ENOIOCTLCMD;
+ case TCSBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+ isicom_send_break(port, HZ/4);
+ return 0;
+
+ case TCSBRKP:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+ return 0;
+
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0,
+ (unsigned long __user *)argp);
+
+ case TIOCSSOFTCAR:
+ if (get_user(arg, (unsigned long __user *) argp))
+ return -EFAULT;
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+
+ case TIOCGSERIAL:
+ return isicom_get_serial_info(port, argp);
+
+ case TIOCSSERIAL:
+ return isicom_set_serial_info(port, argp);
+
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
/* set_termios et all */
-static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void isicom_set_termios(struct tty_struct *tty,
+ struct termios *old_termios)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
return;
-
+
if (tty->termios->c_cflag == old_termios->c_cflag &&
- tty->termios->c_iflag == old_termios->c_iflag)
+ tty->termios->c_iflag == old_termios->c_iflag)
return;
-
+
isicom_config_port(port);
-
+
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios->c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
- isicom_start(tty);
- }
+ isicom_start(tty);
+ }
}
/* throttle et all */
-static void isicom_throttle(struct tty_struct * tty)
+static void isicom_throttle(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
-
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
+
if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
return;
-
+
/* tell the card that this port cannot handle any more data for now */
card->port_status &= ~(1 << port->channel);
outw(card->port_status, card->base + 0x02);
}
/* unthrottle et all */
-static void isicom_unthrottle(struct tty_struct * tty)
+static void isicom_unthrottle(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
-
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
+
if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
return;
-
+
/* tell the card that this port is ready to accept more data */
card->port_status |= (1 << port->channel);
outw(card->port_status, card->base + 0x02);
}
/* stop et all */
-static void isicom_stop(struct tty_struct * tty)
+static void isicom_stop(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
return;
-
+
/* this tells the transmitter not to consider this port for
data output to the card. */
port->status &= ~ISI_TXOK;
}
/* start et all */
-static void isicom_start(struct tty_struct * tty)
+static void isicom_start(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_start"))
return;
-
+
/* this tells the transmitter to consider this port for
data output to the card. */
port->status |= ISI_TXOK;
}
/* hangup et all */
-static void do_isicom_hangup(void * data)
+static void do_isicom_hangup(void *data)
{
- struct isi_port * port = (struct isi_port *) data;
- struct tty_struct * tty;
-
+ struct isi_port *port = data;
+ struct tty_struct *tty;
+
tty = port->tty;
if (tty)
tty_hangup(tty);
}
-static void isicom_hangup(struct tty_struct * tty)
+static void isicom_hangup(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
return;
-
+
isicom_shutdown_port(port);
port->count = 0;
port->flags &= ~ASYNC_NORMAL_ACTIVE;
@@ -1738,342 +1498,540 @@ static void isicom_hangup(struct tty_struct * tty)
}
/* flush_buffer et all */
-static void isicom_flush_buffer(struct tty_struct * tty)
+static void isicom_flush_buffer(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
return;
-
+
spin_lock_irqsave(&card->card_lock, flags);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
}
+/*
+ * Driver init and deinit functions
+ */
-static int __devinit register_ioregion(void)
+static int __devinit isicom_register_ioregion(struct pci_dev *pdev,
+ const unsigned int index)
{
- int count, done=0;
- for (count=0; count < BOARD_COUNT; count++ ) {
- if (isi_card[count].base)
- if (!request_region(isi_card[count].base,16,ISICOM_NAME)) {
- printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
- isi_card[count].base,isi_card[count].base+15,count+1);
- isi_card[count].base=0;
- done++;
- }
- }
- return done;
+ struct isi_board *board = pci_get_drvdata(pdev);
+
+ if (!board->base)
+ return -EINVAL;
+
+ if (!request_region(board->base, 16, ISICOM_NAME)) {
+ dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
+ "will be disabled.\n", board->base, board->base + 15,
+ index + 1);
+ return -EBUSY;
+ }
+
+ return 0;
}
-static void unregister_ioregion(void)
+static void isicom_unregister_ioregion(struct pci_dev *pdev)
{
- int count;
- for (count=0; count < BOARD_COUNT; count++ )
- if (isi_card[count].base) {
- release_region(isi_card[count].base,16);
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
-#endif
- }
+ struct isi_board *board = pci_get_drvdata(pdev);
+
+ if (!board->base)
+ return;
+
+ release_region(board->base, 16);
+ dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n",
+ board->base, board->base + 15);
+ board->base = 0;
}
static struct tty_operations isicom_ops = {
- .open = isicom_open,
- .close = isicom_close,
- .write = isicom_write,
- .put_char = isicom_put_char,
- .flush_chars = isicom_flush_chars,
- .write_room = isicom_write_room,
+ .open = isicom_open,
+ .close = isicom_close,
+ .write = isicom_write,
+ .put_char = isicom_put_char,
+ .flush_chars = isicom_flush_chars,
+ .write_room = isicom_write_room,
.chars_in_buffer = isicom_chars_in_buffer,
- .ioctl = isicom_ioctl,
- .set_termios = isicom_set_termios,
- .throttle = isicom_throttle,
- .unthrottle = isicom_unthrottle,
- .stop = isicom_stop,
- .start = isicom_start,
- .hangup = isicom_hangup,
- .flush_buffer = isicom_flush_buffer,
- .tiocmget = isicom_tiocmget,
- .tiocmset = isicom_tiocmset,
+ .ioctl = isicom_ioctl,
+ .set_termios = isicom_set_termios,
+ .throttle = isicom_throttle,
+ .unthrottle = isicom_unthrottle,
+ .stop = isicom_stop,
+ .start = isicom_start,
+ .hangup = isicom_hangup,
+ .flush_buffer = isicom_flush_buffer,
+ .tiocmget = isicom_tiocmget,
+ .tiocmset = isicom_tiocmset,
};
-static int __devinit register_drivers(void)
+static int __devinit isicom_register_tty_driver(void)
{
- int error;
+ int error = -ENOMEM;
/* tty driver structure initialization */
isicom_normal = alloc_tty_driver(PORT_COUNT);
if (!isicom_normal)
- return -ENOMEM;
-
- isicom_normal->owner = THIS_MODULE;
- isicom_normal->name = "ttyM";
- isicom_normal->devfs_name = "isicom/";
- isicom_normal->major = ISICOM_NMAJOR;
- isicom_normal->minor_start = 0;
- isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
- isicom_normal->subtype = SERIAL_TYPE_NORMAL;
- isicom_normal->init_termios = tty_std_termios;
- isicom_normal->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL |CLOCAL;
- isicom_normal->flags = TTY_DRIVER_REAL_RAW;
+ goto end;
+
+ isicom_normal->owner = THIS_MODULE;
+ isicom_normal->name = "ttyM";
+ isicom_normal->devfs_name = "isicom/";
+ isicom_normal->major = ISICOM_NMAJOR;
+ isicom_normal->minor_start = 0;
+ isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
+ isicom_normal->subtype = SERIAL_TYPE_NORMAL;
+ isicom_normal->init_termios = tty_std_termios;
+ isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
+ isicom_normal->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(isicom_normal, &isicom_ops);
-
- if ((error=tty_register_driver(isicom_normal))!=0) {
- printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
+
+ if ((error = tty_register_driver(isicom_normal))) {
+ pr_dbg("Couldn't register the dialin driver, error=%d\n",
error);
put_tty_driver(isicom_normal);
- return error;
}
- return 0;
+end:
+ return error;
}
-static void unregister_drivers(void)
+static void isicom_unregister_tty_driver(void)
{
- int error = tty_unregister_driver(isicom_normal);
- if (error)
- printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+ int error;
+
+ if ((error = tty_unregister_driver(isicom_normal)))
+ pr_dbg("couldn't unregister normal driver, error=%d.\n", error);
+
put_tty_driver(isicom_normal);
}
-static int __devinit register_isr(void)
+static int __devinit isicom_register_isr(struct pci_dev *pdev,
+ const unsigned int index)
{
- int count, done=0;
- unsigned long irqflags;
-
- for (count=0; count < BOARD_COUNT; count++ ) {
- if (isi_card[count].base) {
- irqflags = (isi_card[count].isa == YES) ?
- SA_INTERRUPT :
- (SA_INTERRUPT | SA_SHIRQ);
-
- if (request_irq(isi_card[count].irq,
- isicom_interrupt,
- irqflags,
- ISICOM_NAME, &isi_card[count])) {
-
- printk(KERN_WARNING "ISICOM: Could not"
- " install handler at Irq %d."
- " Card%d will be disabled.\n",
- isi_card[count].irq, count+1);
-
- release_region(isi_card[count].base,16);
- isi_card[count].base=0;
- }
- else
- done++;
- }
- }
- return done;
+ struct isi_board *board = pci_get_drvdata(pdev);
+ unsigned long irqflags = SA_INTERRUPT;
+ int retval = -EINVAL;
+
+ if (!board->base)
+ goto end;
+
+ if (board->isa == NO)
+ irqflags |= SA_SHIRQ;
+
+ retval = request_irq(board->irq, isicom_interrupt, irqflags,
+ ISICOM_NAME, board);
+ if (retval < 0)
+ dev_warn(&pdev->dev, "Could not install handler at Irq %d. "
+ "Card%d will be disabled.\n", board->irq, index + 1);
+ else
+ retval = 0;
+end:
+ return retval;
}
-static void __exit unregister_isr(void)
+static int __devinit reset_card(struct pci_dev *pdev,
+ const unsigned int card, unsigned int *signature)
{
- int count;
+ struct isi_board *board = pci_get_drvdata(pdev);
+ unsigned long base = board->base;
+ unsigned int portcount = 0;
+ int retval = 0;
+
+ dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
+ base);
- for (count=0; count < BOARD_COUNT; count++ ) {
- if (isi_card[count].base)
- free_irq(isi_card[count].irq, &isi_card[count]);
+ inw(base + 0x8);
+
+ mdelay(10);
+
+ outw(0, base + 0x8); /* Reset */
+
+ msleep(3000);
+
+ *signature = inw(base + 0x4) & 0xff;
+
+ if (board->isa == YES) {
+ if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) {
+ dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+ inw(base + 0x2), inw(base + 0xe));
+ dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure "
+ "(Possible bad I/O Port Address 0x%lx).\n",
+ card + 1, base);
+ retval = -EIO;
+ goto end;
+ }
+ } else {
+ portcount = inw(base + 0x2);
+ if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
+ (portcount != 4) && (portcount != 8))) {
+ dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+ inw(base + 0x2), inw(base + 0xe));
+ dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
+ "(Possible bad I/O Port Address 0x%lx).\n",
+ card + 1, base);
+ retval = -EIO;
+ goto end;
+ }
}
+
+ switch (*signature) {
+ case 0xa5:
+ case 0xbb:
+ case 0xdd:
+ board->port_count = (board->isa == NO && portcount == 4) ? 4 :
+ 8;
+ board->shift_count = 12;
+ break;
+ case 0xcc:
+ board->port_count = 16;
+ board->shift_count = 11;
+ break;
+ default:
+ dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible "
+ "bad I/O Port Address 0x%lx).\n", card + 1, base);
+ dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature);
+ retval = -EIO;
+ }
+ dev_info(&pdev->dev, "-Done\n");
+
+end:
+ return retval;
}
-static int __devinit isicom_init(void)
+static inline int WaitTillCardIsFree(u16 base)
{
- int card, channel, base;
- struct isi_port * port;
- unsigned long page;
-
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
-#else
- printk(KERN_ERR "ISICOM: Not enough memory...\n");
-#endif
- return 0;
- }
- tmp_buf = (unsigned char *) page;
- }
-
- if (!register_ioregion())
- {
- printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
- free_page((unsigned long)tmp_buf);
- return 0;
- }
- if (register_drivers())
- {
- unregister_ioregion();
- free_page((unsigned long)tmp_buf);
- return 0;
- }
- if (!register_isr())
- {
- unregister_drivers();
- /* ioports already uregistered in register_isr */
- free_page((unsigned long)tmp_buf);
- return 0;
+ unsigned long count = 0;
+
+ while (!(inw(base + 0xe) & 0x1) && count++ < 100)
+ msleep(5);
+
+ return !(inw(base + 0xe) & 0x1);
+}
+
+static int __devinit load_firmware(struct pci_dev *pdev,
+ const unsigned int index, const unsigned int signature)
+{
+ struct isi_board *board = pci_get_drvdata(pdev);
+ const struct firmware *fw;
+ unsigned long base = board->base;
+ unsigned int a;
+ u16 word_count, status;
+ int retval = -EIO;
+ char *name;
+ u8 *data;
+
+ struct stframe {
+ u16 addr;
+ u16 count;
+ u8 data[0];
+ } *frame;
+
+ switch (signature) {
+ case 0xa5:
+ name = "isi608.bin";
+ break;
+ case 0xbb:
+ name = "isi608em.bin";
+ break;
+ case 0xcc:
+ name = "isi616em.bin";
+ break;
+ case 0xdd:
+ name = "isi4608.bin";
+ break;
+ case 0xee:
+ name = "isi4616.bin";
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown signature.\n");
+ goto end;
+ }
+
+ retval = request_firmware(&fw, name, &pdev->dev);
+ if (retval)
+ goto end;
+
+ for (frame = (struct stframe *)fw->data;
+ frame < (struct stframe *)(fw->data + fw->size);
+ frame++) {
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ outw(0xf0, base); /* start upload sequence */
+ outw(0x00, base);
+ outw(frame->addr, base); /* lsb of address */
+
+ word_count = frame->count / 2 + frame->count % 2;
+ outw(word_count, base);
+ InterruptTheCard(base);
+
+ udelay(100); /* 0x2f */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_warn(&pdev->dev, "Card%d rejected load header:\n"
+ "Address:0x%x\nCount:0x%x\nStatus:0x%x\n",
+ index + 1, frame->addr, frame->count, status);
+ goto errrelfw;
+ }
+ outsw(base, frame->data, word_count);
+
+ InterruptTheCard(base);
+
+ udelay(50); /* 0x0f */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_err(&pdev->dev, "Card%d got out of sync.Card "
+ "Status:0x%x\n", index + 1, status);
+ goto errrelfw;
+ }
+ }
+
+ retval = -EIO;
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ outw(0xf2, base);
+ outw(0x800, base);
+ outw(0x0, base);
+ outw(0x0, base);
+ InterruptTheCard(base);
+ outw(0x0, base + 0x4); /* for ISI4608 cards */
+
+/* XXX: should we test it by reading it back and comparing with original like
+ * in load firmware package? */
+ for (frame = (struct stframe*)fw->data;
+ frame < (struct stframe*)(fw->data + fw->size);
+ frame++) {
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ outw(0xf1, base); /* start download sequence */
+ outw(0x00, base);
+ outw(frame->addr, base); /* lsb of address */
+
+ word_count = (frame->count >> 1) + frame->count % 2;
+ outw(word_count + 1, base);
+ InterruptTheCard(base);
+
+ udelay(50); /* 0xf */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
+ "Address:0x%x\nCount:0x%x\nStatus: 0x%x\n",
+ index + 1, frame->addr, frame->count, status);
+ goto errrelfw;
+ }
+
+ data = kmalloc(word_count * 2, GFP_KERNEL);
+ inw(base);
+ insw(base, data, word_count);
+ InterruptTheCard(base);
+
+ for (a = 0; a < frame->count; a++)
+ if (data[a] != frame->data[a]) {
+ kfree(data);
+ dev_err(&pdev->dev, "Card%d, firmware upload "
+ "failed\n", index + 1);
+ goto errrelfw;
+ }
+ kfree(data);
+
+ udelay(50); /* 0xf */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_err(&pdev->dev, "Card%d verify got out of sync. "
+ "Card Status:0x%x\n", index + 1, status);
+ goto errrelfw;
+ }
}
-
- memset(isi_ports, 0, sizeof(isi_ports));
- for (card = 0; card < BOARD_COUNT; card++) {
- port = &isi_ports[card * 16];
- isi_card[card].ports = port;
- spin_lock_init(&isi_card[card].card_lock);
- base = isi_card[card].base;
- for (channel = 0; channel < 16; channel++, port++) {
- port->magic = ISICOM_MAGIC;
- port->card = &isi_card[card];
- port->channel = channel;
- port->close_delay = 50 * HZ/100;
- port->closing_wait = 3000 * HZ/100;
- INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
- INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
- port->status = 0;
- init_waitqueue_head(&port->open_wait);
- init_waitqueue_head(&port->close_wait);
- /* . . . */
- }
- }
-
- return 1;
+
+ board->status |= FIRMWARE_LOADED;
+ retval = 0;
+
+errrelfw:
+ release_firmware(fw);
+end:
+ return retval;
}
/*
* Insmod can set static symbols so keep these static
*/
-
static int io[4];
static int irq[4];
+static int card;
-MODULE_AUTHOR("MultiTech");
-MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
-MODULE_LICENSE("GPL");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for the cards");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for the cards");
+static int __devinit isicom_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ unsigned int ioaddr, signature, index;
+ int retval = -EPERM;
+ u8 pciirq;
+ struct isi_board *board = NULL;
+
+ if (card >= BOARD_COUNT)
+ goto err;
+
+ ioaddr = pci_resource_start(pdev, 3);
+ /* i.e at offset 0x1c in the PCI configuration register space. */
+ pciirq = pdev->irq;
+ dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
+
+ /* allot the first empty slot in the array */
+ for (index = 0; index < BOARD_COUNT; index++)
+ if (isi_card[index].base == 0) {
+ board = &isi_card[index];
+ break;
+ }
+
+ board->base = ioaddr;
+ board->irq = pciirq;
+ board->isa = NO;
+ card++;
+
+ pci_set_drvdata(pdev, board);
+
+ retval = isicom_register_ioregion(pdev, index);
+ if (retval < 0)
+ goto err;
+
+ retval = isicom_register_isr(pdev, index);
+ if (retval < 0)
+ goto errunrr;
+
+ retval = reset_card(pdev, index, &signature);
+ if (retval < 0)
+ goto errunri;
+
+ retval = load_firmware(pdev, index, signature);
+ if (retval < 0)
+ goto errunri;
+
+ return 0;
+
+errunri:
+ free_irq(board->irq, board);
+errunrr:
+ isicom_unregister_ioregion(pdev);
+err:
+ board->base = 0;
+ return retval;
+}
+
+static void __devexit isicom_remove(struct pci_dev *pdev)
+{
+ struct isi_board *board = pci_get_drvdata(pdev);
+
+ free_irq(board->irq, board);
+ isicom_unregister_ioregion(pdev);
+}
static int __devinit isicom_setup(void)
{
- struct pci_dev *dev = NULL;
- int retval, card, idx, count;
- unsigned char pciirq;
- unsigned int ioaddr;
-
+ int retval, idx, channel;
+ struct isi_port *port;
+
card = 0;
- for(idx=0; idx < BOARD_COUNT; idx++) {
- if (io[idx]) {
- isi_card[idx].base=io[idx];
- isi_card[idx].irq=irq[idx];
- isi_card[idx].isa=YES;
- card++;
- }
- else {
- isi_card[idx].base = 0;
- isi_card[idx].irq = 0;
- }
- }
-
- for (idx=0 ;idx < card; idx++) {
- if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
- (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
- (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
- (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
- (isi_card[idx].irq==15))) {
-
- if (isi_card[idx].base) {
- printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
- isi_card[idx].irq, idx+1);
- isi_card[idx].base=0;
- card--;
- }
- }
- }
-
- if (card < BOARD_COUNT) {
- for (idx=0; idx < DEVID_COUNT; idx++) {
- dev = NULL;
- for (;;){
- if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev)))
- break;
- if (card >= BOARD_COUNT)
- break;
-
- if (pci_enable_device(dev))
- break;
+ memset(isi_ports, 0, sizeof(isi_ports));
- /* found a PCI ISI card! */
- ioaddr = pci_resource_start (dev, 3); /* i.e at offset 0x1c in the
- * PCI configuration register
- * space.
- */
- pciirq = dev->irq;
- printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl[idx].device);
- /*
- * allot the first empty slot in the array
- */
- for (count=0; count < BOARD_COUNT; count++) {
- if (isi_card[count].base == 0) {
- isi_card[count].base = ioaddr;
- isi_card[count].irq = pciirq;
- isi_card[count].isa = NO;
- card++;
- break;
- }
- }
- }
- if (card >= BOARD_COUNT) break;
- }
+ for(idx = 0; idx < BOARD_COUNT; idx++) {
+ port = &isi_ports[idx * 16];
+ isi_card[idx].ports = port;
+ spin_lock_init(&isi_card[idx].card_lock);
+ for (channel = 0; channel < 16; channel++, port++) {
+ port->magic = ISICOM_MAGIC;
+ port->card = &isi_card[idx];
+ port->channel = channel;
+ port->close_delay = 50 * HZ/100;
+ port->closing_wait = 3000 * HZ/100;
+ INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
+ INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
+ port->status = 0;
+ init_waitqueue_head(&port->open_wait);
+ init_waitqueue_head(&port->close_wait);
+ /* . . . */
+ }
+ isi_card[idx].base = 0;
+ isi_card[idx].irq = 0;
+
+ if (!io[idx])
+ continue;
+
+ if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4 ||
+ irq[idx] == 5 || irq[idx] == 7 ||
+ irq[idx] == 10 || irq[idx] == 11 ||
+ irq[idx] == 12 || irq[idx] == 15) {
+ printk(KERN_ERR "ISICOM: ISA not supported yet.\n");
+ retval = -EINVAL;
+ goto error;
+ } else
+ printk(KERN_ERR "ISICOM: Irq %d unsupported. "
+ "Disabling Card%d...\n", irq[idx], idx + 1);
}
-
- if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
- printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n");
- return -EIO;
- }
- retval = misc_register(&isiloader_device);
+ retval = isicom_register_tty_driver();
+ if (retval < 0)
+ goto error;
+
+ retval = pci_register_driver(&isicom_driver);
if (retval < 0) {
- printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
- return retval;
- }
-
- if (!isicom_init()) {
- if (misc_deregister(&isiloader_device))
- printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
- return -EIO;
+ printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
+ goto errtty;
}
-
+
init_timer(&tx);
tx.expires = jiffies + 1;
tx.data = 0;
tx.function = isicom_tx;
re_schedule = 1;
add_timer(&tx);
-
+
return 0;
+errtty:
+ isicom_unregister_tty_driver();
+error:
+ return retval;
}
static void __exit isicom_exit(void)
{
+ unsigned int index = 0;
+
re_schedule = 0;
- /* FIXME */
- msleep(1000);
- unregister_isr();
- unregister_drivers();
- unregister_ioregion();
- if(tmp_buf)
- free_page((unsigned long)tmp_buf);
- if (misc_deregister(&isiloader_device))
- printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+
+ while (re_schedule != 2 && index++ < 100)
+ msleep(10);
+
+ pci_unregister_driver(&isicom_driver);
+ isicom_unregister_tty_driver();
}
module_init(isicom_setup);
module_exit(isicom_exit);
+
+MODULE_AUTHOR("MultiTech");
+MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
+MODULE_LICENSE("GPL");
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O ports for the cards");
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "Interrupts for the cards");
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index ce3bc0d45f1f..28c5a3193b81 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -135,7 +135,7 @@ static stlconf_t stli_brdconf[] = {
/*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
};
-static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
+static int stli_nrbrds = ARRAY_SIZE(stli_brdconf);
/*
* There is some experimental EISA board detection code in this driver.
@@ -406,7 +406,7 @@ static unsigned long stli_eisamemprobeaddrs[] = {
0xff000000, 0xff010000, 0xff020000, 0xff030000,
};
-static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
+static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
/*
* Define the Stallion PCI vendor and device IDs.
@@ -899,15 +899,13 @@ static void stli_argbrds(void)
{
stlconf_t conf;
stlibrd_t *brdp;
- int nrargs, i;
+ int i;
#ifdef DEBUG
printk("stli_argbrds()\n");
#endif
- nrargs = sizeof(stli_brdsp) / sizeof(char **);
-
- for (i = stli_nrbrds; (i < nrargs); i++) {
+ for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) {
memset(&conf, 0, sizeof(conf));
if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
continue;
@@ -967,7 +965,7 @@ static unsigned long stli_atol(char *str)
static int stli_parsebrd(stlconf_t *confp, char **argp)
{
char *sp;
- int nrbrdnames, i;
+ int i;
#ifdef DEBUG
printk("stli_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
@@ -979,14 +977,13 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
*sp = TOLOWER(*sp);
- nrbrdnames = sizeof(stli_brdstr) / sizeof(stlibrdtype_t);
- for (i = 0; (i < nrbrdnames); i++) {
+ for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
break;
}
- if (i >= nrbrdnames) {
+ if (i == ARRAY_SIZE(stli_brdstr)) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
- return(0);
+ return 0;
}
confp->brdtype = stli_brdstr[i].type;
@@ -2714,17 +2711,13 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp)
stlen = size - tail;
}
- len = MIN(len, (TTY_FLIPBUF_SIZE - tty->flip.count));
+ len = tty_buffer_request_room(tty, len);
+ /* FIXME : iomap ? */
shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
while (len > 0) {
stlen = MIN(len, stlen);
- memcpy(tty->flip.char_buf_ptr, (char *) (shbuf + tail), stlen);
- memset(tty->flip.flag_buf_ptr, 0, stlen);
- tty->flip.char_buf_ptr += stlen;
- tty->flip.flag_buf_ptr += stlen;
- tty->flip.count += stlen;
-
+ tty_insert_flip_string(tty, (char *)(shbuf + tail), stlen);
len -= stlen;
tail += stlen;
if (tail >= size) {
@@ -2909,16 +2902,12 @@ static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
if (tty != (struct tty_struct *) NULL) {
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
- if (portp->flags & ASYNC_SAK) {
- do_SAK(tty);
- EBRDENABLE(brdp);
- }
- tty_schedule_flip(tty);
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
+ if (portp->flags & ASYNC_SAK) {
+ do_SAK(tty);
+ EBRDENABLE(brdp);
}
+ tty_schedule_flip(tty);
}
}
@@ -4943,7 +4932,7 @@ static int stli_portcmdstats(stliport_t *portp)
if (portp->tty != (struct tty_struct *) NULL) {
if (portp->tty->driver_data == portp) {
stli_comstats.ttystate = portp->tty->flags;
- stli_comstats.rxbuffered = portp->tty->flip.count;
+ stli_comstats.rxbuffered = -1 /*portp->tty->flip.count*/;
if (portp->tty->termios != (struct termios *) NULL) {
stli_comstats.cflags = portp->tty->termios->c_cflag;
stli_comstats.iflags = portp->tty->termios->c_iflag;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 91dd669273e0..29c41f4418c0 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -101,6 +101,11 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
return 1;
}
+
+static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size)
+{
+ return 1;
+}
#endif
/*
@@ -228,26 +233,36 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
return written;
}
+#ifndef __HAVE_PHYS_MEM_ACCESS_PROT
+static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot)
+{
+#ifdef pgprot_noncached
+ unsigned long offset = pfn << PAGE_SHIFT;
+
+ if (uncached_access(file, offset))
+ return pgprot_noncached(vma_prot);
+#endif
+ return vma_prot;
+}
+#endif
+
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
-#if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
+ size_t size = vma->vm_end - vma->vm_start;
+
+ if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size))
+ return -EINVAL;
+
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
+ size,
vma->vm_page_prot);
-#elif defined(pgprot_noncached)
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- int uncached;
-
- uncached = uncached_access(file, offset);
- if (uncached)
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#endif
/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
if (remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
- vma->vm_end-vma->vm_start,
+ size,
vma->vm_page_prot))
return -EAGAIN;
return 0;
@@ -519,7 +534,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
return virtr + wrote;
}
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
static ssize_t read_port(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
@@ -726,7 +741,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
{
loff_t ret;
- down(&file->f_dentry->d_inode->i_sem);
+ mutex_lock(&file->f_dentry->d_inode->i_mutex);
switch (orig) {
case 0:
file->f_pos = offset;
@@ -741,7 +756,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
default:
ret = -EINVAL;
}
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return ret;
}
@@ -780,7 +795,7 @@ static struct file_operations null_fops = {
.write = write_null,
};
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
static struct file_operations port_fops = {
.llseek = memory_lseek,
.read = read_port,
@@ -817,7 +832,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
char *tmp;
- int ret;
+ ssize_t ret;
tmp = kmalloc(count + 1, GFP_KERNEL);
if (tmp == NULL)
@@ -826,6 +841,9 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf,
if (!copy_from_user(tmp, buf, count)) {
tmp[count] = 0;
ret = printk("%s", tmp);
+ if (ret > count)
+ /* printk can add a prefix */
+ ret = count;
}
kfree(tmp);
return ret;
@@ -847,7 +865,7 @@ static int memory_open(struct inode * inode, struct file * filp)
case 3:
filp->f_op = &null_fops;
break;
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
case 4:
filp->f_op = &port_fops;
break;
@@ -894,7 +912,7 @@ static const struct {
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
{3, "null", S_IRUGO | S_IWUGO, &null_fops},
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
{4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
#endif
{5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 79e490ef2cf2..f43c2e04eadd 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -269,7 +269,7 @@ static int MoxaPortDCDChange(int);
static int MoxaPortDCDON(int);
static void MoxaPortFlushData(int, int);
static int MoxaPortWriteData(int, unsigned char *, int);
-static int MoxaPortReadData(int, unsigned char *, int);
+static int MoxaPortReadData(int, struct tty_struct *tty);
static int MoxaPortTxQueue(int);
static int MoxaPortRxQueue(int);
static int MoxaPortTxFree(int);
@@ -301,6 +301,8 @@ static struct tty_operations moxa_ops = {
.tiocmset = moxa_tiocmset,
};
+static spinlock_t moxa_lock = SPIN_LOCK_UNLOCKED;
+
#ifdef CONFIG_PCI
static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
{
@@ -448,7 +450,7 @@ static int __init moxa_init(void)
#ifdef CONFIG_PCI
{
struct pci_dev *p = NULL;
- int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
+ int n = ARRAY_SIZE(moxa_pcibrds) - 1;
i = 0;
while (i < n) {
while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
@@ -645,10 +647,10 @@ static int moxa_write(struct tty_struct *tty,
if (ch == NULL)
return (0);
port = ch->port;
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(&moxa_lock, flags);
len = MoxaPortWriteData(port, (unsigned char *) buf, count);
- restore_flags(flags);
+ spin_unlock_irqrestore(&moxa_lock, flags);
/*********************************************
if ( !(ch->statusflags & LOWWAIT) &&
@@ -723,11 +725,10 @@ static void moxa_put_char(struct tty_struct *tty, unsigned char c)
if (ch == NULL)
return;
port = ch->port;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&moxa_lock, flags);
moxaXmitBuff[0] = c;
MoxaPortWriteData(port, moxaXmitBuff, 1);
- restore_flags(flags);
+ spin_unlock_irqrestore(&moxa_lock, flags);
/************************************************
if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
*************************************************/
@@ -1030,12 +1031,12 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
printk("block_til_ready before block: ttys%d, count = %d\n",
ch->line, ch->count);
#endif
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&moxa_lock, flags);
if (!tty_hung_up_p(filp))
ch->count--;
- restore_flags(flags);
ch->blocked_open++;
+ spin_unlock_irqrestore(&moxa_lock, flags);
+
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
@@ -1062,17 +1063,21 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&ch->open_wait, &wait);
+
+ spin_lock_irqsave(&moxa_lock, flags);
if (!tty_hung_up_p(filp))
ch->count++;
ch->blocked_open--;
+ spin_unlock_irqrestore(&moxa_lock, flags);
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready after blocking: ttys%d, count = %d\n",
ch->line, ch->count);
#endif
if (retval)
return (retval);
+ /* FIXME: review to see if we need to use set_bit on these */
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
- return (0);
+ return 0;
}
static void setup_empty_event(struct tty_struct *tty)
@@ -1080,15 +1085,14 @@ static void setup_empty_event(struct tty_struct *tty)
struct moxa_str *ch = tty->driver_data;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&moxa_lock, flags);
ch->statusflags |= EMPTYWAIT;
moxaEmptyTimer_on[ch->port] = 0;
del_timer(&moxaEmptyTimer[ch->port]);
moxaEmptyTimer[ch->port].expires = jiffies + HZ;
moxaEmptyTimer_on[ch->port] = 1;
add_timer(&moxaEmptyTimer[ch->port]);
- restore_flags(flags);
+ spin_unlock_irqrestore(&moxa_lock, flags);
}
static void check_xmit_empty(unsigned long data)
@@ -1135,8 +1139,6 @@ static void receive_data(struct moxa_str *ch)
{
struct tty_struct *tp;
struct termios *ts;
- int i, count, rc, space;
- unsigned char *charptr, *flagptr;
unsigned long flags;
ts = NULL;
@@ -1150,24 +1152,10 @@ static void receive_data(struct moxa_str *ch)
MoxaPortFlushData(ch->port, 0);
return;
}
- space = TTY_FLIPBUF_SIZE - tp->flip.count;
- if (space <= 0)
- return;
- charptr = tp->flip.char_buf_ptr;
- flagptr = tp->flip.flag_buf_ptr;
- rc = tp->flip.count;
- save_flags(flags);
- cli();
- count = MoxaPortReadData(ch->port, charptr, space);
- restore_flags(flags);
- for (i = 0; i < count; i++)
- *flagptr++ = 0;
- charptr += count;
- rc += count;
- tp->flip.count = rc;
- tp->flip.char_buf_ptr = charptr;
- tp->flip.flag_buf_ptr = flagptr;
- tty_schedule_flip(ch->tty);
+ spin_lock_irqsave(&moxa_lock, flags);
+ MoxaPortReadData(ch->port, tp);
+ spin_unlock_irqrestore(&moxa_lock, flags);
+ tty_schedule_flip(tp);
}
#define Magic_code 0x404
@@ -1661,6 +1649,8 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
case MOXA_FIND_BOARD:
case MOXA_LOAD_C320B:
case MOXA_LOAD_CODE:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
break;
}
@@ -1774,7 +1764,7 @@ int MoxaPortsOfCard(int cardno)
* 14. MoxaPortDCDON(int port); *
* 15. MoxaPortFlushData(int port, int mode); *
* 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
- * 17. MoxaPortReadData(int port, unsigned char * buffer, int length); *
+ * 17. MoxaPortReadData(int port, struct tty_struct *tty); *
* 18. MoxaPortTxBufSize(int port); *
* 19. MoxaPortRxBufSize(int port); *
* 20. MoxaPortTxQueue(int port); *
@@ -2003,10 +1993,9 @@ int MoxaPortsOfCard(int cardno)
*
* Function 21: Read data.
* Syntax:
- * int MoxaPortReadData(int port, unsigned char * buffer, int length);
+ * int MoxaPortReadData(int port, struct tty_struct *tty);
* int port : port number (0 - 127)
- * unsigned char * buffer : pointer to read data buffer.
- * int length : read data buffer length
+ * struct tty_struct *tty : tty for data
*
* return: 0 - length : real read data length
*
@@ -2504,7 +2493,7 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len)
return (total);
}
-int MoxaPortReadData(int port, unsigned char * buffer, int space)
+int MoxaPortReadData(int port, struct tty_struct *tty)
{
register ushort head, pageofs;
int i, count, cnt, len, total, remain;
@@ -2522,9 +2511,9 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space)
count = (tail >= head) ? (tail - head)
: (tail - head + rx_mask + 1);
if (count == 0)
- return (0);
+ return 0;
- total = (space > count) ? count : space;
+ total = count;
remain = count - total;
moxaLog.rxcnt[port] += total;
count = total;
@@ -2539,7 +2528,7 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space)
len = (count > len) ? len : count;
ofs = baseAddr + DynPage_addr + bufhead + head;
for (i = 0; i < len; i++)
- *buffer++ = readb(ofs + i);
+ tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
head = (head + len) & rx_mask;
count -= len;
}
@@ -2556,7 +2545,7 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space)
writew(pageno, baseAddr + Control_reg);
ofs = baseAddr + DynPage_addr + pageofs;
for (i = 0; i < cnt; i++)
- *buffer++ = readb(ofs + i);
+ tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
if (count == 0) {
writew((head + len) & rx_mask, ofsAddr + RXrptr);
break;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 26448f176803..ea725a9964e2 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -813,7 +813,7 @@ static int mxser_init(void)
/* start finding PCI board here */
#ifdef CONFIG_PCI
- n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
+ n = ARRAY_SIZE(mxser_pcibrds) - 1;
index = 0;
b = 0;
while (b < n) {
@@ -1982,7 +1982,7 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
spin_lock_irqsave(&info->slock, flags);
- recv_room = tty->ldisc.receive_room(tty);
+ recv_room = tty->receive_room;
if ((recv_room == 0) && (!info->ldisc_stop_rx)) {
//mxser_throttle(tty);
mxser_stoprx(tty);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index a133a62f3d55..9f54733f1623 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -191,7 +191,6 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
poll_table *wait);
static int n_hdlc_tty_open(struct tty_struct *tty);
static void n_hdlc_tty_close(struct tty_struct *tty);
-static int n_hdlc_tty_room(struct tty_struct *tty);
static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp,
char *fp, int count);
static void n_hdlc_tty_wakeup(struct tty_struct *tty);
@@ -212,7 +211,6 @@ static struct tty_ldisc n_hdlc_ldisc = {
.ioctl = n_hdlc_tty_ioctl,
.poll = n_hdlc_tty_poll,
.receive_buf = n_hdlc_tty_receive,
- .receive_room = n_hdlc_tty_room,
.write_wakeup = n_hdlc_tty_wakeup,
};
@@ -337,6 +335,7 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
tty->disc_data = n_hdlc;
n_hdlc->tty = tty;
+ tty->receive_room = 65536;
#if defined(TTY_NO_WRITE_SPLIT)
/* change tty_io write() to not split large writes into 8K chunks */
@@ -478,22 +477,6 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)
} /* end of n_hdlc_tty_wakeup() */
/**
- * n_hdlc_tty_room - Return the amount of space left in the receiver's buffer
- * @tty - pointer to associated tty instance data
- *
- * Callback function from tty driver. Return the amount of space left in the
- * receiver's buffer to decide if remote transmitter is to be throttled.
- */
-static int n_hdlc_tty_room(struct tty_struct *tty)
-{
- if (debuglevel >= DEBUG_LEVEL_INFO)
- printk("%s(%d)n_hdlc_tty_room() called\n",__FILE__,__LINE__);
- /* always return a larger number to prevent */
- /* throttling of remote transmitter. */
- return 65536;
-} /* end of n_hdlc_tty_root() */
-
-/**
* n_hdlc_tty_receive - Called by tty driver when receive data is available
* @tty - pointer to tty instance data
* @data - pointer to received data
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 853c98cee64f..c48de09d68f0 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -147,7 +147,6 @@ static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
struct poll_table_struct *wait);
static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count);
-static int r3964_receive_room(struct tty_struct *tty);
static struct tty_ldisc tty_ldisc_N_R3964 = {
.owner = THIS_MODULE,
@@ -161,7 +160,6 @@ static struct tty_ldisc tty_ldisc_N_R3964 = {
.set_termios = r3964_set_termios,
.poll = r3964_poll,
.receive_buf = r3964_receive_buf,
- .receive_room = r3964_receive_room,
};
@@ -1119,6 +1117,7 @@ static int r3964_open(struct tty_struct *tty)
pInfo->nRetry = 0;
tty->disc_data = pInfo;
+ tty->receive_room = 65536;
init_timer(&pInfo->tmr);
pInfo->tmr.data = (unsigned long)pInfo;
@@ -1405,12 +1404,5 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
}
-static int r3964_receive_room(struct tty_struct *tty)
-{
- TRACE_L("receive_room");
- return -1;
-}
-
-
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_R3964);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index c556f4d3ccd7..ccad7ae94541 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -78,7 +78,32 @@ static inline void free_buf(unsigned char *buf)
free_page((unsigned long) buf);
}
-static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+/**
+ * n_tty_set__room - receive space
+ * @tty: terminal
+ *
+ * Called by the driver to find out how much data it is
+ * permitted to feed to the line discipline without any being lost
+ * and thus to manage flow control. Not serialized. Answers for the
+ * "instant".
+ */
+
+static void n_tty_set_room(struct tty_struct *tty)
+{
+ int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+ /*
+ * If we are doing input canonicalization, and there are no
+ * pending newlines, let characters through without limit, so
+ * that erase characters will be handled. Other excess
+ * characters will be beeped.
+ */
+ if (left <= 0)
+ left = tty->icanon && !tty->canon_data;
+ tty->receive_room = left;
+}
+
+static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
{
if (tty->read_cnt < N_TTY_BUF_SIZE) {
tty->read_buf[tty->read_head] = c;
@@ -87,7 +112,7 @@ static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
}
}
-static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct tty_struct *tty)
{
unsigned long flags;
/*
@@ -136,6 +161,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
spin_unlock_irqrestore(&tty->read_lock, flags);
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
+ n_tty_set_room(tty);
check_unthrottle(tty);
}
@@ -838,30 +864,6 @@ send_signal:
put_tty_queue(c, tty);
}
-/**
- * n_tty_receive_room - receive space
- * @tty: terminal
- *
- * Called by the driver to find out how much data it is
- * permitted to feed to the line discipline without any being lost
- * and thus to manage flow control. Not serialized. Answers for the
- * "instant".
- */
-
-static int n_tty_receive_room(struct tty_struct *tty)
-{
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
-
- /*
- * If we are doing input canonicalization, and there are no
- * pending newlines, let characters through without limit, so
- * that erase characters will be handled. Other excess
- * characters will be beeped.
- */
- if (left <= 0)
- left = tty->icanon && !tty->canon_data;
- return left;
-}
/**
* n_tty_write_wakeup - asynchronous I/O notifier
@@ -953,6 +955,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
tty->driver->flush_chars(tty);
}
+ n_tty_set_room(tty);
+
if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
@@ -964,7 +968,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
* mode. We don't want to throttle the driver if we're in
* canonical mode and don't have a newline yet!
*/
- if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
+ if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
/* check TTY_THROTTLED first so it indicates our state */
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->throttle)
@@ -999,6 +1003,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
tty->raw = 1;
tty->real_raw = 1;
+ n_tty_set_room(tty);
return;
}
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1051,6 +1056,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
else
tty->real_raw = 0;
}
+ n_tty_set_room(tty);
}
/**
@@ -1130,7 +1136,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
*
*/
-static inline int copy_from_read_buf(struct tty_struct *tty,
+static int copy_from_read_buf(struct tty_struct *tty,
unsigned char __user **b,
size_t *nr)
@@ -1308,6 +1314,7 @@ do_it_again:
retval = -ERESTARTSYS;
break;
}
+ n_tty_set_room(tty);
clear_bit(TTY_DONT_FLIP, &tty->flags);
timeout = schedule_timeout(timeout);
set_bit(TTY_DONT_FLIP, &tty->flags);
@@ -1401,6 +1408,8 @@ do_it_again:
} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
goto do_it_again;
+ n_tty_set_room(tty);
+
return retval;
}
@@ -1553,7 +1562,6 @@ struct tty_ldisc tty_ldisc_N_TTY = {
normal_poll, /* poll */
NULL, /* hangup */
n_tty_receive_buf, /* receive_buf */
- n_tty_receive_room, /* receive_room */
n_tty_write_wakeup /* write_wakeup */
};
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 1af733d07321..3556ccd77570 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -557,13 +557,13 @@ pc_proc_infos(unsigned char *nvram, char *buffer, int *len,
(nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
PRINT_PROC("Floppy 0 type : ");
type = nvram[2] >> 4;
- if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+ if (type < ARRAY_SIZE(floppy_types))
PRINT_PROC("%s\n", floppy_types[type]);
else
PRINT_PROC("%d (unknown)\n", type);
PRINT_PROC("Floppy 1 type : ");
type = nvram[2] & 0x0f;
- if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+ if (type < ARRAY_SIZE(floppy_types))
PRINT_PROC("%s\n", floppy_types[type]);
else
PRINT_PROC("%d (unknown)\n", type);
@@ -843,8 +843,6 @@ static char *colors[] = {
"2", "4", "16", "256", "65536", "??", "??", "??"
};
-#define fieldsize(a) (sizeof(a)/sizeof(*a))
-
static int
atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
off_t *begin, off_t offset, int size)
@@ -856,7 +854,7 @@ atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
PRINT_PROC("Checksum status : %svalid\n", checksum ? "" : "not ");
PRINT_PROC("Boot preference : ");
- for (i = fieldsize(boot_prefs) - 1; i >= 0; --i) {
+ for (i = ARRAY_SIZE(boot_prefs) - 1; i >= 0; --i) {
if (nvram[1] == boot_prefs[i].val) {
PRINT_PROC("%s\n", boot_prefs[i].name);
break;
@@ -878,12 +876,12 @@ atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
return 1;
PRINT_PROC("OS language : ");
- if (nvram[6] < fieldsize(languages))
+ if (nvram[6] < ARRAY_SIZE(languages))
PRINT_PROC("%s\n", languages[nvram[6]]);
else
PRINT_PROC("%u (undefined)\n", nvram[6]);
PRINT_PROC("Keyboard language: ");
- if (nvram[7] < fieldsize(languages))
+ if (nvram[7] < ARRAY_SIZE(languages))
PRINT_PROC("%s\n", languages[nvram[7]]);
else
PRINT_PROC("%u (undefined)\n", nvram[7]);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index cf45b100eff1..8a8ca32822ba 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1007,8 +1007,9 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
static void rx_ready_async(MGSLPC_INFO *info, int tcd)
{
- unsigned char data, status;
+ unsigned char data, status, flag;
int fifo_count;
+ int work = 0;
struct tty_struct *tty = info->tty;
struct mgsl_icount *icount = &info->icount;
@@ -1023,20 +1024,16 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
fifo_count = 32;
} else
fifo_count = 32;
-
+
+ tty_buffer_request_room(tty, fifo_count);
/* Flush received async data to receive data buffer. */
while (fifo_count) {
data = read_reg(info, CHA + RXFIFO);
status = read_reg(info, CHA + RXFIFO);
fifo_count -= 2;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
- *tty->flip.char_buf_ptr = data;
icount->rx++;
-
- *tty->flip.flag_buf_ptr = 0;
+ flag = TTY_NORMAL;
// if no frameing/crc error then save data
// BIT7:parity error
@@ -1055,26 +1052,23 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
status &= info->read_status_mask;
if (status & BIT7)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & BIT6)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ work += tty_insert_flip_char(tty, data, flag);
}
issue_command(info, CHA, CMD_RXFIFO);
if (debug_level >= DEBUG_LEVEL_ISR) {
- printk("%s(%d):rx_ready_async count=%d\n",
- __FILE__,__LINE__,tty->flip.count);
+ printk("%s(%d):rx_ready_async",
+ __FILE__,__LINE__);
printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
__FILE__,__LINE__,icount->rx,icount->brk,
icount->parity,icount->frame,icount->overrun);
}
- if (tty->flip.count)
+ if (work)
tty_flip_buffer_push(tty);
}
@@ -4005,7 +3999,7 @@ BOOLEAN register_test(MGSLPC_INFO *info)
{
static unsigned char patterns[] =
{ 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };
- static unsigned int count = sizeof(patterns) / sizeof(patterns[0]);
+ static unsigned int count = ARRAY_SIZE(patterns);
unsigned int i;
BOOLEAN rc = TRUE;
unsigned long flags;
@@ -4016,7 +4010,7 @@ BOOLEAN register_test(MGSLPC_INFO *info)
for (i = 0; i < count; i++) {
write_reg(info, XAD1, patterns[i]);
write_reg(info, XAD2, patterns[(i + 1) % count]);
- if ((read_reg(info, XAD1) != patterns[i]) ||
+ if ((read_reg(info, XAD1) != patterns[i]) ||
(read_reg(info, XAD2) != patterns[(i + 1) % count])) {
rc = FALSE;
break;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 49f3997fd251..9b5a2c0e7008 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -111,7 +111,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun
if (!to || tty->stopped)
return 0;
- c = to->ldisc.receive_room(to);
+ c = to->receive_room;
if (c > count)
c = count;
to->ldisc.receive_buf(to, buf, NULL, c);
@@ -126,7 +126,7 @@ static int pty_write_room(struct tty_struct *tty)
if (!to || tty->stopped)
return 0;
- return to->ldisc.receive_room(to);
+ return to->receive_room;
}
/*
diff --git a/drivers/char/random.c b/drivers/char/random.c
index bdfdfd28594d..86be04b241e1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -632,7 +632,7 @@ out:
preempt_enable();
}
-extern void add_input_randomness(unsigned int type, unsigned int code,
+void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value)
{
static unsigned char last_value;
diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h
index 0b397e1c8f1c..29c980204098 100644
--- a/drivers/char/rio/board.h
+++ b/drivers/char/rio/board.h
@@ -52,63 +52,57 @@ static char *_board_h_sccs_ = "@(#)board.h 1.2";
/*
** The shape of the Host Control area, at offset 0x7C00, Write Only
*/
-struct s_Ctrl
-{
- BYTE DpCtl; /* 7C00 */
- BYTE Dp_Unused2_[127];
- BYTE DpIntSet; /* 7C80 */
- BYTE Dp_Unused3_[127];
- BYTE DpTpuReset; /* 7D00 */
- BYTE Dp_Unused4_[127];
- BYTE DpIntReset; /* 7D80 */
- BYTE Dp_Unused5_[127];
+struct s_Ctrl {
+ BYTE DpCtl; /* 7C00 */
+ BYTE Dp_Unused2_[127];
+ BYTE DpIntSet; /* 7C80 */
+ BYTE Dp_Unused3_[127];
+ BYTE DpTpuReset; /* 7D00 */
+ BYTE Dp_Unused4_[127];
+ BYTE DpIntReset; /* 7D80 */
+ BYTE Dp_Unused5_[127];
};
/*
** The PROM data area on the host (0x7C00), Read Only
*/
-struct s_Prom
-{
- WORD DpSlxCode[2];
- WORD DpRev;
- WORD Dp_Unused6_;
- WORD DpUniq[4];
- WORD DpJahre;
- WORD DpWoche;
- WORD DpHwFeature[5];
- WORD DpOemId;
- WORD DpSiggy[16];
+struct s_Prom {
+ WORD DpSlxCode[2];
+ WORD DpRev;
+ WORD Dp_Unused6_;
+ WORD DpUniq[4];
+ WORD DpJahre;
+ WORD DpWoche;
+ WORD DpHwFeature[5];
+ WORD DpOemId;
+ WORD DpSiggy[16];
};
/*
** Union of the Ctrl and Prom areas
*/
-union u_CtrlProm /* This is the control/PROM area (0x7C00) */
-{
- struct s_Ctrl DpCtrl;
- struct s_Prom DpProm;
+union u_CtrlProm { /* This is the control/PROM area (0x7C00) */
+ struct s_Ctrl DpCtrl;
+ struct s_Prom DpProm;
};
/*
** The top end of memory!
*/
-struct s_ParmMapS /* Area containing Parm Map Pointer */
-{
- BYTE Dp_Unused8_[DP_PARMMAP_ADDR];
- WORD DpParmMapAd;
+struct s_ParmMapS { /* Area containing Parm Map Pointer */
+ BYTE Dp_Unused8_[DP_PARMMAP_ADDR];
+ WORD DpParmMapAd;
};
-struct s_StartUpS
-{
- BYTE Dp_Unused9_[DP_STARTUP_ADDR];
- BYTE Dp_LongJump[0x4];
- BYTE Dp_Unused10_[2];
- BYTE Dp_ShortJump[0x2];
+struct s_StartUpS {
+ BYTE Dp_Unused9_[DP_STARTUP_ADDR];
+ BYTE Dp_LongJump[0x4];
+ BYTE Dp_Unused10_[2];
+ BYTE Dp_ShortJump[0x2];
};
-union u_Sram2ParmMap /* This is the top of memory (0x7E00-0x7FFF) */
-{
- BYTE DpSramMem[DP_SRAM2_SIZE];
+union u_Sram2ParmMap { /* This is the top of memory (0x7E00-0x7FFF) */
+ BYTE DpSramMem[DP_SRAM2_SIZE];
struct s_ParmMapS DpParmMapS;
struct s_StartUpS DpStartUpS;
};
@@ -116,13 +110,12 @@ union u_Sram2ParmMap /* This is the top of memory (0x7E00-0x7FFF) */
/*
** This is the DP RAM overlay.
*/
-struct DpRam
-{
- BYTE DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */
- union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */
- union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */
- BYTE DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */
- BYTE DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */
+struct DpRam {
+ BYTE DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */
+ union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */
+ union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */
+ BYTE DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */
+ BYTE DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */
};
#define DpControl DpCtrlProm.DpCtrl.DpCtl
diff --git a/drivers/char/rio/bootpkt.h b/drivers/char/rio/bootpkt.h
index c329aeb7c871..602266e0c085 100644
--- a/drivers/char/rio/bootpkt.h
+++ b/drivers/char/rio/bootpkt.h
@@ -41,7 +41,7 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1" ;
+static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1";
#endif
#endif
@@ -49,14 +49,13 @@ static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1" ;
* Overlayed onto the Data fields of a regular
* Packet
************************************************/
-typedef struct BOOT_PKT BOOT_PKT ;
+typedef struct BOOT_PKT BOOT_PKT;
struct BOOT_PKT {
- short seq_num ;
- char data[10] ;
- } ;
+ short seq_num;
+ char data[10];
+};
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/brates.h b/drivers/char/rio/brates.h
deleted file mode 100644
index bd4fc84ec6cf..000000000000
--- a/drivers/char/rio/brates.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* BRATES.H *******
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date : 1 Nov 1990
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _brates_h
-#ifndef lint
-/* static char * _brates_h_sccs = "@(#)brates.h 1.4"; */
-#endif
-#define _brates_h 1
-/* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h
-*/
-#ifndef INKERNEL
-
-#define B0 0x00
-#define B50 0x01
-#define B75 0x02
-#define B110 0x03
-#define B134 0x04
-#define B150 0x05
-#define B200 0x06
-#define B300 0x07
-#define B600 0x08
-#define B1200 0x09
-#define B1800 0x0a
-#define B2400 0x0b
-#define B4800 0x0c
-#define B9600 0x0d
-#define B19200 0x0e
-#define B38400 0x0f
-
-#endif
-
-/*
-** The following baudrates may or may not be defined
-** on various UNIX systems.
-** If they are not then we define them.
-** If they are then we do not define them ;-)
-**
-** This is appalling that we use same definitions as UNIX
-** for our own download code as there is no garuntee that
-** B57600 will be defined as 0x11 by a UNIX system....
-** Arghhhhh!!!!!!!!!!!!!!
-*/
-#if !defined(B56000)
-#define B56000 0x10
-#endif
-
-#if !defined(B57600)
-#define B57600 0x11
-#endif
-
-#if !defined(B64000)
-#define B64000 0x12
-#endif
-
-#if !defined(B115200)
-#define B115200 0x13
-#endif
-
-
-#if !defined(B2000)
-#define B2000 0x14
-#endif
-
-
-#define MAX_RATE B2000
-
-struct baud_rate /* Tag for baud rates */
-{
- /* short host_rate,*/ /* As passed by the driver */
- short divisor, /* The divisor */
- prescaler; /* The pre-scaler */
-};
-
-#endif
diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h
deleted file mode 100644
index 5b306543328f..000000000000
--- a/drivers/char/rio/chan.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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 _chan_h
-#define _chan_h
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_chan_h_sccs = "@(#)chan.h 1.1" ;
-#endif
-#endif
-
-#define Link0 0
-#define Link1 1
-#define Link2 2
-#define Link3 3
-
-#endif
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
index cf056a990f18..217ff09f2fa1 100644
--- a/drivers/char/rio/cirrus.h
+++ b/drivers/char/rio/cirrus.h
@@ -73,20 +73,20 @@
#define TIMER_TICK 0x82
#define STOP_BREAK 0x83
#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH)))
-#define txack1 ((short *)0x7104)
-#define rxack1 ((short *)0x7102)
+#define txack1 ((short *)0x7104)
+#define rxack1 ((short *)0x7102)
#define mdack1 ((short *)0x7106)
-#define txack2 ((short *)0x7006)
-#define rxack2 ((short *)0x7004)
-#define mdack2 ((short *)0x7100)
+#define txack2 ((short *)0x7006)
+#define rxack2 ((short *)0x7004)
+#define mdack2 ((short *)0x7100)
#define int_latch ((short *) 0x7800)
-#define int_status ((short *) 0x7c00)
-#define tx1_pending 0x20
-#define rx1_pending 0x10
-#define md1_pending 0x40
-#define tx2_pending 0x02
-#define rx2_pending 0x01
-#define md2_pending 0x40
+#define int_status ((short *) 0x7c00)
+#define tx1_pending 0x20
+#define rx1_pending 0x10
+#define md1_pending 0x40
+#define tx2_pending 0x02
+#define rx2_pending 0x01
+#define md2_pending 0x40
#define module1_bits 0x07
#define module1_modern 0x08
#define module2_bits 0x70
@@ -113,65 +113,65 @@
NB. These registers are relative values on 8 bit boundaries whereas
on the RTA's the CIRRUS registers are on word boundaries. Use pointer
arithmetic (short *) to obtain the real addresses required */
-#define ccr 0x05 /* Channel Command Register */
-#define ier 0x06 /* Interrupt Enable Register */
-#define cor1 0x08 /* Channel Option Register 1 */
-#define cor2 0x09 /* Channel Option Register 2 */
-#define cor3 0x0a /* Channel Option Register 3 */
-#define cor4 0x1e /* Channel Option Register 4 */
-#define cor5 0x1f /* Channel Option Register 5 */
-
-#define ccsr 0x0b /* Channel Control Status Register */
-#define rdcr 0x0e /* Receive Data Count Register */
-#define tdcr 0x12 /* Transmit Data Count Register */
-#define mcor1 0x15 /* Modem Change Option Register 1 */
-#define mcor2 0x16 /* Modem Change Option Regsiter 2 */
-
-#define livr 0x18 /* Local Interrupt Vector Register */
-#define schr1 0x1a /* Special Character Register 1 */
-#define schr2 0x1b /* Special Character Register 2 */
-#define schr3 0x1c /* Special Character Register 3 */
-#define schr4 0x1d /* Special Character Register 4 */
-
-#define rtr 0x20 /* Receive Timer Register */
-#define rtpr 0x21 /* Receive Timeout Period Register */
-#define lnc 0x24 /* Lnext character */
-
-#define rivr 0x43 /* Receive Interrupt Vector Register */
-#define tivr 0x42 /* Transmit Interrupt Vector Register */
-#define mivr 0x41 /* Modem Interrupt Vector Register */
-#define gfrcr 0x40 /* Global Firmware Revision code Reg */
-#define ricr 0x44 /* Receive Interrupting Channel Reg */
-#define ticr 0x45 /* Transmit Interrupting Channel Reg */
-#define micr 0x46 /* Modem Interrupting Channel Register */
-
-#define gcr 0x4b /* Global configuration register*/
-#define misr 0x4c /* Modem interrupt status register */
+#define ccr 0x05 /* Channel Command Register */
+#define ier 0x06 /* Interrupt Enable Register */
+#define cor1 0x08 /* Channel Option Register 1 */
+#define cor2 0x09 /* Channel Option Register 2 */
+#define cor3 0x0a /* Channel Option Register 3 */
+#define cor4 0x1e /* Channel Option Register 4 */
+#define cor5 0x1f /* Channel Option Register 5 */
+
+#define ccsr 0x0b /* Channel Control Status Register */
+#define rdcr 0x0e /* Receive Data Count Register */
+#define tdcr 0x12 /* Transmit Data Count Register */
+#define mcor1 0x15 /* Modem Change Option Register 1 */
+#define mcor2 0x16 /* Modem Change Option Regsiter 2 */
+
+#define livr 0x18 /* Local Interrupt Vector Register */
+#define schr1 0x1a /* Special Character Register 1 */
+#define schr2 0x1b /* Special Character Register 2 */
+#define schr3 0x1c /* Special Character Register 3 */
+#define schr4 0x1d /* Special Character Register 4 */
+
+#define rtr 0x20 /* Receive Timer Register */
+#define rtpr 0x21 /* Receive Timeout Period Register */
+#define lnc 0x24 /* Lnext character */
+
+#define rivr 0x43 /* Receive Interrupt Vector Register */
+#define tivr 0x42 /* Transmit Interrupt Vector Register */
+#define mivr 0x41 /* Modem Interrupt Vector Register */
+#define gfrcr 0x40 /* Global Firmware Revision code Reg */
+#define ricr 0x44 /* Receive Interrupting Channel Reg */
+#define ticr 0x45 /* Transmit Interrupting Channel Reg */
+#define micr 0x46 /* Modem Interrupting Channel Register */
+
+#define gcr 0x4b /* Global configuration register */
+#define misr 0x4c /* Modem interrupt status register */
#define rbusr 0x59
#define tbusr 0x5a
#define mbusr 0x5b
-#define eoir 0x60 /* End Of Interrupt Register */
-#define rdsr 0x62 /* Receive Data / Status Register */
-#define tdr 0x63 /* Transmit Data Register */
-#define svrr 0x67 /* Service Request Register */
+#define eoir 0x60 /* End Of Interrupt Register */
+#define rdsr 0x62 /* Receive Data / Status Register */
+#define tdr 0x63 /* Transmit Data Register */
+#define svrr 0x67 /* Service Request Register */
-#define car 0x68 /* Channel Access Register */
-#define mir 0x69 /* Modem Interrupt Register */
-#define tir 0x6a /* Transmit Interrupt Register */
-#define rir 0x6b /* Receive Interrupt Register */
-#define msvr1 0x6c /* Modem Signal Value Register 1 */
-#define msvr2 0x6d /* Modem Signal Value Register 2*/
-#define psvr 0x6f /* Printer Signal Value Register*/
+#define car 0x68 /* Channel Access Register */
+#define mir 0x69 /* Modem Interrupt Register */
+#define tir 0x6a /* Transmit Interrupt Register */
+#define rir 0x6b /* Receive Interrupt Register */
+#define msvr1 0x6c /* Modem Signal Value Register 1 */
+#define msvr2 0x6d /* Modem Signal Value Register 2 */
+#define psvr 0x6f /* Printer Signal Value Register */
-#define tbpr 0x72 /* Transmit Baud Rate Period Register */
-#define tcor 0x76 /* Transmit Clock Option Register */
+#define tbpr 0x72 /* Transmit Baud Rate Period Register */
+#define tcor 0x76 /* Transmit Clock Option Register */
-#define rbpr 0x78 /* Receive Baud Rate Period Register */
-#define rber 0x7a /* Receive Baud Rate Extension Register */
-#define rcor 0x7c /* Receive Clock Option Register*/
-#define ppr 0x7e /* Prescalar Period Register */
+#define rbpr 0x78 /* Receive Baud Rate Period Register */
+#define rber 0x7a /* Receive Baud Rate Extension Register */
+#define rcor 0x7c /* Receive Clock Option Register */
+#define ppr 0x7e /* Prescalar Period Register */
/* Misc registers used for forcing the 1400 out of its reset woes */
#define airl 0x6d
@@ -192,10 +192,10 @@
/* RDSR - when status read from FIFO */
#define RDSR_BREAK 0x08 /* Break received */
-#define RDSR_TIMEOUT 0x80 /* No new data timeout */
-#define RDSR_SC1 0x10 /* Special char 1 (tx XON) matched */
-#define RDSR_SC2 0x20 /* Special char 2 (tx XOFF) matched */
-#define RDSR_SC12_MASK 0x30 /* Mask for special chars 1 and 2 */
+#define RDSR_TIMEOUT 0x80 /* No new data timeout */
+#define RDSR_SC1 0x10 /* Special char 1 (tx XON) matched */
+#define RDSR_SC2 0x20 /* Special char 2 (tx XOFF) matched */
+#define RDSR_SC12_MASK 0x30 /* Mask for special chars 1 and 2 */
/* PPR */
#define PPR_DEFAULT 0x31 /* Default value - for a 25Mhz clock gives
@@ -244,7 +244,7 @@
#define IER_TIMEOUT 0x01 /* Timeout on no data */
#define IER_DEFAULT 0x94 /* Default values */
-#define IER_PARALLEL 0x84 /* Default for Parallel */
+#define IER_PARALLEL 0x84 /* Default for Parallel */
#define IER_EMPTY 0x92 /* Transmitter empty rather than ready */
/* COR1 - Driver only */
@@ -264,11 +264,11 @@
#define COR1_7BITS 0x02 /* 7 data bits */
#define COR1_8BITS 0x03 /* 8 data bits */
-#define COR1_HOST 0xef /* Safe host bits */
+#define COR1_HOST 0xef /* Safe host bits */
/* RTA only */
-#define COR1_CINPCK 0x00 /* Check parity of received characters */
-#define COR1_CNINPCK 0x10 /* Don't check parity */
+#define COR1_CINPCK 0x00 /* Check parity of received characters */
+#define COR1_CNINPCK 0x10 /* Don't check parity */
/* COR2 bits for both RTA and driver use */
#define COR2_IXANY 0x80 /* IXANY - any character is XON */
@@ -293,9 +293,9 @@
#define COR3_FCT 0x20 /* Flow control transparency */
#define COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */
#define COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */
-#define COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */
-#define COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */
-#define COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */
+#define COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */
+#define COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */
+#define COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */
#define COR3_THRESHOLD COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */
@@ -386,7 +386,7 @@
#define MCOR_THRESHBITS 0x0F /* mask for ANDing out the above */
-#define MCOR_THRESHOLD MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */
+#define MCOR_THRESHOLD MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */
/* RTPR */
@@ -429,25 +429,25 @@
#define CONFIG 0x01 /* Configure a port */
#define MOPEN 0x02 /* Modem open (block for DCD) */
#define CLOSE 0x03 /* Close a port */
-#define WFLUSH (0x04 | PRE_EMPTIVE) /* Write flush */
-#define RFLUSH (0x05 | PRE_EMPTIVE) /* Read flush */
-#define RESUME (0x06 | PRE_EMPTIVE) /* Resume if xoffed */
-#define SBREAK 0x07 /* Start break */
+#define WFLUSH (0x04 | PRE_EMPTIVE) /* Write flush */
+#define RFLUSH (0x05 | PRE_EMPTIVE) /* Read flush */
+#define RESUME (0x06 | PRE_EMPTIVE) /* Resume if xoffed */
+#define SBREAK 0x07 /* Start break */
#define EBREAK 0x08 /* End break */
-#define SUSPEND (0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
-#define FCLOSE (0x0a | PRE_EMPTIVE) /* Force close */
-#define XPRINT 0x0b /* Xprint packet */
-#define MBIS (0x0c | PRE_EMPTIVE) /* Set modem lines */
-#define MBIC (0x0d | PRE_EMPTIVE) /* Clear modem lines */
-#define MSET (0x0e | PRE_EMPTIVE) /* Set modem lines */
+#define SUSPEND (0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
+#define FCLOSE (0x0a | PRE_EMPTIVE) /* Force close */
+#define XPRINT 0x0b /* Xprint packet */
+#define MBIS (0x0c | PRE_EMPTIVE) /* Set modem lines */
+#define MBIC (0x0d | PRE_EMPTIVE) /* Clear modem lines */
+#define MSET (0x0e | PRE_EMPTIVE) /* Set modem lines */
#define PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */
-#define MGET (0x10 | PRE_EMPTIVE) /* Force update of modem status */
-#define MEMDUMP (0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
-#define READ_REGISTER (0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
+#define MGET (0x10 | PRE_EMPTIVE) /* Force update of modem status */
+#define MEMDUMP (0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
+#define READ_REGISTER (0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
use data[4] / data[3] to indicate current state and modem status respectively
-*/
+*/
#define COMPLETE (0x20 | PRE_EMPTIVE)
/* Command complete */
diff --git a/drivers/char/rio/cmd.h b/drivers/char/rio/cmd.h
deleted file mode 100644
index c369edaea2b3..000000000000
--- a/drivers/char/rio/cmd.h
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-/****************************************************************************
- ******* *******
- ******* C O M M A N D P A C K E T H E A D E R S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-
-#ifndef _cmd_h
-#define _cmd_h
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1" ;
-#endif
-#endif
-
-
-#define PRE_EMPTIVE_CMD 0x80
-#define INLINE_CMD ~PRE_EMPTIVE_CMD
-
-#define CMD_IGNORE_PKT ( (ushort) 0)
-#define CMD_STATUS_REQ ( (ushort) 1)
-#define CMD_UNIT_STATUS_REQ ( (ushort) 2) /* Is this needed ??? */
-#define CMD_CONF_PORT ( (ushort) 3)
-#define CMD_CONF_UNIT ( (ushort) 4)
-#define CMD_ROUTE_MAP_REQ ( (ushort) 5)
-#define CMD_FLUSH_TX ( (ushort) 6)
-#define CMD_FLUSH_RX ( (ushort) 7)
-#define CMD_PARTION_PORT ( (ushort) 8)
-#define CMD_RESET_PORT ( (ushort) 0x0a)
-#define CMD_BOOT_UNIT ( (ushort) 0x0b)
-#define CMD_FOUND_UNIT ( (ushort) 0x0c)
-#define CMD_ATTACHED_RTA_2 ( (ushort) 0x0d)
-#define CMD_PROVIDE_BOOT ( (ushort) 0x0e)
-#define CMD_CIRRUS ( (ushort) 0x0f)
-
-#define FORM_STATUS_PKT ( (ushort) 1 )
-#define FORM_POLL_PKT ( (ushort) 2 )
-#define FORM_LINK_STATUS_PKT ( (ushort) 3 )
-
-
-#define CMD_DATA_PORT ( (ushort) 1 )
-#define CMD_DATA ( (ushort) 2 )
-
-#define CMD_TX_PART ( (ushort) 2 )
-#define CMD_RX_PART ( (ushort) 3 )
-#define CMD_RX_LIMIT ( (ushort) 4 )
-
-#endif
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h
index 2b8efbdbee1c..a9a8c45631d7 100644
--- a/drivers/char/rio/cmdblk.h
+++ b/drivers/char/rio/cmdblk.h
@@ -44,16 +44,15 @@ static char *_cmdblk_h_sccs_ = "@(#)cmdblk.h 1.2";
** a rup.
*/
-struct CmdBlk
-{
- struct CmdBlk *NextP; /* Pointer to next command block */
- struct PKT Packet; /* A packet, to copy to the rup */
- /* The func to call to check if OK */
- int (*PreFuncP)(int, struct CmdBlk *);
- int PreArg; /* The arg for the func */
- /* The func to call when completed */
- int (*PostFuncP)(int, struct CmdBlk *);
- int PostArg; /* The arg for the func */
+struct CmdBlk {
+ struct CmdBlk *NextP; /* Pointer to next command block */
+ struct PKT Packet; /* A packet, to copy to the rup */
+ /* The func to call to check if OK */
+ int (*PreFuncP) (int, struct CmdBlk *);
+ int PreArg; /* The arg for the func */
+ /* The func to call when completed */
+ int (*PostFuncP) (int, struct CmdBlk *);
+ int PostArg; /* The arg for the func */
};
#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h
index 46befd354f20..77cee8df68ef 100644
--- a/drivers/char/rio/cmdpkt.h
+++ b/drivers/char/rio/cmdpkt.h
@@ -54,135 +54,112 @@ static char *_cmdpkt_h_sccs_ = "@(#)cmdpkt.h 1.2";
** This structure overlays a PktCmd->CmdData structure, and so starts
** at Data[2] in the actual pkt!
*/
-struct BootSequence
-{
- WORD NumPackets;
- WORD LoadBase;
- WORD CodeSize;
+struct BootSequence {
+ WORD NumPackets;
+ WORD LoadBase;
+ WORD CodeSize;
};
#define BOOT_SEQUENCE_LEN 8
-struct SamTop
-{
- BYTE Unit;
- BYTE Link;
+struct SamTop {
+ BYTE Unit;
+ BYTE Link;
};
-struct CmdHdr
-{
- BYTE PcCommand;
- union
- {
- BYTE PcPhbNum;
- BYTE PcLinkNum;
- BYTE PcIDNum;
- } U0;
+struct CmdHdr {
+ BYTE PcCommand;
+ union {
+ BYTE PcPhbNum;
+ BYTE PcLinkNum;
+ BYTE PcIDNum;
+ } U0;
};
-struct PktCmd
-{
- union
- {
- struct
- {
- struct CmdHdr CmdHdr;
- struct BootSequence PcBootSequence;
- } S1;
- struct
- {
- WORD PcSequence;
- BYTE PcBootData[RTA_BOOT_DATA_SIZE];
- } S2;
- struct
- {
- WORD __crud__;
- BYTE PcUniqNum[4]; /* this is really a uint. */
- BYTE PcModuleTypes; /* what modules are fitted */
- } S3;
- struct
- {
- struct CmdHdr CmdHdr;
- BYTE __undefined__;
- BYTE PcModemStatus;
- BYTE PcPortStatus;
- BYTE PcSubCommand; /* commands like mem or register dump */
- WORD PcSubAddr; /* Address for command */
- BYTE PcSubData[64]; /* Date area for command */
- } S4;
- struct
- {
- struct CmdHdr CmdHdr;
- BYTE PcCommandText[1];
- BYTE __crud__[20];
- BYTE PcIDNum2; /* It had to go somewhere! */
- } S5;
- struct
- {
- struct CmdHdr CmdHdr;
- struct SamTop Topology[LINKS_PER_UNIT];
- } S6;
- } U1;
+struct PktCmd {
+ union {
+ struct {
+ struct CmdHdr CmdHdr;
+ struct BootSequence PcBootSequence;
+ } S1;
+ struct {
+ WORD PcSequence;
+ BYTE PcBootData[RTA_BOOT_DATA_SIZE];
+ } S2;
+ struct {
+ WORD __crud__;
+ BYTE PcUniqNum[4]; /* this is really a uint. */
+ BYTE PcModuleTypes; /* what modules are fitted */
+ } S3;
+ struct {
+ struct CmdHdr CmdHdr;
+ BYTE __undefined__;
+ BYTE PcModemStatus;
+ BYTE PcPortStatus;
+ BYTE PcSubCommand; /* commands like mem or register dump */
+ WORD PcSubAddr; /* Address for command */
+ BYTE PcSubData[64]; /* Date area for command */
+ } S4;
+ struct {
+ struct CmdHdr CmdHdr;
+ BYTE PcCommandText[1];
+ BYTE __crud__[20];
+ BYTE PcIDNum2; /* It had to go somewhere! */
+ } S5;
+ struct {
+ struct CmdHdr CmdHdr;
+ struct SamTop Topology[LINKS_PER_UNIT];
+ } S6;
+ } U1;
};
-struct PktCmd_M
-{
- union
- {
- struct
- {
- struct
- {
- uchar PcCommand;
- union
- {
- uchar PcPhbNum;
- uchar PcLinkNum;
- uchar PcIDNum;
- } U0;
- } CmdHdr;
- struct
- {
- ushort NumPackets;
- ushort LoadBase;
- ushort CodeSize;
- } PcBootSequence;
- } S1;
- struct
- {
- ushort PcSequence;
- uchar PcBootData[RTA_BOOT_DATA_SIZE];
- } S2;
- struct
- {
- ushort __crud__;
- uchar PcUniqNum[4]; /* this is really a uint. */
- uchar PcModuleTypes; /* what modules are fitted */
- } S3;
- struct
- {
- ushort __cmd_hdr__;
- uchar __undefined__;
- uchar PcModemStatus;
- uchar PcPortStatus;
- uchar PcSubCommand;
- ushort PcSubAddr;
- uchar PcSubData[64];
- } S4;
- struct
- {
- ushort __cmd_hdr__;
- uchar PcCommandText[1];
- uchar __crud__[20];
- uchar PcIDNum2; /* Tacked on end */
- } S5;
- struct
- {
- ushort __cmd_hdr__;
- struct Top Topology[LINKS_PER_UNIT];
- } S6;
- } U1;
+struct PktCmd_M {
+ union {
+ struct {
+ struct {
+ uchar PcCommand;
+ union {
+ uchar PcPhbNum;
+ uchar PcLinkNum;
+ uchar PcIDNum;
+ } U0;
+ } CmdHdr;
+ struct {
+ ushort NumPackets;
+ ushort LoadBase;
+ ushort CodeSize;
+ } PcBootSequence;
+ } S1;
+ struct {
+ ushort PcSequence;
+ uchar PcBootData[RTA_BOOT_DATA_SIZE];
+ } S2;
+ struct {
+ ushort __crud__;
+ uchar PcUniqNum[4]; /* this is really a uint. */
+ uchar PcModuleTypes; /* what modules are fitted */
+ } S3;
+ struct {
+ ushort __cmd_hdr__;
+ uchar __undefined__;
+ uchar PcModemStatus;
+ uchar PcPortStatus;
+ uchar PcSubCommand;
+ ushort PcSubAddr;
+ uchar PcSubData[64];
+ } S4;
+ struct {
+ ushort __cmd_hdr__;
+ uchar PcCommandText[1];
+ uchar __crud__[20];
+ uchar PcIDNum2; /* Tacked on end */
+ } S5;
+ struct {
+ ushort __cmd_hdr__;
+ struct Top Topology[LINKS_PER_UNIT];
+ } S6;
+ } U1;
};
#define Command U1.S1.CmdHdr.PcCommand
diff --git a/drivers/char/rio/control.h b/drivers/char/rio/control.h
index 1712f6261dd1..6853d03304a3 100644
--- a/drivers/char/rio/control.h
+++ b/drivers/char/rio/control.h
@@ -51,12 +51,11 @@
#define UFOAD ( CONTROL + 4 )
#define IWAIT ( CONTROL + 5 )
-#define IFOAD_MAGIC 0xF0AD /* of course */
+#define IFOAD_MAGIC 0xF0AD /* of course */
#define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */
-#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */
-#define IWAIT_MAGIC 0xB1DE /* Bide your time */
+#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */
+#define IWAIT_MAGIC 0xB1DE /* Bide your time */
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h
index 62dba0e68b3e..28a991bd4fe6 100644
--- a/drivers/char/rio/daemon.h
+++ b/drivers/char/rio/daemon.h
@@ -44,18 +44,16 @@ static char *_daemon_h_sccs_ = "@(#)daemon.h 1.3";
** structures used on /dev/rio
*/
-struct Error
-{
- uint Error;
- uint Entry;
- uint Other;
+struct Error {
+ uint Error;
+ uint Entry;
+ uint Other;
};
-struct DownLoad
-{
- char *DataP;
- uint Count;
- uint ProductCode;
+struct DownLoad {
+ char *DataP;
+ uint Count;
+ uint ProductCode;
};
/*
@@ -66,46 +64,41 @@ struct DownLoad
#endif
#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */
+#define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */
#endif
-struct PortSetup
-{
- uint From; /* Set/Clear XP & IXANY Control from this port.... */
- uint To; /* .... to this port */
- uint XpCps; /* at this speed */
- char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */
- char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */
- uchar IxAny; /* enable/disable IXANY */
- uchar IxOn; /* enable/disable IXON */
- uchar Lock; /* lock port params */
- uchar Store; /* store params across closes */
- uchar Drain; /* close only when drained */
+struct PortSetup {
+ uint From; /* Set/Clear XP & IXANY Control from this port.... */
+ uint To; /* .... to this port */
+ uint XpCps; /* at this speed */
+ char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */
+ char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */
+ uchar IxAny; /* enable/disable IXANY */
+ uchar IxOn; /* enable/disable IXON */
+ uchar Lock; /* lock port params */
+ uchar Store; /* store params across closes */
+ uchar Drain; /* close only when drained */
};
-struct LpbReq
-{
- uint Host;
- uint Link;
- struct LPB *LpbP;
+struct LpbReq {
+ uint Host;
+ uint Link;
+ struct LPB *LpbP;
};
-struct RupReq
-{
- uint HostNum;
- uint RupNum;
- struct RUP *RupP;
+struct RupReq {
+ uint HostNum;
+ uint RupNum;
+ struct RUP *RupP;
};
-struct PortReq
-{
- uint SysPort;
- struct Port *PortP;
+struct PortReq {
+ uint SysPort;
+ struct Port *PortP;
};
-struct StreamInfo
-{
- uint SysPort;
+struct StreamInfo {
+ uint SysPort;
#if 0
queue_t RQueue;
queue_t WQueue;
@@ -115,68 +108,59 @@ struct StreamInfo
#endif
};
-struct HostReq
-{
- uint HostNum;
- struct Host *HostP;
+struct HostReq {
+ uint HostNum;
+ struct Host *HostP;
};
-struct HostDpRam
-{
- uint HostNum;
- struct DpRam *DpRamP;
+struct HostDpRam {
+ uint HostNum;
+ struct DpRam *DpRamP;
};
-struct DebugCtrl
-{
- uint SysPort;
- uint Debug;
- uint Wait;
+struct DebugCtrl {
+ uint SysPort;
+ uint Debug;
+ uint Wait;
};
-struct MapInfo
-{
- uint FirstPort; /* 8 ports, starting from this (tty) number */
- uint RtaUnique; /* reside on this RTA (unique number) */
+struct MapInfo {
+ uint FirstPort; /* 8 ports, starting from this (tty) number */
+ uint RtaUnique; /* reside on this RTA (unique number) */
};
-struct MapIn
-{
- uint NumEntries; /* How many port sets are we mapping? */
- struct MapInfo *MapInfoP; /* Pointer to (user space) info */
+struct MapIn {
+ uint NumEntries; /* How many port sets are we mapping? */
+ struct MapInfo *MapInfoP; /* Pointer to (user space) info */
};
-struct SendPack
-{
- unsigned int PortNum;
- unsigned char Len;
- unsigned char Data[PKT_MAX_DATA_LEN];
+struct SendPack {
+ unsigned int PortNum;
+ unsigned char Len;
+ unsigned char Data[PKT_MAX_DATA_LEN];
};
-struct SpecialRupCmd
-{
- struct PKT Packet;
- unsigned short Host;
- unsigned short RupNum;
+struct SpecialRupCmd {
+ struct PKT Packet;
+ unsigned short Host;
+ unsigned short RupNum;
};
-struct IdentifyRta
-{
- ulong RtaUnique;
- uchar ID;
+struct IdentifyRta {
+ ulong RtaUnique;
+ uchar ID;
};
-struct KillNeighbour
-{
- ulong UniqueNum;
- uchar Link;
+struct KillNeighbour {
+ ulong UniqueNum;
+ uchar Link;
};
struct rioVersion {
- char version[MAX_VERSION_LEN];
- char relid[MAX_VERSION_LEN];
- int buildLevel;
- char buildDate[MAX_VERSION_LEN];
+ char version[MAX_VERSION_LEN];
+ char relid[MAX_VERSION_LEN];
+ int buildLevel;
+ char buildDate[MAX_VERSION_LEN];
};
@@ -316,16 +300,16 @@ struct rioVersion {
#define RIO_SET_XP_CPS rIOCW(155,int)
#define RIO_GET_IXANY rIOCR(156,int) /* ixany allowed? */
#define RIO_SET_IXANY rIOCW(157,int)
-#define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */
-#define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */
+#define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */
+#define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */
#define RIO_GET_MODEM rIOCR(160,int) /* port is modem/direct line? */
#define RIO_SET_MODEM rIOCW(161,int)
-#define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */
-#define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */
+#define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */
+#define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */
#define RIO_GET_IXON rIOCR(164,int) /* ixon allowed? */
#define RIO_SET_IXON rIOCW(165,int)
-#define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */
-#define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */
+#define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */
+#define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */
#define RIO_GET_SIVIEW ((('s')<<8) | 106) /* backwards compatible with SI */
diff --git a/drivers/char/rio/data.h b/drivers/char/rio/data.h
deleted file mode 100644
index dabc2d1fa40f..000000000000
--- a/drivers/char/rio/data.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-**
-** Module : data.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:09
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)data.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_datadex__
-#define __rio_datadex__
-
-#ifndef lint
-static char *_data_h_sccs_ = "@(#)data.h 1.2";
-#endif
-
-#endif
diff --git a/drivers/char/rio/debug.h b/drivers/char/rio/debug.h
deleted file mode 100644
index b6e0d0935552..000000000000
--- a/drivers/char/rio/debug.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-** File: debug.h
-**
-** Author: David Dix
-**
-** Created: 12th March 1993
-**
-** Last modified: 93/04/27
-**
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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 _debug_h_
-#define _debug_h_
-
-
-#if defined(DCIRRUS)
-#define DBPACKET(pkt, opt, str, chn) debug_packet((pkt), (opt), (str), (chn))
-#else
-#define DBPACKET(pkt, opt, str, c)
-#endif /* DCIRRUS */
-
-
-#endif /* _debug_h_ */
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h
index 2e7309e27622..5b600c32ac02 100644
--- a/drivers/char/rio/defaults.h
+++ b/drivers/char/rio/defaults.h
@@ -37,13 +37,13 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1" ;
+static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1";
#endif
#endif
-#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
-#define SECOND (int) 15625 /* Low priority ticks */
+#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
+#define SECOND (int) 15625 /* Low priority ticks */
#ifdef RTA
#define RX_LIMIT (ushort) 3
@@ -56,4 +56,3 @@ static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1" ;
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/eisa.h b/drivers/char/rio/eisa.h
deleted file mode 100644
index 59371b0528b0..000000000000
--- a/drivers/char/rio/eisa.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-**
-** Module : eisa.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:10
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)eisa.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_eisa_h__
-#define __rio_eisa_h__
-
-#ifdef SCCS_LABELS
-#ifndef lint
-static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2";
-#endif
-#endif
-
-/*
-** things to do with the EISA bus
-*/
-
-#define RIO_EISA_STRING_ADDRESS 0xfffd9 /* where EISA is stored */
-
-#define RIO_MAX_EISA_SLOTS 16 /* how many EISA slots? */
-
-#define RIO_EISA_IDENT 0x984D /* Specialix */
-#define RIO_EISA_PRODUCT_CODE 0x14 /* Code 14 */
-#define RIO_EISA_ENABLE_BIT 0x01 /* To enable card */
-
-#define EISA_MEMORY_BASE_LO 0xC00 /* A16-A23 */
-#define EISA_MEMORY_BASE_HI 0xC01 /* A24-A31 */
-#define EISA_INTERRUPT_VEC 0xC02 /* see below */
-#define EISA_CONTROL_PORT 0xC02 /* see below */
-#define EISA_INTERRUPT_RESET 0xC03 /* read to clear IRQ */
-
-#define EISA_PRODUCT_IDENT_LO 0xC80 /* where RIO_EISA_IDENT is */
-#define EISA_PRODUCT_IDENT_HI 0xC81
-#define EISA_PRODUCT_NUMBER 0xC82 /* where PROD_CODE is */
-#define EISA_REVISION_NUMBER 0xC83 /* revision (1dp) */
-#define EISA_ENABLE 0xC84 /* set LSB to enable card */
-#define EISA_UNIQUE_NUM_0 0xC88 /* vomit */
-#define EISA_UNIQUE_NUM_1 0xC8A
-#define EISA_UNIQUE_NUM_2 0xC90 /* bit strangely arranged */
-#define EISA_UNIQUE_NUM_3 0xC92
-#define EISA_MANUF_YEAR 0xC98 /* when */
-#define EISA_MANUF_WEEK 0xC9A /* more when */
-
-#define EISA_TP_BOOT_FROM_RAM 0x01
-#define EISA_TP_BOOT_FROM_LINK 0x00
-#define EISA_TP_FAST_LINKS 0x02
-#define EISA_TP_SLOW_LINKS 0x00
-#define EISA_TP_BUS_ENABLE 0x04
-#define EISA_TP_BUS_DISABLE 0x00
-#define EISA_TP_RUN 0x08
-#define EISA_TP_RESET 0x00
-#define EISA_POLLED 0x00
-#define EISA_IRQ_3 0x30
-#define EISA_IRQ_4 0x40
-#define EISA_IRQ_5 0x50
-#define EISA_IRQ_6 0x60
-#define EISA_IRQ_7 0x70
-#define EISA_IRQ_9 0x90
-#define EISA_IRQ_10 0xA0
-#define EISA_IRQ_11 0xB0
-#define EISA_IRQ_12 0xC0
-#define EISA_IRQ_14 0xE0
-#define EISA_IRQ_15 0xF0
-
-#define EISA_INTERRUPT_MASK 0xF0
-#define EISA_CONTROL_MASK 0x0F
-
-#define RIO_EISA_DEFAULT_MODE EISA_TP_SLOW_LINKS
-
-#define RIOEisaToIvec(X) (uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4)
-
-#define INBZ(z,x) inb(((z)<<12) | (x))
-#define OUTBZ(z,x,y) outb((((z)<<12) | (x)), y)
-
-#endif /* __rio_eisa_h__ */
diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h
deleted file mode 100644
index 8e9a419e15b0..000000000000
--- a/drivers/char/rio/enable.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* E N A B L E H E A D E R S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_enable_h_sccs = "@(#)enable.h 1.1" ;
-#endif
-#endif
-
-
-#define ENABLE_LTT TRUE
-#define ENABLE_LRT TRUE
-
-
-/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/error.h b/drivers/char/rio/error.h
index 229438e355f2..f20f0789db8f 100644
--- a/drivers/char/rio/error.h
+++ b/drivers/char/rio/error.h
@@ -80,6 +80,3 @@
/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/errors.h b/drivers/char/rio/errors.h
index f920b9f3e2bd..1d0d89144337 100644
--- a/drivers/char/rio/errors.h
+++ b/drivers/char/rio/errors.h
@@ -101,4 +101,4 @@ static char *_errors_h_sccs_ = "@(#)errors.h 1.2";
#define NOT_ENOUGH_CORE_FOR_PCI_COPY 53
-#endif /* __rio_errors_h__ */
+#endif /* __rio_errors_h__ */
diff --git a/drivers/char/rio/formpkt.h b/drivers/char/rio/formpkt.h
deleted file mode 100644
index a8b65ae0de90..000000000000
--- a/drivers/char/rio/formpkt.h
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-/****************************************************************************
- ******* *******
- ******* F O R M P A C K E T H E A D E R F I L E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _formpkt_h
-#define _formpkt_h 1
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1" ;
-#endif
-#endif
-
-typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1 ;
-struct FORM_BOOT_PKT_1 {
- ushort pkt_number ;
- ushort pkt_total ;
- ushort boot_top ;
- } ;
-
-typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2 ;
-struct FORM_BOOT_PKT_2 {
- ushort pkt_number ;
- char boot_data[10] ;
- } ;
-
-
-typedef struct FORM_ATTACH_RTA FORM_ATTACH_RTA ;
-struct FORM_ATTACH_RTA {
- char cmd_code ;
- char booter_serial[4] ;
- char booter_link ;
- char bootee_serial[4] ;
- char bootee_link ;
- } ;
-
-
-typedef struct FORM_BOOT_ID FORM_BOOT_ID ;
-struct FORM_BOOT_ID {
- char cmd_code ;
- char bootee_serial[4] ;
- char bootee_prod_id ;
- char bootee_link ;
- } ;
-
-
-
-typedef struct FORM_ROUTE_1 FORM_ROUTE_1 ;
-struct FORM_ROUTE_1 {
- char cmd_code ;
- char pkt_number ;
- char total_in_sequence ;
- char unit_id ;
- char host_unit_id ;
- } ;
-
-typedef struct FORM_ROUTE_2 FORM_ROUTE_2 ;
-struct FORM_ROUTE_2 {
- char cmd_code ;
- char pkt_number ;
- char total_in_sequence ;
- char route_data[9] ;
- } ;
-
-typedef struct FORM_ROUTE_REQ FORM_ROUTE_REQ ;
-struct FORM_ROUTE_REQ {
- char cmd_code ;
- char pkt_number ;
- char total_in_sequence ;
- char route_data[10] ;
- } ;
-
-
-typedef struct FORM_ERROR FORM_ERROR ;
-struct FORM_ERROR {
- char cmd_code ;
- char error_code ;
-
- } ;
-
-typedef struct FORM_STATUS FORM_STATUS ;
-struct FORM_STATUS {
- char cmd_code ;
- char status_code ;
- char last_packet_valid ;
- char tx_buffer ;
- char rx_buffer ;
- char port_status ;
- char phb_status ;
- } ;
-
-
-typedef struct FORM_LINK_STATUS FORM_LINK_STATUS ;
-struct FORM_LINK_STATUS {
- char cmd_code ;
- char status_code ;
- char link_number ;
- ushort rx_errors ;
- ushort tx_errors ;
- ushort csum_errors ;
- ushort disconnects ;
- } ;
-
-
-
-typedef struct FORM_PARTITION FORM_PARTITION ;
-struct FORM_PARTITION {
- char cmd_code ;
- char status_code ;
- char port_number ;
- char tx_max ;
- char rx_max ;
- char rx_limit ;
- } ;
-
-
-#endif
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index 01987c6dc398..b4778410ec6e 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -47,20 +47,19 @@ int RIOBootCodeHOST(struct rio_info *, register struct DownLoad *);
int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
void msec_timeout(struct Host *);
int RIOBootRup(struct rio_info *, uint, struct Host *, struct PKT *);
-int RIOBootOk(struct rio_info *,struct Host *, ulong);
-int RIORtaBound(struct rio_info *, uint);
+int RIOBootOk(struct rio_info *, struct Host *, ulong);
+int RIORtaBound(struct rio_info *, uint);
void FillSlot(int, int, uint, struct Host *);
/* riocmd.c */
int RIOFoadRta(struct Host *, struct Map *);
int RIOZombieRta(struct Host *, struct Map *);
-int RIOCommandRta(struct rio_info *, uint, int (* func)( struct Host *,
- struct Map *));
-int RIOIdentifyRta(struct rio_info *, caddr_t);
+int RIOCommandRta(struct rio_info *, uint, int (*func) (struct Host *, struct Map *));
+int RIOIdentifyRta(struct rio_info *, caddr_t);
int RIOKillNeighbour(struct rio_info *, caddr_t);
int RIOSuspendBootRta(struct Host *, int, int);
int RIOFoadWakeup(struct rio_info *);
-struct CmdBlk * RIOGetCmdBlk(void);
+struct CmdBlk *RIOGetCmdBlk(void);
void RIOFreeCmdBlk(struct CmdBlk *);
int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *);
void RIOPollHostCommands(struct rio_info *, struct Host *);
@@ -71,13 +70,13 @@ void ShowPacket(uint, struct PKT *);
/* rioctrl.c */
int copyin(int, caddr_t, int);
-int riocontrol(struct rio_info *, dev_t,int,caddr_t,int);
-int RIOPreemptiveCmd(struct rio_info *,struct Port *,uchar);
+int riocontrol(struct rio_info *, dev_t, int, caddr_t, int);
+int RIOPreemptiveCmd(struct rio_info *, struct Port *, uchar);
/* rioinit.c */
void rioinit(struct rio_info *, struct RioHostInfo *);
void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
-void RIOISAinit(struct rio_info *,int);
+void RIOISAinit(struct rio_info *, int);
int RIODoAT(struct rio_info *, int, int);
caddr_t RIOCheckForATCard(int);
int RIOAssignAT(struct rio_info *, int, caddr_t, int);
@@ -85,7 +84,7 @@ int RIOBoardTest(paddr_t, caddr_t, uchar, int);
void RIOAllocDataStructs(struct rio_info *);
void RIOSetupDataStructs(struct rio_info *);
int RIODefaultName(struct rio_info *, struct Host *, uint);
-struct rioVersion * RIOVersid(void);
+struct rioVersion *RIOVersid(void);
int RIOMapin(paddr_t, int, caddr_t *);
void RIOMapout(paddr_t, long, caddr_t);
void RIOHostReset(uint, volatile struct DpRam *, uint);
@@ -108,7 +107,7 @@ void remove_receive(struct Port *);
/* rioroute.c */
int RIORouteRup(struct rio_info *, uint, struct Host *, struct PKT *);
-void RIOFixPhbs(struct rio_info *, struct Host *, uint);
+void RIOFixPhbs(struct rio_info *, struct Host *, uint);
uint GetUnitType(uint);
int RIOSetChange(struct rio_info *);
int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
@@ -116,9 +115,9 @@ int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
/* riotty.c */
-int riotopen(struct tty_struct * tty, struct file * filp);
-int riotclose(void *ptr);
-int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t);
+int riotopen(struct tty_struct *tty, struct file *filp);
+int riotclose(void *ptr);
+int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t);
void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
/* riotable.c */
@@ -127,27 +126,27 @@ int RIOApel(struct rio_info *);
int RIODeleteRta(struct rio_info *, struct Map *);
int RIOAssignRta(struct rio_info *, struct Map *);
int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
-int RIOChangeName(struct rio_info *, struct Map*);
+int RIOChangeName(struct rio_info *, struct Map *);
#if 0
/* riodrvr.c */
-struct rio_info * rio_install(struct RioHostInfo *);
+struct rio_info *rio_install(struct RioHostInfo *);
int rio_uninstall(register struct rio_info *);
int rio_open(struct rio_info *, int, struct file *);
int rio_close(struct rio_info *, struct file *);
int rio_read(struct rio_info *, struct file *, char *, int);
-int rio_write(struct rio_info *, struct file * f, char *, int);
+int rio_write(struct rio_info *, struct file *f, char *, int);
int rio_ioctl(struct rio_info *, struct file *, int, char *);
-int rio_select(struct rio_info *, struct file * f, int, struct sel *);
-int rio_intr(char *);
-int rio_isr_thread(char *);
-struct rio_info * rio_info_store( int cmd, struct rio_info * p);
+int rio_select(struct rio_info *, struct file *f, int, struct sel *);
+int rio_intr(char *);
+int rio_isr_thread(char *);
+struct rio_info *rio_info_store(int cmd, struct rio_info *p);
#endif
-extern int rio_pcicopy(char *src, char *dst, int n);
-extern int rio_minor (struct tty_struct *tty);
-extern int rio_ismodem (struct tty_struct *tty);
+extern int rio_pcicopy(char *src, char *dst, int n);
+extern int rio_minor(struct tty_struct *tty);
+extern int rio_ismodem(struct tty_struct *tty);
-extern void rio_start_card_running (struct Host * HostP);
+extern void rio_start_card_running(struct Host *HostP);
-#endif /* __func_h_def */
+#endif /* __func_h_def */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index 4c65963870a4..f7dfcedf7d45 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -49,33 +49,32 @@ static char *_host_h_sccs_ = "@(#)host.h 1.2";
** Host data structure. This is used for the software equiv. of
** the host.
*/
-struct Host
-{
- uchar Type; /* RIO_EISA, RIO_MCA, ... */
- uchar Ivec; /* POLLED or ivec number */
- uchar Mode; /* Control stuff */
- uchar Slot; /* Slot */
- volatile caddr_t Caddr; /* KV address of DPRAM */
- volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */
- paddr_t PaddrP; /* Phys. address of DPRAM */
- char Name[MAX_NAME_LEN]; /* The name of the host */
- uint UniqueNum; /* host unique number */
- spinlock_t HostLock; /* Lock structure for MPX */
- /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */
- /*struct lockb HostLock; *//* Lock structure for MPX */
- uint WorkToBeDone; /* set to true each interrupt */
- uint InIntr; /* Being serviced? */
- uint IntSrvDone;/* host's interrupt has been serviced */
- int (*Copy)( caddr_t, caddr_t, int ); /* copy func */
- struct timer_list timer;
- /*
- ** I M P O R T A N T !
- **
- ** The rest of this data structure is cleared to zero after
- ** a RIO_HOST_FOAD command.
- */
-
- ulong Flags; /* Whats going down */
+struct Host {
+ uchar Type; /* RIO_EISA, RIO_MCA, ... */
+ uchar Ivec; /* POLLED or ivec number */
+ uchar Mode; /* Control stuff */
+ uchar Slot; /* Slot */
+ volatile caddr_t Caddr; /* KV address of DPRAM */
+ volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */
+ paddr_t PaddrP; /* Phys. address of DPRAM */
+ char Name[MAX_NAME_LEN]; /* The name of the host */
+ uint UniqueNum; /* host unique number */
+ spinlock_t HostLock; /* Lock structure for MPX */
+ /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */
+ /*struct lockb HostLock; *//* Lock structure for MPX */
+ uint WorkToBeDone; /* set to true each interrupt */
+ uint InIntr; /* Being serviced? */
+ uint IntSrvDone; /* host's interrupt has been serviced */
+ int (*Copy) (caddr_t, caddr_t, int); /* copy func */
+ struct timer_list timer;
+ /*
+ ** I M P O R T A N T !
+ **
+ ** The rest of this data structure is cleared to zero after
+ ** a RIO_HOST_FOAD command.
+ */
+
+ ulong Flags; /* Whats going down */
#define RC_WAITING 0
#define RC_STARTUP 1
#define RC_RUNNING 2
@@ -93,25 +92,25 @@ struct Host
#define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */
#define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */
- struct Top Topology[LINKS_PER_UNIT]; /* one per link */
- struct Map Mapping[MAX_RUP]; /* Mappings for host */
- struct PHB *PhbP; /* Pointer to the PHB array */
- ushort *PhbNumP; /* Ptr to Number of PHB's */
- struct LPB *LinkStrP ; /* Link Structure Array */
- struct RUP *RupP; /* Sixteen real rups here */
- struct PARM_MAP *ParmMapP; /* points to the parmmap */
- uint ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */
- uint NumExtraBooted; /* how many of the above */
- /*
- ** Twenty logical rups.
- ** The first sixteen are the real Rup entries (above), the last four
- ** are the link RUPs.
- */
- struct UnixRup UnixRups[MAX_RUP+LINKS_PER_UNIT];
- int timeout_id; /* For calling 100 ms delays */
- int timeout_sem;/* For calling 100 ms delays */
- long locks; /* long req'd for set_bit --RR */
- char ____end_marker____;
+ struct Top Topology[LINKS_PER_UNIT]; /* one per link */
+ struct Map Mapping[MAX_RUP]; /* Mappings for host */
+ struct PHB *PhbP; /* Pointer to the PHB array */
+ ushort *PhbNumP; /* Ptr to Number of PHB's */
+ struct LPB *LinkStrP; /* Link Structure Array */
+ struct RUP *RupP; /* Sixteen real rups here */
+ struct PARM_MAP *ParmMapP; /* points to the parmmap */
+ uint ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */
+ uint NumExtraBooted; /* how many of the above */
+ /*
+ ** Twenty logical rups.
+ ** The first sixteen are the real Rup entries (above), the last four
+ ** are the link RUPs.
+ */
+ struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT];
+ int timeout_id; /* For calling 100 ms delays */
+ int timeout_sem; /* For calling 100 ms delays */
+ long locks; /* long req'd for set_bit --RR */
+ char ____end_marker____;
};
#define Control CardP->DpControl
#define SetInt CardP->DpSetInt
@@ -129,6 +128,6 @@ struct Host
#define Year CardP->DpYear
#define Week CardP->DpWeek
-#define RIO_DUMBPARM 0x0860 /* what not to expect */
+#define RIO_DUMBPARM 0x0860 /* what not to expect */
#endif
diff --git a/drivers/char/rio/hosthw.h b/drivers/char/rio/hosthw.h
deleted file mode 100644
index f6f31ece6e32..000000000000
--- a/drivers/char/rio/hosthw.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* H O S T H A R D W A R E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2" ;
-#endif
-#endif
-
-#define SET_OTHER_INTERRUPT ( (volatile u_short *) 0x7c80 )
-#define SET_EISA_INTERRUPT ( (volatile u_short *) 0x7ef0 )
-
-#define EISA_HOST 0x30
-#define AT_HOST 0xa0
-#define MCA_HOST 0xb0
-#define PCI_HOST 0xd0
-
-#define PRODUCT_MASK 0xf0
-
-
-/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
index 972250348f4a..bfba5b0c033e 100644
--- a/drivers/char/rio/link.h
+++ b/drivers/char/rio/link.h
@@ -70,27 +70,27 @@
#define DIE_NOW (ushort) 0x0200
/* Boot request stuff */
-#define BOOT_REQUEST ((ushort) 0) /* Request for a boot */
-#define BOOT_ABORT ((ushort) 1) /* Abort a boot */
-#define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets
- and load address */
-#define BOOT_COMPLETED ((ushort) 3) /* Boot completed */
+#define BOOT_REQUEST ((ushort) 0) /* Request for a boot */
+#define BOOT_ABORT ((ushort) 1) /* Abort a boot */
+#define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets
+ and load address */
+#define BOOT_COMPLETED ((ushort) 3) /* Boot completed */
/* States that a link can be in */
-#define LINK_DISCONNECTED ((ushort) 0) /* Disconnected */
-#define LINK_BOOT1 ((ushort) 1) /* Trying to send 1st stage boot */
-#define LINK_BOOT2 ((ushort) 2) /* Trying to send 2nd stage boot */
-#define LINK_BOOT2WAIT ((ushort) 3) /* Waiting for selftest results */
-#define LINK_BOOT3 ((ushort) 4) /* Trying to send 3rd stage boots */
-#define LINK_SYNC ((ushort) 5) /* Syncing */
+#define LINK_DISCONNECTED ((ushort) 0) /* Disconnected */
+#define LINK_BOOT1 ((ushort) 1) /* Trying to send 1st stage boot */
+#define LINK_BOOT2 ((ushort) 2) /* Trying to send 2nd stage boot */
+#define LINK_BOOT2WAIT ((ushort) 3) /* Waiting for selftest results */
+#define LINK_BOOT3 ((ushort) 4) /* Trying to send 3rd stage boots */
+#define LINK_SYNC ((ushort) 5) /* Syncing */
-#define LINK_INTRO ((ushort) 10) /* Introductory packet */
-#define LINK_SUPPLYID ((ushort) 11) /* Trying to supply an ID */
-#define LINK_TOPOLOGY ((ushort) 12) /* Send a topology update */
-#define LINK_REQUESTID ((ushort) 13) /* Waiting for an ID */
-#define LINK_CONNECTED ((ushort) 14) /* Connected */
+#define LINK_INTRO ((ushort) 10) /* Introductory packet */
+#define LINK_SUPPLYID ((ushort) 11) /* Trying to supply an ID */
+#define LINK_TOPOLOGY ((ushort) 12) /* Send a topology update */
+#define LINK_REQUESTID ((ushort) 13) /* Waiting for an ID */
+#define LINK_CONNECTED ((ushort) 14) /* Connected */
-#define LINK_INTERCONNECT ((ushort) 20) /* Subnets interconnected */
+#define LINK_INTERCONNECT ((ushort) 20) /* Subnets interconnected */
#define LINK_SPARE ((ushort) 40)
@@ -103,12 +103,12 @@
** LED stuff
*/
#if defined(RTA)
-#define LED_OFF ((ushort) 0) /* LED off */
-#define LED_RED ((ushort) 1) /* LED Red */
-#define LED_GREEN ((ushort) 2) /* LED Green */
-#define LED_ORANGE ((ushort) 4) /* LED Orange */
-#define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */
-#define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */
+#define LED_OFF ((ushort) 0) /* LED off */
+#define LED_RED ((ushort) 1) /* LED Red */
+#define LED_GREEN ((ushort) 2) /* LED Green */
+#define LED_ORANGE ((ushort) 4) /* LED Orange */
+#define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */
+#define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */
#define LED_SET_COLOUR(colour) (link->led = (colour))
#define LED_OR_COLOUR(colour) (link->led |= (colour))
#define LED_TIMEOUT(time) (link->led_timeout = RioTimePlus(RioTime(),(time)))
@@ -116,72 +116,72 @@
#define LED_SET_COLOUR(colour)
#define LED_OR_COLOUR(colour)
#define LED_TIMEOUT(time)
-#endif /* RTA */
+#endif /* RTA */
struct LPB {
- WORD link_number ; /* Link Number */
- Channel_ptr in_ch ; /* Link In Channel */
- Channel_ptr out_ch ; /* Link Out Channel */
+ WORD link_number; /* Link Number */
+ Channel_ptr in_ch; /* Link In Channel */
+ Channel_ptr out_ch; /* Link Out Channel */
#ifdef RTA
- uchar stat_led ; /* Port open leds */
- uchar led ; /* True, light led! */
+ uchar stat_led; /* Port open leds */
+ uchar led; /* True, light led! */
#endif
- BYTE attached_serial[4]; /* Attached serial number */
- BYTE attached_host_serial[4];
- /* Serial number of Host who
- booted the other end */
- WORD descheduled ; /* Currently Descheduled */
- WORD state; /* Current state */
- WORD send_poll ; /* Send a Poll Packet */
- Process_ptr ltt_p ; /* Process Descriptor */
- Process_ptr lrt_p ; /* Process Descriptor */
- WORD lrt_status ; /* Current lrt status */
- WORD ltt_status ; /* Current ltt status */
- WORD timeout ; /* Timeout value */
- WORD topology; /* Topology bits */
- WORD mon_ltt ;
- WORD mon_lrt ;
- WORD WaitNoBoot ; /* Secs to hold off booting */
- PKT_ptr add_packet_list; /* Add packets to here */
- PKT_ptr remove_packet_list; /* Send packets from here */
+ BYTE attached_serial[4]; /* Attached serial number */
+ BYTE attached_host_serial[4];
+ /* Serial number of Host who
+ booted the other end */
+ WORD descheduled; /* Currently Descheduled */
+ WORD state; /* Current state */
+ WORD send_poll; /* Send a Poll Packet */
+ Process_ptr ltt_p; /* Process Descriptor */
+ Process_ptr lrt_p; /* Process Descriptor */
+ WORD lrt_status; /* Current lrt status */
+ WORD ltt_status; /* Current ltt status */
+ WORD timeout; /* Timeout value */
+ WORD topology; /* Topology bits */
+ WORD mon_ltt;
+ WORD mon_lrt;
+ WORD WaitNoBoot; /* Secs to hold off booting */
+ PKT_ptr add_packet_list; /* Add packets to here */
+ PKT_ptr remove_packet_list; /* Send packets from here */
#ifdef RTA
#ifdef DCIRRUS
-#define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1)
+#define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1)
#else
-#define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1)
+#define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1)
#endif
- PKT_ptr_ptr rd_add ; /* Add a new Packet here */
- Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr rd_add_st_qbb ; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr rd_add_end_qbb ; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr rd_remove ; /* Remove a Packet here */
- Q_BUF_ptr rd_remove_qb ; /* Pointer to the remove Q buf */
- PKT_ptr_ptr rd_remove_st_qbb ; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr rd_remove_end_qbb ; /* Pointer to the end of the Q buf */
- ushort pkts_in_q ; /* Packets in queue */
+ PKT_ptr_ptr rd_add; /* Add a new Packet here */
+ Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */
+ PKT_ptr_ptr rd_add_st_qbb; /* Pointer to start of the Q's buf */
+ PKT_ptr_ptr rd_add_end_qbb; /* Pointer to the end of the Q's buf */
+ PKT_ptr_ptr rd_remove; /* Remove a Packet here */
+ Q_BUF_ptr rd_remove_qb; /* Pointer to the remove Q buf */
+ PKT_ptr_ptr rd_remove_st_qbb; /* Pointer to the start of the Q buf */
+ PKT_ptr_ptr rd_remove_end_qbb; /* Pointer to the end of the Q buf */
+ ushort pkts_in_q; /* Packets in queue */
#endif
- Channel_ptr lrt_fail_chan ; /* Lrt's failure channel */
- Channel_ptr ltt_fail_chan ; /* Ltt's failure channel */
+ Channel_ptr lrt_fail_chan; /* Lrt's failure channel */
+ Channel_ptr ltt_fail_chan; /* Ltt's failure channel */
#if defined (HOST) || defined (INKERNEL)
- /* RUP structure for HOST to driver communications */
- struct RUP rup ;
+ /* RUP structure for HOST to driver communications */
+ struct RUP rup;
#endif
- struct RUP link_rup; /* RUP for the link (POLL,
- topology etc.) */
- WORD attached_link ; /* Number of attached link */
- WORD csum_errors ; /* csum errors */
- WORD num_disconnects ; /* number of disconnects */
- WORD num_sync_rcvd ; /* # sync's received */
- WORD num_sync_rqst ; /* # sync requests */
- WORD num_tx ; /* Num pkts sent */
- WORD num_rx ; /* Num pkts received */
- WORD module_attached; /* Module tpyes of attached */
- WORD led_timeout; /* LED timeout */
- WORD first_port; /* First port to service */
- WORD last_port; /* Last port to service */
- } ;
+ struct RUP link_rup; /* RUP for the link (POLL,
+ topology etc.) */
+ WORD attached_link; /* Number of attached link */
+ WORD csum_errors; /* csum errors */
+ WORD num_disconnects; /* number of disconnects */
+ WORD num_sync_rcvd; /* # sync's received */
+ WORD num_sync_rqst; /* # sync requests */
+ WORD num_tx; /* Num pkts sent */
+ WORD num_rx; /* Num pkts received */
+ WORD module_attached; /* Module tpyes of attached */
+ WORD led_timeout; /* LED timeout */
+ WORD first_port; /* First port to service */
+ WORD last_port; /* Last port to service */
+};
#endif
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
index d53843abe02d..17a14c4a3420 100644
--- a/drivers/char/rio/linux_compat.h
+++ b/drivers/char/rio/linux_compat.h
@@ -41,7 +41,7 @@
#endif
struct ttystatics {
- struct termios tm;
+ struct termios tm;
};
#define bzero(d, n) memset((d), 0, (n))
@@ -97,26 +97,24 @@ the older driver. The older driver includes "brates.h" which shadows
the definitions from Linux, and is incompatible... */
/* RxBaud and TxBaud definitions... */
-#define RIO_B0 0x00 /* RTS / DTR signals dropped */
-#define RIO_B50 0x01 /* 50 baud */
-#define RIO_B75 0x02 /* 75 baud */
-#define RIO_B110 0x03 /* 110 baud */
-#define RIO_B134 0x04 /* 134.5 baud */
-#define RIO_B150 0x05 /* 150 baud */
-#define RIO_B200 0x06 /* 200 baud */
-#define RIO_B300 0x07 /* 300 baud */
-#define RIO_B600 0x08 /* 600 baud */
-#define RIO_B1200 0x09 /* 1200 baud */
-#define RIO_B1800 0x0A /* 1800 baud */
-#define RIO_B2400 0x0B /* 2400 baud */
-#define RIO_B4800 0x0C /* 4800 baud */
-#define RIO_B9600 0x0D /* 9600 baud */
-#define RIO_B19200 0x0E /* 19200 baud */
-#define RIO_B38400 0x0F /* 38400 baud */
-#define RIO_B56000 0x10 /* 56000 baud */
-#define RIO_B57600 0x11 /* 57600 baud */
-#define RIO_B64000 0x12 /* 64000 baud */
-#define RIO_B115200 0x13 /* 115200 baud */
-#define RIO_B2000 0x14 /* 2000 baud */
-
-
+#define RIO_B0 0x00 /* RTS / DTR signals dropped */
+#define RIO_B50 0x01 /* 50 baud */
+#define RIO_B75 0x02 /* 75 baud */
+#define RIO_B110 0x03 /* 110 baud */
+#define RIO_B134 0x04 /* 134.5 baud */
+#define RIO_B150 0x05 /* 150 baud */
+#define RIO_B200 0x06 /* 200 baud */
+#define RIO_B300 0x07 /* 300 baud */
+#define RIO_B600 0x08 /* 600 baud */
+#define RIO_B1200 0x09 /* 1200 baud */
+#define RIO_B1800 0x0A /* 1800 baud */
+#define RIO_B2400 0x0B /* 2400 baud */
+#define RIO_B4800 0x0C /* 4800 baud */
+#define RIO_B9600 0x0D /* 9600 baud */
+#define RIO_B19200 0x0E /* 19200 baud */
+#define RIO_B38400 0x0F /* 38400 baud */
+#define RIO_B56000 0x10 /* 56000 baud */
+#define RIO_B57600 0x11 /* 57600 baud */
+#define RIO_B64000 0x12 /* 64000 baud */
+#define RIO_B115200 0x13 /* 115200 baud */
+#define RIO_B2000 0x14 /* 2000 baud */
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h
index a4f7f1f56255..36aad4c9cb3a 100644
--- a/drivers/char/rio/list.h
+++ b/drivers/char/rio/list.h
@@ -38,7 +38,7 @@
#ifdef SCCS_LABELS
#ifndef lint
-static char *_rio_list_h_sccs = "@(#)list.h 1.9" ;
+static char *_rio_list_h_sccs = "@(#)list.h 1.9";
#endif
#endif
@@ -166,7 +166,7 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9" ;
#endif
-#else /* !IN_KERNEL */
+#else /* !IN_KERNEL */
#define ZERO_PTR NULL
@@ -192,5 +192,5 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9" ;
#define splx(oldspl) if ((oldspl) == 0) spl0()
#endif
-#endif /* ifndef _list.h */
+#endif /* ifndef _list.h */
/*********** end of file ***********/
diff --git a/drivers/char/rio/lrt.h b/drivers/char/rio/lrt.h
deleted file mode 100644
index bbac8fa18fee..000000000000
--- a/drivers/char/rio/lrt.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* L R T
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1" ;
-#endif
-#endif
-
-
-#ifdef DCIRRUS
-#define LRT_STACK (unsigned short) 600
-#else
-#define LRT_STACK (ushort) 200
-#endif
-
-
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h
deleted file mode 100644
index f27dcecf03ca..000000000000
--- a/drivers/char/rio/ltt.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* L T T
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1" ;
-#endif
-#endif
-
-#ifdef DCIRRUS
-#define LTT_STACK (unsigned short) 600
-#else
-#define LTT_STACK (ushort) 200
-#endif
-
-
-
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h
deleted file mode 100644
index fe17d0ee4933..000000000000
--- a/drivers/char/rio/lttwake.h
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-/****************************************************************************
- ******* *******
- ******* L T T W A K E U P H E A D E R
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1" ;
-#endif
-#endif
-
-#define LTT_WAKEUP_STACK 500
-#define LTT_WAKEUP_INTERVAL (int) (500 * MILLISECOND)
-
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h
index 400645a1ff28..97fe287aab2a 100644
--- a/drivers/char/rio/map.h
+++ b/drivers/char/rio/map.h
@@ -46,21 +46,20 @@ static char *_map_h_sccs_ = "@(#)map.h 1.2";
#define TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
#define MAX_NAME_LEN 32
-struct Map
-{
- uint HostUniqueNum; /* Supporting hosts unique number */
- uint RtaUniqueNum; /* Unique number */
+struct Map {
+ uint HostUniqueNum; /* Supporting hosts unique number */
+ uint RtaUniqueNum; /* Unique number */
/*
- ** The next two IDs must be swapped on big-endian architectures
- ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
- ** upgrading for example).
- */
- ushort ID; /* ID used in the subnet */
- ushort ID2; /* ID of 2nd block of 8 for 16 port */
- ulong Flags; /* Booted, ID Given, Disconnected */
- ulong SysPort; /* First tty mapped to this port */
- struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */
- char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */
+ ** The next two IDs must be swapped on big-endian architectures
+ ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
+ ** upgrading for example).
+ */
+ ushort ID; /* ID used in the subnet */
+ ushort ID2; /* ID of 2nd block of 8 for 16 port */
+ ulong Flags; /* Booted, ID Given, Disconnected */
+ ulong SysPort; /* First tty mapped to this port */
+ struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */
+ char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */
};
/*
diff --git a/drivers/char/rio/mca.h b/drivers/char/rio/mca.h
deleted file mode 100644
index 08a327e473af..000000000000
--- a/drivers/char/rio/mca.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-**
-** Module : mca.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:11
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)mca.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_mca_h__
-#define __rio_mca_h__
-
-#ifdef SCCS_LABELS
-static char *_mca_h_sccs_ = "@(#)mca.h 1.2";
-#endif
-
-/*
-** Micro Channel stuff
-*/
-
-#define McaMaxSlots 8
-#define McaSlotSelect 0x96
-#define McaSlotEnable 0x08
-#define McaIdLow 0x100
-#define McaIdHigh 0x101
-#define McaIrqEnable 0x102
-#define McaMemory 0x103
-#define McaRIOId 0x6a5c
-#define McaIrq9 0x00
-#define McaIrq3 0x02
-#define McaIrq4 0x04
-#define McaIrq7 0x06
-#define McaIrq10 0x08
-#define McaIrq11 0x0A
-#define McaIrq12 0x0C
-#define McaIrq15 0x0E
-#define McaIrqMask 0x0E
-#define McaCardEnable 0x01
-#define McaAddress(X) (((X)&0xFF)<<16)
-
-#define McaTpFastLinks 0x40
-#define McaTpSlowLinks 0x00
-#define McaTpBootFromRam 0x01
-#define McaTpBootFromLink 0x00
-#define McaTpBusEnable 0x02
-#define McaTpBusDisable 0x00
-
-#define RIO_MCA_DEFAULT_MODE SLOW_LINKS
-
-#endif /* __rio_mca_h__ */
diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h
deleted file mode 100644
index 9cf6c0bacea4..000000000000
--- a/drivers/char/rio/mesg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-**
-** Module : mesg.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:12
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)mesg.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_mesg_h__
-#define __rio_mesg_h__
-
-#ifdef SCCS_LABELS
-static char *_mesg_h_sccs_ = "@(#)mesg.h 1.2";
-#endif
-
-
-#endif /* __rio_mesg_h__ */
diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h
index 2dc30b9aab37..de7e57180c91 100644
--- a/drivers/char/rio/param.h
+++ b/drivers/char/rio/param.h
@@ -42,20 +42,19 @@ static char *_param_h_sccs_ = "@(#)param.h 1.2";
** the param command block, as used in OPEN and PARAM calls.
*/
-struct phb_param
-{
- BYTE Cmd; /* It is very important that these line up */
- BYTE Cor1; /* with what is expected at the other end. */
- BYTE Cor2; /* to confirm that you've got it right, */
- BYTE Cor4; /* check with cirrus/cirrus.h */
- BYTE Cor5;
- BYTE TxXon; /* Transmit X-On character */
- BYTE TxXoff; /* Transmit X-Off character */
- BYTE RxXon; /* Receive X-On character */
- BYTE RxXoff; /* Receive X-Off character */
- BYTE LNext; /* Literal-next character */
- BYTE TxBaud; /* Transmit baudrate */
- BYTE RxBaud; /* Receive baudrate */
+struct phb_param {
+ BYTE Cmd; /* It is very important that these line up */
+ BYTE Cor1; /* with what is expected at the other end. */
+ BYTE Cor2; /* to confirm that you've got it right, */
+ BYTE Cor4; /* check with cirrus/cirrus.h */
+ BYTE Cor5;
+ BYTE TxXon; /* Transmit X-On character */
+ BYTE TxXoff; /* Transmit X-Off character */
+ BYTE RxXon; /* Receive X-On character */
+ BYTE RxXoff; /* Receive X-Off character */
+ BYTE LNext; /* Literal-next character */
+ BYTE TxBaud; /* Transmit baudrate */
+ BYTE RxBaud; /* Receive baudrate */
};
#endif
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h
index 46f99dfdac8d..fe4e00567065 100644
--- a/drivers/char/rio/parmmap.h
+++ b/drivers/char/rio/parmmap.h
@@ -44,53 +44,50 @@
#endif
#endif
-typedef struct PARM_MAP PARM_MAP ;
+typedef struct PARM_MAP PARM_MAP;
-struct PARM_MAP
-{
-PHB_ptr phb_ptr ; /* Pointer to the PHB array */
-WORD_ptr phb_num_ptr ; /* Ptr to Number of PHB's */
-FREE_LIST_ptr free_list; /* Free List pointer */
-FREE_LIST_ptr free_list_end; /* Free List End pointer */
-Q_BUF_ptr_ptr q_free_list_ptr ; /* Ptr to Q_BUF variable */
-BYTE_ptr unit_id_ptr ; /* Unit Id */
-LPB_ptr link_str_ptr ; /* Link Structure Array */
-BYTE_ptr bootloader_1 ; /* 1st Stage Boot Loader */
-BYTE_ptr bootloader_2 ; /* 2nd Stage Boot Loader */
-WORD_ptr port_route_map_ptr ; /* Port Route Map */
-ROUTE_STR_ptr route_ptr ; /* Unit Route Map */
-NUMBER_ptr map_present ; /* Route Map present */
-NUMBER pkt_num ; /* Total number of packets */
-NUMBER q_num ; /* Total number of Q packets */
-WORD buffers_per_port ; /* Number of buffers per port */
-WORD heap_size ; /* Initial size of heap */
-WORD heap_left ; /* Current Heap left */
-WORD error ; /* Error code */
-WORD tx_max; /* Max number of tx pkts per phb */
-WORD rx_max; /* Max number of rx pkts per phb */
-WORD rx_limit; /* For high / low watermarks */
-NUMBER links ; /* Links to use */
-NUMBER timer ; /* Interrupts per second */
-RUP_ptr rups ; /* Pointer to the RUPs */
-WORD max_phb ; /* Mostly for debugging */
-WORD living ; /* Just increments!! */
-WORD init_done ; /* Initialisation over */
-WORD booting_link ;
-WORD idle_count ; /* Idle time counter */
-WORD busy_count ; /* Busy counter */
-WORD idle_control ; /* Control Idle Process */
+struct PARM_MAP {
+ PHB_ptr phb_ptr; /* Pointer to the PHB array */
+ WORD_ptr phb_num_ptr; /* Ptr to Number of PHB's */
+ FREE_LIST_ptr free_list; /* Free List pointer */
+ FREE_LIST_ptr free_list_end; /* Free List End pointer */
+ Q_BUF_ptr_ptr q_free_list_ptr; /* Ptr to Q_BUF variable */
+ BYTE_ptr unit_id_ptr; /* Unit Id */
+ LPB_ptr link_str_ptr; /* Link Structure Array */
+ BYTE_ptr bootloader_1; /* 1st Stage Boot Loader */
+ BYTE_ptr bootloader_2; /* 2nd Stage Boot Loader */
+ WORD_ptr port_route_map_ptr; /* Port Route Map */
+ ROUTE_STR_ptr route_ptr; /* Unit Route Map */
+ NUMBER_ptr map_present; /* Route Map present */
+ NUMBER pkt_num; /* Total number of packets */
+ NUMBER q_num; /* Total number of Q packets */
+ WORD buffers_per_port; /* Number of buffers per port */
+ WORD heap_size; /* Initial size of heap */
+ WORD heap_left; /* Current Heap left */
+ WORD error; /* Error code */
+ WORD tx_max; /* Max number of tx pkts per phb */
+ WORD rx_max; /* Max number of rx pkts per phb */
+ WORD rx_limit; /* For high / low watermarks */
+ NUMBER links; /* Links to use */
+ NUMBER timer; /* Interrupts per second */
+ RUP_ptr rups; /* Pointer to the RUPs */
+ WORD max_phb; /* Mostly for debugging */
+ WORD living; /* Just increments!! */
+ WORD init_done; /* Initialisation over */
+ WORD booting_link;
+ WORD idle_count; /* Idle time counter */
+ WORD busy_count; /* Busy counter */
+ WORD idle_control; /* Control Idle Process */
#if defined(HOST) || defined(INKERNEL)
-WORD tx_intr; /* TX interrupt pending */
-WORD rx_intr; /* RX interrupt pending */
-WORD rup_intr; /* RUP interrupt pending */
+ WORD tx_intr; /* TX interrupt pending */
+ WORD rx_intr; /* RX interrupt pending */
+ WORD rup_intr; /* RUP interrupt pending */
#endif
#if defined(RTA)
-WORD dying_count; /* Count of processes dead */
+ WORD dying_count; /* Count of processes dead */
#endif
-} ;
+};
#endif
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/pci.h b/drivers/char/rio/pci.h
index dc635bd25194..1eba9118079b 100644
--- a/drivers/char/rio/pci.h
+++ b/drivers/char/rio/pci.h
@@ -73,4 +73,4 @@ static char *_pci_h_sccs_ = "@(#)pci.h 1.2";
#define RIO_PCI_DEFAULT_MODE 0x05
-#endif /* __rio_pci_h__ */
+#endif /* __rio_pci_h__ */
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h
index e1483a0e30bd..3baebf8513af 100644
--- a/drivers/char/rio/phb.h
+++ b/drivers/char/rio/phb.h
@@ -58,37 +58,37 @@
/*************************************************
* Handshake asserted. Deasserted by the LTT(s)
************************************************/
-#define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */
+#define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */
-#define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */
+#define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */
#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
- /* Reset by ltt */
+ /* Reset by ltt */
/*************************************************
* Maximum number of PHB's
************************************************/
#if defined (HOST) || defined (INKERNEL)
-#define MAX_PHB ((ushort) 128) /* range 0-127 */
+#define MAX_PHB ((ushort) 128) /* range 0-127 */
#else
-#define MAX_PHB ((ushort) 8) /* range 0-7 */
+#define MAX_PHB ((ushort) 8) /* range 0-7 */
#endif
/*************************************************
* Defines for the mode fields
************************************************/
-#define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */
-#define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */
-#define TX_TAB3 0x0004 /* TAB3 mode */
-#define TX_OCRNL 0x0008 /* OCRNL mode */
-#define TX_ONLCR 0x0010 /* ONLCR mode */
-#define TX_SENDSPACES 0x0020 /* Send n spaces command needs
- completing */
-#define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */
-#define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */
-#define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
- port */
+#define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */
+#define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */
+#define TX_TAB3 0x0004 /* TAB3 mode */
+#define TX_OCRNL 0x0008 /* OCRNL mode */
+#define TX_ONLCR 0x0010 /* ONLCR mode */
+#define TX_SENDSPACES 0x0020 /* Send n spaces command needs
+ completing */
+#define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */
+#define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */
+#define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
+ port */
#define TX_HANGOVER (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
#define TX_DTRFLOW 0x0200 /* DTR tx flow control */
#define TX_DTRFLOWED 0x0400 /* DTR is low - don't allow more data
@@ -96,34 +96,34 @@
#define TX_DATAINFIFO 0x0800 /* There is data in the FIFO */
#define TX_BUSY 0x1000 /* Data in FIFO, shift or holding regs */
-#define RX_SPARE 0x0001 /* SPARE */
-#define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */
-#define RX_ICRNL 0x0008 /* ICRNL mode */
-#define RX_INLCR 0x0010 /* INLCR mode */
-#define RX_IGNCR 0x0020 /* IGNCR mode */
-#define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */
-#define RX_IXOFF 0x0080 /* IXOFF enabled */
-#define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */
-#define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */
-#define RX_BUFFERED 0x0400 /* Try and pass on complete packets */
+#define RX_SPARE 0x0001 /* SPARE */
+#define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */
+#define RX_ICRNL 0x0008 /* ICRNL mode */
+#define RX_INLCR 0x0010 /* INLCR mode */
+#define RX_IGNCR 0x0020 /* IGNCR mode */
+#define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */
+#define RX_IXOFF 0x0080 /* IXOFF enabled */
+#define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */
+#define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */
+#define RX_BUFFERED 0x0400 /* Try and pass on complete packets */
-#define PORT_ISOPEN 0x0001 /* Port open? */
-#define PORT_HUPCL 0x0002 /* Hangup on close? */
-#define PORT_MOPENPEND 0x0004 /* Modem open pending */
-#define PORT_ISPARALLEL 0x0008 /* Parallel port */
-#define PORT_BREAK 0x0010 /* Port on break */
-#define PORT_STATUSPEND 0x0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x0040 /* Break packet pending */
-#define PORT_MODEMPEND 0x0080 /* Modem status packet pending */
-#define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
- port */
-#define PORT_FULLMODEM 0x0200 /* Full modem signals */
-#define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */
-#define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */
+#define PORT_ISOPEN 0x0001 /* Port open? */
+#define PORT_HUPCL 0x0002 /* Hangup on close? */
+#define PORT_MOPENPEND 0x0004 /* Modem open pending */
+#define PORT_ISPARALLEL 0x0008 /* Parallel port */
+#define PORT_BREAK 0x0010 /* Port on break */
+#define PORT_STATUSPEND 0x0020 /* Status packet pending */
+#define PORT_BREAKPEND 0x0040 /* Break packet pending */
+#define PORT_MODEMPEND 0x0080 /* Modem status packet pending */
+#define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
+ port */
+#define PORT_FULLMODEM 0x0200 /* Full modem signals */
+#define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */
+#define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */
-#define PORT_MODEMBITS 0x0600 /* Mask for modem fields */
+#define PORT_MODEMBITS 0x0600 /* Mask for modem fields */
-#define PORT_WCLOSE 0x0800 /* Waiting for close */
+#define PORT_WCLOSE 0x0800 /* Waiting for close */
#define PORT_HANDSHAKEFIX 0x1000 /* Port has H/W flow control fix */
#define PORT_WASPCLOSED 0x2000 /* Port closed with PCLOSE */
#define DUMPMODE 0x4000 /* Dump RTA mem */
@@ -155,139 +155,128 @@
#define rx_end u4.s1.rx_end_ptr_ptr
#define rx_remove u4.s1.rx_remove_ptr_ptr
#endif
-typedef struct PHB PHB ;
+typedef struct PHB PHB;
struct PHB {
#ifdef RTA
- ushort port;
+ ushort port;
#endif
#ifdef INKERNEL
- WORD source;
+ WORD source;
#else
- union
- {
- ushort source; /* Complete source */
- struct
- {
- unsigned char unit; /* Source unit */
- unsigned char port; /* Source port */
- } s2;
- } u2;
+ union {
+ ushort source; /* Complete source */
+ struct {
+ unsigned char unit; /* Source unit */
+ unsigned char port; /* Source port */
+ } s2;
+ } u2;
#endif
- WORD handshake ;
- WORD status ;
- NUMBER timeout ; /* Maximum of 1.9 seconds */
- WORD link ; /* Send down this link */
+ WORD handshake;
+ WORD status;
+ NUMBER timeout; /* Maximum of 1.9 seconds */
+ WORD link; /* Send down this link */
#ifdef INKERNEL
- WORD destination;
+ WORD destination;
#else
- union
- {
- ushort destination; /* Complete destination */
- struct
- {
- unsigned char unit; /* Destination unit */
- unsigned char port; /* Destination port */
- } s1;
- } u1;
+ union {
+ ushort destination; /* Complete destination */
+ struct {
+ unsigned char unit; /* Destination unit */
+ unsigned char port; /* Destination port */
+ } s1;
+ } u1;
#endif
#ifdef RTA
- ushort tx_pkts_added;
- ushort tx_pkts_removed;
- Q_BUF_ptr tx_q_start ; /* Start of the Q list chain */
- short num_tx_q_bufs ; /* Number of Q buffers in the chain */
- PKT_ptr_ptr tx_add ; /* Add a new Packet here */
- Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr tx_add_st_qbb ; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr tx_add_end_qbb ; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr tx_remove ; /* Remove a Packet here */
- Q_BUF_ptr tx_remove_qb ; /* Pointer to the remove Q buf */
- PKT_ptr_ptr tx_remove_st_qbb ; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr tx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+ ushort tx_pkts_added;
+ ushort tx_pkts_removed;
+ Q_BUF_ptr tx_q_start; /* Start of the Q list chain */
+ short num_tx_q_bufs; /* Number of Q buffers in the chain */
+ PKT_ptr_ptr tx_add; /* Add a new Packet here */
+ Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */
+ PKT_ptr_ptr tx_add_st_qbb; /* Pointer to start of the Q's buf */
+ PKT_ptr_ptr tx_add_end_qbb; /* Pointer to the end of the Q's buf */
+ PKT_ptr_ptr tx_remove; /* Remove a Packet here */
+ Q_BUF_ptr tx_remove_qb; /* Pointer to the remove Q buf */
+ PKT_ptr_ptr tx_remove_st_qbb; /* Pointer to the start of the Q buf */
+ PKT_ptr_ptr tx_remove_end_qbb; /* Pointer to the end of the Q buf */
#endif
#ifdef INKERNEL
- PKT_ptr_ptr tx_start ;
- PKT_ptr_ptr tx_end ;
- PKT_ptr_ptr tx_add ;
- PKT_ptr_ptr tx_remove ;
+ PKT_ptr_ptr tx_start;
+ PKT_ptr_ptr tx_end;
+ PKT_ptr_ptr tx_add;
+ PKT_ptr_ptr tx_remove;
#endif
#ifdef HOST
- union
- {
- struct
- {
- PKT_ptr_ptr tx_start_ptr_ptr;
- PKT_ptr_ptr tx_end_ptr_ptr;
- PKT_ptr_ptr tx_add_ptr_ptr;
- PKT_ptr_ptr tx_remove_ptr_ptr;
- } s1;
- struct
- {
- ushort * tx_start_ptr;
- ushort * tx_end_ptr;
- ushort * tx_add_ptr;
- ushort * tx_remove_ptr;
- } s2;
- } u3;
+ union {
+ struct {
+ PKT_ptr_ptr tx_start_ptr_ptr;
+ PKT_ptr_ptr tx_end_ptr_ptr;
+ PKT_ptr_ptr tx_add_ptr_ptr;
+ PKT_ptr_ptr tx_remove_ptr_ptr;
+ } s1;
+ struct {
+ ushort *tx_start_ptr;
+ ushort *tx_end_ptr;
+ ushort *tx_add_ptr;
+ ushort *tx_remove_ptr;
+ } s2;
+ } u3;
#endif
#ifdef RTA
- ushort rx_pkts_added;
- ushort rx_pkts_removed;
- Q_BUF_ptr rx_q_start ; /* Start of the Q list chain */
- short num_rx_q_bufs ; /* Number of Q buffers in the chain */
- PKT_ptr_ptr rx_add ; /* Add a new Packet here */
- Q_BUF_ptr rx_add_qb ; /* Pointer to the add Q buf */
- PKT_ptr_ptr rx_add_st_qbb ; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr rx_add_end_qbb ; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr rx_remove ; /* Remove a Packet here */
- Q_BUF_ptr rx_remove_qb ; /* Pointer to the remove Q buf */
- PKT_ptr_ptr rx_remove_st_qbb ; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr rx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+ ushort rx_pkts_added;
+ ushort rx_pkts_removed;
+ Q_BUF_ptr rx_q_start; /* Start of the Q list chain */
+ short num_rx_q_bufs; /* Number of Q buffers in the chain */
+ PKT_ptr_ptr rx_add; /* Add a new Packet here */
+ Q_BUF_ptr rx_add_qb; /* Pointer to the add Q buf */
+ PKT_ptr_ptr rx_add_st_qbb; /* Pointer to start of the Q's buf */
+ PKT_ptr_ptr rx_add_end_qbb; /* Pointer to the end of the Q's buf */
+ PKT_ptr_ptr rx_remove; /* Remove a Packet here */
+ Q_BUF_ptr rx_remove_qb; /* Pointer to the remove Q buf */
+ PKT_ptr_ptr rx_remove_st_qbb; /* Pointer to the start of the Q buf */
+ PKT_ptr_ptr rx_remove_end_qbb; /* Pointer to the end of the Q buf */
#endif
#ifdef INKERNEL
- PKT_ptr_ptr rx_start ;
- PKT_ptr_ptr rx_end ;
- PKT_ptr_ptr rx_add ;
- PKT_ptr_ptr rx_remove ;
+ PKT_ptr_ptr rx_start;
+ PKT_ptr_ptr rx_end;
+ PKT_ptr_ptr rx_add;
+ PKT_ptr_ptr rx_remove;
#endif
#ifdef HOST
- union
- {
- struct
- {
- PKT_ptr_ptr rx_start_ptr_ptr;
- PKT_ptr_ptr rx_end_ptr_ptr;
- PKT_ptr_ptr rx_add_ptr_ptr;
- PKT_ptr_ptr rx_remove_ptr_ptr;
- } s1;
- struct
- {
- ushort * rx_start_ptr;
- ushort * rx_end_ptr;
- ushort * rx_add_ptr;
- ushort * rx_remove_ptr;
- } s2;
- } u4;
+ union {
+ struct {
+ PKT_ptr_ptr rx_start_ptr_ptr;
+ PKT_ptr_ptr rx_end_ptr_ptr;
+ PKT_ptr_ptr rx_add_ptr_ptr;
+ PKT_ptr_ptr rx_remove_ptr_ptr;
+ } s1;
+ struct {
+ ushort *rx_start_ptr;
+ ushort *rx_end_ptr;
+ ushort *rx_add_ptr;
+ ushort *rx_remove_ptr;
+ } s2;
+ } u4;
#endif
-#ifdef RTA /* some fields for the remotes */
- ushort flush_count; /* Count of write flushes */
- ushort txmode; /* Modes for tx */
- ushort rxmode; /* Modes for rx */
- ushort portmode; /* Generic modes */
- ushort column; /* TAB3 column count */
- ushort tx_subscript; /* (TX) Subscript into data field */
- ushort rx_subscript; /* (RX) Subscript into data field */
- PKT_ptr rx_incomplete; /* Hold an incomplete packet here */
- ushort modem_bits; /* Modem bits to mask */
- ushort lastModem; /* Modem control lines. */
- ushort addr; /* Address for sub commands */
- ushort MonitorTstate; /* TRUE if monitoring tstop */
+#ifdef RTA /* some fields for the remotes */
+ ushort flush_count; /* Count of write flushes */
+ ushort txmode; /* Modes for tx */
+ ushort rxmode; /* Modes for rx */
+ ushort portmode; /* Generic modes */
+ ushort column; /* TAB3 column count */
+ ushort tx_subscript; /* (TX) Subscript into data field */
+ ushort rx_subscript; /* (RX) Subscript into data field */
+ PKT_ptr rx_incomplete; /* Hold an incomplete packet here */
+ ushort modem_bits; /* Modem bits to mask */
+ ushort lastModem; /* Modem control lines. */
+ ushort addr; /* Address for sub commands */
+ ushort MonitorTstate; /* TRUE if monitoring tstop */
#endif
- } ;
+};
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h
index 66bb2ff0f694..882fd429ac2e 100644
--- a/drivers/char/rio/pkt.h
+++ b/drivers/char/rio/pkt.h
@@ -69,52 +69,44 @@
#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
#define CONTROL_DATA_WNDW (DATA_WNDW << 8)
-struct PKT {
+struct PKT {
#ifdef INKERNEL
- BYTE dest_unit ; /* Destination Unit Id */
- BYTE dest_port ; /* Destination POrt */
- BYTE src_unit ; /* Source Unit Id */
- BYTE src_port ; /* Source POrt */
+ BYTE dest_unit; /* Destination Unit Id */
+ BYTE dest_port; /* Destination POrt */
+ BYTE src_unit; /* Source Unit Id */
+ BYTE src_port; /* Source POrt */
#else
- union
- {
- ushort destination; /* Complete destination */
- struct
- {
- unsigned char unit; /* Destination unit */
- unsigned char port; /* Destination port */
- } s1;
- } u1;
- union
- {
- ushort source; /* Complete source */
- struct
- {
- unsigned char unit; /* Source unit */
- unsigned char port; /* Source port */
- } s2;
- } u2;
+ union {
+ ushort destination; /* Complete destination */
+ struct {
+ unsigned char unit; /* Destination unit */
+ unsigned char port; /* Destination port */
+ } s1;
+ } u1;
+ union {
+ ushort source; /* Complete source */
+ struct {
+ unsigned char unit; /* Source unit */
+ unsigned char port; /* Source port */
+ } s2;
+ } u2;
#endif
#ifdef INKERNEL
- BYTE len ;
- BYTE control;
+ BYTE len;
+ BYTE control;
#else
- union
- {
- ushort control;
- struct
- {
- unsigned char len;
- unsigned char control;
- } s3;
- } u3;
+ union {
+ ushort control;
+ struct {
+ unsigned char len;
+ unsigned char control;
+ } s3;
+ } u3;
#endif
- BYTE data[PKT_MAX_DATA_LEN] ;
- /* Actual data :-) */
- WORD csum ; /* C-SUM */
- } ;
+ BYTE data[PKT_MAX_DATA_LEN];
+ /* Actual data :-) */
+ WORD csum; /* C-SUM */
+};
#endif
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/poll.h b/drivers/char/rio/poll.h
deleted file mode 100644
index d9b8e983e175..000000000000
--- a/drivers/char/rio/poll.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* P O L L
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _poll_h
-#define _poll_h
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_poll_h_sccs = "@(#)poll.h 1.2" ;
-#endif
-#endif
-
-
-#ifdef HOST
-#define POLL_STACK 100
-#endif
-#ifdef RTA
-#define POLL_STACK 200
-#endif
-
-#define POLL_PERIOD (int) SECOND
-
-/* The various poll commands */
-#define POLL_POLL 0 /* We are connected and happy.. */
-#define POLL_INTRO 1 /* Introduction packet */
-#define POLL_TOPOLOGY 2 /* Topology update */
-#define POLL_ASSIGN 3 /* ID assign */
-#define POLL_FOAD 4 /* F*** Off And Die */
-#define POLL_LMD 5 /* Let Me Die */
-#define POLL_DYB 6 /* Die You Ba***** */
-
-/* The way data fields are split up for POLL packets */
-#define POLL_HOST_SERIAL 2 /* Host who booted me */
-#define POLL_MY_SERIAL 6 /* My serial number */
-#define POLL_YOUR_ID 1 /* Your ID number */
-#define POLL_TOPOLOGY_FIELDS 2 /* Topology maps */
-
-#endif
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h
index 8506af06aa9f..c99b1e70fdc8 100644
--- a/drivers/char/rio/port.h
+++ b/drivers/char/rio/port.h
@@ -46,96 +46,94 @@ static char *_port_h_sccs_ = "@(#)port.h 1.3";
*/
#ifdef STATS
-struct RIOStats
-{
+struct RIOStats {
/*
- ** interrupt statistics
- */
- uint BreakIntCnt;
- uint ModemOffCnt;
- uint ModemOnCnt;
- uint RxIntCnt;
- uint TxIntCnt;
+ ** interrupt statistics
+ */
+ uint BreakIntCnt;
+ uint ModemOffCnt;
+ uint ModemOnCnt;
+ uint RxIntCnt;
+ uint TxIntCnt;
/*
- ** throughput statistics
- */
- uint RxCharCnt;
- uint RxPktCnt;
- uint RxSaveCnt;
- uint TxCharCnt;
- uint TxPktCnt;
+ ** throughput statistics
+ */
+ uint RxCharCnt;
+ uint RxPktCnt;
+ uint RxSaveCnt;
+ uint TxCharCnt;
+ uint TxPktCnt;
/*
- ** driver entry statistics
- */
- uint CloseCnt;
- uint IoctlCnt;
- uint OpenCnt;
- uint ReadCnt;
- uint WriteCnt;
+ ** driver entry statistics
+ */
+ uint CloseCnt;
+ uint IoctlCnt;
+ uint OpenCnt;
+ uint ReadCnt;
+ uint WriteCnt;
/*
- ** proc statistics
- */
- uint BlockCnt;
- uint OutputCnt;
- uint ResumeCnt;
- uint RflushCnt;
- uint SuspendCnt;
- uint TbreakCnt;
- uint TimeoutCnt;
- uint UnblockCnt;
- uint WflushCnt;
- uint WFBodgeCnt;
+ ** proc statistics
+ */
+ uint BlockCnt;
+ uint OutputCnt;
+ uint ResumeCnt;
+ uint RflushCnt;
+ uint SuspendCnt;
+ uint TbreakCnt;
+ uint TimeoutCnt;
+ uint UnblockCnt;
+ uint WflushCnt;
+ uint WFBodgeCnt;
};
#endif
/*
** Port data structure
*/
-struct Port
-{
- struct gs_port gs;
- int PortNum; /* RIO port no., 0-511 */
- struct Host *HostP;
- volatile caddr_t Caddr;
- ushort HostPort; /* Port number on host card */
- uchar RupNum; /* Number of RUP for port */
- uchar ID2; /* Second ID of RTA for port */
- ulong State; /* FLAGS for open & xopen */
-#define RIO_LOPEN 0x00001 /* Local open */
-#define RIO_MOPEN 0x00002 /* Modem open */
-#define RIO_WOPEN 0x00004 /* Waiting for open */
-#define RIO_CLOSING 0x00008 /* The port is being close */
-#define RIO_XPBUSY 0x00010 /* Transparent printer busy */
-#define RIO_BREAKING 0x00020 /* Break in progress */
-#define RIO_DIRECT 0x00040 /* Doing Direct output */
-#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */
-#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */
-#define RIO_CARR_ON 0x00200 /* Stream has carrier present */
-#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */
-#define RIO_RBLK 0x00800 /* Stream is read-blocked */
-#define RIO_BUSY 0x01000 /* Stream is BUSY for write */
-#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */
-#define RIO_TXSTOP 0x04000 /* Stream output is stopped */
-#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */
-#define RIO_DYNOROD 0x10000 /* Drain failed */
-#define RIO_DELETED 0x20000 /* RTA has been deleted */
-#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */
+struct Port {
+ struct gs_port gs;
+ int PortNum; /* RIO port no., 0-511 */
+ struct Host *HostP;
+ volatile caddr_t Caddr;
+ ushort HostPort; /* Port number on host card */
+ uchar RupNum; /* Number of RUP for port */
+ uchar ID2; /* Second ID of RTA for port */
+ ulong State; /* FLAGS for open & xopen */
+#define RIO_LOPEN 0x00001 /* Local open */
+#define RIO_MOPEN 0x00002 /* Modem open */
+#define RIO_WOPEN 0x00004 /* Waiting for open */
+#define RIO_CLOSING 0x00008 /* The port is being close */
+#define RIO_XPBUSY 0x00010 /* Transparent printer busy */
+#define RIO_BREAKING 0x00020 /* Break in progress */
+#define RIO_DIRECT 0x00040 /* Doing Direct output */
+#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */
+#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */
+#define RIO_CARR_ON 0x00200 /* Stream has carrier present */
+#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */
+#define RIO_RBLK 0x00800 /* Stream is read-blocked */
+#define RIO_BUSY 0x01000 /* Stream is BUSY for write */
+#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */
+#define RIO_TXSTOP 0x04000 /* Stream output is stopped */
+#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */
+#define RIO_DYNOROD 0x10000 /* Drain failed */
+#define RIO_DELETED 0x20000 /* RTA has been deleted */
+#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */
#define RIO_USING_EUC 0x100000 /* Using extended Unix chars */
#define RIO_CAN_COOK 0x200000 /* This line can do cooking */
-#define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */
-#define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */
-#define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */
-#define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */
+#define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */
+#define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */
+#define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */
+#define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */
- ulong Config; /* FLAGS for NOREAD.... */
-#define RIO_NOREAD 0x0001 /* Are not allowed to read port */
-#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */
-#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */
-#define RIO_NOMASK 0x0007 /* All not allowed things */
-#define RIO_IXANY 0x0008 /* Port is allowed ixany */
-#define RIO_MODEM 0x0010 /* Stream is a modem device */
-#define RIO_IXON 0x0020 /* Port is allowed ixon */
-#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */
+ ulong Config; /* FLAGS for NOREAD.... */
+#define RIO_NOREAD 0x0001 /* Are not allowed to read port */
+#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */
+#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */
+#define RIO_NOMASK 0x0007 /* All not allowed things */
+#define RIO_IXANY 0x0008 /* Port is allowed ixany */
+#define RIO_MODEM 0x0010 /* Stream is a modem device */
+#define RIO_IXON 0x0020 /* Port is allowed ixon */
+#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */
#define RIO_MAP_50_TO_50 0x0080 /* Map 50 baud to 50 baud */
#define RIO_MAP_110_TO_110 0x0100 /* Map 110 baud to 110 baud */
@@ -144,92 +142,90 @@ struct Port
** As LynxOS does not appear to support Hardware Flow Control .....
** Define our own flow control flags in 'Config'.
*/
-#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */
-#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */
+#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */
+#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */
- struct PHB *PhbP; /* pointer to PHB for port */
- WORD *TxAdd; /* Add packets here */
- WORD *TxStart; /* Start of add array */
- WORD *TxEnd; /* End of add array */
- WORD *RxRemove; /* Remove packets here */
- WORD *RxStart; /* Start of remove array */
- WORD *RxEnd; /* End of remove array */
- uint RtaUniqueNum; /* Unique number of RTA */
- ushort PortState; /* status of port */
- ushort ModemState; /* status of modem lines */
- ulong ModemLines; /* Modem bits sent to RTA */
- uchar CookMode; /* who expands CR/LF? */
- uchar ParamSem; /* Prevent write during param */
- uchar Mapped; /* if port mapped onto host */
- uchar SecondBlock; /* if port belongs to 2nd block
- of 16 port RTA */
- uchar InUse; /* how many pre-emptive cmds */
- uchar Lock; /* if params locked */
- uchar Store; /* if params stored across closes */
- uchar FirstOpen; /* TRUE if first time port opened */
- uchar FlushCmdBodge; /* if doing a (non)flush */
- uchar MagicFlags; /* require intr processing */
+ struct PHB *PhbP; /* pointer to PHB for port */
+ WORD *TxAdd; /* Add packets here */
+ WORD *TxStart; /* Start of add array */
+ WORD *TxEnd; /* End of add array */
+ WORD *RxRemove; /* Remove packets here */
+ WORD *RxStart; /* Start of remove array */
+ WORD *RxEnd; /* End of remove array */
+ uint RtaUniqueNum; /* Unique number of RTA */
+ ushort PortState; /* status of port */
+ ushort ModemState; /* status of modem lines */
+ ulong ModemLines; /* Modem bits sent to RTA */
+ uchar CookMode; /* who expands CR/LF? */
+ uchar ParamSem; /* Prevent write during param */
+ uchar Mapped; /* if port mapped onto host */
+ uchar SecondBlock; /* if port belongs to 2nd block
+ of 16 port RTA */
+ uchar InUse; /* how many pre-emptive cmds */
+ uchar Lock; /* if params locked */
+ uchar Store; /* if params stored across closes */
+ uchar FirstOpen; /* TRUE if first time port opened */
+ uchar FlushCmdBodge; /* if doing a (non)flush */
+ uchar MagicFlags; /* require intr processing */
#define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */
#define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */
#define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */
- uchar WflushFlag; /* 1 How many WFLUSHs active */
+ uchar WflushFlag; /* 1 How many WFLUSHs active */
/*
** Transparent print stuff
*/
- struct Xprint
- {
+ struct Xprint {
#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */
+#define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */
#endif
- uint XpCps;
- char XpOn[MAX_XP_CTRL_LEN];
- char XpOff[MAX_XP_CTRL_LEN];
- ushort XpLen; /* strlen(XpOn)+strlen(XpOff) */
- uchar XpActive;
- uchar XpLastTickOk; /* TRUE if we can process */
+ uint XpCps;
+ char XpOn[MAX_XP_CTRL_LEN];
+ char XpOff[MAX_XP_CTRL_LEN];
+ ushort XpLen; /* strlen(XpOn)+strlen(XpOff) */
+ uchar XpActive;
+ uchar XpLastTickOk; /* TRUE if we can process */
#define XP_OPEN 00001
#define XP_RUNABLE 00002
- struct ttystatics *XttyP;
- } Xprint;
+ struct ttystatics *XttyP;
+ } Xprint;
#ifdef VPIX
- v86_t *StashP;
- uint IntMask;
- struct termss VpixSs;
- uchar ModemStatusReg; /* Modem status register */
+ v86_t *StashP;
+ uint IntMask;
+ struct termss VpixSs;
+ uchar ModemStatusReg; /* Modem status register */
#endif
- uchar RxDataStart;
- uchar Cor2Copy; /* copy of COR2 */
- char *Name; /* points to the Rta's name */
+ uchar RxDataStart;
+ uchar Cor2Copy; /* copy of COR2 */
+ char *Name; /* points to the Rta's name */
#ifdef STATS
- struct RIOStats Stat; /* ports statistics */
+ struct RIOStats Stat; /* ports statistics */
#endif
- char *TxRingBuffer;
- ushort TxBufferIn; /* New data arrives here */
- ushort TxBufferOut; /* Intr removes data here */
- ushort OldTxBufferOut; /* Indicates if draining */
- int TimeoutId; /* Timeout ID */
- uint Debug;
- uchar WaitUntilBooted; /* True if open should block */
- uint statsGather; /* True if gathering stats */
- ulong txchars; /* Chars transmitted */
- ulong rxchars; /* Chars received */
- ulong opens; /* port open count */
- ulong closes; /* port close count */
- ulong ioctls; /* ioctl count */
- uchar LastRxTgl; /* Last state of rx toggle bit */
- spinlock_t portSem; /* Lock using this sem */
- int MonitorTstate; /* Monitoring ? */
- int timeout_id; /* For calling 100 ms delays */
- int timeout_sem;/* For calling 100 ms delays */
- int firstOpen; /* First time open ? */
- char * p; /* save the global struc here .. */
+ char *TxRingBuffer;
+ ushort TxBufferIn; /* New data arrives here */
+ ushort TxBufferOut; /* Intr removes data here */
+ ushort OldTxBufferOut; /* Indicates if draining */
+ int TimeoutId; /* Timeout ID */
+ uint Debug;
+ uchar WaitUntilBooted; /* True if open should block */
+ uint statsGather; /* True if gathering stats */
+ ulong txchars; /* Chars transmitted */
+ ulong rxchars; /* Chars received */
+ ulong opens; /* port open count */
+ ulong closes; /* port close count */
+ ulong ioctls; /* ioctl count */
+ uchar LastRxTgl; /* Last state of rx toggle bit */
+ spinlock_t portSem; /* Lock using this sem */
+ int MonitorTstate; /* Monitoring ? */
+ int timeout_id; /* For calling 100 ms delays */
+ int timeout_sem; /* For calling 100 ms delays */
+ int firstOpen; /* First time open ? */
+ char *p; /* save the global struc here .. */
};
-struct ModuleInfo
-{
- char *Name;
- uint Flags[4]; /* one per port on a module */
+struct ModuleInfo {
+ char *Name;
+ uint Flags[4]; /* one per port on a module */
};
#endif
@@ -238,8 +234,8 @@ struct ModuleInfo
** runs into problems with differing struct sizes between driver and config.
*/
struct PortParams {
- uint Port;
- ulong Config;
- ulong State;
- struct ttystatics *TtyP;
+ uint Port;
+ ulong Config;
+ ulong State;
+ struct ttystatics *TtyP;
};
diff --git a/drivers/char/rio/proto.h b/drivers/char/rio/proto.h
deleted file mode 100644
index ddff0ef84e3a..000000000000
--- a/drivers/char/rio/proto.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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 _prototypes_h
-#define _prototypes_h
-
-
-/*
-** boot.c
-*/
-void init_boot( char *p, short stage);
-
-/*
-** disconct.c
-*/
-void kill_boot ( LPB *link );
-void disconnected( LPB *link );
-short boot_3( LPB *link, PKT *pkt );
-short send_3_pkt( LPB *link, PKT *pkt);
-
-/*
-** error.c
-*/
-void du_error(void);
-
-/*
-** formpkt.c
-*/
-ushort sum_it( PKT *pkt ) ;
-void form_rup_pkt( RUP *form_rup, PKT *pkt );
-void form_poll_pkt ( int type, LPB *link, int node );
-void form_route_pkt ( int type, PKT *pkt, LPB *link );
-
-/*
-** idle.c
-*/
-void idle( Process *idle_p );
-
-/*
-** init.c
-*/
-void general_init(void);
-void mem_halt( int error);
-
-/*
-** linkinit.c
-*/
-void initlink( u_short number, LPB *link);
-void runlink( LPB *link);
-
-/*
-** list.c
-*/
-PKT *get_free_start(void);
-void put_free_start( PKT *pkt);
-
-#ifdef HOST
-int can_remove_transmit ( PKT **pkt, PKT *pointer );
-#endif
-
-#ifdef RTA
-int spl7 ( void );
-int spl0 ( void );
-Q_BUF *get_free_q( void );
-PKT *get_free_end(void);
-int add_end( PKT *pkt, PHB *phb, int type);
-unsigned short free_packets( PHB *phb, int type);
-int can_remove_start( PKT **pkt, PHB *phb, int type);
-int can_add_start( PHB *phb, int type);
-int can_add_end( PHB *phb, int type);
-void put_free_end( PKT *pkt);
-int remove_start( PKT **pkt, PHB *phb, int type);
-#endif
-
-/*
-** Lrt.c
-*/
-void lrt( Process *lrt_p, LPB *link );
-
-#ifdef RTA
-void set_led_red ( LPB *link );
-#endif
-
-/*
-** ltt.c
-*/
-void ltt( Process *ltt_p, LPB *link, PHB *phb_ptr[] );
-void send_poll ( LPB *link );
-void request_id ( LPB *link );
-void send_topology_update ( LPB *link );
-void send_topology ( LPB *link );
-void supply_id ( LPB *link );
-
-#ifdef RTA
-void redirect_queue ( LPB *link, ushort flush );
-int obtain_rup ( int rup_number, PKT **pkt_address, LPB *link );
-#endif
-
-#ifdef TESTING_PERF
-int consume_cpu( void );
-#endif
-
-/*
-** lttwake.c
-*/
-#ifdef HOST
-void ltt_wakeup( Process *ltt_wakeup_p );
-#endif
-
-/*
-** mapgen.c
-*/
-void generate_id_map( short mapping, ROUTE_STR route[] );
-void gen_map( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl );
-void adjust_ttl( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl);
-void init_sys_map(void);
-
-/*
-** mmu.c
-*/
-char *rio_malloc( unsigned int amount);
-char *rio_calloc( unsigned int num, unsigned int size);
-ERROR rio_mmu_init( uint total_mem );
-
-/*
-** partn.c
-*/
-void partition_tx( struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit);
-
-/*
-** poll.c
-*/
-void tx_poll( Process *tx_poll_p);
-
-/*
-** process.c
-*/
-int get_proc_space( Process **pd, int **pws, int wssize);
-
-/*
-** readrom.c
-*/
-void read_serial_number(char *buf);
-
-/*
-** rio.c
-*/
-int main( void );
-
-/*
-** route.c
-*/
-void route_update ( PKT *pkt, LPB *link);
-
-/*
-** rtainit.c
-*/
-#if defined(RTA)
-void rta_init(ushort RtaType);
-#endif /* defined(RTA) */
-
-/*
-** rupboot.c
-*/
-void rup_boot( PKT *pkt, RUP *this_rup, LPB *link);
-
-#ifdef RTA
-void kill_your_neighbour( int link_to_kill );
-#endif
-
-/*
-** rupcmd.c
-*/
-void rup_command( PKT *pkt, struct RUP *this_rup, LPB *link);
-
-/*
-** ruperr.c
-*/
-void rup_error( PKT *pkt, RUP *this_rup, LPB *link );
-void illegal_cmd( PKT *src_pkt );
-
-/*
-** ruppoll.c
-*/
-void rup_poll( PKT *pkt, RUP *this_rup, LPB *link );
-
-/*
-** ruppower.c
-*/
-void rup_power( PKT *pkt, RUP *this_rup, LPB *link );
-
-/*
-** ruprm.c
-*/
-void rup_route_map( PKT *pkt, RUP *this_rup, LPB *link);
-
-/*
-** rupstat.c
-*/
-void rup_status( PKT *pkt, RUP *this_rup, LPB *link);
-
-/*
-** rupsync.c
-*/
-void rup_sync( PKT *pkt);
-
-/*
-** rxpkt.c
-*/
-ERROR rx_pkt( PKT_ptr_ptr pkt_address, LPB *link);
-
-/*
-** sendsts.c
-*/
-void send_status( PKT *requesting_pkt, RUP *this_rup);
-
-/*
-** serial.c
-*/
-void assign_serial ( char *ser_in, char *ser_out);
-int cmp_serial ( char *ser_1, char *ser_2);
-
-/*
-** txpkt.c
-*/
-ERROR tx_pkt( PKT *pkt, LPB *link);
-short send_sync( LPB *link);
-
-#endif /* _prototypes_h */
diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h
index 848111ac9380..69fc4bc34153 100644
--- a/drivers/char/rio/protsts.h
+++ b/drivers/char/rio/protsts.h
@@ -115,5 +115,3 @@
#endif
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h
index 1fce02f8fcfc..acd9e8e5307d 100644
--- a/drivers/char/rio/qbuf.h
+++ b/drivers/char/rio/qbuf.h
@@ -40,7 +40,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1" ;
+static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1";
#endif
#endif
@@ -52,16 +52,15 @@ static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1" ;
#define PKTS_PER_BUFFER (220 / PKT_LENGTH)
#endif
-typedef struct Q_BUF Q_BUF ;
-struct Q_BUF {
- Q_BUF_ptr next ;
- Q_BUF_ptr prev ;
- PKT_ptr buf[PKTS_PER_BUFFER] ;
- } ;
+typedef struct Q_BUF Q_BUF;
+struct Q_BUF {
+ Q_BUF_ptr next;
+ Q_BUF_ptr prev;
+ PKT_ptr buf[PKTS_PER_BUFFER];
+};
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h
index 13a9931958b1..7f45e1ab5332 100644
--- a/drivers/char/rio/rio.h
+++ b/drivers/char/rio/rio.h
@@ -72,8 +72,8 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3";
#define RIO_HOSTS 4 /* number of hosts that can be found */
#define PORTS_PER_HOST 128 /* number of ports per host */
#define LINKS_PER_UNIT 4 /* number of links from a host */
-#define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */
-#define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */
+#define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */
+#define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */
#define PORTS_PER_RTA (PORTS_PER_HOST/RTAS_PER_HOST) /* ports on a rta */
#define PORTS_PER_MODULE 4 /* number of ports on a plug-in module */
/* number of modules on an RTA */
@@ -216,10 +216,9 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3";
#define RIO_PRI (PZERO+10)
#define RIO_CLOSE_PRI PZERO-1 /* uninterruptible sleeps for close */
-typedef struct DbInf
-{
- uint Flag;
- char Name[8];
+typedef struct DbInf {
+ uint Flag;
+ char Name[8];
} DbInf;
#ifndef TRUE
@@ -251,7 +250,7 @@ typedef struct DbInf
*((uint *)PK) = PP->PacketInfo; \
}
-#define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */
+#define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */
/* prevent a really stupid race condition. */
#define NOT_INITIALISED 0
@@ -291,4 +290,4 @@ typedef struct DbInf
#define DIST_LINESW_OUTPUT 0x40
#define DIST_LINESW_MDMINT 0x80
-#endif /* __rio_h__ */
+#endif /* __rio_h__ */
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d7d484024e2b..c9af283a811d 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -33,7 +33,7 @@
* */
#include <linux/module.h>
-#include <linux/config.h>
+#include <linux/config.h>
#include <linux/kdev_t.h>
#include <asm/io.h>
#include <linux/kernel.h>
@@ -56,10 +56,6 @@
#include <linux/generic_serial.h>
#include <asm/uaccess.h>
-#if BITS_PER_LONG != 32
-# error FIXME: this driver only works on 32-bit platforms
-#endif
-
#include "linux_compat.h"
#include "typdef.h"
#include "pkt.h"
@@ -116,7 +112,7 @@ more than 512 ports.... */
#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
#endif
-#ifndef RIO_WINDOW_LEN
+#ifndef RIO_WINDOW_LEN
#define RIO_WINDOW_LEN 0x10000
#endif
@@ -136,42 +132,49 @@ more than 512 ports.... */
*/
#define IRQ_RATE_LIMIT 200
-#if 0
-/* Not implemented */
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define RIO_REPORT_FIFO
-#define RIO_REPORT_OVERRUN
-#endif
-
/* These constants are derived from SCO Source */
static struct Conf
-RIOConf =
-{
- /* locator */ "RIO Config here",
- /* startuptime */ HZ*2, /* how long to wait for card to run */
- /* slowcook */ 0, /* TRUE -> always use line disc. */
- /* intrpolltime */ 1, /* The frequency of OUR polls */
- /* breakinterval */ 25, /* x10 mS XXX: units seem to be 1ms not 10! -- REW*/
- /* timer */ 10, /* mS */
- /* RtaLoadBase */ 0x7000,
- /* HostLoadBase */ 0x7C00,
- /* XpHz */ 5, /* number of Xprint hits per second */
- /* XpCps */ 120, /* Xprint characters per second */
- /* XpOn */ "\033d#", /* start Xprint for a wyse 60 */
- /* XpOff */ "\024", /* end Xprint for a wyse 60 */
- /* MaxXpCps */ 2000, /* highest Xprint speed */
- /* MinXpCps */ 10, /* slowest Xprint speed */
- /* SpinCmds */ 1, /* non-zero for mega fast boots */
- /* First Addr */ 0x0A0000, /* First address to look at */
- /* Last Addr */ 0xFF0000, /* Last address looked at */
- /* BufferSize */ 1024, /* Bytes per port of buffering */
- /* LowWater */ 256, /* how much data left before wakeup */
- /* LineLength */ 80, /* how wide is the console? */
- /* CmdTimeout */ HZ, /* how long a close command may take */
+ RIOConf = {
+ /* locator */ "RIO Config here",
+ /* startuptime */ HZ * 2,
+ /* how long to wait for card to run */
+ /* slowcook */ 0,
+ /* TRUE -> always use line disc. */
+ /* intrpolltime */ 1,
+ /* The frequency of OUR polls */
+ /* breakinterval */ 25,
+ /* x10 mS XXX: units seem to be 1ms not 10! -- REW */
+ /* timer */ 10,
+ /* mS */
+ /* RtaLoadBase */ 0x7000,
+ /* HostLoadBase */ 0x7C00,
+ /* XpHz */ 5,
+ /* number of Xprint hits per second */
+ /* XpCps */ 120,
+ /* Xprint characters per second */
+ /* XpOn */ "\033d#",
+ /* start Xprint for a wyse 60 */
+ /* XpOff */ "\024",
+ /* end Xprint for a wyse 60 */
+ /* MaxXpCps */ 2000,
+ /* highest Xprint speed */
+ /* MinXpCps */ 10,
+ /* slowest Xprint speed */
+ /* SpinCmds */ 1,
+ /* non-zero for mega fast boots */
+ /* First Addr */ 0x0A0000,
+ /* First address to look at */
+ /* Last Addr */ 0xFF0000,
+ /* Last address looked at */
+ /* BufferSize */ 1024,
+ /* Bytes per port of buffering */
+ /* LowWater */ 256,
+ /* how much data left before wakeup */
+ /* LineLength */ 80,
+ /* how wide is the console? */
+ /* CmdTimeout */ HZ,
+ /* how long a close command may take */
};
@@ -179,21 +182,20 @@ RIOConf =
/* Function prototypes */
-static void rio_disable_tx_interrupts (void * ptr);
-static void rio_enable_tx_interrupts (void * ptr);
-static void rio_disable_rx_interrupts (void * ptr);
-static void rio_enable_rx_interrupts (void * ptr);
-static int rio_get_CD (void * ptr);
-static void rio_shutdown_port (void * ptr);
-static int rio_set_real_termios (void *ptr);
-static void rio_hungup (void *ptr);
-static void rio_close (void *ptr);
-static int rio_chars_in_buffer (void * ptr);
-static int rio_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+static void rio_disable_tx_interrupts(void *ptr);
+static void rio_enable_tx_interrupts(void *ptr);
+static void rio_disable_rx_interrupts(void *ptr);
+static void rio_enable_rx_interrupts(void *ptr);
+static int rio_get_CD(void *ptr);
+static void rio_shutdown_port(void *ptr);
+static int rio_set_real_termios(void *ptr);
+static void rio_hungup(void *ptr);
+static void rio_close(void *ptr);
+static int rio_chars_in_buffer(void *ptr);
+static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static int rio_init_drivers(void);
-static void my_hd (void *addr, int len);
+static void my_hd(void *addr, int len);
static struct tty_driver *rio_driver, *rio_driver2;
@@ -213,9 +215,9 @@ static int rio_poll = 1;
/* These are the only open spaces in my computer. Yours may have more
or less.... */
-static int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000};
+static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 };
-#define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int))
+#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
/* Set the mask to all-ones. This alas, only supports 32 interrupts.
@@ -231,17 +233,17 @@ module_param(rio_debug, int, 0644);
module_param(rio_irqmask, long, 0);
static struct real_driver rio_real_driver = {
- rio_disable_tx_interrupts,
- rio_enable_tx_interrupts,
- rio_disable_rx_interrupts,
- rio_enable_rx_interrupts,
- rio_get_CD,
- rio_shutdown_port,
- rio_set_real_termios,
- rio_chars_in_buffer,
- rio_close,
- rio_hungup,
- NULL
+ rio_disable_tx_interrupts,
+ rio_enable_tx_interrupts,
+ rio_disable_rx_interrupts,
+ rio_enable_rx_interrupts,
+ rio_get_CD,
+ rio_shutdown_port,
+ rio_set_real_termios,
+ rio_chars_in_buffer,
+ rio_close,
+ rio_hungup,
+ NULL
};
/*
@@ -250,8 +252,8 @@ static struct real_driver rio_real_driver = {
*/
static struct file_operations rio_fw_fops = {
- .owner = THIS_MODULE,
- .ioctl = rio_fw_ioctl,
+ .owner = THIS_MODULE,
+ .ioctl = rio_fw_ioctl,
};
static struct miscdevice rio_fw_device = {
@@ -266,25 +268,22 @@ static struct miscdevice rio_fw_device = {
/* This doesn't work. Who's paranoid around here? Not me! */
-static inline int rio_paranoia_check(struct rio_port const * port,
- char *name, const char *routine)
+static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine)
{
- static const char *badmagic =
- KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
- static const char *badinfo =
- KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
-
- if (!port) {
- printk (badinfo, name, routine);
- return 1;
- }
- if (port->magic != RIO_MAGIC) {
- printk (badmagic, name, routine);
- return 1;
- }
-
- return 0;
+ static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
+ static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
+
+ if (!port) {
+ printk(badinfo, name, routine);
+ return 1;
+ }
+ if (port->magic != RIO_MAGIC) {
+ printk(badmagic, name, routine);
+ return 1;
+ }
+
+ return 0;
}
#else
#define rio_paranoia_check(a,b,c) 0
@@ -292,53 +291,53 @@ static inline int rio_paranoia_check(struct rio_port const * port,
#ifdef DEBUG
-static void my_hd (void *ad, int len)
+static void my_hd(void *ad, int len)
{
- int i, j, ch;
- unsigned char *addr = ad;
-
- for (i=0;i<len;i+=16) {
- rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);
- for (j=0;j<16;j++) {
- rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");
- }
- for (j=0;j<16;j++) {
- ch = addr[j+i];
- rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
- }
- rio_dprintk (RIO_DEBUG_PARAM, "\n");
- }
+ int i, j, ch;
+ unsigned char *addr = ad;
+
+ for (i = 0; i < len; i += 16) {
+ rio_dprintk(RIO_DEBUG_PARAM, "%08x ", (int) addr + i);
+ for (j = 0; j < 16; j++) {
+ rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : "");
+ }
+ for (j = 0; j < 16; j++) {
+ ch = addr[j + i];
+ rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch));
+ }
+ rio_dprintk(RIO_DEBUG_PARAM, "\n");
+ }
}
#else
#define my_hd(ad,len) do{/* nothing*/ } while (0)
#endif
-/* Delay a number of jiffies, allowing a signal to interrupt */
-int RIODelay (struct Port *PortP, int njiffies)
+/* Delay a number of jiffies, allowing a signal to interrupt */
+int RIODelay(struct Port *PortP, int njiffies)
{
- func_enter ();
+ func_enter();
- rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
- msleep_interruptible(jiffies_to_msecs(njiffies));
- func_exit();
+ rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
+ msleep_interruptible(jiffies_to_msecs(njiffies));
+ func_exit();
- if (signal_pending(current))
- return RIO_FAIL;
- else
- return !RIO_FAIL;
+ if (signal_pending(current))
+ return RIO_FAIL;
+ else
+ return !RIO_FAIL;
}
-/* Delay a number of jiffies, disallowing a signal to interrupt */
-int RIODelay_ni (struct Port *PortP, int njiffies)
+/* Delay a number of jiffies, disallowing a signal to interrupt */
+int RIODelay_ni(struct Port *PortP, int njiffies)
{
- func_enter ();
+ func_enter();
- rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
- msleep(jiffies_to_msecs(njiffies));
- func_exit();
- return !RIO_FAIL;
+ rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
+ msleep(jiffies_to_msecs(njiffies));
+ func_exit();
+ return !RIO_FAIL;
}
@@ -354,126 +353,121 @@ int rio_ismodem(struct tty_struct *tty)
}
-static int rio_set_real_termios (void *ptr)
+static int rio_set_real_termios(void *ptr)
{
- int rv, modem;
- struct tty_struct *tty;
- func_enter();
+ int rv, modem;
+ struct tty_struct *tty;
+ func_enter();
- tty = ((struct Port *)ptr)->gs.tty;
+ tty = ((struct Port *) ptr)->gs.tty;
- modem = rio_ismodem(tty);
+ modem = rio_ismodem(tty);
- rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1);
+ rv = RIOParam((struct Port *) ptr, CONFIG, modem, 1);
- func_exit ();
+ func_exit();
- return rv;
+ return rv;
}
-static void rio_reset_interrupt (struct Host *HostP)
+static void rio_reset_interrupt(struct Host *HostP)
{
- func_enter();
+ func_enter();
- switch( HostP->Type ) {
- case RIO_AT:
- case RIO_MCA:
- case RIO_PCI:
- WBYTE(HostP->ResetInt , 0xff);
- }
+ switch (HostP->Type) {
+ case RIO_AT:
+ case RIO_MCA:
+ case RIO_PCI:
+ WBYTE(HostP->ResetInt, 0xff);
+ }
- func_exit();
+ func_exit();
}
-static irqreturn_t rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t rio_interrupt(int irq, void *ptr, struct pt_regs *regs)
{
- struct Host *HostP;
- func_enter ();
+ struct Host *HostP;
+ func_enter();
- HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */
- rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n",
- irq, HostP->Ivec);
+ HostP = (struct Host *) ptr; /* &p->RIOHosts[(long)ptr]; */
+ rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
- /* AAargh! The order in which to do these things is essential and
- not trivial.
-
- - Rate limit goes before "recursive". Otherwise a series of
- recursive calls will hang the machine in the interrupt routine.
+ /* AAargh! The order in which to do these things is essential and
+ not trivial.
- - hardware twiddling goes before "recursive". Otherwise when we
- poll the card, and a recursive interrupt happens, we won't
- ack the card, so it might keep on interrupting us. (especially
- level sensitive interrupt systems like PCI).
+ - Rate limit goes before "recursive". Otherwise a series of
+ recursive calls will hang the machine in the interrupt routine.
- - Rate limit goes before hardware twiddling. Otherwise we won't
- catch a card that has gone bonkers.
+ - hardware twiddling goes before "recursive". Otherwise when we
+ poll the card, and a recursive interrupt happens, we won't
+ ack the card, so it might keep on interrupting us. (especially
+ level sensitive interrupt systems like PCI).
- - The "initialized" test goes after the hardware twiddling. Otherwise
- the card will stick us in the interrupt routine again.
+ - Rate limit goes before hardware twiddling. Otherwise we won't
+ catch a card that has gone bonkers.
- - The initialized test goes before recursive.
- */
+ - The "initialized" test goes after the hardware twiddling. Otherwise
+ the card will stick us in the interrupt routine again.
+
+ - The initialized test goes before recursive.
+ */
#ifdef IRQ_RATE_LIMIT
- /* Aaargh! I'm ashamed. This costs more lines-of-code than the
- actual interrupt routine!. (Well, used to when I wrote that comment) */
- {
- static int lastjif;
- static int nintr=0;
-
- if (lastjif == jiffies) {
- if (++nintr > IRQ_RATE_LIMIT) {
- free_irq (HostP->Ivec, ptr);
- printk (KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n",
- HostP->Ivec);
- }
- } else {
- lastjif = jiffies;
- nintr = 0;
- }
- }
+ /* Aaargh! I'm ashamed. This costs more lines-of-code than the
+ actual interrupt routine!. (Well, used to when I wrote that comment) */
+ {
+ static int lastjif;
+ static int nintr = 0;
+
+ if (lastjif == jiffies) {
+ if (++nintr > IRQ_RATE_LIMIT) {
+ free_irq(HostP->Ivec, ptr);
+ printk(KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n", HostP->Ivec);
+ }
+ } else {
+ lastjif = jiffies;
+ nintr = 0;
+ }
+ }
#endif
- rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
- if (HostP->Ivec == irq) {
- /* Tell the card we've noticed the interrupt. */
- rio_reset_interrupt (HostP);
- }
-
- if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
- return IRQ_HANDLED;
-
- if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) {
- printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n",
- (int) ptr, HostP->Ivec);
- return IRQ_HANDLED;
- }
-
- RIOServiceHost(p, HostP, irq);
-
- rio_dprintk ( RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n",
- (int) ptr, HostP->Type);
-
- clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
- rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n",
- irq, HostP->Ivec);
- func_exit ();
- return IRQ_HANDLED;
+ rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
+ if (HostP->Ivec == irq) {
+ /* Tell the card we've noticed the interrupt. */
+ rio_reset_interrupt(HostP);
+ }
+
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
+ return IRQ_HANDLED;
+
+ if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) {
+ printk(KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", (int) ptr, HostP->Ivec);
+ return IRQ_HANDLED;
+ }
+
+ RIOServiceHost(p, HostP, irq);
+
+ rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n", (int) ptr, HostP->Type);
+
+ clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks);
+ rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
+ func_exit();
+ return IRQ_HANDLED;
}
-static void rio_pollfunc (unsigned long data)
+static void rio_pollfunc(unsigned long data)
{
- func_enter ();
+ func_enter();
- rio_interrupt (0, &p->RIOHosts[data], NULL);
- p->RIOHosts[data].timer.expires = jiffies + rio_poll;
- add_timer (&p->RIOHosts[data].timer);
+ rio_interrupt(0, &p->RIOHosts[data], NULL);
+ p->RIOHosts[data].timer.expires = jiffies + rio_poll;
+ add_timer(&p->RIOHosts[data].timer);
- func_exit ();
+ func_exit();
}
@@ -485,106 +479,91 @@ static void rio_pollfunc (unsigned long data)
/* Ehhm. I don't know how to fiddle with interrupts on the Specialix
cards. .... Hmm. Ok I figured it out. You don't. -- REW */
-static void rio_disable_tx_interrupts (void * ptr)
+static void rio_disable_tx_interrupts(void *ptr)
{
- func_enter();
+ func_enter();
- /* port->gs.flags &= ~GS_TX_INTEN; */
+ /* port->gs.flags &= ~GS_TX_INTEN; */
- func_exit();
+ func_exit();
}
-static void rio_enable_tx_interrupts (void * ptr)
+static void rio_enable_tx_interrupts(void *ptr)
{
- struct Port *PortP = ptr;
- /* int hn; */
+ struct Port *PortP = ptr;
+ /* int hn; */
- func_enter();
+ func_enter();
- /* hn = PortP->HostP - p->RIOHosts;
+ /* hn = PortP->HostP - p->RIOHosts;
- rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
- rio_interrupt (-1,(void *) hn, NULL); */
+ rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
+ rio_interrupt (-1,(void *) hn, NULL); */
- RIOTxEnable((char *) PortP);
+ RIOTxEnable((char *) PortP);
- /*
- * In general we cannot count on "tx empty" interrupts, although
- * the interrupt routine seems to be able to tell the difference.
- */
- PortP->gs.flags &= ~GS_TX_INTEN;
+ /*
+ * In general we cannot count on "tx empty" interrupts, although
+ * the interrupt routine seems to be able to tell the difference.
+ */
+ PortP->gs.flags &= ~GS_TX_INTEN;
- func_exit();
+ func_exit();
}
-static void rio_disable_rx_interrupts (void * ptr)
+static void rio_disable_rx_interrupts(void *ptr)
{
- func_enter();
- func_exit();
+ func_enter();
+ func_exit();
}
-static void rio_enable_rx_interrupts (void * ptr)
+static void rio_enable_rx_interrupts(void *ptr)
{
- /* struct rio_port *port = ptr; */
- func_enter();
- func_exit();
+ /* struct rio_port *port = ptr; */
+ func_enter();
+ func_exit();
}
/* Jeez. Isn't this simple? */
-static int rio_get_CD (void * ptr)
+static int rio_get_CD(void *ptr)
{
- struct Port *PortP = ptr;
- int rv;
+ struct Port *PortP = ptr;
+ int rv;
- func_enter();
- rv = (PortP->ModemState & MSVR1_CD) != 0;
+ func_enter();
+ rv = (PortP->ModemState & MSVR1_CD) != 0;
+
+ rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
- rio_dprintk (RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
-
- func_exit();
- return rv;
+ func_exit();
+ return rv;
}
/* Jeez. Isn't this simple? Actually, we can sync with the actual port
by just pushing stuff into the queue going to the port... */
-static int rio_chars_in_buffer (void * ptr)
+static int rio_chars_in_buffer(void *ptr)
{
- func_enter();
+ func_enter();
- func_exit();
- return 0;
+ func_exit();
+ return 0;
}
/* Nothing special here... */
-static void rio_shutdown_port (void * ptr)
+static void rio_shutdown_port(void *ptr)
{
- struct Port *PortP;
-
- func_enter();
-
- PortP = (struct Port *)ptr;
- PortP->gs.tty = NULL;
-#if 0
- port->gs.flags &= ~ GS_ACTIVE;
- if (!port->gs.tty) {
- rio_dprintk (RIO_DBUG_TTY, "No tty.\n");
- return;
- }
- if (!port->gs.tty->termios) {
- rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");
- return;
- }
- if (port->gs.tty->termios->c_cflag & HUPCL) {
- rio_setsignals (port, 0, 0);
- }
-#endif
+ struct Port *PortP;
+
+ func_enter();
- func_exit();
+ PortP = (struct Port *) ptr;
+ PortP->gs.tty = NULL;
+ func_exit();
}
@@ -595,16 +574,16 @@ static void rio_shutdown_port (void * ptr)
running minicom on a serial port that is driven by a modularized
driver. Have the modem hangup. Then remove the driver module. Then
exit minicom. I expect an "oops". -- REW */
-static void rio_hungup (void *ptr)
+static void rio_hungup(void *ptr)
{
- struct Port *PortP;
+ struct Port *PortP;
+
+ func_enter();
- func_enter();
-
- PortP = (struct Port *)ptr;
- PortP->gs.tty = NULL;
+ PortP = (struct Port *) ptr;
+ PortP->gs.tty = NULL;
- func_exit ();
+ func_exit();
}
@@ -612,146 +591,100 @@ static void rio_hungup (void *ptr)
this.
rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
*/
-static void rio_close (void *ptr)
+static void rio_close(void *ptr)
{
- struct Port *PortP;
+ struct Port *PortP;
- func_enter ();
+ func_enter();
- PortP = (struct Port *)ptr;
+ PortP = (struct Port *) ptr;
- riotclose (ptr);
+ riotclose(ptr);
- if(PortP->gs.count) {
- printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count);
- PortP->gs.count = 0;
- }
+ if (PortP->gs.count) {
+ printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.count);
+ PortP->gs.count = 0;
+ }
- PortP->gs.tty = NULL;
- func_exit ();
+ PortP->gs.tty = NULL;
+ func_exit();
}
-static int rio_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
- int rc = 0;
- func_enter();
+ int rc = 0;
+ func_enter();
- /* The "dev" argument isn't used. */
- rc = riocontrol (p, 0, cmd, (void *)arg, capable(CAP_SYS_ADMIN));
+ /* The "dev" argument isn't used. */
+ rc = riocontrol(p, 0, cmd, (void *) arg, capable(CAP_SYS_ADMIN));
- func_exit ();
- return rc;
+ func_exit();
+ return rc;
}
-extern int RIOShortCommand(struct rio_info *p, struct Port *PortP,
- int command, int len, int arg);
+extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-static int rio_ioctl (struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
{
- int rc;
- struct Port *PortP;
- int ival;
-
- func_enter();
+ int rc;
+ struct Port *PortP;
+ int ival;
- PortP = (struct Port *)tty->driver_data;
+ func_enter();
- rc = 0;
- switch (cmd) {
-#if 0
- case TIOCGSOFTCAR:
- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
- (unsigned int *) arg);
- break;
-#endif
- case TIOCSSOFTCAR:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- tty->termios->c_cflag =
- (tty->termios->c_cflag & ~CLOCAL) |
- (ival ? CLOCAL : 0);
- }
- break;
- case TIOCGSERIAL:
- rc = -EFAULT;
- if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct)))
- rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
- break;
- case TCSBRK:
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
- rc = -EIO;
- } else {
- if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
- rc = -EIO;
- }
- }
- break;
- case TCSBRKP:
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
- rc = -EIO;
- } else {
- int l;
- l = arg?arg*100:250;
- if (l > 255) l = 255;
- if (RIOShortCommand(p, PortP, SBREAK, 2, arg?arg*100:250) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
- rc = -EIO;
- }
- }
- break;
- case TIOCSSERIAL:
- rc = -EFAULT;
- if (access_ok(VERIFY_READ, (void *) arg,
- sizeof(struct serial_struct)))
- rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
- break;
-#if 0
- /*
- * note: these IOCTLs no longer reach here. Use
- * tiocmset/tiocmget driver methods instead. The
- * #if 0 disablement predates this comment.
- */
- case TIOCMGET:
- rc = -EFAULT;
- if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))) {
- rc = 0;
- ival = rio_getsignals(port);
- put_user(ival, (unsigned int *) arg);
- }
- break;
- case TIOCMBIS:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
- ((ival & TIOCM_RTS) ? 1 : -1));
- }
- break;
- case TIOCMBIC:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
- ((ival & TIOCM_RTS) ? 0 : -1));
- }
- break;
- case TIOCMSET:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
- ((ival & TIOCM_RTS) ? 1 : 0));
- }
- break;
-#endif
- default:
- rc = -ENOIOCTLCMD;
- break;
- }
- func_exit();
- return rc;
+ PortP = (struct Port *) tty->driver_data;
+
+ rc = 0;
+ switch (cmd) {
+ case TIOCSSOFTCAR:
+ if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+ tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
+ }
+ break;
+ case TIOCGSERIAL:
+ rc = -EFAULT;
+ if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct)))
+ rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
+ break;
+ case TCSBRK:
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+ rc = -EIO;
+ } else {
+ if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+ rc = -EIO;
+ }
+ }
+ break;
+ case TCSBRKP:
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+ rc = -EIO;
+ } else {
+ int l;
+ l = arg ? arg * 100 : 250;
+ if (l > 255)
+ l = 255;
+ if (RIOShortCommand(p, PortP, SBREAK, 2, arg ? arg * 100 : 250) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+ rc = -EIO;
+ }
+ }
+ break;
+ case TIOCSSERIAL:
+ rc = -EFAULT;
+ if (access_ok(VERIFY_READ, (void *) arg, sizeof(struct serial_struct)))
+ rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
+ break;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ func_exit();
+ return rc;
}
@@ -771,37 +704,37 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp,
* flow control scheme is in use for that port. -- Simon Allen
*/
-static void rio_throttle (struct tty_struct * tty)
+static void rio_throttle(struct tty_struct *tty)
{
- struct Port *port = (struct Port *)tty->driver_data;
-
- func_enter();
- /* If the port is using any type of input flow
- * control then throttle the port.
- */
-
- if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {
- port->State |= RIO_THROTTLE_RX;
- }
-
- func_exit();
+ struct Port *port = (struct Port *) tty->driver_data;
+
+ func_enter();
+ /* If the port is using any type of input flow
+ * control then throttle the port.
+ */
+
+ if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
+ port->State |= RIO_THROTTLE_RX;
+ }
+
+ func_exit();
}
-static void rio_unthrottle (struct tty_struct * tty)
+static void rio_unthrottle(struct tty_struct *tty)
{
- struct Port *port = (struct Port *)tty->driver_data;
+ struct Port *port = (struct Port *) tty->driver_data;
- func_enter();
- /* Always unthrottle even if flow control is not enabled on
- * this port in case we disabled flow control while the port
- * was throttled
- */
+ func_enter();
+ /* Always unthrottle even if flow control is not enabled on
+ * this port in case we disabled flow control while the port
+ * was throttled
+ */
- port->State &= ~RIO_THROTTLE_RX;
+ port->State &= ~RIO_THROTTLE_RX;
- func_exit();
- return;
+ func_exit();
+ return;
}
@@ -813,35 +746,34 @@ static void rio_unthrottle (struct tty_struct * tty)
* ********************************************************************** */
-static struct vpd_prom *get_VPD_PROM (struct Host *hp)
+static struct vpd_prom *get_VPD_PROM(struct Host *hp)
{
- static struct vpd_prom vpdp;
- char *p;
- int i;
+ static struct vpd_prom vpdp;
+ char *p;
+ int i;
+
+ func_enter();
+ rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM);
- func_enter();
- rio_dprintk (RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
- hp->Caddr + RIO_VPD_ROM);
+ p = (char *) &vpdp;
+ for (i = 0; i < sizeof(struct vpd_prom); i++)
+ *p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2);
+ /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
- p = (char *) &vpdp;
- for (i=0;i< sizeof (struct vpd_prom);i++)
- *p++ = readb (hp->Caddr+RIO_VPD_ROM + i*2);
- /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
+ /* Terminate the identifier string.
+ *** requires one extra byte in struct vpd_prom *** */
+ *p++ = 0;
- /* Terminate the identifier string.
- *** requires one extra byte in struct vpd_prom *** */
- *p++=0;
+ if (rio_debug & RIO_DEBUG_PROBE)
+ my_hd((char *) &vpdp, 0x20);
- if (rio_debug & RIO_DEBUG_PROBE)
- my_hd ((char *)&vpdp, 0x20);
-
- func_exit();
+ func_exit();
- return &vpdp;
+ return &vpdp;
}
static struct tty_operations rio_ops = {
- .open = riotopen,
+ .open = riotopen,
.close = gs_close,
.write = gs_write,
.put_char = gs_put_char,
@@ -893,7 +825,7 @@ static int rio_init_drivers(void)
rio_driver2->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(rio_driver2, &rio_ops);
- rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+ rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
if ((error = tty_register_driver(rio_driver)))
goto out2;
@@ -901,116 +833,111 @@ static int rio_init_drivers(void)
goto out3;
func_exit();
return 0;
-out3:
+ out3:
tty_unregister_driver(rio_driver);
-out2:
+ out2:
put_tty_driver(rio_driver2);
-out1:
+ out1:
put_tty_driver(rio_driver);
-out:
- printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",
- error);
+ out:
+ printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error);
return 1;
}
-static void * ckmalloc (int size)
+static void *ckmalloc(int size)
{
- void *p;
+ void *p;
- p = kmalloc(size, GFP_KERNEL);
- if (p)
- memset(p, 0, size);
- return p;
+ p = kmalloc(size, GFP_KERNEL);
+ if (p)
+ memset(p, 0, size);
+ return p;
}
-static int rio_init_datastructures (void)
+static int rio_init_datastructures(void)
{
- int i;
- struct Port *port;
- func_enter();
-
- /* Many drivers statically allocate the maximum number of ports
- There is no reason not to allocate them dynamically. Is there? -- REW */
- /* However, the RIO driver allows users to configure their first
- RTA as the ports numbered 504-511. We therefore need to allocate
- the whole range. :-( -- REW */
-
+ int i;
+ struct Port *port;
+ func_enter();
+
+ /* Many drivers statically allocate the maximum number of ports
+ There is no reason not to allocate them dynamically. Is there? -- REW */
+ /* However, the RIO driver allows users to configure their first
+ RTA as the ports numbered 504-511. We therefore need to allocate
+ the whole range. :-( -- REW */
+
#define RI_SZ sizeof(struct rio_info)
#define HOST_SZ sizeof(struct Host)
#define PORT_SZ sizeof(struct Port *)
#define TMIO_SZ sizeof(struct termios *)
- rio_dprintk (RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n",
- RI_SZ,
- RIO_HOSTS * HOST_SZ,
- RIO_PORTS * PORT_SZ,
- RIO_PORTS * TMIO_SZ,
- RIO_PORTS * TMIO_SZ);
-
- if (!(p = ckmalloc ( RI_SZ))) goto free0;
- if (!(p->RIOHosts = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1;
- if (!(p->RIOPortp = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2;
- p->RIOConf = RIOConf;
- rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p\n",
- p, p->RIOHosts, p->RIOPortp);
+ rio_dprintk(RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
+
+ if (!(p = ckmalloc(RI_SZ)))
+ goto free0;
+ if (!(p->RIOHosts = ckmalloc(RIO_HOSTS * HOST_SZ)))
+ goto free1;
+ if (!(p->RIOPortp = ckmalloc(RIO_PORTS * PORT_SZ)))
+ goto free2;
+ p->RIOConf = RIOConf;
+ rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
#if 1
- for (i = 0; i < RIO_PORTS; i++) {
- port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port));
- if (!port) {
- goto free6;
- }
- rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
- port->PortNum = i;
- port->gs.magic = RIO_MAGIC;
- port->gs.close_delay = HZ/2;
- port->gs.closing_wait = 30 * HZ;
- port->gs.rd = &rio_real_driver;
- spin_lock_init(&port->portSem);
- /*
- * Initializing wait queue
- */
- init_waitqueue_head(&port->gs.open_wait);
- init_waitqueue_head(&port->gs.close_wait);
- }
+ for (i = 0; i < RIO_PORTS; i++) {
+ port = p->RIOPortp[i] = ckmalloc(sizeof(struct Port));
+ if (!port) {
+ goto free6;
+ }
+ rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
+ port->PortNum = i;
+ port->gs.magic = RIO_MAGIC;
+ port->gs.close_delay = HZ / 2;
+ port->gs.closing_wait = 30 * HZ;
+ port->gs.rd = &rio_real_driver;
+ spin_lock_init(&port->portSem);
+ /*
+ * Initializing wait queue
+ */
+ init_waitqueue_head(&port->gs.open_wait);
+ init_waitqueue_head(&port->gs.close_wait);
+ }
#else
- /* We could postpone initializing them to when they are configured. */
+ /* We could postpone initializing them to when they are configured. */
#endif
-
- if (rio_debug & RIO_DEBUG_INIT) {
- my_hd (&rio_real_driver, sizeof (rio_real_driver));
- }
-
- func_exit();
- return 0;
+ if (rio_debug & RIO_DEBUG_INIT) {
+ my_hd(&rio_real_driver, sizeof(rio_real_driver));
+ }
- free6:for (i--;i>=0;i--)
- kfree (p->RIOPortp[i]);
+
+ func_exit();
+ return 0;
+
+ free6:for (i--; i >= 0; i--)
+ kfree(p->RIOPortp[i]);
/*free5:
free4:
- free3:*/kfree (p->RIOPortp);
- free2:kfree (p->RIOHosts);
- free1:
- rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n",
- p, p->RIOHosts, p->RIOPortp);
- kfree(p);
- free0:
- return -ENOMEM;
+ free3:*/ kfree(p->RIOPortp);
+ free2:kfree(p->RIOHosts);
+ free1:
+ rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
+ kfree(p);
+ free0:
+ return -ENOMEM;
}
-static void __exit rio_release_drivers(void)
+static void __exit rio_release_drivers(void)
{
- func_enter();
- tty_unregister_driver(rio_driver2);
- tty_unregister_driver(rio_driver);
- put_tty_driver(rio_driver2);
- put_tty_driver(rio_driver);
- func_exit();
+ func_enter();
+ tty_unregister_driver(rio_driver2);
+ tty_unregister_driver(rio_driver);
+ put_tty_driver(rio_driver2);
+ put_tty_driver(rio_driver);
+ func_exit();
}
@@ -1021,7 +948,7 @@ static void __exit rio_release_drivers(void)
There is another bit besides Bit 17. Turning that bit off
(on boards shipped with the fix in the eeprom) results in a
hang on the next access to the card.
- */
+ */
/********************************************************
* Setting bit 17 in the CNTRL register of the PLX 9050 *
@@ -1034,319 +961,293 @@ static void __exit rio_release_drivers(void)
EEprom. As the bit is read/write for the CPU, we can fix it here,
if we detect that it isn't set correctly. -- REW */
-static void fix_rio_pci (struct pci_dev *pdev)
+static void fix_rio_pci(struct pci_dev *pdev)
{
- unsigned int hwbase;
- unsigned long rebase;
- unsigned int t;
+ unsigned int hwbase;
+ unsigned long rebase;
+ unsigned int t;
#define CNTRL_REG_OFFSET 0x50
#define CNTRL_REG_GOODVALUE 0x18260000
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
- hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
- rebase = (ulong) ioremap(hwbase, 0x80);
- t = readl (rebase + CNTRL_REG_OFFSET);
- if (t != CNTRL_REG_GOODVALUE) {
- printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n",
- t, CNTRL_REG_GOODVALUE);
- writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
- }
- iounmap((char*) rebase);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
+ hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
+ rebase = (ulong) ioremap(hwbase, 0x80);
+ t = readl(rebase + CNTRL_REG_OFFSET);
+ if (t != CNTRL_REG_GOODVALUE) {
+ printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
+ writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
+ }
+ iounmap((char *) rebase);
}
#endif
-static int __init rio_init(void)
+static int __init rio_init(void)
{
- int found = 0;
- int i;
- struct Host *hp;
- int retval;
- struct vpd_prom *vpdp;
- int okboard;
+ int found = 0;
+ int i;
+ struct Host *hp;
+ int retval;
+ struct vpd_prom *vpdp;
+ int okboard;
#ifdef CONFIG_PCI
- struct pci_dev *pdev = NULL;
- unsigned int tint;
- unsigned short tshort;
+ struct pci_dev *pdev = NULL;
+ unsigned int tint;
+ unsigned short tshort;
#endif
- func_enter();
- rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n",
- rio_debug);
-
- if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) {
- printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. "
- "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
- rio_debug=-1;
- }
-
- if (misc_register(&rio_fw_device) < 0) {
- printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
- return -EIO;
- }
-
- retval = rio_init_datastructures ();
- if (retval < 0) {
- misc_deregister(&rio_fw_device);
- return retval;
- }
-
+ func_enter();
+ rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug);
+
+ if (abs((long) (&rio_debug) - rio_debug) < 0x10000) {
+ printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
+ rio_debug = -1;
+ }
+
+ if (misc_register(&rio_fw_device) < 0) {
+ printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
+ return -EIO;
+ }
+
+ retval = rio_init_datastructures();
+ if (retval < 0) {
+ misc_deregister(&rio_fw_device);
+ return retval;
+ }
#ifdef CONFIG_PCI
- /* First look for the JET devices: */
- while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- pdev))) {
- if (pci_enable_device(pdev)) continue;
-
- /* Specialix has a whole bunch of cards with
- 0x2000 as the device ID. They say its because
- the standard requires it. Stupid standard. */
- /* It seems that reading a word doesn't work reliably on 2.0.
- Also, reading a non-aligned dword doesn't work. So we read the
- whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
- ourselves */
- /* I don't know why the define doesn't work, constant 0x2c does --REW */
- pci_read_config_dword (pdev, 0x2c, &tint);
- tshort = (tint >> 16) & 0xffff;
- rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
- if (tshort != 0x0100) {
- rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n",
- tshort);
- continue;
- }
- rio_dprintk (RIO_DEBUG_PROBE, "cp1\n");
-
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
-
- hp = &p->RIOHosts[p->RIONumHosts];
- hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
- hp->Ivec = pdev->irq;
- if (((1 << hp->Ivec) & rio_irqmask) == 0)
- hp->Ivec = 0;
- hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
- hp->CardP = (struct DpRam *) hp->Caddr;
- hp->Type = RIO_PCI;
- hp->Copy = rio_pcicopy;
- hp->Mode = RIO_PCI_BOOT_FROM_RAM;
- spin_lock_init(&hp->HostLock);
- rio_reset_interrupt (hp);
- rio_start_card_running (hp);
-
- rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
- (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr);
- if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr,
- RIO_PCI, 0 ) == RIO_SUCCESS) {
- rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n");
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- fix_rio_pci (pdev);
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- found++;
- } else {
- iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
- }
- }
-
- /* Then look for the older PCI card.... : */
-
- /* These older PCI cards have problems (only byte-mode access is
- supported), which makes them a bit awkward to support.
- They also have problems sharing interrupts. Be careful.
- (The driver now refuses to share interrupts for these
- cards. This should be sufficient).
- */
-
- /* Then look for the older RIO/PCI devices: */
- while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_RIO,
- pdev))) {
- if (pci_enable_device(pdev)) continue;
+ /* First look for the JET devices: */
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) {
+ if (pci_enable_device(pdev))
+ continue;
+
+ /* Specialix has a whole bunch of cards with
+ 0x2000 as the device ID. They say its because
+ the standard requires it. Stupid standard. */
+ /* It seems that reading a word doesn't work reliably on 2.0.
+ Also, reading a non-aligned dword doesn't work. So we read the
+ whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
+ ourselves */
+ /* I don't know why the define doesn't work, constant 0x2c does --REW */
+ pci_read_config_dword(pdev, 0x2c, &tint);
+ tshort = (tint >> 16) & 0xffff;
+ rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
+ if (tshort != 0x0100) {
+ rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort);
+ continue;
+ }
+ rio_dprintk(RIO_DEBUG_PROBE, "cp1\n");
+
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
+
+ hp = &p->RIOHosts[p->RIONumHosts];
+ hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
+ hp->Ivec = pdev->irq;
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_PCI;
+ hp->Copy = rio_pcicopy;
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+ spin_lock_init(&hp->HostLock);
+ rio_reset_interrupt(hp);
+ rio_start_card_running(hp);
+
+ rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
+ if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) {
+ rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+ WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+ p->RIOHosts[p->RIONumHosts].UniqueNum =
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+ fix_rio_pci(pdev);
+ p->RIOLastPCISearch = RIO_SUCCESS;
+ p->RIONumHosts++;
+ found++;
+ } else {
+ iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr));
+ }
+ }
+
+ /* Then look for the older PCI card.... : */
+
+ /* These older PCI cards have problems (only byte-mode access is
+ supported), which makes them a bit awkward to support.
+ They also have problems sharing interrupts. Be careful.
+ (The driver now refuses to share interrupts for these
+ cards. This should be sufficient).
+ */
+
+ /* Then look for the older RIO/PCI devices: */
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) {
+ if (pci_enable_device(pdev))
+ continue;
#ifdef CONFIG_RIO_OLDPCI
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint);
-
- hp = &p->RIOHosts[p->RIONumHosts];
- hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
- hp->Ivec = pdev->irq;
- if (((1 << hp->Ivec) & rio_irqmask) == 0)
- hp->Ivec = 0;
- hp->Ivec |= 0x8000; /* Mark as non-sharable */
- hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
- hp->CardP = (struct DpRam *) hp->Caddr;
- hp->Type = RIO_PCI;
- hp->Copy = rio_pcicopy;
- hp->Mode = RIO_PCI_BOOT_FROM_RAM;
- spin_lock_init(&hp->HostLock);
-
- rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
- rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
-
- rio_reset_interrupt (hp);
- rio_start_card_running (hp);
- rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
- (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr);
- if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr,
- RIO_PCI, 0 ) == RIO_SUCCESS) {
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- found++;
- } else {
- iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
- }
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint);
+
+ hp = &p->RIOHosts[p->RIONumHosts];
+ hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
+ hp->Ivec = pdev->irq;
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
+ hp->Ivec |= 0x8000; /* Mark as non-sharable */
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_PCI;
+ hp->Copy = rio_pcicopy;
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+ spin_lock_init(&hp->HostLock);
+
+ rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+ rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+ rio_reset_interrupt(hp);
+ rio_start_card_running(hp);
+ rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
+ if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) {
+ WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+ p->RIOHosts[p->RIONumHosts].UniqueNum =
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+ p->RIOLastPCISearch = RIO_SUCCESS;
+ p->RIONumHosts++;
+ found++;
+ } else {
+ iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr));
+ }
#else
- printk (KERN_ERR "Found an older RIO PCI card, but the driver is not "
- "compiled to support it.\n");
+ printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
#endif
- }
-#endif /* PCI */
-
- /* Now probe for ISA cards... */
- for (i=0;i<NR_RIO_ADDRS;i++) {
- hp = &p->RIOHosts[p->RIONumHosts];
- hp->PaddrP = rio_probe_addrs[i];
- /* There was something about the IRQs of these cards. 'Forget what.--REW */
- hp->Ivec = 0;
- hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
- hp->CardP = (struct DpRam *) hp->Caddr;
- hp->Type = RIO_AT;
- hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
- * -- YES! this is now a normal copy. Only the
- * old PCI card uses the special PCI copy.
- * Moreover, the ISA card will work with the
- * special PCI copy anyway. -- REW */
- hp->Mode = 0;
- spin_lock_init(&hp->HostLock);
-
- vpdp = get_VPD_PROM (hp);
- rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n");
- okboard = 0;
- if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
- (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
- (strncmp (vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
- /* Board is present... */
- if (RIOBoardTest (hp->PaddrP,
- hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) {
- /* ... and feeling fine!!!! */
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
- if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n",
- p->RIONumHosts,
- p->RIOHosts[p->RIONumHosts-1].UniqueNum);
- okboard++;
- found++;
- }
- }
-
- if (!okboard)
- iounmap ((char*) (hp->Caddr));
- }
- }
-
-
- for (i=0;i<p->RIONumHosts;i++) {
- hp = &p->RIOHosts[i];
- if (hp->Ivec) {
- int mode = SA_SHIRQ;
- if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
- rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode);
- retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp);
- rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
- if (retval) {
- printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
- hp->Ivec = 0;
- }
- rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
- if (hp->Ivec != 0){
- rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
- hp->Mode |= RIO_PCI_INT_ENABLE;
- } else
- hp->Mode &= !RIO_PCI_INT_ENABLE;
- rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
- rio_start_card_running (hp);
- }
- /* Init the timer "always" to make sure that it can safely be
- deleted when we unload... */
-
- init_timer (&hp->timer);
- if (!hp->Ivec) {
- rio_dprintk (RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n",
- rio_poll);
- hp->timer.data = i;
- hp->timer.function = rio_pollfunc;
- hp->timer.expires = jiffies + rio_poll;
- add_timer (&hp->timer);
- }
- }
-
- if (found) {
- rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
- rio_init_drivers ();
- } else {
- /* deregister the misc device we created earlier */
- misc_deregister(&rio_fw_device);
- }
-
- func_exit();
- return found?0:-EIO;
+ }
+#endif /* PCI */
+
+ /* Now probe for ISA cards... */
+ for (i = 0; i < NR_RIO_ADDRS; i++) {
+ hp = &p->RIOHosts[p->RIONumHosts];
+ hp->PaddrP = rio_probe_addrs[i];
+ /* There was something about the IRQs of these cards. 'Forget what.--REW */
+ hp->Ivec = 0;
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_AT;
+ hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+ * -- YES! this is now a normal copy. Only the
+ * old PCI card uses the special PCI copy.
+ * Moreover, the ISA card will work with the
+ * special PCI copy anyway. -- REW */
+ hp->Mode = 0;
+ spin_lock_init(&hp->HostLock);
+
+ vpdp = get_VPD_PROM(hp);
+ rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n");
+ okboard = 0;
+ if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
+ /* Board is present... */
+ if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) {
+ /* ... and feeling fine!!!! */
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+ if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum);
+ okboard++;
+ found++;
+ }
+ }
+
+ if (!okboard)
+ iounmap((char *) (hp->Caddr));
+ }
+ }
+
+
+ for (i = 0; i < p->RIONumHosts; i++) {
+ hp = &p->RIOHosts[i];
+ if (hp->Ivec) {
+ int mode = SA_SHIRQ;
+ if (hp->Ivec & 0x8000) {
+ mode = 0;
+ hp->Ivec &= 0x7fff;
+ }
+ rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode);
+ retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp);
+ rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+ if (retval) {
+ printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+ hp->Ivec = 0;
+ }
+ rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+ if (hp->Ivec != 0) {
+ rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
+ hp->Mode |= RIO_PCI_INT_ENABLE;
+ } else
+ hp->Mode &= !RIO_PCI_INT_ENABLE;
+ rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+ rio_start_card_running(hp);
+ }
+ /* Init the timer "always" to make sure that it can safely be
+ deleted when we unload... */
+
+ init_timer(&hp->timer);
+ if (!hp->Ivec) {
+ rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
+ hp->timer.data = i;
+ hp->timer.function = rio_pollfunc;
+ hp->timer.expires = jiffies + rio_poll;
+ add_timer(&hp->timer);
+ }
+ }
+
+ if (found) {
+ rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
+ rio_init_drivers();
+ } else {
+ /* deregister the misc device we created earlier */
+ misc_deregister(&rio_fw_device);
+ }
+
+ func_exit();
+ return found ? 0 : -EIO;
}
-static void __exit rio_exit (void)
+static void __exit rio_exit(void)
{
- int i;
- struct Host *hp;
-
- func_enter();
+ int i;
+ struct Host *hp;
+
+ func_enter();
- for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
- RIOHostReset (hp->Type, hp->CardP, hp->Slot);
- if (hp->Ivec) {
- free_irq (hp->Ivec, hp);
- rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
- }
- /* It is safe/allowed to del_timer a non-active timer */
- del_timer (&hp->timer);
- }
+ for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) {
+ RIOHostReset(hp->Type, hp->CardP, hp->Slot);
+ if (hp->Ivec) {
+ free_irq(hp->Ivec, hp);
+ rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
+ }
+ /* It is safe/allowed to del_timer a non-active timer */
+ del_timer(&hp->timer);
+ }
- if (misc_deregister(&rio_fw_device) < 0) {
- printk (KERN_INFO "rio: couldn't deregister control-device\n");
- }
+ if (misc_deregister(&rio_fw_device) < 0) {
+ printk(KERN_INFO "rio: couldn't deregister control-device\n");
+ }
- rio_dprintk (RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
+ rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
- rio_release_drivers ();
+ rio_release_drivers();
- /* Release dynamically allocated memory */
- kfree (p->RIOPortp);
- kfree (p->RIOHosts);
- kfree (p);
+ /* Release dynamically allocated memory */
+ kfree(p->RIOPortp);
+ kfree(p->RIOHosts);
+ kfree(p);
- func_exit();
+ func_exit();
}
module_init(rio_init);
@@ -1372,4 +1273,3 @@ module_exit(rio_exit);
* tab-width: 8
* End:
*/
-
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
index 1fba19d5b66a..4ce77fb1fae5 100644
--- a/drivers/char/rio/rio_linux.h
+++ b/drivers/char/rio/rio_linux.h
@@ -37,15 +37,15 @@
struct vpd_prom {
- unsigned short id;
- char hwrev;
- char hwass;
- int uniqid;
- char myear;
- char mweek;
- char hw_feature[5];
- char oem_id;
- char identifier[16];
+ unsigned short id;
+ char hwrev;
+ char hwass;
+ int uniqid;
+ char myear;
+ char mweek;
+ char hw_feature[5];
+ char oem_id;
+ char identifier[16];
};
@@ -75,13 +75,13 @@ struct vpd_prom {
(L_ISIG(tty)))
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
#define RIO_BOARD_INTR_LOCK 1
-#ifndef RIOCTL_MISC_MINOR
+#ifndef RIOCTL_MISC_MINOR
/* Allow others to gather this into "major.h" or something like that */
#define RIOCTL_MISC_MINOR 169
#endif
@@ -121,39 +121,39 @@ struct vpd_prom {
spin_unlock_irqrestore(sem, flags)
#define rio_spin_lock(sem) \
- spin_lock(sem)
+ spin_lock(sem)
#define rio_spin_unlock(sem) \
- spin_unlock(sem)
+ spin_unlock(sem)
#endif
#ifdef CONFIG_RIO_OLDPCI
-static inline void *rio_memcpy_toio (void *dummy, void *dest, void *source, int n)
+static inline void *rio_memcpy_toio(void *dummy, void *dest, void *source, int n)
{
- char *dst = dest;
- char *src = source;
+ char *dst = dest;
+ char *src = source;
- while (n--) {
- writeb (*src++, dst++);
- (void) readb (dummy);
- }
+ while (n--) {
+ writeb(*src++, dst++);
+ (void) readb(dummy);
+ }
- return dest;
+ return dest;
}
-static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
+static inline void *rio_memcpy_fromio(void *dest, void *source, int n)
{
- char *dst = dest;
- char *src = source;
+ char *dst = dest;
+ char *src = source;
- while (n--)
- *dst++ = readb (src++);
+ while (n--)
+ *dst++ = readb(src++);
- return dest;
+ return dest;
}
#else
@@ -179,9 +179,8 @@ static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __FUNCTION__)
#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line)
#else
-#define rio_dprintk(f, str...) /* nothing */
+#define rio_dprintk(f, str...) /* nothing */
#define func_enter()
#define func_exit()
#define func_enter2()
#endif
-
diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h
index cc6ac6a98f65..822c071a693b 100644
--- a/drivers/char/rio/rioboard.h
+++ b/drivers/char/rio/rioboard.h
@@ -35,7 +35,7 @@
*/
-#ifndef _rioboard_h /* If RIOBOARD.H not already defined */
+#ifndef _rioboard_h /* If RIOBOARD.H not already defined */
#define _rioboard_h 1
/*****************************************************************************
@@ -46,7 +46,7 @@
/* Hardware Registers... */
-#define RIO_REG_BASE 0x7C00 /* Base of control registers */
+#define RIO_REG_BASE 0x7C00 /* Base of control registers */
#define RIO_CONFIG RIO_REG_BASE + 0x0000 /* WRITE: Configuration Register */
#define RIO_INTSET RIO_REG_BASE + 0x0080 /* WRITE: Interrupt Set */
@@ -58,30 +58,30 @@
#define RIO_RESETSTAT RIO_REG_BASE + 0x0100 /* READ: Reset Status (Jet boards only) */
/* RIO_VPD_ROM definitions... */
-#define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */
-#define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */
-#define VPD_HW_REV 0x02 /* READ: Hardware Revision */
-#define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */
-#define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */
-#define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */
-#define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */
-#define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */
-#define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */
-#define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */
-#define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */
-#define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */
-#define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */
-#define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */
-#define VPD_OEMID 0x0F /* READ: OEM Identifier */
-#define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */
+#define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */
+#define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */
+#define VPD_HW_REV 0x02 /* READ: Hardware Revision */
+#define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */
+#define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */
+#define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */
+#define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */
+#define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */
+#define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */
+#define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */
+#define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */
+#define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */
+#define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */
+#define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */
+#define VPD_OEMID 0x0F /* READ: OEM Identifier */
+#define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */
#define VPD_IDENT_LEN 0x10
/* VPD ROM Definitions... */
#define SLX_ID1 0x4D
#define SLX_ID2 0x98
-#define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */
+#define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */
#define ID_SX_ISA 0x2
#define ID_RIO_EISA 0x3
@@ -101,7 +101,7 @@
/* Firmware load position... */
-#define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */
+#define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */
/*****************************************************************************
***************************** *****************************
@@ -112,14 +112,14 @@
/* Control Register Definitions... */
#define RIO_ISA_IDENT "JBJGPGGHINSMJPJR"
-#define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */
-#define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */
-#define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */
-#define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */
-#define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
+#define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */
+#define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */
+#define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */
+#define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */
+#define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
/*****************************************************************************
***************************** *****************************
@@ -130,17 +130,17 @@
/* Control Register Definitions... */
#define RIO_ISA2_IDENT "JBJGPGGHINSMJPJR"
-#define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */
-#define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */
-#define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */
-#define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */
-#define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */
-#define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */
-#define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
+#define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */
+#define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */
+#define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */
+#define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */
+#define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */
+#define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */
+#define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
/*****************************************************************************
***************************** ******************************
@@ -151,14 +151,14 @@
/* Control Register Definitions... */
#define RIO_ISA3_IDENT "JET HOST BY KEV#"
-#define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */
-#define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
-#define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
-#define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
-#define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
-#define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */
+#define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */
+#define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
+#define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
+#define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
+#define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
+#define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */
/*****************************************************************************
********************************* ********************************
@@ -169,9 +169,9 @@
/* Control Register Definitions... */
#define RIO_MCA_IDENT "JBJGPGGHINSMJPJR"
-#define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
/*****************************************************************************
******************************** ********************************
@@ -185,35 +185,35 @@
#define EISA_PRODUCT_NUMBER 0xC82
#define EISA_REVISION_NUMBER 0xC83
#define EISA_CARD_ENABLE 0xC84
-#define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */
-#define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */
-#define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */
-#define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */
-#define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */
-#define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */
+#define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */
+#define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */
+#define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */
+#define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */
+#define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */
#define EISA_MEM_ADDR_23_16 0xC00
#define EISA_MEM_ADDR_31_24 0xC01
-#define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */
-#define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */
-#define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */
+#define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */
+#define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */
+#define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */
/* Control Register Definitions... */
-#define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */
-#define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */
-#define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */
-#define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */
-#define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
-#define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */
-#define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
-#define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
-#define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
-#define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */
-#define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */
-#define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */
-#define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */
-#define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */
-#define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */
+#define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */
+#define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */
+#define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */
+#define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */
+#define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
+#define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */
+#define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
+#define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
+#define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
+#define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */
+#define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */
+#define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */
+#define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */
+#define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */
+#define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */
/*****************************************************************************
******************************** ********************************
@@ -224,20 +224,20 @@
/* Control Register Definitions... */
#define RIO_SBUS_IDENT "JBPGK#\0\0\0\0\0\0\0\0\0\0"
-#define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */
-#define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */
-#define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */
-#define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */
-#define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */
-#define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */
-#define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */
-#define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */
-#define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */
-#define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
+#define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */
+#define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */
+#define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */
+#define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */
+#define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */
+#define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */
+#define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */
+#define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */
+#define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */
+#define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
/*****************************************************************************
********************************* ********************************
@@ -248,18 +248,18 @@
/* Control Register Definitions... */
#define RIO_PCI_IDENT "ECDDPGJGJHJRGSK#"
-#define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
+#define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
/* PCI Definitions... */
-#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */
-#define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */
-#define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */
+#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */
+#define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */
+#define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */
#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */
-#define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */
+#define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */
/*****************************************************************************
***************************** ******************************
@@ -270,11 +270,11 @@
/* Control Register Definitions... */
#define RIO_PCI2_IDENT "JET HOST BY KEV#"
-#define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
/* PCI Definitions... */
-#define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */
+#define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */
#endif /*_rioboard_h */
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index 34cbb13aad4b..92df43552f15 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -665,13 +665,6 @@ struct PKT *PacketP;
struct CmdBlk *CmdBlkP;
uint sequence;
-#ifdef CHECK
- CheckHost(Host);
- CheckRup(Rup);
- CheckHostP(HostP);
- CheckPacketP(PacketP);
-#endif
-
/*
** If we haven't been told what to boot, we can't boot it.
*/
@@ -956,11 +949,6 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
MyType = "RTA";
MyName = HostP->Mapping[Rup].Name;
}
-#ifdef CHECK
- CheckString(MyType);
- CheckString(MyName);
-#endif
-
MyLink = RBYTE(PktCmdP->LinkNum);
/*
@@ -1309,52 +1297,3 @@ struct Host *HostP;
}
}
-#if 0
-/*
- Function: This function is to disable the disk interrupt
- Returns : Nothing
-*/
-void
-disable_interrupt(vector)
-int vector;
-{
- int ps;
- int val;
-
- disable(ps);
- if (vector > 40) {
- val = 1 << (vector - 40);
- __outb(S8259+1, __inb(S8259+1) | val);
- }
- else {
- val = 1 << (vector - 32);
- __outb(M8259+1, __inb(M8259+1) | val);
- }
- restore(ps);
-}
-
-/*
- Function: This function is to enable the disk interrupt
- Returns : Nothing
-*/
-void
-enable_interrupt(vector)
-int vector;
-{
- int ps;
- int val;
-
- disable(ps);
- if (vector > 40) {
- val = 1 << (vector - 40);
- val = ~val;
- __outb(S8259+1, __inb(S8259+1) & val);
- }
- else {
- val = 1 << (vector - 32);
- val = ~val;
- __outb(M8259+1, __inb(M8259+1) & val);
- }
- restore(ps);
-}
-#endif
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 533085ec6f1b..694bfb9d9378 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -83,102 +83,98 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2";
static struct IdentifyRta IdRta;
static struct KillNeighbour KillUnit;
-int
-RIOFoadRta(struct Host *HostP, struct Map *MapP)
+int RIOFoadRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA\n");
+ rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = MapP->ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = IFOAD;
- CmdBlkP->Packet.data[1] = 0;
- CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
-
- if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = IFOAD;
+ CmdBlkP->Packet.data[1] = 0;
+ CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
+
+ if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
return -EIO;
}
return 0;
}
-int
-RIOZombieRta(struct Host *HostP, struct Map *MapP)
+int RIOZombieRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA\n");
+ rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = MapP->ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = ZOMBIE;
- CmdBlkP->Packet.data[1] = 0;
- CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
-
- if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = ZOMBIE;
+ CmdBlkP->Packet.data[1] = 0;
+ CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
+
+ if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
return -EIO;
}
return 0;
}
-int
-RIOCommandRta(struct rio_info *p, uint RtaUnique,
- int (* func)(struct Host *HostP, struct Map *MapP))
+int RIOCommandRta(struct rio_info *p, uint RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP))
{
uint Host;
- rio_dprintk (RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int)func);
+ rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int) func);
- if ( !RtaUnique )
- return(0);
+ if (!RtaUnique)
+ return (0);
- for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
uint Rta;
struct Host *HostP = &p->RIOHosts[Host];
- for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+ for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
struct Map *MapP = &HostP->Mapping[Rta];
- if ( MapP->RtaUniqueNum == RtaUnique ) {
+ if (MapP->RtaUniqueNum == RtaUnique) {
uint Link;
/*
- ** now, lets just check we have a route to it...
- ** IF the routing stuff is working, then one of the
- ** topology entries for this unit will have a legit
- ** route *somewhere*. We care not where - if its got
- ** any connections, we can get to it.
- */
- for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
- if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+ ** now, lets just check we have a route to it...
+ ** IF the routing stuff is working, then one of the
+ ** topology entries for this unit will have a legit
+ ** route *somewhere*. We care not where - if its got
+ ** any connections, we can get to it.
+ */
+ for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
+ if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) {
/*
- ** Its worth trying the operation...
- */
- return (*func)( HostP, MapP );
+ ** Its worth trying the operation...
+ */
+ return (*func) (HostP, MapP);
}
}
}
@@ -188,60 +184,59 @@ RIOCommandRta(struct rio_info *p, uint RtaUnique,
}
-int
-RIOIdentifyRta(struct rio_info *p, caddr_t arg)
+int RIOIdentifyRta(struct rio_info *p, caddr_t arg)
{
uint Host;
- if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
+ if (copyin((int) arg, (caddr_t) & IdRta, sizeof(IdRta)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
p->RIOError.Error = COPYIN_FAILED;
return -EFAULT;
}
- for ( Host = 0 ; Host < p->RIONumHosts; Host++ ) {
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
uint Rta;
struct Host *HostP = &p->RIOHosts[Host];
- for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+ for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
struct Map *MapP = &HostP->Mapping[Rta];
- if ( MapP->RtaUniqueNum == IdRta.RtaUnique ) {
+ if (MapP->RtaUniqueNum == IdRta.RtaUnique) {
uint Link;
/*
- ** now, lets just check we have a route to it...
- ** IF the routing stuff is working, then one of the
- ** topology entries for this unit will have a legit
- ** route *somewhere*. We care not where - if its got
- ** any connections, we can get to it.
- */
- for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
- if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+ ** now, lets just check we have a route to it...
+ ** IF the routing stuff is working, then one of the
+ ** topology entries for this unit will have a legit
+ ** route *somewhere*. We care not where - if its got
+ ** any connections, we can get to it.
+ */
+ for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
+ if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) {
/*
- ** Its worth trying the operation...
- */
+ ** Its worth trying the operation...
+ */
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA\n");
+ rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
return -ENXIO;
}
-
+
CmdBlkP->Packet.dest_unit = MapP->ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = IDENTIFY;
- CmdBlkP->Packet.data[1] = 0;
- CmdBlkP->Packet.data[2] = IdRta.ID;
-
- if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = IDENTIFY;
+ CmdBlkP->Packet.data[1] = 0;
+ CmdBlkP->Packet.data[2] = IdRta.ID;
+
+ if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
return -EIO;
}
return 0;
@@ -249,114 +244,110 @@ RIOIdentifyRta(struct rio_info *p, caddr_t arg)
}
}
}
- }
+ }
return -ENOENT;
}
-int
-RIOKillNeighbour(struct rio_info *p, caddr_t arg)
+int RIOKillNeighbour(struct rio_info *p, caddr_t arg)
{
uint Host;
uint ID;
struct Host *HostP;
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
+ rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
- if ( copyin( (int)arg, (caddr_t)&KillUnit, sizeof(KillUnit) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
+ if (copyin((int) arg, (caddr_t) & KillUnit, sizeof(KillUnit)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
p->RIOError.Error = COPYIN_FAILED;
return -EFAULT;
}
- if ( KillUnit.Link > 3 )
+ if (KillUnit.Link > 3)
return -ENXIO;
-
+
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = 0;
- CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_unit = 0;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = UFOAD;
- CmdBlkP->Packet.data[1] = KillUnit.Link;
- CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
-
- for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = UFOAD;
+ CmdBlkP->Packet.data[1] = KillUnit.Link;
+ CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
+
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
ID = 0;
HostP = &p->RIOHosts[Host];
- if ( HostP->UniqueNum == KillUnit.UniqueNum ) {
- if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link,
- CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+ if (HostP->UniqueNum == KillUnit.UniqueNum) {
+ if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
return -EIO;
}
return 0;
}
- for ( ID=0; ID < RTAS_PER_HOST; ID++ ) {
- if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) {
- CmdBlkP->Packet.dest_unit = ID+1;
- if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+ for (ID = 0; ID < RTAS_PER_HOST; ID++) {
+ if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {
+ CmdBlkP->Packet.dest_unit = ID + 1;
+ if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
return -EIO;
}
return 0;
}
}
}
- RIOFreeCmdBlk( CmdBlkP );
+ RIOFreeCmdBlk(CmdBlkP);
return -ENXIO;
}
-int
-RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
+int RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
{
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
+ rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = IWAIT;
- CmdBlkP->Packet.data[1] = Link;
- CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
-
- if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = IWAIT;
+ CmdBlkP->Packet.data[1] = Link;
+ CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
+
+ if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
return -EIO;
}
return 0;
}
-int
-RIOFoadWakeup(struct rio_info *p)
+int RIOFoadWakeup(struct rio_info *p)
{
int port;
register struct Port *PortP;
unsigned long flags;
- for ( port=0; port<RIO_PORTS; port++) {
+ for (port = 0; port < RIO_PORTS; port++) {
PortP = p->RIOPortp[port];
rio_spin_lock_irqsave(&PortP->portSem, flags);
@@ -377,16 +368,15 @@ RIOFoadWakeup(struct rio_info *p)
PortP->TxBufferOut = 0;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
}
- return(0);
+ return (0);
}
/*
** Incoming command on the COMMAND_RUP to be processed.
*/
-static int
-RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
+static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP)
{
- struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+ struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
struct Port *PortP;
struct UnixRup *UnixRupP;
ushort SysPort;
@@ -395,128 +385,101 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
ushort subCommand;
unsigned long flags;
- func_enter ();
-
-#ifdef CHECK
- CheckHost( Host );
- CheckHostP( HostP );
- CheckPacketP( PacketP );
-#endif
+ func_enter();
/*
- ** 16 port RTA note:
- ** Command rup packets coming from the RTA will have pkt->data[1] (which
- ** translates to PktCmdP->PhbNum) set to the host port number for the
- ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
- ** we can use PhbNum to get the rup number for the appropriate 8 port
- ** block (for the first block, this should be equal to 'Rup').
- */
- rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA;
+ ** 16 port RTA note:
+ ** Command rup packets coming from the RTA will have pkt->data[1] (which
+ ** translates to PktCmdP->PhbNum) set to the host port number for the
+ ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
+ ** we can use PhbNum to get the rup number for the appropriate 8 port
+ ** block (for the first block, this should be equal to 'Rup').
+ */
+ rup = RBYTE(PktCmdP->PhbNum) / (ushort) PORTS_PER_RTA;
UnixRupP = &HostP->UnixRups[rup];
- SysPort = UnixRupP->BaseSysPort +
- (RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA);
- rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
+ SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort) PORTS_PER_RTA);
+ rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
-#ifdef CHECK
- CheckRup( rup );
- CheckUnixRupP( UnixRupP );
-#endif
- if ( UnixRupP->BaseSysPort == NO_PORT ) {
- rio_dprintk (RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
- rio_dprintk (RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n",
- HostP-p->RIOHosts, HostP->Name );
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup);
-
- if ( Rup >= (ushort)MAX_RUP ) {
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n",
- HostP->Mapping[Rup].Name);
+ if (UnixRupP->BaseSysPort == NO_PORT) {
+ rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup);
+
+ if (Rup >= (ushort) MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
} else
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n",
- ('A' + Rup - MAX_RUP), HostP->Name);
-
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n",
- PacketP->dest_unit, PacketP->dest_port );
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n",
- PacketP->src_unit, PacketP->src_port );
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len );
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control);
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum );
- rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, "
- "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command );
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
+
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", PacketP->dest_unit, PacketP->dest_port);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", PacketP->src_unit, PacketP->src_port);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len, PacketP->len);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum);
+ rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command);
return TRUE;
}
-
-#ifdef CHECK
- CheckSysPort( SysPort );
-#endif
- PortP = p->RIOPortp[ SysPort ];
+ PortP = p->RIOPortp[SysPort];
rio_spin_lock_irqsave(&PortP->portSem, flags);
- switch( RBYTE(PktCmdP->Command) ) {
- case BREAK_RECEIVED:
- rio_dprintk (RIO_DEBUG_CMD, "Received a break!\n");
- /* If the current line disc. is not multi-threading and
- the current processor is not the default, reset rup_intr
- and return FALSE to ensure that the command packet is
- not freed. */
- /* Call tmgr HANGUP HERE */
- /* Fix this later when every thing works !!!! RAMRAJ */
- gs_got_break (&PortP->gs);
+ switch (RBYTE(PktCmdP->Command)) {
+ case BREAK_RECEIVED:
+ rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
+ /* If the current line disc. is not multi-threading and
+ the current processor is not the default, reset rup_intr
+ and return FALSE to ensure that the command packet is
+ not freed. */
+ /* Call tmgr HANGUP HERE */
+ /* Fix this later when every thing works !!!! RAMRAJ */
+ gs_got_break(&PortP->gs);
+ break;
+
+ case COMPLETE:
+ rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", RBYTE(PktCmdP->PhbNum), HostP - p->RIOHosts);
+ subCommand = 1;
+ switch (RBYTE(PktCmdP->SubCommand)) {
+ case MEMDUMP:
+ rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr));
break;
+ case READ_REGISTER:
+ rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr));
+ p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);
+ break;
+ default:
+ subCommand = 0;
+ break;
+ }
+ if (subCommand)
+ break;
+ rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", RBYTE(PktCmdP->PortStatus), PortP->PortState);
+ if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");
+ PortP->PortState = RBYTE(PktCmdP->PortStatus);
+ /* What should we do here ...
+ wakeup( &PortP->PortState );
+ */
+ } else
+ rio_dprintk(RIO_DEBUG_CMD, "No change\n");
- case COMPLETE:
- rio_dprintk (RIO_DEBUG_CMD, "Command complete on phb %d host %d\n",
- RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts);
- subCommand = 1;
- switch (RBYTE(PktCmdP->SubCommand)) {
- case MEMDUMP :
- rio_dprintk (RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n",
- RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr));
- break;
- case READ_REGISTER :
- rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr));
- p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);
- break;
- default :
- subCommand = 0;
- break;
- }
- if (subCommand)
- break;
- rio_dprintk (RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n",
- RBYTE(PktCmdP->PortStatus),PortP->PortState);
- if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
- rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n");
- PortP->PortState = RBYTE(PktCmdP->PortStatus);
- /* What should we do here ...
- wakeup( &PortP->PortState );
- */
- } else
- rio_dprintk (RIO_DEBUG_CMD, "No change\n");
-
- /* FALLTHROUGH */
- case MODEM_STATUS:
+ /* FALLTHROUGH */
+ case MODEM_STATUS:
+ /*
+ ** Knock out the tbusy and tstop bits, as these are not relevant
+ ** to the check for modem status change (they're just there because
+ ** it's a convenient place to put them!).
+ */
+ ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);
+ if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
/*
- ** Knock out the tbusy and tstop bits, as these are not relevant
- ** to the check for modem status change (they're just there because
- ** it's a convenient place to put them!).
- */
- ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);
- if ((PortP->ModemState & MSVR1_HOST) ==
- (ReportedModemStatus & MSVR1_HOST)) {
- rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
- /*
- ** Update ModemState just in case tbusy or tstop states have
- ** changed.
- */
- PortP->ModemState = ReportedModemStatus;
- }
- else {
- rio_dprintk (RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n",
- PortP->ModemState, ReportedModemStatus);
- PortP->ModemState = ReportedModemStatus;
+ ** Update ModemState just in case tbusy or tstop states have
+ ** changed.
+ */
+ PortP->ModemState = ReportedModemStatus;
+ } else {
+ rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);
+ PortP->ModemState = ReportedModemStatus;
#ifdef MODEM_SUPPORT
- if ( PortP->Mapped ) {
+ if (PortP->Mapped) {
/***********************************************************\
*************************************************************
*** ***
@@ -525,68 +488,67 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
*************************************************************
\***********************************************************/
/*
- ** If the device is a modem, then check the modem
- ** carrier.
- */
+ ** If the device is a modem, then check the modem
+ ** carrier.
+ */
if (PortP->gs.tty == NULL)
break;
if (PortP->gs.tty->termios == NULL)
break;
-
- if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) &&
- ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) {
- rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n");
- /*
- ** Is there a carrier?
- */
- if ( PortP->ModemState & MSVR1_CD ) {
- /*
- ** Has carrier just appeared?
- */
+ if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) {
+
+ rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n");
+ /*
+ ** Is there a carrier?
+ */
+ if (PortP->ModemState & MSVR1_CD) {
+ /*
+ ** Has carrier just appeared?
+ */
if (!(PortP->State & RIO_CARR_ON)) {
- rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n");
PortP->State |= RIO_CARR_ON;
- /*
- ** wakeup anyone in WOPEN
- */
- if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) )
- wake_up_interruptible (&PortP->gs.open_wait);
+ /*
+ ** wakeup anyone in WOPEN
+ */
+ if (PortP->State & (PORT_ISOPEN | RIO_WOPEN))
+ wake_up_interruptible(&PortP->gs.open_wait);
#ifdef STATS
- PortP->Stat.ModemOnCnt++;
+ PortP->Stat.ModemOnCnt++;
#endif
- }
+ }
} else {
- /*
- ** Has carrier just dropped?
- */
+ /*
+ ** Has carrier just dropped?
+ */
if (PortP->State & RIO_CARR_ON) {
- if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN))
- tty_hangup (PortP->gs.tty);
+ if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN))
+ tty_hangup(PortP->gs.tty);
PortP->State &= ~RIO_CARR_ON;
- rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n");
#ifdef STATS
- PortP->Stat.ModemOffCnt++;
+ PortP->Stat.ModemOffCnt++;
#endif
+ }
+ }
+ }
}
- }
- }
- }
#endif
- }
- break;
+ }
+ break;
- default:
- rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n",
- RBYTE(PktCmdP->Command),HostP-p->RIOHosts);
- break;
+ default:
+ rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", RBYTE(PktCmdP->Command), HostP - p->RIOHosts);
+ break;
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- func_exit ();
+ func_exit();
return TRUE;
}
+
/*
** The command mechanism:
** Each rup has a chain of commands associated with it.
@@ -600,12 +562,11 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
/*
** Allocate an empty command block.
*/
-struct CmdBlk *
-RIOGetCmdBlk(void)
+struct CmdBlk *RIOGetCmdBlk(void)
{
struct CmdBlk *CmdBlkP;
- CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk));
+ CmdBlkP = (struct CmdBlk *) sysbrk(sizeof(struct CmdBlk));
if (CmdBlkP)
bzero(CmdBlkP, sizeof(struct CmdBlk));
@@ -615,31 +576,24 @@ RIOGetCmdBlk(void)
/*
** Return a block to the head of the free list.
*/
-void
-RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
+void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
{
- sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
+ sysfree((void *) CmdBlkP, sizeof(struct CmdBlk));
}
/*
** attach a command block to the list of commands to be performed for
** a given rup.
*/
-int
-RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
+int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
{
struct CmdBlk **Base;
struct UnixRup *UnixRupP;
unsigned long flags;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckRup( Rup );
- CheckCmdBlkP( CmdBlkP );
-#endif
- if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) {
- rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup);
- RIOFreeCmdBlk( CmdBlkP );
+ if (Rup >= (ushort) (MAX_RUP + LINKS_PER_UNIT)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
+ RIOFreeCmdBlk(CmdBlkP);
return RIO_FAIL;
}
@@ -648,57 +602,52 @@ RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
/*
- ** If the RUP is currently inactive, then put the request
- ** straight on the RUP....
- */
- if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) &&
- (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) &&
- (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP)
- :TRUE)) {
- rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n",
- CmdBlkP->Packet.data[0]);
+ ** If the RUP is currently inactive, then put the request
+ ** straight on the RUP....
+ */
+ if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
+ : TRUE)) {
+ rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]);
/*
- ** Whammy! blat that pack!
- */
- HostP->Copy( (caddr_t)&CmdBlkP->Packet,
- RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) );
+ ** Whammy! blat that pack!
+ */
+ HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
/*
- ** place command packet on the pending position.
- */
+ ** place command packet on the pending position.
+ */
UnixRupP->CmdPendingP = CmdBlkP;
/*
- ** set the command register
- */
- WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY);
+ ** set the command register
+ */
+ WWORD(UnixRupP->RupP->txcontrol, TX_PACKET_READY);
rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
return RIO_SUCCESS;
}
- rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n");
+ rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n");
- if ( UnixRupP->CmdsWaitingP != NULL)
- rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n");
- if ( UnixRupP->CmdPendingP != NULL )
- rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n");
- if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE )
- rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
+ if (UnixRupP->CmdsWaitingP != NULL)
+ rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n");
+ if (UnixRupP->CmdPendingP != NULL)
+ rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n");
+ if (RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE)
+ rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
Base = &UnixRupP->CmdsWaitingP;
- rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base);
+ rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base);
- while ( *Base ) {
- rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base));
+ while (*Base) {
+ rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int) (*Base));
Base = &((*Base)->NextP);
- rio_dprintk (RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n",
- (int)CmdBlkP,(int)Base);
+ rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base);
}
- rio_dprintk (RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base);
+ rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base);
*Base = CmdBlkP;
@@ -713,8 +662,7 @@ RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
** Here we go - if there is an empty rup, fill it!
** must be called at splrio() or higher.
*/
-void
-RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
+void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
{
register struct CmdBlk *CmdBlkP;
register struct UnixRup *UnixRupP;
@@ -723,262 +671,234 @@ RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
unsigned long flags;
- Rup = MAX_RUP+LINKS_PER_UNIT;
+ Rup = MAX_RUP + LINKS_PER_UNIT;
- do { /* do this loop for each RUP */
+ do { /* do this loop for each RUP */
/*
- ** locate the rup we are processing & lock it
- */
+ ** locate the rup we are processing & lock it
+ */
UnixRupP = &HostP->UnixRups[--Rup];
spin_lock_irqsave(&UnixRupP->RupLock, flags);
/*
- ** First check for incoming commands:
- */
- if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) {
+ ** First check for incoming commands:
+ */
+ if (RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
int FreeMe;
- PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt));
+ PacketP = (PKT *) RIO_PTR(HostP->Caddr, RWORD(UnixRupP->RupP->rxpkt));
- ShowPacket( DBG_CMD, PacketP );
+ ShowPacket(DBG_CMD, PacketP);
- switch ( RBYTE(PacketP->dest_port) ) {
- case BOOT_RUP:
- rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n",
- RBYTE(PacketP->len) & 0x80 ? "Command":"Data",
- RBYTE(PacketP->data[0]));
- rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- FreeMe= RIOBootRup(p, Rup,HostP,PacketP);
- rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
- break;
+ switch (RBYTE(PacketP->dest_port)) {
+ case BOOT_RUP:
+ rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", RBYTE(PacketP->len) & 0x80 ? "Command" : "Data", RBYTE(PacketP->data[0]));
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
+ rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+ break;
- case COMMAND_RUP:
- /*
- ** Free the RUP lock as loss of carrier causes a
- ** ttyflush which will (eventually) call another
- ** routine that uses the RUP lock.
- */
- rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- FreeMe= RIOCommandRup(p, Rup,HostP,PacketP);
- if (PacketP->data[5] == MEMDUMP) {
- rio_dprintk (RIO_DEBUG_CMD, "Memdump from 0x%x complete\n",
- *(ushort *) &(PacketP->data[6]));
- HostP->Copy( (caddr_t)&(PacketP->data[8]),
- (caddr_t)p->RIOMemDump, 32 );
- }
- rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
- break;
+ case COMMAND_RUP:
+ /*
+ ** Free the RUP lock as loss of carrier causes a
+ ** ttyflush which will (eventually) call another
+ ** routine that uses the RUP lock.
+ */
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
+ if (PacketP->data[5] == MEMDUMP) {
+ rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", *(ushort *) & (PacketP->data[6]));
+ HostP->Copy((caddr_t) & (PacketP->data[8]), (caddr_t) p->RIOMemDump, 32);
+ }
+ rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+ break;
- case ROUTE_RUP:
- rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags);
- FreeMe = RIORouteRup(p, Rup, HostP, PacketP );
- rio_spin_lock_irqsave( &UnixRupP->RupLock, flags );
- break;
+ case ROUTE_RUP:
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
+ rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+ break;
- default:
- rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port));
- FreeMe = 1;
- break;
+ default:
+ rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port));
+ FreeMe = 1;
+ break;
}
- if ( FreeMe ) {
- rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n");
- put_free_end(HostP,PacketP);
+ if (FreeMe) {
+ rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
+ put_free_end(HostP, PacketP);
- WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE);
+ WWORD(UnixRupP->RupP->rxcontrol, RX_RUP_INACTIVE);
- if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) {
- rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup);
- WWORD(UnixRupP->RupP->handshake,
- PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+ if (RWORD(UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
+ rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
+ WWORD(UnixRupP->RupP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET);
}
}
}
/*
- ** IF a command was running on the port,
- ** and it has completed, then tidy it up.
- */
- if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */
- (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+ ** IF a command was running on the port,
+ ** and it has completed, then tidy it up.
+ */
+ if ((CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */
+ (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
/*
- ** we are idle.
- ** there is a command in pending.
- ** Therefore, this command has finished.
- ** So, wakeup whoever is waiting for it (and tell them
- ** what happened).
- */
- if ( CmdBlkP->Packet.dest_port == BOOT_RUP )
- rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n",
- CmdBlkP->Packet.len & 0x80 ? "Command":"Data",
- CmdBlkP->Packet.data[0]);
-
- rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP);
+ ** we are idle.
+ ** there is a command in pending.
+ ** Therefore, this command has finished.
+ ** So, wakeup whoever is waiting for it (and tell them
+ ** what happened).
+ */
+ if (CmdBlkP->Packet.dest_port == BOOT_RUP)
+ rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);
+
+ rio_dprintk(RIO_DEBUG_CMD, "Command 0x%x completed\n", (int) CmdBlkP);
/*
- ** Clear the Rup lock to prevent mutual exclusion.
- */
- if ( CmdBlkP->PostFuncP ) {
+ ** Clear the Rup lock to prevent mutual exclusion.
+ */
+ if (CmdBlkP->PostFuncP) {
rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP);
+ (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
}
/*
- ** ....clear the pending flag....
- */
+ ** ....clear the pending flag....
+ */
UnixRupP->CmdPendingP = NULL;
/*
- ** ....and return the command block to the freelist.
- */
- RIOFreeCmdBlk( CmdBlkP );
+ ** ....and return the command block to the freelist.
+ */
+ RIOFreeCmdBlk(CmdBlkP);
}
/*
- ** If there is a command for this rup, and the rup
- ** is idle, then process the command
- */
- if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */
- (UnixRupP->CmdPendingP == NULL) &&
- (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+ ** If there is a command for this rup, and the rup
+ ** is idle, then process the command
+ */
+ if ((CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */
+ (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
/*
- ** if the pre-function is non-zero, call it.
- ** If it returns RIO_FAIL then don't
- ** send this command yet!
- */
-#ifdef CHECK
- CheckCmdBlkP (CmdBlkP);
-#endif
- if ( !(CmdBlkP->PreFuncP ?
- (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
- rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP);
- }
- else {
- rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n",
- (int)CmdBlkP, CmdBlkP->Packet.data[0]);
+ ** if the pre-function is non-zero, call it.
+ ** If it returns RIO_FAIL then don't
+ ** send this command yet!
+ */
+ if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%x\n", (int) CmdBlkP);
+ } else {
+ rio_dprintk(RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", (int) CmdBlkP, CmdBlkP->Packet.data[0]);
/*
- ** Whammy! blat that pack!
- */
-#ifdef CHECK
- CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt));
-#endif
- HostP->Copy( (caddr_t)&CmdBlkP->Packet,
- RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
+ ** Whammy! blat that pack!
+ */
+ HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
/*
- ** remove the command from the rup command queue...
- */
+ ** remove the command from the rup command queue...
+ */
UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
/*
- ** ...and place it on the pending position.
- */
+ ** ...and place it on the pending position.
+ */
UnixRupP->CmdPendingP = CmdBlkP;
/*
- ** set the command register
- */
- WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY);
+ ** set the command register
+ */
+ WWORD(UnixRupP->RupP->txcontrol, TX_PACKET_READY);
/*
- ** the command block will be freed
- ** when the command has been processed.
- */
+ ** the command block will be freed
+ ** when the command has been processed.
+ */
}
}
spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- } while ( Rup );
+ } while (Rup);
}
-int
-RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
+int RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
{
- struct Port * PortP = (struct Port *)iPortP;
+ struct Port *PortP = (struct Port *) iPortP;
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
-#ifdef CHECK
- CheckPortP( PortP );
-#endif
PortP->WflushFlag++;
PortP->MagicFlags |= MAGIC_FLUSH;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return RIOUnUse( iPortP, CmdBlkP );
+ return RIOUnUse(iPortP, CmdBlkP);
}
-int
-RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
+int RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
{
- struct Port * PortP = (struct Port *)iPortP;
+ struct Port *PortP = (struct Port *) iPortP;
PKT *PacketP;
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
- while ( can_remove_receive(&PacketP, PortP) ) {
+ while (can_remove_receive(&PacketP, PortP)) {
remove_receive(PortP);
- ShowPacket(DBG_PROC, PacketP );
- put_free_end( PortP->HostP, PacketP );
+ ShowPacket(DBG_PROC, PacketP);
+ put_free_end(PortP->HostP, PacketP);
}
- if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) {
+ if (RWORD(PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) {
/*
- ** MAGIC! (Basically, handshake the RX buffer, so that
- ** the RTAs upstream can be re-enabled.)
- */
- rio_dprintk (RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
- WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+ ** MAGIC! (Basically, handshake the RX buffer, so that
+ ** the RTAs upstream can be re-enabled.)
+ */
+ rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
+ WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET);
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return RIOUnUse( iPortP, CmdBlkP );
+ return RIOUnUse(iPortP, CmdBlkP);
}
-int
-RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
+int RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
{
- struct Port * PortP = (struct Port *)iPortP;
+ struct Port *PortP = (struct Port *) iPortP;
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
-#ifdef CHECK
- CheckPortP( PortP );
-#endif
- rio_dprintk (RIO_DEBUG_CMD, "Decrement in use count for port\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
if (PortP->InUse) {
- if ( --PortP->InUse != NOT_INUSE ) {
+ if (--PortP->InUse != NOT_INUSE) {
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return 0;
}
}
/*
- ** While PortP->InUse is set (i.e. a preemptive command has been sent to
- ** the RTA and is awaiting completion), any transmit data is prevented from
- ** being transferred from the write queue into the transmit packets
- ** (add_transmit) and no furthur transmit interrupt will be sent for that
- ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
- ** twice a second as a saftey measure). This was the case when kermit was
- ** used to send data into a RIO port. After each packet was sent, TCFLSH
- ** was called to flush the read queue preemptively. PortP->InUse was
- ** incremented, thereby blocking the 6 byte acknowledgement packet
- ** transmitted back. This acknowledgment hung around for 500ms before
- ** being sent, thus reducing input performance substantially!.
- ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
- ** hanging around in the transmit buffer is sent immediately.
- */
+ ** While PortP->InUse is set (i.e. a preemptive command has been sent to
+ ** the RTA and is awaiting completion), any transmit data is prevented from
+ ** being transferred from the write queue into the transmit packets
+ ** (add_transmit) and no furthur transmit interrupt will be sent for that
+ ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
+ ** twice a second as a saftey measure). This was the case when kermit was
+ ** used to send data into a RIO port. After each packet was sent, TCFLSH
+ ** was called to flush the read queue preemptively. PortP->InUse was
+ ** incremented, thereby blocking the 6 byte acknowledgement packet
+ ** transmitted back. This acknowledgment hung around for 500ms before
+ ** being sent, thus reducing input performance substantially!.
+ ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
+ ** hanging around in the transmit buffer is sent immediately.
+ */
WWORD(PortP->HostP->ParmMapP->tx_intr, 1);
/* What to do here ..
- wakeup( (caddr_t)&(PortP->InUse) );
- */
+ wakeup( (caddr_t)&(PortP->InUse) );
+ */
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return 0;
}
-void
-ShowPacket(uint Flags, struct PKT *PacketP)
+void ShowPacket(uint Flags, struct PKT *PacketP)
{
}
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index b4d1a23e27e4..fcf18a061228 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -82,16 +82,16 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3";
#include "rioioctl.h"
-static struct LpbReq LpbReq;
-static struct RupReq RupReq;
-static struct PortReq PortReq;
-static struct HostReq HostReq;
+static struct LpbReq LpbReq;
+static struct RupReq RupReq;
+static struct PortReq PortReq;
+static struct HostReq HostReq;
static struct HostDpRam HostDpRam;
static struct DebugCtrl DebugCtrl;
-static struct Map MapEnt;
+static struct Map MapEnt;
static struct PortSetup PortSetup;
-static struct DownLoad DownLoad;
-static struct SendPack SendPack;
+static struct DownLoad DownLoad;
+static struct SendPack SendPack;
/* static struct StreamInfo StreamInfo; */
/* static char modemtable[RIO_PORTS]; */
static struct SpecialRupCmd SpecialRupCmd;
@@ -99,18 +99,18 @@ static struct PortParams PortParams;
static struct portStats portStats;
static struct SubCmdStruct {
- ushort Host;
- ushort Rup;
- ushort Port;
- ushort Addr;
+ ushort Host;
+ ushort Rup;
+ ushort Port;
+ ushort Addr;
} SubCmd;
struct PortTty {
- uint port;
- struct ttystatics Tty;
+ uint port;
+ struct ttystatics Tty;
};
-static struct PortTty PortTty;
+static struct PortTty PortTty;
typedef struct ttystatics TERMIO;
/*
@@ -121,267 +121,259 @@ typedef struct ttystatics TERMIO;
** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
** process to bog off.
*/
-static int
-(*RIOBootTable[MAX_PRODUCT])(struct rio_info *, struct DownLoad *) =
-{
-/* 0 */ RIOBootCodeHOST, /* Host Card */
-/* 1 */ RIOBootCodeRTA, /* RTA */
+static int
+ (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
+ /* 0 */ RIOBootCodeHOST,
+ /* Host Card */
+ /* 1 */ RIOBootCodeRTA,
+ /* RTA */
};
#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
-int copyin (int arg, caddr_t dp, int siz)
+int copyin(int arg, caddr_t dp, int siz)
{
- int rv;
+ int rv;
- rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *)arg, dp);
- rv = copy_from_user (dp, (void *)arg, siz);
- if (rv) return COPYFAIL;
- else return rv;
+ rio_dprintk(RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *) arg, dp);
+ rv = copy_from_user(dp, (void *) arg, siz);
+ if (rv)
+ return COPYFAIL;
+ else
+ return rv;
}
-static int copyout (caddr_t dp, int arg, int siz)
+static int copyout(caddr_t dp, int arg, int siz)
{
- int rv;
+ int rv;
- rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *)arg, dp);
- rv = copy_to_user ((void *)arg, dp, siz);
- if (rv) return COPYFAIL;
- else return rv;
+ rio_dprintk(RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *) arg, dp);
+ rv = copy_to_user((void *) arg, dp, siz);
+ if (rv)
+ return COPYFAIL;
+ else
+ return rv;
}
-int
-riocontrol(p, dev, cmd, arg, su)
-struct rio_info * p;
-dev_t dev;
-int cmd;
-caddr_t arg;
-int su;
+int riocontrol(p, dev, cmd, arg, su)
+struct rio_info *p;
+dev_t dev;
+int cmd;
+caddr_t arg;
+int su;
{
- uint Host; /* leave me unsigned! */
- uint port; /* and me! */
- struct Host *HostP;
- ushort loop;
- int Entry;
- struct Port *PortP;
- PKT *PacketP;
- int retval = 0;
+ uint Host; /* leave me unsigned! */
+ uint port; /* and me! */
+ struct Host *HostP;
+ ushort loop;
+ int Entry;
+ struct Port *PortP;
+ PKT *PacketP;
+ int retval = 0;
unsigned long flags;
-
- func_enter ();
-
+
+ func_enter();
+
/* Confuse the compiler to think that we've initialized these */
- Host=0;
+ Host = 0;
PortP = NULL;
- rio_dprintk (RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int)arg);
+ rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int) arg);
switch (cmd) {
/*
- ** RIO_SET_TIMER
- **
- ** Change the value of the host card interrupt timer.
- ** If the host card number is -1 then all host cards are changed
- ** otherwise just the specified host card will be changed.
- */
- case RIO_SET_TIMER:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint)arg);
- {
- int host, value;
- host = (uint)arg >> 16;
- value = (uint)arg & 0x0000ffff;
- if (host == -1) {
- for (host = 0; host < p->RIONumHosts; host++) {
- if (p->RIOHosts[host].Flags == RC_RUNNING) {
- WWORD(p->RIOHosts[host].ParmMapP->timer , value);
- }
- }
- } else if (host >= p->RIONumHosts) {
- return -EINVAL;
- } else {
- if ( p->RIOHosts[host].Flags == RC_RUNNING ) {
- WWORD(p->RIOHosts[host].ParmMapP->timer , value);
+ ** RIO_SET_TIMER
+ **
+ ** Change the value of the host card interrupt timer.
+ ** If the host card number is -1 then all host cards are changed
+ ** otherwise just the specified host card will be changed.
+ */
+ case RIO_SET_TIMER:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint) arg);
+ {
+ int host, value;
+ host = (uint) arg >> 16;
+ value = (uint) arg & 0x0000ffff;
+ if (host == -1) {
+ for (host = 0; host < p->RIONumHosts; host++) {
+ if (p->RIOHosts[host].Flags == RC_RUNNING) {
+ WWORD(p->RIOHosts[host].ParmMapP->timer, value);
}
}
- }
- return 0;
-
- case RIO_IDENTIFY_DRIVER:
- /*
- ** 15.10.1998 ARG - ESIL 0760 part fix
- ** Added driver ident string output.
- **
-#ifndef __THIS_RELEASE__
-#warning Driver Version string not defined !
-#endif
- cprintf("%s %s %s %s\n",
- RIO_DRV_STR,
- __THIS_RELEASE__,
- __DATE__, __TIME__ );
-
- return 0;
-
- case RIO_DISPLAY_HOST_CFG:
- **
- ** 15.10.1998 ARG - ESIL 0760 part fix
- ** Added driver host card ident string output.
- **
- ** Note that the only types currently supported
- ** are ISA and PCI. Also this driver does not
- ** (yet) distinguish between the Old PCI card
- ** and the Jet PCI card. In fact I think this
- ** driver only supports JET PCI !
- **
-
- for (Host = 0; Host < p->RIONumHosts; Host++)
- {
- HostP = &(p->RIOHosts[Host]);
-
- switch ( HostP->Type )
- {
- case RIO_AT :
- strcpy( host_type, RIO_AT_HOST_STR );
- break;
-
- case RIO_PCI :
- strcpy( host_type, RIO_PCI_HOST_STR );
- break;
-
- default :
- strcpy( host_type, "Unknown" );
- break;
+ } else if (host >= p->RIONumHosts) {
+ return -EINVAL;
+ } else {
+ if (p->RIOHosts[host].Flags == RC_RUNNING) {
+ WWORD(p->RIOHosts[host].ParmMapP->timer, value);
}
+ }
+ }
+ return 0;
- cprintf(
- "RIO Host %d - Type:%s Addr:%X IRQ:%d\n",
- Host, host_type,
- (uint)HostP->PaddrP,
- (int)HostP->Ivec - 32 );
+ case RIO_IDENTIFY_DRIVER:
+ /*
+ ** 15.10.1998 ARG - ESIL 0760 part fix
+ ** Added driver ident string output.
+ **
+ #ifndef __THIS_RELEASE__
+ #warning Driver Version string not defined !
+ #endif
+ cprintf("%s %s %s %s\n",
+ RIO_DRV_STR,
+ __THIS_RELEASE__,
+ __DATE__, __TIME__ );
+
+ return 0;
+
+ case RIO_DISPLAY_HOST_CFG:
+ **
+ ** 15.10.1998 ARG - ESIL 0760 part fix
+ ** Added driver host card ident string output.
+ **
+ ** Note that the only types currently supported
+ ** are ISA and PCI. Also this driver does not
+ ** (yet) distinguish between the Old PCI card
+ ** and the Jet PCI card. In fact I think this
+ ** driver only supports JET PCI !
+ **
+
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ {
+ HostP = &(p->RIOHosts[Host]);
+
+ switch ( HostP->Type )
+ {
+ case RIO_AT :
+ strcpy( host_type, RIO_AT_HOST_STR );
+ break;
+
+ case RIO_PCI :
+ strcpy( host_type, RIO_PCI_HOST_STR );
+ break;
+
+ default :
+ strcpy( host_type, "Unknown" );
+ break;
+ }
+
+ cprintf(
+ "RIO Host %d - Type:%s Addr:%X IRQ:%d\n",
+ Host, host_type,
+ (uint)HostP->PaddrP,
+ (int)HostP->Ivec - 32 );
+ }
+ return 0;
+ **
+ */
+
+ case RIO_FOAD_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
+ return RIOCommandRta(p, (uint) arg, RIOFoadRta);
+
+ case RIO_ZOMBIE_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
+ return RIOCommandRta(p, (uint) arg, RIOZombieRta);
+
+ case RIO_IDENTIFY_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
+ return RIOIdentifyRta(p, arg);
+
+ case RIO_KILL_NEIGHBOUR:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
+ return RIOKillNeighbour(p, arg);
+
+ case SPECIAL_RUP_CMD:
+ {
+ struct CmdBlk *CmdBlkP;
+
+ rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
+ if (copyin((int) arg, (caddr_t) & SpecialRupCmd, sizeof(SpecialRupCmd)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ CmdBlkP = RIOGetCmdBlk();
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
+ return -ENXIO;
+ }
+ CmdBlkP->Packet = SpecialRupCmd.Packet;
+ if (SpecialRupCmd.Host >= p->RIONumHosts)
+ SpecialRupCmd.Host = 0;
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
+ if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
+ cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n");
}
return 0;
- **
- */
-
- case RIO_FOAD_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
- return RIOCommandRta(p, (uint)arg, RIOFoadRta);
-
- case RIO_ZOMBIE_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
- return RIOCommandRta(p, (uint)arg, RIOZombieRta);
-
- case RIO_IDENTIFY_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
- return RIOIdentifyRta(p, arg);
-
- case RIO_KILL_NEIGHBOUR:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
- return RIOKillNeighbour(p, arg);
-
- case SPECIAL_RUP_CMD:
- {
- struct CmdBlk *CmdBlkP;
-
- rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
- if (copyin((int)arg, (caddr_t)&SpecialRupCmd,
- sizeof(SpecialRupCmd)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
- return -ENXIO;
- }
- CmdBlkP->Packet = SpecialRupCmd.Packet;
- if ( SpecialRupCmd.Host >= p->RIONumHosts )
- SpecialRupCmd.Host = 0;
- rio_dprintk (RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n",
- SpecialRupCmd.Host, SpecialRupCmd.RupNum);
- if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host],
- SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
- cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n");
- }
- return 0;
- }
-
- case RIO_DEBUG_MEM:
-#ifdef DEBUG_MEM_SUPPORT
-RIO_DEBUG_CTRL, if (su)
- return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg);
- else
-#endif
- return -EPERM;
-
- case RIO_ALL_MODEM:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
- p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
- return -EINVAL;
+ }
- case RIO_GET_TABLE:
- /*
- ** Read the routing table from the device driver to user space
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
+ case RIO_DEBUG_MEM:
+ return -EPERM;
- if ((retval = RIOApel(p)) != 0)
- return retval;
+ case RIO_ALL_MODEM:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
+ p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+ return -EINVAL;
- if (copyout((caddr_t)p->RIOConnectTable, (int)arg,
- TOTAL_MAP_ENTRIES*sizeof(struct Map)) == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
+ case RIO_GET_TABLE:
+ /*
+ ** Read the routing table from the device driver to user space
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
+
+ if ((retval = RIOApel(p)) != 0)
+ return retval;
+
+ if (copyout((caddr_t) p->RIOConnectTable, (int) arg, TOTAL_MAP_ENTRIES * sizeof(struct Map)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+
+ {
+ int entry;
+ rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
+ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+ if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
+ continue;
+
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
+ }
+ p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */
+ return 0;
- {
- int entry;
- rio_dprintk (RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
- for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
- {
- if ((p->RIOConnectTable[entry].ID == 0) &&
- (p->RIOConnectTable[entry].HostUniqueNum == 0) &&
- (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue;
-
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name );
- }
- rio_dprintk (RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
- }
- p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */
- return 0;
-
- case RIO_PUT_TABLE:
- /*
- ** Write the routing table to the device driver from user space
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
-
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if ( copyin((int)arg, (caddr_t)&p->RIOConnectTable[0],
- TOTAL_MAP_ENTRIES*sizeof(struct Map) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
+ case RIO_PUT_TABLE:
+ /*
+ ** Write the routing table to the device driver from user space
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & p->RIOConnectTable[0], TOTAL_MAP_ENTRIES * sizeof(struct Map)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
/*
***********************************
{
@@ -409,1353 +401,1144 @@ RIO_DEBUG_CTRL, if (su)
}
***********************************
*/
- return RIONewTable(p);
-
- case RIO_GET_BINDINGS :
- /*
- ** Send bindings table, containing unique numbers of RTAs owned
- ** by this system to user space
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
-
- if ( !su )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyout((caddr_t) p->RIOBindTab, (int)arg,
- (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
+ return RIONewTable(p);
- case RIO_PUT_BINDINGS :
+ case RIO_GET_BINDINGS:
+ /*
+ ** Send bindings table, containing unique numbers of RTAs owned
+ ** by this system to user space
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyout((caddr_t) p->RIOBindTab, (int) arg, (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_PUT_BINDINGS:
+ /*
+ ** Receive a bindings table, containing unique numbers of RTAs owned
+ ** by this system
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & p->RIOBindTab[0], (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_BIND_RTA:
+ {
+ int EmptySlot = -1;
/*
- ** Receive a bindings table, containing unique numbers of RTAs owned
- ** by this system
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
-
- if ( !su )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyin((int)arg, (caddr_t)&p->RIOBindTab[0],
- (sizeof(ulong) * MAX_RTA_BINDINGS))==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_BIND_RTA :
- {
- int EmptySlot = -1;
- /*
- ** Bind this RTA to host, so that it will be booted by
- ** host in 'boot owned RTAs' mode.
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
-
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
- if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
- EmptySlot = Entry;
- else if (p->RIOBindTab[Entry] == (int) arg) {
- /*
- ** Already exists - delete
- */
- p->RIOBindTab[Entry] = 0L;
- rio_dprintk (RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n",
- (int) arg);
- return 0;
- }
- }
+ ** Bind this RTA to host, so that it will be booted by
+ ** host in 'boot owned RTAs' mode.
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
+ if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
+ EmptySlot = Entry;
+ else if (p->RIOBindTab[Entry] == (int) arg) {
/*
- ** Dosen't exist - add
- */
- if (EmptySlot != -1) {
- p->RIOBindTab[EmptySlot] = (int) arg;
- rio_dprintk (RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n",
- (int) arg);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n",
- (int) arg);
- return -ENOMEM;
- }
+ ** Already exists - delete
+ */
+ p->RIOBindTab[Entry] = 0L;
+ rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n", (int) arg);
return 0;
}
-
- case RIO_RESUME :
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME\n");
- port = (uint) arg;
- if ((port < 0) || (port > 511)) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- PortP = p->RIOPortp[port];
- if (!PortP->Mapped) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
- p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
- return -EINVAL;
- }
- if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
- return -EINVAL;
- }
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) ==
- RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EBUSY;
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
- PortP->State |= RIO_BUSY;
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return retval;
-
- case RIO_ASSIGN_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
- == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return RIOAssignRta(p, &MapEnt);
-
- case RIO_CHANGE_NAME:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
+ }
+ /*
+ ** Dosen't exist - add
+ */
+ if (EmptySlot != -1) {
+ p->RIOBindTab[EmptySlot] = (int) arg;
+ rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n", (int) arg);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", (int) arg);
+ return -ENOMEM;
+ }
+ return 0;
+ }
+
+ case RIO_RESUME:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
+ port = (uint) arg;
+ if ((port < 0) || (port > 511)) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ PortP = p->RIOPortp[port];
+ if (!PortP->Mapped) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
+ p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+ return -EINVAL;
+ }
+ if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
+ return -EINVAL;
+ }
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
+ PortP->State |= RIO_BUSY;
+ }
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_ASSIGN_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt))
+ == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return RIOAssignRta(p, &MapEnt);
+
+ case RIO_CHANGE_NAME:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt))
+ == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return RIOChangeName(p, &MapEnt);
+
+ case RIO_DELETE_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt))
+ == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return RIODeleteRta(p, &MapEnt);
+
+ case RIO_QUICK_CHECK:
+ /*
+ ** 09.12.1998 ARG - ESIL 0776 part fix
+ ** A customer was using this to get the RTAs
+ ** connect/disconnect status.
+ ** RIOConCon() had been botched use RIOHalted
+ ** to keep track of RTA connections and
+ ** disconnections. That has been changed and
+ ** RIORtaDisCons in the rio_info struct now
+ ** does the job. So we need to return the value
+ ** of RIORtaCons instead of RIOHalted.
+ **
+ if (copyout((caddr_t)&p->RIOHalted,(int)arg,
+ sizeof(uint))==COPYFAIL) {
+ **
+ */
+
+ if (copyout((caddr_t) & p->RIORtaDisCons, (int) arg, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_LAST_ERROR:
+ if (copyout((caddr_t) & p->RIOError, (int) arg, sizeof(struct Error)) == COPYFAIL)
+ return -EFAULT;
+ return 0;
+
+ case RIO_GET_LOG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
+ return -EINVAL;
+
+ case RIO_GET_MODTYPE:
+ if (copyin((int) arg, (caddr_t) & port, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
+ if (port < 0 || port > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ PortP = (p->RIOPortp[port]);
+ if (!PortP->Mapped) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
+ p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+ return -EINVAL;
+ }
+ /*
+ ** Return module type of port
+ */
+ port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
+ if (copyout((caddr_t) & port, (int) arg, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return (0);
+ /*
+ ** 02.03.1999 ARG - ESIL 0820 fix
+ ** We are no longer using "Boot Mode", so these ioctls
+ ** are not required :
+ **
+ case RIO_GET_BOOT_MODE :
+ rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode));
+ **
+ ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE
+ **
+ if (copyout((caddr_t)&p->RIOBootMode, (int)arg,
+ sizeof(p->RIOBootMode)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return(0);
+
+ case RIO_SET_BOOT_MODE :
+ p->RIOBootMode = (uint) arg;
+ rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode));
+ return(0);
+ **
+ ** End ESIL 0820 fix
+ */
+
+ case RIO_BLOCK_OPENS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
+ for (Entry = 0; Entry < RIO_PORTS; Entry++) {
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ p->RIOPortp[Entry]->WaitUntilBooted = 1;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ }
+ return 0;
+
+ case RIO_SETUP_PORTS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
+ if (copyin((int) arg, (caddr_t) & PortSetup, sizeof(PortSetup))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
+ return -EFAULT;
+ }
+ if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
+ return -ENXIO;
+ }
+ if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
+ p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
+ return -EINVAL;
+ }
+ if (!p->RIOPortp) {
+ cprintf("No p->RIOPortp array!\n");
+ rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
+ return -EIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
+ for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
+ rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
+ rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
+ return retval;
+
+ case RIO_GET_PORT_SETUP:
+ rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
+ if (copyin((int) arg, (caddr_t) & PortSetup, sizeof(PortSetup))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortSetup.From >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+
+ port = PortSetup.To = PortSetup.From;
+ PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
+ PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
+ PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
+ PortSetup.Store = p->RIOPortp[port]->Store;
+ PortSetup.Lock = p->RIOPortp[port]->Lock;
+ PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
+ bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn, MAX_XP_CTRL_LEN);
+ bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff, MAX_XP_CTRL_LEN);
+ PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
+ PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
+
+ if (copyout((caddr_t) & PortSetup, (int) arg, sizeof(PortSetup))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_GET_PORT_PARAMS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
+ if (copyin((int) arg, (caddr_t) & PortParams, sizeof(struct PortParams)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortParams.Port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortParams.Port]);
+ PortParams.Config = PortP->Config;
+ PortParams.State = PortP->State;
+ rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
+
+ if (copyout((caddr_t) & PortParams, (int) arg, sizeof(struct PortParams)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_GET_PORT_TTY:
+ rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
+ if (copyin((int) arg, (caddr_t) & PortTty, sizeof(struct PortTty))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortTty.port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+
+ rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
+ PortP = (p->RIOPortp[PortTty.port]);
+ if (copyout((caddr_t) & PortTty, (int) arg, sizeof(struct PortTty)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_SET_PORT_TTY:
+ if (copyin((int) arg, (caddr_t) & PortTty, sizeof(struct PortTty)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
+ if (PortTty.port >= (ushort) RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortTty.port]);
+ RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
+ return retval;
+
+ case RIO_SET_PORT_PARAMS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
+ if (copyin((int) arg, (caddr_t) & PortParams, sizeof(PortParams))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortParams.Port >= (ushort) RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortParams.Port]);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->Config = PortParams.Config;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_GET_PORT_STATS:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
+ if (copyin((int) arg, (caddr_t) & portStats, sizeof(struct portStats)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (portStats.port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[portStats.port]);
+ portStats.gather = PortP->statsGather;
+ portStats.txchars = PortP->txchars;
+ portStats.rxchars = PortP->rxchars;
+ portStats.opens = PortP->opens;
+ portStats.closes = PortP->closes;
+ portStats.ioctls = PortP->ioctls;
+ if (copyout((caddr_t) & portStats, (int) arg, sizeof(struct portStats)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_RESET_PORT_STATS:
+ port = (uint) arg;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
+ if (port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[port]);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->txchars = 0;
+ PortP->rxchars = 0;
+ PortP->opens = 0;
+ PortP->closes = 0;
+ PortP->ioctls = 0;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_GATHER_PORT_STATS:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
+ if (copyin((int) arg, (caddr_t) & portStats, sizeof(struct portStats)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (portStats.port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[portStats.port]);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->statsGather = portStats.gather;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_READ_CONFIG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
+ if (copyout((caddr_t) & p->RIOConf, (int) arg, sizeof(struct Conf)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_SET_CONFIG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
+ if (!su) {
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & p->RIOConf, sizeof(struct Conf))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ /*
+ ** move a few value around
+ */
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
+ WWORD(p->RIOHosts[Host].ParmMapP->timer, p->RIOConf.Timer);
+ return retval;
+
+ case RIO_START_POLLER:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
+ return -EINVAL;
+
+ case RIO_STOP_POLLER:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
+ if (!su) {
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ p->RIOPolling = NOT_POLLING;
+ return retval;
+
+ case RIO_SETDEBUG:
+ case RIO_GETDEBUG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
+ if (copyin((int) arg, (caddr_t) & DebugCtrl, sizeof(DebugCtrl))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (DebugCtrl.SysPort == NO_PORT) {
+ if (cmd == RIO_SETDEBUG) {
+ if (!su) {
p->RIOError.Error = NOT_SUPER_USER;
return -EPERM;
}
- if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
- == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return RIOChangeName(p, &MapEnt);
-
- case RIO_DELETE_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
- == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Copy from data space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return RIODeleteRta(p, &MapEnt);
-
- case RIO_QUICK_CHECK:
- /*
- ** 09.12.1998 ARG - ESIL 0776 part fix
- ** A customer was using this to get the RTAs
- ** connect/disconnect status.
- ** RIOConCon() had been botched use RIOHalted
- ** to keep track of RTA connections and
- ** disconnections. That has been changed and
- ** RIORtaDisCons in the rio_info struct now
- ** does the job. So we need to return the value
- ** of RIORtaCons instead of RIOHalted.
- **
- if (copyout((caddr_t)&p->RIOHalted,(int)arg,
- sizeof(uint))==COPYFAIL) {
- **
- */
-
- if (copyout((caddr_t)&p->RIORtaDisCons,(int)arg,
- sizeof(uint))==COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_LAST_ERROR:
- if (copyout((caddr_t)&p->RIOError, (int)arg,
- sizeof(struct Error)) ==COPYFAIL )
- return -EFAULT;
- return 0;
-
- case RIO_GET_LOG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
-#ifdef LOGGING
- RIOGetLog(arg);
- return 0;
-#else
- return -EINVAL;
-#endif
-
- case RIO_GET_MODTYPE:
- if ( copyin( (int)arg, (caddr_t)&port,
- sizeof(uint)) == COPYFAIL )
- {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
- if ( port < 0 || port > 511 )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- PortP = (p->RIOPortp[port]);
- if (!PortP->Mapped)
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
- p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
- return -EINVAL;
- }
- /*
- ** Return module type of port
- */
- port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
- if (copyout((caddr_t)&port, (int)arg,
- sizeof(uint)) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return(0);
- /*
- ** 02.03.1999 ARG - ESIL 0820 fix
- ** We are no longer using "Boot Mode", so these ioctls
- ** are not required :
- **
- case RIO_GET_BOOT_MODE :
- rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode));
- **
- ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE
- **
- if (copyout((caddr_t)&p->RIOBootMode, (int)arg,
- sizeof(p->RIOBootMode)) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return(0);
-
- case RIO_SET_BOOT_MODE :
- p->RIOBootMode = (uint) arg;
- rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode));
- return(0);
- **
- ** End ESIL 0820 fix
- */
-
- case RIO_BLOCK_OPENS:
- rio_dprintk (RIO_DEBUG_CTRL, "Opens block until booted\n");
- for ( Entry=0; Entry < RIO_PORTS; Entry++ ) {
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- p->RIOPortp[Entry]->WaitUntilBooted = 1;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- }
- return 0;
-
- case RIO_SETUP_PORTS:
- rio_dprintk (RIO_DEBUG_CTRL, "Setup ports\n");
- if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup))
- == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "EFAULT");
- return -EFAULT;
- }
- if ( PortSetup.From > PortSetup.To ||
- PortSetup.To >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "ENXIO");
- return -ENXIO;
- }
- if ( PortSetup.XpCps > p->RIOConf.MaxXpCps ||
- PortSetup.XpCps < p->RIOConf.MinXpCps ) {
- p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "EINVAL");
- return -EINVAL;
- }
- if ( !p->RIOPortp ) {
- cprintf("No p->RIOPortp array!\n");
- rio_dprintk (RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
- return -EIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
- for (loop=PortSetup.From; loop<=PortSetup.To; loop++) {
- rio_dprintk (RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
-#if 0
- PortP = p->RIOPortp[loop];
- if ( !PortP->TtyP )
- PortP->TtyP = &p->channel[loop];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- if ( PortSetup.IxAny )
- PortP->Config |= RIO_IXANY;
- else
- PortP->Config &= ~RIO_IXANY;
- if ( PortSetup.IxOn )
- PortP->Config |= RIO_IXON;
- else
- PortP->Config &= ~RIO_IXON;
-
- /*
- ** If the port needs to wait for all a processes output
- ** to drain before closing then this flag will be set.
- */
- if (PortSetup.Drain) {
- PortP->Config |= RIO_WAITDRAIN;
- } else {
- PortP->Config &= ~RIO_WAITDRAIN;
- }
- /*
- ** Store settings if locking or unlocking port or if the
- ** port is not locked, when setting the store option.
- */
- if (PortP->Mapped &&
- ((PortSetup.Lock && !PortP->Lock) ||
- (!PortP->Lock &&
- (PortSetup.Store && !PortP->Store)))) {
- PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag;
- PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag;
- PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag;
- PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag;
- PortP->StoredTty.line = PortP->TtyP->tm.c_line;
- bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc,
- NCC + 5);
- }
- PortP->Lock = PortSetup.Lock;
- PortP->Store = PortSetup.Store;
- PortP->Xprint.XpCps = PortSetup.XpCps;
- bcopy(PortSetup.XpOn,PortP->Xprint.XpOn,MAX_XP_CTRL_LEN);
- bcopy(PortSetup.XpOff,PortP->Xprint.XpOff,MAX_XP_CTRL_LEN);
- PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
- RIOStrlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
-#endif
- }
- rio_dprintk (RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
- rio_dprintk (RIO_DEBUG_CTRL, "Retval:%x\n", retval);
- return retval;
-
- case RIO_GET_PORT_SETUP :
- rio_dprintk (RIO_DEBUG_CTRL, "Get port setup\n");
- if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup))
- == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( PortSetup.From >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
-
- port = PortSetup.To = PortSetup.From;
- PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ?
- 1 : 0;
- PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ?
- 1 : 0;
- PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ?
- 1 : 0;
- PortSetup.Store = p->RIOPortp[port]->Store;
- PortSetup.Lock = p->RIOPortp[port]->Lock;
- PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
- bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn,
- MAX_XP_CTRL_LEN);
- bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff,
- MAX_XP_CTRL_LEN);
- PortSetup.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
- PortSetup.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
-
- if ( copyout((caddr_t)&PortSetup,(int)arg,sizeof(PortSetup))
- ==COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_GET_PORT_PARAMS :
- rio_dprintk (RIO_DEBUG_CTRL, "Get port params\n");
- if (copyin( (int)arg, (caddr_t)&PortParams,
- sizeof(struct PortParams)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (PortParams.Port >= RIO_PORTS) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[PortParams.Port]);
- PortParams.Config = PortP->Config;
- PortParams.State = PortP->State;
- rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
-
- if (copyout((caddr_t)&PortParams, (int)arg,
- sizeof(struct PortParams)) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_GET_PORT_TTY :
- rio_dprintk (RIO_DEBUG_CTRL, "Get port tty\n");
- if (copyin((int)arg, (caddr_t)&PortTty, sizeof(struct PortTty))
- == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( PortTty.port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
-
- rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
- PortP = (p->RIOPortp[PortTty.port]);
-#if 0
- PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag;
- PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag;
- PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag;
- PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag;
-#endif
- if (copyout((caddr_t)&PortTty, (int)arg,
- sizeof(struct PortTty)) == COPYFAIL) {
+ p->rio_debug = DebugCtrl.Debug;
+ p->RIODebugWait = DebugCtrl.Wait;
+ rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
+ DebugCtrl.Debug = p->rio_debug;
+ DebugCtrl.Wait = p->RIODebugWait;
+ if (copyout((caddr_t) & DebugCtrl, (int) arg, sizeof(DebugCtrl)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
p->RIOError.Error = COPYOUT_FAILED;
return -EFAULT;
}
- return retval;
-
- case RIO_SET_PORT_TTY :
- if (copyin((int)arg, (caddr_t)&PortTty,
- sizeof(struct PortTty)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
- if (PortTty.port >= (ushort) RIO_PORTS) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[PortTty.port]);
-#if 0
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag;
- PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag;
- PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag;
- PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
-#endif
-
- RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
- return retval;
-
- case RIO_SET_PORT_PARAMS :
- rio_dprintk (RIO_DEBUG_CTRL, "Set port params\n");
- if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams))
- == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (PortParams.Port >= (ushort) RIO_PORTS) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[PortParams.Port]);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->Config = PortParams.Config;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_GET_PORT_STATS :
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
- if ( copyin((int)arg, (caddr_t)&portStats,
- sizeof(struct portStats)) == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( portStats.port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[portStats.port]);
- portStats.gather = PortP->statsGather;
- portStats.txchars = PortP->txchars;
- portStats.rxchars = PortP->rxchars;
- portStats.opens = PortP->opens;
- portStats.closes = PortP->closes;
- portStats.ioctls = PortP->ioctls;
- if ( copyout((caddr_t)&portStats, (int)arg,
- sizeof(struct portStats)) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_RESET_PORT_STATS :
- port = (uint) arg;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
- if ( port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[port]);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->txchars = 0;
- PortP->rxchars = 0;
- PortP->opens = 0;
- PortP->closes = 0;
- PortP->ioctls = 0;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return retval;
-
- case RIO_GATHER_PORT_STATS :
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
- if ( copyin( (int)arg, (caddr_t)&portStats,
- sizeof(struct portStats)) == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( portStats.port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[portStats.port]);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->statsGather = portStats.gather;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
-#ifdef DEBUG_SUPPORTED
- case RIO_READ_LEVELS:
- {
- int num;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n");
- for ( num=0; RIODbInf[num].Flag; num++ ) ;
- rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copy\n",num);
- if (copyout((caddr_t)RIODbInf,(int)arg,
- sizeof(struct DbInf)*(num+1))==COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "ReadLevels Copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copied\n",num);
- return retval;
- }
-#endif
-
- case RIO_READ_CONFIG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
- if (copyout((caddr_t)&p->RIOConf, (int)arg,
- sizeof(struct Conf)) ==COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
+ }
+ } else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ } else if (cmd == RIO_SETDEBUG) {
+ if (!su) {
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
+ DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
+ if (copyout((caddr_t) & DebugCtrl, (int) arg, sizeof(DebugCtrl)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ }
+ return retval;
- case RIO_SET_CONFIG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if ( copyin((int)arg, (caddr_t)&p->RIOConf, sizeof(struct Conf) )
- ==COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- /*
- ** move a few value around
- */
- for (Host=0; Host < p->RIONumHosts; Host++)
- if ( (p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING )
- WWORD(p->RIOHosts[Host].ParmMapP->timer ,
- p->RIOConf.Timer);
- return retval;
-
- case RIO_START_POLLER:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
- return -EINVAL;
+ case RIO_VERSID:
+ /*
+ ** Enquire about the release and version.
+ ** We return MAX_VERSION_LEN bytes, being a
+ ** textual null terminated string.
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
+ if (copyout((caddr_t) RIOVersid(), (int) arg, sizeof(struct rioVersion)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
- case RIO_STOP_POLLER:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- p->RIOPolling = NOT_POLLING;
- return retval;
-
- case RIO_SETDEBUG:
- case RIO_GETDEBUG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
- if ( copyin( (int)arg, (caddr_t)&DebugCtrl, sizeof(DebugCtrl) )
- ==COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( DebugCtrl.SysPort == NO_PORT ) {
- if ( cmd == RIO_SETDEBUG ) {
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- p->rio_debug = DebugCtrl.Debug;
- p->RIODebugWait = DebugCtrl.Wait;
- rio_dprintk (RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n",
- p->rio_debug,p->RIODebugWait);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n",
- p->rio_debug,p->RIODebugWait);
- DebugCtrl.Debug = p->rio_debug;
- DebugCtrl.Wait = p->RIODebugWait;
- if ( copyout((caddr_t)&DebugCtrl,(int)arg,
- sizeof(DebugCtrl)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n",
- DebugCtrl.SysPort);
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- }
- }
- else if ( DebugCtrl.SysPort >= RIO_PORTS &&
- DebugCtrl.SysPort != NO_PORT ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n",
- DebugCtrl.SysPort);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- else if ( cmd == RIO_SETDEBUG ) {
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n",
- p->RIOPortp[DebugCtrl.SysPort]->Debug);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n",
- p->RIOPortp[DebugCtrl.SysPort]->Debug);
- DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
- if ( copyout((caddr_t)&DebugCtrl,(int)arg,
- sizeof(DebugCtrl))==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- }
- return retval;
-
- case RIO_VERSID:
- /*
- ** Enquire about the release and version.
- ** We return MAX_VERSION_LEN bytes, being a
- ** textual null terminated string.
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID\n");
- if ( copyout( (caddr_t)RIOVersid(),
- (int)arg,
- sizeof(struct rioVersion) ) == COPYFAIL )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
+ /*
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ ** !! commented out previous 'RIO_VERSID' functionality !!
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ **
+ case RIO_VERSID:
+ **
+ ** Enquire about the release and version.
+ ** We return MAX_VERSION_LEN bytes, being a textual null
+ ** terminated string.
+ **
+ rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n"));
+ if (copyout((caddr_t)RIOVersid(),
+ (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) {
+ rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host));
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+ **
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+ case RIO_NUM_HOSTS:
+ /*
+ ** Enquire as to the number of hosts located
+ ** at init time.
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
+ if (copyout((caddr_t) & p->RIONumHosts, (int) arg, sizeof(p->RIONumHosts)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_FOAD:
+ /*
+ ** Kill host. This may not be in the final version...
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int) arg);
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ p->RIOHalted = 1;
+ p->RIOSystemUp = 0;
+
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
+ (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
+ bzero((caddr_t) & p->RIOHosts[Host].Flags, ((int) &p->RIOHosts[Host].____end_marker____) - ((int) &p->RIOHosts[Host].Flags));
+ p->RIOHosts[Host].Flags = RC_WAITING;
+ }
+ RIOFoadWakeup(p);
+ p->RIONumBootPkts = 0;
+ p->RIOBooting = 0;
+ printk("HEEEEELP!\n");
+
+ for (loop = 0; loop < RIO_PORTS; loop++) {
+ spin_lock_init(&p->RIOPortp[loop]->portSem);
+ p->RIOPortp[loop]->InUse = NOT_INUSE;
+ }
+
+ p->RIOSystemUp = 0;
+ return retval;
+
+ case RIO_DOWNLOAD:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & DownLoad, sizeof(DownLoad)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
+ /*
+ ** It is important that the product code is an unsigned object!
+ */
+ if (DownLoad.ProductCode > MAX_PRODUCT) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
+ p->RIOError.Error = NO_SUCH_PRODUCT;
+ return -ENXIO;
+ }
+ /*
+ ** do something!
+ */
+ retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
+ /* <-- Panic */
+ p->RIOHalted = 0;
+ /*
+ ** and go back, content with a job well completed.
+ */
+ return retval;
+
+ case RIO_PARMS:
+ {
+ uint host;
+
+ if (copyin((int) arg, (caddr_t) & host, sizeof(host)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
/*
- ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ** !! commented out previous 'RIO_VERSID' functionality !!
- ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- **
- case RIO_VERSID:
- **
- ** Enquire about the release and version.
- ** We return MAX_VERSION_LEN bytes, being a textual null
- ** terminated string.
- **
- rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n"));
- if (copyout((caddr_t)RIOVersid(),
- (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) {
- rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host));
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
- **
- ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- */
-
- case RIO_NUM_HOSTS:
- /*
- ** Enquire as to the number of hosts located
- ** at init time.
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
- if (copyout((caddr_t)&p->RIONumHosts, (int)arg,
- sizeof(p->RIONumHosts) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_FOAD:
- /*
- ** Kill host. This may not be in the final version...
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int)arg);
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- p->RIOHalted = 1;
- p->RIOSystemUp = 0;
-
- for ( Host=0; Host<p->RIONumHosts; Host++ ) {
- (void)RIOBoardTest( p->RIOHosts[Host].PaddrP,
- p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type,
- p->RIOHosts[Host].Slot );
- bzero( (caddr_t)&p->RIOHosts[Host].Flags,
- ((int)&p->RIOHosts[Host].____end_marker____) -
- ((int)&p->RIOHosts[Host].Flags) );
- p->RIOHosts[Host].Flags = RC_WAITING;
-#if 0
- RIOSetupDataStructs(p);
-#endif
- }
- RIOFoadWakeup(p);
- p->RIONumBootPkts = 0;
- p->RIOBooting = 0;
-
-#ifdef RINGBUFFER_SUPPORT
- for( loop=0; loop<RIO_PORTS; loop++ )
- if ( p->RIOPortp[loop]->TxRingBuffer )
- sysfree((void *)p->RIOPortp[loop]->TxRingBuffer,
- RIOBufferSize );
-#endif
-#if 0
- bzero((caddr_t)&p->RIOPortp[0],RIO_PORTS*sizeof(struct Port));
-#else
- printk ("HEEEEELP!\n");
-#endif
-
- for( loop=0; loop<RIO_PORTS; loop++ ) {
-#if 0
- p->RIOPortp[loop]->TtyP = &p->channel[loop];
-#endif
-
- spin_lock_init(&p->RIOPortp[loop]->portSem);
- p->RIOPortp[loop]->InUse = NOT_INUSE;
- }
-
- p->RIOSystemUp = 0;
- return retval;
-
- case RIO_DOWNLOAD:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if ( copyin((int)arg, (caddr_t)&DownLoad,
- sizeof(DownLoad) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n",
- DownLoad.ProductCode);
-
- /*
- ** It is important that the product code is an unsigned object!
- */
- if ( DownLoad.ProductCode > MAX_PRODUCT ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n",
- DownLoad.ProductCode);
- p->RIOError.Error = NO_SUCH_PRODUCT;
- return -ENXIO;
- }
- /*
- ** do something!
- */
- retval = (*(RIOBootTable[DownLoad.ProductCode]))(p, &DownLoad);
- /* <-- Panic */
- p->RIOHalted = 0;
- /*
- ** and go back, content with a job well completed.
- */
- return retval;
-
- case RIO_PARMS:
- {
- uint host;
-
- if (copyin((int)arg, (caddr_t)&host,
- sizeof(host) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL,
- "RIO_HOST_REQ: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- /*
- ** Fetch the parmmap
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS\n");
- if ( copyout( (caddr_t)p->RIOHosts[host].ParmMapP,
- (int)arg, sizeof(PARM_MAP) )==COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
- return -EFAULT;
- }
- }
- return retval;
-
- case RIO_HOST_REQ:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
- if (copyin((int)arg, (caddr_t)&HostReq,
- sizeof(HostReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( HostReq.HostNum >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n",
- HostReq.HostNum);
- return -ENXIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
-
- if (copyout((caddr_t)&p->RIOHosts[HostReq.HostNum],
- (int)HostReq.HostP,sizeof(struct Host) ) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_DPRAM:
- rio_dprintk (RIO_DEBUG_CTRL, "Request for DPRAM\n");
- if ( copyin( (int)arg, (caddr_t)&HostDpRam,
- sizeof(HostDpRam) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( HostDpRam.HostNum >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n",
- HostDpRam.HostNum);
- return -ENXIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
-
- if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
- int off;
- /* It's hardware like this that really gets on my tits. */
- static unsigned char copy[sizeof(struct DpRam)];
- for ( off=0; off<sizeof(struct DpRam); off++ )
- copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off];
- if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP,
- sizeof(struct DpRam) ) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
- return -EFAULT;
- }
- }
- else if (copyout((caddr_t)p->RIOHosts[HostDpRam.HostNum].Caddr,
- (int)HostDpRam.DpRamP,
- sizeof(struct DpRam) ) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_SET_BUSY:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
- if ( (int)arg < 0 || (int)arg > 511 ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n",(int)arg);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- p->RIOPortp[(int)arg]->State |= RIO_BUSY;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_HOST_PORT:
- /*
- ** The daemon want port information
- ** (probably for debug reasons)
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
- if ( copyin((int)arg, (caddr_t)&PortReq,
- sizeof(PortReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
-
- if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n",
- PortReq.SysPort);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
- if (copyout((caddr_t)p->RIOPortp[PortReq.SysPort],
- (int)PortReq.PortP,
- sizeof(struct Port) ) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_RUP:
- /*
- ** The daemon want rup information
- ** (probably for debug reasons)
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
- if (copyin((int)arg, (caddr_t)&RupReq,
- sizeof(RupReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n",
- RupReq.HostNum);
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- if ( RupReq.RupNum >= MAX_RUP+LINKS_PER_UNIT ) { /* eek! */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n",
- RupReq.RupNum);
- p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- HostP = &p->RIOHosts[RupReq.HostNum];
-
- if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n",
- RupReq.HostNum);
- p->RIOError.Error = HOST_NOT_RUNNING;
- return -EIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for rup %d from host %d\n",
- RupReq.RupNum,RupReq.HostNum);
-
- if (copyout((caddr_t)HostP->UnixRups[RupReq.RupNum].RupP,
- (int)RupReq.RupP,sizeof(struct RUP) ) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_LPB:
- /*
- ** The daemon want lpb information
- ** (probably for debug reasons)
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
- if (copyin((int)arg, (caddr_t)&LpbReq,
- sizeof(LpbReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n",
- LpbReq.Host);
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- if ( LpbReq.Link >= LINKS_PER_UNIT ) { /* eek! */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n",
- LpbReq.Link);
- p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- HostP = &p->RIOHosts[LpbReq.Host];
-
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n",
- LpbReq.Host );
- p->RIOError.Error = HOST_NOT_RUNNING;
- return -EIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n",
- LpbReq.Link, LpbReq.Host);
-
- if (copyout((caddr_t)&HostP->LinkStrP[LpbReq.Link],
- (int)LpbReq.LpbP,sizeof(struct LPB) ) == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- /*
- ** Here 3 IOCTL's that allow us to change the way in which
- ** rio logs errors. send them just to syslog or send them
- ** to both syslog and console or send them to just the console.
- **
- ** See RioStrBuf() in util.c for the other half.
- */
- case RIO_SYSLOG_ONLY:
- p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */
- return 0;
-
- case RIO_SYSLOG_CONS:
- p->RIOPrintLogState = PRINT_TO_LOG_CONS;/* syslog and console */
- return 0;
-
- case RIO_CONS_ONLY:
- p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */
- return 0;
-
- case RIO_SIGNALS_ON:
- if ( p->RIOSignalProcess ) {
- p->RIOError.Error = SIGNALS_ALREADY_SET;
- return -EBUSY;
- }
- p->RIOSignalProcess = getpid();
- p->RIOPrintDisabled = DONT_PRINT;
- return retval;
-
- case RIO_SIGNALS_OFF:
- if ( p->RIOSignalProcess != getpid() ) {
- p->RIOError.Error = NOT_RECEIVING_PROCESS;
- return -EPERM;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Clear signal process to zero\n");
- p->RIOSignalProcess = 0;
- return retval;
-
- case RIO_SET_BYTE_MODE:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
- return retval;
-
- case RIO_SET_WORD_MODE:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode |= WORD_OPERATION;
- return retval;
-
- case RIO_SET_FAST_BUS:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode |= FAST_AT_BUS;
- return retval;
-
- case RIO_SET_SLOW_BUS:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
- return retval;
-
- case RIO_MAP_B50_TO_50:
- case RIO_MAP_B50_TO_57600:
- case RIO_MAP_B110_TO_110:
- case RIO_MAP_B110_TO_115200:
- rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping\n");
- port = (uint) arg;
- if ( port < 0 || port > 511 ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- switch( cmd )
- {
- case RIO_MAP_B50_TO_50 :
- p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
- break;
- case RIO_MAP_B50_TO_57600 :
- p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
- break;
- case RIO_MAP_B110_TO_110 :
- p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
- break;
- case RIO_MAP_B110_TO_115200 :
- p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
- break;
- }
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_STREAM_INFO:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
- return -EINVAL;
-
- case RIO_SEND_PACKET:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
- if ( copyin( (int)arg, (caddr_t)&SendPack,
- sizeof(SendPack) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( SendPack.PortNum >= 128 ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
-
- PortP = p->RIOPortp[SendPack.PortNum];
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- if ( !can_add_transmit(&PacketP,PortP) ) {
- p->RIOError.Error = UNIT_IS_IN_USE;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return -ENOSPC;
- }
-
- for ( loop=0; loop<(ushort)(SendPack.Len & 127); loop++ )
- WBYTE(PacketP->data[loop], SendPack.Data[loop] );
-
- WBYTE(PacketP->len, SendPack.Len);
-
- add_transmit( PortP );
- /*
- ** Count characters transmitted for port statistics reporting
- */
- if (PortP->statsGather)
- PortP->txchars += (SendPack.Len & 127);
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_NO_MESG:
- if ( su )
- p->RIONoMessage = 1;
- return su ? 0 : -EPERM;
-
- case RIO_MESG:
- if ( su )
- p->RIONoMessage = 0;
- return su ? 0 : -EPERM;
-
- case RIO_WHAT_MESG:
- if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg,
- sizeof(p->RIONoMessage) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_MEM_DUMP :
- if (copyin((int)arg, (caddr_t)&SubCmd,
- sizeof(struct SubCmdStruct)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n",
- SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
-
- if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
- p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- if (SubCmd.Host >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- port = p->RIOHosts[SubCmd.Host].
- UnixRups[SubCmd.Rup].BaseSysPort;
-
- PortP = p->RIOPortp[port];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- if ( RIOPreemptiveCmd(p, PortP, MEMDUMP ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return -EBUSY;
- }
- else
- PortP->State |= RIO_BUSY;
-
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- if ( copyout( (caddr_t)p->RIOMemDump, (int)arg,
- MEMDUMP_SIZE) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_TICK:
- if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
- return -EINVAL;
- rio_dprintk (RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int)arg);
- WBYTE(p->RIOHosts[(int)arg].SetInt , 0xff);
- return 0;
-
- case RIO_TOCK:
- if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
- return -EINVAL;
- rio_dprintk (RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int)arg);
- WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff);
- return 0;
-
- case RIO_READ_CHECK:
- /* Check reads for pkts with data[0] the same */
- p->RIOReadCheck = !p->RIOReadCheck;
- if (copyout((caddr_t)&p->RIOReadCheck,(int)arg,
- sizeof(uint))== COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_READ_REGISTER :
- if (copyin((int)arg, (caddr_t)&SubCmd,
- sizeof(struct SubCmdStruct)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n",
- SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
-
- if (SubCmd.Port > 511) {
- rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n",
- SubCmd.Port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
- p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- if (SubCmd.Host >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- port = p->RIOHosts[SubCmd.Host].
- UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
- PortP = p->RIOPortp[port];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return -EBUSY;
- }
- else
- PortP->State |= RIO_BUSY;
-
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- if (copyout((caddr_t)&p->CdRegister, (int)arg,
- sizeof(uint)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
- /*
- ** rio_make_dev: given port number (0-511) ORed with port type
- ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
- ** value to pass to mknod to create the correct device node.
- */
- case RIO_MAKE_DEV:
- {
- uint port = (uint)arg & RIO_MODEM_MASK;
-
- switch ( (uint)arg & RIO_DEV_MASK ) {
- case RIO_DEV_DIRECT:
- arg = (caddr_t)drv_makedev(MAJOR(dev), port);
- rio_dprintk (RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n",port, (int)arg);
- return (int)arg;
- case RIO_DEV_MODEM:
- arg = (caddr_t)drv_makedev(MAJOR(dev), (port|RIO_MODEM_BIT) );
- rio_dprintk (RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n",port, (int)arg);
- return (int)arg;
- case RIO_DEV_XPRINT:
- arg = (caddr_t)drv_makedev(MAJOR(dev), port);
- rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg);
- return (int)arg;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "MAKE Device is called\n");
- return -EINVAL;
- }
- /*
- ** rio_minor: given a dev_t from a stat() call, return
- ** the port number (0-511) ORed with the port type
- ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
- */
- case RIO_MINOR:
- {
- dev_t dv;
- int mino;
-
- dv = (dev_t)((int)arg);
- mino = RIO_UNMODEM(dv);
+ ** Fetch the parmmap
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
+ if (copyout((caddr_t) p->RIOHosts[host].ParmMapP, (int) arg, sizeof(PARM_MAP)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
+ return -EFAULT;
+ }
+ }
+ return retval;
+
+ case RIO_HOST_REQ:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
+ if (copyin((int) arg, (caddr_t) & HostReq, sizeof(HostReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (HostReq.HostNum >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
+ return -ENXIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
+
+ if (copyout((caddr_t) & p->RIOHosts[HostReq.HostNum], (int) HostReq.HostP, sizeof(struct Host)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_DPRAM:
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
+ if (copyin((int) arg, (caddr_t) & HostDpRam, sizeof(HostDpRam)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (HostDpRam.HostNum >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
+ return -ENXIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
+
+ if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
+ int off;
+ /* It's hardware like this that really gets on my tits. */
+ static unsigned char copy[sizeof(struct DpRam)];
+ for (off = 0; off < sizeof(struct DpRam); off++)
+ copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off];
+ if (copyout((caddr_t) copy, (int) HostDpRam.DpRamP, sizeof(struct DpRam)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ } else if (copyout((caddr_t) p->RIOHosts[HostDpRam.HostNum].Caddr, (int) HostDpRam.DpRamP, sizeof(struct DpRam)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_SET_BUSY:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
+ if ((int) arg < 0 || (int) arg > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n", (int) arg);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ p->RIOPortp[(int) arg]->State |= RIO_BUSY;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_HOST_PORT:
+ /*
+ ** The daemon want port information
+ ** (probably for debug reasons)
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
+ if (copyin((int) arg, (caddr_t) & PortReq, sizeof(PortReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+
+ if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
+ if (copyout((caddr_t) p->RIOPortp[PortReq.SysPort], (int) PortReq.PortP, sizeof(struct Port)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_RUP:
+ /*
+ ** The daemon want rup information
+ ** (probably for debug reasons)
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
+ if (copyin((int) arg, (caddr_t) & RupReq, sizeof(RupReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) { /* eek! */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
+ p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ HostP = &p->RIOHosts[RupReq.HostNum];
+
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
+ p->RIOError.Error = HOST_NOT_RUNNING;
+ return -EIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
+
+ if (copyout((caddr_t) HostP->UnixRups[RupReq.RupNum].RupP, (int) RupReq.RupP, sizeof(struct RUP)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_LPB:
+ /*
+ ** The daemon want lpb information
+ ** (probably for debug reasons)
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
+ if (copyin((int) arg, (caddr_t) & LpbReq, sizeof(LpbReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ if (LpbReq.Link >= LINKS_PER_UNIT) { /* eek! */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
+ p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ HostP = &p->RIOHosts[LpbReq.Host];
+
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
+ p->RIOError.Error = HOST_NOT_RUNNING;
+ return -EIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
+
+ if (copyout((caddr_t) & HostP->LinkStrP[LpbReq.Link], (int) LpbReq.LpbP, sizeof(struct LPB)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
- if ( RIO_ISMODEM(dv) ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
- arg = (caddr_t)(mino | RIO_DEV_MODEM);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
- arg = (caddr_t)(mino | RIO_DEV_DIRECT);
- }
- return (int)arg;
- }
+ /*
+ ** Here 3 IOCTL's that allow us to change the way in which
+ ** rio logs errors. send them just to syslog or send them
+ ** to both syslog and console or send them to just the console.
+ **
+ ** See RioStrBuf() in util.c for the other half.
+ */
+ case RIO_SYSLOG_ONLY:
+ p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */
+ return 0;
+
+ case RIO_SYSLOG_CONS:
+ p->RIOPrintLogState = PRINT_TO_LOG_CONS; /* syslog and console */
+ return 0;
+
+ case RIO_CONS_ONLY:
+ p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */
+ return 0;
+
+ case RIO_SIGNALS_ON:
+ if (p->RIOSignalProcess) {
+ p->RIOError.Error = SIGNALS_ALREADY_SET;
+ return -EBUSY;
+ }
+ p->RIOSignalProcess = getpid();
+ p->RIOPrintDisabled = DONT_PRINT;
+ return retval;
+
+ case RIO_SIGNALS_OFF:
+ if (p->RIOSignalProcess != getpid()) {
+ p->RIOError.Error = NOT_RECEIVING_PROCESS;
+ return -EPERM;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
+ p->RIOSignalProcess = 0;
+ return retval;
+
+ case RIO_SET_BYTE_MODE:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
+ return retval;
+
+ case RIO_SET_WORD_MODE:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode |= WORD_OPERATION;
+ return retval;
+
+ case RIO_SET_FAST_BUS:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode |= FAST_AT_BUS;
+ return retval;
+
+ case RIO_SET_SLOW_BUS:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
+ return retval;
+
+ case RIO_MAP_B50_TO_50:
+ case RIO_MAP_B50_TO_57600:
+ case RIO_MAP_B110_TO_110:
+ case RIO_MAP_B110_TO_115200:
+ rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
+ port = (uint) arg;
+ if (port < 0 || port > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ switch (cmd) {
+ case RIO_MAP_B50_TO_50:
+ p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
+ break;
+ case RIO_MAP_B50_TO_57600:
+ p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
+ break;
+ case RIO_MAP_B110_TO_110:
+ p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
+ break;
+ case RIO_MAP_B110_TO_115200:
+ p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
+ break;
+ }
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_STREAM_INFO:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
+ return -EINVAL;
+
+ case RIO_SEND_PACKET:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
+ if (copyin((int) arg, (caddr_t) & SendPack, sizeof(SendPack)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (SendPack.PortNum >= 128) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+
+ PortP = p->RIOPortp[SendPack.PortNum];
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ if (!can_add_transmit(&PacketP, PortP)) {
+ p->RIOError.Error = UNIT_IS_IN_USE;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -ENOSPC;
+ }
+
+ for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
+ WBYTE(PacketP->data[loop], SendPack.Data[loop]);
+
+ WBYTE(PacketP->len, SendPack.Len);
+
+ add_transmit(PortP);
+ /*
+ ** Count characters transmitted for port statistics reporting
+ */
+ if (PortP->statsGather)
+ PortP->txchars += (SendPack.Len & 127);
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_NO_MESG:
+ if (su)
+ p->RIONoMessage = 1;
+ return su ? 0 : -EPERM;
+
+ case RIO_MESG:
+ if (su)
+ p->RIONoMessage = 0;
+ return su ? 0 : -EPERM;
+
+ case RIO_WHAT_MESG:
+ if (copyout((caddr_t) & p->RIONoMessage, (int) arg, sizeof(p->RIONoMessage)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_MEM_DUMP:
+ if (copyin((int) arg, (caddr_t) & SubCmd, sizeof(struct SubCmdStruct)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
+
+ if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
+ p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ if (SubCmd.Host >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
+
+ PortP = p->RIOPortp[port];
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ if (RIOPreemptiveCmd(p, PortP, MEMDUMP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+ } else
+ PortP->State |= RIO_BUSY;
+
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (copyout((caddr_t) p->RIOMemDump, (int) arg, MEMDUMP_SIZE) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_TICK:
+ if ((int) arg < 0 || (int) arg >= p->RIONumHosts)
+ return -EINVAL;
+ rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int) arg);
+ WBYTE(p->RIOHosts[(int) arg].SetInt, 0xff);
+ return 0;
+
+ case RIO_TOCK:
+ if ((int) arg < 0 || (int) arg >= p->RIONumHosts)
+ return -EINVAL;
+ rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int) arg);
+ WBYTE((p->RIOHosts[(int) arg].ResetInt), 0xff);
+ return 0;
+
+ case RIO_READ_CHECK:
+ /* Check reads for pkts with data[0] the same */
+ p->RIOReadCheck = !p->RIOReadCheck;
+ if (copyout((caddr_t) & p->RIOReadCheck, (int) arg, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_READ_REGISTER:
+ if (copyin((int) arg, (caddr_t) & SubCmd, sizeof(struct SubCmdStruct)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
+
+ if (SubCmd.Port > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
+ p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ if (SubCmd.Host >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
+ PortP = p->RIOPortp[port];
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+ } else
+ PortP->State |= RIO_BUSY;
+
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (copyout((caddr_t) & p->CdRegister, (int) arg, sizeof(uint)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+ /*
+ ** rio_make_dev: given port number (0-511) ORed with port type
+ ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
+ ** value to pass to mknod to create the correct device node.
+ */
+ case RIO_MAKE_DEV:
+ {
+ uint port = (uint) arg & RIO_MODEM_MASK;
+
+ switch ((uint) arg & RIO_DEV_MASK) {
+ case RIO_DEV_DIRECT:
+ arg = (caddr_t) drv_makedev(MAJOR(dev), port);
+ rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, (int) arg);
+ return (int) arg;
+ case RIO_DEV_MODEM:
+ arg = (caddr_t) drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
+ rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, (int) arg);
+ return (int) arg;
+ case RIO_DEV_XPRINT:
+ arg = (caddr_t) drv_makedev(MAJOR(dev), port);
+ rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, (int) arg);
+ return (int) arg;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
+ return -EINVAL;
+ }
+ /*
+ ** rio_minor: given a dev_t from a stat() call, return
+ ** the port number (0-511) ORed with the port type
+ ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
+ */
+ case RIO_MINOR:
+ {
+ dev_t dv;
+ int mino;
+
+ dv = (dev_t) ((int) arg);
+ mino = RIO_UNMODEM(dv);
+
+ if (RIO_ISMODEM(dv)) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
+ arg = (caddr_t) (mino | RIO_DEV_MODEM);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
+ arg = (caddr_t) (mino | RIO_DEV_DIRECT);
+ }
+ return (int) arg;
+ }
}
- rio_dprintk (RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n",cmd);
+ rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
- func_exit ();
+ func_exit();
return -EINVAL;
}
/*
** Pre-emptive commands go on RUPs and are only one byte long.
*/
-int
-RIOPreemptiveCmd(p, PortP, Cmd)
-struct rio_info * p;
+int RIOPreemptiveCmd(p, PortP, Cmd)
+struct rio_info *p;
struct Port *PortP;
uchar Cmd;
{
@@ -1765,105 +1548,96 @@ uchar Cmd;
ushort rup;
int port;
-#ifdef CHECK
- CheckPortP( PortP );
-#endif
-
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
return RIO_FAIL;
}
- if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n",
- Cmd, PortP->PortNum);
+ if (((int) ((char) PortP->InUse) == -1) || !(CmdBlkP = RIOGetCmdBlk())) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", Cmd, PortP->PortNum);
return RIO_FAIL;
}
- rio_dprintk (RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n",
- (int)CmdBlkP,PortP->InUse);
+ rio_dprintk(RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n", (int) CmdBlkP, PortP->InUse);
- PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
+ PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0];
- CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_unit = 0;
if (PortP->SecondBlock)
rup = PortP->ID2;
else
rup = PortP->RupNum;
CmdBlkP->Packet.dest_unit = rup;
- CmdBlkP->Packet.src_port = COMMAND_RUP;
+ CmdBlkP->Packet.src_port = COMMAND_RUP;
CmdBlkP->Packet.dest_port = COMMAND_RUP;
- CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
- CmdBlkP->PostFuncP = RIOUnUse;
- CmdBlkP->PostArg = (int)PortP;
- PktCmdP->Command = Cmd;
- port = PortP->HostPort % (ushort)PORTS_PER_RTA;
+ CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
+ CmdBlkP->PostFuncP = RIOUnUse;
+ CmdBlkP->PostArg = (int) PortP;
+ PktCmdP->Command = Cmd;
+ port = PortP->HostPort % (ushort) PORTS_PER_RTA;
/*
- ** Index ports 8-15 for 2nd block of 16 port RTA.
- */
+ ** Index ports 8-15 for 2nd block of 16 port RTA.
+ */
if (PortP->SecondBlock)
port += (ushort) PORTS_PER_RTA;
- PktCmdP->PhbNum = port;
-
- switch ( Cmd ) {
- case MEMDUMP:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n",
- (int)CmdBlkP, (int)SubCmd.Addr);
- PktCmdP->SubCommand = MEMDUMP;
- PktCmdP->SubAddr = SubCmd.Addr;
- break;
- case FCLOSE:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP);
- break;
- case READ_REGISTER:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n",
- (int)SubCmd.Addr, (int)CmdBlkP);
- PktCmdP->SubCommand = READ_REGISTER;
- PktCmdP->SubAddr = SubCmd.Addr;
- break;
- case RESUME:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n",(int)CmdBlkP);
- break;
- case RFLUSH:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP);
- CmdBlkP->PostFuncP = RIORFlushEnable;
- break;
- case SUSPEND:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP);
- break;
-
- case MGET :
- rio_dprintk (RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int)CmdBlkP);
- break;
-
- case MSET :
- case MBIC :
- case MBIS :
- CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
- rio_dprintk (RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP);
- break;
-
- case WFLUSH:
- /*
- ** If we have queued up the maximum number of Write flushes
- ** allowed then we should not bother sending any more to the
- ** RTA.
- */
- if ((int)((char)PortP->WflushFlag) == (int)-1) {
- rio_dprintk (RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
- RIOFreeCmdBlk(CmdBlkP);
- return(RIO_FAIL);
- } else {
- rio_dprintk (RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n",
- (int)CmdBlkP);
- CmdBlkP->PostFuncP = RIOWFlushMark;
- }
- break;
+ PktCmdP->PhbNum = port;
+
+ switch (Cmd) {
+ case MEMDUMP:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n", (int) CmdBlkP, (int) SubCmd.Addr);
+ PktCmdP->SubCommand = MEMDUMP;
+ PktCmdP->SubAddr = SubCmd.Addr;
+ break;
+ case FCLOSE:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n", (int) CmdBlkP);
+ break;
+ case READ_REGISTER:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n", (int) SubCmd.Addr, (int) CmdBlkP);
+ PktCmdP->SubCommand = READ_REGISTER;
+ PktCmdP->SubAddr = SubCmd.Addr;
+ break;
+ case RESUME:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n", (int) CmdBlkP);
+ break;
+ case RFLUSH:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n", (int) CmdBlkP);
+ CmdBlkP->PostFuncP = RIORFlushEnable;
+ break;
+ case SUSPEND:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n", (int) CmdBlkP);
+ break;
+
+ case MGET:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int) CmdBlkP);
+ break;
+
+ case MSET:
+ case MBIC:
+ case MBIS:
+ CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int) CmdBlkP);
+ break;
+
+ case WFLUSH:
+ /*
+ ** If we have queued up the maximum number of Write flushes
+ ** allowed then we should not bother sending any more to the
+ ** RTA.
+ */
+ if ((int) ((char) PortP->WflushFlag) == (int) -1) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
+ RIOFreeCmdBlk(CmdBlkP);
+ return (RIO_FAIL);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n", (int) CmdBlkP);
+ CmdBlkP->PostFuncP = RIOWFlushMark;
+ }
+ break;
}
PortP->InUse++;
- Ret = RIOQueueCmdBlk( PortP->HostP, rup, CmdBlkP );
+ Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
return Ret;
}
diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h
index bc38ac5dfbde..663ee0914ed7 100644
--- a/drivers/char/rio/riodrvr.h
+++ b/drivers/char/rio/riodrvr.h
@@ -33,7 +33,7 @@
#ifndef __riodrvr_h
#define __riodrvr_h
-#include <asm/param.h> /* for HZ */
+#include <asm/param.h> /* for HZ */
#ifdef SCCS_LABELS
static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h 1.3";
@@ -44,15 +44,15 @@ static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h 1.3";
struct rio_info {
- int mode; /* Intr or polled, word/byte */
- spinlock_t RIOIntrSem; /* Interrupt thread sem */
- int current_chan; /* current channel */
- int RIOFailed; /* Not initialised ? */
- int RIOInstallAttempts; /* no. of rio-install() calls */
- int RIOLastPCISearch; /* status of last search */
- int RIONumHosts; /* Number of RIO Hosts */
- struct Host * RIOHosts; /* RIO Host values */
- struct Port **RIOPortp; /* RIO port values */
+ int mode; /* Intr or polled, word/byte */
+ spinlock_t RIOIntrSem; /* Interrupt thread sem */
+ int current_chan; /* current channel */
+ int RIOFailed; /* Not initialised ? */
+ int RIOInstallAttempts; /* no. of rio-install() calls */
+ int RIOLastPCISearch; /* status of last search */
+ int RIONumHosts; /* Number of RIO Hosts */
+ struct Host *RIOHosts; /* RIO Host values */
+ struct Port **RIOPortp; /* RIO port values */
/*
** 02.03.1999 ARG - ESIL 0820 fix
** We no longer use RIOBootMode
@@ -60,9 +60,9 @@ struct rio_info {
int RIOBootMode; * RIO boot mode *
**
*/
- int RIOPrintDisabled; /* RIO printing disabled ? */
- int RIOPrintLogState; /* RIO printing state ? */
- int RIOPolling; /* Polling ? */
+ int RIOPrintDisabled; /* RIO printing disabled ? */
+ int RIOPrintLogState; /* RIO printing state ? */
+ int RIOPolling; /* Polling ? */
/*
** 09.12.1998 ARG - ESIL 0776 part fix
** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
@@ -70,61 +70,61 @@ struct rio_info {
** updated in RIOConCon() - to keep track of RTA connections/disconnections.
** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
*/
- int RIOHalted; /* halted ? */
- int RIORtaDisCons; /* RTA connections/disconnections */
- uint RIOReadCheck; /* Rio read check */
- uint RIONoMessage; /* To display message or not */
- uint RIONumBootPkts; /* how many packets for an RTA */
- uint RIOBootCount; /* size of RTA code */
- uint RIOBooting; /* count of outstanding boots */
- uint RIOSystemUp; /* Booted ?? */
- uint RIOCounting; /* for counting interrupts */
- uint RIOIntCount; /* # of intr since last check */
- uint RIOTxCount; /* number of xmit intrs */
- uint RIORxCount; /* number of rx intrs */
- uint RIORupCount; /* number of rup intrs */
- int RIXTimer;
- int RIOBufferSize; /* Buffersize */
- int RIOBufferMask; /* Buffersize */
-
- int RIOFirstMajor; /* First host card's major no */
-
- uint RIOLastPortsMapped; /* highest port number known */
- uint RIOFirstPortsMapped; /* lowest port number known */
-
- uint RIOLastPortsBooted; /* highest port number running */
- uint RIOFirstPortsBooted; /* lowest port number running */
-
- uint RIOLastPortsOpened; /* highest port number running */
- uint RIOFirstPortsOpened; /* lowest port number running */
+ int RIOHalted; /* halted ? */
+ int RIORtaDisCons; /* RTA connections/disconnections */
+ uint RIOReadCheck; /* Rio read check */
+ uint RIONoMessage; /* To display message or not */
+ uint RIONumBootPkts; /* how many packets for an RTA */
+ uint RIOBootCount; /* size of RTA code */
+ uint RIOBooting; /* count of outstanding boots */
+ uint RIOSystemUp; /* Booted ?? */
+ uint RIOCounting; /* for counting interrupts */
+ uint RIOIntCount; /* # of intr since last check */
+ uint RIOTxCount; /* number of xmit intrs */
+ uint RIORxCount; /* number of rx intrs */
+ uint RIORupCount; /* number of rup intrs */
+ int RIXTimer;
+ int RIOBufferSize; /* Buffersize */
+ int RIOBufferMask; /* Buffersize */
+
+ int RIOFirstMajor; /* First host card's major no */
+
+ uint RIOLastPortsMapped; /* highest port number known */
+ uint RIOFirstPortsMapped; /* lowest port number known */
+
+ uint RIOLastPortsBooted; /* highest port number running */
+ uint RIOFirstPortsBooted; /* lowest port number running */
+
+ uint RIOLastPortsOpened; /* highest port number running */
+ uint RIOFirstPortsOpened; /* lowest port number running */
/* Flag to say that the topology information has been changed. */
- uint RIOQuickCheck;
- uint CdRegister; /* ??? */
- int RIOSignalProcess; /* Signalling process */
- int rio_debug; /* To debug ... */
- int RIODebugWait; /* For what ??? */
- int tpri; /* Thread prio */
- int tid; /* Thread id */
- uint _RIO_Polled; /* Counter for polling */
- uint _RIO_Interrupted; /* Counter for interrupt */
- int intr_tid; /* iointset return value */
- int TxEnSem; /* TxEnable Semaphore */
-
-
- struct Error RIOError; /* to Identify what went wrong */
- struct Conf RIOConf; /* Configuration ??? */
- struct ttystatics channel[RIO_PORTS]; /* channel information */
- char RIOBootPackets[1+(SIXTY_FOUR_K/RTA_BOOT_DATA_SIZE)]
- [RTA_BOOT_DATA_SIZE];
- struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
- struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
+ uint RIOQuickCheck;
+ uint CdRegister; /* ??? */
+ int RIOSignalProcess; /* Signalling process */
+ int rio_debug; /* To debug ... */
+ int RIODebugWait; /* For what ??? */
+ int tpri; /* Thread prio */
+ int tid; /* Thread id */
+ uint _RIO_Polled; /* Counter for polling */
+ uint _RIO_Interrupted; /* Counter for interrupt */
+ int intr_tid; /* iointset return value */
+ int TxEnSem; /* TxEnable Semaphore */
+
+
+ struct Error RIOError; /* to Identify what went wrong */
+ struct Conf RIOConf; /* Configuration ??? */
+ struct ttystatics channel[RIO_PORTS]; /* channel information */
+ char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)]
+ [RTA_BOOT_DATA_SIZE];
+ struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
+ struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
/* RTA to host binding table for master/slave operation */
- ulong RIOBindTab[MAX_RTA_BINDINGS];
+ ulong RIOBindTab[MAX_RTA_BINDINGS];
/* RTA memory dump variable */
- uchar RIOMemDump[MEMDUMP_SIZE];
- struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
+ uchar RIOMemDump[MEMDUMP_SIZE];
+ struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
};
@@ -141,4 +141,4 @@ struct rio_info {
#define WRBYTE(x,y) *(volatile unsigned char *)((x)) = \
(unsigned char)(y)
-#endif /* __riodrvr.h */
+#endif /* __riodrvr.h */
diff --git a/drivers/char/rio/rioinfo.h b/drivers/char/rio/rioinfo.h
index e08421c9558e..8de7966e603a 100644
--- a/drivers/char/rio/rioinfo.h
+++ b/drivers/char/rio/rioinfo.h
@@ -41,29 +41,29 @@ static char *_rioinfo_h_sccs_ = "@(#)rioinfo.h 1.2";
** Host card data structure
*/
struct RioHostInfo {
- long location; /* RIO Card Base I/O address */
- long vector; /* RIO Card IRQ vector */
- int bus; /* ISA/EISA/MCA/PCI */
- int mode; /* pointer to host mode - INTERRUPT / POLLED */
+ long location; /* RIO Card Base I/O address */
+ long vector; /* RIO Card IRQ vector */
+ int bus; /* ISA/EISA/MCA/PCI */
+ int mode; /* pointer to host mode - INTERRUPT / POLLED */
struct old_sgttyb
- * Sg; /* pointer to default term characteristics */
+ *Sg; /* pointer to default term characteristics */
};
/* Mode in rio device info */
-#define INTERRUPTED_MODE 0x01 /* Interrupt is generated */
-#define POLLED_MODE 0x02 /* No interrupt */
-#define AUTO_MODE 0x03 /* Auto mode */
+#define INTERRUPTED_MODE 0x01 /* Interrupt is generated */
+#define POLLED_MODE 0x02 /* No interrupt */
+#define AUTO_MODE 0x03 /* Auto mode */
-#define WORD_ACCESS_MODE 0x10 /* Word Access Mode */
-#define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */
+#define WORD_ACCESS_MODE 0x10 /* Word Access Mode */
+#define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */
/* Bus type that RIO supports */
-#define ISA_BUS 0x01 /* The card is ISA */
-#define EISA_BUS 0x02 /* The card is EISA */
-#define MCA_BUS 0x04 /* The card is MCA */
-#define PCI_BUS 0x08 /* The card is PCI */
+#define ISA_BUS 0x01 /* The card is ISA */
+#define EISA_BUS 0x02 /* The card is EISA */
+#define MCA_BUS 0x04 /* The card is MCA */
+#define PCI_BUS 0x08 /* The card is PCI */
/*
** 11.11.1998 ARG - ESIL ???? part fix
@@ -93,4 +93,4 @@ struct RioHostInfo {
'V' - '@' /* literal next char */ \
}
-#endif /* __rioinfo_h */
+#endif /* __rioinfo_h */
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index 898a126ae3e6..0d44ef464e6b 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -87,222 +87,8 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
int RIOPCIinit(struct rio_info *p, int Mode);
-#if 0
-static void RIOAllocateInterrupts(struct rio_info *);
-static int RIOReport(struct rio_info *);
-static void RIOStopInterrupts(struct rio_info *, int, int);
-#endif
-
static int RIOScrub(int, BYTE *, int);
-#if 0
-extern int rio_intr();
-
-/*
-** Init time code.
-*/
-void
-rioinit( p, info )
-struct rio_info * p;
-struct RioHostInfo * info;
-{
- /*
- ** Multi-Host card support - taking the easy way out - sorry !
- ** We allocate and set up the Host and Port structs when the
- ** driver is called to 'install' the first host.
- ** We check for this first 'call' by testing the RIOPortp pointer.
- */
- if ( !p->RIOPortp )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Allocating and setting up driver data structures\n");
-
- RIOAllocDataStructs(p); /* allocate host/port structs */
- RIOSetupDataStructs(p); /* setup topology structs */
- }
-
- RIOInitHosts( p, info ); /* hunt down the hardware */
-
- RIOAllocateInterrupts(p); /* allocate interrupts */
- RIOReport(p); /* show what we found */
-}
-
-/*
-** Initialise the Cards
-*/
-void
-RIOInitHosts(p, info)
-struct rio_info * p;
-struct RioHostInfo * info;
-{
-/*
-** 15.10.1998 ARG - ESIL 0762 part fix
-** If there is no ISA card definition - we always look for PCI cards.
-** As we currently only support one host card this lets an ISA card
-** definition take precedence over PLUG and PLAY.
-** No ISA card - we are PLUG and PLAY with PCI.
-*/
-
- /*
- ** Note - for PCI both these will be zero, that's okay because
- ** RIOPCIInit() fills them in if a card is found.
- */
- p->RIOHosts[p->RIONumHosts].Ivec = info->vector;
- p->RIOHosts[p->RIONumHosts].PaddrP = info->location;
-
- /*
- ** Check that we are able to accommodate another host
- */
- if ( p->RIONumHosts >= RIO_HOSTS )
- {
- p->RIOFailed++;
- return;
- }
-
- if ( info->bus & ISA_BUS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (ISA)\n", p->RIONumHosts);
- RIOISAinit(p, p->mode);
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (PCI)\n", p->RIONumHosts);
- RIOPCIinit(p, RIO_PCI_DEFAULT_MODE);
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Total hosts initialised so far : %d\n", p->RIONumHosts);
-
-
-#ifdef FUTURE_RELEASE
- if (p->bus & EISA_BUS)
- /* EISA card */
- RIOEISAinit(p, RIO_EISA_DEFAULT_MODE);
-
- if (p->bus & MCA_BUS)
- /* MCA card */
- RIOMCAinit(p, RIO_MCA_DEFAULT_MODE);
-#endif
-}
-
-/*
-** go through memory for an AT host that we pass in the device info
-** structure and initialise
-*/
-void
-RIOISAinit(p, mode)
-struct rio_info * p;
-int mode;
-{
-
- /* XXX Need to implement this. */
-#if 0
- p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
- (int (*)())rio_intr, (char*)p->RIONumHosts);
-
- rio_dprintk (RIO_DEBUG_INIT, "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid );
-
- if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) {
- return;
- }
- else {
- rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n");
- p->RIOFailed++;
- }
-#endif
-
-}
-
-/*
-** RIODoAT :
-**
-** Map in a boards physical address, check that the board is there,
-** test the board and if everything is okay assign the board an entry
-** in the Rio Hosts structure.
-*/
-int
-RIODoAT(p, Base, mode)
-struct rio_info * p;
-int Base;
-int mode;
-{
-#define FOUND 1
-#define NOT_FOUND 0
-
- caddr_t cardAddr;
-
- /*
- ** Check to see if we actually have a board at this physical address.
- */
- if ((cardAddr = RIOCheckForATCard(Base)) != 0) {
- /*
- ** Now test the board to see if it is working.
- */
- if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) {
- /*
- ** Fill out a slot in the Rio host structure.
- */
- if (RIOAssignAT(p, Base, cardAddr, mode)) {
- return(FOUND);
- }
- }
- RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr);
- }
- return(NOT_FOUND);
-}
-
-caddr_t
-RIOCheckForATCard(Base)
-int Base;
-{
- int off;
- struct DpRam *cardp; /* (Points at the host) */
- caddr_t virtAddr;
- unsigned char RIOSigTab[24];
-/*
-** Table of values to search for as prom signature of a host card
-*/
- strcpy(RIOSigTab, "JBJGPGGHINSMJPJR");
-
- /*
- ** Hey! Yes, You reading this code! Yo, grab a load a this:
- **
- ** IF the card is using WORD MODE rather than BYTE MODE
- ** then it will occupy 128K of PHYSICAL memory area. So,
- ** you might think that the following Mapin is wrong. Well,
- ** it isn't, because the SECOND 64K of occupied space is an
- ** EXACT COPY of the FIRST 64K. (good?), so, we need only
- ** map it in in one 64K block.
- */
- if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n");
- return((caddr_t)0);
- }
-
- /*
- ** virtAddr points to the DP ram of the system.
- ** We now cast this to a pointer to a RIO Host,
- ** and have a rummage about in the PROM.
- */
- cardp = (struct DpRam *)virtAddr;
-
- for (off=0; RIOSigTab[off]; off++) {
- if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) {
- /*
- ** Signature mismatch - card not at this address
- */
- RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr);
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n",
- (int)cardp, off);
- return((caddr_t)0);
- }
- }
-
- /*
- ** If we get here then we must have found a valid board so return
- ** its virtual address.
- */
- return(virtAddr);
-}
-#endif
/**
** RIOAssignAT :
@@ -367,667 +153,6 @@ int mode;
rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
return(1);
}
-#if 0
-#ifdef FUTURE_RELEASE
-int RIOMCAinit(int Mode)
-{
- uchar SlotNumber;
- caddr_t Caddr;
- uint Paddr;
- uint Ivec;
- int Handle;
- int ret = 0;
-
- /*
- ** Valid mode information for MCA cards
- ** is only FAST LINKS
- */
- Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks;
- rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode);
-
-
- /*
- ** Check out each of the slots
- */
- for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) {
- /*
- ** Enable the slot we want to talk to
- */
- outb( McaSlotSelect, SlotNumber | McaSlotEnable );
-
- /*
- ** Read the ID word from the slot
- */
- if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId)
- {
- rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber);
-
- /*
- ** Card appears to be a RIO MCA card!
- */
- RIOMachineType |= (1<<RIO_MCA);
-
- /*
- ** Just check we haven't found too many wonderful objects
- */
- if ( RIONumHosts >= RIO_HOSTS )
- {
- Rprintf(RIOMesgTooManyCards);
- return(ret);
- }
-
- /*
- ** McaIrqEnable contains the interrupt vector, and a card
- ** enable bit.
- */
- Ivec = inb(McaIrqEnable);
-
- rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec);
-
- switch ( Ivec & McaIrqMask )
- {
- case McaIrq9:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n");
- break;
- case McaIrq3:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n");
- break;
- case McaIrq4:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n");
- break;
- case McaIrq7:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n");
- break;
- case McaIrq10:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n");
- break;
- case McaIrq11:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n");
- break;
- case McaIrq12:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n");
- break;
- case McaIrq15:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n");
- break;
- }
-
- /*
- ** If the card enable bit isn't set, then set it!
- */
- if ((Ivec & McaCardEnable) != McaCardEnable) {
- rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n");
- outb(McaIrqEnable,Ivec|McaCardEnable);
- } else
- rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n");
-
- /*
- ** Convert the IRQ enable mask into something useful
- */
- Ivec = RIOMcaToIvec[Ivec & McaIrqMask];
-
- /*
- ** Find the physical address
- */
- rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory));
- Paddr = McaAddress(inb(McaMemory));
-
- rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr);
-
- if ( Paddr != 0 )
- {
-
- /*
- ** Tell the memory mapper that we want to talk to it
- */
- Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr );
-
- if ( Handle == -1 ) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr;
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
-
- /*
- ** And check that it is actually there!
- */
- if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
- SlotNumber, RIO_MCA, Paddr, Caddr, Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[RIONumHosts].Slot = SlotNumber;
- p->RIOHosts[RIONumHosts].Ivec = Ivec;
- p->RIOHosts[RIONumHosts].Type = RIO_MCA;
- p->RIOHosts[RIONumHosts].Copy = bcopy;
- p->RIOHosts[RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[RIONumHosts].Caddr = Caddr;
- p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[RIONumHosts].Mode = Mode;
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff);
- p->RIOHosts[RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
- RIONumHosts++;
- ret++;
- }
- else
- {
- /*
- ** It failed the test, so ignore it.
- */
- rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
- RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr );
- }
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber);
- }
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
- }
- }
- /*
- ** Now we have checked all the slots, turn off the MCA slot selector
- */
- outb(McaSlotSelect,0);
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
- return ret;
-}
-
-int RIOEISAinit( int Mode )
-{
- static int EISADone = 0;
- uint Paddr;
- int PollIntMixMsgDone = 0;
- caddr_t Caddr;
- ushort Ident;
- uchar EisaSlot;
- uchar Ivec;
- int ret = 0;
-
- /*
- ** The only valid mode information for EISA hosts is fast or slow
- ** links.
- */
- Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS;
-
- if ( EISADone )
- {
- rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n");
- return(0);
- }
-
- EISADone++;
-
- rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n");
-
-
- /*
- ** First check all cards to see if ANY are set for polled mode operation.
- ** If so, set ALL to polled.
- */
-
- for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
- {
- Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
- INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
-
- if ( Ident == RIO_EISA_IDENT )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n");
-
- if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n",
- INBZ(EisaSlot, EISA_PRODUCT_NUMBER));
- continue; /* next slot */
- }
- /*
- ** Its a Specialix RIO!
- */
- rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n",
- INBZ(EisaSlot, EISA_REVISION_NUMBER));
-
- RIOMachineType |= (1<<RIO_EISA);
-
- /*
- ** Just check we haven't found too many wonderful objects
- */
- if ( RIONumHosts >= RIO_HOSTS )
- {
- Rprintf(RIOMesgTooManyCards);
- return 0;
- }
-
- /*
- ** Ensure that the enable bit is set!
- */
- OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
-
- /*
- ** EISA_INTERRUPT_VEC contains the interrupt vector.
- */
- Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
-
-#ifdef RIODEBUG
- switch ( Ivec & EISA_INTERRUPT_MASK )
- {
- case EISA_IRQ_3:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 3\n");
- break;
- case EISA_IRQ_4:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 4\n");
- break;
- case EISA_IRQ_5:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 5\n");
- break;
- case EISA_IRQ_6:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 6\n");
- break;
- case EISA_IRQ_7:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 7\n");
- break;
- case EISA_IRQ_9:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 9\n");
- break;
- case EISA_IRQ_10:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 10\n");
- break;
- case EISA_IRQ_11:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 11\n");
- break;
- case EISA_IRQ_12:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 12\n");
- break;
- case EISA_IRQ_14:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 14\n");
- break;
- case EISA_IRQ_15:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 15\n");
- break;
- case EISA_POLLED:
- rio_dprintk (RIO_DEBUG_INIT, "EISA POLLED\n");
- break;
- default:
- rio_dprintk (RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n");
- Ivec &= EISA_CONTROL_MASK;
- }
-#endif
-
- if ( (Ivec & EISA_INTERRUPT_MASK) ==
- EISA_POLLED )
- {
- RIOWillPoll = 1;
- break; /* From EisaSlot loop */
- }
- }
- }
-
- /*
- ** Do it all again now we know whether to change all cards to polled
- ** mode or not
- */
-
- for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
- {
- Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
- INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
-
- if ( Ident == RIO_EISA_IDENT )
- {
- if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
- continue; /* next slot */
-
- /*
- ** Its a Specialix RIO!
- */
-
- /*
- ** Ensure that the enable bit is set!
- */
- OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
-
- /*
- ** EISA_INTERRUPT_VEC contains the interrupt vector.
- */
- Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
-
- if ( RIOWillPoll )
- {
- /*
- ** If we are going to operate in polled mode, but this
- ** board is configured to be interrupt driven, display
- ** the message explaining the situation to the punter,
- ** assuming we haven't already done so.
- */
-
- if ( !PollIntMixMsgDone &&
- (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED )
- {
- Rprintf(RIOMesgAllPolled);
- PollIntMixMsgDone = 1;
- }
-
- /*
- ** Ungraciously ignore whatever the board reports as its
- ** interrupt vector...
- */
-
- Ivec &= ~EISA_INTERRUPT_MASK;
-
- /*
- ** ...and force it to dance to the poll tune.
- */
-
- Ivec |= EISA_POLLED;
- }
-
- /*
- ** Convert the IRQ enable mask into something useful (0-15)
- */
- Ivec = RIOEisaToIvec(Ivec);
-
- rio_dprintk (RIO_DEBUG_INIT, "EISA host in slot %d has Ivec 0x%x\n",
- EisaSlot, Ivec);
-
- /*
- ** Find the physical address
- */
- Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) |
- (INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16);
-
- rio_dprintk (RIO_DEBUG_INIT, "EISA card has Ivec %d Addr %x\n", Ivec, Paddr);
-
- if ( Paddr == 0 )
- {
- rio_dprintk (RIO_DEBUG_INIT,
- "Board in slot %d configured for address zero!\n", EisaSlot);
- continue;
- }
-
- /*
- ** Tell the memory mapper that we want to talk to it
- */
- rio_dprintk (RIO_DEBUG_INIT, "About to map EISA card \n");
-
- if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n",
- RIO_EISA_MEM_SIZE,Paddr);
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
-
- /*
- ** And check that it is actually there!
- */
- if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT,
- "Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
- EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[RIONumHosts].Slot = EisaSlot;
- p->RIOHosts[RIONumHosts].Ivec = Ivec;
- p->RIOHosts[RIONumHosts].Type = RIO_EISA;
- p->RIOHosts[RIONumHosts].Copy = bcopy;
- p->RIOHosts[RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[RIONumHosts].Caddr = Caddr;
- p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[RIONumHosts].Mode = Mode;
- /*
- ** because the EISA prom is mapped into IO space, we
- ** need to copy the unqiue number into the memory area
- ** that it would have occupied, so that the download
- ** code can determine its ID and card type.
- */
- WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3));
- p->RIOHosts[RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
- INBZ(EisaSlot,EISA_INTERRUPT_RESET);
- RIONumHosts++;
- ret++;
- }
- else
- {
- /*
- ** It failed the test, so ignore it.
- */
- rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
-
- RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr );
- }
- }
- }
- if (RIOMachineType & RIO_EISA)
- return ret+1;
- return ret;
-}
-#endif
-
-
-#ifndef linux
-
-#define CONFIG_ADDRESS 0xcf8
-#define CONFIG_DATA 0xcfc
-#define FORWARD_REG 0xcfa
-
-
-static int
-read_config(int bus_number, int device_num, int r_number)
-{
- unsigned int cav;
- unsigned int val;
-
-/*
- Build config_address_value:
-
- 31 24 23 16 15 11 10 8 7 0
- ------------------------------------------------------
- |1| 0000000 | bus_number | device # | 000 | register |
- ------------------------------------------------------
-*/
-
- cav = r_number & 0xff;
- cav |= ((device_num & 0x1f) << 11);
- cav |= ((bus_number & 0xff) << 16);
- cav |= 0x80000000; /* Enable bit */
- outpd(CONFIG_ADDRESS,cav);
- val = inpd(CONFIG_DATA);
- outpd(CONFIG_ADDRESS,0);
- return val;
-}
-
-static
-write_config(bus_number,device_num,r_number,val)
-{
- unsigned int cav;
-
-/*
- Build config_address_value:
-
- 31 24 23 16 15 11 10 8 7 0
- ------------------------------------------------------
- |1| 0000000 | bus_number | device # | 000 | register |
- ------------------------------------------------------
-*/
-
- cav = r_number & 0xff;
- cav |= ((device_num & 0x1f) << 11);
- cav |= ((bus_number & 0xff) << 16);
- cav |= 0x80000000; /* Enable bit */
- outpd(CONFIG_ADDRESS, cav);
- outpd(CONFIG_DATA, val);
- outpd(CONFIG_ADDRESS, 0);
- return val;
-}
-#else
-/* XXX Implement these... */
-static int
-read_config(int bus_number, int device_num, int r_number)
-{
- return 0;
-}
-
-static int
-write_config(int bus_number, int device_num, int r_number)
-{
- return 0;
-}
-
-#endif
-
-int
-RIOPCIinit(p, Mode)
-struct rio_info *p;
-int Mode;
-{
- #define MAX_PCI_SLOT 32
- #define RIO_PCI_JET_CARD 0x200011CB
-
- static int slot; /* count of machine's PCI slots searched so far */
- caddr_t Caddr; /* Virtual address of the current PCI host card. */
- unsigned char Ivec; /* interrupt vector for the current PCI host */
- unsigned long Paddr; /* Physical address for the current PCI host */
- int Handle; /* Handle to Virtual memory allocated for current PCI host */
-
-
- rio_dprintk (RIO_DEBUG_INIT, "Search for a RIO PCI card - start at slot %d\n", slot);
-
- /*
- ** Initialise the search status
- */
- p->RIOLastPCISearch = RIO_FAIL;
-
- while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Currently testing slot %d\n", slot);
-
- if (read_config(0,slot,0) == RIO_PCI_JET_CARD) {
- p->RIOHosts[p->RIONumHosts].Ivec = 0;
- Paddr = read_config(0,slot,0x18);
- Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */
-
- if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) {
- rio_dprintk (RIO_DEBUG_INIT, "Goofed up slot\n"); /* what! */
- slot++;
- continue;
- }
-
- p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
- Ivec = (read_config(0,slot,0x3c) & 0xff);
-
- rio_dprintk (RIO_DEBUG_INIT, "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec);
-
- Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr );
- if (Handle == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr);
- slot++;
- continue;
- }
- p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
- p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
- (int (*)())rio_intr, (char *)p->RIONumHosts);
- if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) {
- rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[p->RIONumHosts].Slot = 0;
- p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
- p->RIOHosts[p->RIONumHosts].Type = RIO_PCI;
- p->RIOHosts[p->RIONumHosts].Copy = rio_pcicopy;
- p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[p->RIONumHosts].Caddr = Caddr;
- p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[p->RIONumHosts].Mode = Mode;
-
-#if 0
- WBYTE(p->RIOHosts[p->RIONumHosts].Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
- p->RIOHosts[p->RIONumHosts].Mode |
- INTERRUPT_DISABLE );
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
- WBYTE(p->RIOHosts[p->RIONumHosts].Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
- p->RIOHosts[p->RIONumHosts].Mode |
- INTERRUPT_DISABLE );
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
-#else
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
-#endif
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
-
- rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- }
- }
- slot++;
- }
-
- if ( slot >= MAX_PCI_SLOT ) {
- rio_dprintk (RIO_DEBUG_INIT, "All %d PCI slots have tested for RIO cards !!!\n",
- MAX_PCI_SLOT);
- }
-
-
- /*
- ** I don't think we want to do this anymore
- **
-
- if (!p->RIOLastPCISearch == RIO_FAIL ) {
- p->RIOFailed++;
- }
-
- **
- */
-}
-
-#ifdef FUTURE_RELEASE
-void riohalt( void )
-{
- int host;
- for ( host=0; host<p->RIONumHosts; host++ )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host);
- (void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot );
- }
-}
-#endif
-#endif
static uchar val[] = {
#ifdef VERY_LONG_TEST
@@ -1262,200 +387,6 @@ int size;
return RIO_SUCCESS;
}
-/*
-** try to ensure that every host is either in polled mode
-** or is in interrupt mode. Only allow interrupt mode if
-** all hosts can interrupt (why?)
-** and force into polled mode if told to. Patch up the
-** interrupt vector & salute The Queen when you've done.
-*/
-#if 0
-static void
-RIOAllocateInterrupts(p)
-struct rio_info * p;
-{
- int Host;
-
- /*
- ** Easy case - if we have been told to poll, then we poll.
- */
- if (p->mode & POLLED_MODE) {
- RIOStopInterrupts(p, 0, 0);
- return;
- }
-
- /*
- ** check - if any host has been set to polled mode, then all must be.
- */
- for (Host=0; Host<p->RIONumHosts; Host++) {
- if ( (p->RIOHosts[Host].Type != RIO_AT) &&
- (p->RIOHosts[Host].Ivec == POLLED) ) {
- RIOStopInterrupts(p, 1, Host );
- return;
- }
- }
- for (Host=0; Host<p->RIONumHosts; Host++) {
- if (p->RIOHosts[Host].Type == RIO_AT) {
- if ( (p->RIOHosts[Host].Ivec - 32) == 0) {
- RIOStopInterrupts(p, 2, Host );
- return;
- }
- }
- }
-}
-
-/*
-** something has decided that we can't be doing with these
-** new-fangled interrupt thingies. Set everything up to just
-** poll.
-*/
-static void
-RIOStopInterrupts(p, Reason, Host)
-struct rio_info * p;
-int Reason;
-int Host;
-{
-#ifdef FUTURE_RELEASE
- switch (Reason) {
- case 0: /* forced into polling by rio_polled */
- break;
- case 1: /* SCU has set 'Host' into polled mode */
- break;
- case 2: /* there aren't enough interrupt vectors for 'Host' */
- break;
- }
-#endif
-
- for (Host=0; Host<p->RIONumHosts; Host++ ) {
- struct Host *HostP = &p->RIOHosts[Host];
-
- switch (HostP->Type) {
- case RIO_AT:
- /*
- ** The AT host has it's interrupts disabled by clearing the
- ** int_enable bit.
- */
- HostP->Mode &= ~INTERRUPT_ENABLE;
- HostP->Ivec = POLLED;
- break;
-#ifdef FUTURE_RELEASE
- case RIO_EISA:
- /*
- ** The EISA host has it's interrupts disabled by setting the
- ** Ivec to zero
- */
- HostP->Ivec = POLLED;
- break;
-#endif
- case RIO_PCI:
- /*
- ** The PCI host has it's interrupts disabled by clearing the
- ** int_enable bit, like a regular host card.
- */
- HostP->Mode &= ~RIO_PCI_INT_ENABLE;
- HostP->Ivec = POLLED;
- break;
-#ifdef FUTURE_RELEASE
- case RIO_MCA:
- /*
- ** There's always one, isn't there?
- ** The MCA host card cannot have it's interrupts disabled.
- */
- RIOPatchVec(HostP);
- break;
-#endif
- }
- }
-}
-
-/*
-** This function is called at init time to setup the data structures.
-*/
-void
-RIOAllocDataStructs(p)
-struct rio_info * p;
-{
- int port,
- host,
- tm;
-
- p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port));
- if (!p->RIOPortp) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n");
- p->RIOFailed++;
- return;
- }
- bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS );
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for port structs\n");
- rio_dprintk (RIO_DEBUG_INIT, "First RIO port struct @0x%x, size=0x%x bytes\n",
- (int)p->RIOPortp, sizeof(struct Port));
-
- for( port=0; port<RIO_PORTS; port++ ) {
- p->RIOPortp[port].PortNum = port;
- p->RIOPortp[port].TtyP = &p->channel[port];
- sreset (p->RIOPortp[port].InUse); /* Let the first guy uses it */
- p->RIOPortp[port].portSem = -1; /* Let the first guy takes it */
- p->RIOPortp[port].ParamSem = -1; /* Let the first guy takes it */
- p->RIOPortp[port].timeout_id = 0; /* Let the first guy takes it */
- }
-
- p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host));
- if (!p->RIOHosts) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n");
- p->RIOFailed++;
- return;
- }
- bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS);
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for host structs\n");
- rio_dprintk (RIO_DEBUG_INIT, "First RIO host struct @0x%x, size=0x%x bytes\n",
- (int)p->RIOHosts, sizeof(struct Host));
-
- for( host=0; host<RIO_HOSTS; host++ ) {
- spin_lock_init (&p->RIOHosts[host].HostLock);
- p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
- }
- /*
- ** check that the buffer size is valid, round down to the next power of
- ** two if necessary; if the result is zero, then, hey, no double buffers.
- */
- for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 )
- ;
- tm >>= 1;
- p->RIOBufferSize = tm;
- p->RIOBufferMask = tm ? tm - 1 : 0;
-}
-
-/*
-** this function gets called whenever the data structures need to be
-** re-setup, for example, after a riohalt (why did I ever invent it?)
-*/
-void
-RIOSetupDataStructs(p)
-struct rio_info * p;
-{
- int host, entry, rup;
-
- for ( host=0; host<RIO_HOSTS; host++ ) {
- struct Host *HostP = &p->RIOHosts[host];
- for ( entry=0; entry<LINKS_PER_UNIT; entry++ ) {
- HostP->Topology[entry].Unit = ROUTE_DISCONNECT;
- HostP->Topology[entry].Link = NO_LINK;
- }
- bcopy("HOST X", HostP->Name, 7);
- HostP->Name[5] = '1'+host;
- for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) {
- if (rup < MAX_RUP) {
- for (entry=0; entry<LINKS_PER_UNIT; entry++ ) {
- HostP->Mapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT;
- HostP->Mapping[rup].Topology[entry].Link = NO_LINK;
- }
- RIODefaultName(p, HostP, rup);
- }
- spin_lock_init(&HostP->UnixRups[rup].RupLock);
- }
- }
-}
-#endif
int
RIODefaultName(p, HostP, UnitId)
@@ -1463,10 +394,6 @@ struct rio_info * p;
struct Host * HostP;
uint UnitId;
{
-#ifdef CHECK
- CheckHost( Host );
- CheckUnitId( UnitId );
-#endif
bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17);
HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
if ((UnitId+1) > 9) {
@@ -1483,33 +410,6 @@ uint UnitId;
#define RIO_RELEASE "Linux"
#define RELEASE_ID "1.0"
-#if 0
-static int
-RIOReport(p)
-struct rio_info * p;
-{
- char * RIORelease = RIO_RELEASE;
- char * RIORelID = RELEASE_ID;
- int host;
-
- rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID);
-
- if ( p->RIONumHosts==0 ) {
- rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n");
- return(0);
- }
-
- for ( host=0; host < p->RIONumHosts; host++ ) {
- struct Host *HostP = &p->RIOHosts[host];
- switch ( HostP->Type ) {
- case RIO_AT:
- rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP);
- }
- }
- return 0;
-}
-#endif
-
static struct rioVersion stVersion;
struct rioVersion *
@@ -1523,27 +423,6 @@ RIOVersid(void)
return &stVersion;
}
-#if 0
-int
-RIOMapin(paddr, size, vaddr)
-paddr_t paddr;
-int size;
-caddr_t * vaddr;
-{
- *vaddr = (caddr_t)permap( (long)paddr, size);
- return ((int)*vaddr);
-}
-
-void
-RIOMapout(paddr, size, vaddr)
-paddr_t paddr;
-long size;
-caddr_t vaddr;
-{
-}
-#endif
-
-
void
RIOHostReset(Type, DpRamP, Slot)
uint Type;
@@ -1570,31 +449,6 @@ uint Slot;
WBYTE(DpRamP->DpResetTpu, 0xFF);
udelay(3);
break;
-#ifdef FUTURE_RELEASE
- case RIO_EISA:
- /*
- ** Bet this doesn't work!
- */
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RUN | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RESET | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- suspend( 3 );
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RUN | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- break;
- case RIO_MCA:
- WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable );
- WBYTE(DpRamP->DpResetTpu , 0xFF );
- suspend( 3 );
- WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable );
- WBYTE(DpRamP->DpResetTpu , 0xFF );
- suspend( 3 );
- break;
-#endif
case RIO_PCI:
rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM;
@@ -1604,12 +458,6 @@ uint Slot;
/* for (i=0; i<6000; i++); */
/* suspend( 3 ); */
break;
-#ifdef FUTURE_RELEASE
- default:
- Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot);
- return;
-#endif
-
default:
rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
break;
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
index e42e7b50bf6b..34d8787557a1 100644
--- a/drivers/char/rio/riointr.c
+++ b/drivers/char/rio/riointr.c
@@ -38,6 +38,7 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/string.h>
@@ -87,99 +88,93 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
static void RIOReceive(struct rio_info *, struct Port *);
-static char *firstchars (char *p, int nch)
+static char *firstchars(char *p, int nch)
{
- static char buf[2][128];
- static int t=0;
- t = ! t;
- memcpy (buf[t], p, nch);
- buf[t][nch] = 0;
- return buf[t];
+ static char buf[2][128];
+ static int t = 0;
+ t = !t;
+ memcpy(buf[t], p, nch);
+ buf[t][nch] = 0;
+ return buf[t];
}
#define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask))
/* Enable and start the transmission of packets */
-void
-RIOTxEnable(en)
-char * en;
+void RIOTxEnable(en)
+char *en;
{
- struct Port * PortP;
- struct rio_info *p;
- struct tty_struct* tty;
- int c;
- struct PKT * PacketP;
- unsigned long flags;
-
- PortP = (struct Port *)en;
- p = (struct rio_info *)PortP->p;
- tty = PortP->gs.tty;
-
-
- rio_dprintk (RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n",
- PortP->PortNum, PortP->gs.xmit_cnt);
-
- if (!PortP->gs.xmit_cnt) return;
-
-
- /* This routine is an order of magnitude simpler than the specialix
- version. One of the disadvantages is that this version will send
- an incomplete packet (usually 64 bytes instead of 72) once for
- every 4k worth of data. Let's just say that this won't influence
- performance significantly..... */
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- while (can_add_transmit( &PacketP, PortP )) {
- c = PortP->gs.xmit_cnt;
- if (c > PKT_MAX_DATA_LEN) c = PKT_MAX_DATA_LEN;
-
- /* Don't copy past the end of the source buffer */
- if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
- c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
-
- { int t;
- t = (c > 10)?10:c;
-
- rio_dprintk (RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n",
- PortP->PortNum, c,
- firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail , t),
- firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail + c-t, t));
- }
- /* If for one reason or another, we can't copy more data,
- we're done! */
- if (c == 0) break;
-
- rio_memcpy_toio (PortP->HostP->Caddr, (caddr_t)PacketP->data,
- PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
- /* udelay (1); */
-
- writeb (c, &(PacketP->len));
- if (!( PortP->State & RIO_DELETED ) ) {
- add_transmit ( PortP );
- /*
- ** Count chars tx'd for port statistics reporting
- */
- if ( PortP->statsGather )
- PortP->txchars += c;
- }
- PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1);
- PortP->gs.xmit_cnt -= c;
- }
-
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
- if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2*PKT_MAX_DATA_LEN)) {
- rio_dprintk (RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....",
- (int)(PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)),
- PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
- if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- PortP->gs.tty->ldisc.write_wakeup)
- (PortP->gs.tty->ldisc.write_wakeup)(PortP->gs.tty);
- rio_dprintk (RIO_DEBUG_INTR, "(%d/%d)\n",
- PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
- wake_up_interruptible(&PortP->gs.tty->write_wait);
- }
+ struct Port *PortP;
+ struct rio_info *p;
+ struct tty_struct *tty;
+ int c;
+ struct PKT *PacketP;
+ unsigned long flags;
+
+ PortP = (struct Port *) en;
+ p = (struct rio_info *) PortP->p;
+ tty = PortP->gs.tty;
+
+
+ rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
+
+ if (!PortP->gs.xmit_cnt)
+ return;
+
+
+ /* This routine is an order of magnitude simpler than the specialix
+ version. One of the disadvantages is that this version will send
+ an incomplete packet (usually 64 bytes instead of 72) once for
+ every 4k worth of data. Let's just say that this won't influence
+ performance significantly..... */
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ while (can_add_transmit(&PacketP, PortP)) {
+ c = PortP->gs.xmit_cnt;
+ if (c > PKT_MAX_DATA_LEN)
+ c = PKT_MAX_DATA_LEN;
+
+ /* Don't copy past the end of the source buffer */
+ if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
+ c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
+
+ {
+ int t;
+ t = (c > 10) ? 10 : c;
+
+ rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
+ }
+ /* If for one reason or another, we can't copy more data,
+ we're done! */
+ if (c == 0)
+ break;
+
+ rio_memcpy_toio(PortP->HostP->Caddr, (caddr_t) PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
+ /* udelay (1); */
+
+ writeb(c, &(PacketP->len));
+ if (!(PortP->State & RIO_DELETED)) {
+ add_transmit(PortP);
+ /*
+ ** Count chars tx'd for port statistics reporting
+ */
+ if (PortP->statsGather)
+ PortP->txchars += c;
+ }
+ PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
+ PortP->gs.xmit_cnt -= c;
+ }
+
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+ if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) {
+ rio_dprintk(RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", (int) (PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
+ if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && PortP->gs.tty->ldisc.write_wakeup)
+ (PortP->gs.tty->ldisc.write_wakeup) (PortP->gs.tty);
+ rio_dprintk(RIO_DEBUG_INTR, "(%d/%d)\n", PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
+ wake_up_interruptible(&PortP->gs.tty->write_wait);
+ }
}
@@ -188,361 +183,349 @@ char * en;
** RIO Host Service routine. Does all the work traditionally associated with an
** interrupt.
*/
-static int RupIntr;
-static int RxIntr;
-static int TxIntr;
-void
-RIOServiceHost(p, HostP, From)
-struct rio_info * p;
+static int RupIntr;
+static int RxIntr;
+static int TxIntr;
+void RIOServiceHost(p, HostP, From)
+struct rio_info *p;
struct Host *HostP;
-int From;
+int From;
{
- rio_spin_lock (&HostP->HostLock);
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
- static int t =0;
- rio_spin_unlock (&HostP->HostLock);
- if ((t++ % 200) == 0)
- rio_dprintk (RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int)HostP->Flags);
- return;
- }
- rio_spin_unlock (&HostP->HostLock);
-
- if ( RWORD( HostP->ParmMapP->rup_intr ) ) {
- WWORD( HostP->ParmMapP->rup_intr , 0 );
- p->RIORupCount++;
- RupIntr++;
- rio_dprintk (RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP-p->RIOHosts);
- RIOPollHostCommands(p, HostP );
- }
-
- if ( RWORD( HostP->ParmMapP->rx_intr ) ) {
- int port;
-
- WWORD( HostP->ParmMapP->rx_intr , 0 );
- p->RIORxCount++;
- RxIntr++;
-
- rio_dprintk (RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP-p->RIOHosts);
- /*
- ** Loop through every port. If the port is mapped into
- ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
- ** worth checking. If the port isn't open, grab any packets
- ** hanging on its receive queue and stuff them on the free
- ** list; check for commands on the way.
- */
- for ( port=p->RIOFirstPortsBooted;
- port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
- struct Port *PortP = p->RIOPortp[port];
- struct tty_struct *ttyP;
- struct PKT *PacketP;
-
- /*
- ** not mapped in - most of the RIOPortp[] information
- ** has not been set up!
- ** Optimise: ports come in bundles of eight.
- */
- if ( !PortP->Mapped ) {
- port += 7;
- continue; /* with the next port */
- }
-
- /*
- ** If the host board isn't THIS host board, check the next one.
- ** optimise: ports come in bundles of eight.
- */
- if ( PortP->HostP != HostP ) {
- port += 7;
- continue;
- }
-
- /*
- ** Let us see - is the port open? If not, then don't service it.
- */
- if ( !( PortP->PortState & PORT_ISOPEN ) ) {
- continue;
- }
-
- /*
- ** find corresponding tty structure. The process of mapping
- ** the ports puts these here.
- */
- ttyP = PortP->gs.tty;
-
- /*
- ** Lock the port before we begin working on it.
- */
- rio_spin_lock(&PortP->portSem);
-
- /*
- ** Process received data if there is any.
- */
- if ( can_remove_receive( &PacketP, PortP ) )
- RIOReceive(p, PortP);
-
- /*
- ** If there is no data left to be read from the port, and
- ** it's handshake bit is set, then we must clear the handshake,
- ** so that that downstream RTA is re-enabled.
- */
- if ( !can_remove_receive( &PacketP, PortP ) &&
- ( RWORD( PortP->PhbP->handshake )==PHB_HANDSHAKE_SET ) ) {
+ rio_spin_lock(&HostP->HostLock);
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ static int t = 0;
+ rio_spin_unlock(&HostP->HostLock);
+ if ((t++ % 200) == 0)
+ rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
+ return;
+ }
+ rio_spin_unlock(&HostP->HostLock);
+
+ if (RWORD(HostP->ParmMapP->rup_intr)) {
+ WWORD(HostP->ParmMapP->rup_intr, 0);
+ p->RIORupCount++;
+ RupIntr++;
+ rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP - p->RIOHosts);
+ RIOPollHostCommands(p, HostP);
+ }
+
+ if (RWORD(HostP->ParmMapP->rx_intr)) {
+ int port;
+
+ WWORD(HostP->ParmMapP->rx_intr, 0);
+ p->RIORxCount++;
+ RxIntr++;
+
+ rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP - p->RIOHosts);
+ /*
+ ** Loop through every port. If the port is mapped into
+ ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
+ ** worth checking. If the port isn't open, grab any packets
+ ** hanging on its receive queue and stuff them on the free
+ ** list; check for commands on the way.
+ */
+ for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
+ struct Port *PortP = p->RIOPortp[port];
+ struct tty_struct *ttyP;
+ struct PKT *PacketP;
+
+ /*
+ ** not mapped in - most of the RIOPortp[] information
+ ** has not been set up!
+ ** Optimise: ports come in bundles of eight.
+ */
+ if (!PortP->Mapped) {
+ port += 7;
+ continue; /* with the next port */
+ }
+
+ /*
+ ** If the host board isn't THIS host board, check the next one.
+ ** optimise: ports come in bundles of eight.
+ */
+ if (PortP->HostP != HostP) {
+ port += 7;
+ continue;
+ }
+
+ /*
+ ** Let us see - is the port open? If not, then don't service it.
+ */
+ if (!(PortP->PortState & PORT_ISOPEN)) {
+ continue;
+ }
+
+ /*
+ ** find corresponding tty structure. The process of mapping
+ ** the ports puts these here.
+ */
+ ttyP = PortP->gs.tty;
+
+ /*
+ ** Lock the port before we begin working on it.
+ */
+ rio_spin_lock(&PortP->portSem);
+
+ /*
+ ** Process received data if there is any.
+ */
+ if (can_remove_receive(&PacketP, PortP))
+ RIOReceive(p, PortP);
+
+ /*
+ ** If there is no data left to be read from the port, and
+ ** it's handshake bit is set, then we must clear the handshake,
+ ** so that that downstream RTA is re-enabled.
+ */
+ if (!can_remove_receive(&PacketP, PortP) && (RWORD(PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
/*
- ** MAGIC! ( Basically, handshake the RX buffer, so that
- ** the RTAs upstream can be re-enabled. )
- */
- rio_dprintk (RIO_DEBUG_INTR, "Set RX handshake bit\n");
- WWORD( PortP->PhbP->handshake,
- PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET );
- }
- rio_spin_unlock(&PortP->portSem);
- }
- }
-
- if ( RWORD( HostP->ParmMapP->tx_intr ) ) {
- int port;
-
- WWORD( HostP->ParmMapP->tx_intr , 0);
-
- p->RIOTxCount++;
- TxIntr++;
- rio_dprintk (RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP-p->RIOHosts);
-
- /*
- ** Loop through every port.
- ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
- ** associated ) then it is worth checking.
- */
- for ( port=p->RIOFirstPortsBooted;
- port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
- struct Port *PortP = p->RIOPortp[port];
- struct tty_struct *ttyP;
- struct PKT *PacketP;
-
- /*
- ** not mapped in - most of the RIOPortp[] information
- ** has not been set up!
- */
- if ( !PortP->Mapped ) {
- port += 7;
- continue; /* with the next port */
- }
-
- /*
- ** If the host board isn't running, then its data structures
- ** are no use to us - continue quietly.
- */
- if ( PortP->HostP != HostP ) {
- port += 7;
- continue; /* with the next port */
- }
-
- /*
- ** Let us see - is the port open? If not, then don't service it.
- */
- if ( !( PortP->PortState & PORT_ISOPEN ) ) {
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
- /*
- ** Lock the port before we begin working on it.
- */
- rio_spin_lock(&PortP->portSem);
-
- /*
- ** If we can't add anything to the transmit queue, then
- ** we need do none of this processing.
- */
- if ( !can_add_transmit( &PacketP, PortP ) ) {
- rio_dprintk (RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
-
- /*
- ** find corresponding tty structure. The process of mapping
- ** the ports puts these here.
- */
- ttyP = PortP->gs.tty;
- /* If ttyP is NULL, the port is getting closed. Forget about it. */
- if (!ttyP) {
- rio_dprintk (RIO_DEBUG_INTR, "no tty, so skipping.\n");
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
- /*
- ** If there is more room available we start up the transmit
- ** data process again. This can be direct I/O, if the cookmode
- ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
- ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
- ** characters via the line discipline. We must always call
- ** the line discipline,
- ** so that user input characters can be echoed correctly.
- **
- ** ++++ Update +++++
- ** With the advent of double buffering, we now see if
- ** TxBufferOut-In is non-zero. If so, then we copy a packet
- ** to the output place, and set it going. If this empties
- ** the buffer, then we must issue a wakeup( ) on OUT.
- ** If it frees space in the buffer then we must issue
- ** a wakeup( ) on IN.
- **
- ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
- ** have to send a WFLUSH command down the PHB, to mark the
- ** end point of a WFLUSH. We also need to clear out any
- ** data from the double buffer! ( note that WflushFlag is a
- ** *count* of the number of WFLUSH commands outstanding! )
- **
- ** ++++ And there's more!
- ** If an RTA is powered off, then on again, and rebooted,
- ** whilst it has ports open, then we need to re-open the ports.
- ** ( reasonable enough ). We can't do this when we spot the
- ** re-boot, in interrupt time, because the queue is probably
- ** full. So, when we come in here, we need to test if any
- ** ports are in this condition, and re-open the port before
- ** we try to send any more data to it. Now, the re-booted
- ** RTA will be discarding packets from the PHB until it
- ** receives this open packet, but don't worry tooo much
- ** about that. The one thing that is interesting is the
- ** combination of this effect and the WFLUSH effect!
- */
- /* For now don't handle RTA reboots. -- REW.
- Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
- if ( PortP->MagicFlags ) {
-#if 1
- if ( PortP->MagicFlags & MAGIC_REBOOT ) {
- /*
- ** well, the RTA has been rebooted, and there is room
- ** on its queue to add the open packet that is required.
- **
- ** The messy part of this line is trying to decide if
- ** we need to call the Param function as a tty or as
- ** a modem.
- ** DONT USE CLOCAL AS A TEST FOR THIS!
- **
- ** If we can't param the port, then move on to the
- ** next port.
- */
- PortP->InUse = NOT_INUSE;
-
- rio_spin_unlock(&PortP->portSem);
- if ( RIOParam(PortP, OPEN, ((PortP->Cor2Copy &
- (COR2_RTSFLOW|COR2_CTSFLOW ) )==
- (COR2_RTSFLOW|COR2_CTSFLOW ) ) ?
- TRUE : FALSE, DONT_SLEEP ) == RIO_FAIL ) {
- continue; /* with next port */
- }
- rio_spin_lock(&PortP->portSem);
- PortP->MagicFlags &= ~MAGIC_REBOOT;
+ ** MAGIC! ( Basically, handshake the RX buffer, so that
+ ** the RTAs upstream can be re-enabled. )
+ */
+ rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
+ WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET);
+ }
+ rio_spin_unlock(&PortP->portSem);
+ }
}
+
+ if (RWORD(HostP->ParmMapP->tx_intr)) {
+ int port;
+
+ WWORD(HostP->ParmMapP->tx_intr, 0);
+
+ p->RIOTxCount++;
+ TxIntr++;
+ rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP - p->RIOHosts);
+
+ /*
+ ** Loop through every port.
+ ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
+ ** associated ) then it is worth checking.
+ */
+ for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
+ struct Port *PortP = p->RIOPortp[port];
+ struct tty_struct *ttyP;
+ struct PKT *PacketP;
+
+ /*
+ ** not mapped in - most of the RIOPortp[] information
+ ** has not been set up!
+ */
+ if (!PortP->Mapped) {
+ port += 7;
+ continue; /* with the next port */
+ }
+
+ /*
+ ** If the host board isn't running, then its data structures
+ ** are no use to us - continue quietly.
+ */
+ if (PortP->HostP != HostP) {
+ port += 7;
+ continue; /* with the next port */
+ }
+
+ /*
+ ** Let us see - is the port open? If not, then don't service it.
+ */
+ if (!(PortP->PortState & PORT_ISOPEN)) {
+ continue;
+ }
+
+ rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
+ /*
+ ** Lock the port before we begin working on it.
+ */
+ rio_spin_lock(&PortP->portSem);
+
+ /*
+ ** If we can't add anything to the transmit queue, then
+ ** we need do none of this processing.
+ */
+ if (!can_add_transmit(&PacketP, PortP)) {
+ rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+
+ /*
+ ** find corresponding tty structure. The process of mapping
+ ** the ports puts these here.
+ */
+ ttyP = PortP->gs.tty;
+ /* If ttyP is NULL, the port is getting closed. Forget about it. */
+ if (!ttyP) {
+ rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+ /*
+ ** If there is more room available we start up the transmit
+ ** data process again. This can be direct I/O, if the cookmode
+ ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
+ ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
+ ** characters via the line discipline. We must always call
+ ** the line discipline,
+ ** so that user input characters can be echoed correctly.
+ **
+ ** ++++ Update +++++
+ ** With the advent of double buffering, we now see if
+ ** TxBufferOut-In is non-zero. If so, then we copy a packet
+ ** to the output place, and set it going. If this empties
+ ** the buffer, then we must issue a wakeup( ) on OUT.
+ ** If it frees space in the buffer then we must issue
+ ** a wakeup( ) on IN.
+ **
+ ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
+ ** have to send a WFLUSH command down the PHB, to mark the
+ ** end point of a WFLUSH. We also need to clear out any
+ ** data from the double buffer! ( note that WflushFlag is a
+ ** *count* of the number of WFLUSH commands outstanding! )
+ **
+ ** ++++ And there's more!
+ ** If an RTA is powered off, then on again, and rebooted,
+ ** whilst it has ports open, then we need to re-open the ports.
+ ** ( reasonable enough ). We can't do this when we spot the
+ ** re-boot, in interrupt time, because the queue is probably
+ ** full. So, when we come in here, we need to test if any
+ ** ports are in this condition, and re-open the port before
+ ** we try to send any more data to it. Now, the re-booted
+ ** RTA will be discarding packets from the PHB until it
+ ** receives this open packet, but don't worry tooo much
+ ** about that. The one thing that is interesting is the
+ ** combination of this effect and the WFLUSH effect!
+ */
+ /* For now don't handle RTA reboots. -- REW.
+ Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
+ if (PortP->MagicFlags) {
+#if 1
+ if (PortP->MagicFlags & MAGIC_REBOOT) {
+ /*
+ ** well, the RTA has been rebooted, and there is room
+ ** on its queue to add the open packet that is required.
+ **
+ ** The messy part of this line is trying to decide if
+ ** we need to call the Param function as a tty or as
+ ** a modem.
+ ** DONT USE CLOCAL AS A TEST FOR THIS!
+ **
+ ** If we can't param the port, then move on to the
+ ** next port.
+ */
+ PortP->InUse = NOT_INUSE;
+
+ rio_spin_unlock(&PortP->portSem);
+ if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? TRUE : FALSE, DONT_SLEEP) == RIO_FAIL) {
+ continue; /* with next port */
+ }
+ rio_spin_lock(&PortP->portSem);
+ PortP->MagicFlags &= ~MAGIC_REBOOT;
+ }
#endif
- /*
- ** As mentioned above, this is a tacky hack to cope
- ** with WFLUSH
- */
- if ( PortP->WflushFlag ) {
- rio_dprintk (RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
-
- if ( PortP->InUse )
- rio_dprintk (RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
- }
-
- while ( PortP->WflushFlag &&
- can_add_transmit( &PacketP, PortP ) &&
- ( PortP->InUse == NOT_INUSE ) ) {
- int p;
- struct PktCmd *PktCmdP;
-
- rio_dprintk (RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
- /*
- ** make it look just like a WFLUSH command
- */
- PktCmdP = ( struct PktCmd * )&PacketP->data[0];
-
- WBYTE( PktCmdP->Command , WFLUSH );
-
- p = PortP->HostPort % ( ushort )PORTS_PER_RTA;
-
- /*
- ** If second block of ports for 16 port RTA, add 8
- ** to index 8-15.
- */
- if ( PortP->SecondBlock )
- p += PORTS_PER_RTA;
-
- WBYTE( PktCmdP->PhbNum, p );
-
- /*
- ** to make debuggery easier
- */
- WBYTE( PacketP->data[ 2], 'W' );
- WBYTE( PacketP->data[ 3], 'F' );
- WBYTE( PacketP->data[ 4], 'L' );
- WBYTE( PacketP->data[ 5], 'U' );
- WBYTE( PacketP->data[ 6], 'S' );
- WBYTE( PacketP->data[ 7], 'H' );
- WBYTE( PacketP->data[ 8], ' ' );
- WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag );
- WBYTE( PacketP->data[10], ' ' );
- WBYTE( PacketP->data[11], ' ' );
- WBYTE( PacketP->data[12], '\0' );
-
- /*
- ** its two bytes long!
- */
- WBYTE( PacketP->len , PKT_CMD_BIT | 2 );
-
- /*
- ** queue it!
- */
- if ( !( PortP->State & RIO_DELETED ) ) {
- add_transmit( PortP );
- /*
- ** Count chars tx'd for port statistics reporting
- */
- if ( PortP->statsGather )
- PortP->txchars += 2;
- }
-
- if ( --( PortP->WflushFlag ) == 0 ) {
- PortP->MagicFlags &= ~MAGIC_FLUSH;
- }
-
- rio_dprintk (RIO_DEBUG_INTR, "Wflush count now stands at %d\n",
- PortP->WflushFlag);
- }
- if ( PortP->MagicFlags & MORE_OUTPUT_EYGOR ) {
- if ( PortP->MagicFlags & MAGIC_FLUSH ) {
- PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
- }
- else {
- if ( !can_add_transmit( &PacketP, PortP ) ) {
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
- rio_spin_unlock(&PortP->portSem);
- RIOTxEnable((char *)PortP);
- rio_spin_lock(&PortP->portSem);
- PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
- }
+ /*
+ ** As mentioned above, this is a tacky hack to cope
+ ** with WFLUSH
+ */
+ if (PortP->WflushFlag) {
+ rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
+
+ if (PortP->InUse)
+ rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
+ }
+
+ while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
+ int p;
+ struct PktCmd *PktCmdP;
+
+ rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
+ /*
+ ** make it look just like a WFLUSH command
+ */
+ PktCmdP = (struct PktCmd *) &PacketP->data[0];
+
+ WBYTE(PktCmdP->Command, WFLUSH);
+
+ p = PortP->HostPort % (ushort) PORTS_PER_RTA;
+
+ /*
+ ** If second block of ports for 16 port RTA, add 8
+ ** to index 8-15.
+ */
+ if (PortP->SecondBlock)
+ p += PORTS_PER_RTA;
+
+ WBYTE(PktCmdP->PhbNum, p);
+
+ /*
+ ** to make debuggery easier
+ */
+ WBYTE(PacketP->data[2], 'W');
+ WBYTE(PacketP->data[3], 'F');
+ WBYTE(PacketP->data[4], 'L');
+ WBYTE(PacketP->data[5], 'U');
+ WBYTE(PacketP->data[6], 'S');
+ WBYTE(PacketP->data[7], 'H');
+ WBYTE(PacketP->data[8], ' ');
+ WBYTE(PacketP->data[9], '0' + PortP->WflushFlag);
+ WBYTE(PacketP->data[10], ' ');
+ WBYTE(PacketP->data[11], ' ');
+ WBYTE(PacketP->data[12], '\0');
+
+ /*
+ ** its two bytes long!
+ */
+ WBYTE(PacketP->len, PKT_CMD_BIT | 2);
+
+ /*
+ ** queue it!
+ */
+ if (!(PortP->State & RIO_DELETED)) {
+ add_transmit(PortP);
+ /*
+ ** Count chars tx'd for port statistics reporting
+ */
+ if (PortP->statsGather)
+ PortP->txchars += 2;
+ }
+
+ if (--(PortP->WflushFlag) == 0) {
+ PortP->MagicFlags &= ~MAGIC_FLUSH;
+ }
+
+ rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
+ }
+ if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
+ if (PortP->MagicFlags & MAGIC_FLUSH) {
+ PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+ } else {
+ if (!can_add_transmit(&PacketP, PortP)) {
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+ rio_spin_unlock(&PortP->portSem);
+ RIOTxEnable((char *) PortP);
+ rio_spin_lock(&PortP->portSem);
+ PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+ }
+ }
+ }
+
+
+ /*
+ ** If we can't add anything to the transmit queue, then
+ ** we need do none of the remaining processing.
+ */
+ if (!can_add_transmit(&PacketP, PortP)) {
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+
+ rio_spin_unlock(&PortP->portSem);
+ RIOTxEnable((char *) PortP);
+ }
}
- }
-
-
- /*
- ** If we can't add anything to the transmit queue, then
- ** we need do none of the remaining processing.
- */
- if (!can_add_transmit( &PacketP, PortP ) ) {
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
-
- rio_spin_unlock(&PortP->portSem);
- RIOTxEnable((char *)PortP);
- }
- }
}
/*
@@ -550,180 +533,162 @@ int From;
** NB: Called with the tty locked. The spl from the lockb( ) is passed.
** we return the ttySpl level that we re-locked at.
*/
-static void
-RIOReceive(p, PortP)
-struct rio_info * p;
-struct Port * PortP;
+static void RIOReceive(p, PortP)
+struct rio_info *p;
+struct Port *PortP;
{
- struct tty_struct *TtyP;
- register ushort transCount;
- struct PKT *PacketP;
- register uint DataCnt;
- uchar * ptr;
- int copied =0;
-
- static int intCount, RxIntCnt;
-
- /*
- ** The receive data process is to remove packets from the
- ** PHB until there aren't any more or the current cblock
- ** is full. When this occurs, there will be some left over
- ** data in the packet, that we must do something with.
- ** As we haven't unhooked the packet from the read list
- ** yet, we can just leave the packet there, having first
- ** made a note of how far we got. This means that we need
- ** a pointer per port saying where we start taking the
- ** data from - this will normally be zero, but when we
- ** run out of space it will be set to the offset of the
- ** next byte to copy from the packet data area. The packet
- ** length field is decremented by the number of bytes that
- ** we succesfully removed from the packet. When this reaches
- ** zero, we reset the offset pointer to be zero, and free
- ** the packet from the front of the queue.
- */
-
- intCount++;
-
- TtyP = PortP->gs.tty;
- if (!TtyP) {
- rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
- return;
- }
-
- if (PortP->State & RIO_THROTTLE_RX) {
- rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
- return;
- }
-
- if ( PortP->State & RIO_DELETED )
- {
- while ( can_remove_receive( &PacketP, PortP ) )
- {
- remove_receive( PortP );
- put_free_end( PortP->HostP, PacketP );
+ struct tty_struct *TtyP;
+ register ushort transCount;
+ struct PKT *PacketP;
+ register uint DataCnt;
+ uchar *ptr;
+ unsigned char *buf;
+ int copied = 0;
+
+ static int intCount, RxIntCnt;
+
+ /*
+ ** The receive data process is to remove packets from the
+ ** PHB until there aren't any more or the current cblock
+ ** is full. When this occurs, there will be some left over
+ ** data in the packet, that we must do something with.
+ ** As we haven't unhooked the packet from the read list
+ ** yet, we can just leave the packet there, having first
+ ** made a note of how far we got. This means that we need
+ ** a pointer per port saying where we start taking the
+ ** data from - this will normally be zero, but when we
+ ** run out of space it will be set to the offset of the
+ ** next byte to copy from the packet data area. The packet
+ ** length field is decremented by the number of bytes that
+ ** we succesfully removed from the packet. When this reaches
+ ** zero, we reset the offset pointer to be zero, and free
+ ** the packet from the front of the queue.
+ */
+
+ intCount++;
+
+ TtyP = PortP->gs.tty;
+ if (!TtyP) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
+ return;
}
- }
- else
- {
- /*
- ** loop, just so long as:
- ** i ) there's some data ( i.e. can_remove_receive )
- ** ii ) we haven't been blocked
- ** iii ) there's somewhere to put the data
- ** iv ) we haven't outstayed our welcome
- */
- transCount = 1;
- while ( can_remove_receive(&PacketP, PortP)
- && transCount)
- {
+
+ if (PortP->State & RIO_THROTTLE_RX) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
+ return;
+ }
+
+ if (PortP->State & RIO_DELETED) {
+ while (can_remove_receive(&PacketP, PortP)) {
+ remove_receive(PortP);
+ put_free_end(PortP->HostP, PacketP);
+ }
+ } else {
+ /*
+ ** loop, just so long as:
+ ** i ) there's some data ( i.e. can_remove_receive )
+ ** ii ) we haven't been blocked
+ ** iii ) there's somewhere to put the data
+ ** iv ) we haven't outstayed our welcome
+ */
+ transCount = 1;
+ while (can_remove_receive(&PacketP, PortP)
+ && transCount) {
#ifdef STATS
- PortP->Stat.RxIntCnt++;
-#endif /* STATS */
- RxIntCnt++;
-
- /*
- ** check that it is not a command!
- */
- if ( PacketP->len & PKT_CMD_BIT ) {
- rio_dprintk (RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
- /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */
- rio_dprintk (RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);
- rio_dprintk (RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);
- rio_dprintk (RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit);
- rio_dprintk (RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port);
- rio_dprintk (RIO_DEBUG_INTR, " len = %d\n", PacketP->len);
- rio_dprintk (RIO_DEBUG_INTR, " control = %d\n", PacketP->control);
- rio_dprintk (RIO_DEBUG_INTR, " csum = %d\n", PacketP->csum);
- rio_dprintk (RIO_DEBUG_INTR, " data bytes: ");
- for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ )
- rio_dprintk (RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);
- remove_receive( PortP );
- put_free_end( PortP->HostP, PacketP );
- continue; /* with next packet */
- }
-
- /*
- ** How many characters can we move 'upstream' ?
- **
- ** Determine the minimum of the amount of data
- ** available and the amount of space in which to
- ** put it.
- **
- ** 1. Get the packet length by masking 'len'
- ** for only the length bits.
- ** 2. Available space is [buffer size] - [space used]
- **
- ** Transfer count is the minimum of packet length
- ** and available space.
- */
-
- transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK,
- TTY_FLIPBUF_SIZE - TtyP->flip.count);
- rio_dprintk (RIO_DEBUG_REC, "port %d: Copy %d bytes\n",
- PortP->PortNum, transCount);
- /*
- ** To use the following 'kkprintfs' for debugging - change the '#undef'
- ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
- ** driver).
- */
+ PortP->Stat.RxIntCnt++;
+#endif /* STATS */
+ RxIntCnt++;
+
+ /*
+ ** check that it is not a command!
+ */
+ if (PacketP->len & PKT_CMD_BIT) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
+ /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */
+ rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);
+ rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);
+ rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit);
+ rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port);
+ rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", PacketP->len);
+ rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", PacketP->control);
+ rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", PacketP->csum);
+ rio_dprintk(RIO_DEBUG_INTR, " data bytes: ");
+ for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
+ rio_dprintk(RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);
+ remove_receive(PortP);
+ put_free_end(PortP->HostP, PacketP);
+ continue; /* with next packet */
+ }
+
+ /*
+ ** How many characters can we move 'upstream' ?
+ **
+ ** Determine the minimum of the amount of data
+ ** available and the amount of space in which to
+ ** put it.
+ **
+ ** 1. Get the packet length by masking 'len'
+ ** for only the length bits.
+ ** 2. Available space is [buffer size] - [space used]
+ **
+ ** Transfer count is the minimum of packet length
+ ** and available space.
+ */
+
+ transCount = tty_buffer_request_room(TtyP, PacketP->len & PKT_LEN_MASK);
+ rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
+ /*
+ ** To use the following 'kkprintfs' for debugging - change the '#undef'
+ ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
+ ** driver).
+ */
#undef ___DEBUG_IT___
#ifdef ___DEBUG_IT___
- kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ",
- intCount,
- RxIntCnt,
- PortP->PortNum,
- TtyP->rxqueue.count,
- transCount,
- TtyP->flags );
+ kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ", intCount, RxIntCnt, PortP->PortNum, TtyP->rxqueue.count, transCount, TtyP->flags);
#endif
- ptr = (uchar *) PacketP->data + PortP->RxDataStart;
-
- rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount);
- memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);
+ ptr = (uchar *) PacketP->data + PortP->RxDataStart;
+ tty_prepare_flip_string(TtyP, &buf, transCount);
+ rio_memcpy_fromio(buf, ptr, transCount);
#ifdef STATS
- /*
- ** keep a count for statistical purposes
- */
- PortP->Stat.RxCharCnt += transCount;
+ /*
+ ** keep a count for statistical purposes
+ */
+ PortP->Stat.RxCharCnt += transCount;
#endif
- PortP->RxDataStart += transCount;
- PacketP->len -= transCount;
- copied += transCount;
- TtyP->flip.count += transCount;
- TtyP->flip.char_buf_ptr += transCount;
- TtyP->flip.flag_buf_ptr += transCount;
+ PortP->RxDataStart += transCount;
+ PacketP->len -= transCount;
+ copied += transCount;
#ifdef ___DEBUG_IT___
- kkprintf("T:%d L:%d\n", DataCnt, PacketP->len );
+ kkprintf("T:%d L:%d\n", DataCnt, PacketP->len);
#endif
- if ( PacketP->len == 0 )
- {
+ if (PacketP->len == 0) {
/*
- ** If we have emptied the packet, then we can
- ** free it, and reset the start pointer for
- ** the next packet.
- */
- remove_receive( PortP );
- put_free_end( PortP->HostP, PacketP );
- PortP->RxDataStart = 0;
+ ** If we have emptied the packet, then we can
+ ** free it, and reset the start pointer for
+ ** the next packet.
+ */
+ remove_receive(PortP);
+ put_free_end(PortP->HostP, PacketP);
+ PortP->RxDataStart = 0;
#ifdef STATS
/*
- ** more lies ( oops, I mean statistics )
- */
- PortP->Stat.RxPktCnt++;
-#endif /* STATS */
- }
+ ** more lies ( oops, I mean statistics )
+ */
+ PortP->Stat.RxPktCnt++;
+#endif /* STATS */
+ }
+ }
+ }
+ if (copied) {
+ rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
+ tty_flip_buffer_push(TtyP);
}
- }
- if (copied) {
- rio_dprintk (RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
- tty_flip_buffer_push (TtyP);
- }
- return;
+ return;
}
#ifdef FUTURE_RELEASE
@@ -731,221 +696,210 @@ struct Port * PortP;
** The proc routine called by the line discipline to do the work for it.
** The proc routine works hand in hand with the interrupt routine.
*/
-int
-riotproc(p, tp, cmd, port)
-struct rio_info * p;
+int riotproc(p, tp, cmd, port)
+struct rio_info *p;
register struct ttystatics *tp;
int cmd;
-int port;
+int port;
{
register struct Port *PortP;
int SysPort;
struct PKT *PacketP;
- SysPort = port; /* Believe me, it works. */
+ SysPort = port; /* Believe me, it works. */
- if ( SysPort < 0 || SysPort >= RIO_PORTS ) {
- rio_dprintk (RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n",SysPort);
+ if (SysPort < 0 || SysPort >= RIO_PORTS) {
+ rio_dprintk(RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n", SysPort);
return 0;
}
PortP = p->RIOPortp[SysPort];
- if ((uint)PortP->PhbP < (uint)PortP->Caddr ||
- (uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) {
- rio_dprintk (RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n",
- SysPort);
- rio_dprintk (RIO_DEBUG_INTR, " PortP = 0x%x\n",PortP);
- rio_dprintk (RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n",PortP->PhbP);
- rio_dprintk (RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n",PortP->PhbP);
- rio_dprintk (RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n",PortP->HostPort);
+ if ((uint) PortP->PhbP < (uint) PortP->Caddr || (uint) PortP->PhbP >= (uint) PortP->Caddr + SIXTY_FOUR_K) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n", SysPort);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP = 0x%x\n", PortP);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n", PortP->PhbP);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n", PortP->PhbP);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n", PortP->HostPort);
return 0;
}
- switch(cmd) {
- case T_WFLUSH:
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH\n");
+ switch (cmd) {
+ case T_WFLUSH:
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH\n");
+ /*
+ ** Because of the spooky way the RIO works, we don't need
+ ** to issue a flush command on any of the SET*F commands,
+ ** as that causes trouble with getty and login, which issue
+ ** these commands to incur a READ flush, and rely on the fact
+ ** that the line discipline does a wait for drain for them.
+ ** As the rio doesn't wait for drain, the write flush would
+ ** destroy the Password: prompt. This isn't very friendly, so
+ ** here we only issue a WFLUSH command if we are in the interrupt
+ ** routine, or we aren't executing a SET*F command.
+ */
+ if (PortP->HostP->InIntr || !PortP->FlushCmdBodge) {
/*
- ** Because of the spooky way the RIO works, we don't need
- ** to issue a flush command on any of the SET*F commands,
- ** as that causes trouble with getty and login, which issue
- ** these commands to incur a READ flush, and rely on the fact
- ** that the line discipline does a wait for drain for them.
- ** As the rio doesn't wait for drain, the write flush would
- ** destroy the Password: prompt. This isn't very friendly, so
- ** here we only issue a WFLUSH command if we are in the interrupt
- ** routine, or we aren't executing a SET*F command.
- */
- if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) {
- /*
- ** form a wflush packet - 1 byte long, no data
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n");
- }
- else {
- if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n");
- }
- else
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n");
- }
- /*
- ** WFLUSH operation - flush the data!
- */
- PortP->TxBufferIn = PortP->TxBufferOut = 0;
- }
- else {
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n");
+ ** form a wflush packet - 1 byte long, no data
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n");
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, WFLUSH) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command failed\n");
+ } else
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command\n");
}
/*
- ** sort out the line discipline
- */
- if (PortP->CookMode == COOK_WELL)
- goto start;
- break;
-
- case T_RESUME:
- rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n");
- /*
- ** send pre-emptive resume packet
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n");
+ ** WFLUSH operation - flush the data!
+ */
+ PortP->TxBufferIn = PortP->TxBufferOut = 0;
+ } else {
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n");
+ }
+ /*
+ ** sort out the line discipline
+ */
+ if (PortP->CookMode == COOK_WELL)
+ goto start;
+ break;
+
+ case T_RESUME:
+ rio_dprintk(RIO_DEBUG_INTR, "T_RESUME\n");
+ /*
+ ** send pre-emptive resume packet
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "RESUME on deleted RTA\n");
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, RESUME) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_RESUME Command failed\n");
}
- else {
- if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n");
- }
+ }
+ /*
+ ** and re-start the sender software!
+ */
+ if (PortP->CookMode == COOK_WELL)
+ goto start;
+ break;
+
+ case T_TIME:
+ rio_dprintk(RIO_DEBUG_INTR, "T_TIME\n");
+ /*
+ ** T_TIME is called when xDLY is set in oflags and
+ ** the line discipline timeout has expired. It's
+ ** function in life is to clear the TIMEOUT flag
+ ** and to re-start output to the port.
+ */
+ /*
+ ** Fall through and re-start output
+ */
+ case T_OUTPUT:
+ start:
+ if (PortP->MagicFlags & MAGIC_FLUSH) {
+ PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+ return 0;
+ }
+ RIOTxEnable((char *) PortP);
+ PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+ /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n"); */
+ break;
+
+ case T_SUSPEND:
+ rio_dprintk(RIO_DEBUG_INTR, "T_SUSPEND\n");
+ /*
+ ** send a suspend pre-emptive packet.
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "SUSPEND deleted RTA\n");
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, SUSPEND) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_SUSPEND Command failed\n");
}
- /*
- ** and re-start the sender software!
- */
- if (PortP->CookMode == COOK_WELL)
- goto start;
- break;
-
- case T_TIME:
- rio_dprintk (RIO_DEBUG_INTR, "T_TIME\n");
- /*
- ** T_TIME is called when xDLY is set in oflags and
- ** the line discipline timeout has expired. It's
- ** function in life is to clear the TIMEOUT flag
- ** and to re-start output to the port.
- */
- /*
- ** Fall through and re-start output
- */
- case T_OUTPUT:
-start:
- if ( PortP->MagicFlags & MAGIC_FLUSH ) {
- PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+ }
+ /*
+ ** done!
+ */
+ break;
+
+ case T_BLOCK:
+ rio_dprintk(RIO_DEBUG_INTR, "T_BLOCK\n");
+ break;
+
+ case T_RFLUSH:
+ rio_dprintk(RIO_DEBUG_INTR, "T_RFLUSH\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n");
+ PortP->RxDataStart = 0;
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, RFLUSH) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_RFLUSH Command failed\n");
return 0;
}
- RIOTxEnable((char *)PortP);
- PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
- /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/
- break;
-
- case T_SUSPEND:
- rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n");
- /*
- ** send a suspend pre-emptive packet.
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n");
- }
- else {
- if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n");
- }
+ PortP->RxDataStart = 0;
+ while (can_remove_receive(&PacketP, PortP)) {
+ remove_receive(PortP);
+ ShowPacket(DBG_PROC, PacketP);
+ put_free_end(PortP->HostP, PacketP);
}
- /*
- ** done!
- */
- break;
-
- case T_BLOCK:
- rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n");
- break;
-
- case T_RFLUSH:
- rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n");
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n");
- PortP->RxDataStart = 0;
- }
- else {
- if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n");
- return 0;
- }
- PortP->RxDataStart = 0;
- while ( can_remove_receive(&PacketP, PortP) ) {
- remove_receive(PortP);
- ShowPacket(DBG_PROC, PacketP );
- put_free_end(PortP->HostP, PacketP );
- }
- if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) {
- /*
- ** MAGIC!
- */
- rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n");
- PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
- }
- }
- break;
- /* FALLTHROUGH */
- case T_UNBLOCK:
- rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n");
- /*
- ** If there is any data to receive set a timeout to service it.
- */
- RIOReceive(p, PortP);
- break;
-
- case T_BREAK:
- rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n");
- /*
- ** Send a break command. For Sys V
- ** this is a timed break, so we
- ** send a SBREAK[time] packet
- */
- /*
- ** Build a BREAK command
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n");
+ if (PortP->PhbP->handshake == PHB_HANDSHAKE_SET) {
+ /*
+ ** MAGIC!
+ */
+ rio_dprintk(RIO_DEBUG_INTR, "Set receive handshake bit\n");
+ PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
}
- else {
- if (RIOShortCommand(PortP,SBREAK,2,
- p->RIOConf.BreakInterval)==RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
- }
+ }
+ break;
+ /* FALLTHROUGH */
+ case T_UNBLOCK:
+ rio_dprintk(RIO_DEBUG_INTR, "T_UNBLOCK\n");
+ /*
+ ** If there is any data to receive set a timeout to service it.
+ */
+ RIOReceive(p, PortP);
+ break;
+
+ case T_BREAK:
+ rio_dprintk(RIO_DEBUG_INTR, "T_BREAK\n");
+ /*
+ ** Send a break command. For Sys V
+ ** this is a timed break, so we
+ ** send a SBREAK[time] packet
+ */
+ /*
+ ** Build a BREAK command
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "BREAK on deleted RTA\n");
+ } else {
+ if (RIOShortCommand(PortP, SBREAK, 2, p->RIOConf.BreakInterval) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
}
-
- /*
- ** done!
- */
- break;
-
- case T_INPUT:
- rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n");
- break;
- case T_PARM:
- rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n");
- break;
-
- case T_SWTCH:
- rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n");
- break;
-
- default:
- rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd);
+ }
+
+ /*
+ ** done!
+ */
+ break;
+
+ case T_INPUT:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n");
+ break;
+ case T_PARM:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n");
+ break;
+
+ case T_SWTCH:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n");
+ break;
+
+ default:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n", cmd);
}
/*
- ** T_OUTPUT returns without passing through this point!
- */
- /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/
- return(0);
+ ** T_OUTPUT returns without passing through this point!
+ */
+ /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n"); */
+ return (0);
}
#endif
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h
index c3d679733c9a..14b83fae75c8 100644
--- a/drivers/char/rio/rioioctl.h
+++ b/drivers/char/rio/rioioctl.h
@@ -42,14 +42,14 @@ static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2";
*/
struct portStats {
- int port;
- int gather;
- ulong txchars;
- ulong rxchars;
- ulong opens;
- ulong closes;
- ulong ioctls;
-};
+ int port;
+ int gather;
+ ulong txchars;
+ ulong rxchars;
+ ulong opens;
+ ulong closes;
+ ulong ioctls;
+};
#define rIOC ('r'<<8)
@@ -100,4 +100,4 @@ struct portStats {
#define RIO_RESET_PORT_STATS (RIOC | 194)
#define RIO_GET_PORT_STATS (RIOC | 195)
-#endif /* __rioioctl_h__ */
+#endif /* __rioioctl_h__ */
diff --git a/drivers/char/rio/riolocks.h b/drivers/char/rio/riolocks.h
deleted file mode 100644
index 0e0cdacebe0b..000000000000
--- a/drivers/char/rio/riolocks.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-**
-** Module : riolocks.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:13
-** Retrieved : 11/6/98 11:34:22
-**
-** ident @(#)riolocks.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riolocks_h__
-#define __rio_riolocks_h__
-
-#ifdef SCCS_LABELS
-static char *_riolocks_h_sccs_ = "@(#)riolocks.h 1.2";
-#endif
-
-#define LOCKB(lk) lockb(lk);
-#define UNLOCKB(lk, oldspl) unlockb(lk, oldspl);
-
-#endif
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
index f10916326ecc..c622f46d6d77 100644
--- a/drivers/char/rio/rioparam.c
+++ b/drivers/char/rio/rioparam.c
@@ -157,295 +157,253 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
** NB. for MPX
** tty lock must NOT have been previously acquired.
*/
-int
-RIOParam(PortP, cmd, Modem, SleepFlag)
+int RIOParam(PortP, cmd, Modem, SleepFlag)
struct Port *PortP;
int cmd;
int Modem;
-int SleepFlag;
+int SleepFlag;
{
register struct tty_struct *TtyP;
- int retval;
+ int retval;
register struct phb_param *phb_param_ptr;
PKT *PacketP;
int res;
- uchar Cor1=0, Cor2=0, Cor4=0, Cor5=0;
- uchar TxXon=0, TxXoff=0, RxXon=0, RxXoff=0;
- uchar LNext=0, TxBaud=0, RxBaud=0;
- int retries = 0xff;
+ uchar Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
+ uchar TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
+ uchar LNext = 0, TxBaud = 0, RxBaud = 0;
+ int retries = 0xff;
unsigned long flags;
- func_enter ();
+ func_enter();
TtyP = PortP->gs.tty;
- rio_dprintk (RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n",
- PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
+ rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
if (!TtyP) {
- rio_dprintk (RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
- func_exit ();
+ func_exit();
- return RIO_FAIL;
+ return RIO_FAIL;
}
- rio_spin_lock_irqsave(&PortP->portSem, flags );
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
if (cmd == OPEN) {
/*
- ** If the port is set to store or lock the parameters, and it is
- ** paramed with OPEN, we want to restore the saved port termio, but
- ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
- */
-#if 0
- if (PortP->FirstOpen) {
- PortP->StoredTty.iflag = TtyP->tm.c_iflag;
- PortP->StoredTty.oflag = TtyP->tm.c_oflag;
- PortP->StoredTty.cflag = TtyP->tm.c_cflag;
- PortP->StoredTty.lflag = TtyP->tm.c_lflag;
- PortP->StoredTty.line = TtyP->tm.c_line;
- for (i = 0; i < NCC + 5; i++)
- PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i];
- PortP->FirstOpen = 0;
- }
- else if (PortP->Store || PortP->Lock) {
- rio_dprintk (RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n");
- TtyP->tm.c_iflag = PortP->StoredTty.iflag;
- TtyP->tm.c_oflag = PortP->StoredTty.oflag;
- TtyP->tm.c_cflag = PortP->StoredTty.cflag;
- TtyP->tm.c_lflag = PortP->StoredTty.lflag;
- TtyP->tm.c_line = PortP->StoredTty.line;
- for (i = 0; i < NCC + 5; i++)
- TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i];
- }
-#endif
+ ** If the port is set to store or lock the parameters, and it is
+ ** paramed with OPEN, we want to restore the saved port termio, but
+ ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
+ */
}
/*
- ** wait for space
- */
- while ( !(res=can_add_transmit(&PacketP,PortP)) ||
- (PortP->InUse != NOT_INUSE) ) {
- if (retries -- <= 0) {
+ ** wait for space
+ */
+ while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
+ if (retries-- <= 0) {
break;
}
- if ( PortP->InUse != NOT_INUSE ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
+ if (PortP->InUse != NOT_INUSE) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
}
- if ( !res ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
+ if (!res) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
}
- if ( SleepFlag != OK_TO_SLEEP ) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ if (SleepFlag != OK_TO_SLEEP) {
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
func_exit();
-
+
return RIO_FAIL;
}
- rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
retval = RIODelay(PortP, HUNDRED_MS);
- rio_spin_lock_irqsave( &PortP->portSem, flags);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
if (retval == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
pseterr(EINTR);
func_exit();
return RIO_FAIL;
}
- if ( PortP->State & RIO_DELETED ) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
- func_exit ();
+ if (PortP->State & RIO_DELETED) {
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
return RIO_SUCCESS;
}
}
if (!res) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
- func_exit ();
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
return RIO_FAIL;
}
- rio_dprintk (RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n",res);
- rio_dprintk (RIO_DEBUG_PARAM, "Packet is 0x%x\n",(int) PacketP);
+ rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
+ rio_dprintk(RIO_DEBUG_PARAM, "Packet is 0x%x\n", (int) PacketP);
- phb_param_ptr = (struct phb_param *)PacketP->data;
+ phb_param_ptr = (struct phb_param *) PacketP->data;
-#if 0
- /*
- ** COR 1
- */
- if ( TtyP->tm.c_iflag & INPCK ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Parity checking on input enabled\n");
- Cor1 |= COR1_INPCK;
- }
-#endif
-
- switch ( TtyP->termios->c_cflag & CSIZE ) {
- case CS5:
+ switch (TtyP->termios->c_cflag & CSIZE) {
+ case CS5:
{
- rio_dprintk (RIO_DEBUG_PARAM, "5 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
Cor1 |= COR1_5BITS;
break;
}
- case CS6:
+ case CS6:
{
- rio_dprintk (RIO_DEBUG_PARAM, "6 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
Cor1 |= COR1_6BITS;
break;
}
- case CS7:
+ case CS7:
{
- rio_dprintk (RIO_DEBUG_PARAM, "7 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
Cor1 |= COR1_7BITS;
break;
}
- case CS8:
+ case CS8:
{
- rio_dprintk (RIO_DEBUG_PARAM, "8 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
Cor1 |= COR1_8BITS;
break;
}
}
- if ( TtyP->termios->c_cflag & CSTOPB ) {
- rio_dprintk (RIO_DEBUG_PARAM, "2 stop bits\n");
+ if (TtyP->termios->c_cflag & CSTOPB) {
+ rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
Cor1 |= COR1_2STOP;
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "1 stop bit\n");
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
Cor1 |= COR1_1STOP;
}
- if ( TtyP->termios->c_cflag & PARENB ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable parity\n");
+ if (TtyP->termios->c_cflag & PARENB) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
Cor1 |= COR1_NORMAL;
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "Disable parity\n");
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
Cor1 |= COR1_NOP;
}
- if ( TtyP->termios->c_cflag & PARODD ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Odd parity\n");
+ if (TtyP->termios->c_cflag & PARODD) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
Cor1 |= COR1_ODD;
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "Even parity\n");
- Cor1 |= COR1_EVEN;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
+ Cor1 |= COR1_EVEN;
}
/*
- ** COR 2
- */
- if ( TtyP->termios->c_iflag & IXON ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop output control\n");
+ ** COR 2
+ */
+ if (TtyP->termios->c_iflag & IXON) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
Cor2 |= COR2_IXON;
- }
- else {
- if ( PortP->Config & RIO_IXON ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
+ } else {
+ if (PortP->Config & RIO_IXON) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
Cor2 |= COR2_IXON;
- }
- else
- rio_dprintk (RIO_DEBUG_PARAM, "IXON has been disabled.\n");
+ } else
+ rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
}
if (TtyP->termios->c_iflag & IXANY) {
- if ( PortP->Config & RIO_IXANY ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable any key to restart output\n");
+ if (PortP->Config & RIO_IXANY) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
Cor2 |= COR2_IXANY;
- }
- else
- rio_dprintk (RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
+ } else
+ rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
}
- if ( TtyP->termios->c_iflag & IXOFF ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
+ if (TtyP->termios->c_iflag & IXOFF) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
Cor2 |= COR2_IXOFF;
}
- if ( TtyP->termios->c_cflag & HUPCL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Hangup on last close\n");
+ if (TtyP->termios->c_cflag & HUPCL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
Cor2 |= COR2_HUPCL;
}
- if ( C_CRTSCTS (TtyP)) {
- rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
+ if (C_CRTSCTS(TtyP)) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
Cor2 |= COR2_CTSFLOW;
Cor2 |= COR2_RTSFLOW;
} else {
- rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
Cor2 &= ~COR2_CTSFLOW;
Cor2 &= ~COR2_RTSFLOW;
}
- if ( TtyP->termios->c_cflag & CLOCAL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Local line\n");
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "Possible Modem line\n");
+ if (TtyP->termios->c_cflag & CLOCAL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
}
/*
- ** COR 4 (there is no COR 3)
- */
- if ( TtyP->termios->c_iflag & IGNBRK ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Ignore break condition\n");
+ ** COR 4 (there is no COR 3)
+ */
+ if (TtyP->termios->c_iflag & IGNBRK) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
Cor4 |= COR4_IGNBRK;
}
- if ( !(TtyP->termios->c_iflag & BRKINT) ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Break generates NULL condition\n");
+ if (!(TtyP->termios->c_iflag & BRKINT)) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
Cor4 |= COR4_NBRKINT;
} else {
- rio_dprintk (RIO_DEBUG_PARAM, "Interrupt on break condition\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on break condition\n");
}
- if ( TtyP->termios->c_iflag & INLCR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
+ if (TtyP->termios->c_iflag & INLCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
Cor4 |= COR4_INLCR;
}
- if ( TtyP->termios->c_iflag & IGNCR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
+ if (TtyP->termios->c_iflag & IGNCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
Cor4 |= COR4_IGNCR;
}
- if ( TtyP->termios->c_iflag & ICRNL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
+ if (TtyP->termios->c_iflag & ICRNL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
Cor4 |= COR4_ICRNL;
}
- if ( TtyP->termios->c_iflag & IGNPAR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
+ if (TtyP->termios->c_iflag & IGNPAR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
Cor4 |= COR4_IGNPAR;
}
- if ( TtyP->termios->c_iflag & PARMRK ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Mark parity errors\n");
+ if (TtyP->termios->c_iflag & PARMRK) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
Cor4 |= COR4_PARMRK;
}
/*
- ** Set the RAISEMOD flag to ensure that the modem lines are raised
- ** on reception of a config packet.
- ** The download code handles the zero baud condition.
- */
+ ** Set the RAISEMOD flag to ensure that the modem lines are raised
+ ** on reception of a config packet.
+ ** The download code handles the zero baud condition.
+ */
Cor4 |= COR4_RAISEMOD;
/*
- ** COR 5
- */
+ ** COR 5
+ */
Cor5 = COR5_CMOE;
/*
- ** Set to monitor tbusy/tstop (or not).
- */
+ ** Set to monitor tbusy/tstop (or not).
+ */
if (PortP->MonitorTstate)
Cor5 |= COR5_TSTATE_ON;
@@ -453,182 +411,183 @@ int SleepFlag;
Cor5 |= COR5_TSTATE_OFF;
/*
- ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
- */
- if ( TtyP->termios->c_iflag & ISTRIP ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Strip input characters\n");
- if (! (PortP->State & RIO_TRIAD_MODE)) {
+ ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
+ */
+ if (TtyP->termios->c_iflag & ISTRIP) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
+ if (!(PortP->State & RIO_TRIAD_MODE)) {
Cor5 |= COR5_ISTRIP;
}
}
- if ( TtyP->termios->c_oflag & ONLCR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
- if ( PortP->CookMode == COOK_MEDIUM )
+ if (TtyP->termios->c_oflag & ONLCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
+ if (PortP->CookMode == COOK_MEDIUM)
Cor5 |= COR5_ONLCR;
}
- if ( TtyP->termios->c_oflag & OCRNL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
- if ( PortP->CookMode == COOK_MEDIUM )
+ if (TtyP->termios->c_oflag & OCRNL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
+ if (PortP->CookMode == COOK_MEDIUM)
Cor5 |= COR5_OCRNL;
}
- if ( ( TtyP->termios->c_oflag & TABDLY) == TAB3 ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Tab delay 3 set\n");
- if ( PortP->CookMode == COOK_MEDIUM )
+ if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
+ if (PortP->CookMode == COOK_MEDIUM)
Cor5 |= COR5_TAB3;
}
/*
- ** Flow control bytes.
- */
+ ** Flow control bytes.
+ */
TxXon = TtyP->termios->c_cc[VSTART];
TxXoff = TtyP->termios->c_cc[VSTOP];
RxXon = TtyP->termios->c_cc[VSTART];
RxXoff = TtyP->termios->c_cc[VSTOP];
/*
- ** LNEXT byte
- */
+ ** LNEXT byte
+ */
LNext = 0;
/*
- ** Baud rate bytes
- */
- rio_dprintk (RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n",
- TtyP->termios->c_cflag, CBAUD);
+ ** Baud rate bytes
+ */
+ rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);
switch (TtyP->termios->c_cflag & CBAUD) {
#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
- e(50);e(75);e(110);e(134);e(150);e(200);e(300);e(600);e(1200);
- e(1800);e(2400);e(4800);e(9600);e(19200);e(38400);e(57600);
- e(115200); /* e(230400);e(460800); e(921600); */
+ e(50);
+ e(75);
+ e(110);
+ e(134);
+ e(150);
+ e(200);
+ e(300);
+ e(600);
+ e(1200);
+ e(1800);
+ e(2400);
+ e(4800);
+ e(9600);
+ e(19200);
+ e(38400);
+ e(57600);
+ e(115200); /* e(230400);e(460800); e(921600); */
}
/* XXX MIssing conversion table. XXX */
- /* (TtyP->termios->c_cflag & V_CBAUD); */
+ /* (TtyP->termios->c_cflag & V_CBAUD); */
- rio_dprintk (RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
+ rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
/*
- ** Leftovers
- */
- if ( TtyP->termios->c_cflag & CREAD )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable receiver\n");
+ ** Leftovers
+ */
+ if (TtyP->termios->c_cflag & CREAD)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
#ifdef RCV1EN
- if ( TtyP->termios->c_cflag & RCV1EN )
- rio_dprintk (RIO_DEBUG_PARAM, "RCV1EN (?)\n");
+ if (TtyP->termios->c_cflag & RCV1EN)
+ rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
#endif
#ifdef XMT1EN
- if ( TtyP->termios->c_cflag & XMT1EN )
- rio_dprintk (RIO_DEBUG_PARAM, "XMT1EN (?)\n");
-#endif
-#if 0
- if ( TtyP->termios->c_cflag & LOBLK )
- rio_dprintk (RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n");
+ if (TtyP->termios->c_cflag & XMT1EN)
+ rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
#endif
- if ( TtyP->termios->c_lflag & ISIG )
- rio_dprintk (RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
- if ( TtyP->termios->c_lflag & ICANON )
- rio_dprintk (RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
- if ( TtyP->termios->c_lflag & XCASE )
- rio_dprintk (RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
- if ( TtyP->termios->c_lflag & ECHO )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable input echo\n");
- if ( TtyP->termios->c_lflag & ECHOE )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable echo erase\n");
- if ( TtyP->termios->c_lflag & ECHOK )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable echo kill\n");
- if ( TtyP->termios->c_lflag & ECHONL )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable echo newline\n");
- if ( TtyP->termios->c_lflag & NOFLSH )
- rio_dprintk (RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
+ if (TtyP->termios->c_lflag & ISIG)
+ rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
+ if (TtyP->termios->c_lflag & ICANON)
+ rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
+ if (TtyP->termios->c_lflag & XCASE)
+ rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
+ if (TtyP->termios->c_lflag & ECHO)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
+ if (TtyP->termios->c_lflag & ECHOE)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
+ if (TtyP->termios->c_lflag & ECHOK)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
+ if (TtyP->termios->c_lflag & ECHONL)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
+ if (TtyP->termios->c_lflag & NOFLSH)
+ rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
#ifdef TOSTOP
- if ( TtyP->termios->c_lflag & TOSTOP )
- rio_dprintk (RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
+ if (TtyP->termios->c_lflag & TOSTOP)
+ rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
#endif
#ifdef XCLUDE
- if ( TtyP->termios->c_lflag & XCLUDE )
- rio_dprintk (RIO_DEBUG_PARAM, "Exclusive use of this line\n");
-#endif
- if ( TtyP->termios->c_iflag & IUCLC )
- rio_dprintk (RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
- if ( TtyP->termios->c_oflag & OPOST )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable output post-processing\n");
- if ( TtyP->termios->c_oflag & OLCUC )
- rio_dprintk (RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
- if ( TtyP->termios->c_oflag & ONOCR )
- rio_dprintk (RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
- if ( TtyP->termios->c_oflag & ONLRET )
- rio_dprintk (RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
- if ( TtyP->termios->c_oflag & OFILL )
- rio_dprintk (RIO_DEBUG_PARAM, "Use fill characters for delay\n");
- if ( TtyP->termios->c_oflag & OFDEL )
- rio_dprintk (RIO_DEBUG_PARAM, "Fill character is DEL\n");
- if ( TtyP->termios->c_oflag & NLDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Newline delay set\n");
- if ( TtyP->termios->c_oflag & CRDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Carriage return delay set\n");
- if ( TtyP->termios->c_oflag & TABDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Tab delay set\n");
-#if 0
- if ( TtyP->termios->c_oflag & BSDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Back-space delay set\n");
- if ( TtyP->termios->c_oflag & VTDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Vertical tab delay set\n");
- if ( TtyP->termios->c_oflag & FFDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Form-feed delay set\n");
+ if (TtyP->termios->c_lflag & XCLUDE)
+ rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
#endif
+ if (TtyP->termios->c_iflag & IUCLC)
+ rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
+ if (TtyP->termios->c_oflag & OPOST)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
+ if (TtyP->termios->c_oflag & OLCUC)
+ rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
+ if (TtyP->termios->c_oflag & ONOCR)
+ rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
+ if (TtyP->termios->c_oflag & ONLRET)
+ rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
+ if (TtyP->termios->c_oflag & OFILL)
+ rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
+ if (TtyP->termios->c_oflag & OFDEL)
+ rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
+ if (TtyP->termios->c_oflag & NLDLY)
+ rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
+ if (TtyP->termios->c_oflag & CRDLY)
+ rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
+ if (TtyP->termios->c_oflag & TABDLY)
+ rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
/*
- ** These things are kind of useful in a later life!
- */
+ ** These things are kind of useful in a later life!
+ */
PortP->Cor2Copy = Cor2;
- if ( PortP->State & RIO_DELETED ) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
- func_exit ();
+ if (PortP->State & RIO_DELETED) {
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
return RIO_FAIL;
}
/*
- ** Actually write the info into the packet to be sent
- */
- WBYTE(phb_param_ptr->Cmd, cmd);
- WBYTE(phb_param_ptr->Cor1, Cor1);
- WBYTE(phb_param_ptr->Cor2, Cor2);
- WBYTE(phb_param_ptr->Cor4, Cor4);
- WBYTE(phb_param_ptr->Cor5, Cor5);
- WBYTE(phb_param_ptr->TxXon, TxXon);
- WBYTE(phb_param_ptr->RxXon, RxXon);
+ ** Actually write the info into the packet to be sent
+ */
+ WBYTE(phb_param_ptr->Cmd, cmd);
+ WBYTE(phb_param_ptr->Cor1, Cor1);
+ WBYTE(phb_param_ptr->Cor2, Cor2);
+ WBYTE(phb_param_ptr->Cor4, Cor4);
+ WBYTE(phb_param_ptr->Cor5, Cor5);
+ WBYTE(phb_param_ptr->TxXon, TxXon);
+ WBYTE(phb_param_ptr->RxXon, RxXon);
WBYTE(phb_param_ptr->TxXoff, TxXoff);
WBYTE(phb_param_ptr->RxXoff, RxXoff);
- WBYTE(phb_param_ptr->LNext, LNext);
+ WBYTE(phb_param_ptr->LNext, LNext);
WBYTE(phb_param_ptr->TxBaud, TxBaud);
WBYTE(phb_param_ptr->RxBaud, RxBaud);
/*
- ** Set the length/command field
- */
- WBYTE(PacketP->len , 12 | PKT_CMD_BIT);
+ ** Set the length/command field
+ */
+ WBYTE(PacketP->len, 12 | PKT_CMD_BIT);
/*
- ** The packet is formed - now, whack it off
- ** to its final destination:
- */
+ ** The packet is formed - now, whack it off
+ ** to its final destination:
+ */
add_transmit(PortP);
/*
- ** Count characters transmitted for port statistics reporting
- */
+ ** Count characters transmitted for port statistics reporting
+ */
if (PortP->statsGather)
PortP->txchars += 12;
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_PARAM, "add_transmit returned.\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
/*
- ** job done.
- */
- func_exit ();
+ ** job done.
+ */
+ func_exit();
return RIO_SUCCESS;
}
@@ -638,16 +597,15 @@ int SleepFlag;
** We can add another packet to a transmit queue if the packet pointer pointed
** to by the TxAdd pointer has PKT_IN_USE clear in its address.
*/
-int
-can_add_transmit(PktP, PortP)
+int can_add_transmit(PktP, PortP)
PKT **PktP;
-struct Port *PortP;
+struct Port *PortP;
{
register PKT *tp;
- *PktP = tp = (PKT *)RIO_PTR(PortP->Caddr,RWORD(*PortP->TxAdd));
+ *PktP = tp = (PKT *) RIO_PTR(PortP->Caddr, RWORD(*PortP->TxAdd));
- return !((uint)tp & PKT_IN_USE);
+ return !((uint) tp & PKT_IN_USE);
}
/*
@@ -655,25 +613,22 @@ struct Port *PortP;
** and then move the TxAdd pointer along one position to point to the next
** packet pointer. You must wrap the pointer from the end back to the start.
*/
-void
-add_transmit(PortP)
-struct Port *PortP;
+void add_transmit(PortP)
+struct Port *PortP;
{
- if (RWORD(*PortP->TxAdd) & PKT_IN_USE) {
- rio_dprintk (RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
- }
- WWORD( *(ushort *)PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE);
- PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart :
- PortP->TxAdd + 1;
- WWORD( PortP->PhbP->tx_add , RIO_OFF(PortP->Caddr,PortP->TxAdd) );
+ if (RWORD(*PortP->TxAdd) & PKT_IN_USE) {
+ rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
+ }
+ WWORD(*(ushort *) PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE);
+ PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1;
+ WWORD(PortP->PhbP->tx_add, RIO_OFF(PortP->Caddr, PortP->TxAdd));
}
/****************************************
* Put a packet onto the end of the
* free list
****************************************/
-void
-put_free_end(HostP, PktP)
+void put_free_end(HostP, PktP)
struct Host *HostP;
PKT *PktP;
{
@@ -688,24 +643,23 @@ PKT *PktP;
*
************************************************/
- rio_dprintk (RIO_DEBUG_PFE, "put_free_end(PktP=%x)\n",(int)PktP);
+ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%x)\n", (int) PktP);
- if ((old_end=RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) {
- new_end = RIO_OFF(HostP->Caddr,PktP);
- tmp_pointer = (FREE_LIST *)RIO_PTR(HostP->Caddr,old_end);
- WWORD(tmp_pointer->next , new_end );
- WWORD(((FREE_LIST *)PktP)->prev , old_end);
- WWORD(((FREE_LIST *)PktP)->next , TPNULL);
+ if ((old_end = RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) {
+ new_end = RIO_OFF(HostP->Caddr, PktP);
+ tmp_pointer = (FREE_LIST *) RIO_PTR(HostP->Caddr, old_end);
+ WWORD(tmp_pointer->next, new_end);
+ WWORD(((FREE_LIST *) PktP)->prev, old_end);
+ WWORD(((FREE_LIST *) PktP)->next, TPNULL);
WWORD(HostP->ParmMapP->free_list_end, new_end);
- }
- else { /* First packet on the free list this should never happen! */
- rio_dprintk (RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
- WWORD(HostP->ParmMapP->free_list_end , RIO_OFF(HostP->Caddr,PktP));
- tmp_pointer = (FREE_LIST *)PktP;
- WWORD(tmp_pointer->prev , TPNULL);
- WWORD(tmp_pointer->next , TPNULL);
- }
- rio_dprintk (RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
+ } else { /* First packet on the free list this should never happen! */
+ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
+ WWORD(HostP->ParmMapP->free_list_end, RIO_OFF(HostP->Caddr, PktP));
+ tmp_pointer = (FREE_LIST *) PktP;
+ WWORD(tmp_pointer->prev, TPNULL);
+ WWORD(tmp_pointer->next, TPNULL);
+ }
+ rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
}
@@ -715,14 +669,12 @@ PKT *PktP;
** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
** then can_remove_receive() returns 0.
*/
-int
-can_remove_receive(PktP, PortP)
+int can_remove_receive(PktP, PortP)
PKT **PktP;
struct Port *PortP;
{
- if ( RWORD(*PortP->RxRemove) & PKT_IN_USE) {
- *PktP = (PKT *)RIO_PTR(PortP->Caddr,
- RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
+ if (RWORD(*PortP->RxRemove) & PKT_IN_USE) {
+ *PktP = (PKT *) RIO_PTR(PortP->Caddr, RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
return 1;
}
return 0;
@@ -733,12 +685,10 @@ struct Port *PortP;
** and then bump the pointers. Once the pointers get to the end, they must
** be wrapped back to the start.
*/
-void
-remove_receive(PortP)
-struct Port *PortP;
+void remove_receive(PortP)
+struct Port *PortP;
{
- WWORD( *PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE );
- PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart :
- PortP->RxRemove + 1;
- WWORD( PortP->PhbP->rx_remove , RIO_OFF(PortP->Caddr, PortP->RxRemove) );
+ WWORD(*PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
+ PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1;
+ WWORD(PortP->PhbP->rx_remove, RIO_OFF(PortP->Caddr, PortP->RxRemove));
}
diff --git a/drivers/char/rio/riopcicopy.c b/drivers/char/rio/riopcicopy.c
index 2ea99a60aa32..535afaa51ca5 100644
--- a/drivers/char/rio/riopcicopy.c
+++ b/drivers/char/rio/riopcicopy.c
@@ -1,8 +1,8 @@
/* Yeah. We have copyright on this one. Sure. */
-void rio_pcicopy( char *from, char *to, int amount)
+void rio_pcicopy(char *from, char *to, int amount)
{
- while ( amount-- )
- *to++ = *from++;
+ while (amount--)
+ *to++ = *from++;
}
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
index e9564c9fb37c..f98888f52659 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -93,625 +93,505 @@ static void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint,
** Incoming on the ROUTE_RUP
** I wrote this while I was tired. Forgive me.
*/
-int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP )
+int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP)
{
- struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
- struct PktCmd_M *PktReplyP;
- struct CmdBlk *CmdBlkP;
- struct Port *PortP;
- struct Map *MapP;
- struct Top *TopP;
- int ThisLink, ThisLinkMin, ThisLinkMax;
- int port;
- int Mod, Mod1, Mod2;
- ushort RtaType;
- uint RtaUniq;
- uint ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */
- uint OldUnit, NewUnit, OldLink, NewLink;
- char *MyType, *MyName;
- int Lies;
- unsigned long flags;
-
-#ifdef STACK
- RIOStackCheck("RIORouteRup");
-#endif
-#ifdef CHECK
- CheckPacketP(PacketP);
- CheckHostP(HostP);
- CheckRup(Rup);
- CheckHost(Host);
-#endif
- /*
- ** Is this unit telling us it's current link topology?
- */
- if ( RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY )
- {
- MapP = HostP->Mapping;
-
- /*
- ** The packet can be sent either by the host or by an RTA.
- ** If it comes from the host, then we need to fill in the
- ** Topology array in the host structure. If it came in
- ** from an RTA then we need to fill in the Mapping structure's
- ** Topology array for the unit.
- */
- if ( Rup >= (ushort)MAX_RUP )
- {
- ThisUnit = HOST_ID;
- TopP = HostP->Topology;
- MyType = "Host";
- MyName = HostP->Name;
- ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
- }
- else
- {
- ThisUnit = Rup+1;
- TopP = HostP->Mapping[Rup].Topology;
- MyType = "RTA";
- MyName = HostP->Mapping[Rup].Name;
- ThisLinkMin = 0;
- ThisLinkMax = LINKS_PER_UNIT - 1;
- }
-
- /*
- ** Lies will not be tolerated.
- ** If any pair of links claim to be connected to the same
- ** place, then ignore this packet completely.
- */
- Lies = 0;
- for ( ThisLink=ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++)
- {
- /*
- ** it won't lie about network interconnect, total disconnects
- ** and no-IDs. (or at least, it doesn't *matter* if it does)
- */
- if ( RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort)MAX_RUP )
- continue;
-
- for ( NewLink=ThisLinkMin; NewLink < ThisLink; NewLink++ )
- {
- if ( (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) ==
- RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) &&
- (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) ==
- RBYTE(PktCmdP->RouteTopology[NewLink].Link)) )
- {
- Lies++;
- }
- }
- }
-
- if ( Lies )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n",Lies);
- rio_dprintk (RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
- RBYTE(PktCmdP->RouteTopology[0].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[0].Link),
- RBYTE(PktCmdP->RouteTopology[1].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[1].Link),
- RBYTE(PktCmdP->RouteTopology[2].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[2].Link),
- RBYTE(PktCmdP->RouteTopology[3].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[3].Link));
- return TRUE;
- }
-
- /*
- ** now, process each link.
- */
- for ( ThisLink=ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++)
- {
- /*
- ** this is what it was connected to
- */
- OldUnit = TopP[ThisLink].Unit;
- OldLink = TopP[ThisLink].Link;
-
- /*
- ** this is what it is now connected to
- */
- NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);
- NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);
-
- if ( OldUnit != NewUnit || OldLink != NewLink )
- {
+ struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
+ struct PktCmd_M *PktReplyP;
+ struct CmdBlk *CmdBlkP;
+ struct Port *PortP;
+ struct Map *MapP;
+ struct Top *TopP;
+ int ThisLink, ThisLinkMin, ThisLinkMax;
+ int port;
+ int Mod, Mod1, Mod2;
+ ushort RtaType;
+ uint RtaUniq;
+ uint ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */
+ uint OldUnit, NewUnit, OldLink, NewLink;
+ char *MyType, *MyName;
+ int Lies;
+ unsigned long flags;
+
/*
- ** something has changed!
- */
-
- if ( NewUnit > MAX_RUP &&
- NewUnit != ROUTE_DISCONNECT &&
- NewUnit != ROUTE_NO_ID &&
- NewUnit != ROUTE_INTERCONNECT )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n",
- MyType,
- MyName,
- NewUnit,
- NewLink);
- }
- else
- {
- /*
- ** put the new values in
- */
- TopP[ThisLink].Unit = NewUnit;
- TopP[ThisLink].Link = NewLink;
-
- RIOSetChange(p);
-
- if ( OldUnit <= MAX_RUP )
- {
- /*
- ** If something has become bust, then re-enable them messages
- */
- if (! p->RIONoMessage)
- RIOConCon(p,HostP,ThisUnit,ThisLink,OldUnit,OldLink,DISCONNECT);
- }
-
- if ( ( NewUnit <= MAX_RUP ) && !p->RIONoMessage )
- RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT);
-
- if ( NewUnit == ROUTE_NO_ID )
- rio_dprintk (RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n",
- MyType,MyName,'A'+ThisLink);
-
- if ( NewUnit == ROUTE_INTERCONNECT )
- {
- if (! p->RIONoMessage)
- cprintf("%s '%s' (%c) is connected to another network.\n", MyType,MyName,'A'+ThisLink);
- }
-
- /*
- ** perform an update for 'the other end', so that these messages
- ** only appears once. Only disconnect the other end if it is pointing
- ** at us!
- */
- if ( OldUnit == HOST_ID )
- {
- if ( HostP->Topology[OldLink].Unit == ThisUnit &&
- HostP->Topology[OldLink].Link == ThisLink )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A');
- HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
- HostP->Topology[OldLink].Link = NO_LINK;
- }
- else
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n",
- OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');
- }
- }
- else if ( OldUnit <= MAX_RUP )
- {
- if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit &&
- HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n",
- HostP->Mapping[OldUnit-1].Name,OldLink+'A');
- HostP->Mapping[OldUnit-1].Topology[OldLink].Unit=ROUTE_DISCONNECT;
- HostP->Mapping[OldUnit-1].Topology[OldLink].Link=NO_LINK;
- }
- else
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n",
- HostP->Mapping[OldUnit-1].Name,OldLink+'A',
- HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');
- }
- }
- if ( NewUnit == HOST_ID )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n",
- NewLink+'A',MyName,ThisLink+'A');
- HostP->Topology[NewLink].Unit = ThisUnit;
- HostP->Topology[NewLink].Link = ThisLink;
- }
- else if ( NewUnit <= MAX_RUP )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n",
- HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A');
- HostP->Mapping[NewUnit-1].Topology[NewLink].Unit=ThisUnit;
- HostP->Mapping[NewUnit-1].Topology[NewLink].Link=ThisLink;
- }
+ ** Is this unit telling us it's current link topology?
+ */
+ if (RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY) {
+ MapP = HostP->Mapping;
+
+ /*
+ ** The packet can be sent either by the host or by an RTA.
+ ** If it comes from the host, then we need to fill in the
+ ** Topology array in the host structure. If it came in
+ ** from an RTA then we need to fill in the Mapping structure's
+ ** Topology array for the unit.
+ */
+ if (Rup >= (ushort) MAX_RUP) {
+ ThisUnit = HOST_ID;
+ TopP = HostP->Topology;
+ MyType = "Host";
+ MyName = HostP->Name;
+ ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
+ } else {
+ ThisUnit = Rup + 1;
+ TopP = HostP->Mapping[Rup].Topology;
+ MyType = "RTA";
+ MyName = HostP->Mapping[Rup].Name;
+ ThisLinkMin = 0;
+ ThisLinkMax = LINKS_PER_UNIT - 1;
+ }
+
+ /*
+ ** Lies will not be tolerated.
+ ** If any pair of links claim to be connected to the same
+ ** place, then ignore this packet completely.
+ */
+ Lies = 0;
+ for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
+ /*
+ ** it won't lie about network interconnect, total disconnects
+ ** and no-IDs. (or at least, it doesn't *matter* if it does)
+ */
+ if (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort) MAX_RUP)
+ continue;
+
+ for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
+ if ((RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) == RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) && (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) == RBYTE(PktCmdP->RouteTopology[NewLink].Link))) {
+ Lies++;
+ }
+ }
+ }
+
+ if (Lies) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
+ rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
+ RBYTE(PktCmdP->RouteTopology[0].Unit),
+ 'A' + RBYTE(PktCmdP->RouteTopology[0].Link),
+ RBYTE(PktCmdP->RouteTopology[1].Unit),
+ 'A' + RBYTE(PktCmdP->RouteTopology[1].Link), RBYTE(PktCmdP->RouteTopology[2].Unit), 'A' + RBYTE(PktCmdP->RouteTopology[2].Link), RBYTE(PktCmdP->RouteTopology[3].Unit), 'A' + RBYTE(PktCmdP->RouteTopology[3].Link));
+ return TRUE;
+ }
+
+ /*
+ ** now, process each link.
+ */
+ for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
+ /*
+ ** this is what it was connected to
+ */
+ OldUnit = TopP[ThisLink].Unit;
+ OldLink = TopP[ThisLink].Link;
+
+ /*
+ ** this is what it is now connected to
+ */
+ NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);
+ NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);
+
+ if (OldUnit != NewUnit || OldLink != NewLink) {
+ /*
+ ** something has changed!
+ */
+
+ if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
+ } else {
+ /*
+ ** put the new values in
+ */
+ TopP[ThisLink].Unit = NewUnit;
+ TopP[ThisLink].Link = NewLink;
+
+ RIOSetChange(p);
+
+ if (OldUnit <= MAX_RUP) {
+ /*
+ ** If something has become bust, then re-enable them messages
+ */
+ if (!p->RIONoMessage)
+ RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
+ }
+
+ if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
+ RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
+
+ if (NewUnit == ROUTE_NO_ID)
+ rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
+
+ if (NewUnit == ROUTE_INTERCONNECT) {
+ if (!p->RIONoMessage)
+ cprintf("%s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
+ }
+
+ /*
+ ** perform an update for 'the other end', so that these messages
+ ** only appears once. Only disconnect the other end if it is pointing
+ ** at us!
+ */
+ if (OldUnit == HOST_ID) {
+ if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
+ HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
+ HostP->Topology[OldLink].Link = NO_LINK;
+ } else {
+ rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
+ }
+ } else if (OldUnit <= MAX_RUP) {
+ if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
+ HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
+ HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
+ } else {
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
+ }
+ }
+ if (NewUnit == HOST_ID) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
+ HostP->Topology[NewLink].Unit = ThisUnit;
+ HostP->Topology[NewLink].Link = ThisLink;
+ } else if (NewUnit <= MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
+ HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
+ HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
+ }
+ }
+ RIOSetChange(p);
+ RIOCheckIsolated(p, HostP, OldUnit);
+ }
+ }
+ return TRUE;
}
- RIOSetChange(p);
- RIOCheckIsolated(p, HostP, OldUnit );
- }
- }
- return TRUE;
- }
-
- /*
- ** The only other command we recognise is a route_request command
- */
- if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n",
- RBYTE(PktCmdP->Command),Rup,(int)HostP);
- return TRUE;
- }
-
- RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
- (RBYTE(PktCmdP->UniqNum[1]) << 8) +
- (RBYTE(PktCmdP->UniqNum[2]) << 16) +
- (RBYTE(PktCmdP->UniqNum[3]) << 24);
-
- /*
- ** Determine if 8 or 16 port RTA
- */
- RtaType = GetUnitType(RtaUniq);
-
- rio_dprintk (RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
-
- Mod = RBYTE(PktCmdP->ModuleTypes);
- Mod1 = LONYBLE(Mod);
- if (RtaType == TYPE_RTA16)
- {
- /*
- ** Only one ident is set for a 16 port RTA. To make compatible
- ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
- */
- Mod2 = Mod1;
- rio_dprintk (RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n",
- p->RIOModuleTypes[Mod1].Name);
- }
- else
- {
- Mod2 = HINYBLE(Mod);
- rio_dprintk (RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n",
- p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
- }
-
- if ( RtaUniq == 0xffffffff )
- {
- ShowPacket( DBG_SPECIAL, PacketP );
- }
-
- /*
- ** try to unhook a command block from the command free list.
- */
- if ( !(CmdBlkP = RIOGetCmdBlk()) )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
- return 0;
- }
-
- /*
- ** Fill in the default info on the command block
- */
- CmdBlkP->Packet.dest_unit = Rup;
- CmdBlkP->Packet.dest_port = ROUTE_RUP;
- CmdBlkP->Packet.src_unit = HOST_ID;
- CmdBlkP->Packet.src_port = ROUTE_RUP;
- CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
- CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
- PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
-
- if (! RIOBootOk(p, HostP, RtaUniq))
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n",
- RtaUniq);
- PktReplyP->Command = ROUTE_FOAD;
- HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
- RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
- return TRUE;
- }
-
- /*
- ** Check to see if the RTA is configured for this host
- */
- for ( ThisUnit=0; ThisUnit<MAX_RUP; ThisUnit++ )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
- ThisUnit,
- HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ?
- "Slot-In-Use":"Not In Use",
- HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ?
- "Slot-Tentative":"Not Tentative",
- HostP->Mapping[ThisUnit].RtaUniqueNum);
-
- /*
- ** We have an entry for it.
- */
- if ( (HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) &&
- (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq) )
- {
- if (RtaType == TYPE_RTA16)
- {
- ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
- rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n",
- RtaUniq,ThisUnit,ThisUnit2);
- }
- else
- rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n",
- RtaUniq,ThisUnit);
- /*
- ** If we have no knowledge of booting it, then the host has
- ** been re-booted, and so we must kill the RTA, so that it
- ** will be booted again (potentially with new bins)
- ** and it will then re-ask for an ID, which we will service.
- */
- if ( (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) &&
- !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED) )
- {
- if ( !(HostP->Mapping[ThisUnit].Flags & MSG_DONE) )
- {
- if ( !p->RIONoMessage )
- cprintf("RTA '%s' is being updated.\n",HostP->Mapping[ThisUnit].Name);
- HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+
+ /*
+ ** The only other command we recognise is a route_request command
+ */
+ if (RBYTE(PktCmdP->Command) != ROUTE_REQUEST) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n", RBYTE(PktCmdP->Command), Rup, (int) HostP);
+ return TRUE;
}
- PktReplyP->Command = ROUTE_FOAD;
- HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
- RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
- return TRUE;
- }
-
- /*
- ** Send the ID (entry) to this RTA. The ID number is implicit as
- ** the offset into the table. It is worth noting at this stage
- ** that offset zero in the table contains the entries for the
- ** RTA with ID 1!!!!
- */
- PktReplyP->Command = ROUTE_ALLOCATE;
- PktReplyP->IDNum = ThisUnit+1;
- if (RtaType == TYPE_RTA16)
- {
- if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
- /*
- ** Adjust the phb and tx pkt dest_units for 2nd block of 8
- ** only if the RTA has ports associated (SLOT_IN_USE)
- */
- RIOFixPhbs(p, HostP, ThisUnit2);
- PktReplyP->IDNum2 = ThisUnit2+1;
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n",
- HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
- }
- else
- {
- PktReplyP->IDNum2 = ROUTE_NO_ID;
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n",
- HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum);
- }
- HostP->Copy("RT_ALLOCAT",PktReplyP->CommandText,10);
-
- RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
-
- /*
- ** If this is a freshly booted RTA, then we need to re-open
- ** the ports, if any where open, so that data may once more
- ** flow around the system!
- */
- if ( (HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) &&
- (HostP->Mapping[ThisUnit].SysPort != NO_PORT) )
- {
+
+ RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + (RBYTE(PktCmdP->UniqNum[1]) << 8) + (RBYTE(PktCmdP->UniqNum[2]) << 16) + (RBYTE(PktCmdP->UniqNum[3]) << 24);
+
/*
- ** look at the ports associated with this beast and
- ** see if any where open. If they was, then re-open
- ** them, using the info from the tty flags.
- */
- for ( port=0; port<PORTS_PER_RTA; port++ )
- {
- PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort];
- if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n");
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->MagicFlags |= MAGIC_REBOOT;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- }
+ ** Determine if 8 or 16 port RTA
+ */
+ RtaType = GetUnitType(RtaUniq);
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
+
+ Mod = RBYTE(PktCmdP->ModuleTypes);
+ Mod1 = LONYBLE(Mod);
+ if (RtaType == TYPE_RTA16) {
+ /*
+ ** Only one ident is set for a 16 port RTA. To make compatible
+ ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
+ */
+ Mod2 = Mod1;
+ rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
+ } else {
+ Mod2 = HINYBLE(Mod);
+ rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
}
- if (RtaType == TYPE_RTA16)
- {
- for ( port=0; port<PORTS_PER_RTA; port++ )
- {
- PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort];
- if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n");
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->MagicFlags |= MAGIC_REBOOT;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- }
- }
+
+ if (RtaUniq == 0xffffffff) {
+ ShowPacket(DBG_SPECIAL, PacketP);
}
- }
-
- /*
- ** keep a copy of the module types!
- */
- HostP->UnixRups[ThisUnit].ModTypes = Mod;
- if (RtaType == TYPE_RTA16)
- HostP->UnixRups[ThisUnit2].ModTypes = Mod;
-
- /*
- ** If either of the modules on this unit is read-only or write-only
- ** or none-xprint, then we need to transfer that info over to the
- ** relevant ports.
- */
- if ( HostP->Mapping[ThisUnit].SysPort != NO_PORT )
- {
- for ( port=0; port<PORTS_PER_MODULE; port++ )
- {
- p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config |=
- p->RIOModuleTypes[Mod1].Flags[port];
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+
+ /*
+ ** try to unhook a command block from the command free list.
+ */
+ if (!(CmdBlkP = RIOGetCmdBlk())) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
+ return 0;
}
- if (RtaType == TYPE_RTA16)
- {
- for ( port=0; port<PORTS_PER_MODULE; port++ )
- {
- p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
- }
+
+ /*
+ ** Fill in the default info on the command block
+ */
+ CmdBlkP->Packet.dest_unit = Rup;
+ CmdBlkP->Packet.dest_port = ROUTE_RUP;
+ CmdBlkP->Packet.src_unit = HOST_ID;
+ CmdBlkP->Packet.src_port = ROUTE_RUP;
+ CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
+ CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+ PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
+
+ if (!RIOBootOk(p, HostP, RtaUniq)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
+ PktReplyP->Command = ROUTE_FOAD;
+ HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+ return TRUE;
}
- }
-
- /*
- ** Job done, get on with the interrupts!
- */
- return TRUE;
- }
- }
- /*
- ** There is no table entry for this RTA at all.
- **
- ** Lets check to see if we actually booted this unit - if not,
- ** then we reset it and it will go round the loop of being booted
- ** we can then worry about trying to fit it into the table.
- */
- for ( ThisUnit=0; ThisUnit<HostP->NumExtraBooted; ThisUnit++ )
- if ( HostP->ExtraUnits[ThisUnit] == RtaUniq )
- break;
- if ( ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS )
- {
- /*
- ** if the unit wasn't in the table, and the table wasn't full, then
- ** we reset the unit, because we didn't boot it.
- ** However, if the table is full, it could be that we did boot
- ** this unit, and so we won't reboot it, because it isn't really
- ** all that disasterous to keep the old bins in most cases. This
- ** is a rather tacky feature, but we are on the edge of reallity
- ** here, because the implication is that someone has connected
- ** 16+MAX_EXTRA_UNITS onto one host.
- */
- static int UnknownMesgDone = 0;
-
- if ( !UnknownMesgDone )
- {
- if (! p->RIONoMessage)
- cprintf("One or more unknown RTAs are being updated.\n");
- UnknownMesgDone = 1;
- }
-
- PktReplyP->Command = ROUTE_FOAD;
- HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
- }
- else
- {
- /*
- ** we did boot it (as an extra), and there may now be a table
- ** slot free (because of a delete), so we will try to make
- ** a tentative entry for it, so that the configurator can see it
- ** and fill in the details for us.
- */
- if (RtaType == TYPE_RTA16)
- {
- if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0)
- {
- RIODefaultName(p, HostP, ThisUnit);
- FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+
+ /*
+ ** Check to see if the RTA is configured for this host
+ */
+ for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
+ ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
+
+ /*
+ ** We have an entry for it.
+ */
+ if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
+ if (RtaType == TYPE_RTA16) {
+ ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
+ rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
+ } else
+ rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
+ /*
+ ** If we have no knowledge of booting it, then the host has
+ ** been re-booted, and so we must kill the RTA, so that it
+ ** will be booted again (potentially with new bins)
+ ** and it will then re-ask for an ID, which we will service.
+ */
+ if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
+ if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
+ if (!p->RIONoMessage)
+ cprintf("RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
+ HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+ }
+ PktReplyP->Command = ROUTE_FOAD;
+ HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+ return TRUE;
+ }
+
+ /*
+ ** Send the ID (entry) to this RTA. The ID number is implicit as
+ ** the offset into the table. It is worth noting at this stage
+ ** that offset zero in the table contains the entries for the
+ ** RTA with ID 1!!!!
+ */
+ PktReplyP->Command = ROUTE_ALLOCATE;
+ PktReplyP->IDNum = ThisUnit + 1;
+ if (RtaType == TYPE_RTA16) {
+ if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
+ /*
+ ** Adjust the phb and tx pkt dest_units for 2nd block of 8
+ ** only if the RTA has ports associated (SLOT_IN_USE)
+ */
+ RIOFixPhbs(p, HostP, ThisUnit2);
+ PktReplyP->IDNum2 = ThisUnit2 + 1;
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
+ } else {
+ PktReplyP->IDNum2 = ROUTE_NO_ID;
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
+ }
+ HostP->Copy("RT_ALLOCAT", PktReplyP->CommandText, 10);
+
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+
+ /*
+ ** If this is a freshly booted RTA, then we need to re-open
+ ** the ports, if any where open, so that data may once more
+ ** flow around the system!
+ */
+ if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
+ /*
+ ** look at the ports associated with this beast and
+ ** see if any where open. If they was, then re-open
+ ** them, using the info from the tty flags.
+ */
+ for (port = 0; port < PORTS_PER_RTA; port++) {
+ PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
+ if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->MagicFlags |= MAGIC_REBOOT;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ }
+ }
+ if (RtaType == TYPE_RTA16) {
+ for (port = 0; port < PORTS_PER_RTA; port++) {
+ PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
+ if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->MagicFlags |= MAGIC_REBOOT;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ }
+ }
+ }
+ }
+
+ /*
+ ** keep a copy of the module types!
+ */
+ HostP->UnixRups[ThisUnit].ModTypes = Mod;
+ if (RtaType == TYPE_RTA16)
+ HostP->UnixRups[ThisUnit2].ModTypes = Mod;
+
+ /*
+ ** If either of the modules on this unit is read-only or write-only
+ ** or none-xprint, then we need to transfer that info over to the
+ ** relevant ports.
+ */
+ if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
+ for (port = 0; port < PORTS_PER_MODULE; port++) {
+ p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+ }
+ if (RtaType == TYPE_RTA16) {
+ for (port = 0; port < PORTS_PER_MODULE; port++) {
+ p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+ }
+ }
+ }
+
+ /*
+ ** Job done, get on with the interrupts!
+ */
+ return TRUE;
+ }
}
- }
- else
- {
- if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0)
- {
- RIODefaultName(p, HostP, ThisUnit);
- FillSlot(ThisUnit, 0, RtaUniq, HostP);
+ /*
+ ** There is no table entry for this RTA at all.
+ **
+ ** Lets check to see if we actually booted this unit - if not,
+ ** then we reset it and it will go round the loop of being booted
+ ** we can then worry about trying to fit it into the table.
+ */
+ for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
+ if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
+ break;
+ if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
+ /*
+ ** if the unit wasn't in the table, and the table wasn't full, then
+ ** we reset the unit, because we didn't boot it.
+ ** However, if the table is full, it could be that we did boot
+ ** this unit, and so we won't reboot it, because it isn't really
+ ** all that disasterous to keep the old bins in most cases. This
+ ** is a rather tacky feature, but we are on the edge of reallity
+ ** here, because the implication is that someone has connected
+ ** 16+MAX_EXTRA_UNITS onto one host.
+ */
+ static int UnknownMesgDone = 0;
+
+ if (!UnknownMesgDone) {
+ if (!p->RIONoMessage)
+ cprintf("One or more unknown RTAs are being updated.\n");
+ UnknownMesgDone = 1;
+ }
+
+ PktReplyP->Command = ROUTE_FOAD;
+ HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+ } else {
+ /*
+ ** we did boot it (as an extra), and there may now be a table
+ ** slot free (because of a delete), so we will try to make
+ ** a tentative entry for it, so that the configurator can see it
+ ** and fill in the details for us.
+ */
+ if (RtaType == TYPE_RTA16) {
+ if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
+ RIODefaultName(p, HostP, ThisUnit);
+ FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+ }
+ } else {
+ if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
+ RIODefaultName(p, HostP, ThisUnit);
+ FillSlot(ThisUnit, 0, RtaUniq, HostP);
+ }
+ }
+ PktReplyP->Command = ROUTE_USED;
+ HostP->Copy("RT_USED", PktReplyP->CommandText, 7);
}
- }
- PktReplyP->Command = ROUTE_USED;
- HostP->Copy("RT_USED",PktReplyP->CommandText,7);
- }
- RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
- return TRUE;
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+ return TRUE;
}
-void
-RIOFixPhbs(p, HostP, unit)
+void RIOFixPhbs(p, HostP, unit)
struct rio_info *p;
struct Host *HostP;
uint unit;
{
- ushort link, port;
- struct Port *PortP;
+ ushort link, port;
+ struct Port *PortP;
unsigned long flags;
int PortN = HostP->Mapping[unit].SysPort;
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
if (PortN != -1) {
- ushort dest_unit = HostP->Mapping[unit].ID2;
+ ushort dest_unit = HostP->Mapping[unit].ID2;
/*
- ** Get the link number used for the 1st 8 phbs on this unit.
- */
+ ** Get the link number used for the 1st 8 phbs on this unit.
+ */
PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
link = RWORD(PortP->PhbP->link);
for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
- ushort dest_port = port + 8;
-#if 0
- uint PktInt;
-#endif
- WORD *TxPktP;
- PKT *Pkt;
+ ushort dest_port = port + 8;
+ WORD *TxPktP;
+ PKT *Pkt;
PortP = p->RIOPortp[PortN];
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** If RTA is not powered on, the tx packets will be
- ** unset, so go no further.
- */
+ ** If RTA is not powered on, the tx packets will be
+ ** unset, so go no further.
+ */
if (PortP->TxStart == 0) {
- rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- break;
+ rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ break;
}
/*
- ** For the second slot of a 16 port RTA, the driver needs to
- ** sort out the phb to port mappings. The dest_unit for this
- ** group of 8 phbs is set to the dest_unit of the accompanying
- ** 8 port block. The dest_port of the second unit is set to
- ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
- ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
- ** (being the second map ID) will be sent to dest_unit 5, port
- ** 14. When this RTA is deleted, dest_unit for ID 6 will be
- ** restored, and the dest_port will be reduced by 8.
- ** Transmit packets also have a destination field which needs
- ** adjusting in the same manner.
- ** Note that the unit/port bytes in 'dest' are swapped.
- ** We also need to adjust the phb and rup link numbers for the
- ** second block of 8 ttys.
- */
+ ** For the second slot of a 16 port RTA, the driver needs to
+ ** sort out the phb to port mappings. The dest_unit for this
+ ** group of 8 phbs is set to the dest_unit of the accompanying
+ ** 8 port block. The dest_port of the second unit is set to
+ ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
+ ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
+ ** (being the second map ID) will be sent to dest_unit 5, port
+ ** 14. When this RTA is deleted, dest_unit for ID 6 will be
+ ** restored, and the dest_port will be reduced by 8.
+ ** Transmit packets also have a destination field which needs
+ ** adjusting in the same manner.
+ ** Note that the unit/port bytes in 'dest' are swapped.
+ ** We also need to adjust the phb and rup link numbers for the
+ ** second block of 8 ttys.
+ */
for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
/*
- ** *TxPktP is the pointer to the transmit packet on the host
- ** card. This needs to be translated into a 32 bit pointer
- ** so it can be accessed from the driver.
- */
- Pkt = (PKT *) RIO_PTR(HostP->Caddr,RINDW(TxPktP));
+ ** *TxPktP is the pointer to the transmit packet on the host
+ ** card. This needs to be translated into a 32 bit pointer
+ ** so it can be accessed from the driver.
+ */
+ Pkt = (PKT *) RIO_PTR(HostP->Caddr, RINDW(TxPktP));
/*
- ** If the packet is used, reset it.
- */
- Pkt = (PKT *)((uint)Pkt & ~PKT_IN_USE);
+ ** If the packet is used, reset it.
+ */
+ Pkt = (PKT *) ((uint) Pkt & ~PKT_IN_USE);
WBYTE(Pkt->dest_unit, dest_unit);
WBYTE(Pkt->dest_port, dest_port);
}
- rio_dprintk (RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n",
- RWORD(PortP->PhbP->destination) & 0xff,
- (RWORD(PortP->PhbP->destination) >> 8) & 0xff,
- dest_unit, dest_port);
+ rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", RWORD(PortP->PhbP->destination) & 0xff, (RWORD(PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8));
WWORD(PortP->PhbP->link, link);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
}
/*
- ** Now make sure the range of ports to be serviced includes
- ** the 2nd 8 on this 16 port RTA.
- */
- if (link > 3) return;
+ ** Now make sure the range of ports to be serviced includes
+ ** the 2nd 8 on this 16 port RTA.
+ */
+ if (link > 3)
+ return;
if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) {
- rio_dprintk (RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
+ rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7);
}
}
@@ -723,26 +603,21 @@ uint unit;
** the world about it. This is done to ensure that the configurator
** only gets up-to-date information about what is going on.
*/
-static int
-RIOCheckIsolated(p, HostP, UnitId)
-struct rio_info * p;
+static int RIOCheckIsolated(p, HostP, UnitId)
+struct rio_info *p;
struct Host *HostP;
uint UnitId;
{
unsigned long flags;
rio_spin_lock_irqsave(&HostP->HostLock, flags);
-#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
-#endif
- if ( RIOCheck( HostP, UnitId ) ) {
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
+ if (RIOCheck(HostP, UnitId)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
- return(0);
+ return (0);
}
- RIOIsolate(p, HostP, UnitId );
+ RIOIsolate(p, HostP, UnitId);
RIOSetChange(p);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
return 1;
@@ -753,85 +628,75 @@ uint UnitId;
** all the units attached to it. This will mean that the entire
** subnet will re-introduce itself.
*/
-static int
-RIOIsolate(p, HostP, UnitId)
-struct rio_info * p;
-struct Host * HostP;
-uint UnitId;
+static int RIOIsolate(p, HostP, UnitId)
+struct rio_info *p;
+struct Host *HostP;
+uint UnitId;
{
uint link, unit;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
-#endif
UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */
- if ( UnitId >= MAX_RUP ) /* dontcha just lurv unsigned maths! */
- return(0);
+ if (UnitId >= MAX_RUP) /* dontcha just lurv unsigned maths! */
+ return (0);
- if ( HostP->Mapping[UnitId].Flags & BEEN_HERE )
- return(0);
+ if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
+ return (0);
HostP->Mapping[UnitId].Flags |= BEEN_HERE;
- if ( p->RIOPrintDisabled == DO_PRINT )
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
+ if (p->RIOPrintDisabled == DO_PRINT)
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
- for ( link=0; link<LINKS_PER_UNIT; link++) {
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
unit = HostP->Mapping[UnitId].Topology[link].Unit;
HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
- RIOIsolate(p, HostP, unit );
+ RIOIsolate(p, HostP, unit);
}
HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
return 1;
}
-static int
-RIOCheck(HostP, UnitId)
+static int RIOCheck(HostP, UnitId)
struct Host *HostP;
uint UnitId;
{
- unsigned char link;
+ unsigned char link;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
-#endif
/* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
- if ( UnitId == HOST_ID ) {
+ if (UnitId == HOST_ID) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
return 1;
}
UnitId--;
- if ( UnitId >= MAX_RUP ) {
+ if (UnitId >= MAX_RUP) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
return 0;
}
- for ( link=0; link<LINKS_PER_UNIT; link++ ) {
- if ( HostP->Mapping[UnitId].Topology[link].Unit==HOST_ID ) {
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n",
- UnitId, 'A'+link)); */
+ UnitId, 'A'+link)); */
return 1;
}
}
- if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) {
+ if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
return 0;
}
HostP->Mapping[UnitId].Flags |= BEEN_HERE;
- for ( link=0; link < LINKS_PER_UNIT; link++ ) {
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
- if ( RIOCheck( HostP, HostP->Mapping[UnitId].Topology[link].Unit ) ) {
+ if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
return 1;
@@ -841,7 +706,7 @@ uint UnitId;
HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
-
+
return 0;
}
@@ -849,61 +714,57 @@ uint UnitId;
** Returns the type of unit (host, 16/8 port RTA)
*/
-uint
-GetUnitType(Uniq)
+uint GetUnitType(Uniq)
uint Uniq;
{
- switch ( (Uniq >> 28) & 0xf)
- {
- case RIO_AT:
- case RIO_MCA:
- case RIO_EISA:
- case RIO_PCI:
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Host\n");
- return(TYPE_HOST);
- case RIO_RTA_16:
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
- return(TYPE_RTA16);
- case RIO_RTA:
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
- return(TYPE_RTA8);
- default :
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
- return(99);
+ switch ((Uniq >> 28) & 0xf) {
+ case RIO_AT:
+ case RIO_MCA:
+ case RIO_EISA:
+ case RIO_PCI:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
+ return (TYPE_HOST);
+ case RIO_RTA_16:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
+ return (TYPE_RTA16);
+ case RIO_RTA:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
+ return (TYPE_RTA8);
+ default:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
+ return (99);
}
}
-int
-RIOSetChange(p)
-struct rio_info * p;
+int RIOSetChange(p)
+struct rio_info *p;
{
- if ( p->RIOQuickCheck != NOT_CHANGED )
- return(0);
+ if (p->RIOQuickCheck != NOT_CHANGED)
+ return (0);
p->RIOQuickCheck = CHANGED;
- if ( p->RIOSignalProcess ) {
- rio_dprintk (RIO_DEBUG_ROUTE, "Send SIG-HUP");
+ if (p->RIOSignalProcess) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
/*
- psignal( RIOSignalProcess, SIGHUP );
- */
+ psignal( RIOSignalProcess, SIGHUP );
+ */
}
- return(0);
+ return (0);
}
-static void
-RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change)
-struct rio_info * p;
+static void RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change)
+struct rio_info *p;
struct Host *HostP;
uint FromId;
uint FromLink;
uint ToId;
uint ToLink;
-int Change;
+int Change;
{
- char *FromName;
- char *FromType;
- char *ToName;
- char *ToType;
- unsigned int tp;
+ char *FromName;
+ char *FromType;
+ char *ToName;
+ char *ToType;
+ unsigned int tp;
/*
** 15.10.1998 ARG - ESIL 0759
@@ -932,38 +793,32 @@ int Change;
** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
** connections and disconnections.
*/
- if (Change == CONNECT) {
- if (p->RIORtaDisCons) p->RIORtaDisCons--;
- }
- else {
+ if (Change == CONNECT) {
+ if (p->RIORtaDisCons)
+ p->RIORtaDisCons--;
+ } else {
p->RIORtaDisCons++;
- }
+ }
- if ( p->RIOPrintDisabled == DONT_PRINT )
+ if (p->RIOPrintDisabled == DONT_PRINT)
return;
- if ( FromId > ToId ) {
+ if (FromId > ToId) {
tp = FromId;
FromId = ToId;
ToId = tp;
tp = FromLink;
FromLink = ToLink;
ToLink = tp;
- }
-
- FromName = FromId ? HostP->Mapping[FromId-1].Name : HostP->Name;
- FromType = FromId ? "RTA" : "HOST";
- ToName = ToId ? HostP->Mapping[ToId-1].Name : HostP->Name;
- ToType = ToId ? "RTA" : "HOST";
-
- rio_dprintk (RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
- FromType, FromName, 'A'+FromLink,
- ToType, ToName, 'A'+ToLink,
- (Change==CONNECT) ? "established" : "disconnected");
- cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
- FromType, FromName, 'A'+FromLink,
- ToType, ToName, 'A'+ToLink,
- (Change==CONNECT) ? "established" : "disconnected");
+ }
+
+ FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
+ FromType = FromId ? "RTA" : "HOST";
+ ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
+ ToType = ToId ? "RTA" : "HOST";
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
+ cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
}
/*
@@ -972,24 +827,21 @@ int Change;
** Delete and RTA entry from the saved table given to us
** by the configuration program.
*/
-static int
-RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
+static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
{
- int entry;
-
- /*
- ** We loop for all entries even after finding an entry and
- ** zeroing it because we may have two entries to delete if
- ** it's a 16 port RTA.
- */
- for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++)
- {
- if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum)
- {
- bzero((caddr_t)&p->RIOSavedTable[entry], sizeof(struct Map));
+ int entry;
+
+ /*
+ ** We loop for all entries even after finding an entry and
+ ** zeroing it because we may have two entries to delete if
+ ** it's a 16 port RTA.
+ */
+ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+ if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
+ bzero((caddr_t) & p->RIOSavedTable[entry], sizeof(struct Map));
+ }
}
- }
- return 0;
+ return 0;
}
@@ -999,64 +851,58 @@ RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
** Scan the unit links to and return zero if the unit is completely
** disconnected.
*/
-static int
-RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
+static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
{
- int link;
-
-
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
- /*
- ** If the slot is tentative and does not belong to the
- ** second half of a 16 port RTA then scan to see if
- ** is disconnected.
- */
- for (link = 0; link < LINKS_PER_UNIT; link++)
- {
- if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
- break;
- }
-
- /*
- ** If not all links are disconnected then we can forget about it.
- */
- if (link < LINKS_PER_UNIT)
- return 1;
+ int link;
+
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
+ /*
+ ** If the slot is tentative and does not belong to the
+ ** second half of a 16 port RTA then scan to see if
+ ** is disconnected.
+ */
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
+ break;
+ }
+
+ /*
+ ** If not all links are disconnected then we can forget about it.
+ */
+ if (link < LINKS_PER_UNIT)
+ return 1;
#ifdef NEED_TO_FIX_THIS
- /* Ok so all the links are disconnected. But we may have only just
- ** made this slot tentative and not yet received a topology update.
- ** Lets check how long ago we made it tentative.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
- if (drv_getparm(LBOLT, (ulong_t *) &current_time))
- rio_dprintk (RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
-
- elapse_time = current_time - TentTime[unit];
- rio_dprintk (RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n",
- elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
- if (drv_hztousec(elapse_time) < WAIT_TO_FINISH)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n",
- unit, drv_hztousec(elapse_time));
- return 1;
- }
+ /* Ok so all the links are disconnected. But we may have only just
+ ** made this slot tentative and not yet received a topology update.
+ ** Lets check how long ago we made it tentative.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
+ if (drv_getparm(LBOLT, (ulong_t *) & current_time))
+ rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
+
+ elapse_time = current_time - TentTime[unit];
+ rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
+ if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
+ return 1;
+ }
#endif
- /*
- ** We have found an usable slot.
- ** If it is half of a 16 port RTA then delete the other half.
- */
- if (HostP->Mapping[unit].ID2 != 0)
- {
- int nOther = (HostP->Mapping[unit].ID2) -1;
-
- rio_dprintk (RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
- bzero((caddr_t)&HostP->Mapping[nOther], sizeof(struct Map));
- }
- RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
+ /*
+ ** We have found an usable slot.
+ ** If it is half of a 16 port RTA then delete the other half.
+ */
+ if (HostP->Mapping[unit].ID2 != 0) {
+ int nOther = (HostP->Mapping[unit].ID2) - 1;
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
+ bzero((caddr_t) & HostP->Mapping[nOther], sizeof(struct Map));
+ }
+ RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
- return 0;
+ return 0;
}
@@ -1066,150 +912,134 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
** This function scans the given host table for either one
** or two free unit ID's.
*/
-int
-RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2)
+int RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint * pID1, uint * pID2)
{
- int unit,tempID;
-
- /*
- ** Initialise the ID's to MAX_RUP.
- ** We do this to make the loop for setting the ID's as simple as
- ** possible.
- */
- *pID1 = MAX_RUP;
- if (pID2 != NULL)
- *pID2 = MAX_RUP;
-
- /*
- ** Scan all entries of the host mapping table for free slots.
- ** We scan for free slots first and then if that is not successful
- ** we start all over again looking for tentative slots we can re-use.
- */
- for (unit = 0; unit < MAX_RUP; unit++)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Scanning unit %d\n",unit);
+ int unit, tempID;
+
/*
- ** If the flags are zero then the slot is empty.
- */
- if (HostP->Mapping[unit].Flags == 0)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, " This slot is empty.\n");
- /*
- ** If we haven't allocated the first ID then do it now.
- */
- if (*pID1 == MAX_RUP)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
- *pID1 = unit;
+ ** Initialise the ID's to MAX_RUP.
+ ** We do this to make the loop for setting the ID's as simple as
+ ** possible.
+ */
+ *pID1 = MAX_RUP;
+ if (pID2 != NULL)
+ *pID2 = MAX_RUP;
+ /*
+ ** Scan all entries of the host mapping table for free slots.
+ ** We scan for free slots first and then if that is not successful
+ ** we start all over again looking for tentative slots we can re-use.
+ */
+ for (unit = 0; unit < MAX_RUP; unit++) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
/*
- ** If the second ID is not needed then we can return
- ** now.
- */
- if (pID2 == NULL)
- return 0;
- }
- else
- {
- /*
- ** Allocate the second slot and return.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
- *pID2 = unit;
- return 0;
- }
+ ** If the flags are zero then the slot is empty.
+ */
+ if (HostP->Mapping[unit].Flags == 0) {
+ rio_dprintk(RIO_DEBUG_ROUTE, " This slot is empty.\n");
+ /*
+ ** If we haven't allocated the first ID then do it now.
+ */
+ if (*pID1 == MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
+ *pID1 = unit;
+
+ /*
+ ** If the second ID is not needed then we can return
+ ** now.
+ */
+ if (pID2 == NULL)
+ return 0;
+ } else {
+ /*
+ ** Allocate the second slot and return.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
+ *pID2 = unit;
+ return 0;
+ }
+ }
}
- }
-
- /*
- ** If we manage to come out of the free slot loop then we
- ** need to start all over again looking for tentative slots
- ** that we can re-use.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
- for (unit = 0; unit < MAX_RUP; unit++)
- {
- if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) ||
- (HostP->Mapping[unit].Flags == 0)) && !
- (HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT ))
- {
- rio_dprintk (RIO_DEBUG_ROUTE, " Slot %d looks promising.\n",unit);
-
- if(unit == *pID1)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n");
- continue;
- }
-
- /*
- ** Slot is Tentative or Empty, but not a tentative second
- ** slot of a 16 porter.
- ** Attempt to free up this slot (and its parnter if
- ** it is a 16 port slot. The second slot will become
- ** empty after a call to RIOFreeDisconnected so thats why
- ** we look for empty slots above as well).
- */
- if (HostP->Mapping[unit].Flags != 0)
- if (RIOFreeDisconnected(p, HostP, unit) != 0)
- continue;
- /*
- ** If we haven't allocated the first ID then do it now.
- */
- if (*pID1 == MAX_RUP)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
- *pID1 = unit;
- /*
- ** Clear out this slot now that we intend to use it.
- */
- bzero(&HostP->Mapping[unit], sizeof(struct Map));
+ /*
+ ** If we manage to come out of the free slot loop then we
+ ** need to start all over again looking for tentative slots
+ ** that we can re-use.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
+ for (unit = 0; unit < MAX_RUP; unit++) {
+ if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, " Slot %d looks promising.\n", unit);
+
+ if (unit == *pID1) {
+ rio_dprintk(RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n");
+ continue;
+ }
- /*
- ** If the second ID is not needed then we can return
- ** now.
- */
- if (pID2 == NULL)
- return 0;
- }
- else
- {
- /*
- ** Allocate the second slot and return.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n",
- unit);
- *pID2 = unit;
+ /*
+ ** Slot is Tentative or Empty, but not a tentative second
+ ** slot of a 16 porter.
+ ** Attempt to free up this slot (and its parnter if
+ ** it is a 16 port slot. The second slot will become
+ ** empty after a call to RIOFreeDisconnected so thats why
+ ** we look for empty slots above as well).
+ */
+ if (HostP->Mapping[unit].Flags != 0)
+ if (RIOFreeDisconnected(p, HostP, unit) != 0)
+ continue;
+ /*
+ ** If we haven't allocated the first ID then do it now.
+ */
+ if (*pID1 == MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
+ *pID1 = unit;
- /*
- ** Clear out this slot now that we intend to use it.
- */
- bzero(&HostP->Mapping[unit], sizeof(struct Map));
-
- /* At this point under the right(wrong?) conditions
- ** we may have a first unit ID being higher than the
- ** second unit ID. This is a bad idea if we are about
- ** to fill the slots with a 16 port RTA.
- ** Better check and swap them over.
- */
-
- if (*pID1 > *pID2)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
- tempID = *pID1;
- *pID1 = *pID2;
- *pID2 = tempID;
+ /*
+ ** Clear out this slot now that we intend to use it.
+ */
+ bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+ /*
+ ** If the second ID is not needed then we can return
+ ** now.
+ */
+ if (pID2 == NULL)
+ return 0;
+ } else {
+ /*
+ ** Allocate the second slot and return.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", unit);
+ *pID2 = unit;
+
+ /*
+ ** Clear out this slot now that we intend to use it.
+ */
+ bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+ /* At this point under the right(wrong?) conditions
+ ** we may have a first unit ID being higher than the
+ ** second unit ID. This is a bad idea if we are about
+ ** to fill the slots with a 16 port RTA.
+ ** Better check and swap them over.
+ */
+
+ if (*pID1 > *pID2) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
+ tempID = *pID1;
+ *pID1 = *pID2;
+ *pID2 = tempID;
+ }
+ return 0;
+ }
}
- return 0;
- }
}
- }
- /*
- ** If we manage to get to the end of the second loop then we
- ** can give up and return a failure.
- */
- return 1;
+ /*
+ ** If we manage to get to the end of the second loop then we
+ ** can give up and return a failure.
+ */
+ return 1;
}
diff --git a/drivers/char/rio/riospace.h b/drivers/char/rio/riospace.h
index 32b09b0f23aa..534f1f5b9f53 100644
--- a/drivers/char/rio/riospace.h
+++ b/drivers/char/rio/riospace.h
@@ -47,9 +47,8 @@ static char *_riospace_h_sccs_ = "@(#)riospace.h 1.2";
** In particular, it won't be able to see changes to RIO_SLOTS
*/
-struct Conf
-{
- char Locator[24];
+struct Conf {
+ char Locator[24];
unsigned int StartupTime;
unsigned int SlowCook;
unsigned int IntrPollTime;
@@ -59,8 +58,8 @@ struct Conf
unsigned int HostLoadBase;
unsigned int XpHz;
unsigned int XpCps;
- char *XpOn;
- char *XpOff;
+ char *XpOn;
+ char *XpOff;
unsigned int MaxXpCps;
unsigned int MinXpCps;
unsigned int SpinCmds;
@@ -74,7 +73,7 @@ struct Conf
/*
** Board types - these MUST correspond to product codes!
-*/
+*/
#define RIO_EMPTY 0x0
#define RIO_EISA 0x3
#define RIO_RTA_16 0x9
@@ -86,18 +85,16 @@ struct Conf
/*
** Board data structure. This is used for configuration info
*/
-struct Brd
-{
- unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
- unsigned char Ivec; /* POLLED or ivec number */
- unsigned char Mode; /* Control stuff, see below */
+struct Brd {
+ unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
+ unsigned char Ivec; /* POLLED or ivec number */
+ unsigned char Mode; /* Control stuff, see below */
};
-struct Board
-{
- char Locator[RIO_LOCATOR_LEN];
- int NumSlots;
- struct Brd Boards[MAX_RIO_BOARDS];
+struct Board {
+ char Locator[RIO_LOCATOR_LEN];
+ int NumSlots;
+ struct Brd Boards[MAX_RIO_BOARDS];
};
#define BOOT_FROM_LINK 0x00
@@ -158,4 +155,4 @@ struct Board
#define DBG_ALWAYS 0x80000000
-#endif /* __rio_riospace_h__ */
+#endif /* __rio_riospace_h__ */
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
index e45bc275907a..a86b216ab653 100644
--- a/drivers/char/rio/riotable.c
+++ b/drivers/char/rio/riotable.c
@@ -91,9 +91,8 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2";
** A configuration table has been loaded. It is now up to us
** to sort it out and use the information contained therein.
*/
-int
-RIONewTable(p)
-struct rio_info * p;
+int RIONewTable(p)
+struct rio_info *p;
{
int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
struct Map *MapP;
@@ -103,26 +102,26 @@ struct rio_info * p;
char *cptr;
/*
- ** We have been sent a new table to install. We need to break
- ** it down into little bits and spread it around a bit to see
- ** what we have got.
- */
+ ** We have been sent a new table to install. We need to break
+ ** it down into little bits and spread it around a bit to see
+ ** what we have got.
+ */
/*
- ** Things to check:
- ** (things marked 'xx' aren't checked any more!)
- ** (1) That there are no booted Hosts/RTAs out there.
- ** (2) That the names are properly formed
- ** (3) That blank entries really are.
- ** xx (4) That hosts mentioned in the table actually exist. xx
- ** (5) That the IDs are unique (per host).
- ** (6) That host IDs are zero
- ** (7) That port numbers are valid
- ** (8) That port numbers aren't duplicated
- ** (9) That names aren't duplicated
- ** xx (10) That hosts that actually exist are mentioned in the table. xx
- */
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
- if ( p->RIOSystemUp ) { /* (1) */
+ ** Things to check:
+ ** (things marked 'xx' aren't checked any more!)
+ ** (1) That there are no booted Hosts/RTAs out there.
+ ** (2) That the names are properly formed
+ ** (3) That blank entries really are.
+ ** xx (4) That hosts mentioned in the table actually exist. xx
+ ** (5) That the IDs are unique (per host).
+ ** (6) That host IDs are zero
+ ** (7) That port numbers are valid
+ ** (8) That port numbers aren't duplicated
+ ** (9) That names aren't duplicated
+ ** xx (10) That hosts that actually exist are mentioned in the table. xx
+ */
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
+ if (p->RIOSystemUp) { /* (1) */
p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
return -EBUSY;
}
@@ -131,19 +130,19 @@ struct rio_info * p;
p->RIOError.Entry = -1;
p->RIOError.Other = -1;
- for ( Entry=0; Entry<TOTAL_MAP_ENTRIES; Entry++ ) {
+ for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
MapP = &p->RIOConnectTable[Entry];
if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
- cptr = MapP->Name; /* (2) */
- cptr[MAX_NAME_LEN-1]='\0';
- if ( cptr[0]=='\0' ) {
- bcopy(MapP->RtaUniqueNum?"RTA NN":"HOST NN",MapP->Name,8);
- MapP->Name[5] = '0'+Entry/10;
- MapP->Name[6] = '0'+Entry%10;
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
+ cptr = MapP->Name; /* (2) */
+ cptr[MAX_NAME_LEN - 1] = '\0';
+ if (cptr[0] == '\0') {
+ bcopy(MapP->RtaUniqueNum ? "RTA NN" : "HOST NN", MapP->Name, 8);
+ MapP->Name[5] = '0' + Entry / 10;
+ MapP->Name[6] = '0' + Entry % 10;
}
- while ( *cptr ) {
- if ( *cptr<' ' || *cptr>'~' ) {
+ while (*cptr) {
+ if (*cptr < ' ' || *cptr > '~') {
p->RIOError.Error = BAD_CHARACTER_IN_NAME;
p->RIOError.Entry = Entry;
return -ENXIO;
@@ -153,133 +152,119 @@ struct rio_info * p;
}
/*
- ** If the entry saved was a tentative entry then just forget
- ** about it.
- */
- if ( MapP->Flags & SLOT_TENTATIVE ) {
+ ** If the entry saved was a tentative entry then just forget
+ ** about it.
+ */
+ if (MapP->Flags & SLOT_TENTATIVE) {
MapP->HostUniqueNum = 0;
MapP->RtaUniqueNum = 0;
continue;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
- if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */
- if ( MapP->ID || MapP->SysPort || MapP->Flags ) {
- rio_dprintk (RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n",MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
+ if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) { /* (3) */
+ if (MapP->ID || MapP->SysPort || MapP->Flags) {
+ rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
continue;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
- for ( Host=0; Host<p->RIONumHosts; Host++ ) { /* (4) */
- if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
+ for (Host = 0; Host < p->RIONumHosts; Host++) { /* (4) */
+ if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
HostP = &p->RIOHosts[Host];
/*
- ** having done the lookup, we don't really want to do
- ** it again, so hang the host number in a safe place
- */
+ ** having done the lookup, we don't really want to do
+ ** it again, so hang the host number in a safe place
+ */
MapP->Topology[0].Unit = Host;
break;
}
}
- if ( Host >= p->RIONumHosts ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n",
- MapP->Name, MapP->HostUniqueNum);
+ if (Host >= p->RIONumHosts) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
MapP->HostUniqueNum = 0;
- /* MapP->RtaUniqueNum = 0; */
- /* MapP->ID = 0; */
- /* MapP->Flags = 0; */
- /* MapP->SysPort = 0; */
- /* MapP->Name[0] = 0; */
+ /* MapP->RtaUniqueNum = 0; */
+ /* MapP->ID = 0; */
+ /* MapP->Flags = 0; */
+ /* MapP->SysPort = 0; */
+ /* MapP->Name[0] = 0; */
continue;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
- if ( MapP->RtaUniqueNum ) { /* (5) */
- if ( !MapP->ID ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n",
- MapP->Name);
- p->RIOError.Error = ZERO_RTA_ID;
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
+ if (MapP->RtaUniqueNum) { /* (5) */
+ if (!MapP->ID) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
+ p->RIOError.Error = ZERO_RTA_ID;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- if ( MapP->ID > MAX_RUP ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n",
- MapP->Name, MapP->ID);
+ if (MapP->ID > MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
- if ( MapP->HostUniqueNum ==
- p->RIOConnectTable[SubEnt].HostUniqueNum &&
- MapP->ID == p->RIOConnectTable[SubEnt].ID ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n",
- MapP->Name, p->RIOConnectTable[SubEnt].Name);
+ for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
+ if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
p->RIOError.Error = DUPLICATED_RTA_ID;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
return -ENXIO;
}
/*
- ** If the RtaUniqueNum is the same, it may be looking at both
- ** entries for a 16 port RTA, so check the ids
- */
- if ((MapP->RtaUniqueNum ==
- p->RIOConnectTable[SubEnt].RtaUniqueNum)
- && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",MapP->Name);
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",
- p->RIOConnectTable[SubEnt].Name);
+ ** If the RtaUniqueNum is the same, it may be looking at both
+ ** entries for a 16 port RTA, so check the ids
+ */
+ if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
+ && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
return -ENXIO;
}
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
/* (7a) */
- if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) {
- rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n",
- (int)MapP->SysPort,MapP->Name, PORTS_PER_RTA);
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
/* (7b) */
- if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) {
- rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n",
- (int)MapP->SysPort, MapP->Name);
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
- if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT )
- continue;
- if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
+ for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
+ if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
+ continue;
+ if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
/* (8) */
- if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort ==
- p->RIOConnectTable[SubEnt].SysPort) ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n",
- MapP->Name, p->RIOConnectTable[SubEnt].Name,
- (int)MapP->SysPort);
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
p->RIOError.Error = TTY_NUMBER_IN_USE;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
- if (strcmp(MapP->Name,
- p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
- rio_dprintk (RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
+ if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
p->RIOError.Error = NAME_USED_TWICE;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
@@ -287,19 +272,16 @@ struct rio_info * p;
}
}
}
- }
- else { /* (6) */
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
- if ( MapP->ID ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n",
- MapP->Name);
+ } else { /* (6) */
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
+ if (MapP->ID) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
p->RIOError.Error = HOST_ID_NOT_ZERO;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- if ( MapP->SysPort != NO_PORT ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n",
- MapP->Name);
+ if (MapP->SysPort != NO_PORT) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
p->RIOError.Error = HOST_SYSPORT_BAD;
p->RIOError.Entry = Entry;
return -ENXIO;
@@ -308,106 +290,101 @@ struct rio_info * p;
}
/*
- ** wow! if we get here then it's a goody!
- */
+ ** wow! if we get here then it's a goody!
+ */
/*
- ** Zero the (old) entries for each host...
- */
- for ( Host=0; Host<RIO_HOSTS; Host++ ) {
- for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
- bzero((caddr_t)&p->RIOHosts[Host].Mapping[Entry],
- sizeof(struct Map));
+ ** Zero the (old) entries for each host...
+ */
+ for (Host = 0; Host < RIO_HOSTS; Host++) {
+ for (Entry = 0; Entry < MAX_RUP; Entry++) {
+ bzero((caddr_t) & p->RIOHosts[Host].Mapping[Entry], sizeof(struct Map));
}
- bzero((caddr_t)&p->RIOHosts[Host].Name[0],
- sizeof(p->RIOHosts[Host].Name) );
+ bzero((caddr_t) & p->RIOHosts[Host].Name[0], sizeof(p->RIOHosts[Host].Name));
}
/*
- ** Copy in the new table entries
- */
- for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
+ ** Copy in the new table entries
+ */
+ for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
MapP = &p->RIOConnectTable[Entry];
/*
- ** Now, if it is an empty slot ignore it!
- */
- if ( MapP->HostUniqueNum==0 )
+ ** Now, if it is an empty slot ignore it!
+ */
+ if (MapP->HostUniqueNum == 0)
continue;
/*
- ** we saved the host number earlier, so grab it back
- */
+ ** we saved the host number earlier, so grab it back
+ */
HostP = &p->RIOHosts[MapP->Topology[0].Unit];
/*
- ** If it is a host, then we only need to fill in the name field.
- */
- if ( MapP->ID==0 ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
- bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN);
+ ** If it is a host, then we only need to fill in the name field.
+ */
+ if (MapP->ID == 0) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
+ bcopy(MapP->Name, HostP->Name, MAX_NAME_LEN);
continue;
}
/*
- ** Its an RTA entry, so fill in the host mapping entries for it
- ** and the port mapping entries. Notice that entry zero is for
- ** ID one.
- */
- HostMapP = &HostP->Mapping[MapP->ID-1];
+ ** Its an RTA entry, so fill in the host mapping entries for it
+ ** and the port mapping entries. Notice that entry zero is for
+ ** ID one.
+ */
+ HostMapP = &HostP->Mapping[MapP->ID - 1];
if (MapP->Flags & SLOT_IN_USE) {
- rio_dprintk (RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
/*
- ** structure assign, then sort out the bits we shouldn't have done
- */
+ ** structure assign, then sort out the bits we shouldn't have done
+ */
*HostMapP = *MapP;
HostMapP->Flags = SLOT_IN_USE;
if (MapP->Flags & RTA16_SECOND_SLOT)
HostMapP->Flags |= RTA16_SECOND_SLOT;
- RIOReMapPorts(p, HostP, HostMapP );
- }
- else {
- rio_dprintk (RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
+ RIOReMapPorts(p, HostP, HostMapP);
+ } else {
+ rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
}
}
- for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
+ for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
}
- for ( Host=0; Host<p->RIONumHosts; Host++ ) {
- for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
+ for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
}
- for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
- for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
- p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit =
- ROUTE_DISCONNECT;
- p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link =
- NO_LINK;
+ for (Entry = 0; Entry < MAX_RUP; Entry++) {
+ for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
+ p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
+ p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
}
}
- if ( !p->RIOHosts[Host].Name[0] ) {
- bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+ if (!p->RIOHosts[Host].Name[0]) {
+ bcopy("HOST 1", p->RIOHosts[Host].Name, 7);
p->RIOHosts[Host].Name[5] += Host;
}
/*
- ** Check that default name assigned is unique.
- */
+ ** Check that default name assigned is unique.
+ */
Host1 = Host;
NameIsUnique = 0;
while (!NameIsUnique) {
NameIsUnique = 1;
- for ( Host2=0; Host2<p->RIONumHosts; Host2++ ) {
+ for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
if (Host2 == Host)
continue;
if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
- == 0) {
+ == 0) {
NameIsUnique = 0;
Host1++;
if (Host1 >= p->RIONumHosts)
@@ -417,15 +394,14 @@ struct rio_info * p;
}
}
/*
- ** Rename host if name already used.
- */
- if (Host1 != Host)
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
- bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+ ** Rename host if name already used.
+ */
+ if (Host1 != Host) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
+ bcopy("HOST 1", p->RIOHosts[Host].Name, 7);
p->RIOHosts[Host].Name[5] += Host1;
}
- rio_dprintk (RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
}
return 0;
}
@@ -434,9 +410,8 @@ struct rio_info * p;
** User process needs the config table - build it from first
** principles.
*/
-int
-RIOApel(p)
-struct rio_info * p;
+int RIOApel(p)
+struct rio_info *p;
{
int Host;
int link;
@@ -446,35 +421,34 @@ struct rio_info * p;
struct Host *HostP;
long oldspl;
- disable(oldspl); /* strange but true! */
-
- rio_dprintk (RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
+ disable(oldspl); /* strange but true! */
+
+ rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
- bzero((caddr_t)&p->RIOConnectTable[0],
- sizeof(struct Map) * TOTAL_MAP_ENTRIES );
+ bzero((caddr_t) & p->RIOConnectTable[0], sizeof(struct Map) * TOTAL_MAP_ENTRIES);
- for ( Host=0; Host<RIO_HOSTS; Host++ ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Processing host %d\n", Host);
+ for (Host = 0; Host < RIO_HOSTS; Host++) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
HostP = &p->RIOHosts[Host];
MapP = &p->RIOConnectTable[Next++];
MapP->HostUniqueNum = HostP->UniqueNum;
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING )
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
continue;
MapP->RtaUniqueNum = 0;
MapP->ID = 0;
MapP->Flags = SLOT_IN_USE;
MapP->SysPort = NO_PORT;
- for ( link=0; link<LINKS_PER_UNIT; link++ )
+ for (link = 0; link < LINKS_PER_UNIT; link++)
MapP->Topology[link] = HostP->Topology[link];
- bcopy(HostP->Name,MapP->Name,MAX_NAME_LEN);
- for ( Rup=0; Rup<MAX_RUP; Rup++ ) {
- if ( HostP->Mapping[Rup].Flags & (SLOT_IN_USE|SLOT_TENTATIVE) ) {
+ bcopy(HostP->Name, MapP->Name, MAX_NAME_LEN);
+ for (Rup = 0; Rup < MAX_RUP; Rup++) {
+ if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
p->RIOConnectTable[Next] = HostP->Mapping[Rup];
- if ( HostP->Mapping[Rup].Flags & SLOT_IN_USE)
+ if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
- if ( HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
+ if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
- if ( HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT )
+ if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
Next++;
}
@@ -489,8 +463,7 @@ struct rio_info * p;
** if the entry is suitably inactive, then we can gob on it and remove
** it from the table.
*/
-int
-RIODeleteRta(p, MapP)
+int RIODeleteRta(p, MapP)
struct rio_info *p;
struct Map *MapP;
{
@@ -502,110 +475,98 @@ struct Map *MapP;
int work_done = 0;
unsigned long lock_flags, sem_flags;
- rio_dprintk (RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n",
- MapP->HostUniqueNum, MapP->RtaUniqueNum);
+ rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
- for ( host=0; host < p->RIONumHosts; host++ ) {
+ for (host = 0; host < p->RIONumHosts; host++) {
HostP = &p->RIOHosts[host];
- rio_spin_lock_irqsave( &HostP->HostLock, lock_flags );
+ rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
continue;
}
- for ( entry=0; entry<MAX_RUP; entry++ ) {
- if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) {
+ for (entry = 0; entry < MAX_RUP; entry++) {
+ if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
HostMapP = &HostP->Mapping[entry];
- rio_dprintk (RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n",
- entry, HostP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
/*
- ** Check all four links of the unit are disconnected
- */
- for ( link=0; link< LINKS_PER_UNIT; link++ ) {
- if ( HostMapP->Topology[link].Unit != ROUTE_DISCONNECT ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
+ ** Check all four links of the unit are disconnected
+ */
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
p->RIOError.Error = UNIT_IS_IN_USE;
- rio_spin_unlock_irqrestore( &HostP->HostLock, lock_flags);
+ rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
return -EBUSY;
}
}
/*
- ** Slot has been allocated, BUT not booted/routed/
- ** connected/selected or anything else-ed
- */
+ ** Slot has been allocated, BUT not booted/routed/
+ ** connected/selected or anything else-ed
+ */
SysPort = HostMapP->SysPort;
- if ( SysPort != NO_PORT ) {
- for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) {
+ if (SysPort != NO_PORT) {
+ for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
PortP = p->RIOPortp[port];
- rio_dprintk (RIO_DEBUG_TABLE, "Unmap port\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
- rio_spin_lock_irqsave( &PortP->portSem, sem_flags );
+ rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
PortP->Mapped = 0;
- if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) {
+ if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
- rio_dprintk (RIO_DEBUG_TABLE, "Gob on port\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
PortP->TxBufferIn = PortP->TxBufferOut = 0;
/* What should I do
- wakeup( &PortP->TxBufferIn );
- wakeup( &PortP->TxBufferOut);
- */
+ wakeup( &PortP->TxBufferIn );
+ wakeup( &PortP->TxBufferOut);
+ */
PortP->InUse = NOT_INUSE;
/* What should I do
- wakeup( &PortP->InUse );
- signal(PortP->TtyP->t_pgrp,SIGKILL);
- ttyflush(PortP->TtyP,(FREAD|FWRITE));
- */
+ wakeup( &PortP->InUse );
+ signal(PortP->TtyP->t_pgrp,SIGKILL);
+ ttyflush(PortP->TtyP,(FREAD|FWRITE));
+ */
PortP->State |= RIO_CLOSING | RIO_DELETED;
}
/*
- ** For the second slot of a 16 port RTA, the
- ** driver needs to reset the changes made to
- ** the phb to port mappings in RIORouteRup.
- */
+ ** For the second slot of a 16 port RTA, the
+ ** driver needs to reset the changes made to
+ ** the phb to port mappings in RIORouteRup.
+ */
if (PortP->SecondBlock) {
ushort dest_unit = HostMapP->ID;
ushort dest_port = port - SysPort;
- WORD *TxPktP;
- PKT *Pkt;
+ WORD *TxPktP;
+ PKT *Pkt;
- for (TxPktP = PortP->TxStart;
- TxPktP <= PortP->TxEnd; TxPktP++) {
+ for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
/*
- ** *TxPktP is the pointer to the
- ** transmit packet on the host card.
- ** This needs to be translated into
- ** a 32 bit pointer so it can be
- ** accessed from the driver.
- */
- Pkt = (PKT *) RIO_PTR(HostP->Caddr,
- RWORD(*TxPktP));
- rio_dprintk (RIO_DEBUG_TABLE,
- "Tx packet (%x) destination: Old %x:%x New %x:%x\n",
- *TxPktP, Pkt->dest_unit,
- Pkt->dest_port, dest_unit, dest_port);
+ ** *TxPktP is the pointer to the
+ ** transmit packet on the host card.
+ ** This needs to be translated into
+ ** a 32 bit pointer so it can be
+ ** accessed from the driver.
+ */
+ Pkt = (PKT *) RIO_PTR(HostP->Caddr, RWORD(*TxPktP));
+ rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port);
WWORD(Pkt->dest_unit, dest_unit);
WWORD(Pkt->dest_port, dest_port);
}
- rio_dprintk (RIO_DEBUG_TABLE,
- "Port %d phb destination: Old %x:%x New %x:%x\n",
- port, PortP->PhbP->destination & 0xff,
- (PortP->PhbP->destination >> 8) & 0xff,
- dest_unit, dest_port);
- WWORD(PortP->PhbP->destination,
- dest_unit + (dest_port << 8));
+ rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, PortP->PhbP->destination & 0xff, (PortP->PhbP->destination >> 8) & 0xff, dest_unit, dest_port);
+ WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8));
}
rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
}
}
- rio_dprintk (RIO_DEBUG_TABLE, "Entry nulled.\n");
- bzero((char *)HostMapP,sizeof(struct Map));
+ rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
+ bzero((char *) HostMapP, sizeof(struct Map));
work_done++;
}
}
@@ -613,203 +574,178 @@ struct Map *MapP;
}
/* XXXXX lock me up */
- for ( entry=0; entry< TOTAL_MAP_ENTRIES; entry++ ) {
- if ( p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
- bzero((char *)&p->RIOSavedTable[entry],sizeof(struct Map));
+ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+ if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
+ bzero((char *) &p->RIOSavedTable[entry], sizeof(struct Map));
work_done++;
}
- if ( p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
- bzero((char *)&p->RIOConnectTable[entry],sizeof(struct Map));
+ if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
+ bzero((char *) &p->RIOConnectTable[entry], sizeof(struct Map));
work_done++;
}
}
- if ( work_done )
+ if (work_done)
return 0;
- rio_dprintk (RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
p->RIOError.Error = COULDNT_FIND_ENTRY;
return -ENXIO;
}
-int RIOAssignRta( struct rio_info *p, struct Map *MapP )
+int RIOAssignRta(struct rio_info *p, struct Map *MapP)
{
- int host;
- struct Map *HostMapP;
- char *sptr;
- int link;
-
-
- rio_dprintk (RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n",
- MapP->HostUniqueNum,MapP->RtaUniqueNum,
- MapP->ID, (int)MapP->SysPort);
-
- if ((MapP->ID != (ushort)-1) &&
- ((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP ))
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
- p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- if (MapP->RtaUniqueNum == 0)
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
- p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
- return -EINVAL;
- }
- if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA) )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n",(int)MapP->SysPort,PORTS_PER_RTA);
- p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS) )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Port %d not valid!\n",(int)MapP->SysPort);
- p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- /*
- ** Copy the name across to the map entry.
- */
- MapP->Name[MAX_NAME_LEN-1] = '\0';
- sptr = MapP->Name;
- while ( *sptr )
- {
- if ( *sptr<' ' || *sptr>'~' )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
- p->RIOError.Error = BAD_CHARACTER_IN_NAME;
- return -EINVAL;
- }
- sptr++;
- }
-
- for ( host=0; host < p->RIONumHosts; host++ )
- {
- if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum )
- {
- if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING )
- {
- p->RIOError.Error = HOST_NOT_RUNNING;
- return -ENXIO;
- }
-
- /*
- ** Now we have a host we need to allocate an ID
- ** if the entry does not already have one.
- */
- if (MapP->ID == (ushort)-1)
- {
- int nNewID;
-
- rio_dprintk (RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n",
- MapP->Name);
- /*
- ** The idea here is to allow RTA's to be assigned
- ** before they actually appear on the network.
- ** This allows the addition of RTA's without having
- ** to plug them in.
- ** What we do is:
- ** - Find a free ID and allocate it to the RTA.
- ** - If this map entry is the second half of a
- ** 16 port entry then find the other half and
- ** make sure the 2 cross reference each other.
- */
- if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0)
- {
- p->RIOError.Error = COULDNT_FIND_ENTRY;
- return -EBUSY;
- }
- MapP->ID = (ushort)nNewID + 1;
- rio_dprintk (RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
- HostMapP = &p->RIOHosts[host].Mapping[nNewID];
- HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
- HostMapP->HostUniqueNum = MapP->HostUniqueNum;
- HostMapP->ID = MapP->ID;
- for (link = 0; link < LINKS_PER_UNIT; link++)
- {
- HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
- HostMapP->Topology[link].Link = NO_LINK;
- }
- if (MapP->Flags & RTA16_SECOND_SLOT)
- {
- int unit;
-
- for (unit = 0; unit < MAX_RUP; unit++)
- if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum ==
- MapP->RtaUniqueNum)
- break;
- if (unit == MAX_RUP)
- {
- p->RIOError.Error = COULDNT_FIND_ENTRY;
- return -EBUSY;
- }
- HostMapP->Flags |= RTA16_SECOND_SLOT;
- HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
- p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
- rio_dprintk (RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n",
- MapP->ID,
- p->RIOHosts[host].Mapping[unit].ID);
+ int host;
+ struct Map *HostMapP;
+ char *sptr;
+ int link;
+
+
+ rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
+
+ if ((MapP->ID != (ushort) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+ p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ if (MapP->RtaUniqueNum == 0) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
+ p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
+ return -EINVAL;
+ }
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
+ p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
+ p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ /*
+ ** Copy the name across to the map entry.
+ */
+ MapP->Name[MAX_NAME_LEN - 1] = '\0';
+ sptr = MapP->Name;
+ while (*sptr) {
+ if (*sptr < ' ' || *sptr > '~') {
+ rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+ p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+ return -EINVAL;
}
- }
+ sptr++;
+ }
- HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+ for (host = 0; host < p->RIONumHosts; host++) {
+ if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
+ if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
+ p->RIOError.Error = HOST_NOT_RUNNING;
+ return -ENXIO;
+ }
- if ( HostMapP->Flags & SLOT_IN_USE )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
- p->RIOError.Error = ID_ALREADY_IN_USE;
- return -EBUSY;
- }
-
- /*
- ** Assign the sys ports and the name, and mark the slot as
- ** being in use.
- */
- HostMapP->SysPort = MapP->SysPort;
- if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
- CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
- HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
+ /*
+ ** Now we have a host we need to allocate an ID
+ ** if the entry does not already have one.
+ */
+ if (MapP->ID == (ushort) - 1) {
+ int nNewID;
+
+ rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
+ /*
+ ** The idea here is to allow RTA's to be assigned
+ ** before they actually appear on the network.
+ ** This allows the addition of RTA's without having
+ ** to plug them in.
+ ** What we do is:
+ ** - Find a free ID and allocate it to the RTA.
+ ** - If this map entry is the second half of a
+ ** 16 port entry then find the other half and
+ ** make sure the 2 cross reference each other.
+ */
+ if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
+ p->RIOError.Error = COULDNT_FIND_ENTRY;
+ return -EBUSY;
+ }
+ MapP->ID = (ushort) nNewID + 1;
+ rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
+ HostMapP = &p->RIOHosts[host].Mapping[nNewID];
+ HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
+ HostMapP->HostUniqueNum = MapP->HostUniqueNum;
+ HostMapP->ID = MapP->ID;
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
+ HostMapP->Topology[link].Link = NO_LINK;
+ }
+ if (MapP->Flags & RTA16_SECOND_SLOT) {
+ int unit;
+
+ for (unit = 0; unit < MAX_RUP; unit++)
+ if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
+ break;
+ if (unit == MAX_RUP) {
+ p->RIOError.Error = COULDNT_FIND_ENTRY;
+ return -EBUSY;
+ }
+ HostMapP->Flags |= RTA16_SECOND_SLOT;
+ HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
+ p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
+ rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
+ }
+ }
+
+ HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
+
+ if (HostMapP->Flags & SLOT_IN_USE) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
+ p->RIOError.Error = ID_ALREADY_IN_USE;
+ return -EBUSY;
+ }
+
+ /*
+ ** Assign the sys ports and the name, and mark the slot as
+ ** being in use.
+ */
+ HostMapP->SysPort = MapP->SysPort;
+ if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
+ CCOPY(MapP->Name, HostMapP->Name, MAX_NAME_LEN);
+ HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
#ifdef NEED_TO_FIX
- RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]);
+ RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
#endif
- if (MapP->Flags & RTA16_SECOND_SLOT)
- HostMapP->Flags |= RTA16_SECOND_SLOT;
-
- RIOReMapPorts( p, &p->RIOHosts[host], HostMapP );
- /*
- ** Adjust 2nd block of 8 phbs
- */
- if (MapP->Flags & RTA16_SECOND_SLOT)
- RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
-
- if ( HostMapP->SysPort != NO_PORT )
- {
- if ( HostMapP->SysPort < p->RIOFirstPortsBooted )
- p->RIOFirstPortsBooted = HostMapP->SysPort;
- if ( HostMapP->SysPort > p->RIOLastPortsBooted )
- p->RIOLastPortsBooted = HostMapP->SysPort;
- }
- if (MapP->Flags & RTA16_SECOND_SLOT)
- rio_dprintk (RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n",
- p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
- else
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
- return 0;
+ if (MapP->Flags & RTA16_SECOND_SLOT)
+ HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+ RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
+ /*
+ ** Adjust 2nd block of 8 phbs
+ */
+ if (MapP->Flags & RTA16_SECOND_SLOT)
+ RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
+
+ if (HostMapP->SysPort != NO_PORT) {
+ if (HostMapP->SysPort < p->RIOFirstPortsBooted)
+ p->RIOFirstPortsBooted = HostMapP->SysPort;
+ if (HostMapP->SysPort > p->RIOLastPortsBooted)
+ p->RIOLastPortsBooted = HostMapP->SysPort;
+ }
+ if (MapP->Flags & RTA16_SECOND_SLOT)
+ rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
+ else
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
+ return 0;
+ }
}
- }
- p->RIOError.Error = UNKNOWN_HOST_NUMBER;
- rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
- return -ENXIO;
+ p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+ rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+ return -ENXIO;
}
-int
-RIOReMapPorts(p, HostP, HostMapP)
-struct rio_info * p;
+int RIOReMapPorts(p, HostP, HostMapP)
+struct rio_info *p;
struct Host *HostP;
-struct Map *HostMapP;
+struct Map *HostMapP;
{
register struct Port *PortP;
uint SubEnt;
@@ -818,136 +754,120 @@ struct Map *HostMapP;
ushort RtaType;
unsigned long flags;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckHostMapP( HostMapP );
-#endif
-
- rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int)HostMapP->SysPort, HostMapP->ID);
+ rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
/*
- ** We need to tell the UnixRups which sysport the rup corresponds to
- */
- HostP->UnixRups[HostMapP->ID-1].BaseSysPort = HostMapP->SysPort;
+ ** We need to tell the UnixRups which sysport the rup corresponds to
+ */
+ HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
- if ( HostMapP->SysPort == NO_PORT )
- return(0);
+ if (HostMapP->SysPort == NO_PORT)
+ return (0);
RtaType = GetUnitType(HostMapP->RtaUniqueNum);
- rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n",
- (int)HostMapP->SysPort, (int)HostMapP->SysPort+PORTS_PER_RTA-1);
+ rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
/*
- ** now map each of its eight ports
- */
- for ( SubEnt=0; SubEnt<PORTS_PER_RTA; SubEnt++) {
- rio_dprintk (RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n",
- SubEnt, (int)HostMapP->SysPort);
- SysPort = HostMapP->SysPort+SubEnt; /* portnumber within system */
- /* portnumber on host */
-
- HostPort = (HostMapP->ID-1)*PORTS_PER_RTA+SubEnt;
-
- rio_dprintk (RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
+ ** now map each of its eight ports
+ */
+ for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
+ rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
+ SysPort = HostMapP->SysPort + SubEnt; /* portnumber within system */
+ /* portnumber on host */
+
+ HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
+
+ rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
PortP = p->RIOPortp[SysPort];
-#if 0
- PortP->TtyP = &p->channel[SysPort];
-#endif
- rio_dprintk (RIO_DEBUG_TABLE, "Map port\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
/*
- ** Point at all the real neat data structures
- */
+ ** Point at all the real neat data structures
+ */
rio_spin_lock_irqsave(&PortP->portSem, flags);
PortP->HostP = HostP;
PortP->Caddr = HostP->Caddr;
/*
- ** The PhbP cannot be filled in yet
- ** unless the host has been booted
- */
+ ** The PhbP cannot be filled in yet
+ ** unless the host has been booted
+ */
if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
- PortP->TxAdd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_add));
- PortP->TxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_start));
- PortP->TxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_end));
- PortP->RxRemove=(WORD *)RIO_PTR(HostP->Caddr,
- RWORD(PhbP->rx_remove));
- PortP->RxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_start));
- PortP->RxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_end));
- }
- else
+ PortP->TxAdd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_add));
+ PortP->TxStart = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_start));
+ PortP->TxEnd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_end));
+ PortP->RxRemove = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_remove));
+ PortP->RxStart = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_start));
+ PortP->RxEnd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_end));
+ } else
PortP->PhbP = NULL;
/*
- ** port related flags
- */
- PortP->HostPort = HostPort;
+ ** port related flags
+ */
+ PortP->HostPort = HostPort;
/*
- ** For each part of a 16 port RTA, RupNum is ID - 1.
- */
+ ** For each part of a 16 port RTA, RupNum is ID - 1.
+ */
PortP->RupNum = HostMapP->ID - 1;
if (HostMapP->Flags & RTA16_SECOND_SLOT) {
- PortP->ID2 = HostMapP->ID2 - 1;
- PortP->SecondBlock = TRUE;
- }
- else {
- PortP->ID2 = 0;
- PortP->SecondBlock = FALSE;
+ PortP->ID2 = HostMapP->ID2 - 1;
+ PortP->SecondBlock = TRUE;
+ } else {
+ PortP->ID2 = 0;
+ PortP->SecondBlock = FALSE;
}
- PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
+ PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
/*
- ** If the port was already mapped then thats all we need to do.
- */
+ ** If the port was already mapped then thats all we need to do.
+ */
if (PortP->Mapped) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
continue;
- }
- else HostMapP->Flags &= ~RTA_NEWBOOT;
+ } else
+ HostMapP->Flags &= ~RTA_NEWBOOT;
- PortP->State = 0;
- PortP->Config = 0;
+ PortP->State = 0;
+ PortP->Config = 0;
/*
- ** Check out the module type - if it is special (read only etc.)
- ** then we need to set flags in the PortP->Config.
- ** Note: For 16 port RTA, all ports are of the same type.
- */
+ ** Check out the module type - if it is special (read only etc.)
+ ** then we need to set flags in the PortP->Config.
+ ** Note: For 16 port RTA, all ports are of the same type.
+ */
if (RtaType == TYPE_RTA16) {
- PortP->Config |= p->RIOModuleTypes[HostP->UnixRups
- [HostMapP->ID-1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
+ PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
} else {
- if ( SubEnt < PORTS_PER_MODULE )
- PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups
- [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+ if (SubEnt < PORTS_PER_MODULE)
+ PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
else
- PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups
- [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+ PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
}
/*
- ** more port related flags
- */
- PortP->PortState = 0;
- PortP->ModemLines = 0;
- PortP->ModemState = 0;
- PortP->CookMode = COOK_WELL;
- PortP->ParamSem = 0;
- PortP->FlushCmdBodge= 0;
- PortP->WflushFlag = 0;
- PortP->MagicFlags = 0;
- PortP->Lock = 0;
- PortP->Store = 0;
- PortP->FirstOpen = 1;
+ ** more port related flags
+ */
+ PortP->PortState = 0;
+ PortP->ModemLines = 0;
+ PortP->ModemState = 0;
+ PortP->CookMode = COOK_WELL;
+ PortP->ParamSem = 0;
+ PortP->FlushCmdBodge = 0;
+ PortP->WflushFlag = 0;
+ PortP->MagicFlags = 0;
+ PortP->Lock = 0;
+ PortP->Store = 0;
+ PortP->FirstOpen = 1;
/*
- ** Buffers 'n things
- */
- PortP->RxDataStart = 0;
- PortP->Cor2Copy = 0;
- PortP->Name = &HostMapP->Name[0];
+ ** Buffers 'n things
+ */
+ PortP->RxDataStart = 0;
+ PortP->Cor2Copy = 0;
+ PortP->Name = &HostMapP->Name[0];
#ifdef STATS
- bzero( (caddr_t)&PortP->Stat, sizeof(struct RIOStats) );
+ bzero((caddr_t) & PortP->Stat, sizeof(struct RIOStats));
#endif
PortP->statsGather = 0;
PortP->txchars = 0;
@@ -955,90 +875,87 @@ struct Map *HostMapP;
PortP->opens = 0;
PortP->closes = 0;
PortP->ioctls = 0;
- if ( PortP->TxRingBuffer )
- bzero( PortP->TxRingBuffer, p->RIOBufferSize );
- else if ( p->RIOBufferSize ) {
+ if (PortP->TxRingBuffer)
+ bzero(PortP->TxRingBuffer, p->RIOBufferSize);
+ else if (p->RIOBufferSize) {
PortP->TxRingBuffer = sysbrk(p->RIOBufferSize);
- bzero( PortP->TxRingBuffer, p->RIOBufferSize );
+ bzero(PortP->TxRingBuffer, p->RIOBufferSize);
}
- PortP->TxBufferOut = 0;
- PortP->TxBufferIn = 0;
- PortP->Debug = 0;
+ PortP->TxBufferOut = 0;
+ PortP->TxBufferIn = 0;
+ PortP->Debug = 0;
/*
- ** LastRxTgl stores the state of the rx toggle bit for this
- ** port, to be compared with the state of the next pkt received.
- ** If the same, we have received the same rx pkt from the RTA
- ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
- */
- PortP->LastRxTgl = ~(uchar)PHB_RX_TGL;
+ ** LastRxTgl stores the state of the rx toggle bit for this
+ ** port, to be compared with the state of the next pkt received.
+ ** If the same, we have received the same rx pkt from the RTA
+ ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
+ */
+ PortP->LastRxTgl = ~(uchar) PHB_RX_TGL;
/*
- ** and mark the port as usable
- */
+ ** and mark the port as usable
+ */
PortP->Mapped = 1;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
}
- if ( HostMapP->SysPort < p->RIOFirstPortsMapped )
+ if (HostMapP->SysPort < p->RIOFirstPortsMapped)
p->RIOFirstPortsMapped = HostMapP->SysPort;
- if ( HostMapP->SysPort > p->RIOLastPortsMapped )
+ if (HostMapP->SysPort > p->RIOLastPortsMapped)
p->RIOLastPortsMapped = HostMapP->SysPort;
return 0;
}
-int
-RIOChangeName(p, MapP)
+int RIOChangeName(p, MapP)
struct rio_info *p;
-struct Map* MapP;
+struct Map *MapP;
{
int host;
struct Map *HostMapP;
char *sptr;
- rio_dprintk (RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n",
- MapP->HostUniqueNum,MapP->RtaUniqueNum,
- MapP->ID, (int)MapP->SysPort);
+ rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
- if ( MapP->ID > MAX_RUP ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+ if (MapP->ID > MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
return -EINVAL;
}
- MapP->Name[MAX_NAME_LEN-1] = '\0';
+ MapP->Name[MAX_NAME_LEN - 1] = '\0';
sptr = MapP->Name;
- while ( *sptr ) {
- if ( *sptr<' ' || *sptr>'~' ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+ while (*sptr) {
+ if (*sptr < ' ' || *sptr > '~') {
+ rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
p->RIOError.Error = BAD_CHARACTER_IN_NAME;
return -EINVAL;
}
sptr++;
}
- for ( host=0; host < p->RIONumHosts; host++ ) {
- if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) {
- if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) {
+ for (host = 0; host < p->RIONumHosts; host++) {
+ if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
+ if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
p->RIOError.Error = HOST_NOT_RUNNING;
return -ENXIO;
}
- if ( MapP->ID==0 ) {
- CCOPY( MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN );
+ if (MapP->ID == 0) {
+ CCOPY(MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN);
return 0;
}
- HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+ HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
- if ( HostMapP->RtaUniqueNum != MapP->RtaUniqueNum ) {
+ if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
p->RIOError.Error = RTA_NUMBER_WRONG;
return -ENXIO;
}
- CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
+ CCOPY(MapP->Name, HostMapP->Name, MAX_NAME_LEN);
return 0;
}
}
p->RIOError.Error = UNKNOWN_HOST_NUMBER;
- rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+ rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
return -ENXIO;
}
diff --git a/drivers/char/rio/riotime.h b/drivers/char/rio/riotime.h
deleted file mode 100644
index 66d52bc0549b..000000000000
--- a/drivers/char/rio/riotime.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* T I M E
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _riotime_h
-#define _riotime_h 1
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1" ;
-#endif
-#endif
-
-#define TWO_POWER_FIFTEEN (ushort)32768
-#define RioTime() riotime
-#define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN
-#define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2)
-
-/**************************************
- * Convert a RIO tick (1/10th second)
- * into transputer low priority ticks
- *************************************/
-#define RioTimeToLow(time) (time*(100000 / 64))
-#define RioLowToTime(time) ((time*64)/100000)
-
-#define RIOTENTHSECOND (ushort)1
-#define RIOSECOND (ushort)(RIOTENTHSECOND * 10)
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index 78a321afdf4f..6379816ed173 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -89,22 +89,13 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
#include "list.h"
#include "sam.h"
-#if 0
-static void ttyseth_pv(struct Port *, struct ttystatics *,
- struct termios *sg, int);
-#endif
-
static void RIOClearUp(struct Port *PortP);
-int RIOShortCommand(struct rio_info *p, struct Port *PortP,
- int command, int len, int arg);
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-#if 0
-static int RIOCookMode(struct ttystatics *);
-#endif
-extern int conv_vb[]; /* now defined in ttymgr.c */
-extern int conv_bv[]; /* now defined in ttymgr.c */
-
+extern int conv_vb[]; /* now defined in ttymgr.c */
+extern int conv_bv[]; /* now defined in ttymgr.c */
+
/*
** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support
**
@@ -117,27 +108,25 @@ extern int conv_bv[]; /* now defined in ttymgr.c */
#endif
#ifdef NEED_THIS2
-static struct old_sgttyb
-default_sg =
-{
- B19200, B19200, /* input and output speed */
- 'H' - '@', /* erase char */
- -1, /* 2nd erase char */
- 'U' - '@', /* kill char */
- ECHO | CRMOD, /* mode */
- 'C' - '@', /* interrupt character */
- '\\' - '@', /* quit char */
- 'Q' - '@', /* start char */
- 'S' - '@', /* stop char */
- 'D' - '@', /* EOF */
- -1, /* brk */
- (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */
- 'Z' - '@', /* process stop */
- 'Y' - '@', /* delayed stop */
- 'R' - '@', /* reprint line */
- 'O' - '@', /* flush output */
- 'W' - '@', /* word erase */
- 'V' - '@' /* literal next char */
+static struct old_sgttyb default_sg = {
+ B19200, B19200, /* input and output speed */
+ 'H' - '@', /* erase char */
+ -1, /* 2nd erase char */
+ 'U' - '@', /* kill char */
+ ECHO | CRMOD, /* mode */
+ 'C' - '@', /* interrupt character */
+ '\\' - '@', /* quit char */
+ 'Q' - '@', /* start char */
+ 'S' - '@', /* stop char */
+ 'D' - '@', /* EOF */
+ -1, /* brk */
+ (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */
+ 'Z' - '@', /* process stop */
+ 'Y' - '@', /* delayed stop */
+ 'R' - '@', /* reprint line */
+ 'O' - '@', /* flush output */
+ 'W' - '@', /* word erase */
+ 'V' - '@' /* literal next char */
};
#endif
@@ -145,62 +134,59 @@ default_sg =
extern struct rio_info *p;
-int
-riotopen(struct tty_struct * tty, struct file * filp)
+int riotopen(struct tty_struct *tty, struct file *filp)
{
register uint SysPort;
int Modem;
int repeat_this = 250;
- struct Port *PortP; /* pointer to the port structure */
+ struct Port *PortP; /* pointer to the port structure */
unsigned long flags;
int retval = 0;
- func_enter ();
+ func_enter();
/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
is going to oops.
- */
+ */
tty->driver_data = NULL;
-
+
SysPort = rio_minor(tty);
- Modem = rio_ismodem(tty);
+ Modem = rio_ismodem(tty);
- if ( p->RIOFailed ) {
- rio_dprintk (RIO_DEBUG_TTY, "System initialisation failed\n");
+ if (p->RIOFailed) {
+ rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
pseterr(ENXIO);
- func_exit ();
+ func_exit();
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n",
- SysPort, Modem ? "Modem" : "tty",
- p->RIOPortp[SysPort]->Mapped);
+ rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n", SysPort, Modem ? "Modem" : "tty", p->RIOPortp[SysPort]->Mapped);
/*
- ** Validate that we have received a legitimate request.
- ** Currently, just check that we are opening a port on
- ** a host card that actually exists, and that the port
- ** has been mapped onto a host.
- */
+ ** Validate that we have received a legitimate request.
+ ** Currently, just check that we are opening a port on
+ ** a host card that actually exists, and that the port
+ ** has been mapped onto a host.
+ */
if (SysPort >= RIO_PORTS) { /* out of range ? */
- rio_dprintk (RIO_DEBUG_TTY, "Illegal port number %d\n",SysPort);
+ rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
pseterr(ENXIO);
func_exit();
return -ENXIO;
}
/*
- ** Grab pointer to the port stucture
- */
+ ** Grab pointer to the port stucture
+ */
PortP = p->RIOPortp[SysPort]; /* Get control struc */
- rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP);
- if ( !PortP->Mapped ) { /* we aren't mapped yet! */
+ rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
+ if (!PortP->Mapped) { /* we aren't mapped yet! */
/*
- ** The system doesn't know which RTA this port
- ** corresponds to.
- */
- rio_dprintk (RIO_DEBUG_TTY, "port not mapped into system\n");
- func_exit ();
+ ** The system doesn't know which RTA this port
+ ** corresponds to.
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
+ func_exit();
pseterr(ENXIO);
return -ENXIO;
}
@@ -210,132 +196,93 @@ riotopen(struct tty_struct * tty, struct file * filp)
PortP->gs.tty = tty;
PortP->gs.count++;
- rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n",
- PortP->gs.xmit_cnt);
+ rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);
- retval = gs_init_port (&PortP->gs);
+ retval = gs_init_port(&PortP->gs);
if (retval) {
PortP->gs.count--;
return -ENXIO;
}
/*
- ** If the host hasn't been booted yet, then
- ** fail
- */
- if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
- rio_dprintk (RIO_DEBUG_TTY, "Host not running\n");
+ ** If the host hasn't been booted yet, then
+ ** fail
+ */
+ if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
pseterr(ENXIO);
- func_exit ();
+ func_exit();
return -ENXIO;
}
/*
- ** If the RTA has not booted yet and the user has choosen to block
- ** until the RTA is present then we must spin here waiting for
- ** the RTA to boot.
- */
-#if 0
- if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
- if (PortP->WaitUntilBooted) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot\n");
- do {
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- func_exit ();
- return -EINTR;
- }
- if (repeat_this -- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
- pseterr(EINTR);
- func_exit ();
- return -EIO;
- }
- } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
- rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
- } else {
- rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n");
- pseterr(ENXIO);
- func_exit ();
- return 0;
- }
- }
-#else
+ ** If the RTA has not booted yet and the user has choosen to block
+ ** until the RTA is present then we must spin here waiting for
+ ** the RTA to boot.
+ */
/* I find the above code a bit hairy. I find the below code
- easier to read and shorter. Now, if it works too that would
+ easier to read and shorter. Now, if it works too that would
be great... -- REW
- */
- rio_dprintk (RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
- if (!PortP->WaitUntilBooted) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n");
- func_exit ();
- return -ENXIO;
- }
-
- /* Under Linux you'd normally use a wait instead of this
- busy-waiting. I'll stick with the old implementation for
- now. --REW
- */
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
- func_exit ();
- return -EINTR;
- }
- if (repeat_this -- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
- func_exit ();
- return -EIO;
- }
+ if (!PortP->WaitUntilBooted) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
+ func_exit();
+ return -ENXIO;
+ }
+
+ /* Under Linux you'd normally use a wait instead of this
+ busy-waiting. I'll stick with the old implementation for
+ now. --REW
+ */
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
+ func_exit();
+ return -EINTR;
+ }
+ if (repeat_this-- <= 0) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
+ func_exit();
+ return -EIO;
+ }
}
- rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
-#endif
-#if 0
- tp = PortP->TtyP; /* get tty struct */
-#endif
+ rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
rio_spin_lock_irqsave(&PortP->portSem, flags);
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
goto bombout;
}
-#if 0
- retval = gs_init_port(&PortP->gs);
- if (retval){
- func_exit ();
- return retval;
- }
-#endif
/*
- ** If the port is in the final throws of being closed,
- ** we should wait here (politely), waiting
- ** for it to finish, so that it doesn't close us!
- */
- while ( (PortP->State & RIO_CLOSING) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
- if (repeat_this -- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
+ ** If the port is in the final throws of being closed,
+ ** we should wait here (politely), waiting
+ ** for it to finish, so that it doesn't close us!
+ */
+ while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
+ if (repeat_this-- <= 0) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
retval = -EINTR;
goto bombout;
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_spin_lock_irqsave(&PortP->portSem, flags);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
retval = -EINTR;
goto bombout;
}
- rio_spin_lock_irqsave(&PortP->portSem, flags);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( !PortP->Mapped ) {
- rio_dprintk (RIO_DEBUG_TTY, "Port unmapped while closing!\n");
+ if (!PortP->Mapped) {
+ rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
retval = -ENXIO;
- func_exit ();
+ func_exit();
return retval;
}
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
goto bombout;
}
@@ -346,16 +293,16 @@ riotopen(struct tty_struct * tty, struct file * filp)
*/
/* Uh? Suppose I turn these on and then another process opens
the port again? The flags get cleared! Not good. -- REW */
- if ( !(PortP->State & (RIO_LOPEN | RIO_MOPEN)) ) {
- PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+ if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+ PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
}
if (!(PortP->firstOpen)) { /* First time ? */
- rio_dprintk (RIO_DEBUG_TTY, "First open for this port\n");
-
+ rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");
+
PortP->firstOpen++;
- PortP->CookMode = 0; /* XXX RIOCookMode(tp); */
+ PortP->CookMode = 0; /* XXX RIOCookMode(tp); */
PortP->InUse = NOT_INUSE;
/* Tentative fix for bug PR27. Didn't work. */
@@ -363,26 +310,21 @@ riotopen(struct tty_struct * tty, struct file * filp)
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
#ifdef NEED_THIS
- ttyseth(PortP, tp, (struct old_sgttyb *)&default_sg);
+ ttyseth(PortP, tp, (struct old_sgttyb *) &default_sg);
#endif
/* Someone explain to me why this delay/config is
- here. If I read the docs correctly the "open"
- command piggybacks the parameters immediately.
+ here. If I read the docs correctly the "open"
+ command piggybacks the parameters immediately.
-- REW */
- RIOParam(PortP,OPEN,Modem,OK_TO_SLEEP); /* Open the port */
-#if 0
- /* This delay of 1 second was annoying. I removed it. -- REW */
- RIODelay(PortP, HUNDRED_MS*10);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); /* Config the port */
-#endif
+ RIOParam(PortP, OPEN, Modem, OK_TO_SLEEP); /* Open the port */
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** wait for the port to be not closed.
- */
- while ( !(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n",PortP->PortState);
+ ** wait for the port to be not closed.
+ */
+ while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
/*
** 15.10.1998 ARG - ESIL 0759
** (Part) fix for port being trashed when opened whilst RTA "disconnected"
@@ -399,115 +341,106 @@ riotopen(struct tty_struct * tty, struct file * filp)
*/
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
- func_exit ();
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ func_exit();
return -EINTR;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( p->RIOHalted ) {
- retval = -EIO;
-bombout:
- /* RIOClearUp( PortP ); */
+ if (p->RIOHalted) {
+ retval = -EIO;
+ bombout:
+ /* RIOClearUp( PortP ); */
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return retval;
}
- rio_dprintk (RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
+ rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
}
-
-#ifdef MODEM_SUPPORT
+#ifdef MODEM_SUPPORT
if (Modem) {
- rio_dprintk (RIO_DEBUG_TTY, "Modem - test for carrier\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
/*
- ** ACTION
- ** insert test for carrier here. -- ???
- ** I already see that test here. What's the deal? -- REW
- */
- if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))
- {
- rio_dprintk (RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
+ ** ACTION
+ ** insert test for carrier here. -- ???
+ ** I already see that test here. What's the deal? -- REW
+ */
+ if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
/*
- tp->tm.c_state |= CARR_ON;
- wakeup((caddr_t) &tp->tm.c_canq);
- */
+ tp->tm.c_state |= CARR_ON;
+ wakeup((caddr_t) &tp->tm.c_canq);
+ */
PortP->State |= RIO_CARR_ON;
- wake_up_interruptible (&PortP->gs.open_wait);
- }
- else /* no carrier - wait for DCD */
- {
- /*
- while (!(PortP->gs.tty->termios->c_state & CARR_ON) &&
- !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
- */
- while (!(PortP->State & RIO_CARR_ON) &&
- !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) {
-
- rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n",SysPort);
+ wake_up_interruptible(&PortP->gs.open_wait);
+ } else { /* no carrier - wait for DCD */
+
+ /*
+ while (!(PortP->gs.tty->termios->c_state & CARR_ON) &&
+ !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
+ */
+ while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
+
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
/*
- PortP->gs.tty->termios->c_state |= WOPEN;
- */
+ PortP->gs.tty->termios->c_state |= WOPEN;
+ */
PortP->State |= RIO_WOPEN;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- if (RIODelay (PortP, HUNDRED_MS) == RIO_FAIL)
-#if 0
- if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH))
-#endif
- {
- /*
- ** ACTION: verify that this is a good thing
- ** to do here. -- ???
- ** I think it's OK. -- REW
- */
- rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n",
- SysPort);
- RIOPreemptiveCmd( p, PortP, FCLOSE );
- /*
- tp->tm.c_state &= ~WOPEN;
- */
- PortP->State &= ~RIO_WOPEN;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- func_exit ();
- return -EINTR;
- }
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL)
+ {
+ /*
+ ** ACTION: verify that this is a good thing
+ ** to do here. -- ???
+ ** I think it's OK. -- REW
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ /*
+ tp->tm.c_state &= ~WOPEN;
+ */
+ PortP->State &= ~RIO_WOPEN;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
+ return -EINTR;
+ }
}
PortP->State &= ~RIO_WOPEN;
}
- if ( p->RIOHalted )
+ if (p->RIOHalted)
goto bombout;
- rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
PortP->State |= RIO_MOPEN;
- }
- else
+ } else
#endif
{
/*
- ** ACTION
- ** Direct line open - force carrier (will probably mean
- ** that sleeping Modem line fubar)
- */
+ ** ACTION
+ ** Direct line open - force carrier (will probably mean
+ ** that sleeping Modem line fubar)
+ */
PortP->State |= RIO_LOPEN;
}
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
goto bombout;
}
- rio_dprintk (RIO_DEBUG_TTY, "high level open done\n");
+ rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");
#ifdef STATS
PortP->Stat.OpenCnt++;
#endif
/*
- ** Count opens for port statistics reporting
- */
+ ** Count opens for port statistics reporting
+ */
if (PortP->statsGather)
PortP->opens++;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n");
- func_exit ();
+ rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
+ func_exit();
return 0;
}
@@ -516,85 +449,73 @@ bombout:
** The operating system thinks that this is last close for the device.
** As there are two interfaces to the port (Modem and tty), we need to
** check that both are closed before we close the device.
-*/
-int
-riotclose(void *ptr)
+*/
+int riotclose(void *ptr)
{
-#if 0
- register uint SysPort = dev;
- struct ttystatics *tp; /* pointer to our ttystruct */
-#endif
struct Port *PortP = ptr; /* pointer to the port structure */
int deleted = 0;
- int try = -1; /* Disable the timeouts by setting them to -1 */
- int repeat_this = -1; /* Congrats to those having 15 years of
- uptime! (You get to break the driver.) */
+ int try = -1; /* Disable the timeouts by setting them to -1 */
+ int repeat_this = -1; /* Congrats to those having 15 years of
+ uptime! (You get to break the driver.) */
unsigned long end_time;
- struct tty_struct * tty;
+ struct tty_struct *tty;
unsigned long flags;
int Modem;
int rv = 0;
-
- rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
+
+ rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);
/* PortP = p->RIOPortp[SysPort]; */
- rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP);
- /* tp = PortP->TtyP;*/ /* Get tty */
+ rio_dprintk(RIO_DEBUG_TTY, "Port is at address 0x%x\n", (int) PortP);
+ /* tp = PortP->TtyP; *//* Get tty */
tty = PortP->gs.tty;
- rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty);
+ rio_dprintk(RIO_DEBUG_TTY, "TTY is at address 0x%x\n", (int) tty);
- if (PortP->gs.closing_wait)
+ if (PortP->gs.closing_wait)
end_time = jiffies + PortP->gs.closing_wait;
- else
+ else
end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
Modem = rio_ismodem(tty);
-#if 0
- /* What F.CKING cache? Even then, a higly idle multiprocessor,
- system with large caches this won't work . Better find out when
- this doesn't work asap, and fix the cause. -- REW */
-
- RIODelay(PortP, HUNDRED_MS*10); /* To flush the cache */
-#endif
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** Setting this flag will make any process trying to open
- ** this port block until we are complete closing it.
- */
+ ** Setting this flag will make any process trying to open
+ ** this port block until we are complete closing it.
+ */
PortP->State |= RIO_CLOSING;
- if ( (PortP->State & RIO_DELETED) ) {
- rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n");
+ if ((PortP->State & RIO_DELETED)) {
+ rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
deleted = 1;
}
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
rv = -EIO;
goto close_end;
}
- rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
/*
- ** clear the open bits for this device
- */
+ ** clear the open bits for this device
+ */
PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN);
PortP->State &= ~RIO_CARR_ON;
PortP->ModemState &= ~MSVR1_CD;
/*
- ** If the device was open as both a Modem and a tty line
- ** then we need to wimp out here, as the port has not really
- ** been finally closed (gee, whizz!) The test here uses the
- ** bit for the OTHER mode of operation, to see if THAT is
- ** still active!
- */
- if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+ ** If the device was open as both a Modem and a tty line
+ ** then we need to wimp out here, as the port has not really
+ ** been finally closed (gee, whizz!) The test here uses the
+ ** bit for the OTHER mode of operation, to see if THAT is
+ ** still active!
+ */
+ if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
/*
- ** The port is still open for the other task -
- ** return, pretending that we are still active.
- */
- rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum);
+ ** The port is still open for the other task -
+ ** return, pretending that we are still active.
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
PortP->State &= ~RIO_CLOSING;
if (PortP->firstOpen)
PortP->firstOpen--;
@@ -602,48 +523,47 @@ riotclose(void *ptr)
return -EIO;
}
- rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");
PortP->State &= ~RIO_DYNOROD;
/*
- ** This is where we wait for the port
- ** to drain down before closing. Bye-bye....
- ** (We never meant to do this)
- */
- rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n");
+ ** This is where we wait for the port
+ ** to drain down before closing. Bye-bye....
+ ** (We never meant to do this)
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");
if (!deleted)
- while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted &&
- (PortP->TxBufferIn != PortP->TxBufferOut) ) {
- cprintf("Need to flush the ttyport\n");
- if (repeat_this -- <= 0) {
- rv = -EINTR;
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE);
- goto close_end;
- }
- rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- rv = -EINTR;
+ while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
+ cprintf("Need to flush the ttyport\n");
+ if (repeat_this-- <= 0) {
+ rv = -EINTR;
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ goto close_end;
+ }
+ rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+ rv = -EINTR;
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ goto close_end;
+ }
rio_spin_lock_irqsave(&PortP->portSem, flags);
- goto close_end;
}
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- }
PortP->TxBufferIn = PortP->TxBufferOut = 0;
repeat_this = 0xff;
PortP->InUse = 0;
- if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+ if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
/*
- ** The port has been re-opened for the other task -
- ** return, pretending that we are still active.
- */
- rio_dprintk (RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
+ ** The port has been re-opened for the other task -
+ ** return, pretending that we are still active.
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
PortP->State &= ~RIO_CLOSING;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (PortP->firstOpen)
@@ -651,8 +571,8 @@ riotclose(void *ptr)
return -EIO;
}
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
goto close_end;
}
@@ -665,115 +585,73 @@ riotclose(void *ptr)
}
if (!deleted)
- while (try && (PortP->PortState & PORT_ISOPEN)) {
- try--;
- if (time_after (jiffies, end_time)) {
- rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" );
- RIOPreemptiveCmd(p, PortP,FCLOSE);
- break;
- }
- rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n",
- PortP->PortState & PORT_ISOPEN);
+ while (try && (PortP->PortState & PORT_ISOPEN)) {
+ try--;
+ if (time_after(jiffies, end_time)) {
+ rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ break;
+ }
+ rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- goto close_end;
- }
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- RIOPreemptiveCmd(p, PortP,FCLOSE);
- break;
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
+ goto close_end;
+ }
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ break;
+ }
}
- }
rio_spin_lock_irqsave(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try );
-
+ rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
+
/* RIOPreemptiveCmd(p, PortP, FCLOSE); */
/*
** 15.10.1998 ARG - ESIL 0761 part fix
** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
*/
- PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+ PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
#ifdef STATS
PortP->Stat.CloseCnt++;
#endif
/*
- ** Count opens for port statistics reporting
- */
+ ** Count opens for port statistics reporting
+ */
if (PortP->statsGather)
PortP->closes++;
-close_end:
+ close_end:
/* XXX: Why would a "DELETED" flag be reset here? I'd have
thought that a "deleted" flag means that the port was
permanently gone, but here we can make it reappear by it
being in close during the "deletion".
- */
- PortP->State &= ~(RIO_CLOSING|RIO_DELETED);
+ */
+ PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
if (PortP->firstOpen)
PortP->firstOpen--;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Return from close\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
return rv;
}
-/*
-** decide if we need to use the line discipline.
-** This routine can return one of three values:
-** COOK_RAW if no processing has to be done by the line discipline or the card
-** COOK_WELL if the line discipline must be used to do the processing
-** COOK_MEDIUM if the card can do all the processing necessary.
-*/
-#if 0
-static int
-RIOCookMode(struct ttystatics *tp)
-{
- /*
- ** We can't handle tm.c_mstate != 0 on SCO
- ** We can't handle mapping
- ** We can't handle non-ttwrite line disc.
- ** We can't handle lflag XCASE
- ** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3)
- */
-
-#ifdef CHECK
- CheckTtyP( tp );
-#endif
- if (!(tp->tm.c_oflag & OPOST)) /* No post processing */
- return COOK_RAW; /* Raw mode o/p */
-
- if ( tp->tm.c_lflag & XCASE )
- return COOK_WELL; /* Use line disc */
- if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) )
- return COOK_WELL; /* Use line disc for strange modes */
-
- if ( tp->tm.c_oflag == OPOST ) /* If only OPOST is set, do RAW */
- return COOK_RAW;
-
- /*
- ** So, we need to output process!
- */
- return COOK_MEDIUM;
-}
-#endif
-
-static void
-RIOClearUp(PortP)
+static void RIOClearUp(PortP)
struct Port *PortP;
{
- rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n");
- PortP->Config = 0; /* Direct semaphore */
+ rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
+ PortP->Config = 0; /* Direct semaphore */
PortP->PortState = 0;
PortP->firstOpen = 0;
PortP->FlushCmdBodge = 0;
PortP->ModemState = PortP->CookMode = 0;
PortP->Mapped = 0;
PortP->WflushFlag = 0;
- PortP->MagicFlags = 0;
+ PortP->MagicFlags = 0;
PortP->RxDataStart = 0;
PortP->TxBufferIn = 0;
PortP->TxBufferOut = 0;
@@ -788,33 +666,26 @@ struct Port *PortP;
** Other values of len aren't allowed, and will cause
** a panic.
*/
-int RIOShortCommand(struct rio_info *p, struct Port *PortP,
- int command, int len, int arg)
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
{
PKT *PacketP;
- int retries = 20; /* at 10 per second -> 2 seconds */
+ int retries = 20; /* at 10 per second -> 2 seconds */
unsigned long flags;
- rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n");
-#ifdef CHECK
- CheckPortP( PortP );
- if ( len < 1 || len > 2 )
- cprintf(("STUPID LENGTH %d\n",len));
-#endif
+ rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
return RIO_FAIL;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** If the port is in use for pre-emptive command, then wait for it to
- ** be free again.
- */
- while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for not in use (%d)\n",
- retries);
+ ** If the port is in use for pre-emptive command, then wait for it to
+ ** be free again.
+ */
+ while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (retries-- <= 0) {
return RIO_FAIL;
@@ -824,47 +695,47 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP,
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return RIO_FAIL;
}
- while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
+ while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (retries-- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "out of tries. Failing\n");
+ rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
return RIO_FAIL;
}
- if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) {
+ if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
return RIO_FAIL;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return RIO_FAIL;
}
/*
- ** set the command byte and the argument byte
- */
- WBYTE(PacketP->data[0] , command);
+ ** set the command byte and the argument byte
+ */
+ WBYTE(PacketP->data[0], command);
- if ( len==2 )
- WBYTE(PacketP->data[1] , arg);
+ if (len == 2)
+ WBYTE(PacketP->data[1], arg);
/*
- ** set the length of the packet and set the command bit.
- */
- WBYTE(PacketP->len , PKT_CMD_BIT | len);
+ ** set the length of the packet and set the command bit.
+ */
+ WBYTE(PacketP->len, PKT_CMD_BIT | len);
add_transmit(PortP);
/*
- ** Count characters transmitted for port statistics reporting
- */
+ ** Count characters transmitted for port statistics reporting
+ */
if (PortP->statsGather)
PortP->txchars += len;
@@ -873,501 +744,3 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP,
}
-#if 0
-/*
-** This is an ioctl interface. This is the twentieth century. You know what
-** its all about.
-*/
-int
-riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
-{
- register struct Port *PortP;
- register struct ttystatics *tp;
- int current;
- int ParamSemIncremented = 0;
- int old_oflag, old_cflag, old_iflag, changed, oldcook;
- int i;
- unsigned char sio_regs[5]; /* Here be magic */
- short vpix_cflag;
- short divisor;
- int baud;
- uint SysPort = rio_minor(tty);
- int Modem = rio_ismodem(tty);
- int ioctl_processed;
-
- rio_dprintk (RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n",
- SysPort, cmd, arg, Modem?"Modem":"tty") ;
-
- if ( SysPort >= RIO_PORTS ) {
- rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort);
- return -ENXIO;
- }
-
- PortP = p->RIOPortp[SysPort];
- tp = PortP->TtyP;
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-#ifdef STATS
- PortP->Stat.IoctlCnt++;
-#endif
-
- if ( PortP->State & RIO_DELETED ) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EIO;
- }
-
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EIO;
- }
-
- /*
- ** Count ioctls for port statistics reporting
- */
- if (PortP->statsGather)
- PortP->ioctls++;
-
- /*
- ** Specialix RIO Ioctl calls
- */
- switch (cmd) {
-
- case TCRIOTRIAD:
- if ( arg )
- PortP->State |= RIO_TRIAD_MODE;
- else
- PortP->State &= ~RIO_TRIAD_MODE;
- /*
- ** Normally, when istrip is set on a port, a config is
- ** sent to the RTA instructing the CD1400 to do the
- ** stripping. In TRIAD mode, the interrupt receive routine
- ** must do the stripping instead, since it has to detect
- ** an 8 bit function key sequence. If istrip is set with
- ** TRIAD mode on(off), and 8 bit data is being read by
- ** the port, the user then turns TRIAD mode off(on), the RTA
- ** must be reconfigured (not) to do the stripping.
- ** Hence we call RIOParam here.
- */
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIOTSTATE:
- rio_dprintk (RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n",
- arg ? "en" : "dis");
- /* MonitorTstate = 0 ;*/
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIOSTATE: /* current state of Modem input pins */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE\n");
- if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL)
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE command failed\n");
- PortP->State |= RIO_BUSY;
- current = PortP->ModemState;
- if ( copyout((caddr_t)&current, (int)arg,
- sizeof(current))==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_TTY, "Copyout failed\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOMBIS: /* Set modem lines */
- case TCRIOMBIC: /* Clear modem lines */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n");
- if (cmd == TCRIOMBIS) {
- uint state;
- state = (uint)arg;
- PortP->ModemState |= (ushort)state;
- PortP->ModemLines = (ulong) arg;
- if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL)
- rio_dprintk (RIO_DEBUG_TTY,
- "TCRIOMBIS command failed\n");
- }
- else {
- uint state;
-
- state = (uint)arg;
- PortP->ModemState &= ~(ushort)state;
- PortP->ModemLines = (ulong) arg;
- if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL)
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIC command failed\n");
- }
- PortP->State |= RIO_BUSY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPON: /* set Xprint ON string */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPON\n");
- if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn,
- MAX_XP_CTRL_LEN)==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n");
- PortP->Xprint.XpOn[0] = '\0';
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+
- strlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPOFF: /* set Xprint OFF string */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPOFF\n");
- if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff,
- MAX_XP_CTRL_LEN)==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n");
- PortP->Xprint.XpOff[0] = '\0';
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+
- strlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPCPS: /* set Xprint CPS string */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPCPS\n");
- if ( (uint)arg > p->RIOConf.MaxXpCps ||
- (uint)arg < p->RIOConf.MinXpCps ) {
- rio_dprintk (RIO_DEBUG_TTY, "%d CPS out of range\n",arg);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EINVAL);
- return 0;
- }
- PortP->Xprint.XpCps = (uint)arg;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPRINT:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPRINT\n");
- if ( copyout((caddr_t)&PortP->Xprint, (int)arg,
- sizeof(struct Xprint))==COPYFAIL ) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXANYON:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n");
- PortP->Config |= RIO_IXANY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXANYOFF:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYOFF\n");
- PortP->Config &= ~RIO_IXANY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXONON:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONON\n");
- PortP->Config |= RIO_IXON;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXONOFF:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONOFF\n");
- PortP->Config &= ~RIO_IXON;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** Added support for CTS and RTS flow control ioctls :
-*/
- case TCRIOCTSFLOWEN:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n");
- PortP->Config |= RIO_CTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIOCTSFLOWDIS:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n");
- PortP->Config &= ~RIO_CTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIORTSFLOWEN:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n");
- PortP->Config |= RIO_RTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIORTSFLOWDIS:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n");
- PortP->Config &= ~RIO_RTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
-/* end ESIL 0761 part fix */
-
- }
-
-
- /* Lynx IOCTLS */
- switch (cmd) {
- case TIOCSETP:
- case TIOCSETN:
- case OTIOCSETP:
- case OTIOCSETN:
- ioctl_processed++;
- ttyseth(PortP, tp, (struct old_sgttyb *)arg);
- break;
- case TCSETA:
- case TCSETAW:
- case TCSETAF:
- ioctl_processed++;
- rio_dprintk (RIO_DEBUG_TTY, "NON POSIX ioctl\n");
- ttyseth_pv(PortP, tp, (struct termios *)arg, 0);
- break;
- case TCSETAP: /* posix tcsetattr() */
- case TCSETAWP: /* posix tcsetattr() */
- case TCSETAFP: /* posix tcsetattr() */
- rio_dprintk (RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n");
- ttyseth_pv(PortP, tp, (struct termios *)arg, 1);
- ioctl_processed++;
- break;
- }
-
- /*
- ** If its any of the commands that require the port to be in the
- ** non-busy state wait until all output has drained
- */
- if (!ioctl_processed)
- switch(cmd) {
- case TCSETAW:
- case TCSETAF:
- case TCSETA:
- case TCSBRK:
-#define OLD_POSIX ('x' << 8)
-#define OLD_POSIX_SETA (OLD_POSIX | 2)
-#define OLD_POSIX_SETAW (OLD_POSIX | 3)
-#define OLD_POSIX_SETAF (OLD_POSIX | 4)
-#define NEW_POSIX (('i' << 24) | ('X' << 16))
-#define NEW_POSIX_SETA (NEW_POSIX | 2)
-#define NEW_POSIX_SETAW (NEW_POSIX | 3)
-#define NEW_POSIX_SETAF (NEW_POSIX | 4)
- case OLD_POSIX_SETA:
- case OLD_POSIX_SETAW:
- case OLD_POSIX_SETAF:
- case NEW_POSIX_SETA:
- case NEW_POSIX_SETAW:
- case NEW_POSIX_SETAF:
-#ifdef TIOCSETP
- case TIOCSETP:
-#endif
- case TIOCSETD:
- case TIOCSETN:
- rio_dprintk (RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n");
- /*
- ** Wait for drain here, at least as far as the double buffer
- ** being empty.
- */
- /* XXX Does the above comment mean that this has
- still to be implemented? -- REW */
- /* XXX Is the locking OK together with locking
- in txenable? (Deadlock?) -- REW */
-
- RIOTxEnable((char *)PortP);
- break;
- default:
- break;
- }
-
- old_cflag = tp->tm.c_cflag;
- old_iflag = tp->tm.c_iflag;
- old_oflag = tp->tm.c_oflag;
- oldcook = PortP->CookMode;
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EIO);
- return 0;
- }
-
- PortP->FlushCmdBodge = 0;
-
- /*
- ** If the port is locked, and it is reconfigured, we want
- ** to restore the state of the tty structure so the change is NOT
- ** made.
- */
- if (PortP->Lock) {
- tp->tm.c_iflag = PortP->StoredTty.iflag;
- tp->tm.c_oflag = PortP->StoredTty.oflag;
- tp->tm.c_cflag = PortP->StoredTty.cflag;
- tp->tm.c_lflag = PortP->StoredTty.lflag;
- tp->tm.c_line = PortP->StoredTty.line;
- for (i = 0; i < NCC + 1; i++)
- tp->tm.c_cc[i] = PortP->StoredTty.cc[i];
- }
- else {
- /*
- ** If the port is set to store the parameters, and it is
- ** reconfigured, we want to save the current tty struct so it
- ** may be restored on the next open.
- */
- if (PortP->Store) {
- PortP->StoredTty.iflag = tp->tm.c_iflag;
- PortP->StoredTty.oflag = tp->tm.c_oflag;
- PortP->StoredTty.cflag = tp->tm.c_cflag;
- PortP->StoredTty.lflag = tp->tm.c_lflag;
- PortP->StoredTty.line = tp->tm.c_line;
- for (i = 0; i < NCC + 1; i++)
- PortP->StoredTty.cc[i] = tp->tm.c_cc[i];
- }
- }
-
- changed = (tp->tm.c_cflag != old_cflag) ||
- (tp->tm.c_iflag != old_iflag) ||
- (tp->tm.c_oflag != old_oflag);
-
- PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */
-
- rio_dprintk (RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n",
- changed,PortP->CookMode,oldcook);
-
-#ifdef MODEM_SUPPORT
- /*
- ** kludge to force CARR_ON if CLOCAL set
- */
- if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
- tp->tm.c_state |= CARR_ON;
- wakeup ((caddr_t)&tp->tm.c_canq);
- }
-#endif
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EIO);
- return 0;
- }
- /*
- ** Re-configure if modes or cooking have changed
- */
- if (changed || oldcook != PortP->CookMode || (ioctl_processed)) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n");
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- }
-
- if (p->RIOHalted) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOClearUp( PortP );
- pseterr(EIO);
- return 0;
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-}
-
-/*
- ttyseth -- set hardware dependent tty settings
-*/
-void
-ttyseth(PortP, s, sg)
-struct Port * PortP;
-struct ttystatics * s;
-struct old_sgttyb *sg;
-{
- struct old_sgttyb * tsg;
- struct termios *tp = &s->tm;
-
- tsg = &s->sg;
-
- if (sg->sg_flags & (EVENP|ODDP)) {
- tp->c_cflag &= PARENB;
- if (sg->sg_flags & EVENP) {
- if (sg->sg_flags & ODDP) {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= ~PARENB;
- }
- else {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- tp->c_cflag &= PARODD;
- }
- }
- else if (sg->sg_flags & ODDP) {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- tp->c_cflag &= PARODD;
- }
- else {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- }
- }
-/*
- * Use ispeed as the desired speed. Most implementations don't handle
- * separate input and output speeds very well. If the RIO handles this,
- * I will have to use separate sets of flags to store them in the
- * Port structure.
- */
- if ( !sg->sg_ospeed )
- sg->sg_ospeed = sg->sg_ispeed;
- else
- sg->sg_ispeed = sg->sg_ospeed;
- if (sg->sg_ispeed > V_EXTB )
- sg->sg_ispeed = V_EXTB;
- if (sg->sg_ispeed < V_B0)
- sg->sg_ispeed = V_B0;
- *tsg = *sg;
- tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int)sg->sg_ispeed];
-}
-
-/*
- ttyseth_pv -- set hardware dependent tty settings using either the
- POSIX termios structure or the System V termio structure.
- sysv = 0 => (POSIX): struct termios *sg
- sysv != 0 => (System V): struct termio *sg
-*/
-static void
-ttyseth_pv(PortP, s, sg, sysv)
-struct Port *PortP;
-struct ttystatics *s;
-struct termios *sg;
-int sysv;
-{
- int speed;
- unsigned char csize;
- unsigned char cread;
- unsigned int lcr_flags;
- int ps;
-
- if (sysv) {
- /* sg points to a System V termio structure */
- csize = ((struct termio *)sg)->c_cflag & CSIZE;
- cread = ((struct termio *)sg)->c_cflag & CREAD;
- speed = conv_vb[((struct termio *)sg)->c_cflag & V_CBAUD];
- }
- else {
- /* sg points to a POSIX termios structure */
- csize = sg->c_cflag & CSIZE;
- cread = sg->c_cflag & CREAD;
- speed = conv_vb[sg->c_cflag & V_CBAUD];
- }
- if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) {
- s->sg.sg_ispeed = speed;
- s->sg.sg_ospeed = speed;
- s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) |
- conv_bv[(int)s->sg.sg_ispeed];
- }
-}
-#endif
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h
index 1c7c42c638f0..9b67e2468bec 100644
--- a/drivers/char/rio/riotypes.h
+++ b/drivers/char/rio/riotypes.h
@@ -89,47 +89,46 @@ typedef RIO_POINTER u_short_ptr;
typedef RIO_POINTER ushort_ptr;
#endif
-#else /* not INKERNEL */
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-typedef short NUMBER;
-typedef short *NUMBER_ptr;
-typedef unsigned short *WORD_ptr;
-typedef unsigned char *BYTE_ptr;
-typedef unsigned char uchar ;
-typedef unsigned short ushort ;
-typedef unsigned int uint ;
-typedef unsigned long ulong ;
-typedef unsigned char u_char ;
-typedef unsigned short u_short ;
-typedef unsigned int u_int ;
-typedef unsigned long u_long ;
-typedef unsigned short ERROR ;
-typedef unsigned long ID ;
-typedef char *char_ptr;
-typedef Channel *Channel_ptr;
+#else /* not INKERNEL */
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef short NUMBER;
+typedef short *NUMBER_ptr;
+typedef unsigned short *WORD_ptr;
+typedef unsigned char *BYTE_ptr;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+typedef unsigned short ERROR;
+typedef unsigned long ID;
+typedef char *char_ptr;
+typedef Channel *Channel_ptr;
typedef struct FREE_LIST *FREE_LIST_ptr;
typedef struct FREE_LIST **FREE_LIST_ptr_ptr;
-typedef struct LPB *LPB_ptr;
-typedef struct Process *Process_ptr;
-typedef struct PHB *PHB_ptr;
-typedef struct PKT *PKT_ptr;
-typedef struct PKT **PKT_ptr_ptr;
-typedef struct Q_BUF *Q_BUF_ptr;
-typedef struct Q_BUF **Q_BUF_ptr_ptr;
+typedef struct LPB *LPB_ptr;
+typedef struct Process *Process_ptr;
+typedef struct PHB *PHB_ptr;
+typedef struct PKT *PKT_ptr;
+typedef struct PKT **PKT_ptr_ptr;
+typedef struct Q_BUF *Q_BUF_ptr;
+typedef struct Q_BUF **Q_BUF_ptr_ptr;
typedef struct ROUTE_STR *ROUTE_STR_ptr;
-typedef struct RUP *RUP_ptr;
-typedef short *short_ptr;
-typedef u_short *u_short_ptr;
-typedef ushort *ushort_ptr;
-typedef struct PKT PKT;
-typedef struct LPB LPB;
-typedef struct RUP RUP;
+typedef struct RUP *RUP_ptr;
+typedef short *short_ptr;
+typedef u_short *u_short_ptr;
+typedef ushort *ushort_ptr;
+typedef struct PKT PKT;
+typedef struct LPB LPB;
+typedef struct RUP RUP;
#endif
-#endif /* __riotypes__ */
+#endif /* __riotypes__ */
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/riowinif.h b/drivers/char/rio/riowinif.h
deleted file mode 100644
index 18a4f147edc2..000000000000
--- a/drivers/char/rio/riowinif.h
+++ /dev/null
@@ -1,1335 +0,0 @@
-/************************************************************************/
-/* */
-/* Title : RIO Shared Memory Window Inteface */
-/* */
-/* Author : N.P.Vassallo */
-/* */
-/* Creation : 7th June 1999 */
-/* */
-/* Version : 1.0.0 */
-/* */
-/* Copyright : (c) Specialix International Ltd. 1999 *
- * This program is free software; you can redistribute 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.
- * */
-/* Description : Prototypes, structures and definitions */
-/* describing RIO host card shared memory */
-/* window interface structures: */
-/* PARMMAP */
-/* RUP */
-/* PHB */
-/* LPB */
-/* PKT */
-/* */
-/************************************************************************/
-
-/* History...
-
-1.0.0 07/06/99 NPV Creation. (based on PARMMAP.H)
-
-*/
-
-#ifndef _riowinif_h /* If RIOWINDIF.H not already defined */
-#define _riowinif_h 1
-
-/*****************************************************************************
-******************************** *********************************
-******************************** General *********************************
-******************************** *********************************
-*****************************************************************************/
-
-#define TPNULL ((_u16)(0x8000))
-
-/*****************************************************************************
-******************************** ********************************
-******************************** PARM_MAP ********************************
-******************************** ********************************
-*****************************************************************************/
-
-/* The PARM_MAP structure defines global values relating to the Host Card / RTA
- and is the main structure from which all other structures are referenced. */
-
-typedef struct _PARM_MAP
-{
- _u16 phb_ptr; /* 0x00 Pointer to the PHB array */
- _u16 phb_num_ptr; /* 0x02 Ptr to Number of PHB's */
- _u16 free_list; /* 0x04 Free List pointer */
- _u16 free_list_end; /* 0x06 Free List End pointer */
- _u16 q_free_list_ptr; /* 0x08 Ptr to Q_BUF variable */
- _u16 unit_id_ptr; /* 0x0A Unit Id */
- _u16 link_str_ptr; /* 0x0C Link Structure Array */
- _u16 bootloader_1; /* 0x0E 1st Stage Boot Loader */
- _u16 bootloader_2; /* 0x10 2nd Stage Boot Loader */
- _u16 port_route_map_ptr; /* 0x12 Port Route Map */
- _u16 route_ptr; /* 0x14 Route Map */
- _u16 map_present; /* 0x16 Route Map present */
- _u16 pkt_num; /* 0x18 Total number of packets */
- _u16 q_num; /* 0x1A Total number of Q packets */
- _u16 buffers_per_port; /* 0x1C Number of buffers per port */
- _u16 heap_size; /* 0x1E Initial size of heap */
- _u16 heap_left; /* 0x20 Current Heap left */
- _u16 error; /* 0x22 Error code */
- _u16 tx_max; /* 0x24 Max number of tx pkts per phb */
- _u16 rx_max; /* 0x26 Max number of rx pkts per phb */
- _u16 rx_limit; /* 0x28 For high / low watermarks */
- _u16 links; /* 0x2A Links to use */
- _u16 timer; /* 0x2C Interrupts per second */
- _u16 rups; /* 0x2E Pointer to the RUPs */
- _u16 max_phb; /* 0x30 Mostly for debugging */
- _u16 living; /* 0x32 Just increments!! */
- _u16 init_done; /* 0x34 Initialisation over */
- _u16 booting_link; /* 0x36 */
- _u16 idle_count; /* 0x38 Idle time counter */
- _u16 busy_count; /* 0x3A Busy counter */
- _u16 idle_control; /* 0x3C Control Idle Process */
- _u16 tx_intr; /* 0x3E TX interrupt pending */
- _u16 rx_intr; /* 0x40 RX interrupt pending */
- _u16 rup_intr; /* 0x42 RUP interrupt pending */
-
-} PARM_MAP;
-
-/* Same thing again, but defined as offsets... */
-
-#define PM_phb_ptr 0x00 /* 0x00 Pointer to the PHB array */
-#define PM_phb_num_ptr 0x02 /* 0x02 Ptr to Number of PHB's */
-#define PM_free_list 0x04 /* 0x04 Free List pointer */
-#define PM_free_list_end 0x06 /* 0x06 Free List End pointer */
-#define PM_q_free_list_ptr 0x08 /* 0x08 Ptr to Q_BUF variable */
-#define PM_unit_id_ptr 0x0A /* 0x0A Unit Id */
-#define PM_link_str_ptr 0x0C /* 0x0C Link Structure Array */
-#define PM_bootloader_1 0x0E /* 0x0E 1st Stage Boot Loader */
-#define PM_bootloader_2 0x10 /* 0x10 2nd Stage Boot Loader */
-#define PM_port_route_map_ptr 0x12 /* 0x12 Port Route Map */
-#define PM_route_ptr 0x14 /* 0x14 Route Map */
-#define PM_map_present 0x16 /* 0x16 Route Map present */
-#define PM_pkt_num 0x18 /* 0x18 Total number of packets */
-#define PM_q_num 0x1A /* 0x1A Total number of Q packets */
-#define PM_buffers_per_port 0x1C /* 0x1C Number of buffers per port */
-#define PM_heap_size 0x1E /* 0x1E Initial size of heap */
-#define PM_heap_left 0x20 /* 0x20 Current Heap left */
-#define PM_error 0x22 /* 0x22 Error code */
-#define PM_tx_max 0x24 /* 0x24 Max number of tx pkts per phb */
-#define PM_rx_max 0x26 /* 0x26 Max number of rx pkts per phb */
-#define PM_rx_limit 0x28 /* 0x28 For high / low watermarks */
-#define PM_links 0x2A /* 0x2A Links to use */
-#define PM_timer 0x2C /* 0x2C Interrupts per second */
-#define PM_rups 0x2E /* 0x2E Pointer to the RUPs */
-#define PM_max_phb 0x30 /* 0x30 Mostly for debugging */
-#define PM_living 0x32 /* 0x32 Just increments!! */
-#define PM_init_done 0x34 /* 0x34 Initialisation over */
-#define PM_booting_link 0x36 /* 0x36 */
-#define PM_idle_count 0x38 /* 0x38 Idle time counter */
-#define PM_busy_count 0x3A /* 0x3A Busy counter */
-#define PM_idle_control 0x3C /* 0x3C Control Idle Process */
-#define PM_tx_intr 0x3E /* 0x4E TX interrupt pending */
-#define PM_rx_intr 0x40 /* 0x40 RX interrupt pending */
-#define PM_rup_intr 0x42 /* 0x42 RUP interrupt pending */
-#define sizeof_PARM_MAP 0x44 /* structure size = 0x44 */
-
-/* PARM_MAP.error definitions... */
-#define E_NO_ERROR 0x00
-#define E_PROCESS_NOT_INIT 0x01
-#define E_LINK_TIMEOUT 0x02
-#define E_NO_ROUTE 0x03
-#define E_CONFUSED 0x04
-#define E_HOME 0x05
-#define E_CSUM_FAIL 0x06
-#define E_DISCONNECTED 0x07
-#define E_BAD_RUP 0x08
-#define E_NO_VIRGIN 0x09
-#define E_BOOT_RUP_BUSY 0x10
-#define E_CHANALLOC 0x80
-#define E_POLL_ALLOC 0x81
-#define E_LTTWAKE 0x82
-#define E_LTT_ALLOC 0x83
-#define E_LRT_ALLOC 0x84
-#define E_CIRRUS 0x85
-#define E_MONITOR 0x86
-#define E_PHB_ALLOC 0x87
-#define E_ARRAY_ALLOC 0x88
-#define E_QBUF_ALLOC 0x89
-#define E_PKT_ALLOC 0x8a
-#define E_GET_TX_Q_BUF 0x8b
-#define E_GET_RX_Q_BUF 0x8c
-#define E_MEM_OUT 0x8d
-#define E_MMU_INIT 0x8e
-#define E_LTT_INIT 0x8f
-#define E_LRT_INIT 0x90
-#define E_LINK_RUN 0x91
-#define E_MONITOR_ALLOC 0x92
-#define E_MONITOR_INIT 0x93
-#define E_POLL_INIT 0x94
-
-/* PARM_MAP.links definitions... */
-#define RIO_LINK_ENABLE 0x80FF
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** RUP ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters
- attached to the system and there is normally an array of MAX_RUPS (=16) structures
- in a host card, defined by PARM_MAP->rup. */
-
-typedef struct _RUP
-{
- _u16 txpkt; /* 0x00 Outgoing packet */
- _u16 rxpkt; /* 0x02 ncoming packet */
- _u16 link; /* 0x04 Which link to send packet down ? */
- _u8 rup_dest_unit[2]; /* 0x06 Destination Unit */
- _u16 handshake; /* 0x08 Handshaking */
- _u16 timeout; /* 0x0A Timeout */
- _u16 status; /* 0x0C Status */
- _u16 txcontrol; /* 0x0E Transmit control */
- _u16 rxcontrol; /* 0x10 Receive control */
-
-} RUP;
-
-/* Same thing again, but defined as offsets... */
-
-#define RUP_txpkt 0x00 /* 0x00 Outgoing packet */
-#define RUP_rxpkt 0x02 /* 0x02 Incoming packet */
-#define RUP_link 0x04 /* 0x04 Which link to send packet down ? */
-#define RUP_rup_dest_unit 0x06 /* 0x06 Destination Unit */
-#define RUP_handshake 0x08 /* 0x08 Handshaking */
-#define RUP_timeout 0x0A /* 0x0A Timeout */
-#define RUP_status 0x0C /* 0x0C Status */
-#define RUP_txcontrol 0x0E /* 0x0E Transmit control */
-#define RUP_rxcontrol 0x10 /* 0x10 Receive control */
-#define sizeof_RUP 0x12 /* structure size = 0x12 */
-
-#define MAX_RUP 16
-
-/* RUP.txcontrol definitions... */
-#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
-#define TX_PACKET_READY 1 /* Transmit packet ready */
-#define TX_LOCK_RUP 2 /* Transmit side locked */
-
-/* RUP.txcontrol definitions... */
-#define RX_RUP_INACTIVE 0 /* Nothing received */
-#define RX_PACKET_READY 1 /* Packet received */
-
-#define RUP_NO_OWNER 0xFF /* RUP not owned by any process */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** PHB ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The PHB (Port Header Block) structure relates to the serial ports attached
- to the system and there is normally an array of MAX_PHBS (=128) structures
- in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */
-
-typedef struct _PHB
-{
- _u16 source; /* 0x00 Location of the PHB in the host card */
- _u16 handshake; /* 0x02 Used to manage receive packet flow control */
- _u16 status; /* 0x04 Internal port transmit/receive status */
- _u16 timeout; /* 0x06 Time period to wait for an ACK */
- _u16 link; /* 0x08 The host link associated with the PHB */
- _u16 destination; /* 0x0A Location of the remote port on the network */
-
- _u16 tx_start; /* 0x0C first entry in the packet array for transmit packets */
- _u16 tx_end; /* 0x0E last entry in the packet array for transmit packets */
- _u16 tx_add; /* 0x10 position in the packet array for new transmit packets */
- _u16 tx_remove; /* 0x12 current position in the packet pointer array */
-
- _u16 rx_start; /* 0x14 first entry in the packet array for receive packets */
- _u16 rx_end; /* 0x16 last entry in the packet array for receive packets */
- _u16 rx_add; /* 0x18 position in the packet array for new receive packets */
- _u16 rx_remove; /* 0x1A current position in the packet pointer array */
-
-} PHB;
-
-/* Same thing again, but defined as offsets... */
-
-#define PHB_source 0x00 /* 0x00 Location of the PHB in the host card */
-#define PHB_handshake 0x02 /* 0x02 Used to manage receive packet flow control */
-#define PHB_status 0x04 /* 0x04 Internal port transmit/receive status */
-#define PHB_timeout 0x06 /* 0x06 Time period to wait for an ACK */
-#define PHB_link 0x08 /* 0x08 The host link associated with the PHB */
-#define PHB_destination 0x0A /* 0x0A Location of the remote port on the network */
-#define PHB_tx_start 0x0C /* 0x0C first entry in the packet array for transmit packets */
-#define PHB_tx_end 0x0E /* 0x0E last entry in the packet array for transmit packets */
-#define PHB_tx_add 0x10 /* 0x10 position in the packet array for new transmit packets */
-#define PHB_tx_remove 0x12 /* 0x12 current position in the packet pointer array */
-#define PHB_rx_start 0x14 /* 0x14 first entry in the packet array for receive packets */
-#define PHB_rx_end 0x16 /* 0x16 last entry in the packet array for receive packets */
-#define PHB_rx_add 0x18 /* 0x18 position in the packet array for new receive packets */
-#define PHB_rx_remove 0x1A /* 0x1A current position in the packet pointer array */
-#define sizeof_PHB 0x1C /* structure size = 0x1C */
-
-/* PHB.handshake definitions... */
-#define PHB_HANDSHAKE_SET 0x0001 /* Set by LRT */
-#define PHB_HANDSHAKE_RESET 0x0002 /* Set by ISR / driver */
-#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET)
- /* Reset by ltt */
-
-#define MAX_PHB 128 /* range 0-127 */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** LPB ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The LPB (Link Parameter Block) structure relates to a RIO Network Link
- and there is normally an array of MAX_LINKS (=4) structures in a host card,
- defined by PARM_MAP->link_str_ptr. */
-
-typedef struct _LPB
-{
- _u16 link_number; /* 0x00 Link Number */
- _u16 in_ch; /* 0x02 Link In Channel */
- _u16 out_ch; /* 0x04 Link Out Channel */
- _u8 attached_serial[4]; /* 0x06 Attached serial number */
- _u8 attached_host_serial[4];/* 0x0A Serial number of Host who booted other end */
- _u16 descheduled; /* 0x0E Currently Descheduled */
- _u16 state; /* 0x10 Current state */
- _u16 send_poll; /* 0x12 Send a Poll Packet */
- _u16 ltt_p; /* 0x14 Process Descriptor */
- _u16 lrt_p; /* 0x16 Process Descriptor */
- _u16 lrt_status; /* 0x18 Current lrt status */
- _u16 ltt_status; /* 0x1A Current ltt status */
- _u16 timeout; /* 0x1C Timeout value */
- _u16 topology; /* 0x1E Topology bits */
- _u16 mon_ltt; /* 0x20 */
- _u16 mon_lrt; /* 0x22 */
- _u16 num_pkts; /* 0x24 */
- _u16 add_packet_list; /* 0x26 Add packets to here */
- _u16 remove_packet_list; /* 0x28 Send packets from here */
-
- _u16 lrt_fail_chan; /* 0x2A Lrt's failure channel */
- _u16 ltt_fail_chan; /* 0x2C Ltt's failure channel */
-
- RUP rup; /* 0x2E RUP structure for HOST to driver comms */
- RUP link_rup; /* 0x40 RUP for the link (POLL, topology etc.) */
- _u16 attached_link; /* 0x52 Number of attached link */
- _u16 csum_errors; /* 0x54 csum errors */
- _u16 num_disconnects; /* 0x56 number of disconnects */
- _u16 num_sync_rcvd; /* 0x58 # sync's received */
- _u16 num_sync_rqst; /* 0x5A # sync requests */
- _u16 num_tx; /* 0x5C Num pkts sent */
- _u16 num_rx; /* 0x5E Num pkts received */
- _u16 module_attached; /* 0x60 Module tpyes of attached */
- _u16 led_timeout; /* 0x62 LED timeout */
- _u16 first_port; /* 0x64 First port to service */
- _u16 last_port; /* 0x66 Last port to service */
-
-} LPB;
-
-/* Same thing again, but defined as offsets... */
-
-#define LPB_link_number 0x00 /* 0x00 Link Number */
-#define LPB_in_ch 0x02 /* 0x02 Link In Channel */
-#define LPB_out_ch 0x04 /* 0x04 Link Out Channel */
-#define LPB_attached_serial 0x06 /* 0x06 Attached serial number */
-#define LPB_attached_host_serial 0x0A /* 0x0A Serial number of Host who booted other end */
-#define LPB_descheduled 0x0E /* 0x0E Currently Descheduled */
-#define LPB_state 0x10 /* 0x10 Current state */
-#define LPB_send_poll 0x12 /* 0x12 Send a Poll Packet */
-#define LPB_ltt_p 0x14 /* 0x14 Process Descriptor */
-#define LPB_lrt_p 0x16 /* 0x16 Process Descriptor */
-#define LPB_lrt_status 0x18 /* 0x18 Current lrt status */
-#define LPB_ltt_status 0x1A /* 0x1A Current ltt status */
-#define LPB_timeout 0x1C /* 0x1C Timeout value */
-#define LPB_topology 0x1E /* 0x1E Topology bits */
-#define LPB_mon_ltt 0x20 /* 0x20 */
-#define LPB_mon_lrt 0x22 /* 0x22 */
-#define LPB_num_pkts 0x24 /* 0x24 */
-#define LPB_add_packet_list 0x26 /* 0x26 Add packets to here */
-#define LPB_remove_packet_list 0x28 /* 0x28 Send packets from here */
-#define LPB_lrt_fail_chan 0x2A /* 0x2A Lrt's failure channel */
-#define LPB_ltt_fail_chan 0x2C /* 0x2C Ltt's failure channel */
-#define LPB_rup 0x2E /* 0x2E RUP structure for HOST to driver comms */
-#define LPB_link_rup 0x40 /* 0x40 RUP for the link (POLL, topology etc.) */
-#define LPB_attached_link 0x52 /* 0x52 Number of attached link */
-#define LPB_csum_errors 0x54 /* 0x54 csum errors */
-#define LPB_num_disconnects 0x56 /* 0x56 number of disconnects */
-#define LPB_num_sync_rcvd 0x58 /* 0x58 # sync's received */
-#define LPB_num_sync_rqst 0x5A /* 0x5A # sync requests */
-#define LPB_num_tx 0x5C /* 0x5C Num pkts sent */
-#define LPB_num_rx 0x5E /* 0x5E Num pkts received */
-#define LPB_module_attached 0x60 /* 0x60 Module tpyes of attached */
-#define LPB_led_timeout 0x62 /* 0x62 LED timeout */
-#define LPB_first_port 0x64 /* 0x64 First port to service */
-#define LPB_last_port 0x66 /* 0x66 Last port to service */
-#define sizeof_LPB 0x68 /* structure size = 0x68 */
-
-#define LINKS_PER_UNIT 4 /* number of links from a host */
-
-/*****************************************************************************
-******************************** *******************************
-******************************** FREE_LIST *******************************
-******************************** *******************************
-*****************************************************************************/
-
-/* Used to overlay packet headers when allocating/freeing packets from the free list */
-
-typedef struct _FREE_LIST
-{
- _u16 next; /* 0x00 offset of next list item */
- _u16 prev; /* 0x02 offset of previous list item */
-
-} FREE_LIST;
-
-/* Same thing again, but defined as offsets... */
-
-#define FL_next 0x00 /* 0x00 offset of next list item */
-#define FL_prev 0x02 /* 0x02 offset of previous list item */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** PKT ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The PKT is the main unit of communication between Host Cards and RTAs across
- the RIO network. */
-
-#define PKT_MAX_DATA_LEN 72 /* Size of packet data */
-
-typedef struct _PKT
-{
- _u8 dest_unit; /* 0x00 Destination Unit Id */
- _u8 dest_port; /* 0x01 Destination Port */
- _u8 src_unit; /* 0x02 Source Unit Id */
- _u8 src_port; /* 0x03 Source Port */
- _u8 len; /* 0x04 Length (in bytes) of data field */
- _u8 control; /* 0x05 */
- _u8 data[PKT_MAX_DATA_LEN]; /* 0x06 Actual data */
- _u16 csum; /* 0x4E C-SUM */
-
-} PKT;
-
-/* Same thing again, but defined as offsets... */
-
-#define PKT_dest_unit 0x00 /* 0x00 Destination Unit Id */
-#define PKT_dest_port 0x01 /* 0x01 Destination Port */
-#define PKT_src_unit 0x02 /* 0x02 Source Unit Id */
-#define PKT_src_port 0x03 /* 0x03 Source Port */
-#define PKT_len 0x04 /* 0x04 Length (in bytes) of data field */
-#define PKT_control 0x05 /* 0x05 */
-#define PKT_data 0x06 /* 0x06 Actual data */
-#define PKT_csum 0x4E /* 0x4E C-SUM */
-#define sizeof_PKT 0x50 /* structure size = 0x50 */
-
-/* PKT.len definitions... */
-#define PKT_CMD_BIT 0x80
-#define PKT_CMD_DATA 0x80
-#define PKT_LEN_MASK 0x7F
-
-/* PKT.control definitions... */
-#define PKT_ACK 0x40
-#define PKT_TGL 0x20
-#define DATA_WNDW 0x10
-#define PKT_TTL_MASK 0x0F
-#define MAX_TTL 0x0F
-
-/*****************************************************************************
-***************************** ****************************
-***************************** Control Packets ****************************
-***************************** ****************************
-*****************************************************************************/
-
-/* The following definitions and structures define the control packets sent
- between the driver and RIO Ports, RTAs and Host Cards. */
-
-#define PRE_EMPTIVE 0x80 /* Pre-emptive command (sent via port's RUP) */
-
-/* "in-band" and "pre-emptive" port commands... */
-#define OPEN 0x00 /* Driver->RIO Open a port */
-#define CONFIG 0x01 /* Driver->RIO Configure a port */
-#define MOPEN 0x02 /* Driver->RIO Modem open (wait for DCD) */
-#define CLOSE 0x03 /* Driver->RIO Close a port */
-#define WFLUSH (0x04|PRE_EMPTIVE) /* Driver->RIO Write flush */
-#define RFLUSH (0x05|PRE_EMPTIVE) /* Driver->RIO Read flush */
-#define RESUME (0x06|PRE_EMPTIVE) /* Driver->RIO Behave as if XON received */
-#define SBREAK 0x07 /* Driver->RIO Start break */
-#define EBREAK 0x08 /* Driver->RIO End break */
-#define SUSPEND (0x09|PRE_EMPTIVE) /* Driver->RIO Behave as if XOFF received */
-#define FCLOSE (0x0A|PRE_EMPTIVE) /* Driver->RIO Force close */
-#define XPRINT 0x0B /* Driver->RIO Xprint packet */
-#define MBIS (0x0C|PRE_EMPTIVE) /* Driver->RIO Set modem lines */
-#define MBIC (0x0D|PRE_EMPTIVE) /* Driver->RIO Clear modem lines */
-#define MSET (0x0E|PRE_EMPTIVE) /* Driver->RIO Set modem lines */
-#define PCLOSE 0x0F /* Driver->RIO Pseudo close */
-#define MGET (0x10|PRE_EMPTIVE) /* Driver->RIO Force update of modem status */
-#define MEMDUMP (0x11|PRE_EMPTIVE) /* Driver->RIO DEBUG request for RTA memory */
-#define READ_REGISTER (0x12|PRE_EMPTIVE) /* Driver->RIO DEBUG read CD1400 register */
-
-/* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */
-#define SYNC_RUP 0xFF /* Download internal */
-#define COMMAND_RUP 0xFE /* Command ack/status */
-#define ERROR_RUP 0xFD /* Download internal */
-#define POLL_RUP 0xFC /* Download internal */
-#define BOOT_RUP 0xFB /* Used to boot RTAs */
-#define ROUTE_RUP 0xFA /* Used to specify routing/topology */
-#define STATUS_RUP 0xF9 /* Not used */
-#define POWER_RUP 0xF8 /* Download internal */
-
-/* COMMAND_RUP definitions... */
-#define COMPLETE (0x20|PRE_EMPTIVE) /* RIO->Driver Command complete */
-#define BREAK_RECEIVED (0x21|PRE_EMPTIVE) /* RIO->Driver Break received */
-#define MODEM_STATUS (0x22|PRE_EMPTIVE) /* RIO->Driver Modem status change */
-
-/* BOOT_RUP definitions... */
-#define BOOT_REQUEST 0x00 /* RIO->Driver Request for boot */
-#define BOOT_ABORT 0x01 /* Driver->RIO Abort a boot */
-#define BOOT_SEQUENCE 0x02 /* Driver->RIO Packet with firmware details */
-#define BOOT_COMPLETED 0x03 /* RIO->Driver Boot completed */
-#define IFOAD 0x2F /* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */
-#define IDENTIFY 0x30 /* Driver->RIO Identify RTA */
-#define ZOMBIE 0x31 /* Driver->RIO Shutdown/Flash LEDs */
-#define UFOAD 0x32 /* Driver->RIO Shutdown/Reboot neighbouring RTA */
-#define IWAIT 0x33 /* Driver->RIO Pause booting process */
-
-/* ROUTE_RUP definitions... */
-#define ROUTE_REQUEST 0x00 /* RIO->Driver Request an ID */
-#define ROUTE_FOAD 0x01 /* Driver->RIO Shutdown/reboot RTA */
-#define ROUTE_ALREADY 0x02 /* Driver->RIO Not used */
-#define ROUTE_USED 0x03 /* Driver->RIO Not used */
-#define ROUTE_ALLOCATE 0x04 /* Driver->RIO Allocate RTA RUP numbers */
-#define ROUTE_REQ_TOP 0x05 /* Driver->RIO Not used */
-#define ROUTE_TOPOLOGY 0x06 /* RIO->Driver Route/Topology status */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** OPEN **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- Sent to open a port.
- Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_Cor1 (PKT_Data+1) /* Channel Option Register 1 */
-#define PKT_Cor2 (PKT_Data+2) /* Channel Option Register 2 */
-#define PKT_Cor4 (PKT_Data+3) /* Channel Option Register 4 */
-#define PKT_Cor5 (PKT_Data+4) /* Channel Option Register 5 */
-#define PKT_TxXon (PKT_Data+5) /* Transmit XON character */
-#define PKT_TxXoff (PKT_Data+6) /* Transmit XOFF character */
-#define PKT_RxXon (PKT_Data+7) /* Receive XON character */
-#define PKT_RxXoff (PKT_Data+8) /* Receive XOFF character */
-#define PKT_Lnext (PKT_Data+9) /* Lnext character */
-#define PKT_TxBaud (PKT_Data+10) /* Transmit baud rate */
-#define PKT_RxBaud (PKT_Data+11) /* Receive baud rate */
-
-/* COR1 definitions... */
-#define COR1_PARITY 0xE0 /* Parity mask */
-#define COR1_NONE 0x00 /* No parity */
-#define COR1_SPACE 0x20 /* Space parity */
-#define COR1_EVEN 0x40 /* Even parity */
-#define COR1_MARK 0xA0 /* Mark parity */
-#define COR1_ODD 0xC0 /* Odd parity */
-
-#define COR1_STOPBITS 0x0C /* Stop bits mask */
-#define COR1_STOP1 0x00 /* 1 stop bit */
-#define COR1_STOP1_5 0x04 /* 1.5 stop bits */
-#define COR1_STOP2 0x08 /* 2 stop bits */
-
-#define COR1_DATABITS 0x03 /* Data bits mask */
-#define COR1_DATA5 0x00 /* 5 data bits */
-#define COR1_DATA6 0x01 /* 6 data bits */
-#define COR1_DATA7 0x02 /* 7 data bits */
-#define COR1_DATA8 0x03 /* 8 data bits */
-
-/* COR2 definitions... */
-#define COR2_XON_TXFLOW 0x40 /* XON/XOFF Transmit Flow */
-#define COR2_XANY_TXFLOW 0xC0 /* XON/XANY Transmit Flow */
-#define COR2_HUPCL 0x20 /* Hang Up On Close */
-#define COR2_DSR_TXFLOW 0x08 /* DSR Transmit Flow Control */
-#define COR2_RTS_RXFLOW 0x04 /* RTS Receive Flow Control */
-#define COR2_CTS_TXFLOW 0x02 /* CTS Transmit Flow Control */
-#define COR2_XON_RXFLOW 0x01 /* XON/XOFF Receive Flow */
-
-/* COR4 definition... */
-#define COR4_IGNCR 0x80 /* Discard received CR */
-#define COR4_ICRNL 0x40 /* Map received CR -> NL */
-#define COR4_INLCR 0x20 /* Map received NL -> CR */
-#define COR4_IGNBRK 0x10 /* Ignore Received Break */
-#define COR4_NBRKINT 0x08 /* No interrupt on rx Break */
-#define COR4_IGNPAR 0x04 /* ignore rx parity error chars */
-#define COR4_PARMRK 0x02 /* Mark rx parity error chars */
-#define COR4_RAISEMOD 0x01 /* Raise modem lines on !0 baud */
-
-/* COR5 definitions... */
-#define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */
-#define COR5_LNE 0x40 /* Enable LNEXT processing */
-#define COR5_CMOE 0x20 /* Match good & error characters */
-#define COR5_TAB3 0x10 /* TAB3 mode */
-#define COR5_TSTATE_ON 0x08 /* Enable tbusy/tstop monitoring */
-#define COR5_TSTATE_OFF 0x04 /* Disable tbusy/tstop monitoring */
-#define COR5_ONLCR 0x02 /* NL -> CR NL on output */
-#define COR5_OCRNL 0x01 /* CR -> NL on output */
-
-/* RxBaud and TxBaud definitions... */
-#define RIO_B0 0x00 /* RTS / DTR signals dropped */
-#define RIO_B50 0x01 /* 50 baud */
-#define RIO_B75 0x02 /* 75 baud */
-#define RIO_B110 0x03 /* 110 baud */
-#define RIO_B134 0x04 /* 134.5 baud */
-#define RIO_B150 0x05 /* 150 baud */
-#define RIO_B200 0x06 /* 200 baud */
-#define RIO_B300 0x07 /* 300 baud */
-#define RIO_B600 0x08 /* 600 baud */
-#define RIO_B1200 0x09 /* 1200 baud */
-#define RIO_B1800 0x0A /* 1800 baud */
-#define RIO_B2400 0x0B /* 2400 baud */
-#define RIO_B4800 0x0C /* 4800 baud */
-#define RIO_B9600 0x0D /* 9600 baud */
-#define RIO_B19200 0x0E /* 19200 baud */
-#define RIO_B38400 0x0F /* 38400 baud */
-#define RIO_B56000 0x10 /* 56000 baud */
-#define RIO_B57600 0x11 /* 57600 baud */
-#define RIO_B64000 0x12 /* 64000 baud */
-#define RIO_B115200 0x13 /* 115200 baud */
-#define RIO_B2000 0x14 /* 2000 baud */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* CONFIG *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- CONFIG is sent from the driver to configure an already opened port.
- Packet structure is same as OPEN. */
-
-/*****************************************************************************
-********************************* **********************************
-********************************* MOPEN **********************************
-********************************* **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- MOPEN is sent from the driver to open a port attached to a modem. (in-band)
- Packet structure is same as OPEN. */
-
-/*****************************************************************************
-********************************* **********************************
-********************************* CLOSE **********************************
-********************************* **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- CLOSE is sent from the driver to close a previously opened port.
- No parameters.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-/*****************************************************************************
-********************************* *********************************
-********************************* WFLUSH *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- WFLUSH is sent pre-emptively from the driver to flush the write buffers and
- packets of a port. (pre-emptive)
-
- WFLUSH is also sent in-band from the driver to a port as a marker to end
- write flushing previously started by a pre-emptive WFLUSH packet. (in-band)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* RFLUSH *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- RFLUSH is sent pre-emptively from the driver to flush the read buffers and
- packets of a port.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* RESUME *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- RESUME is sent pre-emptively from the driver to cause a port to resume
- transmission of data if blocked by XOFF. (as if XON had been received)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* SBREAK *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- SBREAK is sent in-band from the driver to a port to suspend data and start
- break signal transmission.
-
- If the break delay is 0, the break signal will be acknowledged with a
- RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received.
-
- Otherwise, there is no acknowledgement and the break signal will last for the
- specified number of mS.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* EBREAK *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- EBREAK is sent in-band from the driver to a port to stop transmission of a
- break signal.
-
- No parameters. */
-
-/*****************************************************************************
-********************************* ********************************
-********************************* SUSPEND ********************************
-********************************* ********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- SUSPEND is sent pre-emptively from the driver to cause a port to suspend
- transmission of data. (as if XOFF had been received)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* FCLOSE *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- FCLOSE is sent pre-emptively from the driver to force close a port.
- A force close flushes receive and transmit queues, and also lowers all output
- modem signals if the COR5_HUPCL (Hang Up On Close) flag is set.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* XPRINT *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of
- the "len" field is set, and the first "data" byte is XPRINT.
-
- The I/O data in the XPRINT packet will contain the following:
- - Transparent Print Start Sequence
- - Transparent Print Data
- - Transparent Print Stop Sequence.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MBIS **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MBIS is sent pre-emptively from the driver to set a port's modem signals.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */
-
-/* ModemSet definitions... */
-#define MBIS_RTS 0x01 /* RTS modem signal */
-#define MBIS_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MBIC **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MBIC is sent pre-emptively from the driver to clear a port's modem signals.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-#define PKT_ModemClear (PKT_Data+4) /* Modem clear signals mask */
-
-/* ModemClear definitions... */
-#define MBIC_RTS 0x01 /* RTS modem signal */
-#define MBIC_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MSET **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */
-
-/* ModemSet definitions... */
-#define MSET_RTS 0x01 /* RTS modem signal */
-#define MSET_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* PCLOSE *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- PCLOSE is sent from the driver to pseudo close a previously opened port.
-
- The port will close when all data has been sent/received, however, the
- port's transmit / receive and modem signals will be left enabled and the
- port marked internally as Pseudo Closed. */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MGET **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MGET is sent pre-emptively from the driver to request the port's current modem signals. */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-
-/*****************************************************************************
-********************************* ********************************
-********************************* MEMDUMP ********************************
-********************************* ********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes
- of the specified port's RTA address space.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-
-/*****************************************************************************
-****************************** *****************************
-****************************** READ_REGISTER *****************************
-****************************** *****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- READ_REGISTER is sent pre-emptively from the driver to request the contents
- of the CD1400 register specified in address.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-
-/*****************************************************************************
-************************ **************************
-************************ COMMAND_RUP - COMPLETE **************************
-************************ **************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
- packets, except MEMDUMP and READ_REGISTER.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-
-/* ModemStatus definitions... */
-#define MODEM_DSR 0x80 /* Data Set Ready modem state */
-#define MODEM_CTS 0x40 /* Clear To Send modem state */
-#define MODEM_RI 0x20 /* Ring Indicate modem state */
-#define MODEM_CD 0x10 /* Carrier Detect modem state */
-#define MODEM_TSTOP 0x08 /* Transmit Stopped state */
-#define MODEM_TEMPTY 0x04 /* Transmit Empty state */
-#define MODEM_DTR 0x02 /* DTR modem output state */
-#define MODEM_RTS 0x01 /* RTS modem output state */
-
-/* PortStatus definitions... */
-#define PORT_ISOPEN 0x01 /* Port open ? */
-#define PORT_HUPCL 0x02 /* Hangup on close? */
-#define PORT_MOPENPEND 0x04 /* Modem open pending */
-#define PORT_ISPARALLEL 0x08 /* Parallel port */
-#define PORT_BREAK 0x10 /* Port on break */
-#define PORT_STATUSPEND 0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x40 /* Break packet pending */
-#define PORT_MODEMPEND 0x80 /* Modem status packet pending */
-
-/*****************************************************************************
-************************ **************************
-************************ COMMAND_RUP - COMPLETE **************************
-************************ **************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
- packets, except MEMDUMP and READ_REGISTER.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#if 0
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#endif
-
-/* ModemStatus definitions... */
-#define MODEM_DSR 0x80 /* Data Set Ready modem state */
-#define MODEM_CTS 0x40 /* Clear To Send modem state */
-#define MODEM_RI 0x20 /* Ring Indicate modem state */
-#define MODEM_CD 0x10 /* Carrier Detect modem state */
-#define MODEM_TSTOP 0x08 /* Transmit Stopped state */
-#define MODEM_TEMPTY 0x04 /* Transmit Empty state */
-#define MODEM_DTR 0x02 /* DTR modem output state */
-#define MODEM_RTS 0x01 /* RTS modem output state */
-
-/* PortStatus definitions... */
-#define PORT_ISOPEN 0x01 /* Port open ? */
-#define PORT_HUPCL 0x02 /* Hangup on close? */
-#define PORT_MOPENPEND 0x04 /* Modem open pending */
-#define PORT_ISPARALLEL 0x08 /* Parallel port */
-#define PORT_BREAK 0x10 /* Port on break */
-#define PORT_STATUSPEND 0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x40 /* Break packet pending */
-#define PORT_MODEMPEND 0x80 /* Modem status packet pending */
-
-/*****************************************************************************
-******************** ********************
-******************** COMMAND_RUP - COMPLETE - MEMDUMP ********************
-******************** ********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP
- port I/O control command packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-#endif
-#define PKT_Dump (PKT_Data+8) /* 32bytes of requested dump data */
-
-/*****************************************************************************
-***************** *****************
-***************** COMMAND_RUP - COMPLETE - READ_REGISTER *****************
-***************** *****************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a
- READ_REGISTER port I/O control command packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /*Command code */
-#define PKT_PhbNum (PKT_Data+1) /*Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-#define PKT_RegisterValue (PKT_Data+3) /* Modem signal status */
-#if 0
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#endif
-
-/*****************************************************************************
-********************* ***********************
-********************* COMMAND_RUP - BREAK_RECEIVED ***********************
-********************* ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-
-/*****************************************************************************
-********************* *************************
-********************* COMMAND_RUP - MODEM_STATUS *************************
-********************* *************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a
- change in the input modem signal states.
-
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#endif
-
-/*****************************************************************************
-************************ *************************
-************************ BOOT_RUP - BOOT_REQUEST *************************
-************************ *************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request
- firmware code to load onto attached RTAs.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-
-/*****************************************************************************
-************************ ************************
-************************ BOOT_RUP - BOOT_SEQUENCE ************************
-************************ ************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response
- to a BOOT_RUP - BOOT_REQUEST packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_NumPackets (PKT_Data+2) /* Packets required to load firmware */
-#define PKT_LoadBase (PKT_Data+4) /* RTA firmware load address */
-#define PKT_CodeSize (PKT_Data+6) /* Size of firmware in bytes */
-#define PKT_CmdString (PKT_Data+8) /* Command string */
-
-/*****************************************************************************
-************************ ***********************
-************************ BOOT_RUP - BOOT_COMPLETED ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of
- RTA firmware has completed.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_LinkNumber (PKT_Data+1) /* Link number RTA booted on */
-#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
-
-/*****************************************************************************
-************************ ***********************
-************************ BOOT_RUP - Packet Request ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent
- from RIO to the Driver as a request for a firmware boot packet. */
-
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** BOOT_RUP - Packet Response ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- In response to a BOOT_RUP boot packet request, the driver fills out the response
- packet with the 70 bytes of the requested sequence.
- */
-#if 0
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
-#endif
-#define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - IFOAD ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the
- RTA to shut down and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IfoadId1 (PKT_Data+2) /* IFOAD Id 1 */
-#define PKT_IfoadId2 (PKT_Data+3) /* IFOAD Id 2 */
-
-#define IFOADID1 0xAD
-#define IFOADID2 0xF0
-
-/*****************************************************************************
-************************** ***************************
-************************** BOOT_RUP - IDENTIFY ***************************
-************************** ***************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the
- RTA to flash its LEDs for a period of time.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */
-
-/*****************************************************************************
-**************************** ***************************
-**************************** BOOT_RUP - ZOMBIE ***************************
-**************************** ***************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the
- RTA to shut down and flash it's LEDs.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_ZombieId1 (PKT_Data+2) /* ZOMBIE Id 1 */
-#define PKT_ZombieId2 (PKT_Data+3) /* ZOMBIE Id 2 */
-
-#define ZOMBIEID1 0x52
-#define ZOMBIEID2 0x21
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - UFOAD ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA
- to ask it's neighbouring RTA to shut down and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */
-#endif
-#define PKT_UfoadId1 (PKT_Data+2) /* UFOAD Id 1 */
-#define PKT_UfoadId2 (PKT_Data+3) /* UFOAD Id 2 */
-
-#define UFOADID1 0x1E
-#define UFOADID2 0x0D
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - IWAIT ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA
- to pause booting on the specified link for 30 seconds.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */
-#endif
-#define PKT_IwaitId1 (PKT_Data+2) /* IWAIT Id 1 */
-#define PKT_IwaitId2 (PKT_Data+3) /* IWAIT Id 2 */
-
-#define IWAITID1 0xDE
-#define IWAITID2 0xB1
-
-/*****************************************************************************
-************************ ***********************
-************************ ROUTE_RUP - ROUTE_REQUEST ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected
- RTA to a Driver to request an ID (RUP or unit number).
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
-#define PKT_ModuleTypes (PKT_Data+6) /* RTA Module types */
-
-/* ModuleTypes definitions... */
-#define MOD_BLANK 0x0F /* Blank plate attached */
-#define MOD_RS232DB25 0x00 /* RS232 DB25 connector */
-#define MOD_RS232RJ45 0x01 /* RS232 RJ45 connector */
-#define MOD_RS422DB25 0x02 /* RS422 DB25 connector */
-#define MOD_RS485DB25 0x03 /* RS485 DB25 connector */
-#define MOD_PARALLEL 0x04 /* Centronics parallel */
-
-#define MOD2 0x08 /* Set to indicate Rev2 module */
-
-/*****************************************************************************
-************************* *************************
-************************* ROUTE_RUP - ROUTE_FOAD *************************
-************************* *************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
- packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** ROUTE_RUP - ROUTE_ALLOCATE ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
- packet to allocate the RTA's Id number (RUP number 1..16)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */
-#if 0
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
-#endif
-#define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** ROUTE_RUP - ROUTE_TOPOLOGY ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's
- current link status.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_Link1Rup (PKT_Data+2) /* Link 1 RUP number */
-#define PKT_Link1Link (PKT_Data+3) /* Link 1 link number */
-#define PKT_Link2Rup (PKT_Data+4) /* Link 2 RUP number */
-#define PKT_Link2Link (PKT_Data+5) /* Link 2 link number */
-#define PKT_Link3Rup (PKT_Data+6) /* Link 3 RUP number */
-#define PKT_Link3Link (PKT_Data+7) /* Link 3 link number */
-#define PKT_Link4Rup (PKT_Data+8) /* Link 4 RUP number */
-#define PKT_Link4Link (PKT_Data+9) /* Link 4 link number */
-#define PKT_RtaVpdProm (PKT_Data+10) /* 32 bytes of RTA VPD PROM Contents */
-
-#endif /* _sxwinif_h */
-
-/* End of RIOWINIF.H */
diff --git a/drivers/char/rio/riscos.h b/drivers/char/rio/riscos.h
deleted file mode 100644
index 7685cc1d9e7b..000000000000
--- a/drivers/char/rio/riscos.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-**
-** Module : riscos.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:19
-** Retrieved : 11/6/98 11:34:22
-**
-** ident @(#)riscos.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riscos_h__
-#define __rio_riscos_h__
-
-#ifdef SCCS_LABELS
-static char *_riscos_h_sccs_ = "@(#)riscos.h 1.2";
-#endif
-
-/*
-** This module used to define all those little itsy bits required for RISC/OS
-** now it's full of null macros.
-*/
-
-/*
-** RBYTE reads a byte from a location.
-** RWORD reads a word from a location.
-** WBYTE writes a byte to a location.
-** WWORD writes a word to a location.
-** RINDW reads a word through a pointer.
-** WINDW writes a word through a pointer.
-** RIOSWAB swaps the two bytes of a word, if needed.
-*/
-
-#define RIOSWAB(N) (N)
-#define WBYTE(A,V) (A)=(uchar)(V)
-#define WWORD(A,V) (A)=(ushort)(V)
-#define RBYTE(A) (uchar)(A)
-#define RWORD(A) (ushort)(A)
-#define RINDW(A) (*(ushort *)(A))
-#define WINDW(A,V) (*(ushort *)(A)=(ushort)(V))
-
-#endif /* __rio_riscos_h__ */
diff --git a/drivers/char/rio/rom.h b/drivers/char/rio/rom.h
index ee79b8e5b972..58a7843625ff 100644
--- a/drivers/char/rio/rom.h
+++ b/drivers/char/rio/rom.h
@@ -39,19 +39,19 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_rom_h_sccs = "@(#)rom.h 1.1" ;
+static char *_rio_rom_h_sccs = "@(#)rom.h 1.1";
#endif
#endif
-typedef struct ROM ROM ;
-struct ROM {
- u_short slx ;
- char pcb_letter_rev ;
- char pcb_number_rev ;
- char serial[4] ;
- char year ;
- char week ;
- } ;
+typedef struct ROM ROM;
+struct ROM {
+ u_short slx;
+ char pcb_letter_rev;
+ char pcb_number_rev;
+ char serial[4];
+ char year;
+ char week;
+};
#endif
@@ -60,5 +60,3 @@ struct ROM {
#define ROM_LENGTH 0x20
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/route.h b/drivers/char/rio/route.h
index c42dbb971718..769744e575ab 100644
--- a/drivers/char/rio/route.h
+++ b/drivers/char/rio/route.h
@@ -44,26 +44,26 @@
#endif
#define MAX_LINKS 4
-#define MAX_NODES 17 /* Maximum nodes in a subnet */
-#define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for
- 1 bit per node */
-#define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete
- info about cost etc. */
+#define MAX_NODES 17 /* Maximum nodes in a subnet */
+#define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for
+ 1 bit per node */
+#define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete
+ info about cost etc. */
#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
- /* Number of nodes we can squeeze
- into one packet */
+ /* Number of nodes we can squeeze
+ into one packet */
#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
/************************************************
* Define the types of command for the ROUTE RUP.
************************************************/
-#define ROUTE_REQUEST 0 /* Request an ID */
-#define ROUTE_FOAD 1 /* Kill the RTA */
-#define ROUTE_ALREADY 2 /* ID given already */
-#define ROUTE_USED 3 /* All ID's used */
-#define ROUTE_ALLOCATE 4 /* Here it is */
-#define ROUTE_REQ_TOP 5 /* I bet you didn't expect....
- the Topological Inquisition */
-#define ROUTE_TOPOLOGY 6 /* Topology request answered FD */
+#define ROUTE_REQUEST 0 /* Request an ID */
+#define ROUTE_FOAD 1 /* Kill the RTA */
+#define ROUTE_ALREADY 2 /* ID given already */
+#define ROUTE_USED 3 /* All ID's used */
+#define ROUTE_ALLOCATE 4 /* Here it is */
+#define ROUTE_REQ_TOP 5 /* I bet you didn't expect....
+ the Topological Inquisition */
+#define ROUTE_TOPOLOGY 6 /* Topology request answered FD */
/*******************************************************************
* Define the Route Map Structure
*
@@ -72,22 +72,22 @@
******************************************************************/
typedef struct COST_ROUTE COST_ROUTE;
struct COST_ROUTE {
- unsigned char cost; /* Cost down this link */
- unsigned char route[NODE_BYTES]; /* Nodes thorough this route */
- } ;
+ unsigned char cost; /* Cost down this link */
+ unsigned char route[NODE_BYTES]; /* Nodes thorough this route */
+};
-typedef struct ROUTE_STR ROUTE_STR ;
-struct ROUTE_STR {
- COST_ROUTE cost_route[MAX_LINKS];
- /* cost / route for this link */
- ushort favoured; /* favoured link */
- } ;
+typedef struct ROUTE_STR ROUTE_STR;
+struct ROUTE_STR {
+ COST_ROUTE cost_route[MAX_LINKS];
+ /* cost / route for this link */
+ ushort favoured; /* favoured link */
+};
-#define NO_LINK (short) 5 /* Link unattached */
-#define ROUTE_NO_ID (short) 100 /* No Id */
-#define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */
-#define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */
+#define NO_LINK (short) 5 /* Link unattached */
+#define ROUTE_NO_ID (short) 100 /* No Id */
+#define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */
+#define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */
#define SYNC_RUP (ushort) 255
@@ -99,10 +99,9 @@ struct ROUTE_STR {
#define STATUS_RUP (ushort) 249
#define POWER_RUP (ushort) 248
-#define HIGHEST_RUP (ushort) 255 /* Set to Top one */
-#define LOWEST_RUP (ushort) 248 /* Set to bottom one */
+#define HIGHEST_RUP (ushort) 255 /* Set to Top one */
+#define LOWEST_RUP (ushort) 248 /* Set to bottom one */
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/rtahw.h b/drivers/char/rio/rtahw.h
deleted file mode 100644
index 06860118cbc5..000000000000
--- a/drivers/char/rio/rtahw.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* R T A H A R D W A R E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5" ;
-#endif
-#endif
-
-#define WATCHDOG_ADDR ((unsigned short *)0x7a00)
-#define RTA_LED_ADDR ((unsigned short *)0x7c00)
-#define SERIALNUM_ADDR ((unsigned char *)0x7809)
-#define LATCH_ADDR ((unsigned char *)0x7800)
-
-/*
-** Here we define where the cd1400 chips are in memory.
-*/
-#define CD1400_ONE_ADDR (0x7300)
-#define CD1400_TWO_ADDR (0x7200)
-#define CD1400_THREE_ADDR (0x7100)
-#define CD1400_FOUR_ADDR (0x7000)
-
-/*
-** Define the different types of modules we can have
-*/
-enum module {
- MOD_BLANK = 0x0f, /* Blank plate attached */
- MOD_RS232DB25 = 0x00, /* RS232 DB25 connector */
- MOD_RS232RJ45 = 0x01, /* RS232 RJ45 connector */
- MOD_RS422DB25 = 0x02, /* RS422 DB25 connector */
- MOD_RS485DB25 = 0x03, /* RS485 DB25 connector */
- MOD_PARALLEL = 0x04 /* Centronics parallel */
-};
-
-#define TYPE_HOST 0
-#define TYPE_RTA8 1
-#define TYPE_RTA16 2
-
-#define WATCH_DOG WATCHDOG_ADDR
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
index b9d2bc03d14b..8d44fec91dd5 100644
--- a/drivers/char/rio/rup.h
+++ b/drivers/char/rio/rup.h
@@ -44,39 +44,38 @@
#endif
#if defined( HOST ) || defined( INKERNEL )
-#define MAX_RUP ((short) 16)
+#define MAX_RUP ((short) 16)
#endif
#ifdef RTA
#define MAX_RUP ((short) 1)
#endif
-#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */
+#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */
/*************************************************
* Define all the packet request stuff
************************************************/
-#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
-#define TX_PACKET_READY 1 /* Transmit packet ready */
-#define TX_LOCK_RUP 2 /* Transmit side locked */
+#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
+#define TX_PACKET_READY 1 /* Transmit packet ready */
+#define TX_LOCK_RUP 2 /* Transmit side locked */
-#define RX_RUP_INACTIVE 0 /* Nothing received */
-#define RX_PACKET_READY 1 /* Packet received */
+#define RX_RUP_INACTIVE 0 /* Nothing received */
+#define RX_PACKET_READY 1 /* Packet received */
-#define RUP_NO_OWNER 0xff /* RUP not owned by any process */
+#define RUP_NO_OWNER 0xff /* RUP not owned by any process */
struct RUP {
- PKT_ptr txpkt; /* Outgoing packet */
- PKT_ptr rxpkt; /* Incoming packet */
- WORD link; /* Which link to send down? */
- BYTE rup_dest_unit[2]; /* Destination unit */
- WORD handshake; /* For handshaking */
- WORD timeout; /* Timeout */
- WORD status; /* Status */
- WORD txcontrol; /* Transmit control */
- WORD rxcontrol; /* Receive control */
- };
-
+ PKT_ptr txpkt; /* Outgoing packet */
+ PKT_ptr rxpkt; /* Incoming packet */
+ WORD link; /* Which link to send down? */
+ BYTE rup_dest_unit[2]; /* Destination unit */
+ WORD handshake; /* For handshaking */
+ WORD timeout; /* Timeout */
+ WORD status; /* Status */
+ WORD txcontrol; /* Transmit control */
+ WORD rxcontrol; /* Receive control */
+};
+
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/rupstat.h b/drivers/char/rio/rupstat.h
deleted file mode 100644
index b4aafaff0d78..000000000000
--- a/drivers/char/rio/rupstat.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* RUPSTAT
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _rupstat_h
-#define _rupstat_h
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1" ;
-#endif
-#endif
-
-#define STATUS_SYNC 0
-#define STATUS_REQ_TOP 1
-#define STATUS_TOPOLOGY 2
-
-#endif
-
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h
index c1accb8cb624..31494054b213 100644
--- a/drivers/char/rio/sam.h
+++ b/drivers/char/rio/sam.h
@@ -60,15 +60,12 @@
#define RX FALSE
-typedef struct FREE_LIST FREE_LIST ;
-struct FREE_LIST {
- FREE_LIST_ptr next ;
- FREE_LIST_ptr prev ;
- } ;
+typedef struct FREE_LIST FREE_LIST;
+struct FREE_LIST {
+ FREE_LIST_ptr next;
+ FREE_LIST_ptr prev;
+};
#endif
/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/selftest.h b/drivers/char/rio/selftest.h
deleted file mode 100644
index deae48722a21..000000000000
--- a/drivers/char/rio/selftest.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-** File: selftest.h
-**
-** Author: David Dix
-**
-** Created: 15th March 1993
-**
-** Last modified: 94/06/14
-**
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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 _selftests_h_
-#define _selftests_h_
-
-/*
-** Selftest identifier...
-*/
-#define SELFTEST_MAGIC 0x5a5a
-
-/*
-** This is the structure of the packet that is sent back after each
-** selftest on a booting RTA.
-*/
-typedef struct {
- short magic; /* Identifies packet type */
- int test; /* Test number, see below */
- unsigned int result; /* Result value */
- unsigned int dataIn;
- unsigned int dataOut;
-}selftestStruct;
-
-/*
-** The different tests are identified by the following data values.
-*/
-enum test {
- TESTS_COMPLETE = 0x00,
- MEMTEST_ADDR = 0x01,
- MEMTEST_BIT = 0x02,
- MEMTEST_FILL = 0x03,
- MEMTEST_DATABUS = 0x04,
- MEMTEST_ADDRBUS = 0x05,
- CD1400_INIT = 0x10,
- CD1400_LOOP = 0x11,
- CD1400_INTERRUPT = 0x12
-};
-
-enum result {
- E_PORT = 0x10,
- E_TX = 0x11,
- E_RX = 0x12,
- E_EXCEPT = 0x13,
- E_COMPARE = 0x14,
- E_MODEM = 0x15,
- E_TIMEOUT = 0x16,
- E_INTERRUPT = 0x17
-};
-#endif /* _selftests_h_ */
diff --git a/drivers/char/rio/space.h b/drivers/char/rio/space.h
index 72398d342051..1f12690f9d1f 100644
--- a/drivers/char/rio/space.h
+++ b/drivers/char/rio/space.h
@@ -42,4 +42,4 @@ extern int rio_bases[];
extern int rio_limits[];
extern int rio_vects[];
-#endif /* __rio_space_h__ */
+#endif /* __rio_space_h__ */
diff --git a/drivers/char/rio/sysmap.h b/drivers/char/rio/sysmap.h
deleted file mode 100644
index fdc731393576..000000000000
--- a/drivers/char/rio/sysmap.h
+++ /dev/null
@@ -1,63 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* S Y S T E M M A P H E A D E R
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1" ;
-#endif
-#endif
-
-#define SYSTEM_MAP_LEN 64 /* Len of System Map array */
-
-
-typedef struct SYS_MAP SYS_MAP ;
-typedef struct SYS_MAP_LINK SYS_MAP_LINK ;
-
-struct SYS_MAP_LINK {
- short id ; /* Unit Id */
- short link ; /* Id's Link */
- short been_here ; /* Used by map_gen */
- } ;
-
-struct SYS_MAP {
- char serial_num[4] ;
- SYS_MAP_LINK link[4] ;
- } ;
-
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/timeouts.h b/drivers/char/rio/timeouts.h
deleted file mode 100644
index 11b31330c901..000000000000
--- a/drivers/char/rio/timeouts.h
+++ /dev/null
@@ -1,51 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* T I M E O U T S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_defaults_h_sccs = "@(#)timeouts.h 1.3" ;
-#endif
-#endif
-
-#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
-#define SECOND (int) 15625 /* Low priority ticks */
-
-#define TX_TIMEOUT (int) (200 * MILLISECOND)
-
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/top.h b/drivers/char/rio/top.h
index 255c40d463a6..d15a11dc4f73 100644
--- a/drivers/char/rio/top.h
+++ b/drivers/char/rio/top.h
@@ -40,10 +40,9 @@ static char *_top_h_sccs_ = "@(#)top.h 1.2";
/*
** Topology information
*/
-struct Top
-{
- uchar Unit;
- uchar Link;
+struct Top {
+ uchar Unit;
+ uchar Link;
};
-#endif /* __rio_top_h__ */
+#endif /* __rio_top_h__ */
diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h
index 2cb9dd693fa1..185b889e1510 100644
--- a/drivers/char/rio/typdef.h
+++ b/drivers/char/rio/typdef.h
@@ -45,11 +45,11 @@ static char *_typdef_h_sccs_ = "@(#)typdef.h 1.2";
** These types are ONLY to be used for refering to data structures
** on the RIO Host card!
*/
-typedef volatile unsigned char BYTE;
-typedef volatile unsigned short WORD;
-typedef volatile unsigned int DWORD;
-typedef volatile unsigned short RIOP;
-typedef volatile short NUMBER;
+typedef volatile unsigned char BYTE;
+typedef volatile unsigned short WORD;
+typedef volatile unsigned int DWORD;
+typedef volatile unsigned short RIOP;
+typedef volatile short NUMBER;
/*
@@ -59,13 +59,13 @@ typedef volatile short NUMBER;
** are here only to make the source compile.
*/
/* typedef unsigned int uint; */
-typedef unsigned long ulong_t;
-typedef unsigned short ushort_t;
-typedef unsigned char uchar_t;
-typedef unsigned char queue_t;
-typedef unsigned char mblk_t;
-typedef unsigned int paddr_t;
-typedef unsigned char uchar;
+typedef unsigned long ulong_t;
+typedef unsigned short ushort_t;
+typedef unsigned char uchar_t;
+typedef unsigned char queue_t;
+typedef unsigned char mblk_t;
+typedef unsigned int paddr_t;
+typedef unsigned char uchar;
#define TPNULL ((ushort)(0x8000))
@@ -73,10 +73,10 @@ typedef unsigned char uchar;
/*
** RIO structures defined in other include files.
*/
-typedef struct PKT PKT;
-typedef struct LPB LPB;
-typedef struct RUP RUP;
-typedef struct Port Port;
-typedef struct DpRam DpRam;
+typedef struct PKT PKT;
+typedef struct LPB LPB;
+typedef struct RUP RUP;
+typedef struct Port Port;
+typedef struct DpRam DpRam;
-#endif /* __rio_typdef_h__ */
+#endif /* __rio_typdef_h__ */
diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h
index eddf86278abc..a126c7cabac6 100644
--- a/drivers/char/rio/unixrup.h
+++ b/drivers/char/rio/unixrup.h
@@ -41,16 +41,15 @@ static char *_unixrup_h_sccs_ = "@(#)unixrup.h 1.2";
** UnixRup data structure. This contains pointers to actual RUPs on the
** host card, and all the command/boot control stuff.
*/
-struct UnixRup
-{
- struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */
- struct CmdBlk *CmdPendingP; /* The command currently being sent */
- struct RUP *RupP; /* the Rup to send it to */
- uint Id; /* Id number */
- uint BaseSysPort; /* SysPort of first tty on this RTA */
- uint ModTypes; /* Modules on this RTA */
- spinlock_t RupLock; /* Lock structure for MPX */
-/* struct lockb RupLock; */ /* Lock structure for MPX */
+struct UnixRup {
+ struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */
+ struct CmdBlk *CmdPendingP; /* The command currently being sent */
+ struct RUP *RupP; /* the Rup to send it to */
+ uint Id; /* Id number */
+ uint BaseSysPort; /* SysPort of first tty on this RTA */
+ uint ModTypes; /* Modules on this RTA */
+ spinlock_t RupLock; /* Lock structure for MPX */
+ /* struct lockb RupLock; *//* Lock structure for MPX */
};
-#endif /* __rio_unixrup_h__ */
+#endif /* __rio_unixrup_h__ */
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 55a3a0188eda..119e629656b7 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -46,6 +46,7 @@
#include <linux/major.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/tty_flip.h>
#include <asm/uaccess.h>
@@ -81,7 +82,6 @@
static struct riscom_board * IRQ_to_board[16];
static struct tty_driver *riscom_driver;
static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static unsigned long baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -107,15 +107,15 @@ static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
/* RISCom/8 I/O ports addresses (without address translation) */
static unsigned short rc_ioport[] = {
-#if 1
+#if 1
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
-#else
+#else
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
-#endif
+#endif
};
-#define RC_NIOPORT (sizeof(rc_ioport) / sizeof(rc_ioport[0]))
+#define RC_NIOPORT ARRAY_SIZE(rc_ioport)
static inline int rc_paranoia_check(struct riscom_port const * port,
@@ -354,28 +354,17 @@ static inline void rc_receive_exc(struct riscom_board const * bp)
struct riscom_port *port;
struct tty_struct *tty;
unsigned char status;
- unsigned char ch;
+ unsigned char ch, flag;
if (!(port = rc_get_port(bp, "Receive")))
return;
tty = port->tty;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- printk(KERN_WARNING "rc%d: port %d: Working around flip "
- "buffer overflow.\n",
- board_No(bp), port_No(port));
- return;
- }
#ifdef RC_REPORT_OVERRUN
status = rc_in(bp, CD180_RCSR);
- if (status & RCSR_OE) {
+ if (status & RCSR_OE)
port->overrun++;
-#if 0
- printk(KERN_ERR "rc%d: port %d: Overrun. Total %ld overruns\n",
- board_No(bp), port_No(port), port->overrun);
-#endif
- }
status &= port->mark_mask;
#else
status = rc_in(bp, CD180_RCSR) & port->mark_mask;
@@ -393,25 +382,24 @@ static inline void rc_receive_exc(struct riscom_board const * bp)
} else if (status & RCSR_BREAK) {
printk(KERN_INFO "rc%d: port %d: Handling break...\n",
board_No(bp), port_No(port));
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ flag = TTY_BREAK;
if (port->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & RCSR_PE)
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & RCSR_FE)
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ flag = TTY_FRAME;
else if (status & RCSR_OE)
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
else
- *tty->flip.flag_buf_ptr++ = 0;
+ flag = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_insert_flip_char(tty, ch, flag);
+ tty_flip_buffer_push(tty);
}
static inline void rc_receive(struct riscom_board const * bp)
@@ -432,17 +420,15 @@ static inline void rc_receive(struct riscom_board const * bp)
#endif
while (count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty_buffer_request_room(tty, 1) == 0) {
printk(KERN_WARNING "rc%d: port %d: Working around "
"flip buffer overflow.\n",
board_No(bp), port_No(port));
break;
}
- *tty->flip.char_buf_ptr++ = rc_in(bp, CD180_RDR);
- *tty->flip.flag_buf_ptr++ = 0;
- tty->flip.count++;
+ tty_insert_flip_char(tty, rc_in(bp, CD180_RDR), TTY_NORMAL);
}
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_flip_buffer_push(tty);
}
static inline void rc_transmit(struct riscom_board const * bp)
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index d3bc731fbb27..0949dcef0697 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -325,19 +325,16 @@ static void rp_do_receive(struct r_port *info,
{
unsigned int CharNStat;
int ToRecv, wRecv, space = 0, count;
- unsigned char *cbuf;
- char *fbuf;
+ unsigned char *cbuf, *chead;
+ char *fbuf, *fhead;
struct tty_ldisc *ld;
ld = tty_ldisc_ref(tty);
ToRecv = sGetRxCnt(cp);
- if (ld)
- space = ld->receive_room(tty);
+ space = tty->receive_room;
if (space > 2 * TTY_FLIPBUF_SIZE)
space = 2 * TTY_FLIPBUF_SIZE;
- cbuf = tty->flip.char_buf;
- fbuf = tty->flip.flag_buf;
count = 0;
#ifdef ROCKET_DEBUG_INTR
printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
@@ -350,9 +347,13 @@ static void rp_do_receive(struct r_port *info,
if (ToRecv > space)
ToRecv = space;
+ ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
if (ToRecv <= 0)
goto done;
+ cbuf = chead;
+ fbuf = fhead;
+
/*
* if status indicates there are errored characters in the
* FIFO, then enter status mode (a word in FIFO holds
@@ -399,7 +400,7 @@ static void rp_do_receive(struct r_port *info,
else if (CharNStat & STMRCVROVRH)
*fbuf++ = TTY_OVERRUN;
else
- *fbuf++ = 0;
+ *fbuf++ = TTY_NORMAL;
*cbuf++ = CharNStat & 0xff;
count++;
ToRecv--;
@@ -426,13 +427,13 @@ static void rp_do_receive(struct r_port *info,
sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
if (ToRecv & 1)
cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
- memset(fbuf, 0, ToRecv);
+ memset(fbuf, TTY_NORMAL, ToRecv);
cbuf += ToRecv;
fbuf += ToRecv;
count += ToRecv;
}
/* Push the data up to the tty layer */
- ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+ ld->receive_buf(tty, cbuf, fbuf, count);
done:
tty_ldisc_deref(ld);
}
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index a7f099fb7dfe..7cac6d05d723 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -46,10 +46,10 @@
* 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init
* 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
* CONFIG_HPET_EMULATE_RTC
- *
+ * 1.12ac Alan Cox: Allow read access to the day of week register
*/
-#define RTC_VERSION "1.12"
+#define RTC_VERSION "1.12ac"
#define RTC_IO_EXTENT 0x8
@@ -1250,9 +1250,9 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
/*
* Only the values that we read from the RTC are set. We leave
- * tm_wday, tm_yday and tm_isdst untouched. Even though the
- * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
- * by the RTC when initially set to a non-zero value.
+ * tm_wday, tm_yday and tm_isdst untouched. Note that while the
+ * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is
+ * only updated by the RTC when initially set to a non-zero value.
*/
spin_lock_irq(&rtc_lock);
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
@@ -1261,6 +1261,9 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
+ /* Only set from 2.6.16 onwards */
+ rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK);
+
#ifdef CONFIG_MACH_DECSTATION
real_year = CMOS_READ(RTC_DEC_YEAR);
#endif
@@ -1275,6 +1278,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
BCD_TO_BIN(rtc_tm->tm_mday);
BCD_TO_BIN(rtc_tm->tm_mon);
BCD_TO_BIN(rtc_tm->tm_year);
+ BCD_TO_BIN(rtc_tm->tm_wday);
}
#ifdef CONFIG_MACH_DECSTATION
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index 3df7a574267b..2e308657f6f6 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
@@ -33,7 +34,6 @@
#include <asm/mach/time.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-rtc.h>
/* need this for the RTC_AF definitions */
diff --git a/drivers/char/scc.h b/drivers/char/scc.h
index 51810f72f1a9..93998f5baff5 100644
--- a/drivers/char/scc.h
+++ b/drivers/char/scc.h
@@ -399,7 +399,7 @@ struct scc_port {
__asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
} while (0)
-extern unsigned char scc_shadow[2][16];
+static unsigned char scc_shadow[2][16];
/* The following functions should relax the somehow complicated
* register access of the SCC. _SCCwrite() stores all written values
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 5b187c895c18..71093a9fc462 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -275,7 +275,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
int paste_selection(struct tty_struct *tty)
{
struct vc_data *vc = (struct vc_data *)tty->driver_data;
- int pasted = 0, count;
+ int pasted = 0;
+ unsigned int count;
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
@@ -293,7 +294,7 @@ int paste_selection(struct tty_struct *tty)
continue;
}
count = sel_buffer_lth - pasted;
- count = min(count, tty->ldisc.receive_room(tty));
+ count = min(count, tty->receive_room);
tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
pasted += count;
}
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index dda30e42ec79..80a5b840e22f 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -194,11 +194,6 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
*/
struct tty_struct *tty = port->gs.tty;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return;
-
- tty->flip.count++;
-
#if 0
switch(err) {
case TTY_BREAK:
@@ -212,8 +207,7 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
}
#endif
- *tty->flip.flag_buf_ptr++ = err;
- *tty->flip.char_buf_ptr++ = ch;
+ tty_insert_flip_char(tty, ch, err);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index c2deac968bdd..037c940ac71b 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -117,7 +117,7 @@ struct cyclades_port cy_port[] = {
{-1 }, /* ttyS2 */
{-1 }, /* ttyS3 */
};
-#define NR_PORTS (sizeof(cy_port)/sizeof(struct cyclades_port))
+#define NR_PORTS ARRAY_SIZE(cy_port)
/*
* tmp_buf is used as a temporary buffer by serial_write. We need to
@@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = {
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf = 0;
-DECLARE_MUTEX(tmp_buf_sem);
/*
* This is used to look up the divisor speeds and the timeouts
@@ -422,45 +421,35 @@ cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
return IRQ_HANDLED;
}
- if (tty->flip.count < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
+ if (tty_buffer_request_room(tty, 1) != 0){
if (err & info->read_status_mask){
if(err & CyBREAK){
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_BREAK);
if (info->flags & ASYNC_SAK){
do_SAK(tty);
}
}else if(err & CyFRAME){
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_FRAME);
}else if(err & CyPARITY){
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_PARITY);
}else if(err & CyOVERRUN){
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
/*
If the flip buffer itself is
overflowing, we still loose
the next incoming character.
*/
- if(tty->flip.count < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
- }
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
+ }
/* These two conditions may imply */
/* a normal read should be done. */
/* else if(data & CyTIMEOUT) */
/* else if(data & CySPECHAR) */
}else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
}
}else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
}
}else{
/* there was a software buffer overrun
@@ -692,12 +681,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
#endif
while(char_count--){
data = base_addr[CyRDR];
- if (tty->flip.count >= TTY_FLIPBUF_SIZE){
- continue;
- }
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
#ifdef CYCLOM_16Y_HACK
udelay(10L);
#endif
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 51a07370e636..f8dd8527c6aa 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -471,7 +471,6 @@ struct sonypi_keypress {
static struct sonypi_device {
struct pci_dev *dev;
- struct platform_device *pdev;
u16 irq;
u16 bits;
u16 ioport1;
@@ -511,6 +510,11 @@ static struct sonypi_device {
#define SONYPI_ACPI_ACTIVE 0
#endif /* CONFIG_ACPI */
+#ifdef CONFIG_ACPI
+static struct acpi_device *sonypi_acpi_device;
+static int acpi_enabled;
+#endif
+
static int sonypi_ec_write(u8 addr, u8 value)
{
#ifdef CONFIG_ACPI_EC
@@ -864,6 +868,11 @@ found:
if (useinput)
sonypi_report_input_event(event);
+#ifdef CONFIG_ACPI
+ if (acpi_enabled)
+ acpi_bus_generate_event(sonypi_acpi_device, 1, event);
+#endif
+
kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
wake_up_interruptible(&sonypi_device.fifo_proc_list);
@@ -1165,45 +1174,38 @@ static int sonypi_disable(void)
return 0;
}
-#ifdef CONFIG_PM
-static int old_camera_power;
-
-static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_ACPI
+static int sonypi_acpi_add(struct acpi_device *device)
{
- old_camera_power = sonypi_device.camera_power;
- sonypi_disable();
-
+ sonypi_acpi_device = device;
+ strcpy(acpi_device_name(device), "Sony laptop hotkeys");
+ strcpy(acpi_device_class(device), "sony/hotkey");
return 0;
}
-static int sonypi_resume(struct platform_device *dev)
+static int sonypi_acpi_remove(struct acpi_device *device, int type)
{
- sonypi_enable(old_camera_power);
+ sonypi_acpi_device = NULL;
return 0;
}
-#endif
-
-static void sonypi_shutdown(struct platform_device *dev)
-{
- sonypi_disable();
-}
-static struct platform_driver sonypi_driver = {
-#ifdef CONFIG_PM
- .suspend = sonypi_suspend,
- .resume = sonypi_resume,
-#endif
- .shutdown = sonypi_shutdown,
- .driver = {
- .name = "sonypi",
+static struct acpi_driver sonypi_acpi_driver = {
+ .name = "sonypi",
+ .class = "hkey",
+ .ids = "SNY6001",
+ .ops = {
+ .add = sonypi_acpi_add,
+ .remove = sonypi_acpi_remove,
},
};
+#endif
static int __devinit sonypi_create_input_devices(void)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
int i;
+ int error;
sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
if (!jog_dev)
@@ -1219,9 +1221,8 @@ static int __devinit sonypi_create_input_devices(void)
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;
+ error = -ENOMEM;
+ goto err_free_jogdev;
}
key_dev->name = "Sony Vaio Keys";
@@ -1234,56 +1235,122 @@ static int __devinit sonypi_create_input_devices(void)
if (sonypi_inputkeys[i].inputev)
set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
- input_register_device(jog_dev);
- input_register_device(key_dev);
+ error = input_register_device(jog_dev);
+ if (error)
+ goto err_free_keydev;
+
+ error = input_register_device(key_dev);
+ if (error)
+ goto err_unregister_jogdev;
return 0;
+
+ err_unregister_jogdev:
+ input_unregister_device(jog_dev);
+ /* Set to NULL so we don't free it again below */
+ jog_dev = NULL;
+ err_free_keydev:
+ input_free_device(key_dev);
+ sonypi_device.input_key_dev = NULL;
+ err_free_jogdev:
+ input_free_device(jog_dev);
+ sonypi_device.input_jog_dev = NULL;
+
+ return error;
}
-static int __devinit sonypi_probe(void)
+static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
+ const struct sonypi_ioport_list *ioport_list)
{
- int i, ret;
- struct sonypi_ioport_list *ioport_list;
- struct sonypi_irq_list *irq_list;
- struct pci_dev *pcidev;
+ while (ioport_list->port1) {
- 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;
+ if (request_region(ioport_list->port1,
+ sonypi_device.region_size,
+ "Sony Programable I/O Device")) {
+ dev->ioport1 = ioport_list->port1;
+ dev->ioport2 = ioport_list->port2;
+ return 0;
+ }
+ ioport_list++;
+ }
- sonypi_device.dev = pcidev;
+ return -EBUSY;
+}
+
+static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
+ const struct sonypi_irq_list *irq_list)
+{
+ while (irq_list->irq) {
+
+ if (!request_irq(irq_list->irq, sonypi_irq,
+ SA_SHIRQ, "sonypi", sonypi_irq)) {
+ dev->irq = irq_list->irq;
+ dev->bits = irq_list->bits;
+ return 0;
+ }
+ irq_list++;
+ }
+
+ return -EBUSY;
+}
+
+static void __devinit sonypi_display_info(void)
+{
+ 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,
+ verbose,
+ fnkeyinit ? "on" : "off",
+ camera ? "on" : "off",
+ compat ? "on" : "off",
+ mask,
+ useinput ? "on" : "off",
+ SONYPI_ACPI_ACTIVE ? "on" : "off");
+ printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
+ sonypi_device.irq,
+ sonypi_device.ioport1, sonypi_device.ioport2);
+
+ if (minor == -1)
+ printk(KERN_INFO "sonypi: device allocated minor is %d\n",
+ sonypi_misc_device.minor);
+}
+
+static int __devinit sonypi_probe(struct platform_device *dev)
+{
+ const struct sonypi_ioport_list *ioport_list;
+ const struct sonypi_irq_list *irq_list;
+ struct pci_dev *pcidev;
+ int error;
spin_lock_init(&sonypi_device.fifo_lock);
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
&sonypi_device.fifo_lock);
if (IS_ERR(sonypi_device.fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
- ret = PTR_ERR(sonypi_device.fifo);
- goto out_fifo;
+ return PTR_ERR(sonypi_device.fifo);
}
init_waitqueue_head(&sonypi_device.fifo_proc_list);
init_MUTEX(&sonypi_device.lock);
sonypi_device.bluetooth_power = -1;
+ 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;
+
if (pcidev && pci_enable_device(pcidev)) {
printk(KERN_ERR "sonypi: pci_enable_device failed\n");
- ret = -EIO;
- goto out_pcienable;
- }
-
- if (minor != -1)
- sonypi_misc_device.minor = minor;
- if ((ret = misc_register(&sonypi_misc_device))) {
- printk(KERN_ERR "sonypi: misc_register failed\n");
- goto out_miscreg;
+ error = -EIO;
+ goto err_put_pcidev;
}
+ sonypi_device.dev = pcidev;
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
ioport_list = sonypi_type1_ioport_list;
@@ -1302,43 +1369,36 @@ static int __devinit sonypi_probe(void)
irq_list = sonypi_type3_irq_list;
}
- for (i = 0; ioport_list[i].port1; i++) {
- if (request_region(ioport_list[i].port1,
- sonypi_device.region_size,
- "Sony Programable I/O Device")) {
- /* get the ioport */
- sonypi_device.ioport1 = ioport_list[i].port1;
- sonypi_device.ioport2 = ioport_list[i].port2;
- break;
- }
- }
- if (!sonypi_device.ioport1) {
- printk(KERN_ERR "sonypi: request_region failed\n");
- ret = -ENODEV;
- goto out_reqreg;
+ error = sonypi_setup_ioports(&sonypi_device, ioport_list);
+ if (error) {
+ printk(KERN_ERR "sonypi: failed to request ioports\n");
+ goto err_disable_pcidev;
}
- for (i = 0; irq_list[i].irq; i++) {
-
- sonypi_device.irq = irq_list[i].irq;
- sonypi_device.bits = irq_list[i].bits;
-
- if (!request_irq(sonypi_device.irq, sonypi_irq,
- SA_SHIRQ, "sonypi", sonypi_irq))
- break;
+ error = sonypi_setup_irq(&sonypi_device, irq_list);
+ if (error) {
+ printk(KERN_ERR "sonypi: request_irq failed\n");
+ goto err_free_ioports;
}
- if (!irq_list[i].irq) {
- printk(KERN_ERR "sonypi: request_irq failed\n");
- ret = -ENODEV;
- goto out_reqirq;
+ if (minor != -1)
+ sonypi_misc_device.minor = minor;
+ error = misc_register(&sonypi_misc_device);
+ if (error) {
+ printk(KERN_ERR "sonypi: misc_register failed\n");
+ goto err_free_irq;
}
+ sonypi_display_info();
+
if (useinput) {
- ret = sonypi_create_input_devices();
- if (ret)
- goto out_inputdevices;
+ error = sonypi_create_input_devices();
+ if (error) {
+ printk(KERN_ERR
+ "sonypi: failed to create input devices\n");
+ goto err_miscdev_unregister;
+ }
spin_lock_init(&sonypi_device.input_fifo_lock);
sonypi_device.input_fifo =
@@ -1346,91 +1406,104 @@ static int __devinit sonypi_probe(void)
&sonypi_device.input_fifo_lock);
if (IS_ERR(sonypi_device.input_fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
- ret = PTR_ERR(sonypi_device.input_fifo);
- goto out_infifo;
+ error = PTR_ERR(sonypi_device.input_fifo);
+ goto err_inpdev_unregister;
}
INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL);
}
- sonypi_device.pdev = platform_device_register_simple("sonypi", -1,
- NULL, 0);
- if (IS_ERR(sonypi_device.pdev)) {
- ret = PTR_ERR(sonypi_device.pdev);
- goto out_platformdev;
- }
-
sonypi_enable(0);
- printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
- "v%s.\n", SONYPI_DRIVER_VERSION);
- 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,
- verbose,
- fnkeyinit ? "on" : "off",
- camera ? "on" : "off",
- compat ? "on" : "off",
- mask,
- useinput ? "on" : "off",
- SONYPI_ACPI_ACTIVE ? "on" : "off");
- printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
- sonypi_device.irq,
- sonypi_device.ioport1, sonypi_device.ioport2);
-
- if (minor == -1)
- printk(KERN_INFO "sonypi: device allocated minor is %d\n",
- sonypi_misc_device.minor);
-
return 0;
-out_platformdev:
- kfifo_free(sonypi_device.input_fifo);
-out_infifo:
+ err_inpdev_unregister:
input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(sonypi_device.input_jog_dev);
-out_inputdevices:
+ err_miscdev_unregister:
+ misc_deregister(&sonypi_misc_device);
+ err_free_irq:
free_irq(sonypi_device.irq, sonypi_irq);
-out_reqirq:
+ err_free_ioports:
release_region(sonypi_device.ioport1, sonypi_device.region_size);
-out_reqreg:
- misc_deregister(&sonypi_misc_device);
-out_miscreg:
+ err_disable_pcidev:
if (pcidev)
pci_disable_device(pcidev);
-out_pcienable:
+ err_put_pcidev:
+ pci_dev_put(pcidev);
kfifo_free(sonypi_device.fifo);
-out_fifo:
- pci_dev_put(sonypi_device.dev);
- return ret;
+
+ return error;
}
-static void __devexit sonypi_remove(void)
+static int __devexit sonypi_remove(struct platform_device *dev)
{
sonypi_disable();
synchronize_sched(); /* Allow sonypi interrupt to complete. */
flush_scheduled_work();
- platform_device_unregister(sonypi_device.pdev);
-
if (useinput) {
input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(sonypi_device.input_jog_dev);
kfifo_free(sonypi_device.input_fifo);
}
+ misc_deregister(&sonypi_misc_device);
+
free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size);
- misc_deregister(&sonypi_misc_device);
- if (sonypi_device.dev)
+
+ if (sonypi_device.dev) {
pci_disable_device(sonypi_device.dev);
+ pci_dev_put(sonypi_device.dev);
+ }
+
kfifo_free(sonypi_device.fifo);
- pci_dev_put(sonypi_device.dev);
- printk(KERN_INFO "sonypi: removed.\n");
+
+ return 0;
}
+#ifdef CONFIG_PM
+static int old_camera_power;
+
+static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+{
+ old_camera_power = sonypi_device.camera_power;
+ sonypi_disable();
+
+ return 0;
+}
+
+static int sonypi_resume(struct platform_device *dev)
+{
+ sonypi_enable(old_camera_power);
+ return 0;
+}
+#else
+#define sonypi_suspend NULL
+#define sonypi_resume NULL
+#endif
+
+static void sonypi_shutdown(struct platform_device *dev)
+{
+ sonypi_disable();
+}
+
+static struct platform_driver sonypi_driver = {
+ .driver = {
+ .name = "sonypi",
+ .owner = THIS_MODULE,
+ },
+ .probe = sonypi_probe,
+ .remove = __devexit_p(sonypi_remove),
+ .shutdown = sonypi_shutdown,
+ .suspend = sonypi_suspend,
+ .resume = sonypi_resume,
+};
+
+static struct platform_device *sonypi_platform_device;
+
static struct dmi_system_id __initdata sonypi_dmi_table[] = {
{
.ident = "Sony Vaio",
@@ -1451,26 +1524,52 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = {
static int __init sonypi_init(void)
{
- int ret;
+ int error;
+
+ printk(KERN_INFO
+ "sonypi: Sony Programmable I/O Controller Driver v%s.\n",
+ SONYPI_DRIVER_VERSION);
if (!dmi_check_system(sonypi_dmi_table))
return -ENODEV;
- ret = platform_driver_register(&sonypi_driver);
- if (ret)
- return ret;
+ error = platform_driver_register(&sonypi_driver);
+ if (error)
+ return error;
- ret = sonypi_probe();
- if (ret)
- platform_driver_unregister(&sonypi_driver);
+ sonypi_platform_device = platform_device_alloc("sonypi", -1);
+ if (!sonypi_platform_device) {
+ error = -ENOMEM;
+ goto err_driver_unregister;
+ }
- return ret;
+ error = platform_device_add(sonypi_platform_device);
+ if (error)
+ goto err_free_device;
+
+#ifdef CONFIG_ACPI
+ if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0)
+ acpi_enabled = 1;
+#endif
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(sonypi_platform_device);
+ err_driver_unregister:
+ platform_driver_unregister(&sonypi_driver);
+ return error;
}
static void __exit sonypi_exit(void)
{
+#ifdef CONFIG_ACPI
+ if (acpi_enabled)
+ acpi_bus_unregister_driver(&sonypi_acpi_driver);
+#endif
+ platform_device_unregister(sonypi_platform_device);
platform_driver_unregister(&sonypi_driver);
- sonypi_remove();
+ printk(KERN_INFO "sonypi: removed.\n");
}
module_init(sonypi_init);
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 0bbfce43031c..5343e9fc6ab7 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -85,6 +85,7 @@
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/mm.h>
#include <linux/serial.h>
#include <linux/fcntl.h>
@@ -183,7 +184,6 @@ static int sx_poll = HZ;
static struct tty_driver *specialix_driver;
static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static unsigned long baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -665,7 +665,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
struct specialix_port *port;
struct tty_struct *tty;
unsigned char status;
- unsigned char ch;
+ unsigned char ch, flag;
func_enter();
@@ -676,8 +676,6 @@ static inline void sx_receive_exc(struct specialix_board * bp)
return;
}
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);
@@ -691,7 +689,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
/* This flip buffer check needs to be below the reading of the
status register to reset the chip's IRQ.... */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty_buffer_request_room(tty, 1) == 0) {
dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
board_No(bp), port_No(port));
func_exit();
@@ -712,26 +710,24 @@ static inline void sx_receive_exc(struct specialix_board * bp)
} 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;
+ flag = TTY_BREAK;
if (port->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & RCSR_PE)
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & RCSR_FE)
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ flag = TTY_FRAME;
else if (status & RCSR_OE)
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = 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);
+ flag = TTY_NORMAL;
+ if(tty_insert_flip_char(tty, ch, flag))
+ tty_flip_buffer_push(tty);
func_exit();
}
@@ -755,18 +751,11 @@ static inline void sx_receive(struct specialix_board * bp)
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",
- board_No(bp), port_No(port));
- break;
- }
- *tty->flip.char_buf_ptr++ = sx_in(bp, CD186x_RDR);
- *tty->flip.flag_buf_ptr++ = 0;
- tty->flip.count++;
- }
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_buffer_request_room(tty, count);
+ while (count--)
+ tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
+ tty_flip_buffer_push(tty);
func_exit();
}
@@ -2566,8 +2555,6 @@ static int __init specialix_init_module(void)
func_enter();
- init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */
-
if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
for(i = 0; i < SX_NBOARD; i++) {
sx_board[i].base = iobase[i];
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 95af2a941595..bdaab6992109 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -103,7 +103,7 @@ static stlconf_t stl_brdconf[] = {
/*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
};
-static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
+static int stl_nrbrds = ARRAY_SIZE(stl_brdconf);
/*****************************************************************************/
@@ -424,7 +424,7 @@ static stlpcibrd_t stl_pcibrds[] = {
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
};
-static int stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t);
+static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
#endif
@@ -704,7 +704,7 @@ static unsigned int sc26198_baudtable[] = {
230400, 460800, 921600
};
-#define SC26198_NRBAUDS (sizeof(sc26198_baudtable) / sizeof(unsigned int))
+#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
/*****************************************************************************/
@@ -738,7 +738,7 @@ static int __init stallion_module_init(void)
stl_init();
restore_flags(flags);
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -889,7 +889,7 @@ static unsigned long stl_atol(char *str)
}
val = (val * base) + c;
}
- return(val);
+ return val;
}
/*****************************************************************************/
@@ -901,26 +901,25 @@ static unsigned long stl_atol(char *str)
static int stl_parsebrd(stlconf_t *confp, char **argp)
{
char *sp;
- int nrbrdnames, i;
+ int i;
#ifdef DEBUG
printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
#endif
if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
- return(0);
+ return 0;
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
*sp = TOLOWER(*sp);
- nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);
- for (i = 0; (i < nrbrdnames); i++) {
+ for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
break;
}
- if (i >= nrbrdnames) {
+ if (i == ARRAY_SIZE(stl_brdstr)) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
- return(0);
+ return 0;
}
confp->brdtype = stl_brdstr[i].type;
@@ -936,7 +935,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
}
if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
confp->irq = stl_atol(argp[i]);
- return(1);
+ return 1;
}
/*****************************************************************************/
@@ -947,7 +946,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
static void *stl_memalloc(int len)
{
- return((void *) kmalloc(len, GFP_KERNEL));
+ return (void *) kmalloc(len, GFP_KERNEL);
}
/*****************************************************************************/
@@ -964,12 +963,12 @@ static stlbrd_t *stl_allocbrd(void)
if (brdp == (stlbrd_t *) NULL) {
printk("STALLION: failed to allocate memory (size=%d)\n",
sizeof(stlbrd_t));
- return((stlbrd_t *) NULL);
+ return (stlbrd_t *) NULL;
}
memset(brdp, 0, sizeof(stlbrd_t));
brdp->magic = STL_BOARDMAGIC;
- return(brdp);
+ return brdp;
}
/*****************************************************************************/
@@ -989,10 +988,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
minordev = tty->index;
brdnr = MINOR2BRD(minordev);
if (brdnr >= stl_nrbrds)
- return(-ENODEV);
+ return -ENODEV;
brdp = stl_brds[brdnr];
if (brdp == (stlbrd_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
minordev = MINOR2PORT(minordev);
for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
if (brdp->panels[panelnr] == (stlpanel_t *) NULL)
@@ -1004,11 +1003,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
minordev -= brdp->panels[panelnr]->nrports;
}
if (portnr < 0)
- return(-ENODEV);
+ return -ENODEV;
portp = brdp->panels[panelnr]->ports[portnr];
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
/*
* On the first open of the device setup the port hardware, and
@@ -1022,7 +1021,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
if (portp->tx.buf == (char *) NULL) {
portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE);
if (portp->tx.buf == (char *) NULL)
- return(-ENOMEM);
+ return -ENOMEM;
portp->tx.head = portp->tx.buf;
portp->tx.tail = portp->tx.buf;
}
@@ -1044,8 +1043,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
if (portp->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&portp->close_wait);
if (portp->flags & ASYNC_HUP_NOTIFY)
- return(-EAGAIN);
- return(-ERESTARTSYS);
+ return -EAGAIN;
+ return -ERESTARTSYS;
}
/*
@@ -1055,11 +1054,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
*/
if (!(filp->f_flags & O_NONBLOCK)) {
if ((rc = stl_waitcarrier(portp, filp)) != 0)
- return(rc);
+ return rc;
}
portp->flags |= ASYNC_NORMAL_ACTIVE;
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -1116,7 +1115,7 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
portp->openwaitcnt--;
restore_flags(flags);
- return(rc);
+ return rc;
}
/*****************************************************************************/
@@ -1212,12 +1211,12 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
if ((tty == (struct tty_struct *) NULL) ||
(stl_tmpwritebuf == (char *) NULL))
- return(0);
+ return 0;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (portp->tx.buf == (char *) NULL)
- return(0);
+ return 0;
/*
* If copying direct from user space we must cater for page faults,
@@ -1256,7 +1255,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
clear_bit(ASYI_TXLOW, &portp->istate);
stl_startrxtx(portp, -1, 1);
- return(count);
+ return count;
}
/*****************************************************************************/
@@ -1337,16 +1336,16 @@ static int stl_writeroom(struct tty_struct *tty)
#endif
if (tty == (struct tty_struct *) NULL)
- return(0);
+ return 0;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (portp->tx.buf == (char *) NULL)
- return(0);
+ return 0;
head = portp->tx.head;
tail = portp->tx.tail;
- return((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
+ return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
}
/*****************************************************************************/
@@ -1371,19 +1370,19 @@ static int stl_charsinbuffer(struct tty_struct *tty)
#endif
if (tty == (struct tty_struct *) NULL)
- return(0);
+ return 0;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (portp->tx.buf == (char *) NULL)
- return(0);
+ return 0;
head = portp->tx.head;
tail = portp->tx.tail;
size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
size = 1;
- return(size);
+ return size;
}
/*****************************************************************************/
@@ -1448,7 +1447,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
(sio.close_delay != portp->close_delay) ||
((sio.flags & ~ASYNC_USR_MASK) !=
(portp->flags & ~ASYNC_USR_MASK)))
- return(-EPERM);
+ return -EPERM;
}
portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
@@ -1458,7 +1457,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
portp->closing_wait = sio.closing_wait;
portp->custom_divisor = sio.custom_divisor;
stl_setport(portp, portp->tty->termios);
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -1468,12 +1467,12 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
stlport_t *portp;
if (tty == (struct tty_struct *) NULL)
- return(-ENODEV);
+ return -ENODEV;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
- return(-EIO);
+ return -EIO;
return stl_getsignals(portp);
}
@@ -1485,12 +1484,12 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
int rts = -1, dtr = -1;
if (tty == (struct tty_struct *) NULL)
- return(-ENODEV);
+ return -ENODEV;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
- return(-EIO);
+ return -EIO;
if (set & TIOCM_RTS)
rts = 1;
@@ -1518,15 +1517,15 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
#endif
if (tty == (struct tty_struct *) NULL)
- return(-ENODEV);
+ return -ENODEV;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
if (tty->flags & (1 << TTY_IO_ERROR))
- return(-EIO);
+ return -EIO;
}
rc = 0;
@@ -1567,7 +1566,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
break;
}
- return(rc);
+ return rc;
}
/*****************************************************************************/
@@ -1873,7 +1872,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
pos[(MAXLINE - 2)] = '+';
pos[(MAXLINE - 1)] = '\n';
- return(MAXLINE);
+ return MAXLINE;
}
/*****************************************************************************/
@@ -1958,7 +1957,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
stl_readdone:
*start = page;
- return(pos - page);
+ return (pos - page);
}
/*****************************************************************************/
@@ -2350,7 +2349,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
} else {
rc = 0;
}
- return(rc);
+ return rc;
}
/*****************************************************************************/
@@ -2902,7 +2901,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
if (portp->tty != (struct tty_struct *) NULL) {
if (portp->tty->driver_data == portp) {
portp->stats.ttystate = portp->tty->flags;
- portp->stats.rxbuffered = portp->tty->flip.count;
+ /* No longer available as a statistic */
+ portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
if (portp->tty->termios != (struct termios *) NULL) {
portp->stats.cflags = portp->tty->termios->c_cflag;
portp->stats.iflags = portp->tty->termios->c_iflag;
@@ -3116,7 +3116,7 @@ static int __init stl_init(void)
return -1;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -3132,7 +3132,7 @@ static int __init stl_init(void)
static int stl_cd1400getreg(stlport_t *portp, int regnr)
{
outb((regnr + portp->uartaddr), portp->ioaddr);
- return(inb(portp->ioaddr + EREG_DATA));
+ return inb(portp->ioaddr + EREG_DATA);
}
static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
@@ -3146,9 +3146,9 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
outb((regnr + portp->uartaddr), portp->ioaddr);
if (inb(portp->ioaddr + EREG_DATA) != value) {
outb(value, portp->ioaddr + EREG_DATA);
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -3206,7 +3206,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
}
BRDDISABLE(panelp->brdnr);
- return(chipmask);
+ return chipmask;
}
/*****************************************************************************/
@@ -3557,7 +3557,7 @@ static int stl_cd1400getsignals(stlport_t *portp)
#else
sigs |= TIOCM_DSR;
#endif
- return(sigs);
+ return sigs;
}
/*****************************************************************************/
@@ -3830,9 +3830,9 @@ static int stl_cd1400datastate(stlport_t *portp)
#endif
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
- return(test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0);
+ return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
}
/*****************************************************************************/
@@ -3912,20 +3912,20 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
outb((SRER + portp->uartaddr), ioaddr);
outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
(ioaddr + EREG_DATA));
- return(1);
+ return 1;
} else if (portp->brklen > 1) {
outb((TDR + portp->uartaddr), ioaddr);
outb(ETC_CMD, (ioaddr + EREG_DATA));
outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
portp->brklen = -1;
- return(1);
+ return 1;
} else {
outb((COR2 + portp->uartaddr), ioaddr);
outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
(ioaddr + EREG_DATA));
portp->brklen = 0;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -4046,9 +4046,7 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
outb((RDCR + portp->uartaddr), ioaddr);
len = inb(ioaddr + EREG_DATA);
- if ((tty == (struct tty_struct *) NULL) ||
- (tty->flip.char_buf_ptr == (char *) NULL) ||
- ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+ if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
len = MIN(len, sizeof(stl_unwanted));
outb((RDSR + portp->uartaddr), ioaddr);
insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
@@ -4057,12 +4055,10 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
} else {
len = MIN(len, buflen);
if (len > 0) {
+ unsigned char *ptr;
outb((RDSR + portp->uartaddr), ioaddr);
- insb((ioaddr + EREG_DATA), tty->flip.char_buf_ptr, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.count += len;
+ tty_prepare_flip_string(tty, &ptr, len);
+ insb((ioaddr + EREG_DATA), ptr, len);
tty_schedule_flip(tty);
portp->stats.rxtotal += len;
}
@@ -4086,8 +4082,7 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
portp->stats.txxoff++;
goto stl_rxalldone;
}
- if ((tty != (struct tty_struct *) NULL) &&
- ((portp->rxignoremsk & status) == 0)) {
+ if (tty != NULL && (portp->rxignoremsk & status) == 0) {
if (portp->rxmarkmsk & status) {
if (status & ST_BREAK) {
status = TTY_BREAK;
@@ -4107,14 +4102,8 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
} else {
status = 0;
}
- if (tty->flip.char_buf_ptr != (char *) NULL) {
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr++ = status;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- }
- tty_schedule_flip(tty);
- }
+ tty_insert_flip_char(tty, ch, status);
+ tty_schedule_flip(tty);
}
} else {
printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
@@ -4177,7 +4166,7 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
static int stl_sc26198getreg(stlport_t *portp, int regnr)
{
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
- return(inb(portp->ioaddr + XP_DATA));
+ return inb(portp->ioaddr + XP_DATA);
}
static void stl_sc26198setreg(stlport_t *portp, int regnr, int value)
@@ -4191,9 +4180,9 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
if (inb(portp->ioaddr + XP_DATA) != value) {
outb(value, (portp->ioaddr + XP_DATA));
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -4205,7 +4194,7 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
static int stl_sc26198getglobreg(stlport_t *portp, int regnr)
{
outb(regnr, (portp->ioaddr + XP_ADDR));
- return(inb(portp->ioaddr + XP_DATA));
+ return inb(portp->ioaddr + XP_DATA);
}
#if 0
@@ -4263,7 +4252,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
}
BRDDISABLE(panelp->brdnr);
- return(chipmask);
+ return chipmask;
}
/*****************************************************************************/
@@ -4557,7 +4546,7 @@ static int stl_sc26198getsignals(stlport_t *portp)
sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
sigs |= TIOCM_DSR;
- return(sigs);
+ return sigs;
}
/*****************************************************************************/
@@ -4839,9 +4828,9 @@ static int stl_sc26198datastate(stlport_t *portp)
#endif
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (test_bit(ASYI_TXBUSY, &portp->istate))
- return(1);
+ return 1;
save_flags(flags);
cli();
@@ -4850,7 +4839,7 @@ static int stl_sc26198datastate(stlport_t *portp)
BRDDISABLE(portp->brdnr);
restore_flags(flags);
- return((sr & SR_TXEMPTY) ? 0 : 1);
+ return (sr & SR_TXEMPTY) ? 0 : 1;
}
/*****************************************************************************/
@@ -5013,9 +5002,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
len = inb(ioaddr + XP_DATA) + 1;
if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
- if ((tty == (struct tty_struct *) NULL) ||
- (tty->flip.char_buf_ptr == (char *) NULL) ||
- ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+ if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
len = MIN(len, sizeof(stl_unwanted));
outb(GRXFIFO, (ioaddr + XP_ADDR));
insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
@@ -5024,12 +5011,10 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
} else {
len = MIN(len, buflen);
if (len > 0) {
+ unsigned char *ptr;
outb(GRXFIFO, (ioaddr + XP_ADDR));
- insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.count += len;
+ tty_prepare_flip_string(tty, &ptr, len);
+ insb((ioaddr + XP_DATA), ptr, len);
tty_schedule_flip(tty);
portp->stats.rxtotal += len;
}
@@ -5097,14 +5082,8 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
status = 0;
}
- if (tty->flip.char_buf_ptr != (char *) NULL) {
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr++ = status;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- }
- tty_schedule_flip(tty);
- }
+ tty_insert_flip_char(tty, ch, status);
+ tty_schedule_flip(tty);
if (status == 0)
portp->stats.rxtotal++;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 3ad758a9a1dc..64bf89cb574f 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -345,9 +345,9 @@ static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
0xc8000, 0xd8000, 0xe8000, 0xa0000};
static int si1_probe_addrs[]= { 0xd0000};
-#define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
-#define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
-#define NR_SI1_ADDRS (sizeof(si1_probe_addrs)/sizeof (int))
+#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
+#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
+#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
/* Set the mask to all-ones. This alas, only supports 32 interrupts.
@@ -1085,6 +1085,7 @@ static inline void sx_receive_chars (struct sx_port *port)
int rx_op;
struct tty_struct *tty;
int copied=0;
+ unsigned char *rp;
func_enter2 ();
tty = port->gs.tty;
@@ -1095,8 +1096,8 @@ static inline void sx_receive_chars (struct sx_port *port)
sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
/* Don't copy more bytes than there is room for in the buffer */
- if (tty->flip.count + c > TTY_FLIPBUF_SIZE)
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+ c = tty_prepare_flip_string(tty, &rp, c);
sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
@@ -1111,14 +1112,8 @@ static inline void sx_receive_chars (struct sx_port *port)
sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c,
read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op),
CHAN_OFFSET(port, hi_rxbuf));
- memcpy_fromio (tty->flip.char_buf_ptr,
+ memcpy_fromio (rp,
port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c);
- memset(tty->flip.flag_buf_ptr, TTY_NORMAL, c);
-
- /* Update the kernel buffer end */
- tty->flip.count += c;
- tty->flip.char_buf_ptr += c;
- tty->flip.flag_buf_ptr += c;
/* This one last. ( Not essential.)
It allows the card to start putting more data into the buffer!
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 62aa0e534a6d..ede688a4e141 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void)
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static inline int mgsl_paranoia_check(struct mgsl_struct *info,
char *name, const char *routine)
@@ -1467,6 +1466,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
{
int Fifocount;
u16 status;
+ int work = 0;
unsigned char DataByte;
struct tty_struct *tty = info->tty;
struct mgsl_icount *icount = &info->icount;
@@ -1487,6 +1487,8 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
/* flush the receive FIFO */
while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
+ int flag;
+
/* read one byte from RxFIFO */
outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
info->io_base + CCAR );
@@ -1498,13 +1500,9 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = DataByte;
icount->rx++;
- *tty->flip.flag_buf_ptr = 0;
+ flag = 0;
if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
printk("rxerr=%04X\n",status);
@@ -1530,41 +1528,31 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
status &= info->read_status_mask;
if (status & RXSTATUS_BREAK_RECEIVED) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & RXSTATUS_PARITY_ERROR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & RXSTATUS_FRAMING_ERROR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (status & RXSTATUS_OVERRUN) {
- /* Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
- }
+ flag = TTY_FRAME;
} /* end of if (error) */
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, DataByte, flag);
+ if (status & RXSTATUS_OVERRUN) {
+ /* Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
}
if ( debug_level >= DEBUG_LEVEL_ISR ) {
- printk("%s(%d):mgsl_isr_receive_data flip count=%d\n",
- __FILE__,__LINE__,tty->flip.count);
printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
__FILE__,__LINE__,icount->rx,icount->brk,
icount->parity,icount->frame,icount->overrun);
}
- if ( tty->flip.count )
+ if(work)
tty_flip_buffer_push(tty);
}
@@ -7058,7 +7046,7 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
{
static unsigned short BitPatterns[] =
{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
- static unsigned int Patterncount = sizeof(BitPatterns)/sizeof(unsigned short);
+ static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
unsigned int i;
BOOLEAN rc = TRUE;
unsigned long flags;
@@ -7501,9 +7489,9 @@ static int mgsl_adapter_test( struct mgsl_struct *info )
*/
static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
{
- static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa,
- 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
- unsigned long Patterncount = sizeof(BitPatterns)/sizeof(unsigned long);
+ static unsigned long BitPatterns[] =
+ { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+ unsigned long Patterncount = ARRAY_SIZE(BitPatterns);
unsigned long i;
unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
unsigned long * TestAddr;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
new file mode 100644
index 000000000000..a85a60a93deb
--- /dev/null
+++ b/drivers/char/synclink_gt.c
@@ -0,0 +1,4491 @@
+/*
+ * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $
+ *
+ * Device driver for Microgate SyncLink GT serial adapters.
+ *
+ * written by Paul Fulghum for Microgate Corporation
+ * paulkf@microgate.com
+ *
+ * Microgate and SyncLink are trademarks of Microgate Corporation
+ *
+ * This code is released under the GNU General Public License (GPL)
+ *
+ * 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.
+ */
+
+/*
+ * DEBUG OUTPUT DEFINITIONS
+ *
+ * uncomment lines below to enable specific types of debug output
+ *
+ * DBGINFO information - most verbose output
+ * DBGERR serious errors
+ * DBGBH bottom half service routine debugging
+ * DBGISR interrupt service routine debugging
+ * DBGDATA output receive and transmit data
+ * DBGTBUF output transmit DMA buffers and registers
+ * DBGRBUF output receive DMA buffers and registers
+ */
+
+#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt
+#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt
+#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
+#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
+#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
+//#define DBGTBUF(info) dump_tbufs(info)
+//#define DBGRBUF(info) dump_rbufs(info)
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/termios.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/hdlc.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+
+#include "linux/synclink.h"
+
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
+#endif
+
+/*
+ * module identification
+ */
+static char *driver_name = "SyncLink GT";
+static char *driver_version = "$Revision: 4.22 $";
+static char *tty_driver_name = "synclink_gt";
+static char *tty_dev_prefix = "ttySLG";
+MODULE_LICENSE("GPL");
+#define MGSL_MAGIC 0x5401
+#define MAX_DEVICES 12
+
+static struct pci_device_id pci_table[] = {
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,}, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_table);
+
+static int init_one(struct pci_dev *dev,const struct pci_device_id *ent);
+static void remove_one(struct pci_dev *dev);
+static struct pci_driver pci_driver = {
+ .name = "synclink_gt",
+ .id_table = pci_table,
+ .probe = init_one,
+ .remove = __devexit_p(remove_one),
+};
+
+static int pci_registered;
+
+/*
+ * module configuration and status
+ */
+static struct slgt_info *slgt_device_list;
+static int slgt_device_count;
+
+static int ttymajor;
+static int debug_level;
+static int maxframe[MAX_DEVICES];
+static int dosyncppp[MAX_DEVICES];
+
+module_param(ttymajor, int, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+module_param_array(dosyncppp, int, NULL, 0);
+
+MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned");
+MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail");
+MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
+MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable");
+
+/*
+ * tty support and callbacks
+ */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+static struct tty_driver *serial_driver;
+
+static int open(struct tty_struct *tty, struct file * filp);
+static void close(struct tty_struct *tty, struct file * filp);
+static void hangup(struct tty_struct *tty);
+static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+
+static int write(struct tty_struct *tty, const unsigned char *buf, int count);
+static void put_char(struct tty_struct *tty, unsigned char ch);
+static void send_xchar(struct tty_struct *tty, char ch);
+static void wait_until_sent(struct tty_struct *tty, int timeout);
+static int write_room(struct tty_struct *tty);
+static void flush_chars(struct tty_struct *tty);
+static void flush_buffer(struct tty_struct *tty);
+static void tx_hold(struct tty_struct *tty);
+static void tx_release(struct tty_struct *tty);
+
+static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
+static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data);
+static int chars_in_buffer(struct tty_struct *tty);
+static void throttle(struct tty_struct * tty);
+static void unthrottle(struct tty_struct * tty);
+static void set_break(struct tty_struct *tty, int break_state);
+
+/*
+ * generic HDLC support and callbacks
+ */
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct slgt_info *info);
+static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
+static int hdlcdev_init(struct slgt_info *info);
+static void hdlcdev_exit(struct slgt_info *info);
+#endif
+
+
+/*
+ * device specific structures, macros and functions
+ */
+
+#define SLGT_MAX_PORTS 4
+#define SLGT_REG_SIZE 256
+
+/*
+ * DMA buffer descriptor and access macros
+ */
+struct slgt_desc
+{
+ unsigned short count;
+ unsigned short status;
+ unsigned int pbuf; /* physical address of data buffer */
+ unsigned int next; /* physical address of next descriptor */
+
+ /* driver book keeping */
+ char *buf; /* virtual address of data buffer */
+ unsigned int pdesc; /* physical address of this descriptor */
+ dma_addr_t buf_dma_addr;
+};
+
+#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
+#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b))
+#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b))
+#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
+#define desc_count(a) (le16_to_cpu((a).count))
+#define desc_status(a) (le16_to_cpu((a).status))
+#define desc_complete(a) (le16_to_cpu((a).status) & BIT15)
+#define desc_eof(a) (le16_to_cpu((a).status) & BIT2)
+#define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1)
+#define desc_abort(a) (le16_to_cpu((a).status) & BIT0)
+#define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3)
+
+struct _input_signal_events {
+ int ri_up;
+ int ri_down;
+ int dsr_up;
+ int dsr_down;
+ int dcd_up;
+ int dcd_down;
+ int cts_up;
+ int cts_down;
+};
+
+/*
+ * device instance data structure
+ */
+struct slgt_info {
+ void *if_ptr; /* General purpose pointer (used by SPPP) */
+
+ struct slgt_info *next_device; /* device list link */
+
+ int magic;
+ int flags;
+
+ char device_name[25];
+ struct pci_dev *pdev;
+
+ int port_count; /* count of ports on adapter */
+ int adapter_num; /* adapter instance number */
+ int port_num; /* port instance number */
+
+ /* array of pointers to port contexts on this adapter */
+ struct slgt_info *port_array[SLGT_MAX_PORTS];
+
+ int count; /* count of opens */
+ int line; /* tty line instance number */
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+
+ struct mgsl_icount icount;
+
+ struct tty_struct *tty;
+ int timeout;
+ int x_char; /* xon/xoff character */
+ int blocked_open; /* # of blocked opens */
+ unsigned int read_status_mask;
+ unsigned int ignore_status_mask;
+
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ wait_queue_head_t status_event_wait_q;
+ wait_queue_head_t event_wait_q;
+ struct timer_list tx_timer;
+ struct timer_list rx_timer;
+
+ spinlock_t lock; /* spinlock for synchronizing with ISR */
+
+ struct work_struct task;
+ u32 pending_bh;
+ int bh_requested;
+ int bh_running;
+
+ int isr_overflow;
+ int irq_requested; /* nonzero if IRQ requested */
+ int irq_occurred; /* for diagnostics use */
+
+ /* device configuration */
+
+ unsigned int bus_type;
+ unsigned int irq_level;
+ unsigned long irq_flags;
+
+ unsigned char __iomem * reg_addr; /* memory mapped registers address */
+ u32 phys_reg_addr;
+ int reg_addr_requested;
+
+ MGSL_PARAMS params; /* communications parameters */
+ u32 idle_mode;
+ u32 max_frame_size; /* as set by device config */
+
+ unsigned int raw_rx_size;
+ unsigned int if_mode;
+
+ /* device status */
+
+ int rx_enabled;
+ int rx_restart;
+
+ int tx_enabled;
+ int tx_active;
+
+ unsigned char signals; /* serial signal states */
+ unsigned int init_error; /* initialization error */
+
+ unsigned char *tx_buf;
+ int tx_count;
+
+ char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+ char char_buf[MAX_ASYNC_BUFFER_SIZE];
+ BOOLEAN drop_rts_on_tx_done;
+ struct _input_signal_events input_signal_events;
+
+ int dcd_chkcount; /* check counts to prevent */
+ int cts_chkcount; /* too many IRQs if a signal */
+ int dsr_chkcount; /* is floating */
+ int ri_chkcount;
+
+ char *bufs; /* virtual address of DMA buffer lists */
+ dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */
+
+ unsigned int rbuf_count;
+ struct slgt_desc *rbufs;
+ unsigned int rbuf_current;
+ unsigned int rbuf_index;
+
+ unsigned int tbuf_count;
+ struct slgt_desc *tbufs;
+ unsigned int tbuf_current;
+ unsigned int tbuf_start;
+
+ unsigned char *tmp_rbuf;
+ unsigned int tmp_rbuf_count;
+
+ /* SPPP/Cisco HDLC device parts */
+
+ int netcount;
+ int dosyncppp;
+ spinlock_t netlock;
+#ifdef CONFIG_HDLC
+ struct net_device *netdev;
+#endif
+
+};
+
+static MGSL_PARAMS default_params = {
+ .mode = MGSL_MODE_HDLC,
+ .loopback = 0,
+ .flags = HDLC_FLAG_UNDERRUN_ABORT15,
+ .encoding = HDLC_ENCODING_NRZI_SPACE,
+ .clock_speed = 0,
+ .addr_filter = 0xff,
+ .crc_type = HDLC_CRC_16_CCITT,
+ .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS,
+ .preamble = HDLC_PREAMBLE_PATTERN_NONE,
+ .data_rate = 9600,
+ .data_bits = 8,
+ .stop_bits = 1,
+ .parity = ASYNC_PARITY_NONE
+};
+
+
+#define BH_RECEIVE 1
+#define BH_TRANSMIT 2
+#define BH_STATUS 4
+#define IO_PIN_SHUTDOWN_LIMIT 100
+
+#define DMABUFSIZE 256
+#define DESC_LIST_SIZE 4096
+
+#define MASK_PARITY BIT1
+#define MASK_FRAMING BIT2
+#define MASK_BREAK BIT3
+#define MASK_OVERRUN BIT4
+
+#define GSR 0x00 /* global status */
+#define TDR 0x80 /* tx data */
+#define RDR 0x80 /* rx data */
+#define TCR 0x82 /* tx control */
+#define TIR 0x84 /* tx idle */
+#define TPR 0x85 /* tx preamble */
+#define RCR 0x86 /* rx control */
+#define VCR 0x88 /* V.24 control */
+#define CCR 0x89 /* clock control */
+#define BDR 0x8a /* baud divisor */
+#define SCR 0x8c /* serial control */
+#define SSR 0x8e /* serial status */
+#define RDCSR 0x90 /* rx DMA control/status */
+#define TDCSR 0x94 /* tx DMA control/status */
+#define RDDAR 0x98 /* rx DMA descriptor address */
+#define TDDAR 0x9c /* tx DMA descriptor address */
+
+#define RXIDLE BIT14
+#define RXBREAK BIT14
+#define IRQ_TXDATA BIT13
+#define IRQ_TXIDLE BIT12
+#define IRQ_TXUNDER BIT11 /* HDLC */
+#define IRQ_RXDATA BIT10
+#define IRQ_RXIDLE BIT9 /* HDLC */
+#define IRQ_RXBREAK BIT9 /* async */
+#define IRQ_RXOVER BIT8
+#define IRQ_DSR BIT7
+#define IRQ_CTS BIT6
+#define IRQ_DCD BIT5
+#define IRQ_RI BIT4
+#define IRQ_ALL 0x3ff0
+#define IRQ_MASTER BIT0
+
+#define slgt_irq_on(info, mask) \
+ wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask)))
+#define slgt_irq_off(info, mask) \
+ wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask)))
+
+static __u8 rd_reg8(struct slgt_info *info, unsigned int addr);
+static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value);
+static __u16 rd_reg16(struct slgt_info *info, unsigned int addr);
+static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value);
+static __u32 rd_reg32(struct slgt_info *info, unsigned int addr);
+static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
+
+static void msc_set_vcr(struct slgt_info *info);
+
+static int startup(struct slgt_info *info);
+static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
+static void shutdown(struct slgt_info *info);
+static void program_hw(struct slgt_info *info);
+static void change_params(struct slgt_info *info);
+
+static int register_test(struct slgt_info *info);
+static int irq_test(struct slgt_info *info);
+static int loopback_test(struct slgt_info *info);
+static int adapter_test(struct slgt_info *info);
+
+static void reset_adapter(struct slgt_info *info);
+static void reset_port(struct slgt_info *info);
+static void async_mode(struct slgt_info *info);
+static void hdlc_mode(struct slgt_info *info);
+
+static void rx_stop(struct slgt_info *info);
+static void rx_start(struct slgt_info *info);
+static void reset_rbufs(struct slgt_info *info);
+static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
+static void rdma_reset(struct slgt_info *info);
+static int rx_get_frame(struct slgt_info *info);
+static int rx_get_buf(struct slgt_info *info);
+
+static void tx_start(struct slgt_info *info);
+static void tx_stop(struct slgt_info *info);
+static void tx_set_idle(struct slgt_info *info);
+static unsigned int free_tbuf_count(struct slgt_info *info);
+static void reset_tbufs(struct slgt_info *info);
+static void tdma_reset(struct slgt_info *info);
+static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
+
+static void get_signals(struct slgt_info *info);
+static void set_signals(struct slgt_info *info);
+static void enable_loopback(struct slgt_info *info);
+static void set_rate(struct slgt_info *info, u32 data_rate);
+
+static int bh_action(struct slgt_info *info);
+static void bh_handler(void* context);
+static void bh_transmit(struct slgt_info *info);
+static void isr_serial(struct slgt_info *info);
+static void isr_rdma(struct slgt_info *info);
+static void isr_txeom(struct slgt_info *info, unsigned short status);
+static void isr_tdma(struct slgt_info *info);
+static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+
+static int alloc_dma_bufs(struct slgt_info *info);
+static void free_dma_bufs(struct slgt_info *info);
+static int alloc_desc(struct slgt_info *info);
+static void free_desc(struct slgt_info *info);
+static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
+static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
+
+static int alloc_tmp_rbuf(struct slgt_info *info);
+static void free_tmp_rbuf(struct slgt_info *info);
+
+static void tx_timeout(unsigned long context);
+static void rx_timeout(unsigned long context);
+
+/*
+ * ioctl handlers
+ */
+static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount);
+static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params);
+static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params);
+static int get_txidle(struct slgt_info *info, int __user *idle_mode);
+static int set_txidle(struct slgt_info *info, int idle_mode);
+static int tx_enable(struct slgt_info *info, int enable);
+static int tx_abort(struct slgt_info *info);
+static int rx_enable(struct slgt_info *info, int enable);
+static int modem_input_wait(struct slgt_info *info,int arg);
+static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
+static int tiocmget(struct tty_struct *tty, struct file *file);
+static int tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void set_break(struct tty_struct *tty, int break_state);
+static int get_interface(struct slgt_info *info, int __user *if_mode);
+static int set_interface(struct slgt_info *info, int if_mode);
+
+/*
+ * driver functions
+ */
+static void add_device(struct slgt_info *info);
+static void device_init(int adapter_num, struct pci_dev *pdev);
+static int claim_resources(struct slgt_info *info);
+static void release_resources(struct slgt_info *info);
+
+/*
+ * DEBUG OUTPUT CODE
+ */
+#ifndef DBGINFO
+#define DBGINFO(fmt)
+#endif
+#ifndef DBGERR
+#define DBGERR(fmt)
+#endif
+#ifndef DBGBH
+#define DBGBH(fmt)
+#endif
+#ifndef DBGISR
+#define DBGISR(fmt)
+#endif
+
+#ifdef DBGDATA
+static void trace_block(struct slgt_info *info, const char *data, int count, const char *label)
+{
+ int i;
+ int linecount;
+ printk("%s %s data:\n",info->device_name, label);
+ while(count) {
+ linecount = (count > 16) ? 16 : count;
+ for(i=0; i < linecount; i++)
+ printk("%02X ",(unsigned char)data[i]);
+ for(;i<17;i++)
+ printk(" ");
+ for(i=0;i<linecount;i++) {
+ if (data[i]>=040 && data[i]<=0176)
+ printk("%c",data[i]);
+ else
+ printk(".");
+ }
+ printk("\n");
+ data += linecount;
+ count -= linecount;
+ }
+}
+#else
+#define DBGDATA(info, buf, size, label)
+#endif
+
+#ifdef DBGTBUF
+static void dump_tbufs(struct slgt_info *info)
+{
+ int i;
+ printk("tbuf_current=%d\n", info->tbuf_current);
+ for (i=0 ; i < info->tbuf_count ; i++) {
+ printk("%d: count=%04X status=%04X\n",
+ i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status));
+ }
+}
+#else
+#define DBGTBUF(info)
+#endif
+
+#ifdef DBGRBUF
+static void dump_rbufs(struct slgt_info *info)
+{
+ int i;
+ printk("rbuf_current=%d\n", info->rbuf_current);
+ for (i=0 ; i < info->rbuf_count ; i++) {
+ printk("%d: count=%04X status=%04X\n",
+ i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status));
+ }
+}
+#else
+#define DBGRBUF(info)
+#endif
+
+static inline int sanity_check(struct slgt_info *info, char *devname, const char *name)
+{
+#ifdef SANITY_CHECK
+ if (!info) {
+ printk("null struct slgt_info for (%s) in %s\n", devname, name);
+ return 1;
+ }
+ if (info->magic != MGSL_MAGIC) {
+ printk("bad magic number struct slgt_info (%s) in %s\n", devname, name);
+ return 1;
+ }
+#else
+ if (!info)
+ return 1;
+#endif
+ return 0;
+}
+
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf - pass receive data to line discipline
+ */
+static void ldisc_receive_buf(struct tty_struct *tty,
+ const __u8 *data, char *flags, int count)
+{
+ struct tty_ldisc *ld;
+ if (!tty)
+ return;
+ ld = tty_ldisc_ref(tty);
+ if (ld) {
+ if (ld->receive_buf)
+ ld->receive_buf(tty, data, flags, count);
+ tty_ldisc_deref(ld);
+ }
+}
+
+/* tty callbacks */
+
+static int open(struct tty_struct *tty, struct file *filp)
+{
+ struct slgt_info *info;
+ int retval, line;
+ unsigned long flags;
+
+ line = tty->index;
+ if ((line < 0) || (line >= slgt_device_count)) {
+ DBGERR(("%s: open with invalid line #%d.\n", driver_name, line));
+ return -ENODEV;
+ }
+
+ info = slgt_device_list;
+ while(info && info->line != line)
+ info = info->next_device;
+ if (sanity_check(info, tty->name, "open"))
+ return -ENODEV;
+ if (info->init_error) {
+ DBGERR(("%s init error=%d\n", info->device_name, info->init_error));
+ return -ENODEV;
+ }
+
+ tty->driver_data = info;
+ info->tty = tty;
+
+ DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->count));
+
+ /* If port is closing, signal caller to try again */
+ if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+ goto cleanup;
+ }
+
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ spin_lock_irqsave(&info->netlock, flags);
+ if (info->netcount) {
+ retval = -EBUSY;
+ spin_unlock_irqrestore(&info->netlock, flags);
+ goto cleanup;
+ }
+ info->count++;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ if (info->count == 1) {
+ /* 1st open on this device, init hardware */
+ retval = startup(info);
+ if (retval < 0)
+ goto cleanup;
+ }
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+ DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
+ goto cleanup;
+ }
+
+ retval = 0;
+
+cleanup:
+ if (retval) {
+ if (tty->count == 1)
+ info->tty = NULL; /* tty layer will release tty struct */
+ if(info->count)
+ info->count--;
+ }
+
+ DBGINFO(("%s open rc=%d\n", info->device_name, retval));
+ return retval;
+}
+
+static void close(struct tty_struct *tty, struct file *filp)
+{
+ struct slgt_info *info = tty->driver_data;
+
+ if (sanity_check(info, tty->name, "close"))
+ return;
+ DBGINFO(("%s close entry, count=%d\n", info->device_name, info->count));
+
+ if (!info->count)
+ return;
+
+ if (tty_hung_up_p(filp))
+ goto cleanup;
+
+ if ((tty->count == 1) && (info->count != 1)) {
+ /*
+ * tty->count is 1 and the tty structure will be freed.
+ * info->count should be one in this case.
+ * if it's not, correct it so that the port is shutdown.
+ */
+ DBGERR(("%s close: bad refcount; tty->count=1, "
+ "info->count=%d\n", info->device_name, info->count));
+ info->count = 1;
+ }
+
+ info->count--;
+
+ /* if at least one open remaining, leave hardware active */
+ if (info->count)
+ goto cleanup;
+
+ info->flags |= ASYNC_CLOSING;
+
+ /* set tty->closing to notify line discipline to
+ * only process XON/XOFF characters. Only the N_TTY
+ * discipline appears to use this (ppp does not).
+ */
+ tty->closing = 1;
+
+ /* wait for transmit data to clear all layers */
+
+ if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
+ DBGINFO(("%s call tty_wait_until_sent\n", info->device_name));
+ tty_wait_until_sent(tty, info->closing_wait);
+ }
+
+ if (info->flags & ASYNC_INITIALIZED)
+ wait_until_sent(tty, info->timeout);
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ shutdown(info);
+
+ tty->closing = 0;
+ info->tty = NULL;
+
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+
+ wake_up_interruptible(&info->close_wait);
+
+cleanup:
+ DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->count));
+}
+
+static void hangup(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+
+ if (sanity_check(info, tty->name, "hangup"))
+ return;
+ DBGINFO(("%s hangup\n", info->device_name));
+
+ flush_buffer(tty);
+ shutdown(info);
+
+ info->count = 0;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->tty = NULL;
+
+ wake_up_interruptible(&info->open_wait);
+}
+
+static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ DBGINFO(("%s set_termios\n", tty->driver->name));
+
+ /* just return if nothing has changed */
+ if ((tty->termios->c_cflag == old_termios->c_cflag)
+ && (RELEVANT_IFLAG(tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag)))
+ return;
+
+ change_params(info);
+
+ /* Handle transition to B0 status */
+ if (old_termios->c_cflag & CBAUD &&
+ !(tty->termios->c_cflag & CBAUD)) {
+ info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+ spin_lock_irqsave(&info->lock,flags);
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ tty->termios->c_cflag & CBAUD) {
+ info->signals |= SerialSignal_DTR;
+ if (!(tty->termios->c_cflag & CRTSCTS) ||
+ !test_bit(TTY_THROTTLED, &tty->flags)) {
+ info->signals |= SerialSignal_RTS;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+ /* Handle turning off CRTSCTS */
+ if (old_termios->c_cflag & CRTSCTS &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ tx_release(tty);
+ }
+}
+
+static int write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+{
+ int ret = 0;
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "write"))
+ goto cleanup;
+ DBGINFO(("%s write count=%d\n", info->device_name, count));
+
+ if (!tty || !info->tx_buf)
+ goto cleanup;
+
+ if (count > info->max_frame_size) {
+ ret = -EIO;
+ goto cleanup;
+ }
+
+ if (!count)
+ goto cleanup;
+
+ if (info->params.mode == MGSL_MODE_RAW) {
+ unsigned int bufs_needed = (count/DMABUFSIZE);
+ unsigned int bufs_free = free_tbuf_count(info);
+ if (count % DMABUFSIZE)
+ ++bufs_needed;
+ if (bufs_needed > bufs_free)
+ goto cleanup;
+ } else {
+ if (info->tx_active)
+ goto cleanup;
+ if (info->tx_count) {
+ /* send accumulated data from send_char() calls */
+ /* as frame and wait before accepting more data. */
+ tx_load(info, info->tx_buf, info->tx_count);
+ goto start;
+ }
+ }
+
+ ret = info->tx_count = count;
+ tx_load(info, buf, count);
+ goto start;
+
+start:
+ if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+cleanup:
+ DBGINFO(("%s write rc=%d\n", info->device_name, ret));
+ return ret;
+}
+
+static void put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "put_char"))
+ return;
+ DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
+ if (!tty || !info->tx_buf)
+ return;
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active && (info->tx_count < info->max_frame_size))
+ info->tx_buf[info->tx_count++] = ch;
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+static void send_xchar(struct tty_struct *tty, char ch)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "send_xchar"))
+ return;
+ DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch));
+ info->x_char = ch;
+ if (ch) {
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_enabled)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+}
+
+static void wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+
+ if (!info )
+ return;
+ if (sanity_check(info, tty->name, "wait_until_sent"))
+ return;
+ DBGINFO(("%s wait_until_sent entry\n", info->device_name));
+ if (!(info->flags & ASYNC_INITIALIZED))
+ goto exit;
+
+ orig_jiffies = jiffies;
+
+ /* Set check interval to 1/5 of estimated time to
+ * send a character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ * Note: use tight timings here to satisfy the NIST-PCTS.
+ */
+
+ if (info->params.data_rate) {
+ char_time = info->timeout/(32 * 5);
+ if (!char_time)
+ char_time++;
+ } else
+ char_time = 1;
+
+ if (timeout)
+ char_time = min_t(unsigned long, char_time, timeout);
+
+ while (info->tx_active) {
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+
+exit:
+ DBGINFO(("%s wait_until_sent exit\n", info->device_name));
+}
+
+static int write_room(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ int ret;
+
+ if (sanity_check(info, tty->name, "write_room"))
+ return 0;
+ ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
+ DBGINFO(("%s write_room=%d\n", info->device_name, ret));
+ return ret;
+}
+
+static void flush_chars(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "flush_chars"))
+ return;
+ DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));
+
+ if (info->tx_count <= 0 || tty->stopped ||
+ tty->hw_stopped || !info->tx_buf)
+ return;
+
+ DBGINFO(("%s flush_chars start transmit\n", info->device_name));
+
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active && info->tx_count) {
+ tx_load(info, info->tx_buf,info->tx_count);
+ tx_start(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+static void flush_buffer(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "flush_buffer"))
+ return;
+ DBGINFO(("%s flush_buffer\n", info->device_name));
+
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ info->tx_count = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ wake_up_interruptible(&tty->write_wait);
+ tty_wakeup(tty);
+}
+
+/*
+ * throttle (stop) transmitter
+ */
+static void tx_hold(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "tx_hold"))
+ return;
+ DBGINFO(("%s tx_hold\n", info->device_name));
+ spin_lock_irqsave(&info->lock,flags);
+ if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)
+ tx_stop(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * release (start) transmitter
+ */
+static void tx_release(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "tx_release"))
+ return;
+ DBGINFO(("%s tx_release\n", info->device_name));
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active && info->tx_count) {
+ tx_load(info, info->tx_buf, info->tx_count);
+ tx_start(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * Service an IOCTL request
+ *
+ * Arguments
+ *
+ * tty pointer to tty instance data
+ * file pointer to associated file object for device
+ * cmd IOCTL command code
+ * arg command argument/context
+ *
+ * Return 0 if success, otherwise error code
+ */
+static int ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct slgt_info *info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ struct serial_icounter_struct __user *p_cuser; /* user space */
+ unsigned long flags;
+ void __user *argp = (void __user *)arg;
+
+ if (sanity_check(info, tty->name, "ioctl"))
+ return -ENODEV;
+ DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case MGSL_IOCGPARAMS:
+ return get_params(info, argp);
+ case MGSL_IOCSPARAMS:
+ return set_params(info, argp);
+ case MGSL_IOCGTXIDLE:
+ return get_txidle(info, argp);
+ case MGSL_IOCSTXIDLE:
+ return set_txidle(info, (int)arg);
+ case MGSL_IOCTXENABLE:
+ return tx_enable(info, (int)arg);
+ case MGSL_IOCRXENABLE:
+ return rx_enable(info, (int)arg);
+ case MGSL_IOCTXABORT:
+ return tx_abort(info);
+ case MGSL_IOCGSTATS:
+ return get_stats(info, argp);
+ case MGSL_IOCWAITEVENT:
+ return wait_mgsl_event(info, argp);
+ case TIOCMIWAIT:
+ return modem_input_wait(info,(int)arg);
+ case MGSL_IOCGIF:
+ return get_interface(info, argp);
+ case MGSL_IOCSIF:
+ return set_interface(info,(int)arg);
+ case TIOCGICOUNT:
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+ p_cuser = argp;
+ if (put_user(cnow.cts, &p_cuser->cts) ||
+ put_user(cnow.dsr, &p_cuser->dsr) ||
+ put_user(cnow.rng, &p_cuser->rng) ||
+ put_user(cnow.dcd, &p_cuser->dcd) ||
+ put_user(cnow.rx, &p_cuser->rx) ||
+ put_user(cnow.tx, &p_cuser->tx) ||
+ put_user(cnow.frame, &p_cuser->frame) ||
+ put_user(cnow.overrun, &p_cuser->overrun) ||
+ put_user(cnow.parity, &p_cuser->parity) ||
+ put_user(cnow.brk, &p_cuser->brk) ||
+ put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
+ return -EFAULT;
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+/*
+ * proc fs support
+ */
+static inline int line_info(char *buf, struct slgt_info *info)
+{
+ char stat_buf[30];
+ int ret;
+ unsigned long flags;
+
+ ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n",
+ info->device_name, info->phys_reg_addr,
+ info->irq_level, info->max_frame_size);
+
+ /* output current serial signal states */
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ stat_buf[0] = 0;
+ stat_buf[1] = 0;
+ if (info->signals & SerialSignal_RTS)
+ strcat(stat_buf, "|RTS");
+ if (info->signals & SerialSignal_CTS)
+ strcat(stat_buf, "|CTS");
+ if (info->signals & SerialSignal_DTR)
+ strcat(stat_buf, "|DTR");
+ if (info->signals & SerialSignal_DSR)
+ strcat(stat_buf, "|DSR");
+ if (info->signals & SerialSignal_DCD)
+ strcat(stat_buf, "|CD");
+ if (info->signals & SerialSignal_RI)
+ strcat(stat_buf, "|RI");
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d",
+ info->icount.txok, info->icount.rxok);
+ if (info->icount.txunder)
+ ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder);
+ if (info->icount.txabort)
+ ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort);
+ if (info->icount.rxshort)
+ ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort);
+ if (info->icount.rxlong)
+ ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong);
+ if (info->icount.rxover)
+ ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
+ if (info->icount.rxcrc)
+ ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
+ } else {
+ ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d",
+ info->icount.tx, info->icount.rx);
+ if (info->icount.frame)
+ ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+ if (info->icount.parity)
+ ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+ if (info->icount.brk)
+ ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+ if (info->icount.overrun)
+ ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+ }
+
+ /* Append serial signal status to end */
+ ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+
+ ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
+ info->tx_active,info->bh_requested,info->bh_running,
+ info->pending_bh);
+
+ return ret;
+}
+
+/* Called to print information about devices
+ */
+static int read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len = 0, l;
+ off_t begin = 0;
+ struct slgt_info *info;
+
+ len += sprintf(page, "synclink_gt driver:%s\n", driver_version);
+
+ info = slgt_device_list;
+ while( info ) {
+ l = line_info(page + len, info);
+ len += l;
+ if (len+begin > off+count)
+ goto done;
+ if (len+begin < off) {
+ begin += len;
+ len = 0;
+ }
+ info = info->next_device;
+ }
+
+ *eof = 1;
+done:
+ if (off >= len+begin)
+ return 0;
+ *start = page + (off-begin);
+ return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * return count of bytes in transmit buffer
+ */
+static int chars_in_buffer(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ if (sanity_check(info, tty->name, "chars_in_buffer"))
+ return 0;
+ DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count));
+ return info->tx_count;
+}
+
+/*
+ * signal remote device to throttle send data (our receive data)
+ */
+static void throttle(struct tty_struct * tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "throttle"))
+ return;
+ DBGINFO(("%s throttle\n", info->device_name));
+ if (I_IXOFF(tty))
+ send_xchar(tty, STOP_CHAR(tty));
+ if (tty->termios->c_cflag & CRTSCTS) {
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals &= ~SerialSignal_RTS;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+}
+
+/*
+ * signal remote device to stop throttling send data (our receive data)
+ */
+static void unthrottle(struct tty_struct * tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "unthrottle"))
+ return;
+ DBGINFO(("%s unthrottle\n", info->device_name));
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ send_xchar(tty, START_CHAR(tty));
+ }
+ if (tty->termios->c_cflag & CRTSCTS) {
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals |= SerialSignal_RTS;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+}
+
+/*
+ * set or clear transmit break condition
+ * break_state -1=set break condition, 0=clear
+ */
+static void set_break(struct tty_struct *tty, int break_state)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned short value;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "set_break"))
+ return;
+ DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
+
+ spin_lock_irqsave(&info->lock,flags);
+ value = rd_reg16(info, TCR);
+ if (break_state == -1)
+ value |= BIT6;
+ else
+ value &= ~BIT6;
+ wr_reg16(info, TCR, value);
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+#ifdef CONFIG_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev pointer to network device structure
+ * encoding serial encoding setting
+ * parity FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ unsigned char new_encoding;
+ unsigned short new_crctype;
+
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
+
+ DBGINFO(("%s hdlcdev_attach\n", info->device_name));
+
+ switch (encoding)
+ {
+ case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break;
+ case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+ case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+ case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+ case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+ default: return -EINVAL;
+ }
+
+ switch (parity)
+ {
+ case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break;
+ case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+ case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+ default: return -EINVAL;
+ }
+
+ info->params.encoding = new_encoding;
+ info->params.crc_type = new_crctype;;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ program_hw(info);
+
+ return 0;
+}
+
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb socket buffer containing HDLC frame
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
+ unsigned long flags;
+
+ DBGINFO(("%s hdlc_xmit\n", dev->name));
+
+ /* stop sending until this frame completes */
+ netif_stop_queue(dev);
+
+ /* copy data to device buffers */
+ info->tx_count = skb->len;
+ tx_load(info, skb->data, skb->len);
+
+ /* update network statistics */
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
+
+ /* done with socket buffer, so free it */
+ dev_kfree_skb(skb);
+
+ /* save start time for transmit timeout detection */
+ dev->trans_start = jiffies;
+
+ /* start hardware transmitter if necessary */
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return 0;
+}
+
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ int rc;
+ unsigned long flags;
+
+ DBGINFO(("%s hdlcdev_open\n", dev->name));
+
+ /* generic HDLC layer open processing */
+ if ((rc = hdlc_open(dev)))
+ return rc;
+
+ /* arbitrate between network and tty opens */
+ spin_lock_irqsave(&info->netlock, flags);
+ if (info->count != 0 || info->netcount != 0) {
+ DBGINFO(("%s hdlc_open busy\n", dev->name));
+ spin_unlock_irqrestore(&info->netlock, flags);
+ return -EBUSY;
+ }
+ info->netcount=1;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ /* claim resources and init adapter */
+ if ((rc = startup(info)) != 0) {
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+ return rc;
+ }
+
+ /* assert DTR and RTS, apply hardware settings */
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ program_hw(info);
+
+ /* enable network layer transmit */
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
+
+ /* inform generic HDLC layer of current DCD status */
+ spin_lock_irqsave(&info->lock, flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+ hdlc_set_carrier(info->signals & SerialSignal_DCD, dev);
+
+ return 0;
+}
+
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ unsigned long flags;
+
+ DBGINFO(("%s hdlcdev_close\n", dev->name));
+
+ netif_stop_queue(dev);
+
+ /* shutdown adapter and release resources */
+ shutdown(info);
+
+ hdlc_close(dev);
+
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ return 0;
+}
+
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev pointer to network device structure
+ * ifr pointer to network interface request structure
+ * cmd IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ const size_t size = sizeof(sync_serial_settings);
+ sync_serial_settings new_line;
+ sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+ struct slgt_info *info = dev_to_port(dev);
+ unsigned int flags;
+
+ DBGINFO(("%s hdlcdev_ioctl\n", dev->name));
+
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
+
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
+
+ switch(ifr->ifr_settings.type) {
+ case IF_GET_IFACE: /* return current sync_serial_settings */
+
+ ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
+
+ flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+
+ switch (flags){
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+ case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+ default: new_line.clock_type = CLOCK_DEFAULT;
+ }
+
+ new_line.clock_rate = info->params.clock_speed;
+ new_line.loopback = info->params.loopback ? 1:0;
+
+ if (copy_to_user(line, &new_line, size))
+ return -EFAULT;
+ return 0;
+
+ case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&new_line, line, size))
+ return -EFAULT;
+
+ switch (new_line.clock_type)
+ {
+ case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+ case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+ case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_DEFAULT: flags = info->params.flags &
+ (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break;
+ default: return -EINVAL;
+ }
+
+ if (new_line.loopback != 0 && new_line.loopback != 1)
+ return -EINVAL;
+
+ info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+ info->params.flags |= flags;
+
+ info->params.loopback = new_line.loopback;
+
+ if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+ info->params.clock_speed = new_line.clock_rate;
+ else
+ info->params.clock_speed = 0;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ program_hw(info);
+ return 0;
+
+ default:
+ return hdlc_ioctl(dev, ifr, cmd);
+ }
+}
+
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
+ unsigned long flags;
+
+ DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name));
+
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
+
+ spin_lock_irqsave(&info->lock,flags);
+ tx_stop(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct slgt_info *info)
+{
+ if (netif_queue_stopped(info->netdev))
+ netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info pointer to device instance information
+ * buf pointer to buffer contianing frame data
+ * size count of data bytes in buf
+ */
+static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
+{
+ struct sk_buff *skb = dev_alloc_skb(size);
+ struct net_device *dev = info->netdev;
+ struct net_device_stats *stats = hdlc_stats(dev);
+
+ DBGINFO(("%s hdlcdev_rx\n", dev->name));
+
+ if (skb == NULL) {
+ DBGERR(("%s: can't alloc skb, drop packet\n", dev->name));
+ stats->rx_dropped++;
+ return;
+ }
+
+ memcpy(skb_put(skb, size),buf,size);
+
+ skb->protocol = hdlc_type_trans(skb, info->netdev);
+
+ stats->rx_packets++;
+ stats->rx_bytes += size;
+
+ netif_rx(skb);
+
+ info->netdev->last_rx = jiffies;
+}
+
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct slgt_info *info)
+{
+ int rc;
+ struct net_device *dev;
+ hdlc_device *hdlc;
+
+ /* allocate and initialize network and HDLC layer objects */
+
+ if (!(dev = alloc_hdlcdev(info))) {
+ printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
+ return -ENOMEM;
+ }
+
+ /* for network layer reporting purposes only */
+ dev->mem_start = info->phys_reg_addr;
+ dev->mem_end = info->phys_reg_addr + SLGT_REG_SIZE - 1;
+ dev->irq = info->irq_level;
+
+ /* network layer callbacks and settings */
+ dev->do_ioctl = hdlcdev_ioctl;
+ dev->open = hdlcdev_open;
+ dev->stop = hdlcdev_close;
+ dev->tx_timeout = hdlcdev_tx_timeout;
+ dev->watchdog_timeo = 10*HZ;
+ dev->tx_queue_len = 50;
+
+ /* generic HDLC layer callbacks and settings */
+ hdlc = dev_to_hdlc(dev);
+ hdlc->attach = hdlcdev_attach;
+ hdlc->xmit = hdlcdev_xmit;
+
+ /* register objects with HDLC layer */
+ if ((rc = register_hdlc_device(dev))) {
+ printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+ free_netdev(dev);
+ return rc;
+ }
+
+ info->netdev = dev;
+ return 0;
+}
+
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_exit(struct slgt_info *info)
+{
+ unregister_hdlc_device(info->netdev);
+ free_netdev(info->netdev);
+ info->netdev = NULL;
+}
+
+#endif /* ifdef CONFIG_HDLC */
+
+/*
+ * get async data from rx DMA buffers
+ */
+static void rx_async(struct slgt_info *info)
+{
+ struct tty_struct *tty = info->tty;
+ struct mgsl_icount *icount = &info->icount;
+ unsigned int start, end;
+ unsigned char *p;
+ unsigned char status;
+ struct slgt_desc *bufs = info->rbufs;
+ int i, count;
+ int chars = 0;
+ int stat;
+ unsigned char ch;
+
+ start = end = info->rbuf_current;
+
+ while(desc_complete(bufs[end])) {
+ count = desc_count(bufs[end]) - info->rbuf_index;
+ p = bufs[end].buf + info->rbuf_index;
+
+ DBGISR(("%s rx_async count=%d\n", info->device_name, count));
+ DBGDATA(info, p, count, "rx");
+
+ for(i=0 ; i < count; i+=2, p+=2) {
+ if (tty && chars) {
+ tty_flip_buffer_push(tty);
+ chars = 0;
+ }
+ ch = *p;
+ icount->rx++;
+
+ stat = 0;
+
+ if ((status = *(p+1) & (BIT9 + BIT8))) {
+ if (status & BIT9)
+ icount->parity++;
+ else if (status & BIT8)
+ icount->frame++;
+ /* discard char if tty control flags say so */
+ if (status & info->ignore_status_mask)
+ continue;
+ if (status & BIT9)
+ stat = TTY_PARITY;
+ else if (status & BIT8)
+ stat = TTY_FRAME;
+ }
+ if (tty) {
+ tty_insert_flip_char(tty, ch, stat);
+ chars++;
+ }
+ }
+
+ if (i < count) {
+ /* receive buffer not completed */
+ info->rbuf_index += i;
+ info->rx_timer.expires = jiffies + 1;
+ add_timer(&info->rx_timer);
+ break;
+ }
+
+ info->rbuf_index = 0;
+ free_rbufs(info, end, end);
+
+ if (++end == info->rbuf_count)
+ end = 0;
+
+ /* if entire list searched then no frame available */
+ if (end == start)
+ break;
+ }
+
+ if (tty && chars)
+ tty_flip_buffer_push(tty);
+}
+
+/*
+ * return next bottom half action to perform
+ */
+static int bh_action(struct slgt_info *info)
+{
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ if (info->pending_bh & BH_RECEIVE) {
+ info->pending_bh &= ~BH_RECEIVE;
+ rc = BH_RECEIVE;
+ } else if (info->pending_bh & BH_TRANSMIT) {
+ info->pending_bh &= ~BH_TRANSMIT;
+ rc = BH_TRANSMIT;
+ } else if (info->pending_bh & BH_STATUS) {
+ info->pending_bh &= ~BH_STATUS;
+ rc = BH_STATUS;
+ } else {
+ /* Mark BH routine as complete */
+ info->bh_running = 0;
+ info->bh_requested = 0;
+ rc = 0;
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return rc;
+}
+
+/*
+ * perform bottom half processing
+ */
+static void bh_handler(void* context)
+{
+ struct slgt_info *info = context;
+ int action;
+
+ if (!info)
+ return;
+ info->bh_running = 1;
+
+ while((action = bh_action(info))) {
+ switch (action) {
+ case BH_RECEIVE:
+ DBGBH(("%s bh receive\n", info->device_name));
+ switch(info->params.mode) {
+ case MGSL_MODE_ASYNC:
+ rx_async(info);
+ break;
+ case MGSL_MODE_HDLC:
+ while(rx_get_frame(info));
+ break;
+ case MGSL_MODE_RAW:
+ while(rx_get_buf(info));
+ break;
+ }
+ /* restart receiver if rx DMA buffers exhausted */
+ if (info->rx_restart)
+ rx_start(info);
+ break;
+ case BH_TRANSMIT:
+ bh_transmit(info);
+ break;
+ case BH_STATUS:
+ DBGBH(("%s bh status\n", info->device_name));
+ info->ri_chkcount = 0;
+ info->dsr_chkcount = 0;
+ info->dcd_chkcount = 0;
+ info->cts_chkcount = 0;
+ break;
+ default:
+ DBGBH(("%s unknown action\n", info->device_name));
+ break;
+ }
+ }
+ DBGBH(("%s bh_handler exit\n", info->device_name));
+}
+
+static void bh_transmit(struct slgt_info *info)
+{
+ struct tty_struct *tty = info->tty;
+
+ DBGBH(("%s bh_transmit\n", info->device_name));
+ if (tty) {
+ tty_wakeup(tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+static void dsr_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_DSR);
+ return;
+ }
+ info->icount.dsr++;
+ if (info->signals & SerialSignal_DSR)
+ info->input_signal_events.dsr_up++;
+ else
+ info->input_signal_events.dsr_down++;
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+}
+
+static void cts_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_CTS);
+ return;
+ }
+ info->icount.cts++;
+ if (info->signals & SerialSignal_CTS)
+ info->input_signal_events.cts_up++;
+ else
+ info->input_signal_events.cts_down++;
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+
+ if (info->flags & ASYNC_CTS_FLOW) {
+ if (info->tty) {
+ if (info->tty->hw_stopped) {
+ if (info->signals & SerialSignal_CTS) {
+ info->tty->hw_stopped = 0;
+ info->pending_bh |= BH_TRANSMIT;
+ return;
+ }
+ } else {
+ if (!(info->signals & SerialSignal_CTS))
+ info->tty->hw_stopped = 1;
+ }
+ }
+ }
+}
+
+static void dcd_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_DCD);
+ return;
+ }
+ info->icount.dcd++;
+ if (info->signals & SerialSignal_DCD) {
+ info->input_signal_events.dcd_up++;
+ } else {
+ info->input_signal_events.dcd_down++;
+ }
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev);
+#endif
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+
+ if (info->flags & ASYNC_CHECK_CD) {
+ if (info->signals & SerialSignal_DCD)
+ wake_up_interruptible(&info->open_wait);
+ else {
+ if (info->tty)
+ tty_hangup(info->tty);
+ }
+ }
+}
+
+static void ri_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_RI);
+ return;
+ }
+ info->icount.dcd++;
+ if (info->signals & SerialSignal_RI) {
+ info->input_signal_events.ri_up++;
+ } else {
+ info->input_signal_events.ri_down++;
+ }
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+}
+
+static void isr_serial(struct slgt_info *info)
+{
+ unsigned short status = rd_reg16(info, SSR);
+
+ DBGISR(("%s isr_serial status=%04X\n", info->device_name, status));
+
+ wr_reg16(info, SSR, status); /* clear pending */
+
+ info->irq_occurred = 1;
+
+ if (info->params.mode == MGSL_MODE_ASYNC) {
+ if (status & IRQ_TXIDLE) {
+ if (info->tx_count)
+ isr_txeom(info, status);
+ }
+ if ((status & IRQ_RXBREAK) && (status & RXBREAK)) {
+ info->icount.brk++;
+ /* process break detection if tty control allows */
+ if (info->tty) {
+ if (!(status & info->ignore_status_mask)) {
+ if (info->read_status_mask & MASK_BREAK) {
+ tty_insert_flip_char(info->tty, 0, TTY_BREAK);
+ if (info->flags & ASYNC_SAK)
+ do_SAK(info->tty);
+ }
+ }
+ }
+ }
+ } else {
+ if (status & (IRQ_TXIDLE + IRQ_TXUNDER))
+ isr_txeom(info, status);
+
+ if (status & IRQ_RXIDLE) {
+ if (status & RXIDLE)
+ info->icount.rxidle++;
+ else
+ info->icount.exithunt++;
+ wake_up_interruptible(&info->event_wait_q);
+ }
+
+ if (status & IRQ_RXOVER)
+ rx_start(info);
+ }
+
+ if (status & IRQ_DSR)
+ dsr_change(info);
+ if (status & IRQ_CTS)
+ cts_change(info);
+ if (status & IRQ_DCD)
+ dcd_change(info);
+ if (status & IRQ_RI)
+ ri_change(info);
+}
+
+static void isr_rdma(struct slgt_info *info)
+{
+ unsigned int status = rd_reg32(info, RDCSR);
+
+ DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status));
+
+ /* RDCSR (rx DMA control/status)
+ *
+ * 31..07 reserved
+ * 06 save status byte to DMA buffer
+ * 05 error
+ * 04 eol (end of list)
+ * 03 eob (end of buffer)
+ * 02 IRQ enable
+ * 01 reset
+ * 00 enable
+ */
+ wr_reg32(info, RDCSR, status); /* clear pending */
+
+ if (status & (BIT5 + BIT4)) {
+ DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
+ info->rx_restart = 1;
+ }
+ info->pending_bh |= BH_RECEIVE;
+}
+
+static void isr_tdma(struct slgt_info *info)
+{
+ unsigned int status = rd_reg32(info, TDCSR);
+
+ DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status));
+
+ /* TDCSR (tx DMA control/status)
+ *
+ * 31..06 reserved
+ * 05 error
+ * 04 eol (end of list)
+ * 03 eob (end of buffer)
+ * 02 IRQ enable
+ * 01 reset
+ * 00 enable
+ */
+ wr_reg32(info, TDCSR, status); /* clear pending */
+
+ if (status & (BIT5 + BIT4 + BIT3)) {
+ // another transmit buffer has completed
+ // run bottom half to get more send data from user
+ info->pending_bh |= BH_TRANSMIT;
+ }
+}
+
+static void isr_txeom(struct slgt_info *info, unsigned short status)
+{
+ DBGISR(("%s txeom status=%04x\n", info->device_name, status));
+
+ slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+ tdma_reset(info);
+ reset_tbufs(info);
+ if (status & IRQ_TXUNDER) {
+ unsigned short val = rd_reg16(info, TCR);
+ wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, TCR, val); /* clear reset bit */
+ }
+
+ if (info->tx_active) {
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ if (status & IRQ_TXUNDER)
+ info->icount.txunder++;
+ else if (status & IRQ_TXIDLE)
+ info->icount.txok++;
+ }
+
+ info->tx_active = 0;
+ info->tx_count = 0;
+
+ del_timer(&info->tx_timer);
+
+ if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
+ info->signals &= ~SerialSignal_RTS;
+ info->drop_rts_on_tx_done = 0;
+ set_signals(info);
+ }
+
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_tx_done(info);
+ else
+#endif
+ {
+ if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
+ tx_stop(info);
+ return;
+ }
+ info->pending_bh |= BH_TRANSMIT;
+ }
+ }
+}
+
+/* interrupt service routine
+ *
+ * irq interrupt number
+ * dev_id device ID supplied during interrupt registration
+ * regs interrupted processor context
+ */
+static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct slgt_info *info;
+ unsigned int gsr;
+ unsigned int i;
+
+ DBGISR(("slgt_interrupt irq=%d entry\n", irq));
+
+ info = dev_id;
+ if (!info)
+ return IRQ_NONE;
+
+ spin_lock(&info->lock);
+
+ while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
+ DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
+ info->irq_occurred = 1;
+ for(i=0; i < info->port_count ; i++) {
+ if (info->port_array[i] == NULL)
+ continue;
+ if (gsr & (BIT8 << i))
+ isr_serial(info->port_array[i]);
+ if (gsr & (BIT16 << (i*2)))
+ isr_rdma(info->port_array[i]);
+ if (gsr & (BIT17 << (i*2)))
+ isr_tdma(info->port_array[i]);
+ }
+ }
+
+ for(i=0; i < info->port_count ; i++) {
+ struct slgt_info *port = info->port_array[i];
+
+ if (port && (port->count || port->netcount) &&
+ port->pending_bh && !port->bh_running &&
+ !port->bh_requested) {
+ DBGISR(("%s bh queued\n", port->device_name));
+ schedule_work(&port->task);
+ port->bh_requested = 1;
+ }
+ }
+
+ spin_unlock(&info->lock);
+
+ DBGISR(("slgt_interrupt irq=%d exit\n", irq));
+ return IRQ_HANDLED;
+}
+
+static int startup(struct slgt_info *info)
+{
+ DBGINFO(("%s startup\n", info->device_name));
+
+ if (info->flags & ASYNC_INITIALIZED)
+ return 0;
+
+ if (!info->tx_buf) {
+ info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
+ if (!info->tx_buf) {
+ DBGERR(("%s can't allocate tx buffer\n", info->device_name));
+ return -ENOMEM;
+ }
+ }
+
+ info->pending_bh = 0;
+
+ memset(&info->icount, 0, sizeof(info->icount));
+
+ /* program hardware for current parameters */
+ change_params(info);
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags |= ASYNC_INITIALIZED;
+
+ return 0;
+}
+
+/*
+ * called by close() and hangup() to shutdown hardware
+ */
+static void shutdown(struct slgt_info *info)
+{
+ unsigned long flags;
+
+ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+
+ DBGINFO(("%s shutdown\n", info->device_name));
+
+ /* clear status wait queue because status changes */
+ /* can't happen after shutting down the hardware */
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+
+ del_timer_sync(&info->tx_timer);
+ del_timer_sync(&info->rx_timer);
+
+ kfree(info->tx_buf);
+ info->tx_buf = NULL;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ tx_stop(info);
+ rx_stop(info);
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+
+ if (!info->tty || info->tty->termios->c_cflag & HUPCL) {
+ info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+ set_signals(info);
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ASYNC_INITIALIZED;
+}
+
+static void program_hw(struct slgt_info *info)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ rx_stop(info);
+ tx_stop(info);
+
+ if (info->params.mode == MGSL_MODE_HDLC ||
+ info->params.mode == MGSL_MODE_RAW ||
+ info->netcount)
+ hdlc_mode(info);
+ else
+ async_mode(info);
+
+ set_signals(info);
+
+ info->dcd_chkcount = 0;
+ info->cts_chkcount = 0;
+ info->ri_chkcount = 0;
+ info->dsr_chkcount = 0;
+
+ slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR);
+ get_signals(info);
+
+ if (info->netcount ||
+ (info->tty && info->tty->termios->c_cflag & CREAD))
+ rx_start(info);
+
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * reconfigure adapter based on new parameters
+ */
+static void change_params(struct slgt_info *info)
+{
+ unsigned cflag;
+ int bits_per_char;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+ DBGINFO(("%s change_params\n", info->device_name));
+
+ cflag = info->tty->termios->c_cflag;
+
+ /* if B0 rate (hangup) specified then negate DTR and RTS */
+ /* otherwise assert DTR and RTS */
+ if (cflag & CBAUD)
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ else
+ info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+
+ /* byte size and parity */
+
+ switch (cflag & CSIZE) {
+ case CS5: info->params.data_bits = 5; break;
+ case CS6: info->params.data_bits = 6; break;
+ case CS7: info->params.data_bits = 7; break;
+ case CS8: info->params.data_bits = 8; break;
+ default: info->params.data_bits = 7; break;
+ }
+
+ info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1;
+
+ if (cflag & PARENB)
+ info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN;
+ else
+ info->params.parity = ASYNC_PARITY_NONE;
+
+ /* calculate number of jiffies to transmit a full
+ * FIFO (32 bytes) at specified data rate
+ */
+ bits_per_char = info->params.data_bits +
+ info->params.stop_bits + 1;
+
+ info->params.data_rate = tty_get_baud_rate(info->tty);
+
+ if (info->params.data_rate) {
+ info->timeout = (32*HZ*bits_per_char) /
+ info->params.data_rate;
+ }
+ info->timeout += HZ/50; /* Add .02 seconds of slop */
+
+ if (cflag & CRTSCTS)
+ info->flags |= ASYNC_CTS_FLOW;
+ else
+ info->flags &= ~ASYNC_CTS_FLOW;
+
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+ else
+ info->flags |= ASYNC_CHECK_CD;
+
+ /* process tty input control flags */
+
+ info->read_status_mask = IRQ_RXOVER;
+ if (I_INPCK(info->tty))
+ info->read_status_mask |= MASK_PARITY | MASK_FRAMING;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= MASK_BREAK;
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING;
+ if (I_IGNBRK(info->tty)) {
+ info->ignore_status_mask |= MASK_BREAK;
+ /* If ignoring parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= MASK_OVERRUN;
+ }
+
+ program_hw(info);
+}
+
+static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount)
+{
+ DBGINFO(("%s get_stats\n", info->device_name));
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params)
+{
+ DBGINFO(("%s get_params\n", info->device_name));
+ if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS)))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params)
+{
+ unsigned long flags;
+ MGSL_PARAMS tmp_params;
+
+ DBGINFO(("%s set_params\n", info->device_name));
+ if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS)))
+ return -EFAULT;
+
+ spin_lock_irqsave(&info->lock, flags);
+ memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS));
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ change_params(info);
+
+ return 0;
+}
+
+static int get_txidle(struct slgt_info *info, int __user *idle_mode)
+{
+ DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode));
+ if (put_user(info->idle_mode, idle_mode))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_txidle(struct slgt_info *info, int idle_mode)
+{
+ unsigned long flags;
+ DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
+ spin_lock_irqsave(&info->lock,flags);
+ info->idle_mode = idle_mode;
+ tx_set_idle(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+static int tx_enable(struct slgt_info *info, int enable)
+{
+ unsigned long flags;
+ DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable));
+ spin_lock_irqsave(&info->lock,flags);
+ if (enable) {
+ if (!info->tx_enabled)
+ tx_start(info);
+ } else {
+ if (info->tx_enabled)
+ tx_stop(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+/*
+ * abort transmit HDLC frame
+ */
+static int tx_abort(struct slgt_info *info)
+{
+ unsigned long flags;
+ DBGINFO(("%s tx_abort\n", info->device_name));
+ spin_lock_irqsave(&info->lock,flags);
+ tdma_reset(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+static int rx_enable(struct slgt_info *info, int enable)
+{
+ unsigned long flags;
+ DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable));
+ spin_lock_irqsave(&info->lock,flags);
+ if (enable) {
+ if (!info->rx_enabled)
+ rx_start(info);
+ } else {
+ if (info->rx_enabled)
+ rx_stop(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+/*
+ * wait for specified event to occur
+ */
+static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr)
+{
+ unsigned long flags;
+ int s;
+ int rc=0;
+ struct mgsl_icount cprev, cnow;
+ int events;
+ int mask;
+ struct _input_signal_events oldsigs, newsigs;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (get_user(mask, mask_ptr))
+ return -EFAULT;
+
+ DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask));
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ /* return immediately if state matches requested events */
+ get_signals(info);
+ s = info->signals;
+
+ events = mask &
+ ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
+ ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
+ ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
+ ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) );
+ if (events) {
+ spin_unlock_irqrestore(&info->lock,flags);
+ goto exit;
+ }
+
+ /* save current irq counts */
+ cprev = info->icount;
+ oldsigs = info->input_signal_events;
+
+ /* enable hunt and idle irqs if needed */
+ if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
+ unsigned short val = rd_reg16(info, SCR);
+ if (!(val & IRQ_RXIDLE))
+ wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE));
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&info->event_wait_q, &wait);
+
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ for(;;) {
+ schedule();
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ break;
+ }
+
+ /* get current irq counts */
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ newsigs = info->input_signal_events;
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ /* if no change, wait aborted for some reason */
+ if (newsigs.dsr_up == oldsigs.dsr_up &&
+ newsigs.dsr_down == oldsigs.dsr_down &&
+ newsigs.dcd_up == oldsigs.dcd_up &&
+ newsigs.dcd_down == oldsigs.dcd_down &&
+ newsigs.cts_up == oldsigs.cts_up &&
+ newsigs.cts_down == oldsigs.cts_down &&
+ newsigs.ri_up == oldsigs.ri_up &&
+ newsigs.ri_down == oldsigs.ri_down &&
+ cnow.exithunt == cprev.exithunt &&
+ cnow.rxidle == cprev.rxidle) {
+ rc = -EIO;
+ break;
+ }
+
+ events = mask &
+ ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) +
+ (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
+ (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) +
+ (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
+ (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) +
+ (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
+ (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) +
+ (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) +
+ (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) +
+ (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) );
+ if (events)
+ break;
+
+ cprev = cnow;
+ oldsigs = newsigs;
+ }
+
+ remove_wait_queue(&info->event_wait_q, &wait);
+ set_current_state(TASK_RUNNING);
+
+
+ if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+ spin_lock_irqsave(&info->lock,flags);
+ if (!waitqueue_active(&info->event_wait_q)) {
+ /* disable enable exit hunt mode/idle rcvd IRQs */
+ wr_reg16(info, SCR,
+ (unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE));
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+exit:
+ if (rc == 0)
+ rc = put_user(events, mask_ptr);
+ return rc;
+}
+
+static int get_interface(struct slgt_info *info, int __user *if_mode)
+{
+ DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode));
+ if (put_user(info->if_mode, if_mode))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_interface(struct slgt_info *info, int if_mode)
+{
+ unsigned long flags;
+ unsigned short val;
+
+ DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
+ spin_lock_irqsave(&info->lock,flags);
+ info->if_mode = if_mode;
+
+ msc_set_vcr(info);
+
+ /* TCR (tx control) 07 1=RTS driver control */
+ val = rd_reg16(info, TCR);
+ if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+ val |= BIT7;
+ else
+ val &= ~BIT7;
+ wr_reg16(info, TCR, val);
+
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+static int modem_input_wait(struct slgt_info *info,int arg)
+{
+ unsigned long flags;
+ int rc;
+ struct mgsl_icount cprev, cnow;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* save current irq counts */
+ spin_lock_irqsave(&info->lock,flags);
+ cprev = info->icount;
+ add_wait_queue(&info->status_event_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ for(;;) {
+ schedule();
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ break;
+ }
+
+ /* get new irq counts */
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ /* if no change, wait aborted for some reason */
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+ rc = -EIO;
+ break;
+ }
+
+ /* check for change in caller specified modem input */
+ if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
+ (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
+ (arg & TIOCM_CD && cnow.dcd != cprev.dcd) ||
+ (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
+ rc = 0;
+ break;
+ }
+
+ cprev = cnow;
+ }
+ remove_wait_queue(&info->status_event_wait_q, &wait);
+ set_current_state(TASK_RUNNING);
+ return rc;
+}
+
+/*
+ * return state of serial control and status signals
+ */
+static int tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
+ ((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
+ ((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
+ ((info->signals & SerialSignal_RI) ? TIOCM_RNG:0) +
+ ((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
+ ((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0);
+
+ DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result));
+ return result;
+}
+
+/*
+ * set modem control signals (DTR/RTS)
+ *
+ * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit
+ * TIOCMSET = set/clear signal values
+ * value bit mask for command
+ */
+static int tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear));
+
+ if (set & TIOCM_RTS)
+ info->signals |= SerialSignal_RTS;
+ if (set & TIOCM_DTR)
+ info->signals |= SerialSignal_DTR;
+ if (clear & TIOCM_RTS)
+ info->signals &= ~SerialSignal_RTS;
+ if (clear & TIOCM_DTR)
+ info->signals &= ~SerialSignal_DTR;
+
+ spin_lock_irqsave(&info->lock,flags);
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+/*
+ * block current process until the device is ready to open
+ */
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct slgt_info *info)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+ int do_clocal = 0, extra_count = 0;
+ unsigned long flags;
+
+ DBGINFO(("%s block_til_ready\n", tty->driver->name));
+
+ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+ /* nonblock mode is set or port is not enabled */
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+
+ /* Wait for carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (!tty_hung_up_p(filp)) {
+ extra_count = 1;
+ info->count--;
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+ info->blocked_open++;
+
+ while (1) {
+ if ((tty->termios->c_cflag & CBAUD)) {
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){
+ retval = (info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS;
+ break;
+ }
+
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ if (!(info->flags & ASYNC_CLOSING) &&
+ (do_clocal || (info->signals & SerialSignal_DCD)) ) {
+ break;
+ }
+
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+
+ DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
+ schedule();
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&info->open_wait, &wait);
+
+ if (extra_count)
+ info->count++;
+ info->blocked_open--;
+
+ if (!retval)
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+
+ DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
+ return retval;
+}
+
+static int alloc_tmp_rbuf(struct slgt_info *info)
+{
+ info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL);
+ if (info->tmp_rbuf == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static void free_tmp_rbuf(struct slgt_info *info)
+{
+ kfree(info->tmp_rbuf);
+ info->tmp_rbuf = NULL;
+}
+
+/*
+ * allocate DMA descriptor lists.
+ */
+static int alloc_desc(struct slgt_info *info)
+{
+ unsigned int i;
+ unsigned int pbufs;
+
+ /* allocate memory to hold descriptor lists */
+ info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr);
+ if (info->bufs == NULL)
+ return -ENOMEM;
+
+ memset(info->bufs, 0, DESC_LIST_SIZE);
+
+ info->rbufs = (struct slgt_desc*)info->bufs;
+ info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count;
+
+ pbufs = (unsigned int)info->bufs_dma_addr;
+
+ /*
+ * Build circular lists of descriptors
+ */
+
+ for (i=0; i < info->rbuf_count; i++) {
+ /* physical address of this descriptor */
+ info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc));
+
+ /* physical address of next descriptor */
+ if (i == info->rbuf_count - 1)
+ info->rbufs[i].next = cpu_to_le32(pbufs);
+ else
+ info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc)));
+ set_desc_count(info->rbufs[i], DMABUFSIZE);
+ }
+
+ for (i=0; i < info->tbuf_count; i++) {
+ /* physical address of this descriptor */
+ info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc));
+
+ /* physical address of next descriptor */
+ if (i == info->tbuf_count - 1)
+ info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc));
+ else
+ info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc)));
+ }
+
+ return 0;
+}
+
+static void free_desc(struct slgt_info *info)
+{
+ if (info->bufs != NULL) {
+ pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr);
+ info->bufs = NULL;
+ info->rbufs = NULL;
+ info->tbufs = NULL;
+ }
+}
+
+static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
+{
+ int i;
+ for (i=0; i < count; i++) {
+ if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL)
+ return -ENOMEM;
+ bufs[i].pbuf = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr);
+ }
+ return 0;
+}
+
+static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
+{
+ int i;
+ for (i=0; i < count; i++) {
+ if (bufs[i].buf == NULL)
+ continue;
+ pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr);
+ bufs[i].buf = NULL;
+ }
+}
+
+static int alloc_dma_bufs(struct slgt_info *info)
+{
+ info->rbuf_count = 32;
+ info->tbuf_count = 32;
+
+ if (alloc_desc(info) < 0 ||
+ alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 ||
+ alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 ||
+ alloc_tmp_rbuf(info) < 0) {
+ DBGERR(("%s DMA buffer alloc fail\n", info->device_name));
+ return -ENOMEM;
+ }
+ reset_rbufs(info);
+ return 0;
+}
+
+static void free_dma_bufs(struct slgt_info *info)
+{
+ if (info->bufs) {
+ free_bufs(info, info->rbufs, info->rbuf_count);
+ free_bufs(info, info->tbufs, info->tbuf_count);
+ free_desc(info);
+ }
+ free_tmp_rbuf(info);
+}
+
+static int claim_resources(struct slgt_info *info)
+{
+ if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) {
+ DBGERR(("%s reg addr conflict, addr=%08X\n",
+ info->device_name, info->phys_reg_addr));
+ info->init_error = DiagStatus_AddressConflict;
+ goto errout;
+ }
+ else
+ info->reg_addr_requested = 1;
+
+ info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE);
+ if (!info->reg_addr) {
+ DBGERR(("%s cant map device registers, addr=%08X\n",
+ info->device_name, info->phys_reg_addr));
+ info->init_error = DiagStatus_CantAssignPciResources;
+ goto errout;
+ }
+ return 0;
+
+errout:
+ release_resources(info);
+ return -ENODEV;
+}
+
+static void release_resources(struct slgt_info *info)
+{
+ if (info->irq_requested) {
+ free_irq(info->irq_level, info);
+ info->irq_requested = 0;
+ }
+
+ if (info->reg_addr_requested) {
+ release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
+ info->reg_addr_requested = 0;
+ }
+
+ if (info->reg_addr) {
+ iounmap(info->reg_addr);
+ info->reg_addr = NULL;
+ }
+}
+
+/* Add the specified device instance data structure to the
+ * global linked list of devices and increment the device count.
+ */
+static void add_device(struct slgt_info *info)
+{
+ char *devstr;
+
+ info->next_device = NULL;
+ info->line = slgt_device_count;
+ sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line);
+
+ if (info->line < MAX_DEVICES) {
+ if (maxframe[info->line])
+ info->max_frame_size = maxframe[info->line];
+ info->dosyncppp = dosyncppp[info->line];
+ }
+
+ slgt_device_count++;
+
+ if (!slgt_device_list)
+ slgt_device_list = info;
+ else {
+ struct slgt_info *current_dev = slgt_device_list;
+ while(current_dev->next_device)
+ current_dev = current_dev->next_device;
+ current_dev->next_device = info;
+ }
+
+ if (info->max_frame_size < 4096)
+ info->max_frame_size = 4096;
+ else if (info->max_frame_size > 65535)
+ info->max_frame_size = 65535;
+
+ switch(info->pdev->device) {
+ case SYNCLINK_GT_DEVICE_ID:
+ devstr = "GT";
+ break;
+ case SYNCLINK_GT4_DEVICE_ID:
+ devstr = "GT4";
+ break;
+ case SYNCLINK_AC_DEVICE_ID:
+ devstr = "AC";
+ info->params.mode = MGSL_MODE_ASYNC;
+ break;
+ default:
+ devstr = "(unknown model)";
+ }
+ printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n",
+ devstr, info->device_name, info->phys_reg_addr,
+ info->irq_level, info->max_frame_size);
+
+#ifdef CONFIG_HDLC
+ hdlcdev_init(info);
+#endif
+}
+
+/*
+ * allocate device instance structure, return NULL on failure
+ */
+static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
+{
+ struct slgt_info *info;
+
+ info = kmalloc(sizeof(struct slgt_info), GFP_KERNEL);
+
+ if (!info) {
+ DBGERR(("%s device alloc failed adapter=%d port=%d\n",
+ driver_name, adapter_num, port_num));
+ } else {
+ memset(info, 0, sizeof(struct slgt_info));
+ info->magic = MGSL_MAGIC;
+ INIT_WORK(&info->task, bh_handler, info);
+ info->max_frame_size = 4096;
+ info->raw_rx_size = DMABUFSIZE;
+ info->close_delay = 5*HZ/10;
+ info->closing_wait = 30*HZ;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->status_event_wait_q);
+ init_waitqueue_head(&info->event_wait_q);
+ spin_lock_init(&info->netlock);
+ memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+ info->idle_mode = HDLC_TXIDLE_FLAGS;
+ info->adapter_num = adapter_num;
+ info->port_num = port_num;
+
+ init_timer(&info->tx_timer);
+ info->tx_timer.data = (unsigned long)info;
+ info->tx_timer.function = tx_timeout;
+
+ init_timer(&info->rx_timer);
+ info->rx_timer.data = (unsigned long)info;
+ info->rx_timer.function = rx_timeout;
+
+ /* Copy configuration info to device instance data */
+ info->pdev = pdev;
+ info->irq_level = pdev->irq;
+ info->phys_reg_addr = pci_resource_start(pdev,0);
+
+ info->bus_type = MGSL_BUS_TYPE_PCI;
+ info->irq_flags = SA_SHIRQ;
+
+ info->init_error = -1; /* assume error, set to 0 on successful init */
+ }
+
+ return info;
+}
+
+static void device_init(int adapter_num, struct pci_dev *pdev)
+{
+ struct slgt_info *port_array[SLGT_MAX_PORTS];
+ int i;
+ int port_count = 1;
+
+ if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
+ port_count = 4;
+
+ /* allocate device instances for all ports */
+ for (i=0; i < port_count; ++i) {
+ port_array[i] = alloc_dev(adapter_num, i, pdev);
+ if (port_array[i] == NULL) {
+ for (--i; i >= 0; --i)
+ kfree(port_array[i]);
+ return;
+ }
+ }
+
+ /* give copy of port_array to all ports and add to device list */
+ for (i=0; i < port_count; ++i) {
+ memcpy(port_array[i]->port_array, port_array, sizeof(port_array));
+ add_device(port_array[i]);
+ port_array[i]->port_count = port_count;
+ spin_lock_init(&port_array[i]->lock);
+ }
+
+ /* Allocate and claim adapter resources */
+ if (!claim_resources(port_array[0])) {
+
+ alloc_dma_bufs(port_array[0]);
+
+ /* copy resource information from first port to others */
+ for (i = 1; i < port_count; ++i) {
+ port_array[i]->lock = port_array[0]->lock;
+ port_array[i]->irq_level = port_array[0]->irq_level;
+ port_array[i]->reg_addr = port_array[0]->reg_addr;
+ alloc_dma_bufs(port_array[i]);
+ }
+
+ if (request_irq(port_array[0]->irq_level,
+ slgt_interrupt,
+ port_array[0]->irq_flags,
+ port_array[0]->device_name,
+ port_array[0]) < 0) {
+ DBGERR(("%s request_irq failed IRQ=%d\n",
+ port_array[0]->device_name,
+ port_array[0]->irq_level));
+ } else {
+ port_array[0]->irq_requested = 1;
+ adapter_test(port_array[0]);
+ for (i=1 ; i < port_count ; i++)
+ port_array[i]->init_error = port_array[0]->init_error;
+ }
+ }
+}
+
+static int __devinit init_one(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ if (pci_enable_device(dev)) {
+ printk("error enabling pci device %p\n", dev);
+ return -EIO;
+ }
+ pci_set_master(dev);
+ device_init(slgt_device_count, dev);
+ return 0;
+}
+
+static void __devexit remove_one(struct pci_dev *dev)
+{
+}
+
+static struct tty_operations ops = {
+ .open = open,
+ .close = close,
+ .write = write,
+ .put_char = put_char,
+ .flush_chars = flush_chars,
+ .write_room = write_room,
+ .chars_in_buffer = chars_in_buffer,
+ .flush_buffer = flush_buffer,
+ .ioctl = ioctl,
+ .throttle = throttle,
+ .unthrottle = unthrottle,
+ .send_xchar = send_xchar,
+ .break_ctl = set_break,
+ .wait_until_sent = wait_until_sent,
+ .read_proc = read_proc,
+ .set_termios = set_termios,
+ .stop = tx_hold,
+ .start = tx_release,
+ .hangup = hangup,
+ .tiocmget = tiocmget,
+ .tiocmset = tiocmset,
+};
+
+static void slgt_cleanup(void)
+{
+ int rc;
+ struct slgt_info *info;
+ struct slgt_info *tmp;
+
+ printk("unload %s %s\n", driver_name, driver_version);
+
+ if (serial_driver) {
+ if ((rc = tty_unregister_driver(serial_driver)))
+ DBGERR(("tty_unregister_driver error=%d\n", rc));
+ put_tty_driver(serial_driver);
+ }
+
+ /* reset devices */
+ info = slgt_device_list;
+ while(info) {
+ reset_port(info);
+ info = info->next_device;
+ }
+
+ /* release devices */
+ info = slgt_device_list;
+ while(info) {
+#ifdef CONFIG_HDLC
+ hdlcdev_exit(info);
+#endif
+ free_dma_bufs(info);
+ free_tmp_rbuf(info);
+ if (info->port_num == 0)
+ release_resources(info);
+ tmp = info;
+ info = info->next_device;
+ kfree(tmp);
+ }
+
+ if (pci_registered)
+ pci_unregister_driver(&pci_driver);
+}
+
+/*
+ * Driver initialization entry point.
+ */
+static int __init slgt_init(void)
+{
+ int rc;
+
+ printk("%s %s\n", driver_name, driver_version);
+
+ slgt_device_count = 0;
+ if ((rc = pci_register_driver(&pci_driver)) < 0) {
+ printk("%s pci_register_driver error=%d\n", driver_name, rc);
+ return rc;
+ }
+ pci_registered = 1;
+
+ if (!slgt_device_list) {
+ printk("%s no devices found\n",driver_name);
+ return -ENODEV;
+ }
+
+ serial_driver = alloc_tty_driver(MAX_DEVICES);
+ if (!serial_driver) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ /* Initialize the tty_driver structure */
+
+ serial_driver->owner = THIS_MODULE;
+ serial_driver->driver_name = tty_driver_name;
+ serial_driver->name = tty_dev_prefix;
+ serial_driver->major = ttymajor;
+ serial_driver->minor_start = 64;
+ serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver->subtype = SERIAL_TYPE_NORMAL;
+ serial_driver->init_termios = tty_std_termios;
+ serial_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(serial_driver, &ops);
+ if ((rc = tty_register_driver(serial_driver)) < 0) {
+ DBGERR(("%s can't register serial driver\n", driver_name));
+ put_tty_driver(serial_driver);
+ serial_driver = NULL;
+ goto error;
+ }
+
+ printk("%s %s, tty major#%d\n",
+ driver_name, driver_version,
+ serial_driver->major);
+
+ return 0;
+
+error:
+ slgt_cleanup();
+ return rc;
+}
+
+static void __exit slgt_exit(void)
+{
+ slgt_cleanup();
+}
+
+module_init(slgt_init);
+module_exit(slgt_exit);
+
+/*
+ * register access routines
+ */
+
+#define CALC_REGADDR() \
+ unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
+ if (addr >= 0x80) \
+ reg_addr += (info->port_num) * 32;
+
+static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
+{
+ CALC_REGADDR();
+ return readb((void __iomem *)reg_addr);
+}
+
+static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value)
+{
+ CALC_REGADDR();
+ writeb(value, (void __iomem *)reg_addr);
+}
+
+static __u16 rd_reg16(struct slgt_info *info, unsigned int addr)
+{
+ CALC_REGADDR();
+ return readw((void __iomem *)reg_addr);
+}
+
+static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value)
+{
+ CALC_REGADDR();
+ writew(value, (void __iomem *)reg_addr);
+}
+
+static __u32 rd_reg32(struct slgt_info *info, unsigned int addr)
+{
+ CALC_REGADDR();
+ return readl((void __iomem *)reg_addr);
+}
+
+static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value)
+{
+ CALC_REGADDR();
+ writel(value, (void __iomem *)reg_addr);
+}
+
+static void rdma_reset(struct slgt_info *info)
+{
+ unsigned int i;
+
+ /* set reset bit */
+ wr_reg32(info, RDCSR, BIT1);
+
+ /* wait for enable bit cleared */
+ for(i=0 ; i < 1000 ; i++)
+ if (!(rd_reg32(info, RDCSR) & BIT0))
+ break;
+}
+
+static void tdma_reset(struct slgt_info *info)
+{
+ unsigned int i;
+
+ /* set reset bit */
+ wr_reg32(info, TDCSR, BIT1);
+
+ /* wait for enable bit cleared */
+ for(i=0 ; i < 1000 ; i++)
+ if (!(rd_reg32(info, TDCSR) & BIT0))
+ break;
+}
+
+/*
+ * enable internal loopback
+ * TxCLK and RxCLK are generated from BRG
+ * and TxD is looped back to RxD internally.
+ */
+static void enable_loopback(struct slgt_info *info)
+{
+ /* SCR (serial control) BIT2=looopback enable */
+ wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2));
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ /* CCR (clock control)
+ * 07..05 tx clock source (010 = BRG)
+ * 04..02 rx clock source (010 = BRG)
+ * 01 auxclk enable (0 = disable)
+ * 00 BRG enable (1 = enable)
+ *
+ * 0100 1001
+ */
+ wr_reg8(info, CCR, 0x49);
+
+ /* set speed if available, otherwise use default */
+ if (info->params.clock_speed)
+ set_rate(info, info->params.clock_speed);
+ else
+ set_rate(info, 3686400);
+ }
+}
+
+/*
+ * set baud rate generator to specified rate
+ */
+static void set_rate(struct slgt_info *info, u32 rate)
+{
+ unsigned int div;
+ static unsigned int osc = 14745600;
+
+ /* div = osc/rate - 1
+ *
+ * Round div up if osc/rate is not integer to
+ * force to next slowest rate.
+ */
+
+ if (rate) {
+ div = osc/rate;
+ if (!(osc % rate) && div)
+ div--;
+ wr_reg16(info, BDR, (unsigned short)div);
+ }
+}
+
+static void rx_stop(struct slgt_info *info)
+{
+ unsigned short val;
+
+ /* disable and reset receiver */
+ val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
+ wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, RCR, val); /* clear reset bit */
+
+ slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE);
+
+ /* clear pending rx interrupts */
+ wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER);
+
+ rdma_reset(info);
+
+ info->rx_enabled = 0;
+ info->rx_restart = 0;
+}
+
+static void rx_start(struct slgt_info *info)
+{
+ unsigned short val;
+
+ slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA);
+
+ /* clear pending rx overrun IRQ */
+ wr_reg16(info, SSR, IRQ_RXOVER);
+
+ /* reset and disable receiver */
+ val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
+ wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, RCR, val); /* clear reset bit */
+
+ rdma_reset(info);
+ reset_rbufs(info);
+
+ /* set 1st descriptor address */
+ wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ /* enable rx DMA and DMA interrupt */
+ wr_reg32(info, RDCSR, (BIT2 + BIT0));
+ } else {
+ /* enable saving of rx status, rx DMA and DMA interrupt */
+ wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+ }
+
+ slgt_irq_on(info, IRQ_RXOVER);
+
+ /* enable receiver */
+ wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
+
+ info->rx_restart = 0;
+ info->rx_enabled = 1;
+}
+
+static void tx_start(struct slgt_info *info)
+{
+ if (!info->tx_enabled) {
+ wr_reg16(info, TCR,
+ (unsigned short)(rd_reg16(info, TCR) | BIT1));
+ info->tx_enabled = TRUE;
+ }
+
+ if (info->tx_count) {
+ info->drop_rts_on_tx_done = 0;
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
+ get_signals(info);
+ if (!(info->signals & SerialSignal_RTS)) {
+ info->signals |= SerialSignal_RTS;
+ set_signals(info);
+ info->drop_rts_on_tx_done = 1;
+ }
+ }
+
+ slgt_irq_off(info, IRQ_TXDATA);
+ slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE);
+ /* clear tx idle and underrun status bits */
+ wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
+
+ if (!(rd_reg32(info, TDCSR) & BIT0)) {
+ /* tx DMA stopped, restart tx DMA */
+ tdma_reset(info);
+ /* set 1st descriptor address */
+ wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
+ if (info->params.mode == MGSL_MODE_RAW)
+ wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
+ else
+ wr_reg32(info, TDCSR, BIT0); /* DMA enable */
+ }
+
+ if (info->params.mode != MGSL_MODE_RAW) {
+ info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
+ add_timer(&info->tx_timer);
+ }
+ } else {
+ tdma_reset(info);
+ /* set 1st descriptor address */
+ wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
+
+ slgt_irq_off(info, IRQ_TXDATA);
+ slgt_irq_on(info, IRQ_TXIDLE);
+ /* clear tx idle status bit */
+ wr_reg16(info, SSR, IRQ_TXIDLE);
+
+ /* enable tx DMA */
+ wr_reg32(info, TDCSR, BIT0);
+ }
+
+ info->tx_active = 1;
+ }
+}
+
+static void tx_stop(struct slgt_info *info)
+{
+ unsigned short val;
+
+ del_timer(&info->tx_timer);
+
+ tdma_reset(info);
+
+ /* reset and disable transmitter */
+ val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */
+ wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, TCR, val); /* clear reset */
+
+ slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+
+ /* clear tx idle and underrun status bit */
+ wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
+
+ reset_tbufs(info);
+
+ info->tx_enabled = 0;
+ info->tx_active = 0;
+}
+
+static void reset_port(struct slgt_info *info)
+{
+ if (!info->reg_addr)
+ return;
+
+ tx_stop(info);
+ rx_stop(info);
+
+ info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+ set_signals(info);
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+}
+
+static void reset_adapter(struct slgt_info *info)
+{
+ int i;
+ for (i=0; i < info->port_count; ++i) {
+ if (info->port_array[i])
+ reset_port(info->port_array[i]);
+ }
+}
+
+static void async_mode(struct slgt_info *info)
+{
+ unsigned short val;
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+ tx_stop(info);
+ rx_stop(info);
+
+ /* TCR (tx control)
+ *
+ * 15..13 mode, 010=async
+ * 12..10 encoding, 000=NRZ
+ * 09 parity enable
+ * 08 1=odd parity, 0=even parity
+ * 07 1=RTS driver control
+ * 06 1=break enable
+ * 05..04 character length
+ * 00=5 bits
+ * 01=6 bits
+ * 10=7 bits
+ * 11=8 bits
+ * 03 0=1 stop bit, 1=2 stop bits
+ * 02 reset
+ * 01 enable
+ * 00 auto-CTS enable
+ */
+ val = 0x4000;
+
+ if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+ val |= BIT7;
+
+ if (info->params.parity != ASYNC_PARITY_NONE) {
+ val |= BIT9;
+ if (info->params.parity == ASYNC_PARITY_ODD)
+ val |= BIT8;
+ }
+
+ switch (info->params.data_bits)
+ {
+ case 6: val |= BIT4; break;
+ case 7: val |= BIT5; break;
+ case 8: val |= BIT5 + BIT4; break;
+ }
+
+ if (info->params.stop_bits != 1)
+ val |= BIT3;
+
+ if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+ val |= BIT0;
+
+ wr_reg16(info, TCR, val);
+
+ /* RCR (rx control)
+ *
+ * 15..13 mode, 010=async
+ * 12..10 encoding, 000=NRZ
+ * 09 parity enable
+ * 08 1=odd parity, 0=even parity
+ * 07..06 reserved, must be 0
+ * 05..04 character length
+ * 00=5 bits
+ * 01=6 bits
+ * 10=7 bits
+ * 11=8 bits
+ * 03 reserved, must be zero
+ * 02 reset
+ * 01 enable
+ * 00 auto-DCD enable
+ */
+ val = 0x4000;
+
+ if (info->params.parity != ASYNC_PARITY_NONE) {
+ val |= BIT9;
+ if (info->params.parity == ASYNC_PARITY_ODD)
+ val |= BIT8;
+ }
+
+ switch (info->params.data_bits)
+ {
+ case 6: val |= BIT4; break;
+ case 7: val |= BIT5; break;
+ case 8: val |= BIT5 + BIT4; break;
+ }
+
+ if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+ val |= BIT0;
+
+ wr_reg16(info, RCR, val);
+
+ /* CCR (clock control)
+ *
+ * 07..05 011 = tx clock source is BRG/16
+ * 04..02 010 = rx clock source is BRG
+ * 01 0 = auxclk disabled
+ * 00 1 = BRG enabled
+ *
+ * 0110 1001
+ */
+ wr_reg8(info, CCR, 0x69);
+
+ msc_set_vcr(info);
+
+ tx_set_idle(info);
+
+ /* SCR (serial control)
+ *
+ * 15 1=tx req on FIFO half empty
+ * 14 1=rx req on FIFO half full
+ * 13 tx data IRQ enable
+ * 12 tx idle IRQ enable
+ * 11 rx break on IRQ enable
+ * 10 rx data IRQ enable
+ * 09 rx break off IRQ enable
+ * 08 overrun IRQ enable
+ * 07 DSR IRQ enable
+ * 06 CTS IRQ enable
+ * 05 DCD IRQ enable
+ * 04 RI IRQ enable
+ * 03 reserved, must be zero
+ * 02 1=txd->rxd internal loopback enable
+ * 01 reserved, must be zero
+ * 00 1=master IRQ enable
+ */
+ val = BIT15 + BIT14 + BIT0;
+ wr_reg16(info, SCR, val);
+
+ slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER);
+
+ set_rate(info, info->params.data_rate * 16);
+
+ if (info->params.loopback)
+ enable_loopback(info);
+}
+
+static void hdlc_mode(struct slgt_info *info)
+{
+ unsigned short val;
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+ tx_stop(info);
+ rx_stop(info);
+
+ /* TCR (tx control)
+ *
+ * 15..13 mode, 000=HDLC 001=raw sync
+ * 12..10 encoding
+ * 09 CRC enable
+ * 08 CRC32
+ * 07 1=RTS driver control
+ * 06 preamble enable
+ * 05..04 preamble length
+ * 03 share open/close flag
+ * 02 reset
+ * 01 enable
+ * 00 auto-CTS enable
+ */
+ val = 0;
+
+ if (info->params.mode == MGSL_MODE_RAW)
+ val |= BIT13;
+ if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+ val |= BIT7;
+
+ switch(info->params.encoding)
+ {
+ case HDLC_ENCODING_NRZB: val |= BIT10; break;
+ case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break;
+ case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break;
+ case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
+ case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
+ }
+
+ switch (info->params.crc_type)
+ {
+ case HDLC_CRC_16_CCITT: val |= BIT9; break;
+ case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
+ }
+
+ if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
+ val |= BIT6;
+
+ switch (info->params.preamble_length)
+ {
+ case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break;
+ case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break;
+ case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break;
+ }
+
+ if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+ val |= BIT0;
+
+ wr_reg16(info, TCR, val);
+
+ /* TPR (transmit preamble) */
+
+ switch (info->params.preamble)
+ {
+ case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break;
+ case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break;
+ case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break;
+ case HDLC_PREAMBLE_PATTERN_10: val = 0x55; break;
+ case HDLC_PREAMBLE_PATTERN_01: val = 0xaa; break;
+ default: val = 0x7e; break;
+ }
+ wr_reg8(info, TPR, (unsigned char)val);
+
+ /* RCR (rx control)
+ *
+ * 15..13 mode, 000=HDLC 001=raw sync
+ * 12..10 encoding
+ * 09 CRC enable
+ * 08 CRC32
+ * 07..03 reserved, must be 0
+ * 02 reset
+ * 01 enable
+ * 00 auto-DCD enable
+ */
+ val = 0;
+
+ if (info->params.mode == MGSL_MODE_RAW)
+ val |= BIT13;
+
+ switch(info->params.encoding)
+ {
+ case HDLC_ENCODING_NRZB: val |= BIT10; break;
+ case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break;
+ case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break;
+ case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
+ case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
+ }
+
+ switch (info->params.crc_type)
+ {
+ case HDLC_CRC_16_CCITT: val |= BIT9; break;
+ case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
+ }
+
+ if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+ val |= BIT0;
+
+ wr_reg16(info, RCR, val);
+
+ /* CCR (clock control)
+ *
+ * 07..05 tx clock source
+ * 04..02 rx clock source
+ * 01 auxclk enable
+ * 00 BRG enable
+ */
+ val = 0;
+
+ if (info->params.flags & HDLC_FLAG_TXC_BRG)
+ {
+ // when RxC source is DPLL, BRG generates 16X DPLL
+ // reference clock, so take TxC from BRG/16 to get
+ // transmit clock at actual data rate
+ if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+ val |= BIT6 + BIT5; /* 011, txclk = BRG/16 */
+ else
+ val |= BIT6; /* 010, txclk = BRG */
+ }
+ else if (info->params.flags & HDLC_FLAG_TXC_DPLL)
+ val |= BIT7; /* 100, txclk = DPLL Input */
+ else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN)
+ val |= BIT5; /* 001, txclk = RXC Input */
+
+ if (info->params.flags & HDLC_FLAG_RXC_BRG)
+ val |= BIT3; /* 010, rxclk = BRG */
+ else if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+ val |= BIT4; /* 100, rxclk = DPLL */
+ else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN)
+ val |= BIT2; /* 001, rxclk = TXC Input */
+
+ if (info->params.clock_speed)
+ val |= BIT1 + BIT0;
+
+ wr_reg8(info, CCR, (unsigned char)val);
+
+ if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL))
+ {
+ // program DPLL mode
+ switch(info->params.encoding)
+ {
+ case HDLC_ENCODING_BIPHASE_MARK:
+ case HDLC_ENCODING_BIPHASE_SPACE:
+ val = BIT7; break;
+ case HDLC_ENCODING_BIPHASE_LEVEL:
+ case HDLC_ENCODING_DIFF_BIPHASE_LEVEL:
+ val = BIT7 + BIT6; break;
+ default: val = BIT6; // NRZ encodings
+ }
+ wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val));
+
+ // DPLL requires a 16X reference clock from BRG
+ set_rate(info, info->params.clock_speed * 16);
+ }
+ else
+ set_rate(info, info->params.clock_speed);
+
+ tx_set_idle(info);
+
+ msc_set_vcr(info);
+
+ /* SCR (serial control)
+ *
+ * 15 1=tx req on FIFO half empty
+ * 14 1=rx req on FIFO half full
+ * 13 tx data IRQ enable
+ * 12 tx idle IRQ enable
+ * 11 underrun IRQ enable
+ * 10 rx data IRQ enable
+ * 09 rx idle IRQ enable
+ * 08 overrun IRQ enable
+ * 07 DSR IRQ enable
+ * 06 CTS IRQ enable
+ * 05 DCD IRQ enable
+ * 04 RI IRQ enable
+ * 03 reserved, must be zero
+ * 02 1=txd->rxd internal loopback enable
+ * 01 reserved, must be zero
+ * 00 1=master IRQ enable
+ */
+ wr_reg16(info, SCR, BIT15 + BIT14 + BIT0);
+
+ if (info->params.loopback)
+ enable_loopback(info);
+}
+
+/*
+ * set transmit idle mode
+ */
+static void tx_set_idle(struct slgt_info *info)
+{
+ unsigned char val = 0xff;
+
+ switch(info->idle_mode)
+ {
+ case HDLC_TXIDLE_FLAGS: val = 0x7e; break;
+ case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break;
+ case HDLC_TXIDLE_ZEROS: val = 0x00; break;
+ case HDLC_TXIDLE_ONES: val = 0xff; break;
+ case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
+ case HDLC_TXIDLE_SPACE: val = 0x00; break;
+ case HDLC_TXIDLE_MARK: val = 0xff; break;
+ }
+
+ wr_reg8(info, TIR, val);
+}
+
+/*
+ * get state of V24 status (input) signals
+ */
+static void get_signals(struct slgt_info *info)
+{
+ unsigned short status = rd_reg16(info, SSR);
+
+ /* clear all serial signals except DTR and RTS */
+ info->signals &= SerialSignal_DTR + SerialSignal_RTS;
+
+ if (status & BIT3)
+ info->signals |= SerialSignal_DSR;
+ if (status & BIT2)
+ info->signals |= SerialSignal_CTS;
+ if (status & BIT1)
+ info->signals |= SerialSignal_DCD;
+ if (status & BIT0)
+ info->signals |= SerialSignal_RI;
+}
+
+/*
+ * set V.24 Control Register based on current configuration
+ */
+static void msc_set_vcr(struct slgt_info *info)
+{
+ unsigned char val = 0;
+
+ /* VCR (V.24 control)
+ *
+ * 07..04 serial IF select
+ * 03 DTR
+ * 02 RTS
+ * 01 LL
+ * 00 RL
+ */
+
+ switch(info->if_mode & MGSL_INTERFACE_MASK)
+ {
+ case MGSL_INTERFACE_RS232:
+ val |= BIT5; /* 0010 */
+ break;
+ case MGSL_INTERFACE_V35:
+ val |= BIT7 + BIT6 + BIT5; /* 1110 */
+ break;
+ case MGSL_INTERFACE_RS422:
+ val |= BIT6; /* 0100 */
+ break;
+ }
+
+ if (info->signals & SerialSignal_DTR)
+ val |= BIT3;
+ if (info->signals & SerialSignal_RTS)
+ val |= BIT2;
+ if (info->if_mode & MGSL_INTERFACE_LL)
+ val |= BIT1;
+ if (info->if_mode & MGSL_INTERFACE_RL)
+ val |= BIT0;
+ wr_reg8(info, VCR, val);
+}
+
+/*
+ * set state of V24 control (output) signals
+ */
+static void set_signals(struct slgt_info *info)
+{
+ unsigned char val = rd_reg8(info, VCR);
+ if (info->signals & SerialSignal_DTR)
+ val |= BIT3;
+ else
+ val &= ~BIT3;
+ if (info->signals & SerialSignal_RTS)
+ val |= BIT2;
+ else
+ val &= ~BIT2;
+ wr_reg8(info, VCR, val);
+}
+
+/*
+ * free range of receive DMA buffers (i to last)
+ */
+static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last)
+{
+ int done = 0;
+
+ while(!done) {
+ /* reset current buffer for reuse */
+ info->rbufs[i].status = 0;
+ if (info->params.mode == MGSL_MODE_RAW)
+ set_desc_count(info->rbufs[i], info->raw_rx_size);
+ else
+ set_desc_count(info->rbufs[i], DMABUFSIZE);
+
+ if (i == last)
+ done = 1;
+ if (++i == info->rbuf_count)
+ i = 0;
+ }
+ info->rbuf_current = i;
+}
+
+/*
+ * mark all receive DMA buffers as free
+ */
+static void reset_rbufs(struct slgt_info *info)
+{
+ free_rbufs(info, 0, info->rbuf_count - 1);
+}
+
+/*
+ * pass receive HDLC frame to upper layer
+ *
+ * return 1 if frame available, otherwise 0
+ */
+static int rx_get_frame(struct slgt_info *info)
+{
+ unsigned int start, end;
+ unsigned short status;
+ unsigned int framesize = 0;
+ int rc = 0;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+ unsigned char addr_field = 0xff;
+
+check_again:
+
+ framesize = 0;
+ addr_field = 0xff;
+ start = end = info->rbuf_current;
+
+ for (;;) {
+ if (!desc_complete(info->rbufs[end]))
+ goto cleanup;
+
+ if (framesize == 0 && info->params.addr_filter != 0xff)
+ addr_field = info->rbufs[end].buf[0];
+
+ framesize += desc_count(info->rbufs[end]);
+
+ if (desc_eof(info->rbufs[end]))
+ break;
+
+ if (++end == info->rbuf_count)
+ end = 0;
+
+ if (end == info->rbuf_current) {
+ if (info->rx_enabled){
+ spin_lock_irqsave(&info->lock,flags);
+ rx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+ goto cleanup;
+ }
+ }
+
+ /* status
+ *
+ * 15 buffer complete
+ * 14..06 reserved
+ * 05..04 residue
+ * 02 eof (end of frame)
+ * 01 CRC error
+ * 00 abort
+ */
+ status = desc_status(info->rbufs[end]);
+
+ /* ignore CRC bit if not using CRC (bit is undefined) */
+ if (info->params.crc_type == HDLC_CRC_NONE)
+ status &= ~BIT1;
+
+ if (framesize == 0 ||
+ (addr_field != 0xff && addr_field != info->params.addr_filter)) {
+ free_rbufs(info, start, end);
+ goto check_again;
+ }
+
+ if (framesize < 2 || status & (BIT1+BIT0)) {
+ if (framesize < 2 || (status & BIT0))
+ info->icount.rxshort++;
+ else
+ info->icount.rxcrc++;
+ framesize = 0;
+
+#ifdef CONFIG_HDLC
+ {
+ struct net_device_stats *stats = hdlc_stats(info->netdev);
+ stats->rx_errors++;
+ stats->rx_frame_errors++;
+ }
+#endif
+ } else {
+ /* adjust frame size for CRC, if any */
+ if (info->params.crc_type == HDLC_CRC_16_CCITT)
+ framesize -= 2;
+ else if (info->params.crc_type == HDLC_CRC_32_CCITT)
+ framesize -= 4;
+ }
+
+ DBGBH(("%s rx frame status=%04X size=%d\n",
+ info->device_name, status, framesize));
+ DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
+
+ if (framesize) {
+ if (framesize > info->max_frame_size)
+ info->icount.rxlong++;
+ else {
+ /* copy dma buffer(s) to contiguous temp buffer */
+ int copy_count = framesize;
+ int i = start;
+ unsigned char *p = info->tmp_rbuf;
+ info->tmp_rbuf_count = framesize;
+
+ info->icount.rxok++;
+
+ while(copy_count) {
+ int partial_count = min(copy_count, DMABUFSIZE);
+ memcpy(p, info->rbufs[i].buf, partial_count);
+ p += partial_count;
+ copy_count -= partial_count;
+ if (++i == info->rbuf_count)
+ i = 0;
+ }
+
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_rx(info,info->tmp_rbuf, framesize);
+ else
+#endif
+ ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize);
+ }
+ }
+ free_rbufs(info, start, end);
+ rc = 1;
+
+cleanup:
+ return rc;
+}
+
+/*
+ * pass receive buffer (RAW synchronous mode) to tty layer
+ * return 1 if buffer available, otherwise 0
+ */
+static int rx_get_buf(struct slgt_info *info)
+{
+ unsigned int i = info->rbuf_current;
+
+ if (!desc_complete(info->rbufs[i]))
+ return 0;
+ DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx");
+ DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i])));
+ ldisc_receive_buf(info->tty, info->rbufs[i].buf,
+ info->flag_buf, desc_count(info->rbufs[i]));
+ free_rbufs(info, i, i);
+ return 1;
+}
+
+static void reset_tbufs(struct slgt_info *info)
+{
+ unsigned int i;
+ info->tbuf_current = 0;
+ for (i=0 ; i < info->tbuf_count ; i++) {
+ info->tbufs[i].status = 0;
+ info->tbufs[i].count = 0;
+ }
+}
+
+/*
+ * return number of free transmit DMA buffers
+ */
+static unsigned int free_tbuf_count(struct slgt_info *info)
+{
+ unsigned int count = 0;
+ unsigned int i = info->tbuf_current;
+
+ do
+ {
+ if (desc_count(info->tbufs[i]))
+ break; /* buffer in use */
+ ++count;
+ if (++i == info->tbuf_count)
+ i=0;
+ } while (i != info->tbuf_current);
+
+ /* last buffer with zero count may be in use, assume it is */
+ if (count)
+ --count;
+
+ return count;
+}
+
+/*
+ * load transmit DMA buffer(s) with data
+ */
+static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
+{
+ unsigned short count;
+ unsigned int i;
+ struct slgt_desc *d;
+
+ if (size == 0)
+ return;
+
+ DBGDATA(info, buf, size, "tx");
+
+ info->tbuf_start = i = info->tbuf_current;
+
+ while (size) {
+ d = &info->tbufs[i];
+ if (++i == info->tbuf_count)
+ i = 0;
+
+ count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
+ memcpy(d->buf, buf, count);
+
+ size -= count;
+ buf += count;
+
+ if (!size && info->params.mode != MGSL_MODE_RAW)
+ set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */
+ else
+ set_desc_eof(*d, 0);
+
+ set_desc_count(*d, count);
+ }
+
+ info->tbuf_current = i;
+}
+
+static int register_test(struct slgt_info *info)
+{
+ static unsigned short patterns[] =
+ {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696};
+ static unsigned int count = sizeof(patterns)/sizeof(patterns[0]);
+ unsigned int i;
+ int rc = 0;
+
+ for (i=0 ; i < count ; i++) {
+ wr_reg16(info, TIR, patterns[i]);
+ wr_reg16(info, BDR, patterns[(i+1)%count]);
+ if ((rd_reg16(info, TIR) != patterns[i]) ||
+ (rd_reg16(info, BDR) != patterns[(i+1)%count])) {
+ rc = -ENODEV;
+ break;
+ }
+ }
+
+ info->init_error = rc ? 0 : DiagStatus_AddressFailure;
+ return rc;
+}
+
+static int irq_test(struct slgt_info *info)
+{
+ unsigned long timeout;
+ unsigned long flags;
+ struct tty_struct *oldtty = info->tty;
+ u32 speed = info->params.data_rate;
+
+ info->params.data_rate = 921600;
+ info->tty = NULL;
+
+ spin_lock_irqsave(&info->lock, flags);
+ async_mode(info);
+ slgt_irq_on(info, IRQ_TXIDLE);
+
+ /* enable transmitter */
+ wr_reg16(info, TCR,
+ (unsigned short)(rd_reg16(info, TCR) | BIT1));
+
+ /* write one byte and wait for tx idle */
+ wr_reg16(info, TDR, 0);
+
+ /* assume failure */
+ info->init_error = DiagStatus_IrqFailure;
+ info->irq_occurred = FALSE;
+
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ timeout=100;
+ while(timeout-- && !info->irq_occurred)
+ msleep_interruptible(10);
+
+ spin_lock_irqsave(&info->lock,flags);
+ reset_port(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ info->params.data_rate = speed;
+ info->tty = oldtty;
+
+ info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure;
+ return info->irq_occurred ? 0 : -ENODEV;
+}
+
+static int loopback_test_rx(struct slgt_info *info)
+{
+ unsigned char *src, *dest;
+ int count;
+
+ if (desc_complete(info->rbufs[0])) {
+ count = desc_count(info->rbufs[0]);
+ src = info->rbufs[0].buf;
+ dest = info->tmp_rbuf;
+
+ for( ; count ; count-=2, src+=2) {
+ /* src=data byte (src+1)=status byte */
+ if (!(*(src+1) & (BIT9 + BIT8))) {
+ *dest = *src;
+ dest++;
+ info->tmp_rbuf_count++;
+ }
+ }
+ DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx");
+ return 1;
+ }
+ return 0;
+}
+
+static int loopback_test(struct slgt_info *info)
+{
+#define TESTFRAMESIZE 20
+
+ unsigned long timeout;
+ u16 count = TESTFRAMESIZE;
+ unsigned char buf[TESTFRAMESIZE];
+ int rc = -ENODEV;
+ unsigned long flags;
+
+ struct tty_struct *oldtty = info->tty;
+ MGSL_PARAMS params;
+
+ memcpy(&params, &info->params, sizeof(params));
+
+ info->params.mode = MGSL_MODE_ASYNC;
+ info->params.data_rate = 921600;
+ info->params.loopback = 1;
+ info->tty = NULL;
+
+ /* build and send transmit frame */
+ for (count = 0; count < TESTFRAMESIZE; ++count)
+ buf[count] = (unsigned char)count;
+
+ info->tmp_rbuf_count = 0;
+ memset(info->tmp_rbuf, 0, TESTFRAMESIZE);
+
+ /* program hardware for HDLC and enabled receiver */
+ spin_lock_irqsave(&info->lock,flags);
+ async_mode(info);
+ rx_start(info);
+ info->tx_count = count;
+ tx_load(info, buf, count);
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ /* wait for receive complete */
+ for (timeout = 100; timeout; --timeout) {
+ msleep_interruptible(10);
+ if (loopback_test_rx(info)) {
+ rc = 0;
+ break;
+ }
+ }
+
+ /* verify received frame length and contents */
+ if (!rc && (info->tmp_rbuf_count != count ||
+ memcmp(buf, info->tmp_rbuf, count))) {
+ rc = -ENODEV;
+ }
+
+ spin_lock_irqsave(&info->lock,flags);
+ reset_adapter(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ memcpy(&info->params, &params, sizeof(info->params));
+ info->tty = oldtty;
+
+ info->init_error = rc ? DiagStatus_DmaFailure : 0;
+ return rc;
+}
+
+static int adapter_test(struct slgt_info *info)
+{
+ DBGINFO(("testing %s\n", info->device_name));
+ if ((info->init_error = register_test(info)) < 0) {
+ printk("register test failure %s addr=%08X\n",
+ info->device_name, info->phys_reg_addr);
+ } else if ((info->init_error = irq_test(info)) < 0) {
+ printk("IRQ test failure %s IRQ=%d\n",
+ info->device_name, info->irq_level);
+ } else if ((info->init_error = loopback_test(info)) < 0) {
+ printk("loopback test failure %s\n", info->device_name);
+ }
+ return info->init_error;
+}
+
+/*
+ * transmit timeout handler
+ */
+static void tx_timeout(unsigned long context)
+{
+ struct slgt_info *info = (struct slgt_info*)context;
+ unsigned long flags;
+
+ DBGINFO(("%s tx_timeout\n", info->device_name));
+ if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
+ info->icount.txtimeout++;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+ info->tx_active = 0;
+ info->tx_count = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_tx_done(info);
+ else
+#endif
+ bh_transmit(info);
+}
+
+/*
+ * receive buffer polling timer
+ */
+static void rx_timeout(unsigned long context)
+{
+ struct slgt_info *info = (struct slgt_info*)context;
+ unsigned long flags;
+
+ DBGINFO(("%s rx_timeout\n", info->device_name));
+ spin_lock_irqsave(&info->lock, flags);
+ info->pending_bh |= BH_RECEIVE;
+ spin_unlock_irqrestore(&info->lock, flags);
+ bh_handler(info);
+}
+
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ee5a40be9f99..960adb256fbb 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2196,7 +2196,7 @@ void isr_rxint(SLMP_INFO * info)
if ( tty ) {
if (!(status & info->ignore_status_mask1)) {
if (info->read_status_mask1 & BRKD) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
if (info->flags & ASYNC_SAK)
do_SAK(tty);
}
@@ -2240,16 +2240,10 @@ void isr_rxrdy(SLMP_INFO * info)
while((status = read_reg(info,CST0)) & BIT0)
{
+ int flag = 0;
+ int over = 0;
DataByte = read_reg(info,TRB);
- if ( tty ) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = DataByte;
- *tty->flip.flag_buf_ptr = 0;
- }
-
icount->rx++;
if ( status & (PE + FRME + OVRN) ) {
@@ -2272,42 +2266,34 @@ void isr_rxrdy(SLMP_INFO * info)
if ( tty ) {
if (status & PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & FRME)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
if (status & OVRN) {
/* Overrun is special, since it's
* reported immediately, and doesn't
* affect the current character
*/
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
+ over = 1;
}
}
} /* end of if (error) */
if ( tty ) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, DataByte, flag);
+ if (over)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
}
if ( debug_level >= DEBUG_LEVEL_ISR ) {
- printk("%s(%d):%s isr_rxrdy() flip count=%d\n",
- __FILE__,__LINE__,info->device_name,
- tty ? tty->flip.count : 0);
printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
__FILE__,__LINE__,info->device_name,
icount->rx,icount->brk,icount->parity,
icount->frame,icount->overrun);
}
- if ( tty && tty->flip.count )
+ if ( tty )
tty_flip_buffer_push(tty);
}
@@ -5104,7 +5090,7 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
int register_test(SLMP_INFO *info)
{
static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
- static unsigned int count = sizeof(testval)/sizeof(unsigned char);
+ static unsigned int count = ARRAY_SIZE(testval);
unsigned int i;
int rc = TRUE;
unsigned long flags;
@@ -5422,7 +5408,7 @@ int memory_test(SLMP_INFO *info)
{
static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
- unsigned long count = sizeof(testval)/sizeof(unsigned long);
+ unsigned long count = ARRAY_SIZE(testval);
unsigned long i;
unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long);
unsigned long * addr = (unsigned long *)info->memory_base;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 145275ebdd7e..5765f672e853 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -153,6 +153,21 @@ static struct sysrq_key_op sysrq_mountro_op = {
/* END SYNC SYSRQ HANDLERS BLOCK */
+#ifdef CONFIG_DEBUG_MUTEXES
+
+static void
+sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+{
+ mutex_debug_show_all_locks();
+}
+
+static struct sysrq_key_op sysrq_showlocks_op = {
+ .handler = sysrq_handle_showlocks,
+ .help_msg = "show-all-locks(D)",
+ .action_msg = "Show Locks Held",
+};
+
+#endif
/* SHOW SYSRQ HANDLERS BLOCK */
@@ -294,7 +309,11 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
#else
/* c */ NULL,
#endif
+#ifdef CONFIG_DEBUG_MUTEXES
+/* d */ &sysrq_showlocks_op,
+#else
/* d */ NULL,
+#endif
/* e */ &sysrq_term_op,
/* f */ &sysrq_moom_op,
/* g */ NULL,
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index b3d411a756fe..ac2a297ce37c 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -1,7 +1,7 @@
/*
* Driver for TANBAC TB0219 base board.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/tb0219.h>
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 12167c04fa4c..4c272189cd42 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -34,7 +34,6 @@
#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>
@@ -156,6 +155,8 @@ 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 :
+received_ref_clk3a :
+received_ref_clk3b :
enable_clk3a_output :
enable_clk3b_output :
enable_clka0_output :
@@ -165,7 +166,7 @@ enable_clkb1_output :
filter_select :
hardware_switching :
hardware_switching_mode :
-interrupt_switch :
+telclock_version :
mode_select :
refalign :
reset :
@@ -173,7 +174,6 @@ 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.
@@ -211,7 +211,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
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");
+ printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
return -EBUSY;
}
inb(TLCLK_REG6); /* Clear interrupt events */
@@ -226,7 +226,7 @@ static int tlclk_release(struct inode *inode, struct file *filp)
return 0;
}
-ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
+static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
if (count < sizeof(struct tlclk_alarms))
@@ -242,7 +242,7 @@ ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
return sizeof(struct tlclk_alarms);
}
-ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
+static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
return 0;
@@ -278,21 +278,21 @@ static ssize_t show_current_ref(struct device *d,
static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
-static ssize_t show_interrupt_switch(struct device *d,
+static ssize_t show_telclock_version(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);
+ ret_val = inb(TLCLK_REG5);
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 DEVICE_ATTR(telclock_version, S_IRUGO,
+ show_telclock_version, NULL);
static ssize_t show_alarms(struct device *d,
struct device_attribute *attr, char *buf)
@@ -309,6 +309,50 @@ static ssize_t show_alarms(struct device *d,
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t store_received_ref_clk3a(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, 0xef, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+ store_received_ref_clk3a);
+
+
+static ssize_t store_received_ref_clk3b(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, 0xef, val << 1);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+ store_received_ref_clk3b);
+
+
static ssize_t store_enable_clk3b_output(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -436,26 +480,6 @@ static ssize_t store_enable_clka0_output(struct device *d,
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)
{
@@ -475,7 +499,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
switch (val) {
case CLK_8_592MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
break;
case CLK_11_184MHz:
SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
@@ -484,7 +508,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
break;
case CLK_44_736MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
break;
}
} else
@@ -653,9 +677,7 @@ static ssize_t store_refalign (struct device *d,
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);
@@ -706,15 +728,16 @@ 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_telclock_version.attr,
&dev_attr_alarms.attr,
+ &dev_attr_received_ref_clk3a.attr,
+ &dev_attr_received_ref_clk3b.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,
@@ -741,7 +764,7 @@ static int __init tlclk_init(void)
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);
+ printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
return ret;
}
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
@@ -750,7 +773,7 @@ static int __init tlclk_init(void)
/* 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",
+ printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
TLCLK_BASE);
ret = -EBUSY;
goto out2;
@@ -758,7 +781,7 @@ static int __init tlclk_init(void)
telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
- printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw\n",
+ printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw.\n",
telclk_interrupt);
ret = -ENXIO;
goto out3;
@@ -768,7 +791,7 @@ static int __init tlclk_init(void)
ret = misc_register(&tlclk_miscdev);
if (ret < 0) {
- printk(KERN_ERR " misc_register retruns %d\n", ret);
+ printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
ret = -EBUSY;
goto out3;
}
@@ -776,8 +799,7 @@ static int __init tlclk_init(void)
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);
+ printk(KERN_ERR "tlclk: platform_device_register failed.\n");
ret = -EBUSY;
goto out4;
}
@@ -785,7 +807,7 @@ static int __init tlclk_init(void)
ret = sysfs_create_group(&tlclk_device->dev.kobj,
&tlclk_attribute_group);
if (ret) {
- printk(KERN_ERR "failed to create sysfs device attributes\n");
+ printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n");
sysfs_remove_group(&tlclk_device->dev.kobj,
&tlclk_attribute_group);
goto out5;
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 2392e404e8d1..ba4582d160fd 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,6 +2,9 @@
# Makefile for the kernel tpm device drivers.
#
obj-$(CONFIG_TCG_TPM) += tpm.o
+ifdef CONFIG_ACPI
+ obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+endif
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index a9be0e8eaea5..5a3870477ef1 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -466,6 +466,7 @@ void tpm_remove_hardware(struct device *dev)
kfree(chip->vendor->miscdev.name);
sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+ tpm_bios_log_teardown(chip->bios_dir);
dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
@@ -593,6 +594,8 @@ dev_num_search_complete:
sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+ chip->bios_dir = tpm_bios_log_setup(devname);
+
return 0;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 159882ca69dd..fd3a4beaa53d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -82,6 +82,8 @@ struct tpm_chip {
struct tpm_vendor_specific *vendor;
+ struct dentry **bios_dir;
+
struct list_head list;
};
@@ -107,3 +109,16 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
extern void tpm_remove_hardware(struct device *);
extern int tpm_pm_suspend(struct device *, pm_message_t);
extern int tpm_pm_resume(struct device *);
+
+#ifdef CONFIG_ACPI
+extern struct dentry ** tpm_bios_log_setup(char *);
+extern void tpm_bios_log_teardown(struct dentry **);
+#else
+static inline struct dentry* tpm_bios_log_setup(char *name)
+{
+ return NULL;
+}
+static inline void tpm_bios_log_teardown(struct dentry **dir)
+{
+}
+#endif
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
new file mode 100644
index 000000000000..aedf7a8e6da7
--- /dev/null
+++ b/drivers/char/tpm/tpm_bios.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Authors:
+ * Seiji Munetoh <munetoh@jp.ibm.com>
+ * Stefan Berger <stefanb@us.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Access to the eventlog extended by the TCG BIOS of PC platform
+ *
+ * This program is free software; you can redistribute 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <acpi/acpi.h>
+#include <acpi/actypes.h>
+#include <acpi/actbl.h>
+#include "tpm.h"
+
+#define TCG_EVENT_NAME_LEN_MAX 255
+#define MAX_TEXT_EVENT 1000 /* Max event string length */
+#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
+
+struct tpm_bios_log {
+ void *bios_event_log;
+ void *bios_event_log_end;
+};
+
+struct acpi_tcpa {
+ struct acpi_table_header hdr;
+ u16 reserved;
+ u32 log_max_len __attribute__ ((packed));
+ u32 log_start_addr __attribute__ ((packed));
+};
+
+struct tcpa_event {
+ u32 pcr_index;
+ u32 event_type;
+ u8 pcr_value[20]; /* SHA1 */
+ u32 event_size;
+ u8 event_data[0];
+};
+
+enum tcpa_event_types {
+ PREBOOT = 0,
+ POST_CODE,
+ UNUSED,
+ NO_ACTION,
+ SEPARATOR,
+ ACTION,
+ EVENT_TAG,
+ SCRTM_CONTENTS,
+ SCRTM_VERSION,
+ CPU_MICROCODE,
+ PLATFORM_CONFIG_FLAGS,
+ TABLE_OF_DEVICES,
+ COMPACT_HASH,
+ IPL,
+ IPL_PARTITION_DATA,
+ NONHOST_CODE,
+ NONHOST_CONFIG,
+ NONHOST_INFO,
+};
+
+static const char* tcpa_event_type_strings[] = {
+ "PREBOOT",
+ "POST CODE",
+ "",
+ "NO ACTION",
+ "SEPARATOR",
+ "ACTION",
+ "EVENT TAG",
+ "S-CRTM Contents",
+ "S-CRTM Version",
+ "CPU Microcode",
+ "Platform Config Flags",
+ "Table of Devices",
+ "Compact Hash",
+ "IPL",
+ "IPL Partition Data",
+ "Non-Host Code",
+ "Non-Host Config",
+ "Non-Host Info"
+};
+
+enum tcpa_pc_event_ids {
+ SMBIOS = 1,
+ BIS_CERT,
+ POST_BIOS_ROM,
+ ESCD,
+ CMOS,
+ NVRAM,
+ OPTION_ROM_EXEC,
+ OPTION_ROM_CONFIG,
+ OPTION_ROM_MICROCODE,
+ S_CRTM_VERSION,
+ S_CRTM_CONTENTS,
+ POST_CONTENTS,
+};
+
+static const char* tcpa_pc_event_id_strings[] = {
+ ""
+ "SMBIOS",
+ "BIS Certificate",
+ "POST BIOS ",
+ "ESCD ",
+ "CMOS",
+ "NVRAM",
+ "Option ROM",
+ "Option ROM config",
+ "Option ROM microcode",
+ "S-CRTM Version",
+ "S-CRTM Contents",
+ "S-CRTM POST Contents",
+};
+
+/* returns pointer to start of pos. entry of tcg log */
+static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t i;
+ struct tpm_bios_log *log = m->private;
+ void *addr = log->bios_event_log;
+ void *limit = log->bios_event_log_end;
+ struct tcpa_event *event;
+
+ /* read over *pos measurements */
+ for (i = 0; i < *pos; i++) {
+ event = addr;
+
+ if ((addr + sizeof(struct tcpa_event)) < limit) {
+ if (event->event_type == 0 && event->event_size == 0)
+ return NULL;
+ addr += sizeof(struct tcpa_event) + event->event_size;
+ }
+ }
+
+ /* now check if current entry is valid */
+ if ((addr + sizeof(struct tcpa_event)) >= limit)
+ return NULL;
+
+ event = addr;
+
+ if ((event->event_type == 0 && event->event_size == 0) ||
+ ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
+ return NULL;
+
+ return addr;
+}
+
+static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
+ loff_t *pos)
+{
+ struct tcpa_event *event = v;
+ struct tpm_bios_log *log = m->private;
+ void *limit = log->bios_event_log_end;
+
+ v += sizeof(struct tcpa_event) + event->event_size;
+
+ /* now check if current entry is valid */
+ if ((v + sizeof(struct tcpa_event)) >= limit)
+ return NULL;
+
+ event = v;
+
+ if (event->event_type == 0 && event->event_size == 0)
+ return NULL;
+
+ if ((event->event_type == 0 && event->event_size == 0) ||
+ ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
+ return NULL;
+
+ (*pos)++;
+ return v;
+}
+
+static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static int get_event_name(char *dest, struct tcpa_event *event,
+ unsigned char * event_entry)
+{
+ const char *name = "";
+ char data[40] = "";
+ int i, n_len = 0, d_len = 0;
+ u32 event_id, event_data_size;
+
+ switch(event->event_type) {
+ case PREBOOT:
+ case POST_CODE:
+ case UNUSED:
+ case NO_ACTION:
+ case SCRTM_CONTENTS:
+ case SCRTM_VERSION:
+ case CPU_MICROCODE:
+ case PLATFORM_CONFIG_FLAGS:
+ case TABLE_OF_DEVICES:
+ case COMPACT_HASH:
+ case IPL:
+ case IPL_PARTITION_DATA:
+ case NONHOST_CODE:
+ case NONHOST_CONFIG:
+ case NONHOST_INFO:
+ name = tcpa_event_type_strings[event->event_type];
+ n_len = strlen(name);
+ break;
+ case SEPARATOR:
+ case ACTION:
+ if (MAX_TEXT_EVENT > event->event_size) {
+ name = event_entry;
+ n_len = event->event_size;
+ }
+ break;
+ case EVENT_TAG:
+ event_id = be32_to_cpu(event_entry);
+ event_data_size = be32_to_cpu(&event_entry[4]);
+
+ /* ToDo Row data -> Base64 */
+
+ switch (event_id) {
+ case SMBIOS:
+ case BIS_CERT:
+ case CMOS:
+ case NVRAM:
+ case OPTION_ROM_EXEC:
+ case OPTION_ROM_CONFIG:
+ case OPTION_ROM_MICROCODE:
+ case S_CRTM_VERSION:
+ case S_CRTM_CONTENTS:
+ case POST_CONTENTS:
+ name = tcpa_pc_event_id_strings[event_id];
+ n_len = strlen(name);
+ break;
+ case POST_BIOS_ROM:
+ case ESCD:
+ name = tcpa_pc_event_id_strings[event_id];
+ n_len = strlen(name);
+ for (i = 0; i < 20; i++)
+ d_len += sprintf(data, "%02x",
+ event_entry[8 + i]);
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
+ n_len, name, d_len, data);
+
+}
+
+static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+{
+
+ char *eventname;
+ char data[4];
+ u32 help;
+ int i, len;
+ struct tcpa_event *event = (struct tcpa_event *) v;
+ unsigned char *event_entry =
+ (unsigned char *) (v + sizeof(struct tcpa_event));
+
+ eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+ if (!eventname) {
+ printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* 1st: PCR used is in little-endian format (4 bytes) */
+ help = le32_to_cpu(event->pcr_index);
+ memcpy(data, &help, 4);
+ for (i = 0; i < 4; i++)
+ seq_putc(m, data[i]);
+
+ /* 2nd: SHA1 (20 bytes) */
+ for (i = 0; i < 20; i++)
+ seq_putc(m, event->pcr_value[i]);
+
+ /* 3rd: event type identifier (4 bytes) */
+ help = le32_to_cpu(event->event_type);
+ memcpy(data, &help, 4);
+ for (i = 0; i < 4; i++)
+ seq_putc(m, data[i]);
+
+ len = 0;
+
+ len += get_event_name(eventname, event, event_entry);
+
+ /* 4th: filename <= 255 + \'0' delimiter */
+ if (len > TCG_EVENT_NAME_LEN_MAX)
+ len = TCG_EVENT_NAME_LEN_MAX;
+
+ for (i = 0; i < len; i++)
+ seq_putc(m, eventname[i]);
+
+ /* 5th: delimiter */
+ seq_putc(m, '\0');
+
+ return 0;
+}
+
+static int tpm_bios_measurements_release(struct inode *inode,
+ struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct tpm_bios_log *log = seq->private;
+
+ if (log) {
+ kfree(log->bios_event_log);
+ kfree(log);
+ }
+
+ return seq_release(inode, file);
+}
+
+static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
+{
+ int len = 0;
+ int i;
+ char *eventname;
+ struct tcpa_event *event = v;
+ unsigned char *event_entry =
+ (unsigned char *) (v + sizeof(struct tcpa_event));
+
+ eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+ if (!eventname) {
+ printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+ __func__);
+ return -EFAULT;
+ }
+
+ seq_printf(m, "%2d ", event->pcr_index);
+
+ /* 2nd: SHA1 */
+ for (i = 0; i < 20; i++)
+ seq_printf(m, "%02x", event->pcr_value[i]);
+
+ /* 3rd: event type identifier */
+ seq_printf(m, " %02x", event->event_type);
+
+ len += get_event_name(eventname, event, event_entry);
+
+ /* 4th: eventname <= max + \'0' delimiter */
+ seq_printf(m, " %s\n", eventname);
+
+ return 0;
+}
+
+static struct seq_operations tpm_ascii_b_measurments_seqops = {
+ .start = tpm_bios_measurements_start,
+ .next = tpm_bios_measurements_next,
+ .stop = tpm_bios_measurements_stop,
+ .show = tpm_ascii_bios_measurements_show,
+};
+
+static struct seq_operations tpm_binary_b_measurments_seqops = {
+ .start = tpm_bios_measurements_start,
+ .next = tpm_bios_measurements_next,
+ .stop = tpm_bios_measurements_stop,
+ .show = tpm_binary_bios_measurements_show,
+};
+
+/* read binary bios log */
+static int read_log(struct tpm_bios_log *log)
+{
+ struct acpi_tcpa *buff;
+ acpi_status status;
+ void *virt;
+
+ if (log->bios_event_log != NULL) {
+ printk(KERN_ERR
+ "%s: ERROR - Eventlog already initialized\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
+ status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1,
+ ACPI_LOGICAL_ADDRESSING,
+ (struct acpi_table_header **)
+ &buff);
+
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (buff->log_max_len == 0) {
+ printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+ return -EIO;
+ }
+
+ /* malloc EventLog space */
+ log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
+ if (!log->bios_event_log) {
+ printk
+ ("%s: ERROR - Not enough Memory for BIOS measurements\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
+
+ acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt);
+
+ memcpy(log->bios_event_log, virt, buff->log_max_len);
+
+ acpi_os_unmap_memory(virt, buff->log_max_len);
+ return 0;
+}
+
+static int tpm_ascii_bios_measurements_open(struct inode *inode,
+ struct file *file)
+{
+ int err;
+ struct tpm_bios_log *log;
+ struct seq_file *seq;
+
+ log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+ if (!log)
+ return -ENOMEM;
+
+ if ((err = read_log(log)))
+ return err;
+
+ /* now register seq file */
+ err = seq_open(file, &tpm_ascii_b_measurments_seqops);
+ if (!err) {
+ seq = file->private_data;
+ seq->private = log;
+ } else {
+ kfree(log->bios_event_log);
+ kfree(log);
+ }
+ return err;
+}
+
+struct file_operations tpm_ascii_bios_measurements_ops = {
+ .open = tpm_ascii_bios_measurements_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = tpm_bios_measurements_release,
+};
+
+static int tpm_binary_bios_measurements_open(struct inode *inode,
+ struct file *file)
+{
+ int err;
+ struct tpm_bios_log *log;
+ struct seq_file *seq;
+
+ log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+ if (!log)
+ return -ENOMEM;
+
+ if ((err = read_log(log)))
+ return err;
+
+ /* now register seq file */
+ err = seq_open(file, &tpm_binary_b_measurments_seqops);
+ if (!err) {
+ seq = file->private_data;
+ seq->private = log;
+ } else {
+ kfree(log->bios_event_log);
+ kfree(log);
+ }
+ return err;
+}
+
+struct file_operations tpm_binary_bios_measurements_ops = {
+ .open = tpm_binary_bios_measurements_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = tpm_bios_measurements_release,
+};
+
+struct dentry **tpm_bios_log_setup(char *name)
+{
+ struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
+
+ tpm_dir = securityfs_create_dir(name, NULL);
+ if (!tpm_dir)
+ goto out;
+
+ bin_file =
+ securityfs_create_file("binary_bios_measurements",
+ S_IRUSR | S_IRGRP, tpm_dir, NULL,
+ &tpm_binary_bios_measurements_ops);
+ if (!bin_file)
+ goto out_tpm;
+
+ ascii_file =
+ securityfs_create_file("ascii_bios_measurements",
+ S_IRUSR | S_IRGRP, tpm_dir, NULL,
+ &tpm_ascii_bios_measurements_ops);
+ if (!ascii_file)
+ goto out_bin;
+
+ ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
+ if (!ret)
+ goto out_ascii;
+
+ ret[0] = ascii_file;
+ ret[1] = bin_file;
+ ret[2] = tpm_dir;
+
+ return ret;
+
+out_ascii:
+ securityfs_remove(ascii_file);
+out_bin:
+ securityfs_remove(bin_file);
+out_tpm:
+ securityfs_remove(tpm_dir);
+out:
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
+
+void tpm_bios_log_teardown(struct dentry **lst)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ securityfs_remove(lst[i]);
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 4b1eef51ec59..eb8b5be4e249 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -166,9 +166,12 @@ static struct tty_struct *alloc_tty_struct(void)
return tty;
}
+static void tty_buffer_free_all(struct tty_struct *);
+
static inline void free_tty_struct(struct tty_struct *tty)
{
kfree(tty->write_buf);
+ tty_buffer_free_all(tty);
kfree(tty);
}
@@ -231,6 +234,200 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
}
/*
+ * Tty buffer allocation management
+ */
+
+static void tty_buffer_free_all(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+ while((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ kfree(thead);
+ }
+ while((thead = tty->buf.free) != NULL) {
+ tty->buf.free = thead->next;
+ kfree(thead);
+ }
+ tty->buf.tail = NULL;
+}
+
+static void tty_buffer_init(struct tty_struct *tty)
+{
+ tty->buf.head = NULL;
+ tty->buf.tail = NULL;
+ tty->buf.free = NULL;
+}
+
+static struct tty_buffer *tty_buffer_alloc(size_t size)
+{
+ struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+ if(p == NULL)
+ return NULL;
+ p->used = 0;
+ p->size = size;
+ p->next = NULL;
+ p->char_buf_ptr = (char *)(p->data);
+ p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
+/* printk("Flip create %p\n", p); */
+ return p;
+}
+
+/* Must be called with the tty_read lock held. This needs to acquire strategy
+ code to decide if we should kfree or relink a given expired buffer */
+
+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+{
+ /* Dumb strategy for now - should keep some stats */
+/* printk("Flip dispose %p\n", b); */
+ if(b->size >= 512)
+ kfree(b);
+ else {
+ b->next = tty->buf.free;
+ tty->buf.free = b;
+ }
+}
+
+static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer **tbh = &tty->buf.free;
+ while((*tbh) != NULL) {
+ struct tty_buffer *t = *tbh;
+ if(t->size >= size) {
+ *tbh = t->next;
+ t->next = NULL;
+ t->used = 0;
+ /* DEBUG ONLY */
+ memset(t->data, '*', size);
+/* printk("Flip recycle %p\n", t); */
+ return t;
+ }
+ tbh = &((*tbh)->next);
+ }
+ /* Round the buffer size out */
+ size = (size + 0xFF) & ~ 0xFF;
+ return tty_buffer_alloc(size);
+ /* Should possibly check if this fails for the largest buffer we
+ have queued and recycle that ? */
+}
+
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer *b = tty->buf.tail, *n;
+ int left = 0;
+
+ /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ remove this conditional if its worth it. This would be invisible
+ to the callers */
+ if(b != NULL)
+ left = b->size - b->used;
+ if(left >= size)
+ return size;
+ /* This is the slow path - looking for new buffers to use */
+ n = tty_buffer_find(tty, size);
+ if(n == NULL)
+ return left;
+ if(b != NULL)
+ b->next = n;
+ else
+ tty->buf.head = n;
+ tty->buf.tail = n;
+ return size;
+}
+
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if(unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+/* printk("Flip insert %d.\n", space); */
+ }
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ while (unlikely(size > copied));
+ return copied;
+}
+
+EXPORT_SYMBOL_GPL(tty_insert_flip_string);
+
+int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if(unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+ flags += space;
+ }
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ while (unlikely(size > copied));
+ return copied;
+}
+
+EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
+
+
+/*
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for normal characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ */
+
+int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
+
+/*
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ */
+
+int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ *flags = tb->flag_buf_ptr + tb->used;
+ tb->used += space;
+ return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
+
+
+
+/*
* This is probably overkill for real world processors but
* they are not on hot paths so a little discipline won't do
* any harm.
@@ -492,6 +689,17 @@ restart:
if (ld == NULL)
return -EINVAL;
+ /*
+ * No more input please, we are switching. The new ldisc
+ * will update this value in the ldisc open function
+ */
+
+ tty->receive_room = 0;
+
+ /*
+ * Problem: What do we do if this blocks ?
+ */
+
tty_wait_until_sent(tty, 0);
if (tty->ldisc.num == ldisc) {
@@ -560,9 +768,9 @@ restart:
* we say so later on.
*/
- work = cancel_delayed_work(&tty->flip.work);
+ work = cancel_delayed_work(&tty->buf.work);
/*
- * Wait for ->hangup_work and ->flip.work handlers to terminate
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
*/
flush_scheduled_work();
@@ -616,7 +824,7 @@ restart:
/* Restart it in case no characters kick it off. Safe if
already running */
if (work)
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
return retval;
}
@@ -1721,10 +1929,10 @@ static void release_dev(struct file * filp)
*/
clear_bit(TTY_LDISC, &tty->flags);
clear_bit(TTY_DONT_FLIP, &tty->flags);
- cancel_delayed_work(&tty->flip.work);
+ cancel_delayed_work(&tty->buf.work);
/*
- * Wait for ->hangup_work and ->flip.work handlers to terminate
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
*/
flush_scheduled_work();
@@ -2518,17 +2726,15 @@ EXPORT_SYMBOL(do_SAK);
/*
* This routine is called out of the software interrupt to flush data
- * from the flip buffer to the line discipline.
+ * from the buffer chain to the line discipline.
*/
static void flush_to_ldisc(void *private_)
{
struct tty_struct *tty = (struct tty_struct *) private_;
- unsigned char *cp;
- char *fp;
- int count;
unsigned long flags;
struct tty_ldisc *disc;
+ struct tty_buffer *tbuf;
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
@@ -2538,28 +2744,23 @@ static void flush_to_ldisc(void *private_)
/*
* Do it after the next timer tick:
*/
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
goto out;
}
spin_lock_irqsave(&tty->read_lock, flags);
- if (tty->flip.buf_num) {
- cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
- fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
- tty->flip.buf_num = 0;
- tty->flip.char_buf_ptr = tty->flip.char_buf;
- tty->flip.flag_buf_ptr = tty->flip.flag_buf;
- } else {
- cp = tty->flip.char_buf;
- fp = tty->flip.flag_buf;
- tty->flip.buf_num = 1;
- tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
- tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
- }
- count = tty->flip.count;
- tty->flip.count = 0;
+ while((tbuf = tty->buf.head) != NULL) {
+ tty->buf.head = tbuf->next;
+ if (tty->buf.head == NULL)
+ tty->buf.tail = NULL;
+ spin_unlock_irqrestore(&tty->read_lock, flags);
+ /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
+ disc->receive_buf(tty, tbuf->char_buf_ptr,
+ tbuf->flag_buf_ptr,
+ tbuf->used);
+ spin_lock_irqsave(&tty->read_lock, flags);
+ tty_buffer_free(tty, tbuf);
+ }
spin_unlock_irqrestore(&tty->read_lock, flags);
-
- disc->receive_buf(tty, cp, fp, count);
out:
tty_ldisc_deref(disc);
}
@@ -2654,11 +2855,12 @@ void tty_flip_buffer_push(struct tty_struct *tty)
if (tty->low_latency)
flush_to_ldisc((void *) tty);
else
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
EXPORT_SYMBOL(tty_flip_buffer_push);
+
/*
* This subroutine initializes a tty structure.
*/
@@ -2669,10 +2871,10 @@ static void initialize_tty_struct(struct tty_struct *tty)
tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
tty->pgrp = -1;
tty->overrun_time = jiffies;
- tty->flip.char_buf_ptr = tty->flip.char_buf;
- tty->flip.flag_buf_ptr = tty->flip.flag_buf;
- INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
- init_MUTEX(&tty->flip.pty_sem);
+ tty->buf.head = tty->buf.tail = NULL;
+ tty_buffer_init(tty);
+ INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
+ init_MUTEX(&tty->buf.pty_sem);
init_MUTEX(&tty->termios_sem);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index 4d75c261f98a..4e5360388748 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -131,7 +131,7 @@ static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp);
static struct tty_driver *viotty_driver;
-void hvlog(char *fmt, ...)
+static void hvlog(char *fmt, ...)
{
int i;
unsigned long flags;
@@ -147,7 +147,7 @@ void hvlog(char *fmt, ...)
spin_unlock_irqrestore(&consoleloglock, flags);
}
-void hvlogOutput(const char *buf, int count)
+static void hvlogOutput(const char *buf, int count)
{
unsigned long flags;
int begin;
@@ -476,19 +476,19 @@ static struct port_info *get_port_data(struct tty_struct *tty)
*/
static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp)
{
+ struct HvLpEvent *hev = &viochar->event;
+
memset(viochar, 0, sizeof(struct viocharlpevent));
- viochar->event.xFlags.xValid = 1;
- viochar->event.xFlags.xFunction = HvLpEvent_Function_Int;
- viochar->event.xFlags.xAckInd = HvLpEvent_AckInd_NoAck;
- viochar->event.xFlags.xAckType = HvLpEvent_AckType_DeferredAck;
- viochar->event.xType = HvLpEvent_Type_VirtualIo;
- viochar->event.xSubtype = viomajorsubtype_chario | viochardata;
- viochar->event.xSourceLp = HvLpConfig_getLpIndex();
- viochar->event.xTargetLp = lp;
- viochar->event.xSizeMinus1 = sizeof(struct viocharlpevent);
- viochar->event.xSourceInstanceId = viopath_sourceinst(lp);
- viochar->event.xTargetInstanceId = viopath_targetinst(lp);
+ hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK |
+ HV_LP_EVENT_INT;
+ hev->xType = HvLpEvent_Type_VirtualIo;
+ hev->xSubtype = viomajorsubtype_chario | viochardata;
+ hev->xSourceLp = HvLpConfig_getLpIndex();
+ hev->xTargetLp = lp;
+ hev->xSizeMinus1 = sizeof(struct viocharlpevent);
+ hev->xSourceInstanceId = viopath_sourceinst(lp);
+ hev->xTargetInstanceId = viopath_targetinst(lp);
}
/*
@@ -752,7 +752,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event)
struct port_info *pi;
int reject = 0;
- if (event->xFlags.xFunction == HvLpEvent_Function_Ack) {
+ if (hvlpevent_is_ack(event)) {
if (port >= VTTY_PORTS)
return;
@@ -788,7 +788,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event)
}
/* This had better require an ack, otherwise complain */
- if (event->xFlags.xAckInd != HvLpEvent_AckInd_DoAck) {
+ if (!hvlpevent_need_ack(event)) {
printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n");
return;
}
@@ -856,7 +856,7 @@ static void vioHandleCloseEvent(struct HvLpEvent *event)
struct viocharlpevent *cevent = (struct viocharlpevent *)event;
u8 port = cevent->virtual_device;
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
if (port >= VTTY_PORTS) {
printk(VIOCONS_KERN_WARN
"close message from invalid virtual device.\n");
@@ -904,6 +904,7 @@ static void vioHandleData(struct HvLpEvent *event)
struct viocharlpevent *cevent = (struct viocharlpevent *)event;
struct port_info *pi;
int index;
+ int num_pushed;
u8 port = cevent->virtual_device;
if (port >= VTTY_PORTS) {
@@ -964,6 +965,7 @@ static void vioHandleData(struct HvLpEvent *event)
* functionality will only work if built into the kernel and
* then only if sysrq is enabled through the proc filesystem.
*/
+ num_pushed = 0;
for (index = 0; index < cevent->len; index++) {
#ifdef CONFIG_MAGIC_SYSRQ
if (sysrq_enabled) {
@@ -993,16 +995,14 @@ static void vioHandleData(struct HvLpEvent *event)
* Don't attempt to copy more data into the buffer than we
* have room for because it would fail without indication.
*/
- if ((tty->flip.count + 1) > TTY_FLIPBUF_SIZE) {
+ if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) {
printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
break;
}
- tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL);
+ num_pushed++;
}
- /* if cevent->len == 0 then no data was added to the buffer and flip.count == 0 */
- if (tty->flip.count)
- /* The next call resets flip.count when the data is flushed. */
+ if (num_pushed)
tty_flip_buffer_push(tty);
}
@@ -1056,8 +1056,7 @@ static void vioHandleCharEvent(struct HvLpEvent *event)
vioHandleConfig(event);
break;
default:
- if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
- (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
+ if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 19ba83635dd7..d9325281e482 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -434,13 +434,7 @@ static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp)
SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
return IRQ_HANDLED;
}
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ tty_insert_flip_char(tty, ch, 0);
/* Check if another character is already ready; in that case, the
* spcond_int() function must be used, because this character may have an
@@ -487,13 +481,7 @@ static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp)
else
err = 0;
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = err;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ tty_insert_flip_char(tty, ch, err);
/* ++TeSche: *All* errors have to be cleared manually,
* else the condition persists for the next chars
@@ -875,13 +863,13 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
local_irq_save(flags);
#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
- for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)
+ for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
}
#endif
#if defined(CONFIG_BVME6000_SCC)
if (MACH_IS_BVME6000) {
- for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i)
+ for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
}
#endif
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 9ac6d43437b3..2267c7b81799 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/vr41xx.h>
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
MODULE_LICENSE("GPL");
@@ -718,7 +718,7 @@ static struct platform_driver giu_device_driver = {
},
};
-static int __devinit vr41xx_giu_init(void)
+static int __init vr41xx_giu_init(void)
{
int retval;
@@ -733,7 +733,7 @@ static int __devinit vr41xx_giu_init(void)
return retval;
}
-static void __devexit vr41xx_giu_exit(void)
+static void __exit vr41xx_giu_exit(void)
{
platform_driver_unregister(&giu_device_driver);
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
index 435b30748e23..bc1b4a15212c 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/char/vr41xx_rtc.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Real Time Clock unit.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
#include <asm/uaccess.h>
#include <asm/vr41xx/vr41xx.h>
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
MODULE_LICENSE("GPL");
@@ -127,8 +127,6 @@ struct resource rtc_resource[2] = {
.flags = IORESOURCE_MEM, },
};
-#define RTC_NUM_RESOURCES sizeof(rtc_resource) / sizeof(struct resource)
-
static inline unsigned long read_elapsed_second(void)
{
unsigned long first_low, first_mid, first_high;
@@ -686,7 +684,8 @@ static int __devinit vr41xx_rtc_init(void)
break;
}
- rtc_platform_device = platform_device_register_simple("RTC", -1, rtc_resource, RTC_NUM_RESOURCES);
+ rtc_platform_device = platform_device_register_simple("RTC", -1,
+ rtc_resource, ARRAY_SIZE(rtc_resource));
if (IS_ERR(rtc_platform_device))
return PTR_ERR(rtc_platform_device);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e91268e86833..f1d9cb7feae6 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2758,29 +2758,6 @@ static void set_vesa_blanking(char __user *p)
vesa_blank_mode = (mode < 4) ? mode : 0;
}
-/*
- * This is called by a timer handler
- */
-static void vesa_powerdown(void)
-{
- struct vc_data *c = vc_cons[fg_console].d;
- /*
- * Power down if currently suspended (1 or 2),
- * suspend if currently blanked (0),
- * else do nothing (i.e. already powered down (3)).
- * Called only if powerdown features are allowed.
- */
- switch (vesa_blank_mode) {
- case VESA_NO_BLANKING:
- c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0);
- break;
- case VESA_VSYNC_SUSPEND:
- case VESA_HSYNC_SUSPEND:
- c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0);
- break;
- }
-}
-
void do_blank_screen(int entering_gfx)
{
struct vc_data *vc = vc_cons[fg_console].d;
@@ -2791,8 +2768,7 @@ void do_blank_screen(int entering_gfx)
if (console_blanked) {
if (blank_state == blank_vesa_wait) {
blank_state = blank_off;
- vesa_powerdown();
-
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
return;
}
@@ -2822,7 +2798,7 @@ void do_blank_screen(int entering_gfx)
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = vc->vc_sw->con_blank(vc, 1, 0);
+ i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
console_blanked = fg_console + 1;
if (i)
set_origin(vc);
@@ -2830,13 +2806,10 @@ void do_blank_screen(int entering_gfx)
if (console_blank_hook && console_blank_hook(1))
return;
- if (vesa_off_interval) {
+ if (vesa_off_interval && vesa_blank_mode) {
blank_state = blank_vesa_wait;
mod_timer(&console_timer, jiffies + vesa_off_interval);
}
-
- if (vesa_blank_mode)
- vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
EXPORT_SYMBOL(do_blank_screen);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index a6544790af60..c0dfcf273f0a 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -395,12 +395,38 @@ config MACHZ_WDT
To compile this driver as a module, choose M here: the
module will be called machzwd.
+config SBC_EPX_C3_WATCHDOG
+ tristate "Winsystems SBC EPX-C3 watchdog"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the built-in watchdog timer on the EPX-C3
+ Single-board computer made by Winsystems, Inc.
+
+ *Note*: This hardware watchdog is not probeable and thus there
+ is no way to know if writing to its IO address will corrupt
+ your system or have any real effect. The only way to be sure
+ that this driver does what you want is to make sure you
+ are runnning it on an EPX-C3 from Winsystems with the watchdog
+ timer at IO address 0x1ee and 0x1ef. It will write to both those
+ IO ports. Basically, the assumption is made that if you compile
+ this driver into your kernel and/or load it as a module, that you
+ know what you are doing and that you are in fact running on an
+ EPX-C3 board!
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc_epx_c3.
+
+
# PowerPC Architecture
config 8xx_WDT
tristate "MPC8xx Watchdog Timer"
depends on WATCHDOG && 8xx
+config 83xx_WDT
+ tristate "MPC83xx Watchdog Timer"
+ depends on WATCHDOG && PPC_83xx
+
config MV64X60_WDT
tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
depends on WATCHDOG && MV64X60
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index cfd0a3987710..36c0b282b8ba 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -52,9 +52,11 @@ 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
+obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o
obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index e75045fe2641..3e8410b5a65e 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/completion.h>
#include <linux/jiffies.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -57,7 +58,7 @@ static int ticks = 10000;
/* some device data */
static struct {
- struct semaphore stop;
+ struct completion stop;
volatile int running;
struct timer_list timer;
volatile int queue;
@@ -85,7 +86,7 @@ static void cpu5wdt_trigger(unsigned long unused)
}
else {
/* ticks doesn't matter anyway */
- up(&cpu5wdt_device.stop);
+ complete(&cpu5wdt_device.stop);
}
}
@@ -239,7 +240,7 @@ static int __devinit cpu5wdt_init(void)
if ( !val )
printk(KERN_INFO PFX "sorry, was my fault\n");
- init_MUTEX_LOCKED(&cpu5wdt_device.stop);
+ init_completion(&cpu5wdt_device.stop);
cpu5wdt_device.queue = 0;
clear_bit(0, &cpu5wdt_device.inuse);
@@ -269,7 +270,7 @@ static void __devexit cpu5wdt_exit(void)
{
if ( cpu5wdt_device.queue ) {
cpu5wdt_device.queue = 0;
- down(&cpu5wdt_device.stop);
+ wait_for_completion(&cpu5wdt_device.stop);
}
misc_deregister(&cpu5wdt_misc);
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c
new file mode 100644
index 000000000000..5d6f5061603a
--- /dev/null
+++ b/drivers/char/watchdog/mpc83xx_wdt.c
@@ -0,0 +1,229 @@
+/*
+ * mpc83xx_wdt.c - MPC83xx watchdog userspace interface
+ *
+ * Authors: Dave Updegraff <dave@cray.org>
+ * Kumar Gala <galak@kernel.crashing.org>
+ * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
+ * ..and from sc520_wdt
+ *
+ * Note: it appears that you can only actually ENABLE or DISABLE the thing
+ * once after POR. Once enabled, you cannot disable, and vice versa.
+ *
+ * This program is free software; you can redistribute 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/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+struct mpc83xx_wdt {
+ __be32 res0;
+ __be32 swcrr; /* System watchdog control register */
+#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
+#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
+#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
+#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
+ __be32 swcnr; /* System watchdog count register */
+ u8 res1[2];
+ __be16 swsrr; /* System watchdog service register */
+ u8 res2[0xF0];
+};
+
+static struct mpc83xx_wdt __iomem *wd_base;
+
+static u16 timeout = 0xffff;
+module_param(timeout, ushort, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
+
+static int reset = 1;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
+
+/*
+ * We always prescale, but if someone really doesn't want to they can set this
+ * to 0
+ */
+static int prescale = 1;
+static unsigned int timeout_sec;
+
+static unsigned long wdt_is_open;
+static spinlock_t wdt_spinlock;
+
+static void mpc83xx_wdt_keepalive(void)
+{
+ /* Ping the WDT */
+ spin_lock(&wdt_spinlock);
+ out_be16(&wd_base->swsrr, 0x556c);
+ out_be16(&wd_base->swsrr, 0xaa39);
+ spin_unlock(&wdt_spinlock);
+}
+
+static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count)
+ mpc83xx_wdt_keepalive();
+ return count;
+}
+
+static int mpc83xx_wdt_open(struct inode *inode, struct file *file)
+{
+ u32 tmp = SWCRR_SWEN;
+ if (test_and_set_bit(0, &wdt_is_open))
+ return -EBUSY;
+
+ /* Once we start the watchdog we can't stop it */
+ __module_get(THIS_MODULE);
+
+ /* Good, fire up the show */
+ if (prescale)
+ tmp |= SWCRR_SWPR;
+ if (reset)
+ tmp |= SWCRR_SWRI;
+
+ tmp |= timeout << 16;
+
+ out_be32(&wd_base->swcrr, tmp);
+
+ return nonseekable_open(inode, file);
+}
+
+static int mpc83xx_wdt_release(struct inode *inode, struct file *file)
+{
+ printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
+ mpc83xx_wdt_keepalive();
+ clear_bit(0, &wdt_is_open);
+ return 0;
+}
+
+static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = "MPC83xx",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+ case WDIOC_KEEPALIVE:
+ mpc83xx_wdt_keepalive();
+ return 0;
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout_sec, p);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct file_operations mpc83xx_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mpc83xx_wdt_write,
+ .ioctl = mpc83xx_wdt_ioctl,
+ .open = mpc83xx_wdt_open,
+ .release = mpc83xx_wdt_release,
+};
+
+static struct miscdevice mpc83xx_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mpc83xx_wdt_fops,
+};
+
+static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
+{
+ struct resource *r;
+ int ret;
+ unsigned int *freq = dev->dev.platform_data;
+
+ /* get a pointer to the register memory */
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+ if (!r) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));
+
+ if (wd_base == NULL) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ ret = misc_register(&mpc83xx_wdt_miscdev);
+ if (ret) {
+ printk(KERN_ERR "cannot register miscdev on minor=%d "
+ "(err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_unmap;
+ }
+
+ /* Calculate the timeout in seconds */
+ if (prescale)
+ timeout_sec = (timeout * 0x10000) / (*freq);
+ else
+ timeout_sec = timeout / (*freq);
+
+ printk(KERN_INFO "WDT driver for MPC83xx initialized. "
+ "mode:%s timeout=%d (%d seconds)\n",
+ reset ? "reset":"interrupt", timeout, timeout_sec);
+
+ spin_lock_init(&wdt_spinlock);
+
+ return 0;
+
+err_unmap:
+ iounmap(wd_base);
+err_out:
+ return ret;
+}
+
+static int __devexit mpc83xx_wdt_remove(struct platform_device *dev)
+{
+ misc_deregister(&mpc83xx_wdt_miscdev);
+ iounmap(wd_base);
+
+ return 0;
+}
+
+static struct platform_driver mpc83xx_wdt_driver = {
+ .probe = mpc83xx_wdt_probe,
+ .remove = __devexit_p(mpc83xx_wdt_remove),
+ .driver = {
+ .name = "mpc83xx_wdt",
+ },
+};
+
+static int __init mpc83xx_wdt_init(void)
+{
+ return platform_driver_register(&mpc83xx_wdt_driver);
+}
+
+static void __exit mpc83xx_wdt_exit(void)
+{
+ platform_driver_unregister(&mpc83xx_wdt_driver);
+}
+
+module_init(mpc83xx_wdt_init);
+module_exit(mpc83xx_wdt_exit);
+
+MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
+MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
index 56d62ba7c6ce..b2fc71e20850 100644
--- a/drivers/char/watchdog/mpc8xx_wdt.c
+++ b/drivers/char/watchdog/mpc8xx_wdt.c
@@ -18,6 +18,7 @@
#include <linux/watchdog.h>
#include <asm/8xx_immap.h>
#include <asm/uaccess.h>
+#include <asm/io.h>
#include <syslib/m8xx_wdt.h>
static unsigned long wdt_opened;
@@ -25,18 +26,26 @@ static int wdt_status;
static void mpc8xx_wdt_handler_disable(void)
{
- volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ volatile uint __iomem *piscr;
+ piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
- imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE);
+ if (!m8xx_has_internal_rtc)
+ m8xx_wdt_stop_timer();
+ else
+ out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
}
static void mpc8xx_wdt_handler_enable(void)
{
- volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ volatile uint __iomem *piscr;
+ piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
- imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE;
+ if (!m8xx_has_internal_rtc)
+ m8xx_wdt_install_timer();
+ else
+ out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
}
@@ -68,9 +77,6 @@ static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
loff_t * ppos)
{
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
if (len)
m8xx_wdt_reset();
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index eb667daee19b..9dc54736e4eb 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -46,12 +46,12 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/clk.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/arch/map.h>
-#include <asm/hardware/clock.h>
#undef S3C24XX_VA_WATCHDOG
#define S3C24XX_VA_WATCHDOG (0)
@@ -397,7 +397,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
return -ENOENT;
}
- clk_use(wdt_clock);
clk_enable(wdt_clock);
/* see if we can actually set the requested timer margin, and if
@@ -444,7 +443,6 @@ static int s3c2410wdt_remove(struct platform_device *dev)
if (wdt_clock != NULL) {
clk_disable(wdt_clock);
- clk_unuse(wdt_clock);
clk_put(wdt_clock);
wdt_clock = NULL;
}
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index fb88b4041dca..b474ea52d6e8 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -74,7 +74,7 @@ static int sa1100dog_release(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
{
if (len)
/* Refresh OSMR3 timer. */
@@ -96,20 +96,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case WDIOC_GETSUPPORT:
- ret = copy_to_user((struct watchdog_info *)arg, &ident,
+ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETSTATUS:
- ret = put_user(0, (int *)arg);
+ ret = put_user(0, (int __user *)arg);
break;
case WDIOC_GETBOOTSTATUS:
- ret = put_user(boot_status, (int *)arg);
+ ret = put_user(boot_status, (int __user *)arg);
break;
case WDIOC_SETTIMEOUT:
- ret = get_user(time, (int *)arg);
+ ret = get_user(time, (int __user *)arg);
if (ret)
break;
@@ -123,7 +123,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
/*fall through*/
case WDIOC_GETTIMEOUT:
- ret = put_user(pre_margin / OSCR_FREQ, (int *)arg);
+ ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg);
break;
case WDIOC_KEEPALIVE:
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
new file mode 100644
index 000000000000..951764614ebf
--- /dev/null
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -0,0 +1,216 @@
+/*
+ * SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3
+ * single board computer
+ *
+ * (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, 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.
+ *
+ * based on softdog.c by Alan Cox <alan@redhat.com>
+ */
+
+#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/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define PFX "epx_c3: "
+static int epx_c3_alive;
+
+#define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
+#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
+
+static void epx_c3_start(void)
+{
+ outb(1, EPXC3_WATCHDOG_CTL_REG);
+}
+
+static void epx_c3_stop(void)
+{
+
+ outb(0, EPXC3_WATCHDOG_CTL_REG);
+
+ printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+}
+
+static void epx_c3_pet(void)
+{
+ outb(1, EPXC3_WATCHDOG_PET_REG);
+}
+
+/*
+ * Allow only one person to hold it open
+ */
+static int epx_c3_open(struct inode *inode, struct file *file)
+{
+ if (epx_c3_alive)
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Activate timer */
+ epx_c3_start();
+ epx_c3_pet();
+
+ epx_c3_alive = 1;
+ printk(KERN_INFO "Started watchdog timer.\n");
+
+ return nonseekable_open(inode, file);
+}
+
+static int epx_c3_release(struct inode *inode, struct file *file)
+{
+ /* Shut off the timer.
+ * Lock it in if it's a module and we defined ...NOWAYOUT */
+ if (!nowayout)
+ epx_c3_stop(); /* Turn the WDT off */
+
+ epx_c3_alive = 0;
+
+ return 0;
+}
+
+static ssize_t epx_c3_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ /* Refresh the timer. */
+ if (len)
+ epx_c3_pet();
+ return len;
+}
+
+static int epx_c3_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int options, retval = -EINVAL;
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = "Winsystems EPX-C3 H/W Watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((struct watchdog_info *)arg,
+ &ident, sizeof(ident)))
+ return -EFAULT;
+ return 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0,(int *)arg);
+ case WDIOC_KEEPALIVE:
+ epx_c3_pet();
+ return 0;
+ case WDIOC_GETTIMEOUT:
+ return put_user(WATCHDOG_TIMEOUT,(int *)arg);
+ case WDIOC_SETOPTIONS: {
+ if (get_user(options, (int *)arg))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ epx_c3_stop();
+ retval = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ epx_c3_start();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ epx_c3_stop(); /* Turn the WDT off */
+
+ return NOTIFY_DONE;
+}
+
+static struct file_operations epx_c3_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = epx_c3_write,
+ .ioctl = epx_c3_ioctl,
+ .open = epx_c3_open,
+ .release = epx_c3_release,
+};
+
+static struct miscdevice epx_c3_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &epx_c3_fops,
+};
+
+static struct notifier_block epx_c3_notifier = {
+ .notifier_call = epx_c3_notify_sys,
+};
+
+static const char banner[] __initdata =
+ KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
+
+static int __init watchdog_init(void)
+{
+ int ret;
+
+ ret = register_reboot_notifier(&epx_c3_notifier);
+ if (ret) {
+ printk(KERN_ERR PFX "cannot register reboot notifier "
+ "(err=%d)\n", ret);
+ return ret;
+ }
+
+ ret = misc_register(&epx_c3_miscdev);
+ if (ret) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
+ "(err=%d)\n", WATCHDOG_MINOR, ret);
+ unregister_reboot_notifier(&epx_c3_notifier);
+ return ret;
+ }
+
+ printk(banner);
+
+ return 0;
+}
+
+static void __exit watchdog_exit(void)
+{
+ misc_deregister(&epx_c3_miscdev);
+ unregister_reboot_notifier(&epx_c3_notifier);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
+MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index 44d49dfacbb3..3843900e94c4 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -1,5 +1,5 @@
/*
- * Wdt977 0.03: A Watchdog Device for Netwinder W83977AF chip
+ * Wdt977 0.04: A Watchdog Device for Netwinder W83977AF chip
*
* (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
*
@@ -18,6 +18,8 @@
* from minutes to seconds.
* 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
* nwwatchdog_init.
+ * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks
+ * remove limitiation to be used on Netwinders only
*/
#include <linux/module.h>
@@ -28,6 +30,7 @@
#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>
@@ -37,8 +40,18 @@
#include <asm/mach-types.h>
#include <asm/uaccess.h>
-#define PFX "Wdt977: "
-#define WATCHDOG_MINOR 130
+#define WATCHDOG_VERSION "0.04"
+#define WATCHDOG_NAME "Wdt977"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */
+#define IO_DATA_PORT (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA 0x87
+#define LOCK_DATA 0xAA
+#define DEVICE_REGISTER 0x07
+
#define DEFAULT_TIMEOUT 60 /* default timeout in seconds */
@@ -47,6 +60,7 @@ static int timeoutM; /* timeout in minutes */
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 (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
@@ -63,9 +77,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
static int wdt977_start(void)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
* F2 has the timeout in minutes
@@ -73,28 +91,29 @@ static int wdt977_start(void)
* at timeout, and to reset timer on kbd/mouse activity (not impl.)
* F4 is used to just clear the TIMEOUT'ed state (bit 0)
*/
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF2,0x370);
- outb(timeoutM,0x371);
- outb(0xF3,0x370);
- outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */
- outb(0xF4,0x370);
- outb(0x00,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
+ outb_p(0xF2, IO_INDEX_PORT);
+ outb_p(timeoutM, IO_DATA_PORT);
+ outb_p(0xF3, IO_INDEX_PORT);
+ outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */
+ outb_p(0xF4, IO_INDEX_PORT);
+ outb_p(0x00, IO_DATA_PORT);
/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
/* in test mode watch the bit 1 on F4 to indicate "triggered" */
if (!testmode)
{
- outb(0x07,0x370);
- outb(0x07,0x371);
- outb(0xE6,0x370);
- outb(0x08,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x07, IO_DATA_PORT);
+ outb_p(0xE6, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
}
/* lock the SuperIO chip */
- outb(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
printk(KERN_INFO PFX "activated.\n");
return 0;
@@ -106,35 +125,39 @@ static int wdt977_start(void)
static int wdt977_stop(void)
{
+ unsigned long flags;
+ spin_lock_irqsave(&spinlock, flags);
+
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
* F3 is reset to its default state
* F4 can clear the TIMEOUT'ed state (bit 0) - back to default
* We can not use GP17 as a PowerLed, as we use its usage as a RedLed
*/
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF2,0x370);
- outb(0xFF,0x371);
- outb(0xF3,0x370);
- outb(0x00,0x371);
- outb(0xF4,0x370);
- outb(0x00,0x371);
- outb(0xF2,0x370);
- outb(0x00,0x371);
+ 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);
/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
- outb(0x07,0x370);
- outb(0x07,0x371);
- outb(0xE6,0x370);
- outb(0x08,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x07, IO_DATA_PORT);
+ outb_p(0xE6, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
/* lock the SuperIO chip */
- outb(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
printk(KERN_INFO PFX "shutdown.\n");
return 0;
@@ -147,19 +170,23 @@ static int wdt977_stop(void)
static int wdt977_keepalive(void)
{
+ unsigned long flags;
+ spin_lock_irqsave(&spinlock, flags);
+
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and kicks watchdog reg F2 */
/* F2 has the timeout in minutes */
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF2,0x370);
- outb(timeoutM,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
+ outb_p(0xF2, IO_INDEX_PORT);
+ outb_p(timeoutM, IO_DATA_PORT);
/* lock the SuperIO chip */
- outb(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
return 0;
}
@@ -198,22 +225,26 @@ static int wdt977_set_timeout(int t)
static int wdt977_get_status(int *status)
{
int new_status;
+ unsigned long flags;
- *status=0;
+ spin_lock_irqsave(&spinlock, flags);
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and read watchdog reg F4 */
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF4,0x370);
- new_status = inb(0x371);
+ 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(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ *status=0;
if (new_status & 1)
*status |= WDIOF_CARDRESET;
@@ -249,8 +280,8 @@ static int wdt977_release(struct inode *inode, struct file *file)
wdt977_stop();
clear_bit(0,&timer_alive);
} else {
- printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
wdt977_keepalive();
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
}
expect_close = 0;
return 0;
@@ -271,14 +302,17 @@ static int wdt977_release(struct inode *inode, struct file *file)
static ssize_t wdt977_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- if (count) {
- if (!nowayout) {
+ if (count)
+ {
+ if (!nowayout)
+ {
size_t i;
/* In case it was set long ago */
expect_close = 0;
- for (i = 0; i != count; i++) {
+ for (i = 0; i != count; i++)
+ {
char c;
if (get_user(c, buf + i))
return -EFAULT;
@@ -287,6 +321,7 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf,
}
}
+ /* someone wrote to us, we should restart timer */
wdt977_keepalive();
}
return count;
@@ -308,7 +343,7 @@ static struct watchdog_info ident = {
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.firmware_version = 1,
- .identity = "Winbond 83977",
+ .identity = WATCHDOG_NAME,
};
static int wdt977_ioctl(struct inode *inode, struct file *file,
@@ -405,50 +440,81 @@ static struct notifier_block wdt977_notifier = {
.notifier_call = wdt977_notify_sys,
};
-static int __init nwwatchdog_init(void)
+static int __init wd977_init(void)
{
- int retval;
- if (!machine_is_netwinder())
- return -ENODEV;
+ int rc;
+
+ //if (!machine_is_netwinder())
+ // return -ENODEV;
+
+ 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 (wdt977_set_timeout(timeout)) {
+ if (wdt977_set_timeout(timeout))
+ {
wdt977_set_timeout(DEFAULT_TIMEOUT);
printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n",
DEFAULT_TIMEOUT);
}
- retval = register_reboot_notifier(&wdt977_notifier);
- if (retval) {
- printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
- retval);
- return retval;
+ /* on Netwinder the IOports are already reserved by
+ * arch/arm/mach-footbridge/netwinder-hw.c
+ */
+ if (!machine_is_netwinder())
+ {
+ 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;
+ }
}
- retval = misc_register(&wdt977_miscdev);
- if (retval) {
+ rc = misc_register(&wdt977_miscdev);
+ if (rc)
+ {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, retval);
- unregister_reboot_notifier(&wdt977_notifier);
- return retval;
+ wdt977_miscdev.minor, rc);
+ goto err_out_region;
+ }
+
+ rc = register_reboot_notifier(&wdt977_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 = %i)\n",
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
timeout, nowayout, testmode);
return 0;
+
+err_out_miscdev:
+ misc_deregister(&wdt977_miscdev);
+err_out_region:
+ if (!machine_is_netwinder())
+ release_region(IO_INDEX_PORT,2);
+err_out:
+ return rc;
}
-static void __exit nwwatchdog_exit(void)
+static void __exit wd977_exit(void)
{
+ wdt977_stop();
misc_deregister(&wdt977_miscdev);
unregister_reboot_notifier(&wdt977_notifier);
+ release_region(IO_INDEX_PORT,2);
}
-module_init(nwwatchdog_init);
-module_exit(nwwatchdog_exit);
+module_init(wd977_init);
+module_exit(wd977_exit);
-MODULE_AUTHOR("Woody Suwalski <woody@netwinder.org>");
+MODULE_AUTHOR("Woody Suwalski <woodys@xandros.com>");
MODULE_DESCRIPTION("W83977AF Watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 969d2b4aaec0..4b4d7db1ff7b 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <linux/init.h>
#include <asm/atomic.h>
@@ -34,14 +35,14 @@
static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
-/* proc_counts is used as the sequence number of the netlink message */
+/* proc_event_counts is used as the sequence number of the netlink message */
static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 };
static inline void get_seq(__u32 *ts, int *cpu)
{
*ts = get_cpu_var(proc_event_counts)++;
*cpu = smp_processor_id();
- put_cpu_var(proc_counts);
+ put_cpu_var(proc_event_counts);
}
void proc_fork_connector(struct task_struct *task)
@@ -56,7 +57,7 @@ void proc_fork_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */
ev->what = PROC_EVENT_FORK;
ev->event_data.fork.parent_pid = task->real_parent->pid;
ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -82,7 +83,7 @@ void proc_exec_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -116,7 +117,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
} else
return;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -136,7 +137,7 @@ void proc_exit_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -169,7 +170,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
msg->seq = rcvd_seq;
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a9163d02983a..277a843a87a6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -41,7 +41,6 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock);
/* internal prototypes */
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
static void handle_update(void *data);
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci);
/**
* Two notifier lists: the "policy" list is involved in the
@@ -127,7 +126,7 @@ static unsigned int debug_ratelimit = 1;
static unsigned int disable_ratelimit = 1;
static DEFINE_SPINLOCK(disable_ratelimit_lock);
-static inline void cpufreq_debug_enable_ratelimit(void)
+static void cpufreq_debug_enable_ratelimit(void)
{
unsigned long flags;
@@ -137,7 +136,7 @@ static inline void cpufreq_debug_enable_ratelimit(void)
spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
}
-static inline void cpufreq_debug_disable_ratelimit(void)
+static void cpufreq_debug_disable_ratelimit(void)
{
unsigned long flags;
@@ -206,7 +205,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; }
static unsigned long l_p_j_ref;
static unsigned int l_p_j_ref_freq;
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
{
if (ci->flags & CPUFREQ_CONST_LOOPS)
return;
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 71407c578afe..64819aa7cac4 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -99,9 +99,6 @@ byte(const uint32_t x, const unsigned n)
return x >> (n << 3);
}
-#define uint32_t_in(x) le32_to_cpu(*(const uint32_t *)(x))
-#define uint32_t_out(to, from) (*(uint32_t *)(to) = cpu_to_le32(from))
-
#define E_KEY ctx->E
#define D_KEY ctx->D
@@ -294,6 +291,7 @@ static int
aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags)
{
struct aes_ctx *ctx = aes_ctx(ctx_arg);
+ const __le32 *key = (const __le32 *)in_key;
uint32_t i, t, u, v, w;
uint32_t P[AES_EXTENDED_KEY_SIZE];
uint32_t rounds;
@@ -313,10 +311,10 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t
ctx->E = ctx->e_data;
ctx->D = ctx->e_data;
- E_KEY[0] = uint32_t_in (in_key);
- E_KEY[1] = uint32_t_in (in_key + 4);
- E_KEY[2] = uint32_t_in (in_key + 8);
- E_KEY[3] = uint32_t_in (in_key + 12);
+ E_KEY[0] = le32_to_cpu(key[0]);
+ E_KEY[1] = le32_to_cpu(key[1]);
+ E_KEY[2] = le32_to_cpu(key[2]);
+ E_KEY[3] = le32_to_cpu(key[3]);
/* Prepare control words. */
memset(&ctx->cword, 0, sizeof(ctx->cword));
@@ -343,17 +341,17 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t
break;
case 24:
- E_KEY[4] = uint32_t_in (in_key + 16);
- t = E_KEY[5] = uint32_t_in (in_key + 20);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ t = E_KEY[5] = le32_to_cpu(key[5]);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
- E_KEY[4] = uint32_t_in (in_key + 16);
- E_KEY[5] = uint32_t_in (in_key + 20);
- E_KEY[6] = uint32_t_in (in_key + 24);
- t = E_KEY[7] = uint32_t_in (in_key + 28);
+ E_KEY[4] = le32_to_cpu(in_key[4]);
+ E_KEY[5] = le32_to_cpu(in_key[5]);
+ E_KEY[6] = le32_to_cpu(in_key[6]);
+ t = E_KEY[7] = le32_to_cpu(in_key[7]);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
@@ -468,6 +466,8 @@ static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
static struct crypto_alg aes_alg = {
.cra_name = "aes",
+ .cra_driver_name = "aes-padlock",
+ .cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h
index 3cf2b7a12348..b78489bc298a 100644
--- a/drivers/crypto/padlock.h
+++ b/drivers/crypto/padlock.h
@@ -17,7 +17,7 @@
/* Control word. */
struct cword {
- int __attribute__ ((__packed__))
+ unsigned int __attribute__ ((__packed__))
rounds:4,
algo:3,
keygen:1,
diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c
index ffe6f44ac76f..ca8e69d2f64d 100644
--- a/drivers/dio/dio-driver.c
+++ b/drivers/dio/dio-driver.c
@@ -83,7 +83,6 @@ int dio_register_driver(struct dio_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &dio_bus_type;
- drv->driver.probe = dio_device_probe;
/* register with core */
count = driver_register(&drv->driver);
@@ -145,7 +144,8 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv)
struct bus_type dio_bus_type = {
.name = "dio",
- .match = dio_bus_match
+ .match = dio_bus_match,
+ .probe = dio_device_probe,
};
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
new file mode 100644
index 000000000000..4819e7fc00dd
--- /dev/null
+++ b/drivers/edac/Kconfig
@@ -0,0 +1,102 @@
+#
+# EDAC Kconfig
+# Copyright (c) 2003 Linux Networx
+# Licensed and distributed under the GPL
+#
+# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
+#
+
+menu 'EDAC - error detection and reporting (RAS)'
+
+config EDAC
+ tristate "EDAC core system error reporting"
+ depends on X86
+ default y
+ help
+ EDAC is designed to report errors in the core system.
+ These are low-level errors that are reported in the CPU or
+ supporting chipset: memory errors, cache errors, PCI errors,
+ thermal throttling, etc.. If unsure, select 'Y'.
+
+
+comment "Reporting subsystems"
+ depends on EDAC
+
+config EDAC_DEBUG
+ bool "Debugging"
+ depends on EDAC
+ help
+ This turns on debugging information for the entire EDAC
+ sub-system. You can insert module with "debug_level=x", current
+ there're four debug levels (x=0,1,2,3 from low to high).
+ Usually you should select 'N'.
+
+config EDAC_MM_EDAC
+ tristate "Main Memory EDAC (Error Detection And Correction) reporting"
+ depends on EDAC
+ default y
+ help
+ Some systems are able to detect and correct errors in main
+ memory. EDAC can report statistics on memory error
+ detection and correction (EDAC - or commonly referred to ECC
+ errors). EDAC will also try to decode where these errors
+ occurred so that a particular failing memory module can be
+ replaced. If unsure, select 'Y'.
+
+
+config EDAC_AMD76X
+ tristate "AMD 76x (760, 762, 768)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the AMD 76x
+ series of chipsets used with the Athlon processor.
+
+config EDAC_E7XXX
+ tristate "Intel e7xxx (e7205, e7500, e7501, e7505)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ E7205, E7500, E7501 and E7505 server chipsets.
+
+config EDAC_E752X
+ tristate "Intel e752x (e7520, e7525, e7320)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ E7520, E7525, E7320 server chipsets.
+
+config EDAC_I82875P
+ tristate "Intel 82875p (D82875P, E7210)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ DP82785P and E7210 server chipsets.
+
+config EDAC_I82860
+ tristate "Intel 82860"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ 82860 chipset.
+
+config EDAC_R82600
+ tristate "Radisys 82600 embedded chipset"
+ depends on EDAC_MM_EDAC
+ help
+ Support for error detection and correction on the Radisys
+ 82600 embedded chipset.
+
+choice
+ prompt "Error detecting method"
+ depends on EDAC
+ default EDAC_POLL
+
+config EDAC_POLL
+ bool "Poll for errors"
+ depends on EDAC
+ help
+ Poll the chipset periodically to detect errors.
+
+endchoice
+
+endmenu
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
new file mode 100644
index 000000000000..93137fdab4b3
--- /dev/null
+++ b/drivers/edac/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux kernel EDAC drivers.
+#
+# Copyright 02 Jul 2003, Linux Networx (http://lnxi.com)
+# This file may be distributed under the terms of the
+# GNU General Public License.
+#
+# $Id: Makefile,v 1.4.2.3 2005/07/08 22:05:38 dsp_llnl Exp $
+
+
+obj-$(CONFIG_EDAC_MM_EDAC) += edac_mc.o
+obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
+obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
+obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
+obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
+obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
+obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
+
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
new file mode 100644
index 000000000000..2fcc8120b53c
--- /dev/null
+++ b/drivers/edac/amd76x_edac.c
@@ -0,0 +1,356 @@
+/*
+ * AMD 76x Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#define AMD76X_NR_CSROWS 8
+#define AMD76X_NR_CHANS 1
+#define AMD76X_NR_DIMMS 4
+
+
+/* AMD 76x register addresses - device 0 function 0 - PCI bridge */
+#define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b)
+ *
+ * 31:16 reserved
+ * 15:14 SERR enabled: x1=ue 1x=ce
+ * 13 reserved
+ * 12 diag: disabled, enabled
+ * 11:10 mode: dis, EC, ECC, ECC+scrub
+ * 9:8 status: x1=ue 1x=ce
+ * 7:4 UE cs row
+ * 3:0 CE cs row
+ */
+#define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b)
+ *
+ * 31:26 clock disable 5 - 0
+ * 25 SDRAM init
+ * 24 reserved
+ * 23 mode register service
+ * 22:21 suspend to RAM
+ * 20 burst refresh enable
+ * 19 refresh disable
+ * 18 reserved
+ * 17:16 cycles-per-refresh
+ * 15:8 reserved
+ * 7:0 x4 mode enable 7 - 0
+ */
+#define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b)
+ *
+ * 31:23 chip-select base
+ * 22:16 reserved
+ * 15:7 chip-select mask
+ * 6:3 reserved
+ * 2:1 address mode
+ * 0 chip-select enable
+ */
+
+
+struct amd76x_error_info {
+ u32 ecc_mode_status;
+};
+
+
+enum amd76x_chips {
+ AMD761 = 0,
+ AMD762
+};
+
+
+struct amd76x_dev_info {
+ const char *ctl_name;
+};
+
+
+static const struct amd76x_dev_info amd76x_devs[] = {
+ [AMD761] = {.ctl_name = "AMD761"},
+ [AMD762] = {.ctl_name = "AMD762"},
+};
+
+
+/**
+ * amd76x_get_error_info - fetch error information
+ * @mci: Memory controller
+ * @info: Info to fill in
+ *
+ * Fetch and store the AMD76x ECC status. Clear pending status
+ * on the chip so that further errors will be reported
+ */
+
+static void amd76x_get_error_info (struct mem_ctl_info *mci,
+ struct amd76x_error_info *info)
+{
+ pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ &info->ecc_mode_status);
+
+ if (info->ecc_mode_status & BIT(8))
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ (u32) BIT(8), (u32) BIT(8));
+
+ if (info->ecc_mode_status & BIT(9))
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ (u32) BIT(9), (u32) BIT(9));
+}
+
+
+/**
+ * amd76x_process_error_info - Error check
+ * @mci: Memory controller
+ * @info: Previously fetched information from chip
+ * @handle_errors: 1 if we should do recovery
+ *
+ * Process the chip state and decide if an error has occurred.
+ * A return of 1 indicates an error. Also if handle_errors is true
+ * then attempt to handle and clean up after the error
+ */
+
+static int amd76x_process_error_info (struct mem_ctl_info *mci,
+ struct amd76x_error_info *info, int handle_errors)
+{
+ int error_found;
+ u32 row;
+
+ error_found = 0;
+
+ /*
+ * Check for an uncorrectable error
+ */
+ if (info->ecc_mode_status & BIT(8)) {
+ error_found = 1;
+
+ if (handle_errors) {
+ row = (info->ecc_mode_status >> 4) & 0xf;
+ edac_mc_handle_ue(mci,
+ mci->csrows[row].first_page, 0, row,
+ mci->ctl_name);
+ }
+ }
+
+ /*
+ * Check for a correctable error
+ */
+ if (info->ecc_mode_status & BIT(9)) {
+ error_found = 1;
+
+ if (handle_errors) {
+ row = info->ecc_mode_status & 0xf;
+ edac_mc_handle_ce(mci,
+ mci->csrows[row].first_page, 0, 0, row, 0,
+ mci->ctl_name);
+ }
+ }
+ return error_found;
+}
+
+/**
+ * amd76x_check - Poll the controller
+ * @mci: Memory controller
+ *
+ * Called by the poll handlers this function reads the status
+ * from the controller and checks for errors.
+ */
+
+static void amd76x_check(struct mem_ctl_info *mci)
+{
+ struct amd76x_error_info info;
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ amd76x_get_error_info(mci, &info);
+ amd76x_process_error_info(mci, &info, 1);
+}
+
+
+/**
+ * amd76x_probe1 - Perform set up for detected device
+ * @pdev; PCI device detected
+ * @dev_idx: Device type index
+ *
+ * We have found an AMD76x and now need to set up the memory
+ * controller status reporting. We configure and set up the
+ * memory controller reporting and claim the device.
+ */
+
+static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ enum edac_type ems_modes[] = {
+ EDAC_NONE,
+ EDAC_EC,
+ EDAC_SECDED,
+ EDAC_SECDED
+ };
+ u32 ems;
+ u32 ems_mode;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
+ ems_mode = (ems >> 10) & 0x3;
+
+ mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->pdev = pci_dev_get(pdev);
+ mci->mtype_cap = MEM_FLAG_RDDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ mci->edac_cap = ems_mode ?
+ (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.4.2.5 $";
+ mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
+ mci->edac_check = amd76x_check;
+ mci->ctl_page_to_phys = NULL;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ struct csrow_info *csrow = &mci->csrows[index];
+ u32 mba;
+ u32 mba_base;
+ u32 mba_mask;
+ u32 dms;
+
+ /* find the DRAM Chip Select Base address and mask */
+ pci_read_config_dword(mci->pdev,
+ AMD76X_MEM_BASE_ADDR + (index * 4),
+ &mba);
+
+ if (!(mba & BIT(0)))
+ continue;
+
+ mba_base = mba & 0xff800000UL;
+ mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
+
+ pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
+ &dms);
+
+ csrow->first_page = mba_base >> PAGE_SHIFT;
+ csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
+ csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+ csrow->page_mask = mba_mask >> PAGE_SHIFT;
+ csrow->grain = csrow->nr_pages << PAGE_SHIFT;
+ csrow->mtype = MEM_RDDR;
+ csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
+ csrow->edac_mode = ems_modes[ems_mode];
+ }
+
+ /* clear counters */
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8),
+ (u32) (0x3 << 8));
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci) {
+ if(mci->pdev)
+ pci_dev_put(mci->pdev);
+ edac_mc_free(mci);
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit amd76x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* don't need to call pci_device_enable() */
+ return amd76x_probe1(pdev, ent->driver_data);
+}
+
+
+/**
+ * amd76x_remove_one - driver shutdown
+ * @pdev: PCI device being handed back
+ *
+ * Called when the driver is unloaded. Find the matching mci
+ * structure for the device then delete the mci and free the
+ * resources.
+ */
+
+static void __devexit amd76x_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+ if (edac_mc_del_mc(mci))
+ return;
+ pci_dev_put(mci->pdev);
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD762},
+ {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD761},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
+
+
+static struct pci_driver amd76x_driver = {
+ .name = BS_MOD_STR,
+ .probe = amd76x_init_one,
+ .remove = __devexit_p(amd76x_remove_one),
+ .id_table = amd76x_pci_tbl,
+};
+
+static int __init amd76x_init(void)
+{
+ return pci_register_driver(&amd76x_driver);
+}
+
+static void __exit amd76x_exit(void)
+{
+ pci_unregister_driver(&amd76x_driver);
+}
+
+module_init(amd76x_init);
+module_exit(amd76x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
new file mode 100644
index 000000000000..770a5a633079
--- /dev/null
+++ b/drivers/edac/e752x_edac.c
@@ -0,0 +1,1071 @@
+/*
+ * Intel e752x Memory Controller kernel module
+ * (C) 2004 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e752x_chips" below for supported chipsets
+ *
+ * Written by Tom Zimmerman
+ *
+ * Contributors:
+ * Thayne Harbaugh at realmsys.com (?)
+ * Wang Zhenyu at intel.com
+ * Dave Jiang at mvista.com
+ *
+ * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_0
+#define PCI_DEVICE_ID_INTEL_7520_0 0x3590
+#endif /* PCI_DEVICE_ID_INTEL_7520_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR
+#define PCI_DEVICE_ID_INTEL_7520_1_ERR 0x3591
+#endif /* PCI_DEVICE_ID_INTEL_7520_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_0
+#define PCI_DEVICE_ID_INTEL_7525_0 0x359E
+#endif /* PCI_DEVICE_ID_INTEL_7525_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR
+#define PCI_DEVICE_ID_INTEL_7525_1_ERR 0x3593
+#endif /* PCI_DEVICE_ID_INTEL_7525_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_0
+#define PCI_DEVICE_ID_INTEL_7320_0 0x3592
+#endif /* PCI_DEVICE_ID_INTEL_7320_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR
+#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593
+#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */
+
+#define E752X_NR_CSROWS 8 /* number of csrows */
+
+
+/* E752X register addresses - device 0 function 0 */
+#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */
+#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */
+ /*
+ * 31:30 Device width row 7
+ * 01=x8 10=x4 11=x8 DDR2
+ * 27:26 Device width row 6
+ * 23:22 Device width row 5
+ * 19:20 Device width row 4
+ * 15:14 Device width row 3
+ * 11:10 Device width row 2
+ * 7:6 Device width row 1
+ * 3:2 Device width row 0
+ */
+#define E752X_DRC 0x7C /* DRAM controller mode reg (32b) */
+ /* FIXME:IS THIS RIGHT? */
+ /*
+ * 22 Number channels 0=1,1=2
+ * 19:18 DRB Granularity 32/64MB
+ */
+#define E752X_DRM 0x80 /* Dimm mapping register */
+#define E752X_DDRCSR 0x9A /* DDR control and status reg (16b) */
+ /*
+ * 14:12 1 single A, 2 single B, 3 dual
+ */
+#define E752X_TOLM 0xC4 /* DRAM top of low memory reg (16b) */
+#define E752X_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */
+#define E752X_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */
+#define E752X_REMAPOFFSET 0xCA /* DRAM remap limit offset reg (16b) */
+
+/* E752X register addresses - device 0 function 1 */
+#define E752X_FERR_GLOBAL 0x40 /* Global first error register (32b) */
+#define E752X_NERR_GLOBAL 0x44 /* Global next error register (32b) */
+#define E752X_HI_FERR 0x50 /* Hub interface first error reg (8b) */
+#define E752X_HI_NERR 0x52 /* Hub interface next error reg (8b) */
+#define E752X_HI_ERRMASK 0x54 /* Hub interface error mask reg (8b) */
+#define E752X_HI_SMICMD 0x5A /* Hub interface SMI command reg (8b) */
+#define E752X_SYSBUS_FERR 0x60 /* System buss first error reg (16b) */
+#define E752X_SYSBUS_NERR 0x62 /* System buss next error reg (16b) */
+#define E752X_SYSBUS_ERRMASK 0x64 /* System buss error mask reg (16b) */
+#define E752X_SYSBUS_SMICMD 0x6A /* System buss SMI command reg (16b) */
+#define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */
+#define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */
+#define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */
+#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI command reg (8b) */
+#define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */
+#define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */
+#define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */
+#define E752X_DRAM_SMICMD 0x8A /* DRAM SMI command register (8b) */
+#define E752X_DRAM_RETR_ADD 0xAC /* DRAM Retry address register (32b) */
+#define E752X_DRAM_SEC1_ADD 0xA0 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SEC2_ADD 0xC8 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_DED_ADD 0xA4 /* DRAM first uncorrectable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM first uncorrectable scrub memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SEC1_SYNDROME 0xC4 /* DRAM first correctable memory */
+ /* error syndrome register (16b) */
+#define E752X_DRAM_SEC2_SYNDROME 0xC6 /* DRAM second correctable memory */
+ /* error syndrome register (16b) */
+#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */
+
+/* ICH5R register addresses - device 30 function 0 */
+#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */
+#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */
+#define ICH5R_PCI_BRIDGE_CTL 0x3E /* PCI bridge control register (16b) */
+
+enum e752x_chips {
+ E7520 = 0,
+ E7525 = 1,
+ E7320 = 2
+};
+
+
+struct e752x_pvt {
+ struct pci_dev *bridge_ck;
+ struct pci_dev *dev_d0f0;
+ struct pci_dev *dev_d0f1;
+ u32 tolm;
+ u32 remapbase;
+ u32 remaplimit;
+ int mc_symmetric;
+ u8 map[8];
+ int map_type;
+ const struct e752x_dev_info *dev_info;
+};
+
+
+struct e752x_dev_info {
+ u16 err_dev;
+ const char *ctl_name;
+};
+
+struct e752x_error_info {
+ u32 ferr_global;
+ u32 nerr_global;
+ u8 hi_ferr;
+ u8 hi_nerr;
+ u16 sysbus_ferr;
+ u16 sysbus_nerr;
+ u8 buf_ferr;
+ u8 buf_nerr;
+ u16 dram_ferr;
+ u16 dram_nerr;
+ u32 dram_sec1_add;
+ u32 dram_sec2_add;
+ u16 dram_sec1_syndrome;
+ u16 dram_sec2_syndrome;
+ u32 dram_ded_add;
+ u32 dram_scrb_add;
+ u32 dram_retr_add;
+};
+
+static const struct e752x_dev_info e752x_devs[] = {
+ [E7520] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
+ .ctl_name = "E7520"},
+ [E7525] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
+ .ctl_name = "E7525"},
+ [E7320] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
+ .ctl_name = "E7320"},
+};
+
+
+static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
+ unsigned long page)
+{
+ u32 remap;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (page < pvt->tolm)
+ return page;
+ if ((page >= 0x100000) && (page < pvt->remapbase))
+ return page;
+ remap = (page - pvt->tolm) + pvt->remapbase;
+ if (remap < pvt->remaplimit)
+ return remap;
+ printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+ return pvt->tolm - 1;
+}
+
+static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
+ u32 sec1_add, u16 sec1_syndrome)
+{
+ u32 page;
+ int row;
+ int channel;
+ int i;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* convert the addr to 4k page */
+ page = sec1_add >> (PAGE_SHIFT - 4);
+
+ /* FIXME - check for -1 */
+ if (pvt->mc_symmetric) {
+ /* chip select are bits 14 & 13 */
+ row = ((page >> 1) & 3);
+ printk(KERN_WARNING
+ "Test row %d Table %d %d %d %d %d %d %d %d\n",
+ row, pvt->map[0], pvt->map[1], pvt->map[2],
+ pvt->map[3], pvt->map[4], pvt->map[5],
+ pvt->map[6], pvt->map[7]);
+
+ /* test for channel remapping */
+ for (i = 0; i < 8; i++) {
+ if (pvt->map[i] == row)
+ break;
+ }
+ printk(KERN_WARNING "Test computed row %d\n", i);
+ if (i < 8)
+ row = i;
+ else
+ printk(KERN_WARNING
+ "MC%d: row %d not found in remap table\n",
+ mci->mc_idx, row);
+ } else
+ row = edac_mc_find_csrow_by_page(mci, page);
+ /* 0 = channel A, 1 = channel B */
+ channel = !(error_one & 1);
+
+ if (!pvt->map_type)
+ row = 7 - row;
+ edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
+ "e752x CE");
+}
+
+
+static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
+ u32 sec1_add, u16 sec1_syndrome, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
+}
+
+static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
+ u32 scrb_add)
+{
+ u32 error_2b, block_page;
+ int row;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (error_one & 0x0202) {
+ error_2b = ded_add;
+ /* convert to 4k address */
+ block_page = error_2b >> (PAGE_SHIFT - 4);
+ row = pvt->mc_symmetric ?
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row,
+ "e752x UE from Read");
+ }
+ if (error_one & 0x0404) {
+ error_2b = scrb_add;
+ /* convert to 4k address */
+ block_page = error_2b >> (PAGE_SHIFT - 4);
+ row = pvt->mc_symmetric ?
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row,
+ "e752x UE from Scruber");
+ }
+}
+
+static inline void process_ue(struct mem_ctl_info *mci, u16 error_one,
+ u32 ded_add, u32 scrb_add, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ue(mci, error_one, ded_add, scrb_add);
+}
+
+static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
+ int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (!handle_error)
+ return;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ue_no_info(mci, "e752x UE log memory write");
+}
+
+static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
+ u32 retry_add)
+{
+ u32 error_1b, page;
+ int row;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ error_1b = retry_add;
+ page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
+ row = pvt->mc_symmetric ?
+ ((page >> 1) & 3) : /* chip select are bits 14 & 13 */
+ edac_mc_find_csrow_by_page(mci, page);
+ printk(KERN_WARNING
+ "MC%d: CE page 0x%lx, row %d : Memory read retry\n",
+ mci->mc_idx, (long unsigned int) page, row);
+}
+
+static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
+ u32 retry_add, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ded_retry(mci, error, retry_add);
+}
+
+static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
+ int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ printk(KERN_WARNING "MC%d: Memory threshold CE\n",
+ mci->mc_idx);
+}
+
+static char *global_message[11] = {
+ "PCI Express C1", "PCI Express C", "PCI Express B1",
+ "PCI Express B", "PCI Express A1", "PCI Express A",
+ "DMA Controler", "HUB Interface", "System Bus",
+ "DRAM Controler", "Internal Buffer"
+};
+
+static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
+
+static void do_global_error(int fatal, u32 errors)
+{
+ int i;
+
+ for (i = 0; i < 11; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError %s\n",
+ fatal_message[fatal], global_message[i]);
+ }
+}
+
+static inline void global_error(int fatal, u32 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_global_error(fatal, errors);
+}
+
+static char *hub_message[7] = {
+ "HI Address or Command Parity", "HI Illegal Access",
+ "HI Internal Parity", "Out of Range Access",
+ "HI Data Parity", "Enhanced Config Access",
+ "Hub Interface Target Abort"
+};
+
+static void do_hub_error(int fatal, u8 errors)
+{
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError %s\n",
+ fatal_message[fatal], hub_message[i]);
+ }
+}
+
+static inline void hub_error(int fatal, u8 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_hub_error(fatal, errors);
+}
+
+static char *membuf_message[4] = {
+ "Internal PMWB to DRAM parity",
+ "Internal PMWB to System Bus Parity",
+ "Internal System Bus or IO to PMWB Parity",
+ "Internal DRAM to PMWB Parity"
+};
+
+static void do_membuf_error(u8 errors)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "Non-Fatal Error %s\n",
+ membuf_message[i]);
+ }
+}
+
+static inline void membuf_error(u8 errors, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_membuf_error(errors);
+}
+
+#if 0
+char *sysbus_message[10] = {
+ "Addr or Request Parity",
+ "Data Strobe Glitch",
+ "Addr Strobe Glitch",
+ "Data Parity",
+ "Addr Above TOM",
+ "Non DRAM Lock Error",
+ "MCERR", "BINIT",
+ "Memory Parity",
+ "IO Subsystem Parity"
+};
+#endif /* 0 */
+
+static void do_sysbus_error(int fatal, u32 errors)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError System Bus %s\n",
+ fatal_message[fatal], global_message[i]);
+ }
+}
+
+static inline void sysbus_error(int fatal, u32 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_sysbus_error(fatal, errors);
+}
+
+static void e752x_check_hub_interface (struct e752x_error_info *info,
+ int *error_found, int handle_error)
+{
+ u8 stat8;
+
+ //pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
+ stat8 = info->hi_ferr;
+ if(stat8 & 0x7f) { /* Error, so process */
+ stat8 &= 0x7f;
+ if(stat8 & 0x2b)
+ hub_error(1, stat8 & 0x2b, error_found, handle_error);
+ if(stat8 & 0x54)
+ hub_error(0, stat8 & 0x54, error_found, handle_error);
+ }
+ //pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
+ stat8 = info->hi_nerr;
+ if(stat8 & 0x7f) { /* Error, so process */
+ stat8 &= 0x7f;
+ if (stat8 & 0x2b)
+ hub_error(1, stat8 & 0x2b, error_found, handle_error);
+ if(stat8 & 0x54)
+ hub_error(0, stat8 & 0x54, error_found, handle_error);
+ }
+}
+
+static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
+ int handle_error)
+{
+ u32 stat32, error32;
+
+ //pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32);
+ stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16);
+
+ if (stat32 == 0)
+ return; /* no errors */
+
+ error32 = (stat32 >> 16) & 0x3ff;
+ stat32 = stat32 & 0x3ff;
+ if(stat32 & 0x083)
+ sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+ if(stat32 & 0x37c)
+ sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+ if(error32 & 0x083)
+ sysbus_error(1, error32 & 0x083, error_found, handle_error);
+ if(error32 & 0x37c)
+ sysbus_error(0, error32 & 0x37c, error_found, handle_error);
+}
+
+static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
+ int handle_error)
+{
+ u8 stat8;
+
+ stat8 = info->buf_ferr;
+ if (stat8 & 0x0f) { /* Error, so process */
+ stat8 &= 0x0f;
+ membuf_error(stat8, error_found, handle_error);
+ }
+ stat8 = info->buf_nerr;
+ if (stat8 & 0x0f) { /* Error, so process */
+ stat8 &= 0x0f;
+ membuf_error(stat8, error_found, handle_error);
+ }
+}
+
+static void e752x_check_dram (struct mem_ctl_info *mci,
+ struct e752x_error_info *info, int *error_found, int handle_error)
+{
+ u16 error_one, error_next;
+
+ error_one = info->dram_ferr;
+ error_next = info->dram_nerr;
+
+ /* decode and report errors */
+ if(error_one & 0x0101) /* check first error correctable */
+ process_ce(mci, error_one, info->dram_sec1_add,
+ info->dram_sec1_syndrome, error_found,
+ handle_error);
+
+ if(error_next & 0x0101) /* check next error correctable */
+ process_ce(mci, error_next, info->dram_sec2_add,
+ info->dram_sec2_syndrome, error_found,
+ handle_error);
+
+ if(error_one & 0x4040)
+ process_ue_no_info_wr(mci, error_found, handle_error);
+
+ if(error_next & 0x4040)
+ process_ue_no_info_wr(mci, error_found, handle_error);
+
+ if(error_one & 0x2020)
+ process_ded_retry(mci, error_one, info->dram_retr_add,
+ error_found, handle_error);
+
+ if(error_next & 0x2020)
+ process_ded_retry(mci, error_next, info->dram_retr_add,
+ error_found, handle_error);
+
+ if(error_one & 0x0808)
+ process_threshold_ce(mci, error_one, error_found,
+ handle_error);
+
+ if(error_next & 0x0808)
+ process_threshold_ce(mci, error_next, error_found,
+ handle_error);
+
+ if(error_one & 0x0606)
+ process_ue(mci, error_one, info->dram_ded_add,
+ info->dram_scrb_add, error_found, handle_error);
+
+ if(error_next & 0x0606)
+ process_ue(mci, error_next, info->dram_ded_add,
+ info->dram_scrb_add, error_found, handle_error);
+}
+
+static void e752x_get_error_info (struct mem_ctl_info *mci,
+ struct e752x_error_info *info)
+{
+ struct pci_dev *dev;
+ struct e752x_pvt *pvt;
+
+ memset(info, 0, sizeof(*info));
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ dev = pvt->dev_d0f1;
+
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
+
+ if (info->ferr_global) {
+ pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr);
+ pci_read_config_word(dev, E752X_SYSBUS_FERR,
+ &info->sysbus_ferr);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
+ pci_read_config_word(dev, E752X_DRAM_FERR,
+ &info->dram_ferr);
+ pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD,
+ &info->dram_sec1_add);
+ pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME,
+ &info->dram_sec1_syndrome);
+ pci_read_config_dword(dev, E752X_DRAM_DED_ADD,
+ &info->dram_ded_add);
+ pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD,
+ &info->dram_scrb_add);
+ pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
+ &info->dram_retr_add);
+
+ if (info->hi_ferr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_FERR,
+ info->hi_ferr);
+
+ if (info->sysbus_ferr)
+ pci_write_config_word(dev, E752X_SYSBUS_FERR,
+ info->sysbus_ferr);
+
+ if (info->buf_ferr & 0x0f)
+ pci_write_config_byte(dev, E752X_BUF_FERR,
+ info->buf_ferr);
+
+ if (info->dram_ferr)
+ pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR,
+ info->dram_ferr, info->dram_ferr);
+
+ pci_write_config_dword(dev, E752X_FERR_GLOBAL,
+ info->ferr_global);
+ }
+
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
+
+ if (info->nerr_global) {
+ pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr);
+ pci_read_config_word(dev, E752X_SYSBUS_NERR,
+ &info->sysbus_nerr);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
+ pci_read_config_word(dev, E752X_DRAM_NERR,
+ &info->dram_nerr);
+ pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD,
+ &info->dram_sec2_add);
+ pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME,
+ &info->dram_sec2_syndrome);
+
+ if (info->hi_nerr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_NERR,
+ info->hi_nerr);
+
+ if (info->sysbus_nerr)
+ pci_write_config_word(dev, E752X_SYSBUS_NERR,
+ info->sysbus_nerr);
+
+ if (info->buf_nerr & 0x0f)
+ pci_write_config_byte(dev, E752X_BUF_NERR,
+ info->buf_nerr);
+
+ if (info->dram_nerr)
+ pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR,
+ info->dram_nerr, info->dram_nerr);
+
+ pci_write_config_dword(dev, E752X_NERR_GLOBAL,
+ info->nerr_global);
+ }
+}
+
+static int e752x_process_error_info (struct mem_ctl_info *mci,
+ struct e752x_error_info *info, int handle_errors)
+{
+ u32 error32, stat32;
+ int error_found;
+
+ error_found = 0;
+ error32 = (info->ferr_global >> 18) & 0x3ff;
+ stat32 = (info->ferr_global >> 4) & 0x7ff;
+
+ if (error32)
+ global_error(1, error32, &error_found, handle_errors);
+
+ if (stat32)
+ global_error(0, stat32, &error_found, handle_errors);
+
+ error32 = (info->nerr_global >> 18) & 0x3ff;
+ stat32 = (info->nerr_global >> 4) & 0x7ff;
+
+ if (error32)
+ global_error(1, error32, &error_found, handle_errors);
+
+ if (stat32)
+ global_error(0, stat32, &error_found, handle_errors);
+
+ e752x_check_hub_interface(info, &error_found, handle_errors);
+ e752x_check_sysbus(info, &error_found, handle_errors);
+ e752x_check_membuf(info, &error_found, handle_errors);
+ e752x_check_dram(mci, info, &error_found, handle_errors);
+ return error_found;
+}
+
+static void e752x_check(struct mem_ctl_info *mci)
+{
+ struct e752x_error_info info;
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ e752x_get_error_info(mci, &info);
+ e752x_process_error_info(mci, &info, 1);
+}
+
+static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ u16 pci_data, stat;
+ u32 stat32;
+ u16 stat16;
+ u8 stat8;
+ struct mem_ctl_info *mci = NULL;
+ struct e752x_pvt *pvt = NULL;
+ u16 ddrcsr;
+ u32 drc;
+ int drc_chan; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg; /* DRB granularity 0=64mb,1=128mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ u32 dra;
+ unsigned long last_cumul_size;
+ struct pci_dev *pres_dev;
+ struct pci_dev *dev = NULL;
+
+ debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+ debugf0("Starting Probe1\n");
+
+ /* enable device 0 function 1 */
+ pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+ stat8 |= (1 << 5);
+ pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
+
+ /* need to find out the number of channels */
+ pci_read_config_dword(pdev, E752X_DRC, &drc);
+ pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr);
+ /* FIXME: should check >>12 or 0xf, true for all? */
+ /* Dual channel = 1, Single channel = 0 */
+ drc_chan = (((ddrcsr >> 12) & 3) == 3);
+ drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */
+ drc_ddim = (drc >> 20) & 0x3;
+
+ mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->mtype_cap = MEM_FLAG_RDDR;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
+ EDAC_FLAG_S4ECD4ED;
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.11 $";
+ mci->pdev = pdev;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ pvt->dev_info = &e752x_devs[dev_idx];
+ pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+ if (pvt->bridge_ck == NULL)
+ pvt->bridge_ck = pci_scan_single_device(pdev->bus,
+ PCI_DEVFN(0, 1));
+ if (pvt->bridge_ck == NULL) {
+ printk(KERN_ERR "MC: error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
+ goto fail;
+ }
+ pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
+
+ debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ mci->ctl_name = pvt->dev_info->ctl_name;
+ mci->edac_check = e752x_check;
+ mci->ctl_page_to_phys = ctl_page_to_phys;
+
+ /* find out the device types */
+ pci_read_config_dword(pdev, E752X_DRA, &dra);
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address for
+ * each DRAM row with a granularity of 64 or 128MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ /* mem_dev 0=x8, 1=x4 */
+ int mem_dev = (dra >> (index * 4 + 2)) & 0x3;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ mem_dev = (mem_dev == 2);
+ pci_read_config_byte(mci->pdev, E752X_DRB + index, &value);
+ /* convert a 128 or 64 MiB DRB to a page size. */
+ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+ /*
+ * if single channel or x8 devices then SECDED
+ * if dual channel and x4 then S4ECD4ED
+ */
+ if (drc_ddim) {
+ if (drc_chan && mem_dev) {
+ csrow->edac_mode = EDAC_S4ECD4ED;
+ mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+ } else {
+ csrow->edac_mode = EDAC_SECDED;
+ mci->edac_cap |= EDAC_FLAG_SECDED;
+ }
+ } else
+ csrow->edac_mode = EDAC_NONE;
+ }
+
+ /* Fill in the memory map table */
+ {
+ u8 value;
+ u8 last = 0;
+ u8 row = 0;
+ for (index = 0; index < 8; index += 2) {
+
+ pci_read_config_byte(mci->pdev, E752X_DRB + index,
+ &value);
+ /* test if there is a dimm in this slot */
+ if (value == last) {
+ /* no dimm in the slot, so flag it as empty */
+ pvt->map[index] = 0xff;
+ pvt->map[index + 1] = 0xff;
+ } else { /* there is a dimm in the slot */
+ pvt->map[index] = row;
+ row++;
+ last = value;
+ /* test the next value to see if the dimm is
+ double sided */
+ pci_read_config_byte(mci->pdev,
+ E752X_DRB + index + 1,
+ &value);
+ pvt->map[index + 1] = (value == last) ?
+ 0xff : /* the dimm is single sided,
+ so flag as empty */
+ row; /* this is a double sided dimm
+ to save the next row # */
+ row++;
+ last = value;
+ }
+ }
+ }
+
+ /* set the map type. 1 = normal, 0 = reversed */
+ pci_read_config_byte(mci->pdev, E752X_DRM, &stat8);
+ pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
+
+ mci->edac_cap |= EDAC_FLAG_NONE;
+
+ debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+ __func__);
+ /* load the top of low memory, remap base, and remap limit vars */
+ pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
+ pvt->tolm = ((u32) pci_data) << 4;
+ pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data);
+ pvt->remapbase = ((u32) pci_data) << 14;
+ pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
+ pvt->remaplimit = ((u32) pci_data) << 14;
+ printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ goto fail;
+ }
+
+ /* Walk through the PCI table and clear errors */
+ switch (dev_idx) {
+ case E7520:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7520_0, NULL);
+ break;
+ case E7525:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7525_0, NULL);
+ break;
+ case E7320:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7320_0, NULL);
+ break;
+ }
+
+
+ pvt->dev_d0f0 = dev;
+ for (pres_dev = dev;
+ ((struct pci_dev *) pres_dev->global_list.next != dev);
+ pres_dev = (struct pci_dev *) pres_dev->global_list.next) {
+ pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32);
+ stat = (u16) (stat32 >> 16);
+ /* clear any error bits */
+ if (stat32 & ((1 << 6) + (1 << 8)))
+ pci_write_config_word(pres_dev, PCI_STATUS, stat);
+ }
+ /* find the error reporting device and clear errors */
+ dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
+ /* Turn off error disable & SMI in case the BIOS turned it on */
+ pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
+ pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
+ pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
+ /* clear other MCH errors */
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32);
+ pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32);
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32);
+ pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32);
+ pci_read_config_byte(dev, E752X_HI_FERR, &stat8);
+ pci_write_config_byte(dev, E752X_HI_FERR, stat8);
+ pci_read_config_byte(dev, E752X_HI_NERR, &stat8);
+ pci_write_config_byte(dev, E752X_HI_NERR, stat8);
+ pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32);
+ pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &stat8);
+ pci_write_config_byte(dev, E752X_BUF_FERR, stat8);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &stat8);
+ pci_write_config_byte(dev, E752X_BUF_NERR, stat8);
+ pci_read_config_word(dev, E752X_DRAM_FERR, &stat16);
+ pci_write_config_word(dev, E752X_DRAM_FERR, stat16);
+ pci_read_config_word(dev, E752X_DRAM_NERR, &stat16);
+ pci_write_config_word(dev, E752X_DRAM_NERR, stat16);
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci) {
+ if (pvt->dev_d0f0)
+ pci_dev_put(pvt->dev_d0f0);
+ if (pvt->dev_d0f1)
+ pci_dev_put(pvt->dev_d0f1);
+ if (pvt->bridge_ck)
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit e752x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up and enable device */
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ return e752x_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e752x_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct e752x_pvt *pvt;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+
+ if (edac_mc_del_mc(mci))
+ return;
+
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->dev_d0f0);
+ pci_dev_put(pvt->dev_d0f1);
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7520},
+ {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7525},
+ {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7320},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
+
+
+static struct pci_driver e752x_driver = {
+ name: BS_MOD_STR,
+ probe: e752x_init_one,
+ remove: __devexit_p(e752x_remove_one),
+ id_table: e752x_pci_tbl,
+};
+
+
+static int __init e752x_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_rc = pci_register_driver(&e752x_driver);
+ return (pci_rc < 0) ? pci_rc : 0;
+}
+
+
+static void __exit e752x_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_unregister_driver(&e752x_driver);
+}
+
+
+module_init(e752x_init);
+module_exit(e752x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
+MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
new file mode 100644
index 000000000000..d5e320dfc66f
--- /dev/null
+++ b/drivers/edac/e7xxx_edac.c
@@ -0,0 +1,558 @@
+/*
+ * Intel e7xxx Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e7xxx_chips" below for supported chipsets
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Contributors:
+ * Eric Biederman (Linux Networx)
+ * Tom Zimmerman (Linux Networx)
+ * Jim Garlick (Lawrence Livermore National Labs)
+ * Dave Peterson (Lawrence Livermore National Labs)
+ * That One Guy (Some other place)
+ * Wang Zhenyu (intel.com)
+ *
+ * $Id: edac_e7xxx.c,v 1.5.2.9 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_0
+#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
+#endif /* PCI_DEVICE_ID_INTEL_7205_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_1_ERR
+#define PCI_DEVICE_ID_INTEL_7205_1_ERR 0x2551
+#endif /* PCI_DEVICE_ID_INTEL_7205_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_0
+#define PCI_DEVICE_ID_INTEL_7500_0 0x2540
+#endif /* PCI_DEVICE_ID_INTEL_7500_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_1_ERR
+#define PCI_DEVICE_ID_INTEL_7500_1_ERR 0x2541
+#endif /* PCI_DEVICE_ID_INTEL_7500_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_0
+#define PCI_DEVICE_ID_INTEL_7501_0 0x254c
+#endif /* PCI_DEVICE_ID_INTEL_7501_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_1_ERR
+#define PCI_DEVICE_ID_INTEL_7501_1_ERR 0x2541
+#endif /* PCI_DEVICE_ID_INTEL_7501_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_0
+#define PCI_DEVICE_ID_INTEL_7505_0 0x2550
+#endif /* PCI_DEVICE_ID_INTEL_7505_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_1_ERR
+#define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551
+#endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */
+
+
+#define E7XXX_NR_CSROWS 8 /* number of csrows */
+#define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */
+
+
+/* E7XXX register addresses - device 0 function 0 */
+#define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */
+#define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */
+ /*
+ * 31 Device width row 7 0=x8 1=x4
+ * 27 Device width row 6
+ * 23 Device width row 5
+ * 19 Device width row 4
+ * 15 Device width row 3
+ * 11 Device width row 2
+ * 7 Device width row 1
+ * 3 Device width row 0
+ */
+#define E7XXX_DRC 0x7C /* DRAM controller mode reg (32b) */
+ /*
+ * 22 Number channels 0=1,1=2
+ * 19:18 DRB Granularity 32/64MB
+ */
+#define E7XXX_TOLM 0xC4 /* DRAM top of low memory reg (16b) */
+#define E7XXX_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */
+#define E7XXX_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */
+
+/* E7XXX register addresses - device 0 function 1 */
+#define E7XXX_DRAM_FERR 0x80 /* DRAM first error register (8b) */
+#define E7XXX_DRAM_NERR 0x82 /* DRAM next error register (8b) */
+#define E7XXX_DRAM_CELOG_ADD 0xA0 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31:28 Reserved
+ * 27:6 CE address (4k block 33:12)
+ * 5:0 Reserved
+ */
+#define E7XXX_DRAM_UELOG_ADD 0xB0 /* DRAM first uncorrectable memory */
+ /* error address register (32b) */
+ /*
+ * 31:28 Reserved
+ * 27:6 CE address (4k block 33:12)
+ * 5:0 Reserved
+ */
+#define E7XXX_DRAM_CELOG_SYNDROME 0xD0 /* DRAM first correctable memory */
+ /* error syndrome register (16b) */
+
+enum e7xxx_chips {
+ E7500 = 0,
+ E7501,
+ E7505,
+ E7205,
+};
+
+
+struct e7xxx_pvt {
+ struct pci_dev *bridge_ck;
+ u32 tolm;
+ u32 remapbase;
+ u32 remaplimit;
+ const struct e7xxx_dev_info *dev_info;
+};
+
+
+struct e7xxx_dev_info {
+ u16 err_dev;
+ const char *ctl_name;
+};
+
+
+struct e7xxx_error_info {
+ u8 dram_ferr;
+ u8 dram_nerr;
+ u32 dram_celog_add;
+ u16 dram_celog_syndrome;
+ u32 dram_uelog_add;
+};
+
+static const struct e7xxx_dev_info e7xxx_devs[] = {
+ [E7500] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
+ .ctl_name = "E7500"},
+ [E7501] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
+ .ctl_name = "E7501"},
+ [E7505] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
+ .ctl_name = "E7505"},
+ [E7205] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
+ .ctl_name = "E7205"},
+};
+
+
+/* FIXME - is this valid for both SECDED and S4ECD4ED? */
+static inline int e7xxx_find_channel(u16 syndrome)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if ((syndrome & 0xff00) == 0)
+ return 0;
+ if ((syndrome & 0x00ff) == 0)
+ return 1;
+ if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0)
+ return 0;
+ return 1;
+}
+
+
+static unsigned long
+ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
+{
+ u32 remap;
+ struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if ((page < pvt->tolm) ||
+ ((page >= 0x100000) && (page < pvt->remapbase)))
+ return page;
+ remap = (page - pvt->tolm) + pvt->remapbase;
+ if (remap < pvt->remaplimit)
+ return remap;
+ printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+ return pvt->tolm - 1;
+}
+
+
+static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+ u32 error_1b, page;
+ u16 syndrome;
+ int row;
+ int channel;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* read the error address */
+ error_1b = info->dram_celog_add;
+ /* FIXME - should use PAGE_SHIFT */
+ page = error_1b >> 6; /* convert the address to 4k page */
+ /* read the syndrome */
+ syndrome = info->dram_celog_syndrome;
+ /* FIXME - check for -1 */
+ row = edac_mc_find_csrow_by_page(mci, page);
+ /* convert syndrome to channel */
+ channel = e7xxx_find_channel(syndrome);
+ edac_mc_handle_ce(mci, page, 0, syndrome, row, channel,
+ "e7xxx CE");
+}
+
+
+static void process_ce_no_info(struct mem_ctl_info *mci)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow");
+}
+
+
+static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+ u32 error_2b, block_page;
+ int row;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* read the error address */
+ error_2b = info->dram_uelog_add;
+ /* FIXME - should use PAGE_SHIFT */
+ block_page = error_2b >> 6; /* convert to 4k address */
+ row = edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE");
+}
+
+
+static void process_ue_no_info(struct mem_ctl_info *mci)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow");
+}
+
+
+static void e7xxx_get_error_info (struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info)
+{
+ struct e7xxx_pvt *pvt;
+
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR,
+ &info->dram_ferr);
+ pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR,
+ &info->dram_nerr);
+
+ if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) {
+ pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD,
+ &info->dram_celog_add);
+ pci_read_config_word(pvt->bridge_ck,
+ E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome);
+ }
+
+ if ((info->dram_ferr & 2) || (info->dram_nerr & 2))
+ pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD,
+ &info->dram_uelog_add);
+
+ if (info->dram_ferr & 3)
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03,
+ 0x03);
+
+ if (info->dram_nerr & 3)
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03,
+ 0x03);
+}
+
+
+static int e7xxx_process_error_info (struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info, int handle_errors)
+{
+ int error_found;
+
+ error_found = 0;
+
+ /* decode and report errors */
+ if (info->dram_ferr & 1) { /* check first error correctable */
+ error_found = 1;
+
+ if (handle_errors)
+ process_ce(mci, info);
+ }
+
+ if (info->dram_ferr & 2) { /* check first error uncorrectable */
+ error_found = 1;
+
+ if (handle_errors)
+ process_ue(mci, info);
+ }
+
+ if (info->dram_nerr & 1) { /* check next error correctable */
+ error_found = 1;
+
+ if (handle_errors) {
+ if (info->dram_ferr & 1)
+ process_ce_no_info(mci);
+ else
+ process_ce(mci, info);
+ }
+ }
+
+ if (info->dram_nerr & 2) { /* check next error uncorrectable */
+ error_found = 1;
+
+ if (handle_errors) {
+ if (info->dram_ferr & 2)
+ process_ue_no_info(mci);
+ else
+ process_ue(mci, info);
+ }
+ }
+
+ return error_found;
+}
+
+
+static void e7xxx_check(struct mem_ctl_info *mci)
+{
+ struct e7xxx_error_info info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ e7xxx_get_error_info(mci, &info);
+ e7xxx_process_error_info(mci, &info, 1);
+}
+
+
+static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ u16 pci_data;
+ struct mem_ctl_info *mci = NULL;
+ struct e7xxx_pvt *pvt = NULL;
+ u32 drc;
+ int drc_chan = 1; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg = 1; /* DRB granularity 0=32mb,1=64mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ u32 dra;
+ unsigned long last_cumul_size;
+
+
+ debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+
+ /* need to find out the number of channels */
+ pci_read_config_dword(pdev, E7XXX_DRC, &drc);
+ /* only e7501 can be single channel */
+ if (dev_idx == E7501) {
+ drc_chan = ((drc >> 22) & 0x1);
+ drc_drbg = (drc >> 18) & 0x3;
+ }
+ drc_ddim = (drc >> 20) & 0x3;
+
+ mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->mtype_cap = MEM_FLAG_RDDR;
+ mci->edac_ctl_cap =
+ EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED;
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.9 $";
+ mci->pdev = pdev;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pvt->dev_info = &e7xxx_devs[dev_idx];
+ pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+ if (!pvt->bridge_ck) {
+ printk(KERN_ERR
+ "MC: error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ mci->ctl_name = pvt->dev_info->ctl_name;
+
+ mci->edac_check = e7xxx_check;
+ mci->ctl_page_to_phys = ctl_page_to_phys;
+
+ /* find out the device types */
+ pci_read_config_dword(pdev, E7XXX_DRA, &dra);
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address
+ * for each DRAM row with a granularity of 32 or 64MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ /* mem_dev 0=x8, 1=x4 */
+ int mem_dev = (dra >> (index * 4 + 3)) & 0x1;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value);
+ /* convert a 64 or 32 MiB DRB to a page size. */
+ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+ /*
+ * if single channel or x8 devices then SECDED
+ * if dual channel and x4 then S4ECD4ED
+ */
+ if (drc_ddim) {
+ if (drc_chan && mem_dev) {
+ csrow->edac_mode = EDAC_S4ECD4ED;
+ mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+ } else {
+ csrow->edac_mode = EDAC_SECDED;
+ mci->edac_cap |= EDAC_FLAG_SECDED;
+ }
+ } else
+ csrow->edac_mode = EDAC_NONE;
+ }
+
+ mci->edac_cap |= EDAC_FLAG_NONE;
+
+ debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+ __func__);
+ /* load the top of low memory, remap base, and remap limit vars */
+ pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data);
+ pvt->tolm = ((u32) pci_data) << 4;
+ pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data);
+ pvt->remapbase = ((u32) pci_data) << 14;
+ pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
+ pvt->remaplimit = ((u32) pci_data) << 14;
+ printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
+
+ /* clear any pending errors, or initial state bits */
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
+
+ if (edac_mc_add_mc(mci) != 0) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci != NULL) {
+ if(pvt != NULL && pvt->bridge_ck)
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit
+e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up and enable device */
+ return pci_enable_device(pdev) ?
+ -EIO : e7xxx_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct e7xxx_pvt *pvt;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) &&
+ edac_mc_del_mc(mci)) {
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+}
+
+
+static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7205},
+ {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7500},
+ {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7501},
+ {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7505},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
+
+
+static struct pci_driver e7xxx_driver = {
+ .name = BS_MOD_STR,
+ .probe = e7xxx_init_one,
+ .remove = __devexit_p(e7xxx_remove_one),
+ .id_table = e7xxx_pci_tbl,
+};
+
+
+static int __init e7xxx_init(void)
+{
+ return pci_register_driver(&e7xxx_driver);
+}
+
+
+static void __exit e7xxx_exit(void)
+{
+ pci_unregister_driver(&e7xxx_driver);
+}
+
+module_init(e7xxx_init);
+module_exit(e7xxx_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+ "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
new file mode 100644
index 000000000000..4be9bd0a1267
--- /dev/null
+++ b/drivers/edac/edac_mc.c
@@ -0,0 +1,2209 @@
+/*
+ * edac_mc kernel module
+ * (C) 2005 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Modified by Dave Peterson and Doug Thompson
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/highmem.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/sysdev.h>
+#include <linux/ctype.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/edac.h>
+
+#include "edac_mc.h"
+
+#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__
+
+#ifdef CONFIG_EDAC_DEBUG
+/* Values of 0 to 4 will generate output */
+int edac_debug_level = 1;
+EXPORT_SYMBOL(edac_debug_level);
+#endif
+
+/* EDAC Controls, setable by module parameter, and sysfs */
+static int log_ue = 1;
+static int log_ce = 1;
+static int panic_on_ue = 1;
+static int poll_msec = 1000;
+
+static int check_pci_parity = 0; /* default YES check PCI parity */
+static int panic_on_pci_parity; /* default no panic on PCI Parity */
+static atomic_t pci_parity_count = ATOMIC_INIT(0);
+
+/* lock to memory controller's control array */
+static DECLARE_MUTEX(mem_ctls_mutex);
+static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
+
+/* Structure of the whitelist and blacklist arrays */
+struct edac_pci_device_list {
+ unsigned int vendor; /* Vendor ID */
+ unsigned int device; /* Deviice ID */
+};
+
+
+#define MAX_LISTED_PCI_DEVICES 32
+
+/* List of PCI devices (vendor-id:device-id) that should be skipped */
+static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
+static int pci_blacklist_count;
+
+/* List of PCI devices (vendor-id:device-id) that should be scanned */
+static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
+static int pci_whitelist_count ;
+
+/* START sysfs data and methods */
+
+static const char *mem_types[] = {
+ [MEM_EMPTY] = "Empty",
+ [MEM_RESERVED] = "Reserved",
+ [MEM_UNKNOWN] = "Unknown",
+ [MEM_FPM] = "FPM",
+ [MEM_EDO] = "EDO",
+ [MEM_BEDO] = "BEDO",
+ [MEM_SDR] = "Unbuffered-SDR",
+ [MEM_RDR] = "Registered-SDR",
+ [MEM_DDR] = "Unbuffered-DDR",
+ [MEM_RDDR] = "Registered-DDR",
+ [MEM_RMBS] = "RMBS"
+};
+
+static const char *dev_types[] = {
+ [DEV_UNKNOWN] = "Unknown",
+ [DEV_X1] = "x1",
+ [DEV_X2] = "x2",
+ [DEV_X4] = "x4",
+ [DEV_X8] = "x8",
+ [DEV_X16] = "x16",
+ [DEV_X32] = "x32",
+ [DEV_X64] = "x64"
+};
+
+static const char *edac_caps[] = {
+ [EDAC_UNKNOWN] = "Unknown",
+ [EDAC_NONE] = "None",
+ [EDAC_RESERVED] = "Reserved",
+ [EDAC_PARITY] = "PARITY",
+ [EDAC_EC] = "EC",
+ [EDAC_SECDED] = "SECDED",
+ [EDAC_S2ECD2ED] = "S2ECD2ED",
+ [EDAC_S4ECD4ED] = "S4ECD4ED",
+ [EDAC_S8ECD8ED] = "S8ECD8ED",
+ [EDAC_S16ECD16ED] = "S16ECD16ED"
+};
+
+
+/* sysfs object: /sys/devices/system/edac */
+static struct sysdev_class edac_class = {
+ set_kset_name("edac"),
+};
+
+/* sysfs objects:
+ * /sys/devices/system/edac/mc
+ * /sys/devices/system/edac/pci
+ */
+static struct kobject edac_memctrl_kobj;
+static struct kobject edac_pci_kobj;
+
+/*
+ * /sys/devices/system/edac/mc;
+ * data structures and methods
+ */
+static ssize_t memctrl_string_show(void *ptr, char *buffer)
+{
+ char *value = (char*) ptr;
+ return sprintf(buffer, "%s\n", value);
+}
+
+static ssize_t memctrl_int_show(void *ptr, char *buffer)
+{
+ int *value = (int*) ptr;
+ return sprintf(buffer, "%d\n", *value);
+}
+
+static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
+{
+ int *value = (int*) ptr;
+
+ if (isdigit(*buffer))
+ *value = simple_strtoul(buffer, NULL, 0);
+
+ return count;
+}
+
+struct memctrl_dev_attribute {
+ struct attribute attr;
+ void *value;
+ ssize_t (*show)(void *,char *);
+ ssize_t (*store)(void *, const char *, size_t);
+};
+
+/* Set of show/store abstract level functions for memory control object */
+static ssize_t
+memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
+{
+ struct memctrl_dev_attribute *memctrl_dev;
+ memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+ if (memctrl_dev->show)
+ return memctrl_dev->show(memctrl_dev->value, buffer);
+ return -EIO;
+}
+
+static ssize_t
+memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct memctrl_dev_attribute *memctrl_dev;
+ memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+ if (memctrl_dev->store)
+ return memctrl_dev->store(memctrl_dev->value, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops memctrlfs_ops = {
+ .show = memctrl_dev_show,
+ .store = memctrl_dev_store
+};
+
+#define MEMCTRL_ATTR(_name,_mode,_show,_store) \
+struct memctrl_dev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = &_name, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store) \
+struct memctrl_dev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = _data, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* cwrow<id> attribute f*/
+MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
+
+/* csrow<id> control files */
+MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+
+
+/* Base Attributes of the memory ECC object */
+static struct memctrl_dev_attribute *memctrl_attr[] = {
+ &attr_panic_on_ue,
+ &attr_log_ue,
+ &attr_log_ce,
+ &attr_poll_msec,
+ &attr_mc_version,
+ NULL,
+};
+
+/* Main MC kobject release() function */
+static void edac_memctrl_master_release(struct kobject *kobj)
+{
+ debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_memctrl = {
+ .release = edac_memctrl_master_release,
+ .sysfs_ops = &memctrlfs_ops,
+ .default_attrs = (struct attribute **) memctrl_attr,
+};
+
+
+/* Initialize the main sysfs entries for edac:
+ * /sys/devices/system/edac
+ *
+ * and children
+ *
+ * Return: 0 SUCCESS
+ * !0 FAILURE
+ */
+static int edac_sysfs_memctrl_setup(void)
+{
+ int err=0;
+
+ debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* create the /sys/devices/system/edac directory */
+ err = sysdev_class_register(&edac_class);
+ if (!err) {
+ /* Init the MC's kobject */
+ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
+ kobject_init(&edac_memctrl_kobj);
+
+ edac_memctrl_kobj.parent = &edac_class.kset.kobj;
+ edac_memctrl_kobj.ktype = &ktype_memctrl;
+
+ /* generate sysfs "..../edac/mc" */
+ err = kobject_set_name(&edac_memctrl_kobj,"mc");
+ if (!err) {
+ /* FIXME: maybe new sysdev_create_subdir() */
+ err = kobject_register(&edac_memctrl_kobj);
+ if (err) {
+ debugf1("Failed to register '.../edac/mc'\n");
+ } else {
+ debugf1("Registered '.../edac/mc' kobject\n");
+ }
+ }
+ } else {
+ debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err);
+ }
+
+ return err;
+}
+
+/*
+ * MC teardown:
+ * the '..../edac/mc' kobject followed by '..../edac' itself
+ */
+static void edac_sysfs_memctrl_teardown(void)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* Unregister the MC's kobject */
+ kobject_unregister(&edac_memctrl_kobj);
+
+ /* release the master edac mc kobject */
+ kobject_put(&edac_memctrl_kobj);
+
+ /* Unregister the 'edac' object */
+ sysdev_class_unregister(&edac_class);
+}
+
+/*
+ * /sys/devices/system/edac/pci;
+ * data structures and methods
+ */
+
+struct list_control {
+ struct edac_pci_device_list *list;
+ int *count;
+};
+
+/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
+static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
+{
+ struct list_control *listctl;
+ struct edac_pci_device_list *list;
+ char *p = buffer;
+ int len=0;
+ int i;
+
+ listctl = ptr;
+ list = listctl->list;
+
+ for (i = 0; i < *(listctl->count); i++, list++ ) {
+ if (len > 0)
+ len += snprintf(p + len, (PAGE_SIZE-len), ",");
+
+ len += snprintf(p + len,
+ (PAGE_SIZE-len),
+ "%x:%x",
+ list->vendor,list->device);
+ }
+
+ len += snprintf(p + len,(PAGE_SIZE-len), "\n");
+
+ return (ssize_t) len;
+}
+
+/**
+ *
+ * Scan string from **s to **e looking for one 'vendor:device' tuple
+ * where each field is a hex value
+ *
+ * return 0 if an entry is NOT found
+ * return 1 if an entry is found
+ * fill in *vendor_id and *device_id with values found
+ *
+ * In both cases, make sure *s has been moved forward toward *e
+ */
+static int parse_one_device(const char **s,const char **e,
+ unsigned int *vendor_id, unsigned int *device_id)
+{
+ const char *runner, *p;
+
+ /* if null byte, we are done */
+ if (!**s) {
+ (*s)++; /* keep *s moving */
+ return 0;
+ }
+
+ /* skip over newlines & whitespace */
+ if ((**s == '\n') || isspace(**s)) {
+ (*s)++;
+ return 0;
+ }
+
+ if (!isxdigit(**s)) {
+ (*s)++;
+ return 0;
+ }
+
+ /* parse vendor_id */
+ runner = *s;
+ while (runner < *e) {
+ /* scan for vendor:device delimiter */
+ if (*runner == ':') {
+ *vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
+ runner = p + 1;
+ break;
+ }
+ runner++;
+ }
+
+ if (!isxdigit(*runner)) {
+ *s = ++runner;
+ return 0;
+ }
+
+ /* parse device_id */
+ if (runner < *e) {
+ *device_id = simple_strtol((char*)runner, (char**)&p, 16);
+ runner = p;
+ }
+
+ *s = runner;
+
+ return 1;
+}
+
+static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
+ size_t count)
+{
+ struct list_control *listctl;
+ struct edac_pci_device_list *list;
+ unsigned int vendor_id, device_id;
+ const char *s, *e;
+ int *index;
+
+ s = (char*)buffer;
+ e = s + count;
+
+ listctl = ptr;
+ list = listctl->list;
+ index = listctl->count;
+
+ *index = 0;
+ while (*index < MAX_LISTED_PCI_DEVICES) {
+
+ if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
+ list[ *index ].vendor = vendor_id;
+ list[ *index ].device = device_id;
+ (*index)++;
+ }
+
+ /* check for all data consume */
+ if (s >= e)
+ break;
+ }
+
+ return count;
+}
+
+static ssize_t edac_pci_int_show(void *ptr, char *buffer)
+{
+ int *value = ptr;
+ return sprintf(buffer,"%d\n",*value);
+}
+
+static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
+{
+ int *value = ptr;
+
+ if (isdigit(*buffer))
+ *value = simple_strtoul(buffer,NULL,0);
+
+ return count;
+}
+
+struct edac_pci_dev_attribute {
+ struct attribute attr;
+ void *value;
+ ssize_t (*show)(void *,char *);
+ ssize_t (*store)(void *, const char *,size_t);
+};
+
+/* Set of show/store abstract level functions for PCI Parity object */
+static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct edac_pci_dev_attribute *edac_pci_dev;
+ edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+ if (edac_pci_dev->show)
+ return edac_pci_dev->show(edac_pci_dev->value, buffer);
+ return -EIO;
+}
+
+static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct edac_pci_dev_attribute *edac_pci_dev;
+ edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+ if (edac_pci_dev->show)
+ return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops edac_pci_sysfs_ops = {
+ .show = edac_pci_dev_show,
+ .store = edac_pci_dev_store
+};
+
+
+#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \
+struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = &_name, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store) \
+struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = _data, \
+ .show = _show, \
+ .store = _store, \
+};
+
+static struct list_control pci_whitelist_control = {
+ .list = pci_whitelist,
+ .count = &pci_whitelist_count
+};
+
+static struct list_control pci_blacklist_control = {
+ .list = pci_blacklist,
+ .count = &pci_blacklist_count
+};
+
+/* whitelist attribute */
+EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
+ &pci_whitelist_control,
+ S_IRUGO|S_IWUSR,
+ edac_pci_list_string_show,
+ edac_pci_list_string_store);
+
+EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
+ &pci_blacklist_control,
+ S_IRUGO|S_IWUSR,
+ edac_pci_list_string_show,
+ edac_pci_list_string_store);
+
+/* PCI Parity control files */
+EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
+
+/* Base Attributes of the memory ECC object */
+static struct edac_pci_dev_attribute *edac_pci_attr[] = {
+ &edac_pci_attr_check_pci_parity,
+ &edac_pci_attr_panic_on_pci_parity,
+ &edac_pci_attr_pci_parity_count,
+ &edac_pci_attr_pci_parity_whitelist,
+ &edac_pci_attr_pci_parity_blacklist,
+ NULL,
+};
+
+/* No memory to release */
+static void edac_pci_release(struct kobject *kobj)
+{
+ debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_edac_pci = {
+ .release = edac_pci_release,
+ .sysfs_ops = &edac_pci_sysfs_ops,
+ .default_attrs = (struct attribute **) edac_pci_attr,
+};
+
+/**
+ * edac_sysfs_pci_setup()
+ *
+ */
+static int edac_sysfs_pci_setup(void)
+{
+ int err;
+
+ debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+ memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
+
+ kobject_init(&edac_pci_kobj);
+ edac_pci_kobj.parent = &edac_class.kset.kobj;
+ edac_pci_kobj.ktype = &ktype_edac_pci;
+
+ err = kobject_set_name(&edac_pci_kobj, "pci");
+ if (!err) {
+ /* Instanstiate the csrow object */
+ /* FIXME: maybe new sysdev_create_subdir() */
+ err = kobject_register(&edac_pci_kobj);
+ if (err)
+ debugf1("Failed to register '.../edac/pci'\n");
+ else
+ debugf1("Registered '.../edac/pci' kobject\n");
+ }
+ return err;
+}
+
+
+static void edac_sysfs_pci_teardown(void)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ kobject_unregister(&edac_pci_kobj);
+ kobject_put(&edac_pci_kobj);
+}
+
+/* EDAC sysfs CSROW data structures and methods */
+
+/* Set of more detailed csrow<id> attribute show/store functions */
+static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
+ csrow->channels[0].label);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
+ csrow->channels[1].label);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
+ const char *data, size_t size)
+{
+ ssize_t max_size = 0;
+
+ if (csrow->nr_channels > 0) {
+ max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[0].label, data, max_size);
+ csrow->channels[0].label[max_size] = '\0';
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
+ const char *data, size_t size)
+{
+ ssize_t max_size = 0;
+
+ if (csrow->nr_channels > 1) {
+ max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[1].label, data, max_size);
+ csrow->channels[1].label[max_size] = '\0';
+ }
+ return max_size;
+}
+
+static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", csrow->ue_count);
+}
+
+static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", csrow->ce_count);
+}
+
+static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 1) {
+ size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
+ }
+ return size;
+}
+
+static ssize_t csrow_size_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
+}
+
+static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", mem_types[csrow->mtype]);
+}
+
+static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", dev_types[csrow->dtype]);
+}
+
+static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
+}
+
+struct csrowdev_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct csrow_info *,char *);
+ ssize_t (*store)(struct csrow_info *, const char *,size_t);
+};
+
+#define to_csrow(k) container_of(k, struct csrow_info, kobj)
+#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
+
+/* Set of show/store higher level functions for csrow objects */
+static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct csrow_info *csrow = to_csrow(kobj);
+ struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
+
+ if (csrowdev_attr->show)
+ return csrowdev_attr->show(csrow, buffer);
+ return -EIO;
+}
+
+static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct csrow_info *csrow = to_csrow(kobj);
+ struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
+
+ if (csrowdev_attr->store)
+ return csrowdev_attr->store(csrow, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops csrowfs_ops = {
+ .show = csrowdev_show,
+ .store = csrowdev_store
+};
+
+#define CSROWDEV_ATTR(_name,_mode,_show,_store) \
+struct csrowdev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* cwrow<id>/attribute files */
+CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL);
+CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL);
+CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL);
+CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL);
+CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL);
+CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL);
+CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
+CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
+
+/* control/attribute files */
+CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
+ csrow_ch0_dimm_label_show,
+ csrow_ch0_dimm_label_store);
+CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
+ csrow_ch1_dimm_label_show,
+ csrow_ch1_dimm_label_store);
+
+
+/* Attributes of the CSROW<id> object */
+static struct csrowdev_attribute *csrow_attr[] = {
+ &attr_dev_type,
+ &attr_mem_type,
+ &attr_edac_mode,
+ &attr_size_mb,
+ &attr_ue_count,
+ &attr_ce_count,
+ &attr_ch0_ce_count,
+ &attr_ch1_ce_count,
+ &attr_ch0_dimm_label,
+ &attr_ch1_dimm_label,
+ NULL,
+};
+
+
+/* No memory to release */
+static void edac_csrow_instance_release(struct kobject *kobj)
+{
+ debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_csrow = {
+ .release = edac_csrow_instance_release,
+ .sysfs_ops = &csrowfs_ops,
+ .default_attrs = (struct attribute **) csrow_attr,
+};
+
+/* Create a CSROW object under specifed edac_mc_device */
+static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
+ struct csrow_info *csrow, int index )
+{
+ int err = 0;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ memset(&csrow->kobj, 0, sizeof(csrow->kobj));
+
+ /* generate ..../edac/mc/mc<id>/csrow<index> */
+
+ kobject_init(&csrow->kobj);
+ csrow->kobj.parent = edac_mci_kobj;
+ csrow->kobj.ktype = &ktype_csrow;
+
+ /* name this instance of csrow<id> */
+ err = kobject_set_name(&csrow->kobj,"csrow%d",index);
+ if (!err) {
+ /* Instanstiate the csrow object */
+ err = kobject_register(&csrow->kobj);
+ if (err)
+ debugf0("Failed to register CSROW%d\n",index);
+ else
+ debugf0("Registered CSROW%d\n",index);
+ }
+
+ return err;
+}
+
+/* sysfs data structures and methods for the MCI kobjects */
+
+static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
+ const char *data, size_t count )
+{
+ int row, chan;
+
+ mci->ue_noinfo_count = 0;
+ mci->ce_noinfo_count = 0;
+ mci->ue_count = 0;
+ mci->ce_count = 0;
+ for (row = 0; row < mci->nr_csrows; row++) {
+ struct csrow_info *ri = &mci->csrows[row];
+
+ ri->ue_count = 0;
+ ri->ce_count = 0;
+ for (chan = 0; chan < ri->nr_channels; chan++)
+ ri->channels[chan].ce_count = 0;
+ }
+ mci->start_time = jiffies;
+
+ return count;
+}
+
+static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ue_count);
+}
+
+static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ce_count);
+}
+
+static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ce_noinfo_count);
+}
+
+static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ue_noinfo_count);
+}
+
+static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
+}
+
+static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
+}
+
+static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%s\n", mci->ctl_name);
+}
+
+static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
+{
+ char *p = buf;
+ int bit_idx;
+
+ for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
+ if ((edac_cap >> bit_idx) & 0x1)
+ p += sprintf(p, "%s ", edac_caps[bit_idx]);
+ }
+
+ return p - buf;
+}
+
+static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
+{
+ char *p = data;
+
+ p += mci_output_edac_cap(p,mci->edac_ctl_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ char *p = data;
+
+ p += mci_output_edac_cap(p,mci->edac_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
+{
+ char *p = buf;
+ int bit_idx;
+
+ for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
+ if ((mtype_cap >> bit_idx) & 0x1)
+ p += sprintf(p, "%s ", mem_types[bit_idx]);
+ }
+
+ return p - buf;
+}
+
+static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
+{
+ char *p = data;
+
+ p += mci_output_mtype_cap(p,mci->mtype_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
+{
+ int total_pages, csrow_idx;
+
+ for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
+ csrow_idx++) {
+ struct csrow_info *csrow = &mci->csrows[csrow_idx];
+
+ if (!csrow->nr_pages)
+ continue;
+ total_pages += csrow->nr_pages;
+ }
+
+ return sprintf(data,"%u\n", PAGES_TO_MiB(total_pages));
+}
+
+struct mcidev_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct mem_ctl_info *,char *);
+ ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
+};
+
+#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
+#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
+
+static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+ struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+ if (mcidev_attr->show)
+ return mcidev_attr->show(mem_ctl_info, buffer);
+ return -EIO;
+}
+
+static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+ struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+ if (mcidev_attr->store)
+ return mcidev_attr->store(mem_ctl_info, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops mci_ops = {
+ .show = mcidev_show,
+ .store = mcidev_store
+};
+
+#define MCIDEV_ATTR(_name,_mode,_show,_store) \
+struct mcidev_attribute mci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* Control file */
+MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
+
+/* Attribute files */
+MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
+MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
+MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
+MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
+MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
+MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
+MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
+MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
+MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
+MCIDEV_ATTR(edac_current_capability,S_IRUGO,
+ mci_edac_current_capability_show,NULL);
+MCIDEV_ATTR(supported_mem_type,S_IRUGO,
+ mci_supported_mem_type_show,NULL);
+
+
+static struct mcidev_attribute *mci_attr[] = {
+ &mci_attr_reset_counters,
+ &mci_attr_module_name,
+ &mci_attr_mc_name,
+ &mci_attr_edac_capability,
+ &mci_attr_edac_current_capability,
+ &mci_attr_supported_mem_type,
+ &mci_attr_size_mb,
+ &mci_attr_seconds_since_reset,
+ &mci_attr_ue_noinfo_count,
+ &mci_attr_ce_noinfo_count,
+ &mci_attr_ue_count,
+ &mci_attr_ce_count,
+ NULL
+};
+
+
+/*
+ * Release of a MC controlling instance
+ */
+static void edac_mci_instance_release(struct kobject *kobj)
+{
+ struct mem_ctl_info *mci;
+ mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
+
+ debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n",
+ __func__, mci->mc_idx);
+
+ kfree(mci);
+}
+
+static struct kobj_type ktype_mci = {
+ .release = edac_mci_instance_release,
+ .sysfs_ops = &mci_ops,
+ .default_attrs = (struct attribute **) mci_attr,
+};
+
+#define EDAC_DEVICE_SYMLINK "device"
+
+/*
+ * Create a new Memory Controller kobject instance,
+ * mc<id> under the 'mc' directory
+ *
+ * Return:
+ * 0 Success
+ * !0 Failure
+ */
+static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+ int i;
+ int err;
+ struct csrow_info *csrow;
+ struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
+
+ debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx);
+
+ memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
+ kobject_init(edac_mci_kobj);
+
+ /* set the name of the mc<id> object */
+ err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
+ if (err)
+ return err;
+
+ /* link to our parent the '..../edac/mc' object */
+ edac_mci_kobj->parent = &edac_memctrl_kobj;
+ edac_mci_kobj->ktype = &ktype_mci;
+
+ /* register the mc<id> kobject */
+ err = kobject_register(edac_mci_kobj);
+ if (err)
+ return err;
+
+ /* create a symlink for the device */
+ err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
+ EDAC_DEVICE_SYMLINK);
+ if (err) {
+ kobject_unregister(edac_mci_kobj);
+ return err;
+ }
+
+ /* Make directories for each CSROW object
+ * under the mc<id> kobject
+ */
+ for (i = 0; i < mci->nr_csrows; i++) {
+
+ csrow = &mci->csrows[i];
+
+ /* Only expose populated CSROWs */
+ if (csrow->nr_pages > 0) {
+ err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
+ if (err)
+ goto fail;
+ }
+ }
+
+ /* Mark this MCI instance as having sysfs entries */
+ mci->sysfs_active = MCI_SYSFS_ACTIVE;
+
+ return 0;
+
+
+ /* CSROW error: backout what has already been registered, */
+fail:
+ for ( i--; i >= 0; i--) {
+ if (csrow->nr_pages > 0) {
+ kobject_unregister(&mci->csrows[i].kobj);
+ kobject_put(&mci->csrows[i].kobj);
+ }
+ }
+
+ kobject_unregister(edac_mci_kobj);
+ kobject_put(edac_mci_kobj);
+
+ return err;
+}
+
+/*
+ * remove a Memory Controller instance
+ */
+static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+ int i;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* remove all csrow kobjects */
+ for (i = 0; i < mci->nr_csrows; i++) {
+ if (mci->csrows[i].nr_pages > 0) {
+ kobject_unregister(&mci->csrows[i].kobj);
+ kobject_put(&mci->csrows[i].kobj);
+ }
+ }
+
+ sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
+
+ kobject_unregister(&mci->edac_mci_kobj);
+ kobject_put(&mci->edac_mci_kobj);
+}
+
+/* END OF sysfs data and methods */
+
+#ifdef CONFIG_EDAC_DEBUG
+
+EXPORT_SYMBOL(edac_mc_dump_channel);
+
+void edac_mc_dump_channel(struct channel_info *chan)
+{
+ debugf4("\tchannel = %p\n", chan);
+ debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
+ debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
+ debugf4("\tchannel->label = '%s'\n", chan->label);
+ debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_csrow);
+
+void edac_mc_dump_csrow(struct csrow_info *csrow)
+{
+ debugf4("\tcsrow = %p\n", csrow);
+ debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);
+ debugf4("\tcsrow->first_page = 0x%lx\n",
+ csrow->first_page);
+ debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page);
+ debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask);
+ debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages);
+ debugf4("\tcsrow->nr_channels = %d\n",
+ csrow->nr_channels);
+ debugf4("\tcsrow->channels = %p\n", csrow->channels);
+ debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_mci);
+
+void edac_mc_dump_mci(struct mem_ctl_info *mci)
+{
+ debugf3("\tmci = %p\n", mci);
+ debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap);
+ debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap);
+ debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap);
+ debugf4("\tmci->edac_check = %p\n", mci->edac_check);
+ debugf3("\tmci->nr_csrows = %d, csrows = %p\n",
+ mci->nr_csrows, mci->csrows);
+ debugf3("\tpdev = %p\n", mci->pdev);
+ debugf3("\tmod_name:ctl_name = %s:%s\n",
+ mci->mod_name, mci->ctl_name);
+ debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
+}
+
+
+#endif /* CONFIG_EDAC_DEBUG */
+
+/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
+ * Adjust 'ptr' so that its alignment is at least as stringent as what the
+ * compiler would provide for X and return the aligned result.
+ *
+ * If 'size' is a constant, the compiler will optimize this whole function
+ * down to either a no-op or the addition of a constant to the value of 'ptr'.
+ */
+static inline char * align_ptr (void *ptr, unsigned size)
+{
+ unsigned align, r;
+
+ /* Here we assume that the alignment of a "long long" is the most
+ * stringent alignment that the compiler will ever provide by default.
+ * As far as I know, this is a reasonable assumption.
+ */
+ if (size > sizeof(long))
+ align = sizeof(long long);
+ else if (size > sizeof(int))
+ align = sizeof(long);
+ else if (size > sizeof(short))
+ align = sizeof(int);
+ else if (size > sizeof(char))
+ align = sizeof(short);
+ else
+ return (char *) ptr;
+
+ r = size % align;
+
+ if (r == 0)
+ return (char *) ptr;
+
+ return (char *) (((unsigned long) ptr) + align - r);
+}
+
+
+EXPORT_SYMBOL(edac_mc_alloc);
+
+/**
+ * edac_mc_alloc: Allocate a struct mem_ctl_info structure
+ * @size_pvt: size of private storage needed
+ * @nr_csrows: Number of CWROWS needed for this MC
+ * @nr_chans: Number of channels for the MC
+ *
+ * Everything is kmalloc'ed as one big chunk - more efficient.
+ * Only can be used if all structures have the same lifetime - otherwise
+ * you have to allocate and initialize your own structures.
+ *
+ * Use edac_mc_free() to free mc structures allocated by this function.
+ *
+ * Returns:
+ * NULL allocation failed
+ * struct mem_ctl_info pointer
+ */
+struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
+ unsigned nr_chans)
+{
+ struct mem_ctl_info *mci;
+ struct csrow_info *csi, *csrow;
+ struct channel_info *chi, *chp, *chan;
+ void *pvt;
+ unsigned size;
+ int row, chn;
+
+ /* Figure out the offsets of the various items from the start of an mc
+ * structure. We want the alignment of each item to be at least as
+ * stringent as what the compiler would provide if we could simply
+ * hardcode everything into a single struct.
+ */
+ mci = (struct mem_ctl_info *) 0;
+ csi = (struct csrow_info *)align_ptr(&mci[1], sizeof(*csi));
+ chi = (struct channel_info *)
+ align_ptr(&csi[nr_csrows], sizeof(*chi));
+ pvt = align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
+ size = ((unsigned long) pvt) + sz_pvt;
+
+ if ((mci = kmalloc(size, GFP_KERNEL)) == NULL)
+ return NULL;
+
+ /* Adjust pointers so they point within the memory we just allocated
+ * rather than an imaginary chunk of memory located at address 0.
+ */
+ csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi));
+ chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
+ pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
+
+ memset(mci, 0, size); /* clear all fields */
+
+ mci->csrows = csi;
+ mci->pvt_info = pvt;
+ mci->nr_csrows = nr_csrows;
+
+ for (row = 0; row < nr_csrows; row++) {
+ csrow = &csi[row];
+ csrow->csrow_idx = row;
+ csrow->mci = mci;
+ csrow->nr_channels = nr_chans;
+ chp = &chi[row * nr_chans];
+ csrow->channels = chp;
+
+ for (chn = 0; chn < nr_chans; chn++) {
+ chan = &chp[chn];
+ chan->chan_idx = chn;
+ chan->csrow = csrow;
+ }
+ }
+
+ return mci;
+}
+
+
+EXPORT_SYMBOL(edac_mc_free);
+
+/**
+ * edac_mc_free: Free a previously allocated 'mci' structure
+ * @mci: pointer to a struct mem_ctl_info structure
+ *
+ * Free up a previously allocated mci structure
+ * A MCI structure can be in 2 states after being allocated
+ * by edac_mc_alloc().
+ * 1) Allocated in a MC driver's probe, but not yet committed
+ * 2) Allocated and committed, by a call to edac_mc_add_mc()
+ * edac_mc_add_mc() is the function that adds the sysfs entries
+ * thus, this free function must determine which state the 'mci'
+ * structure is in, then either free it directly or
+ * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
+ *
+ * VOID Return
+ */
+void edac_mc_free(struct mem_ctl_info *mci)
+{
+ /* only if sysfs entries for this mci instance exist
+ * do we remove them and defer the actual kfree via
+ * the kobject 'release()' callback.
+ *
+ * Otherwise, do a straight kfree now.
+ */
+ if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
+ edac_remove_sysfs_mci_device(mci);
+ else
+ kfree(mci);
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
+
+struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct list_head *item;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ list_for_each(item, &mc_devices) {
+ mci = list_entry(item, struct mem_ctl_info, link);
+
+ if (mci->pdev == pdev)
+ return mci;
+ }
+
+ return NULL;
+}
+
+static int add_mc_to_global_list (struct mem_ctl_info *mci)
+{
+ struct list_head *item, *insert_before;
+ struct mem_ctl_info *p;
+ int i;
+
+ if (list_empty(&mc_devices)) {
+ mci->mc_idx = 0;
+ insert_before = &mc_devices;
+ } else {
+ if (edac_mc_find_mci_by_pdev(mci->pdev)) {
+ printk(KERN_WARNING
+ "EDAC MC: %s (%s) %s %s already assigned %d\n",
+ mci->pdev->dev.bus_id, pci_name(mci->pdev),
+ mci->mod_name, mci->ctl_name, mci->mc_idx);
+ return 1;
+ }
+
+ insert_before = NULL;
+ i = 0;
+
+ list_for_each(item, &mc_devices) {
+ p = list_entry(item, struct mem_ctl_info, link);
+
+ if (p->mc_idx != i) {
+ insert_before = item;
+ break;
+ }
+
+ i++;
+ }
+
+ mci->mc_idx = i;
+
+ if (insert_before == NULL)
+ insert_before = &mc_devices;
+ }
+
+ list_add_tail_rcu(&mci->link, insert_before);
+ return 0;
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_add_mc);
+
+/**
+ * edac_mc_add_mc: Insert the 'mci' structure into the mci global list
+ * @mci: pointer to the mci structure to be added to the list
+ *
+ * Return:
+ * 0 Success
+ * !0 Failure
+ */
+
+/* FIXME - should a warning be printed if no error detection? correction? */
+int edac_mc_add_mc(struct mem_ctl_info *mci)
+{
+ int rc = 1;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+#ifdef CONFIG_EDAC_DEBUG
+ if (edac_debug_level >= 3)
+ edac_mc_dump_mci(mci);
+ if (edac_debug_level >= 4) {
+ int i;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ int j;
+ edac_mc_dump_csrow(&mci->csrows[i]);
+ for (j = 0; j < mci->csrows[i].nr_channels; j++)
+ edac_mc_dump_channel(&mci->csrows[i].
+ channels[j]);
+ }
+ }
+#endif
+ down(&mem_ctls_mutex);
+
+ if (add_mc_to_global_list(mci))
+ goto finish;
+
+ /* set load time so that error rate can be tracked */
+ mci->start_time = jiffies;
+
+ if (edac_create_sysfs_mci_device(mci)) {
+ printk(KERN_WARNING
+ "EDAC MC%d: failed to create sysfs device\n",
+ mci->mc_idx);
+ /* FIXME - should there be an error code and unwind? */
+ goto finish;
+ }
+
+ /* Report action taken */
+ printk(KERN_INFO
+ "EDAC MC%d: Giving out device to %s %s: PCI %s\n",
+ mci->mc_idx, mci->mod_name, mci->ctl_name,
+ pci_name(mci->pdev));
+
+
+ rc = 0;
+
+finish:
+ up(&mem_ctls_mutex);
+ return rc;
+}
+
+
+
+static void complete_mc_list_del (struct rcu_head *head)
+{
+ struct mem_ctl_info *mci;
+
+ mci = container_of(head, struct mem_ctl_info, rcu);
+ INIT_LIST_HEAD(&mci->link);
+ complete(&mci->complete);
+}
+
+static void del_mc_from_global_list (struct mem_ctl_info *mci)
+{
+ list_del_rcu(&mci->link);
+ init_completion(&mci->complete);
+ call_rcu(&mci->rcu, complete_mc_list_del);
+ wait_for_completion(&mci->complete);
+}
+
+EXPORT_SYMBOL(edac_mc_del_mc);
+
+/**
+ * edac_mc_del_mc: Remove the specified mci structure from global list
+ * @mci: Pointer to struct mem_ctl_info structure
+ *
+ * Returns:
+ * 0 Success
+ * 1 Failure
+ */
+int edac_mc_del_mc(struct mem_ctl_info *mci)
+{
+ int rc = 1;
+
+ debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ down(&mem_ctls_mutex);
+ del_mc_from_global_list(mci);
+ printk(KERN_INFO
+ "EDAC MC%d: Removed device %d for %s %s: PCI %s\n",
+ mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name,
+ pci_name(mci->pdev));
+ rc = 0;
+ up(&mem_ctls_mutex);
+
+ return rc;
+}
+
+
+EXPORT_SYMBOL(edac_mc_scrub_block);
+
+void edac_mc_scrub_block(unsigned long page, unsigned long offset,
+ u32 size)
+{
+ struct page *pg;
+ void *virt_addr;
+ unsigned long flags = 0;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* ECC error page was not in our memory. Ignore it. */
+ if(!pfn_valid(page))
+ return;
+
+ /* Find the actual page structure then map it and fix */
+ pg = pfn_to_page(page);
+
+ if (PageHighMem(pg))
+ local_irq_save(flags);
+
+ virt_addr = kmap_atomic(pg, KM_BOUNCE_READ);
+
+ /* Perform architecture specific atomic scrub operation */
+ atomic_scrub(virt_addr + offset, size);
+
+ /* Unmap and complete */
+ kunmap_atomic(virt_addr, KM_BOUNCE_READ);
+
+ if (PageHighMem(pg))
+ local_irq_restore(flags);
+}
+
+
+/* FIXME - should return -1 */
+EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
+
+int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+ unsigned long page)
+{
+ struct csrow_info *csrows = mci->csrows;
+ int row, i;
+
+ debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__,
+ page);
+ row = -1;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ struct csrow_info *csrow = &csrows[i];
+
+ if (csrow->nr_pages == 0)
+ continue;
+
+ debugf3("MC%d: " __FILE__
+ ": %s(): first(0x%lx) page(0x%lx)"
+ " last(0x%lx) mask(0x%lx)\n", mci->mc_idx,
+ __func__, csrow->first_page, page,
+ csrow->last_page, csrow->page_mask);
+
+ if ((page >= csrow->first_page) &&
+ (page <= csrow->last_page) &&
+ ((page & csrow->page_mask) ==
+ (csrow->first_page & csrow->page_mask))) {
+ row = i;
+ break;
+ }
+ }
+
+ if (row == -1)
+ printk(KERN_ERR
+ "EDAC MC%d: could not look up page error address %lx\n",
+ mci->mc_idx, (unsigned long) page);
+
+ return row;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce);
+
+/* FIXME - setable log (warning/emerg) levels */
+/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
+void edac_mc_handle_ce(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ unsigned long syndrome, int row, int channel,
+ const char *msg)
+{
+ unsigned long remapped_page;
+
+ debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+ /* FIXME - maybe make panic on INTERNAL ERROR an option */
+ if (row >= mci->nr_csrows || row < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+ mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+ if (channel >= mci->csrows[row].nr_channels || channel < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: channel out of range "
+ "(%d >= %d)\n",
+ mci->mc_idx, channel, mci->csrows[row].nr_channels);
+ edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+
+ if (log_ce)
+ /* FIXME - put in DIMM location */
+ printk(KERN_WARNING
+ "EDAC MC%d: CE page 0x%lx, offset 0x%lx,"
+ " grain %d, syndrome 0x%lx, row %d, channel %d,"
+ " label \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, syndrome, row, channel,
+ mci->csrows[row].channels[channel].label, msg);
+
+ mci->ce_count++;
+ mci->csrows[row].ce_count++;
+ mci->csrows[row].channels[channel].ce_count++;
+
+ if (mci->scrub_mode & SCRUB_SW_SRC) {
+ /*
+ * Some MC's can remap memory so that it is still available
+ * at a different address when PCI devices map into memory.
+ * MC's that can't do this lose the memory where PCI devices
+ * are mapped. This mapping is MC dependant and so we call
+ * back into the MC driver for it to map the MC page to
+ * a physical (CPU) page which can then be mapped to a virtual
+ * page - which can then be scrubbed.
+ */
+ remapped_page = mci->ctl_page_to_phys ?
+ mci->ctl_page_to_phys(mci, page_frame_number) :
+ page_frame_number;
+
+ edac_mc_scrub_block(remapped_page, offset_in_page,
+ mci->csrows[row].grain);
+ }
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
+
+void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+ const char *msg)
+{
+ if (log_ce)
+ printk(KERN_WARNING
+ "EDAC MC%d: CE - no information available: %s\n",
+ mci->mc_idx, msg);
+ mci->ce_noinfo_count++;
+ mci->ce_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue);
+
+void edac_mc_handle_ue(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page, int row,
+ const char *msg)
+{
+ int len = EDAC_MC_LABEL_LEN * 4;
+ char labels[len + 1];
+ char *pos = labels;
+ int chan;
+ int chars;
+
+ debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+ /* FIXME - maybe make panic on INTERNAL ERROR an option */
+ if (row >= mci->nr_csrows || row < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+ mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+
+ chars = snprintf(pos, len + 1, "%s",
+ mci->csrows[row].channels[0].label);
+ len -= chars;
+ pos += chars;
+ for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
+ chan++) {
+ chars = snprintf(pos, len + 1, ":%s",
+ mci->csrows[row].channels[chan].label);
+ len -= chars;
+ pos += chars;
+ }
+
+ if (log_ue)
+ printk(KERN_EMERG
+ "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+ " labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
+
+ if (panic_on_ue)
+ panic
+ ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+ " labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
+
+ mci->ue_count++;
+ mci->csrows[row].ue_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
+
+void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+ const char *msg)
+{
+ if (panic_on_ue)
+ panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
+
+ if (log_ue)
+ printk(KERN_WARNING
+ "EDAC MC%d: UE - no information available: %s\n",
+ mci->mc_idx, msg);
+ mci->ue_noinfo_count++;
+ mci->ue_count++;
+}
+
+
+#ifdef CONFIG_PCI
+
+static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
+{
+ int where;
+ u16 status;
+
+ where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
+ pci_read_config_word(dev, where, &status);
+
+ /* If we get back 0xFFFF then we must suspect that the card has been pulled but
+ the Linux PCI layer has not yet finished cleaning up. We don't want to report
+ on such devices */
+
+ if (status == 0xFFFF) {
+ u32 sanity;
+ pci_read_config_dword(dev, 0, &sanity);
+ if (sanity == 0xFFFFFFFF)
+ return 0;
+ }
+ status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
+ PCI_STATUS_PARITY;
+
+ if (status)
+ /* reset only the bits we are interested in */
+ pci_write_config_word(dev, where, status);
+
+ return status;
+}
+
+typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
+
+/* Clear any PCI parity errors logged by this device. */
+static void edac_pci_dev_parity_clear( struct pci_dev *dev )
+{
+ u8 header_type;
+
+ get_pci_parity_status(dev, 0);
+
+ /* read the device TYPE, looking for bridges */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
+ get_pci_parity_status(dev, 1);
+}
+
+/*
+ * PCI Parity polling
+ *
+ */
+static void edac_pci_dev_parity_test(struct pci_dev *dev)
+{
+ u16 status;
+ u8 header_type;
+
+ /* read the STATUS register on this device
+ */
+ status = get_pci_parity_status(dev, 0);
+
+ debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );
+
+ /* check the status reg for errors */
+ if (status) {
+ if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Signaled System Error on %s\n",
+ pci_name (dev));
+
+ if (status & (PCI_STATUS_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Master Data Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Detected Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+ }
+
+ /* read the device TYPE, looking for bridges */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+ debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* On bridges, need to examine secondary status register */
+ status = get_pci_parity_status(dev, 1);
+
+ debugf2("PCI SEC_STATUS= 0x%04x %s\n",
+ status, dev->dev.bus_id );
+
+ /* check the secondary status reg for errors */
+ if (status) {
+ if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Signaled System Error on %s\n",
+ pci_name (dev));
+
+ if (status & (PCI_STATUS_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Master Data Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Detected Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+ }
+ }
+}
+
+/*
+ * check_dev_on_list: Scan for a PCI device on a white/black list
+ * @list: an EDAC &edac_pci_device_list white/black list pointer
+ * @free_index: index of next free entry on the list
+ * @pci_dev: PCI Device pointer
+ *
+ * see if list contains the device.
+ *
+ * Returns: 0 not found
+ * 1 found on list
+ */
+static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
+ struct pci_dev *dev)
+{
+ int i;
+ int rc = 0; /* Assume not found */
+ unsigned short vendor=dev->vendor;
+ unsigned short device=dev->device;
+
+ /* Scan the list, looking for a vendor/device match
+ */
+ for (i = 0; i < free_index; i++, list++ ) {
+ if ( (list->vendor == vendor ) &&
+ (list->device == device )) {
+ rc = 1;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * pci_dev parity list iterator
+ * Scan the PCI device list for one iteration, looking for SERRORs
+ * Master Parity ERRORS or Parity ERRORs on primary or secondary devices
+ */
+static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
+{
+ struct pci_dev *dev=NULL;
+
+ /* request for kernel access to the next PCI device, if any,
+ * and while we are looking at it have its reference count
+ * bumped until we are done with it
+ */
+ while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+
+ /* if whitelist exists then it has priority, so only scan those
+ * devices on the whitelist
+ */
+ if (pci_whitelist_count > 0 ) {
+ if (check_dev_on_list(pci_whitelist,
+ pci_whitelist_count, dev))
+ fn(dev);
+ } else {
+ /*
+ * if no whitelist, then check if this devices is
+ * blacklisted
+ */
+ if (!check_dev_on_list(pci_blacklist,
+ pci_blacklist_count, dev))
+ fn(dev);
+ }
+ }
+}
+
+static void do_pci_parity_check(void)
+{
+ unsigned long flags;
+ int before_count;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (!check_pci_parity)
+ return;
+
+ before_count = atomic_read(&pci_parity_count);
+
+ /* scan all PCI devices looking for a Parity Error on devices and
+ * bridges
+ */
+ local_irq_save(flags);
+ edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
+ local_irq_restore(flags);
+
+ /* Only if operator has selected panic on PCI Error */
+ if (panic_on_pci_parity) {
+ /* If the count is different 'after' from 'before' */
+ if (before_count != atomic_read(&pci_parity_count))
+ panic("EDAC: PCI Parity Error");
+ }
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+ /* Clear any PCI bus parity errors that devices initially have logged
+ * in their registers.
+ */
+ edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
+}
+
+
+#else /* CONFIG_PCI */
+
+
+static inline void do_pci_parity_check(void)
+{
+ /* no-op */
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+ /* no-op */
+}
+
+
+#endif /* CONFIG_PCI */
+
+/*
+ * Iterate over all MC instances and check for ECC, et al, errors
+ */
+static inline void check_mc_devices (void)
+{
+ unsigned long flags;
+ struct list_head *item;
+ struct mem_ctl_info *mci;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* during poll, have interrupts off */
+ local_irq_save(flags);
+
+ list_for_each(item, &mc_devices) {
+ mci = list_entry(item, struct mem_ctl_info, link);
+
+ if (mci->edac_check != NULL)
+ mci->edac_check(mci);
+ }
+
+ local_irq_restore(flags);
+}
+
+
+/*
+ * Check MC status every poll_msec.
+ * Check PCI status every poll_msec as well.
+ *
+ * This where the work gets done for edac.
+ *
+ * SMP safe, doesn't use NMI, and auto-rate-limits.
+ */
+static void do_edac_check(void)
+{
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ check_mc_devices();
+
+ do_pci_parity_check();
+}
+
+
+/*
+ * EDAC thread state information
+ */
+struct bs_thread_info
+{
+ struct task_struct *task;
+ struct completion *event;
+ char *name;
+ void (*run)(void);
+};
+
+static struct bs_thread_info bs_thread;
+
+/*
+ * edac_kernel_thread
+ * This the kernel thread that processes edac operations
+ * in a normal thread environment
+ */
+static int edac_kernel_thread(void *arg)
+{
+ struct bs_thread_info *thread = (struct bs_thread_info *) arg;
+
+ /* detach thread */
+ daemonize(thread->name);
+
+ current->exit_signal = SIGCHLD;
+ allow_signal(SIGKILL);
+ thread->task = current;
+
+ /* indicate to starting task we have started */
+ complete(thread->event);
+
+ /* loop forever, until we are told to stop */
+ while(thread->run != NULL) {
+ void (*run)(void);
+
+ /* call the function to check the memory controllers */
+ run = thread->run;
+ if (run)
+ run();
+
+ if (signal_pending(current))
+ flush_signals(current);
+
+ /* ensure we are interruptable */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* goto sleep for the interval */
+ schedule_timeout((HZ * poll_msec) / 1000);
+ try_to_freeze();
+ }
+
+ /* notify waiter that we are exiting */
+ complete(thread->event);
+
+ return 0;
+}
+
+/*
+ * edac_mc_init
+ * module initialization entry point
+ */
+static int __init edac_mc_init(void)
+{
+ int ret;
+ struct completion event;
+
+ printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n");
+
+ /*
+ * Harvest and clear any boot/initialization PCI parity errors
+ *
+ * FIXME: This only clears errors logged by devices present at time of
+ * module initialization. We should also do an initial clear
+ * of each newly hotplugged device.
+ */
+ clear_pci_parity_errors();
+
+ /* perform check for first time to harvest boot leftovers */
+ do_edac_check();
+
+ /* Create the MC sysfs entires */
+ if (edac_sysfs_memctrl_setup()) {
+ printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n");
+ return -ENODEV;
+ }
+
+ /* Create the PCI parity sysfs entries */
+ if (edac_sysfs_pci_setup()) {
+ edac_sysfs_memctrl_teardown();
+ printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n");
+ return -ENODEV;
+ }
+
+ /* Create our kernel thread */
+ init_completion(&event);
+ bs_thread.event = &event;
+ bs_thread.name = "kedac";
+ bs_thread.run = do_edac_check;
+
+ /* create our kernel thread */
+ ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL);
+ if (ret < 0) {
+ /* remove the sysfs entries */
+ edac_sysfs_memctrl_teardown();
+ edac_sysfs_pci_teardown();
+ return -ENOMEM;
+ }
+
+ /* wait for our kernel theard ack that it is up and running */
+ wait_for_completion(&event);
+
+ return 0;
+}
+
+
+/*
+ * edac_mc_exit()
+ * module exit/termination functioni
+ */
+static void __exit edac_mc_exit(void)
+{
+ struct completion event;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ init_completion(&event);
+ bs_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
+ */
+ read_lock(&tasklist_lock);
+ bs_thread.run = NULL;
+ send_sig(SIGKILL, bs_thread.task, 1);
+ read_unlock(&tasklist_lock);
+ wait_for_completion(&event);
+
+ /* tear down the sysfs device */
+ edac_sysfs_memctrl_teardown();
+ edac_sysfs_pci_teardown();
+}
+
+
+
+
+module_init(edac_mc_init);
+module_exit(edac_mc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+ "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("Core library routines for MC reporting");
+
+module_param(panic_on_ue, int, 0644);
+MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
+module_param(check_pci_parity, int, 0644);
+MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on");
+module_param(panic_on_pci_parity, int, 0644);
+MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on");
+module_param(log_ue, int, 0644);
+MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on");
+module_param(log_ce, int, 0644);
+MODULE_PARM_DESC(log_ce, "Log correctable error to console: 0=off 1=on");
+module_param(poll_msec, int, 0644);
+MODULE_PARM_DESC(poll_msec, "Polling period in milliseconds");
+#ifdef CONFIG_EDAC_DEBUG
+module_param(edac_debug_level, int, 0644);
+MODULE_PARM_DESC(edac_debug_level, "Debug level");
+#endif
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
new file mode 100644
index 000000000000..75ecf484a43a
--- /dev/null
+++ b/drivers/edac/edac_mc.h
@@ -0,0 +1,448 @@
+/*
+ * MC kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ * Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * $Id: edac_mc.h,v 1.4.2.10 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#ifndef _EDAC_MC_H_
+#define _EDAC_MC_H_
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/nmi.h>
+#include <linux/rcupdate.h>
+#include <linux/completion.h>
+#include <linux/kobject.h>
+
+
+#define EDAC_MC_LABEL_LEN 31
+#define MC_PROC_NAME_MAX_LEN 7
+
+#if PAGE_SHIFT < 20
+#define PAGES_TO_MiB( pages ) ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
+#else /* PAGE_SHIFT > 20 */
+#define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#endif
+
+#ifdef CONFIG_EDAC_DEBUG
+extern int edac_debug_level;
+#define edac_debug_printk(level, fmt, args...) \
+do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0)
+#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ )
+#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ )
+#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
+#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
+#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
+#else /* !CONFIG_EDAC_DEBUG */
+#define debugf0( ... )
+#define debugf1( ... )
+#define debugf2( ... )
+#define debugf3( ... )
+#define debugf4( ... )
+#endif /* !CONFIG_EDAC_DEBUG */
+
+
+#define bs_xstr(s) bs_str(s)
+#define bs_str(s) #s
+#define BS_MOD_STR bs_xstr(KBUILD_BASENAME)
+
+#define BIT(x) (1 << (x))
+
+#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev
+
+/* memory devices */
+enum dev_type {
+ DEV_UNKNOWN = 0,
+ DEV_X1,
+ DEV_X2,
+ DEV_X4,
+ DEV_X8,
+ DEV_X16,
+ DEV_X32, /* Do these parts exist? */
+ DEV_X64 /* Do these parts exist? */
+};
+
+#define DEV_FLAG_UNKNOWN BIT(DEV_UNKNOWN)
+#define DEV_FLAG_X1 BIT(DEV_X1)
+#define DEV_FLAG_X2 BIT(DEV_X2)
+#define DEV_FLAG_X4 BIT(DEV_X4)
+#define DEV_FLAG_X8 BIT(DEV_X8)
+#define DEV_FLAG_X16 BIT(DEV_X16)
+#define DEV_FLAG_X32 BIT(DEV_X32)
+#define DEV_FLAG_X64 BIT(DEV_X64)
+
+/* memory types */
+enum mem_type {
+ MEM_EMPTY = 0, /* Empty csrow */
+ MEM_RESERVED, /* Reserved csrow type */
+ MEM_UNKNOWN, /* Unknown csrow type */
+ MEM_FPM, /* Fast page mode */
+ MEM_EDO, /* Extended data out */
+ MEM_BEDO, /* Burst Extended data out */
+ MEM_SDR, /* Single data rate SDRAM */
+ MEM_RDR, /* Registered single data rate SDRAM */
+ MEM_DDR, /* Double data rate SDRAM */
+ MEM_RDDR, /* Registered Double data rate SDRAM */
+ MEM_RMBS /* Rambus DRAM */
+};
+
+#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
+#define MEM_FLAG_RESERVED BIT(MEM_RESERVED)
+#define MEM_FLAG_UNKNOWN BIT(MEM_UNKNOWN)
+#define MEM_FLAG_FPM BIT(MEM_FPM)
+#define MEM_FLAG_EDO BIT(MEM_EDO)
+#define MEM_FLAG_BEDO BIT(MEM_BEDO)
+#define MEM_FLAG_SDR BIT(MEM_SDR)
+#define MEM_FLAG_RDR BIT(MEM_RDR)
+#define MEM_FLAG_DDR BIT(MEM_DDR)
+#define MEM_FLAG_RDDR BIT(MEM_RDDR)
+#define MEM_FLAG_RMBS BIT(MEM_RMBS)
+
+
+/* chipset Error Detection and Correction capabilities and mode */
+enum edac_type {
+ EDAC_UNKNOWN = 0, /* Unknown if ECC is available */
+ EDAC_NONE, /* Doesnt support ECC */
+ EDAC_RESERVED, /* Reserved ECC type */
+ EDAC_PARITY, /* Detects parity errors */
+ EDAC_EC, /* Error Checking - no correction */
+ EDAC_SECDED, /* Single bit error correction, Double detection */
+ EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */
+ EDAC_S4ECD4ED, /* Chipkill x4 devices */
+ EDAC_S8ECD8ED, /* Chipkill x8 devices */
+ EDAC_S16ECD16ED, /* Chipkill x16 devices */
+};
+
+#define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN)
+#define EDAC_FLAG_NONE BIT(EDAC_NONE)
+#define EDAC_FLAG_PARITY BIT(EDAC_PARITY)
+#define EDAC_FLAG_EC BIT(EDAC_EC)
+#define EDAC_FLAG_SECDED BIT(EDAC_SECDED)
+#define EDAC_FLAG_S2ECD2ED BIT(EDAC_S2ECD2ED)
+#define EDAC_FLAG_S4ECD4ED BIT(EDAC_S4ECD4ED)
+#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED)
+#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED)
+
+
+/* scrubbing capabilities */
+enum scrub_type {
+ SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */
+ SCRUB_NONE, /* No scrubber */
+ SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */
+ SCRUB_SW_SRC, /* Software scrub only errors */
+ SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */
+ SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */
+ SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */
+ SCRUB_HW_SRC, /* Hardware scrub only errors */
+ SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */
+ SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */
+};
+
+#define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG)
+#define SCRUB_FLAG_SW_SRC BIT(SCRUB_SW_SRC_CORR)
+#define SCRUB_FLAG_SW_PROG_SRC BIT(SCRUB_SW_PROG_SRC_CORR)
+#define SCRUB_FLAG_SW_TUN BIT(SCRUB_SW_SCRUB_TUNABLE)
+#define SCRUB_FLAG_HW_PROG BIT(SCRUB_HW_PROG)
+#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC_CORR)
+#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR)
+#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
+
+enum mci_sysfs_status {
+ MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */
+ MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */
+};
+
+/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
+
+/*
+ * There are several things to be aware of that aren't at all obvious:
+ *
+ *
+ * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
+ *
+ * These are some of the many terms that are thrown about that don't always
+ * mean what people think they mean (Inconceivable!). In the interest of
+ * creating a common ground for discussion, terms and their definitions
+ * will be established.
+ *
+ * Memory devices: The individual chip on a memory stick. These devices
+ * commonly output 4 and 8 bits each. Grouping several
+ * of these in parallel provides 64 bits which is common
+ * for a memory stick.
+ *
+ * Memory Stick: A printed circuit board that agregates multiple
+ * memory devices in parallel. This is the atomic
+ * memory component that is purchaseable by Joe consumer
+ * and loaded into a memory socket.
+ *
+ * Socket: A physical connector on the motherboard that accepts
+ * a single memory stick.
+ *
+ * Channel: Set of memory devices on a memory stick that must be
+ * grouped in parallel with one or more additional
+ * channels from other memory sticks. This parallel
+ * grouping of the output from multiple channels are
+ * necessary for the smallest granularity of memory access.
+ * Some memory controllers are capable of single channel -
+ * which means that memory sticks can be loaded
+ * individually. Other memory controllers are only
+ * capable of dual channel - which means that memory
+ * sticks must be loaded as pairs (see "socket set").
+ *
+ * Chip-select row: All of the memory devices that are selected together.
+ * for a single, minimum grain of memory access.
+ * This selects all of the parallel memory devices across
+ * all of the parallel channels. Common chip-select rows
+ * for single channel are 64 bits, for dual channel 128
+ * bits.
+ *
+ * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memmory.
+ * Motherboards commonly drive two chip-select pins to
+ * a memory stick. A single-ranked stick, will occupy
+ * only one of those rows. The other will be unused.
+ *
+ * Double-Ranked stick: A double-ranked stick has two chip-select rows which
+ * access different sets of memory devices. The two
+ * rows cannot be accessed concurrently.
+ *
+ * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick.
+ * A double-sided stick has two chip-select rows which
+ * access different sets of memory devices. The two
+ * rows cannot be accessed concurrently. "Double-sided"
+ * is irrespective of the memory devices being mounted
+ * on both sides of the memory stick.
+ *
+ * Socket set: All of the memory sticks that are required for for
+ * a single memory access or all of the memory sticks
+ * spanned by a chip-select row. A single socket set
+ * has two chip-select rows and if double-sided sticks
+ * are used these will occupy those chip-select rows.
+ *
+ * Bank: This term is avoided because it is unclear when
+ * needing to distinguish between chip-select rows and
+ * socket sets.
+ *
+ * Controller pages:
+ *
+ * Physical pages:
+ *
+ * Virtual pages:
+ *
+ *
+ * STRUCTURE ORGANIZATION AND CHOICES
+ *
+ *
+ *
+ * PS - I enjoyed writing all that about as much as you enjoyed reading it.
+ */
+
+
+struct channel_info {
+ int chan_idx; /* channel index */
+ u32 ce_count; /* Correctable Errors for this CHANNEL */
+ char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
+ struct csrow_info *csrow; /* the parent */
+};
+
+
+struct csrow_info {
+ unsigned long first_page; /* first page number in dimm */
+ unsigned long last_page; /* last page number in dimm */
+ unsigned long page_mask; /* used for interleaving -
+ 0UL for non intlv */
+ u32 nr_pages; /* number of pages in csrow */
+ u32 grain; /* granularity of reported error in bytes */
+ int csrow_idx; /* the chip-select row */
+ enum dev_type dtype; /* memory device type */
+ u32 ue_count; /* Uncorrectable Errors for this csrow */
+ u32 ce_count; /* Correctable Errors for this csrow */
+ enum mem_type mtype; /* memory csrow type */
+ enum edac_type edac_mode; /* EDAC mode for this csrow */
+ struct mem_ctl_info *mci; /* the parent */
+
+ struct kobject kobj; /* sysfs kobject for this csrow */
+
+ /* FIXME the number of CHANNELs might need to become dynamic */
+ u32 nr_channels;
+ struct channel_info *channels;
+};
+
+
+struct mem_ctl_info {
+ struct list_head link; /* for global list of mem_ctl_info structs */
+ unsigned long mtype_cap; /* memory types supported by mc */
+ unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */
+ unsigned long edac_cap; /* configuration capabilities - this is
+ closely related to edac_ctl_cap. The
+ difference is that the controller
+ may be capable of s4ecd4ed which would
+ be listed in edac_ctl_cap, but if
+ channels aren't capable of s4ecd4ed then the
+ edac_cap would not have that capability. */
+ unsigned long scrub_cap; /* chipset scrub capabilities */
+ enum scrub_type scrub_mode; /* current scrub mode */
+
+ enum mci_sysfs_status sysfs_active; /* status of sysfs */
+
+ /* pointer to edac checking routine */
+ void (*edac_check) (struct mem_ctl_info * mci);
+ /*
+ * Remaps memory pages: controller pages to physical pages.
+ * For most MC's, this will be NULL.
+ */
+ /* FIXME - why not send the phys page to begin with? */
+ unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
+ unsigned long page);
+ int mc_idx;
+ int nr_csrows;
+ struct csrow_info *csrows;
+ /*
+ * FIXME - what about controllers on other busses? - IDs must be
+ * unique. pdev pointer should be sufficiently unique, but
+ * BUS:SLOT.FUNC numbers may not be unique.
+ */
+ struct pci_dev *pdev;
+ const char *mod_name;
+ const char *mod_ver;
+ const char *ctl_name;
+ char proc_name[MC_PROC_NAME_MAX_LEN + 1];
+ void *pvt_info;
+ u32 ue_noinfo_count; /* Uncorrectable Errors w/o info */
+ u32 ce_noinfo_count; /* Correctable Errors w/o info */
+ u32 ue_count; /* Total Uncorrectable Errors for this MC */
+ u32 ce_count; /* Total Correctable Errors for this MC */
+ unsigned long start_time; /* mci load start time (in jiffies) */
+
+ /* this stuff is for safe removal of mc devices from global list while
+ * NMI handlers may be traversing list
+ */
+ struct rcu_head rcu;
+ struct completion complete;
+
+ /* edac sysfs device control */
+ struct kobject edac_mci_kobj;
+};
+
+
+
+/* write all or some bits in a byte-register*/
+static inline void pci_write_bits8(struct pci_dev *pdev, int offset,
+ u8 value, u8 mask)
+{
+ if (mask != 0xff) {
+ u8 buf;
+ pci_read_config_byte(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_byte(pdev, offset, value);
+}
+
+
+/* write all or some bits in a word-register*/
+static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
+ u16 value, u16 mask)
+{
+ if (mask != 0xffff) {
+ u16 buf;
+ pci_read_config_word(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_word(pdev, offset, value);
+}
+
+
+/* write all or some bits in a dword-register*/
+static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
+ u32 value, u32 mask)
+{
+ if (mask != 0xffff) {
+ u32 buf;
+ pci_read_config_dword(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_dword(pdev, offset, value);
+}
+
+
+#ifdef CONFIG_EDAC_DEBUG
+void edac_mc_dump_channel(struct channel_info *chan);
+void edac_mc_dump_mci(struct mem_ctl_info *mci);
+void edac_mc_dump_csrow(struct csrow_info *csrow);
+#endif /* CONFIG_EDAC_DEBUG */
+
+extern int edac_mc_add_mc(struct mem_ctl_info *mci);
+extern int edac_mc_del_mc(struct mem_ctl_info *mci);
+
+extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+ unsigned long page);
+
+extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev
+ *pdev);
+
+extern void edac_mc_scrub_block(unsigned long page,
+ unsigned long offset, u32 size);
+
+/*
+ * The no info errors are used when error overflows are reported.
+ * There are a limited number of error logging registers that can
+ * be exausted. When all registers are exhausted and an additional
+ * error occurs then an error overflow register records that an
+ * error occured and the type of error, but doesn't have any
+ * further information. The ce/ue versions make for cleaner
+ * reporting logic and function interface - reduces conditional
+ * statement clutter and extra function arguments.
+ */
+extern void edac_mc_handle_ce(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ unsigned long syndrome,
+ int row, int channel, const char *msg);
+
+extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+ const char *msg);
+
+extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ int row, const char *msg);
+
+extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+ const char *msg);
+
+/*
+ * This kmalloc's and initializes all the structures.
+ * Can't be used if all structures don't have the same lifetime.
+ */
+extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt,
+ unsigned nr_csrows, unsigned nr_chans);
+
+/* Free an mc previously allocated by edac_mc_alloc() */
+extern void edac_mc_free(struct mem_ctl_info *mci);
+
+
+#endif /* _EDAC_MC_H_ */
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
new file mode 100644
index 000000000000..52596e75f9c2
--- /dev/null
+++ b/drivers/edac/i82860_edac.c
@@ -0,0 +1,299 @@
+/*
+ * Intel 82860 Memory Controller kernel module
+ * (C) 2005 Red Hat (http://www.redhat.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Ben Woodard <woodard@redhat.com>
+ * shamelessly copied from and based upon the edac_i82875 driver
+ * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82860_0
+#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
+#endif /* PCI_DEVICE_ID_INTEL_82860_0 */
+
+#define I82860_MCHCFG 0x50
+#define I82860_GBA 0x60
+#define I82860_GBA_MASK 0x7FF
+#define I82860_GBA_SHIFT 24
+#define I82860_ERRSTS 0xC8
+#define I82860_EAP 0xE4
+#define I82860_DERRCTL_STS 0xE2
+
+enum i82860_chips {
+ I82860 = 0,
+};
+
+struct i82860_dev_info {
+ const char *ctl_name;
+};
+
+struct i82860_error_info {
+ u16 errsts;
+ u32 eap;
+ u16 derrsyn;
+ u16 errsts2;
+};
+
+static const struct i82860_dev_info i82860_devs[] = {
+ [I82860] = {
+ .ctl_name = "i82860"},
+};
+
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
+ has already registered driver */
+
+static int i82860_registered = 1;
+
+static void i82860_get_error_info (struct mem_ctl_info *mci,
+ struct i82860_error_info *info)
+{
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts);
+ pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+ pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, &info->derrsyn);
+ pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts2);
+
+ pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+ /*
+ * If the error is the same for both reads then the first set of reads
+ * is valid. If there is a change then there is a CE no info and the
+ * second set of reads is valid and should be UE info.
+ */
+ if (!(info->errsts2 & 0x0003))
+ return;
+ if ((info->errsts ^ info->errsts2) & 0x0003) {
+ pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+ pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
+ &info->derrsyn);
+ }
+}
+
+static int i82860_process_error_info (struct mem_ctl_info *mci,
+ struct i82860_error_info *info, int handle_errors)
+{
+ int row;
+
+ if (!(info->errsts2 & 0x0003))
+ return 0;
+
+ if (!handle_errors)
+ return 1;
+
+ if ((info->errsts ^ info->errsts2) & 0x0003) {
+ edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+ info->errsts = info->errsts2;
+ }
+
+ info->eap >>= PAGE_SHIFT;
+ row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+ if (info->errsts & 0x0002)
+ edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
+ else
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+ 0, "i82860 UE");
+
+ return 1;
+}
+
+static void i82860_check(struct mem_ctl_info *mci)
+{
+ struct i82860_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i82860_get_error_info(mci, &info);
+ i82860_process_error_info(mci, &info, 1);
+}
+
+static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ unsigned long last_cumul_size;
+
+ u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+
+ /* RDRAM has channels but these don't map onto the abstractions that
+ edac uses.
+ The device groups from the GRA registers seem to map reasonably
+ well onto the notion of a chip select row.
+ There are 16 GRA registers and since the name is associated with
+ the channel and the GRA registers map to physical devices so we are
+ going to make 1 channel for group.
+ */
+ mci = edac_mc_alloc(0, 16, 1);
+ if (!mci)
+ return -ENOMEM;
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_DDR;
+
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ /* I"m not sure about this but I think that all RDRAM is SECDED */
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ /* adjust FLAGS */
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.1.2.6 $";
+ mci->ctl_name = i82860_devs[dev_idx].ctl_name;
+ mci->edac_check = i82860_check;
+ mci->ctl_page_to_phys = NULL;
+
+ pci_read_config_word(mci->pdev, I82860_MCHCFG, &mchcfg_ddim);
+ mchcfg_ddim = mchcfg_ddim & 0x180;
+
+ /*
+ * The group row boundary (GRA) reg values are boundary address
+ * for each DRAM row with a granularity of 16MB. GRA regs are
+ * cumulative; therefore GRA15 will contain the total memory contained
+ * in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u16 value;
+ u32 cumul_size;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
+ &value);
+
+ cumul_size = (value & I82860_GBA_MASK) <<
+ (I82860_GBA_SHIFT - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
+ csrow->mtype = MEM_RMBS;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
+ }
+
+ /* clear counters */
+ pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ edac_mc_free(mci);
+ } else {
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ rc = 0;
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82860_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ printk(KERN_INFO "i82860 init one\n");
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ rc = i82860_probe1(pdev, ent->driver_data);
+ if(rc == 0)
+ mci_pdev = pci_dev_get(pdev);
+ return rc;
+}
+
+static void __devexit i82860_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ mci = edac_mc_find_mci_by_pdev(pdev);
+ if ((mci != NULL) && (edac_mc_del_mc(mci) == 0))
+ edac_mc_free(mci);
+}
+
+static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82860},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
+
+static struct pci_driver i82860_driver = {
+ .name = BS_MOD_STR,
+ .probe = i82860_init_one,
+ .remove = __devexit_p(i82860_remove_one),
+ .id_table = i82860_pci_tbl,
+};
+
+static int __init i82860_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
+ return pci_rc;
+
+ if (!mci_pdev) {
+ i82860_registered = 0;
+ mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82860_0, NULL);
+ if (mci_pdev == NULL) {
+ debugf0("860 pci_get_device fail\n");
+ return -ENODEV;
+ }
+ pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
+ if (pci_rc < 0) {
+ debugf0("860 init fail\n");
+ pci_dev_put(mci_pdev);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static void __exit i82860_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_unregister_driver(&i82860_driver);
+ if (!i82860_registered) {
+ i82860_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+ }
+}
+
+module_init(i82860_init);
+module_exit(i82860_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR
+ ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>");
+MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
new file mode 100644
index 000000000000..009c08fe5d69
--- /dev/null
+++ b/drivers/edac/i82875p_edac.c
@@ -0,0 +1,532 @@
+/*
+ * Intel D82875P Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Contributors:
+ * Wang Zhenyu at intel.com
+ *
+ * $Id: edac_i82875p.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_0
+#define PCI_DEVICE_ID_INTEL_82875_0 0x2578
+#endif /* PCI_DEVICE_ID_INTEL_82875_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_6
+#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
+#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
+
+
+/* four csrows in dual channel, eight in single channel */
+#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
+
+
+/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
+#define I82875P_EAP 0x58 /* Error Address Pointer (32b)
+ *
+ * 31:12 block address
+ * 11:0 reserved
+ */
+
+#define I82875P_DERRSYN 0x5c /* DRAM Error Syndrome (8b)
+ *
+ * 7:0 DRAM ECC Syndrome
+ */
+
+#define I82875P_DES 0x5d /* DRAM Error Status (8b)
+ *
+ * 7:1 reserved
+ * 0 Error channel 0/1
+ */
+
+#define I82875P_ERRSTS 0xc8 /* Error Status Register (16b)
+ *
+ * 15:10 reserved
+ * 9 non-DRAM lock error (ndlock)
+ * 8 Sftwr Generated SMI
+ * 7 ECC UE
+ * 6 reserved
+ * 5 MCH detects unimplemented cycle
+ * 4 AGP access outside GA
+ * 3 Invalid AGP access
+ * 2 Invalid GA translation table
+ * 1 Unsupported AGP command
+ * 0 ECC CE
+ */
+
+#define I82875P_ERRCMD 0xca /* Error Command (16b)
+ *
+ * 15:10 reserved
+ * 9 SERR on non-DRAM lock
+ * 8 SERR on ECC UE
+ * 7 SERR on ECC CE
+ * 6 target abort on high exception
+ * 5 detect unimplemented cyc
+ * 4 AGP access outside of GA
+ * 3 SERR on invalid AGP access
+ * 2 invalid translation table
+ * 1 SERR on unsupported AGP command
+ * 0 reserved
+ */
+
+
+/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
+#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b)
+ *
+ * 15:10 reserved
+ * 9 fast back-to-back - ro 0
+ * 8 SERR enable - ro 0
+ * 7 addr/data stepping - ro 0
+ * 6 parity err enable - ro 0
+ * 5 VGA palette snoop - ro 0
+ * 4 mem wr & invalidate - ro 0
+ * 3 special cycle - ro 0
+ * 2 bus master - ro 0
+ * 1 mem access dev6 - 0(dis),1(en)
+ * 0 IO access dev3 - 0(dis),1(en)
+ */
+
+#define I82875P_BAR6 0x10 /* Mem Delays Base ADDR Reg (32b)
+ *
+ * 31:12 mem base addr [31:12]
+ * 11:4 address mask - ro 0
+ * 3 prefetchable - ro 0(non),1(pre)
+ * 2:1 mem type - ro 0
+ * 0 mem space - ro 0
+ */
+
+/* Intel 82875p MMIO register space - device 0 function 0 - MMR space */
+
+#define I82875P_DRB_SHIFT 26 /* 64MiB grain */
+#define I82875P_DRB 0x00 /* DRAM Row Boundary (8b x 8)
+ *
+ * 7 reserved
+ * 6:0 64MiB row boundary addr
+ */
+
+#define I82875P_DRA 0x10 /* DRAM Row Attribute (4b x 8)
+ *
+ * 7 reserved
+ * 6:4 row attr row 1
+ * 3 reserved
+ * 2:0 row attr row 0
+ *
+ * 000 = 4KiB
+ * 001 = 8KiB
+ * 010 = 16KiB
+ * 011 = 32KiB
+ */
+
+#define I82875P_DRC 0x68 /* DRAM Controller Mode (32b)
+ *
+ * 31:30 reserved
+ * 29 init complete
+ * 28:23 reserved
+ * 22:21 nr chan 00=1,01=2
+ * 20 reserved
+ * 19:18 Data Integ Mode 00=none,01=ecc
+ * 17:11 reserved
+ * 10:8 refresh mode
+ * 7 reserved
+ * 6:4 mode select
+ * 3:2 reserved
+ * 1:0 DRAM type 01=DDR
+ */
+
+
+enum i82875p_chips {
+ I82875P = 0,
+};
+
+
+struct i82875p_pvt {
+ struct pci_dev *ovrfl_pdev;
+ void *ovrfl_window;
+};
+
+
+struct i82875p_dev_info {
+ const char *ctl_name;
+};
+
+
+struct i82875p_error_info {
+ u16 errsts;
+ u32 eap;
+ u8 des;
+ u8 derrsyn;
+ u16 errsts2;
+};
+
+
+static const struct i82875p_dev_info i82875p_devs[] = {
+ [I82875P] = {
+ .ctl_name = "i82875p"},
+};
+
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
+ has already registered driver */
+static int i82875p_registered = 1;
+
+static void i82875p_get_error_info (struct mem_ctl_info *mci,
+ struct i82875p_error_info *info)
+{
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts);
+ pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+ pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+ pci_read_config_byte(mci->pdev, I82875P_DERRSYN, &info->derrsyn);
+ pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts2);
+
+ pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+ /*
+ * If the error is the same then we can for both reads then
+ * the first set of reads is valid. If there is a change then
+ * there is a CE no info and the second set of reads is valid
+ * and should be UE info.
+ */
+ if (!(info->errsts2 & 0x0081))
+ return;
+ if ((info->errsts ^ info->errsts2) & 0x0081) {
+ pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+ pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+ pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
+ &info->derrsyn);
+ }
+}
+
+static int i82875p_process_error_info (struct mem_ctl_info *mci,
+ struct i82875p_error_info *info, int handle_errors)
+{
+ int row, multi_chan;
+
+ multi_chan = mci->csrows[0].nr_channels - 1;
+
+ if (!(info->errsts2 & 0x0081))
+ return 0;
+
+ if (!handle_errors)
+ return 1;
+
+ if ((info->errsts ^ info->errsts2) & 0x0081) {
+ edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+ info->errsts = info->errsts2;
+ }
+
+ info->eap >>= PAGE_SHIFT;
+ row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+ if (info->errsts & 0x0080)
+ edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
+ else
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+ multi_chan ? (info->des & 0x1) : 0,
+ "i82875p CE");
+
+ return 1;
+}
+
+
+static void i82875p_check(struct mem_ctl_info *mci)
+{
+ struct i82875p_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i82875p_get_error_info(mci, &info);
+ i82875p_process_error_info(mci, &info, 1);
+}
+
+
+#ifdef CONFIG_PROC_FS
+extern int pci_proc_attach_device(struct pci_dev *);
+#endif
+
+static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ struct i82875p_pvt *pvt = NULL;
+ unsigned long last_cumul_size;
+ struct pci_dev *ovrfl_pdev;
+ void __iomem *ovrfl_window = NULL;
+
+ u32 drc;
+ u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
+ u32 nr_chans;
+ u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
+
+ if (!ovrfl_pdev) {
+ /*
+ * Intel tells BIOS developers to hide device 6 which
+ * configures the overflow device access containing
+ * the DRBs - this is where we expose device 6.
+ * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
+ */
+ pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
+ ovrfl_pdev =
+ pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
+ if (!ovrfl_pdev)
+ goto fail;
+ }
+#ifdef CONFIG_PROC_FS
+ if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to attach overflow device\n",
+ __func__);
+ goto fail;
+ }
+#endif /* CONFIG_PROC_FS */
+ if (pci_enable_device(ovrfl_pdev)) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to enable overflow device\n",
+ __func__);
+ goto fail;
+ }
+
+ if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) {
+#ifdef CORRECT_BIOS
+ goto fail;
+#endif
+ }
+ /* cache is irrelevant for PCI bus reads/writes */
+ ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
+ pci_resource_len(ovrfl_pdev, 0));
+
+ if (!ovrfl_window) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to ioremap bar6\n", __func__);
+ goto fail;
+ }
+
+ /* need to find out the number of channels */
+ drc = readl(ovrfl_window + I82875P_DRC);
+ drc_chan = ((drc >> 21) & 0x1);
+ nr_chans = drc_chan + 1;
+ drc_ddim = (drc >> 18) & 0x1;
+
+ mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
+ nr_chans);
+
+ if (!mci) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_DDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ mci->edac_cap = EDAC_FLAG_UNKNOWN;
+ /* adjust FLAGS */
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.11 $";
+ mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
+ mci->edac_check = i82875p_check;
+ mci->ctl_page_to_phys = NULL;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+
+ pvt = (struct i82875p_pvt *) mci->pvt_info;
+ pvt->ovrfl_pdev = ovrfl_pdev;
+ pvt->ovrfl_window = ovrfl_window;
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address
+ * for each DRAM row with a granularity of 32 or 64MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ value = readb(ovrfl_window + I82875P_DRB + index);
+ cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
+ csrow->mtype = MEM_DDR;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
+ }
+
+ /* clear counters */
+ pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+ fail:
+ if (mci)
+ edac_mc_free(mci);
+
+ if (ovrfl_window)
+ iounmap(ovrfl_window);
+
+ if (ovrfl_pdev) {
+ pci_release_regions(ovrfl_pdev);
+ pci_disable_device(ovrfl_pdev);
+ }
+
+ /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
+ return rc;
+}
+
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82875p_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ printk(KERN_INFO "i82875p init one\n");
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ rc = i82875p_probe1(pdev, ent->driver_data);
+ if (mci_pdev == NULL)
+ mci_pdev = pci_dev_get(pdev);
+ return rc;
+}
+
+
+static void __devexit i82875p_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct i82875p_pvt *pvt = NULL;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+
+ pvt = (struct i82875p_pvt *) mci->pvt_info;
+ if (pvt->ovrfl_window)
+ iounmap(pvt->ovrfl_window);
+
+ if (pvt->ovrfl_pdev) {
+#ifdef CORRECT_BIOS
+ pci_release_regions(pvt->ovrfl_pdev);
+#endif /*CORRECT_BIOS */
+ pci_disable_device(pvt->ovrfl_pdev);
+ pci_dev_put(pvt->ovrfl_pdev);
+ }
+
+ if (edac_mc_del_mc(mci))
+ return;
+
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82875P},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
+
+
+static struct pci_driver i82875p_driver = {
+ .name = BS_MOD_STR,
+ .probe = i82875p_init_one,
+ .remove = __devexit_p(i82875p_remove_one),
+ .id_table = i82875p_pci_tbl,
+};
+
+
+static int __init i82875p_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_rc = pci_register_driver(&i82875p_driver);
+ if (pci_rc < 0)
+ return pci_rc;
+ if (mci_pdev == NULL) {
+ i82875p_registered = 0;
+ mci_pdev =
+ pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82875_0, NULL);
+ if (!mci_pdev) {
+ debugf0("875p pci_get_device fail\n");
+ return -ENODEV;
+ }
+ pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
+ if (pci_rc < 0) {
+ debugf0("875p init fail\n");
+ pci_dev_put(mci_pdev);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+
+static void __exit i82875p_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_unregister_driver(&i82875p_driver);
+ if (!i82875p_registered) {
+ i82875p_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+ }
+}
+
+
+module_init(i82875p_init);
+module_exit(i82875p_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
new file mode 100644
index 000000000000..e90892831b90
--- /dev/null
+++ b/drivers/edac/r82600_edac.c
@@ -0,0 +1,407 @@
+/*
+ * Radisys 82600 Embedded chipset Memory Controller kernel module
+ * (C) 2005 EADS Astrium
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Tim Small <tim@buttersideup.com>, based on work by Thayne
+ * Harbaugh, Dan Hollis <goemon at anime dot net> and others.
+ *
+ * $Id: edac_r82600.c,v 1.1.2.6 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Written with reference to 82600 High Integration Dual PCI System
+ * Controller Data Book:
+ * http://www.radisys.com/files/support_downloads/007-01277-0002.82600DataBook.pdf
+ * references to this document given in []
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+/* Radisys say "The 82600 integrates a main memory SDRAM controller that
+ * supports up to four banks of memory. The four banks can support a mix of
+ * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs,
+ * each of which can be any size from 16MB to 512MB. Both registered (control
+ * signals buffered) and unbuffered DIMM types are supported. Mixing of
+ * registered and unbuffered DIMMs as well as mixing of ECC and non-ECC DIMMs
+ * is not allowed. The 82600 SDRAM interface operates at the same frequency as
+ * the CPU bus, 66MHz, 100MHz or 133MHz."
+ */
+
+#define R82600_NR_CSROWS 4
+#define R82600_NR_CHANS 1
+#define R82600_NR_DIMMS 4
+
+#define R82600_BRIDGE_ID 0x8200
+
+/* Radisys 82600 register addresses - device 0 function 0 - PCI bridge */
+#define R82600_DRAMC 0x57 /* Various SDRAM related control bits
+ * all bits are R/W
+ *
+ * 7 SDRAM ISA Hole Enable
+ * 6 Flash Page Mode Enable
+ * 5 ECC Enable: 1=ECC 0=noECC
+ * 4 DRAM DIMM Type: 1=
+ * 3 BIOS Alias Disable
+ * 2 SDRAM BIOS Flash Write Enable
+ * 1:0 SDRAM Refresh Rate: 00=Disabled
+ * 01=7.8usec (256Mbit SDRAMs)
+ * 10=15.6us 11=125usec
+ */
+
+#define R82600_SDRAMC 0x76 /* "SDRAM Control Register"
+ * More SDRAM related control bits
+ * all bits are R/W
+ *
+ * 15:8 Reserved.
+ *
+ * 7:5 Special SDRAM Mode Select
+ *
+ * 4 Force ECC
+ *
+ * 1=Drive ECC bits to 0 during
+ * write cycles (i.e. ECC test mode)
+ *
+ * 0=Normal ECC functioning
+ *
+ * 3 Enhanced Paging Enable
+ *
+ * 2 CAS# Latency 0=3clks 1=2clks
+ *
+ * 1 RAS# to CAS# Delay 0=3 1=2
+ *
+ * 0 RAS# Precharge 0=3 1=2
+ */
+
+#define R82600_EAP 0x80 /* ECC Error Address Pointer Register
+ *
+ * 31 Disable Hardware Scrubbing (RW)
+ * 0=Scrub on corrected read
+ * 1=Don't scrub on corrected read
+ *
+ * 30:12 Error Address Pointer (RO)
+ * Upper 19 bits of error address
+ *
+ * 11:4 Syndrome Bits (RO)
+ *
+ * 3 BSERR# on multibit error (RW)
+ * 1=enable 0=disable
+ *
+ * 2 NMI on Single Bit Eror (RW)
+ * 1=NMI triggered by SBE n.b. other
+ * prerequeists
+ * 0=NMI not triggered
+ *
+ * 1 MBE (R/WC)
+ * read 1=MBE at EAP (see above)
+ * read 0=no MBE, or SBE occurred first
+ * write 1=Clear MBE status (must also
+ * clear SBE)
+ * write 0=NOP
+ *
+ * 1 SBE (R/WC)
+ * read 1=SBE at EAP (see above)
+ * read 0=no SBE, or MBE occurred first
+ * write 1=Clear SBE status (must also
+ * clear MBE)
+ * write 0=NOP
+ */
+
+#define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundry Address
+ * Registers
+ *
+ * 7:0 Address lines 30:24 - upper limit of
+ * each row [p57]
+ */
+
+struct r82600_error_info {
+ u32 eapr;
+};
+
+
+static unsigned int disable_hardware_scrub = 0;
+
+
+static void r82600_get_error_info (struct mem_ctl_info *mci,
+ struct r82600_error_info *info)
+{
+ pci_read_config_dword(mci->pdev, R82600_EAP, &info->eapr);
+
+ if (info->eapr & BIT(0))
+ /* Clear error to allow next error to be reported [p.62] */
+ pci_write_bits32(mci->pdev, R82600_EAP,
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
+
+ if (info->eapr & BIT(1))
+ /* Clear error to allow next error to be reported [p.62] */
+ pci_write_bits32(mci->pdev, R82600_EAP,
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
+}
+
+
+static int r82600_process_error_info (struct mem_ctl_info *mci,
+ struct r82600_error_info *info, int handle_errors)
+{
+ int error_found;
+ u32 eapaddr, page;
+ u32 syndrome;
+
+ error_found = 0;
+
+ /* bits 30:12 store the upper 19 bits of the 32 bit error address */
+ eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
+ /* Syndrome in bits 11:4 [p.62] */
+ syndrome = (info->eapr >> 4) & 0xFF;
+
+ /* the R82600 reports at less than page *
+ * granularity (upper 19 bits only) */
+ page = eapaddr >> PAGE_SHIFT;
+
+ if (info->eapr & BIT(0)) { /* CE? */
+ error_found = 1;
+
+ if (handle_errors)
+ edac_mc_handle_ce(
+ mci, page, 0, /* not avail */
+ syndrome,
+ edac_mc_find_csrow_by_page(mci, page),
+ 0, /* channel */
+ mci->ctl_name);
+ }
+
+ if (info->eapr & BIT(1)) { /* UE? */
+ error_found = 1;
+
+ if (handle_errors)
+ /* 82600 doesn't give enough info */
+ edac_mc_handle_ue(mci, page, 0,
+ edac_mc_find_csrow_by_page(mci, page),
+ mci->ctl_name);
+ }
+
+ return error_found;
+}
+
+static void r82600_check(struct mem_ctl_info *mci)
+{
+ struct r82600_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ r82600_get_error_info(mci, &info);
+ r82600_process_error_info(mci, &info, 1);
+}
+
+static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ u8 dramcr;
+ u32 ecc_on;
+ u32 reg_sdram;
+ u32 eapr;
+ u32 scrub_disabled;
+ u32 sdram_refresh_rate;
+ u32 row_high_limit_last = 0;
+ u32 eap_init_bits;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+
+ pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
+ pci_read_config_dword(pdev, R82600_EAP, &eapr);
+
+ ecc_on = dramcr & BIT(5);
+ reg_sdram = dramcr & BIT(4);
+ scrub_disabled = eapr & BIT(31);
+ sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
+
+ debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n",
+ __func__, sdram_refresh_rate);
+
+ debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__,
+ dramcr);
+
+ mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ /* FIXME try to work out if the chip leads have been *
+ * used for COM2 instead on this board? [MA6?] MAYBE: */
+
+ /* On the R82600, the pins for memory bits 72:65 - i.e. the *
+ * EC bits are shared with the pins for COM2 (!), so if COM2 *
+ * is enabled, we assume COM2 is wired up, and thus no EDAC *
+ * is possible. */
+ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ if (ecc_on) {
+ if (scrub_disabled)
+ debugf3("MC: " __FILE__ ": %s(): mci = %p - "
+ "Scrubbing disabled! EAP: %#0x\n", __func__,
+ mci, eapr);
+ } else
+ mci->edac_cap = EDAC_FLAG_NONE;
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.1.2.6 $";
+ mci->ctl_name = "R82600";
+ mci->edac_check = r82600_check;
+ mci->ctl_page_to_phys = NULL;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ struct csrow_info *csrow = &mci->csrows[index];
+ u8 drbar; /* sDram Row Boundry Address Register */
+ u32 row_high_limit;
+ u32 row_base;
+
+ /* find the DRAM Chip Select Base address and mask */
+ pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar);
+
+ debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n",
+ mci->mc_idx, __func__, index, drbar);
+
+ row_high_limit = ((u32) drbar << 24);
+/* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
+
+ debugf1("MC%d: " __FILE__ ": %s() Row=%d, "
+ "Boundry Address=%#0x, Last = %#0x \n",
+ mci->mc_idx, __func__, index, row_high_limit,
+ row_high_limit_last);
+
+ /* Empty row [p.57] */
+ if (row_high_limit == row_high_limit_last)
+ continue;
+
+ row_base = row_high_limit_last;
+
+ csrow->first_page = row_base >> PAGE_SHIFT;
+ csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
+ csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
+ /* Error address is top 19 bits - so granularity is *
+ * 14 bits */
+ csrow->grain = 1 << 14;
+ csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
+ /* FIXME - check that this is unknowable with this chipset */
+ csrow->dtype = DEV_UNKNOWN;
+
+ /* Mode is global on 82600 */
+ csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
+ row_high_limit_last = row_high_limit;
+ }
+
+ /* clear counters */
+ /* FIXME should we? */
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+
+ /* Clear error flags to allow next error to be reported [p.62] */
+ /* Test systems seem to always have the UE flag raised on boot */
+
+ eap_init_bits = BIT(0) & BIT(1);
+ if (disable_hardware_scrub) {
+ eap_init_bits |= BIT(31);
+ debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub "
+ "(scrub on error)\n", __func__);
+ }
+
+ pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits,
+ eap_init_bits);
+
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci)
+ edac_mc_free(mci);
+
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit r82600_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* don't need to call pci_device_enable() */
+ return r82600_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit r82600_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) &&
+ !edac_mc_del_mc(mci))
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
+
+
+static struct pci_driver r82600_driver = {
+ .name = BS_MOD_STR,
+ .probe = r82600_init_one,
+ .remove = __devexit_p(r82600_remove_one),
+ .id_table = r82600_pci_tbl,
+};
+
+
+static int __init r82600_init(void)
+{
+ return pci_register_driver(&r82600_driver);
+}
+
+
+static void __exit r82600_exit(void)
+{
+ pci_unregister_driver(&r82600_driver);
+}
+
+
+module_init(r82600_init);
+module_exit(r82600_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
+ "on behalf of EADS Astrium");
+MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
+
+module_param(disable_hardware_scrub, bool, 0644);
+MODULE_PARM_DESC(disable_hardware_scrub,
+ "If set, disable the chipset's automatic scrub for CEs");
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index dfedb777d8c9..fdb8b042e64d 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -49,7 +49,7 @@
MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
MODULE_LICENSE("GPL");
-MODULE_VERSION("3.1");
+MODULE_VERSION("3.2");
#define BIOS_SCAN_LIMIT 0xffffffff
#define MAX_IMAGE_LENGTH 16
@@ -564,12 +564,10 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
static void callbackfn_rbu(const struct firmware *fw, void *context)
{
- int rc = 0;
+ rbu_data.entry_created = 0;
- if (!fw || !fw->size) {
- rbu_data.entry_created = 0;
+ if (!fw || !fw->size)
return;
- }
spin_lock(&rbu_data.lock);
if (!strcmp(image_type, "mono")) {
@@ -592,15 +590,6 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
} 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,
@@ -735,14 +724,7 @@ static int __init dcdrbu_init(void)
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;
-
+ rbu_data.entry_created = 0;
return rc;
}
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index bda5bce681b6..343379f23a53 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -65,11 +65,11 @@
* v0.01 release to linux-ia64@linuxia64.org
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/sched.h> /* for capable() */
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/string.h>
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index d00a726d0239..3eb08f004c0f 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -841,7 +841,7 @@ static int __devinit vt8231_pci_probe(struct pci_dev *dev,
static int __init sm_vt8231_init(void)
{
- return pci_module_init(&vt8231_pci_driver);
+ return pci_register_driver(&vt8231_pci_driver);
}
static void __exit sm_vt8231_exit(void)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4010fe92e72b..08d5b8fed2dc 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -236,27 +236,17 @@ config I2C_IXP2000
This support is also available as a module. If so, the module
will be called i2c-ixp2000.
-config I2C_KEYWEST
- tristate "Powermac Keywest I2C interface"
+config I2C_POWERMAC
+ tristate "Powermac I2C interface"
depends on I2C && PPC_PMAC
+ default y
help
- This supports the use of the I2C interface in the combo-I/O
- chip on recent Apple 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-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 exposes the various PowerMac i2c interfaces to the linux i2c
+ layer and to userland. It is used by various drivers on the powemac
+ platform, thus should generally be enabled.
This support is also available as a module. If so, the module
- will be called i2c-pmac-smu.
+ will be called i2c-powermac.
config I2C_MPC
tristate "MPC107/824x/85xx/52xx"
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index f1df00f66c6c..b44831dff683 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -19,8 +19,7 @@ obj-$(CONFIG_I2C_ISA) += i2c-isa.o
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_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
deleted file mode 100644
index d61f748278fc..000000000000
--- a/drivers/i2c/busses/i2c-keywest.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- i2c Support for Apple Keywest I2C Bus Controller
-
- Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
-
- Original work by
-
- Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.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.
-
- Changes:
-
- 2001/12/13 BenH New implementation
- 2001/12/15 BenH Add support for "byte" and "quick"
- transfers. Add i2c_xfer routine.
- 2003/09/21 BenH Rework state machine with Paulus help
- 2004/01/21 BenH Merge in Greg KH changes, polled mode is back
- 2004/02/05 BenH Merge 64 bits fixes from the g5 ppc64 tree
-
- My understanding of the various modes supported by keywest are:
-
- - Dumb mode : not implemented, probably direct tweaking of lines
- - Standard mode : simple i2c transaction of type
- S Addr R/W A Data A Data ... T
- - Standard sub mode : combined 8 bit subaddr write with data read
- S Addr R/W A SubAddr A Data A Data ... T
- - Combined mode : Subaddress and Data sequences appended with no stop
- S Addr R/W A SubAddr S Addr R/W A Data A Data ... T
-
- Currently, this driver uses only Standard mode for i2c xfer, and
- smbus byte & quick transfers ; and uses StandardSub mode for
- other smbus transfers instead of combined as we need that for the
- sound driver to be happy
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pmac_low_i2c.h>
-
-#include "i2c-keywest.h"
-
-#undef POLLED_MODE
-
-/* Some debug macros */
-#define WRONG_STATE(name) do {\
- pr_debug("KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
- name, __kw_state_names[iface->state], isr); \
- } while(0)
-
-#ifdef DEBUG
-static const char *__kw_state_names[] = {
- "state_idle",
- "state_addr",
- "state_read",
- "state_write",
- "state_stop",
- "state_dead"
-};
-#endif /* DEBUG */
-
-MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
-MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
-MODULE_LICENSE("GPL");
-
-#ifdef POLLED_MODE
-/* Don't schedule, the g5 fan controller is too
- * timing sensitive
- */
-static u8
-wait_interrupt(struct keywest_iface* iface)
-{
- int i;
- u8 isr;
-
- for (i = 0; i < 200000; i++) {
- isr = read_reg(reg_isr) & KW_I2C_IRQ_MASK;
- if (isr != 0)
- return isr;
- udelay(10);
- }
- return isr;
-}
-#endif /* POLLED_MODE */
-
-static void
-do_stop(struct keywest_iface* iface, int result)
-{
- write_reg(reg_control, KW_I2C_CTL_STOP);
- iface->state = state_stop;
- iface->result = result;
-}
-
-/* Main state machine for standard & standard sub mode */
-static void
-handle_interrupt(struct keywest_iface *iface, u8 isr)
-{
- int ack;
-
- if (isr == 0) {
- if (iface->state != state_stop) {
- pr_debug("KW: Timeout !\n");
- do_stop(iface, -EIO);
- }
- if (iface->state == state_stop) {
- ack = read_reg(reg_status);
- if (!(ack & KW_I2C_STAT_BUSY)) {
- iface->state = state_idle;
- write_reg(reg_ier, 0x00);
-#ifndef POLLED_MODE
- complete(&iface->complete);
-#endif /* POLLED_MODE */
- }
- }
- return;
- }
-
- if (isr & KW_I2C_IRQ_ADDR) {
- ack = read_reg(reg_status);
- if (iface->state != state_addr) {
- write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- WRONG_STATE("KW_I2C_IRQ_ADDR");
- do_stop(iface, -EIO);
- return;
- }
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- iface->state = state_stop;
- iface->result = -ENODEV;
- pr_debug("KW: NAK on address\n");
- } else {
- /* Handle rw "quick" mode */
- if (iface->datalen == 0) {
- do_stop(iface, 0);
- } else if (iface->read_write == I2C_SMBUS_READ) {
- iface->state = state_read;
- if (iface->datalen > 1)
- write_reg(reg_control, KW_I2C_CTL_AAK);
- } else {
- iface->state = state_write;
- write_reg(reg_data, *(iface->data++));
- iface->datalen--;
- }
- }
- write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- }
-
- if (isr & KW_I2C_IRQ_DATA) {
- if (iface->state == state_read) {
- *(iface->data++) = read_reg(reg_data);
- write_reg(reg_isr, KW_I2C_IRQ_DATA);
- iface->datalen--;
- if (iface->datalen == 0)
- iface->state = state_stop;
- else if (iface->datalen == 1)
- write_reg(reg_control, 0);
- } else if (iface->state == state_write) {
- /* Check ack status */
- ack = read_reg(reg_status);
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- pr_debug("KW: nack on data write (%x): %x\n",
- iface->data[-1], ack);
- do_stop(iface, -EIO);
- } else if (iface->datalen) {
- write_reg(reg_data, *(iface->data++));
- iface->datalen--;
- } else {
- write_reg(reg_control, KW_I2C_CTL_STOP);
- iface->state = state_stop;
- iface->result = 0;
- }
- write_reg(reg_isr, KW_I2C_IRQ_DATA);
- } else {
- write_reg(reg_isr, KW_I2C_IRQ_DATA);
- WRONG_STATE("KW_I2C_IRQ_DATA");
- if (iface->state != state_stop)
- do_stop(iface, -EIO);
- }
- }
-
- if (isr & KW_I2C_IRQ_STOP) {
- write_reg(reg_isr, KW_I2C_IRQ_STOP);
- if (iface->state != state_stop) {
- WRONG_STATE("KW_I2C_IRQ_STOP");
- iface->result = -EIO;
- }
- iface->state = state_idle;
- write_reg(reg_ier, 0x00);
-#ifndef POLLED_MODE
- complete(&iface->complete);
-#endif /* POLLED_MODE */
- }
-
- if (isr & KW_I2C_IRQ_START)
- write_reg(reg_isr, KW_I2C_IRQ_START);
-}
-
-#ifndef POLLED_MODE
-
-/* Interrupt handler */
-static irqreturn_t
-keywest_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct keywest_iface *iface = (struct keywest_iface *)dev_id;
- unsigned long flags;
-
- spin_lock_irqsave(&iface->lock, flags);
- del_timer(&iface->timeout_timer);
- handle_interrupt(iface, read_reg(reg_isr));
- if (iface->state != state_idle) {
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
- }
- spin_unlock_irqrestore(&iface->lock, flags);
- return IRQ_HANDLED;
-}
-
-static void
-keywest_timeout(unsigned long data)
-{
- struct keywest_iface *iface = (struct keywest_iface *)data;
- unsigned long flags;
-
- pr_debug("timeout !\n");
- spin_lock_irqsave(&iface->lock, flags);
- handle_interrupt(iface, read_reg(reg_isr));
- if (iface->state != state_idle) {
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
- }
- spin_unlock_irqrestore(&iface->lock, flags);
-}
-
-#endif /* POLLED_MODE */
-
-/*
- * SMBUS-type transfer entrypoint
- */
-static s32
-keywest_smbus_xfer( struct i2c_adapter* adap,
- u16 addr,
- unsigned short flags,
- char read_write,
- u8 command,
- int size,
- union i2c_smbus_data* data)
-{
- struct keywest_chan* chan = i2c_get_adapdata(adap);
- struct keywest_iface* iface = chan->iface;
- int len;
- u8* buffer;
- u16 cur_word;
- int rc = 0;
-
- if (iface->state == state_dead)
- return -ENXIO;
-
- /* Prepare datas & select mode */
- iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
- switch (size) {
- case I2C_SMBUS_QUICK:
- len = 0;
- buffer = NULL;
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
- break;
- case I2C_SMBUS_BYTE:
- len = 1;
- buffer = &data->byte;
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
- break;
- case I2C_SMBUS_BYTE_DATA:
- len = 1;
- buffer = &data->byte;
- iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
- break;
- case I2C_SMBUS_WORD_DATA:
- len = 2;
- cur_word = cpu_to_le16(data->word);
- buffer = (u8 *)&cur_word;
- iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
- break;
- case I2C_SMBUS_BLOCK_DATA:
- len = data->block[0];
- buffer = &data->block[1];
- iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
- break;
- default:
- return -1;
- }
-
- /* Turn a standardsub read into a combined mode access */
- if (read_write == I2C_SMBUS_READ
- && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) {
- iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
- iface->cur_mode |= KW_I2C_MODE_COMBINED;
- }
-
- /* Original driver had this limitation */
- if (len > 32)
- len = 32;
-
- if (pmac_low_i2c_lock(iface->node))
- return -ENXIO;
-
- pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n",
- chan->chan_no, addr, len, read_write == I2C_SMBUS_READ);
-
- iface->data = buffer;
- iface->datalen = len;
- iface->state = state_addr;
- iface->result = 0;
- iface->read_write = read_write;
-
- /* Setup channel & clear pending irqs */
- write_reg(reg_isr, read_reg(reg_isr));
- write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));
- write_reg(reg_status, 0);
-
- /* Set up address and r/w bit */
- write_reg(reg_addr,
- (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));
-
- /* Set up the sub address */
- if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
- || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
- write_reg(reg_subaddr, command);
-
-#ifndef POLLED_MODE
- /* Arm timeout */
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
-#endif
-
- /* Start sending address & enable interrupt*/
- write_reg(reg_control, KW_I2C_CTL_XADDR);
- write_reg(reg_ier, KW_I2C_IRQ_MASK);
-
-#ifdef POLLED_MODE
- pr_debug("using polled mode...\n");
- /* State machine, to turn into an interrupt handler */
- while(iface->state != state_idle) {
- unsigned long flags;
-
- u8 isr = wait_interrupt(iface);
- spin_lock_irqsave(&iface->lock, flags);
- handle_interrupt(iface, isr);
- spin_unlock_irqrestore(&iface->lock, flags);
- }
-#else /* POLLED_MODE */
- pr_debug("using interrupt mode...\n");
- wait_for_completion(&iface->complete);
-#endif /* POLLED_MODE */
-
- rc = iface->result;
- pr_debug("transfer done, result: %d\n", rc);
-
- if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ)
- data->word = le16_to_cpu(cur_word);
-
- /* Release sem */
- pmac_low_i2c_unlock(iface->node);
-
- return rc;
-}
-
-/*
- * Generic i2c master transfer entrypoint
- */
-static int
-keywest_xfer( struct i2c_adapter *adap,
- struct i2c_msg *msgs,
- int num)
-{
- struct keywest_chan* chan = i2c_get_adapdata(adap);
- struct keywest_iface* iface = chan->iface;
- struct i2c_msg *pmsg;
- int i, completed;
- int rc = 0;
-
- if (iface->state == state_dead)
- return -ENXIO;
-
- if (pmac_low_i2c_lock(iface->node))
- return -ENXIO;
-
- /* Set adapter to standard mode */
- iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
-
- completed = 0;
- for (i = 0; rc >= 0 && i < num;) {
- u8 addr;
-
- pmsg = &msgs[i++];
- addr = pmsg->addr;
- if (pmsg->flags & I2C_M_TEN) {
- printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n");
- rc = -EINVAL;
- break;
- }
- pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n",
- chan->chan_no,
- pmsg->flags & I2C_M_RD ? "read" : "write",
- pmsg->len, addr, i, num);
-
- /* Setup channel & clear pending irqs */
- write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));
- write_reg(reg_isr, read_reg(reg_isr));
- write_reg(reg_status, 0);
-
- iface->data = pmsg->buf;
- iface->datalen = pmsg->len;
- iface->state = state_addr;
- iface->result = 0;
- if (pmsg->flags & I2C_M_RD)
- iface->read_write = I2C_SMBUS_READ;
- else
- iface->read_write = I2C_SMBUS_WRITE;
-
- /* Set up address and r/w bit */
- if (pmsg->flags & I2C_M_REV_DIR_ADDR)
- addr ^= 1;
- write_reg(reg_addr,
- (addr << 1) |
- ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));
-
-#ifndef POLLED_MODE
- /* Arm timeout */
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
-#endif
-
- /* Start sending address & enable interrupt*/
- write_reg(reg_ier, KW_I2C_IRQ_MASK);
- write_reg(reg_control, KW_I2C_CTL_XADDR);
-
-#ifdef POLLED_MODE
- pr_debug("using polled mode...\n");
- /* State machine, to turn into an interrupt handler */
- while(iface->state != state_idle) {
- u8 isr = wait_interrupt(iface);
- handle_interrupt(iface, isr);
- }
-#else /* POLLED_MODE */
- pr_debug("using interrupt mode...\n");
- wait_for_completion(&iface->complete);
-#endif /* POLLED_MODE */
-
- rc = iface->result;
- if (rc == 0)
- completed++;
- pr_debug("transfer done, result: %d\n", rc);
- }
-
- /* Release sem */
- pmac_low_i2c_unlock(iface->node);
-
- return completed;
-}
-
-static u32
-keywest_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 keywest_algorithm = {
- .smbus_xfer = keywest_smbus_xfer,
- .master_xfer = keywest_xfer,
- .functionality = keywest_func,
-};
-
-
-static int
-create_iface(struct device_node *np, struct device *dev)
-{
- unsigned long steps;
- unsigned bsteps, tsize, i, nchan, addroffset;
- struct keywest_iface* iface;
- u32 *psteps, *prate;
- int rc;
-
- if (np->n_intrs < 1 || np->n_addrs < 1) {
- printk(KERN_ERR "%s: Missing interrupt or address !\n",
- np->full_name);
- return -ENODEV;
- }
- if (pmac_low_i2c_lock(np))
- return -ENODEV;
-
- psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
- steps = psteps ? (*psteps) : 0x10;
-
- /* Hrm... maybe we can be smarter here */
- for (bsteps = 0; (steps & 0x01) == 0; bsteps++)
- steps >>= 1;
-
- if (np->parent->name[0] == 'u') {
- nchan = 2;
- addroffset = 3;
- } else {
- addroffset = 0;
- nchan = 1;
- }
-
- tsize = sizeof(struct keywest_iface) +
- (sizeof(struct keywest_chan) + 4) * nchan;
- 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;
- }
- spin_lock_init(&iface->lock);
- init_completion(&iface->complete);
- iface->node = of_node_get(np);
- iface->bsteps = bsteps;
- iface->chan_count = nchan;
- iface->state = state_idle;
- iface->irq = np->intrs[0].line;
- iface->channels = (struct keywest_chan *)
- (((unsigned long)(iface + 1) + 3UL) & ~3UL);
- iface->base = ioremap(np->addrs[0].address + addroffset,
- np->addrs[0].size);
- if (!iface->base) {
- printk(KERN_ERR "i2c-keywest: can't map inteface !\n");
- kfree(iface);
- pmac_low_i2c_unlock(np);
- return -ENOMEM;
- }
-
-#ifndef POLLED_MODE
- init_timer(&iface->timeout_timer);
- iface->timeout_timer.function = keywest_timeout;
- iface->timeout_timer.data = (unsigned long)iface;
-#endif
-
- /* Select interface rate */
- iface->cur_mode = KW_I2C_MODE_100KHZ;
- prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
- if (prate) switch(*prate) {
- case 100:
- iface->cur_mode = KW_I2C_MODE_100KHZ;
- break;
- case 50:
- iface->cur_mode = KW_I2C_MODE_50KHZ;
- break;
- case 25:
- iface->cur_mode = KW_I2C_MODE_25KHZ;
- break;
- default:
- printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n",
- (long)*prate);
- }
-
- /* Select standard mode by default */
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
-
- /* Write mode */
- write_reg(reg_mode, iface->cur_mode);
-
- /* Switch interrupts off & clear them*/
- write_reg(reg_ier, 0x00);
- write_reg(reg_isr, KW_I2C_IRQ_MASK);
-
-#ifndef POLLED_MODE
- /* Request chip interrupt */
- rc = request_irq(iface->irq, keywest_irq, SA_INTERRUPT, "keywest i2c", iface);
- if (rc) {
- printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq);
- iounmap(iface->base);
- kfree(iface);
- pmac_low_i2c_unlock(np);
- return -ENODEV;
- }
-#endif /* POLLED_MODE */
-
- pmac_low_i2c_unlock(np);
- dev_set_drvdata(dev, iface);
-
- for (i=0; i<nchan; i++) {
- struct keywest_chan* chan = &iface->channels[i];
-
- sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
- chan->iface = iface;
- chan->chan_no = i;
- chan->adapter.algo = &keywest_algorithm;
- chan->adapter.algo_data = NULL;
- chan->adapter.client_register = NULL;
- chan->adapter.client_unregister = NULL;
- i2c_set_adapdata(&chan->adapter, chan);
- chan->adapter.dev.parent = dev;
-
- rc = i2c_add_adapter(&chan->adapter);
- if (rc) {
- printk("i2c-keywest.c: Adapter %s registration failed\n",
- chan->adapter.name);
- i2c_set_adapdata(&chan->adapter, NULL);
- }
- }
-
- printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
- np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps);
-
- return 0;
-}
-
-static int
-dispose_iface(struct device *dev)
-{
- struct keywest_iface *iface = dev_get_drvdata(dev);
- int i, rc;
-
- /* Make sure we stop all activity */
- if (pmac_low_i2c_lock(iface->node))
- return -ENODEV;
-
-#ifndef POLLED_MODE
- spin_lock_irq(&iface->lock);
- while (iface->state != state_idle) {
- spin_unlock_irq(&iface->lock);
- msleep(100);
- spin_lock_irq(&iface->lock);
- }
-#endif /* POLLED_MODE */
- iface->state = state_dead;
-#ifndef POLLED_MODE
- spin_unlock_irq(&iface->lock);
- free_irq(iface->irq, iface);
-#endif /* POLLED_MODE */
-
- pmac_low_i2c_unlock(iface->node);
-
- /* Release all channels */
- for (i=0; i<iface->chan_count; i++) {
- struct keywest_chan* chan = &iface->channels[i];
- if (i2c_get_adapdata(&chan->adapter) == NULL)
- continue;
- rc = i2c_del_adapter(&chan->adapter);
- i2c_set_adapdata(&chan->adapter, NULL);
- /* We aren't that prepared to deal with this... */
- if (rc)
- printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n");
- }
- iounmap(iface->base);
- dev_set_drvdata(dev, NULL);
- of_node_put(iface->node);
- kfree(iface);
-
- return 0;
-}
-
-static int
-create_iface_macio(struct macio_dev* dev, const struct of_device_id *match)
-{
- return create_iface(dev->ofdev.node, &dev->ofdev.dev);
-}
-
-static int
-dispose_iface_macio(struct macio_dev* dev)
-{
- return dispose_iface(&dev->ofdev.dev);
-}
-
-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_keywest_match[] =
-{
- {
- .type = "i2c",
- .compatible = "keywest"
- },
- {},
-};
-
-static struct macio_driver i2c_keywest_macio_driver =
-{
- .owner = THIS_MODULE,
- .name = "i2c-keywest",
- .match_table = i2c_keywest_match,
- .probe = create_iface_macio,
- .remove = dispose_iface_macio
-};
-
-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,
- .remove = dispose_iface_of_platform
-};
-
-static int __init
-i2c_keywest_init(void)
-{
- of_register_driver(&i2c_keywest_of_platform_driver);
- macio_register_driver(&i2c_keywest_macio_driver);
-
- return 0;
-}
-
-static void __exit
-i2c_keywest_cleanup(void)
-{
- of_unregister_driver(&i2c_keywest_of_platform_driver);
- macio_unregister_driver(&i2c_keywest_macio_driver);
-}
-
-module_init(i2c_keywest_init);
-module_exit(i2c_keywest_cleanup);
diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h
deleted file mode 100644
index c5022e1ca6ff..000000000000
--- a/drivers/i2c/busses/i2c-keywest.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef __I2C_KEYWEST_H__
-#define __I2C_KEYWEST_H__
-
-/* The Tumbler audio equalizer can be really slow sometimes */
-#define POLL_TIMEOUT (2*HZ)
-
-/* Register indices */
-typedef enum {
- reg_mode = 0,
- reg_control,
- reg_status,
- reg_isr,
- reg_ier,
- reg_addr,
- reg_subaddr,
- reg_data
-} reg_t;
-
-
-/* Mode register */
-#define KW_I2C_MODE_100KHZ 0x00
-#define KW_I2C_MODE_50KHZ 0x01
-#define KW_I2C_MODE_25KHZ 0x02
-#define KW_I2C_MODE_DUMB 0x00
-#define KW_I2C_MODE_STANDARD 0x04
-#define KW_I2C_MODE_STANDARDSUB 0x08
-#define KW_I2C_MODE_COMBINED 0x0C
-#define KW_I2C_MODE_MODE_MASK 0x0C
-#define KW_I2C_MODE_CHAN_MASK 0xF0
-
-/* Control register */
-#define KW_I2C_CTL_AAK 0x01
-#define KW_I2C_CTL_XADDR 0x02
-#define KW_I2C_CTL_STOP 0x04
-#define KW_I2C_CTL_START 0x08
-
-/* Status register */
-#define KW_I2C_STAT_BUSY 0x01
-#define KW_I2C_STAT_LAST_AAK 0x02
-#define KW_I2C_STAT_LAST_RW 0x04
-#define KW_I2C_STAT_SDA 0x08
-#define KW_I2C_STAT_SCL 0x10
-
-/* IER & ISR registers */
-#define KW_I2C_IRQ_DATA 0x01
-#define KW_I2C_IRQ_ADDR 0x02
-#define KW_I2C_IRQ_STOP 0x04
-#define KW_I2C_IRQ_START 0x08
-#define KW_I2C_IRQ_MASK 0x0F
-
-/* Physical interface */
-struct keywest_iface
-{
- struct device_node *node;
- void __iomem * base;
- unsigned bsteps;
- int irq;
- spinlock_t lock;
- struct keywest_chan *channels;
- unsigned chan_count;
- u8 cur_mode;
- char read_write;
- u8 *data;
- unsigned datalen;
- int state;
- int result;
- struct timer_list timeout_timer;
- struct completion complete;
-};
-
-enum {
- state_idle,
- state_addr,
- state_read,
- state_write,
- state_stop,
- state_dead
-};
-
-/* Channel on an interface */
-struct keywest_chan
-{
- struct i2c_adapter adapter;
- struct keywest_iface* iface;
- unsigned chan_no;
-};
-
-/* Register access */
-
-static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg)
-{
- return in_8(iface->base
- + (((unsigned)reg) << iface->bsteps));
-}
-
-static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val)
-{
- out_8(iface->base
- + (((unsigned)reg) << iface->bsteps), val);
- (void)__read_reg(iface, reg_subaddr);
-}
-
-#define write_reg(reg, val) __write_reg(iface, reg, val)
-#define read_reg(reg) __read_reg(iface, reg)
-
-
-
-#endif /* __I2C_KEYWEST_H__ */
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
deleted file mode 100644
index bfefe7f7a53d..000000000000
--- a/drivers/i2c/busses/i2c-pmac-smu.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- 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-powermac.c b/drivers/i2c/busses/i2c-powermac.c
new file mode 100644
index 000000000000..df786eb55295
--- /dev/null
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -0,0 +1,290 @@
+/*
+ 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 <linux/platform_device.h>
+#include <asm/prom.h>
+#include <asm/pmac_low_i2c.h>
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("I2C driver for Apple PowerMac");
+MODULE_LICENSE("GPL");
+
+/*
+ * SMBUS-type transfer entrypoint
+ */
+static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
+ u16 addr,
+ unsigned short flags,
+ char read_write,
+ u8 command,
+ int size,
+ union i2c_smbus_data* data)
+{
+ struct pmac_i2c_bus *bus = i2c_get_adapdata(adap);
+ int rc = 0;
+ int read = (read_write == I2C_SMBUS_READ);
+ int addrdir = (addr << 1) | read;
+ u8 local[2];
+
+ rc = pmac_i2c_open(bus, 0);
+ if (rc)
+ return rc;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0);
+ break;
+ case I2C_SMBUS_BYTE:
+ rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1);
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1);
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ if (!read) {
+ local[0] = data->word & 0xff;
+ local[1] = (data->word >> 8) & 0xff;
+ }
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2);
+ if (rc == 0 && read) {
+ data->word = ((u16)local[1]) << 8;
+ data->word |= local[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 ...
+ *
+ * I'm also not completely sure what kind of phases to do between
+ * the actual command and the data (what I am _supposed_ to do that
+ * is). For now, I assume writes are a single stream and reads have
+ * a repeat start/addr phase (but not stop in between)
+ */
+ case I2C_SMBUS_BLOCK_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block,
+ data->block[0] + 1);
+
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command,
+ read ? data->block : &data->block[1],
+ data->block[0]);
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+ bail:
+ pmac_i2c_close(bus);
+ return rc;
+}
+
+/*
+ * Generic i2c master transfer entrypoint. This driver only support single
+ * messages (for "lame i2c" transfers). Anything else should use the smbus
+ * entry point
+ */
+static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
+ struct i2c_msg *msgs,
+ int num)
+{
+ struct pmac_i2c_bus *bus = i2c_get_adapdata(adap);
+ int rc = 0;
+ int read;
+ int addrdir;
+
+ if (num != 1)
+ return -EINVAL;
+ if (msgs->flags & I2C_M_TEN)
+ return -EINVAL;
+ read = (msgs->flags & I2C_M_RD) != 0;
+ addrdir = (msgs->addr << 1) | read;
+ if (msgs->flags & I2C_M_REV_DIR_ADDR)
+ addrdir ^= 1;
+
+ rc = pmac_i2c_open(bus, 0);
+ if (rc)
+ return rc;
+ rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
+ bail:
+ pmac_i2c_close(bus);
+ return rc < 0 ? rc : msgs->len;
+}
+
+static u32 i2c_powermac_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_I2C;
+}
+
+/* For now, we only handle smbus */
+static struct i2c_algorithm i2c_powermac_algorithm = {
+ .smbus_xfer = i2c_powermac_smbus_xfer,
+ .master_xfer = i2c_powermac_master_xfer,
+ .functionality = i2c_powermac_func,
+};
+
+
+static int i2c_powermac_remove(struct device *dev)
+{
+ struct i2c_adapter *adapter = dev_get_drvdata(dev);
+ struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter);
+ int rc;
+
+ rc = i2c_del_adapter(adapter);
+ pmac_i2c_detach_adapter(bus, adapter);
+ i2c_set_adapdata(adapter, NULL);
+ /* We aren't that prepared to deal with this... */
+ if (rc)
+ printk("i2c-powermac.c: Failed to remove bus %s !\n",
+ adapter->name);
+ dev_set_drvdata(dev, NULL);
+ kfree(adapter);
+
+ return 0;
+}
+
+
+static int i2c_powermac_probe(struct device *dev)
+{
+ struct pmac_i2c_bus *bus = dev->platform_data;
+ struct device_node *parent = NULL;
+ struct i2c_adapter *adapter;
+ char name[32], *basename;
+ int rc;
+
+ if (bus == NULL)
+ return -EINVAL;
+
+ /* Ok, now we need to make up a name for the interface that will
+ * match what we used to do in the past, that is basically the
+ * controller's parent device node for keywest. PMU didn't have a
+ * naming convention and SMU has a different one
+ */
+ switch(pmac_i2c_get_type(bus)) {
+ case pmac_i2c_bus_keywest:
+ parent = of_get_parent(pmac_i2c_get_controller(bus));
+ if (parent == NULL)
+ return -EINVAL;
+ basename = parent->name;
+ break;
+ case pmac_i2c_bus_pmu:
+ basename = "pmu";
+ break;
+ case pmac_i2c_bus_smu:
+ /* This is not what we used to do but I'm fixing drivers at
+ * the same time as this change
+ */
+ basename = "smu";
+ break;
+ default:
+ return -EINVAL;
+ }
+ snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus));
+ of_node_put(parent);
+
+ adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(dev, adapter);
+ strcpy(adapter->name, name);
+ adapter->algo = &i2c_powermac_algorithm;
+ i2c_set_adapdata(adapter, bus);
+ adapter->dev.parent = dev;
+ pmac_i2c_attach_adapter(bus, adapter);
+ rc = i2c_add_adapter(adapter);
+ if (rc) {
+ printk(KERN_ERR "i2c-powermac: Adapter %s registration "
+ "failed\n", name);
+ i2c_set_adapdata(adapter, NULL);
+ pmac_i2c_detach_adapter(bus, adapter);
+ }
+
+ printk(KERN_INFO "PowerMac i2c bus %s registered\n", name);
+ return rc;
+}
+
+
+static struct device_driver i2c_powermac_driver = {
+ .name = "i2c-powermac",
+ .bus = &platform_bus_type,
+ .probe = i2c_powermac_probe,
+ .remove = i2c_powermac_remove,
+};
+
+static int __init i2c_powermac_init(void)
+{
+ driver_register(&i2c_powermac_driver);
+ return 0;
+}
+
+
+static void __exit i2c_powermac_cleanup(void)
+{
+ driver_unregister(&i2c_powermac_driver);
+}
+
+module_init(i2c_powermac_init);
+module_exit(i2c_powermac_cleanup);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 70f7ab829d36..86e2234faf80 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -899,6 +899,12 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
struct pxa_i2c *i2c = adap->algo_data;
int ret, i;
+ /* If the I2C controller is disabled we need to reset it (probably due
+ to a suspend/resume destroying state). We do this here as we can then
+ avoid worrying about resuming the controller before its users. */
+ if (!(ICR & ICR_IUE))
+ i2c_pxa_reset(i2c);
+
for (i = adap->retries; i >= 0; i--) {
ret = i2c_pxa_do_xfer(i2c, msgs, num);
if (ret != I2C_RETRY)
@@ -939,7 +945,9 @@ static struct pxa_i2c i2c_pxa = {
static int i2c_pxa_probe(struct platform_device *dev)
{
struct pxa_i2c *i2c = &i2c_pxa;
+#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
+#endif
int ret;
#ifdef CONFIG_PXA27x
@@ -1024,5 +1032,7 @@ static void i2c_adap_pxa_exit(void)
return platform_driver_unregister(&i2c_pxa_driver);
}
+MODULE_LICENSE("GPL");
+
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 58cfd3111ef6..f7d40f8e5f5c 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -34,12 +34,12 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-iic.h>
#include <asm/arch/iic.h>
@@ -738,7 +738,6 @@ static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
{
if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
clk_disable(i2c->clk);
- clk_unuse(i2c->clk);
clk_put(i2c->clk);
i2c->clk = NULL;
}
@@ -778,7 +777,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
- clk_use(i2c->clk);
clk_enable(i2c->clk);
/* map the registers */
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index e70b3db69edd..1af3dfbb8086 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -494,6 +494,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
{
struct tps65010 *tps;
int status;
+ unsigned long irqflags;
if (the_tps) {
dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
@@ -520,13 +521,14 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
}
#ifdef CONFIG_ARM
+ irqflags = SA_SAMPLE_RANDOM | SA_TRIGGER_LOW;
if (machine_is_omap_h2()) {
tps->model = TPS65010;
omap_cfg_reg(W4_GPIO58);
tps->irq = OMAP_GPIO_IRQ(58);
omap_request_gpio(58);
omap_set_gpio_direction(58, 1);
- set_irq_type(tps->irq, IRQT_FALLING);
+ irqflags |= SA_TRIGGER_FALLING;
}
if (machine_is_omap_osk()) {
tps->model = TPS65010;
@@ -534,7 +536,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
omap_request_gpio(OMAP_MPUIO(1));
omap_set_gpio_direction(OMAP_MPUIO(1), 1);
- set_irq_type(tps->irq, IRQT_FALLING);
+ irqflags |= SA_TRIGGER_FALLING;
}
if (machine_is_omap_h3()) {
tps->model = TPS65013;
@@ -542,13 +544,12 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
// FIXME set up this board's IRQ ...
}
#else
-#define set_irq_type(num,trigger) do{}while(0)
+ irqflags = SA_SAMPLE_RANDOM;
#endif
if (tps->irq > 0) {
- set_irq_type(tps->irq, IRQT_LOW);
status = request_irq(tps->irq, tps65010_irq,
- SA_SAMPLE_RANDOM, DRIVER_NAME, tps);
+ irqflags, DRIVER_NAME, tps);
if (status < 0) {
dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n",
tps->irq, status);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 52b77477df57..0ce58b506046 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev)
return rc;
}
-struct bus_type i2c_bus_type = {
- .name = "i2c",
- .match = i2c_device_match,
- .suspend = i2c_bus_suspend,
- .resume = i2c_bus_resume,
-};
-
static int i2c_device_probe(struct device *dev)
{
return -ENODEV;
@@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev)
return 0;
}
+struct bus_type i2c_bus_type = {
+ .name = "i2c",
+ .match = i2c_device_match,
+ .probe = i2c_device_probe,
+ .remove = i2c_device_remove,
+ .suspend = i2c_bus_suspend,
+ .resume = i2c_bus_resume,
+};
+
void i2c_adapter_dev_release(struct device *dev)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
@@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = {
.owner = THIS_MODULE,
.name = "i2c_adapter",
.bus = &i2c_bus_type,
- .probe = i2c_device_probe,
- .remove = i2c_device_remove,
};
static void i2c_adapter_class_dev_release(struct class_device *dev)
@@ -294,8 +294,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
- driver->driver.probe = i2c_device_probe;
- driver->driver.remove = i2c_device_remove;
res = driver_register(&driver->driver);
if (res)
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index d31117eb95aa..3325660f7248 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
* and attempt to recover if there are problems. Returns 0 if everything's
* ok; nonzero if the request has been terminated.
*/
-static inline
+static
int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
{
if (ireason == 2)
@@ -1332,8 +1332,6 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
if (cdrom_read_from_buffer(drive))
return ide_stopped;
- blk_attempt_remerge(drive->queue, rq);
-
/* Clear the local sector buffer. */
info->nsectors_buffered = 0;
@@ -1541,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
/*
* Write handling
*/
-static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
+static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
{
/* Two notes about IDE interrupt reason here - 0 means that
* the drive wants to receive data from us, 2 means that
@@ -1874,14 +1872,6 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
- /*
- * for dvd-ram and such media, it's a really big deal to get
- * big writes all the time. so scour the queue and attempt to
- * remerge requests, often the plugging will not have had time
- * to do this properly
- */
- blk_attempt_remerge(drive->queue, rq);
-
info->nsectors_buffered = 0;
/* use dma, if possible. we don't need to check more, since we
@@ -2905,6 +2895,8 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
devinfo->mask |= CDC_CLOSE_TRAY;
if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
devinfo->mask |= CDC_MO_DRIVE;
+ if (!CDROM_CONFIG_FLAGS(drive)->ram)
+ devinfo->mask |= CDC_RAM;
devinfo->disk = info->disk;
return register_cdrom(devinfo);
@@ -3264,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
}
#endif
-static int ide_cd_remove(struct device *dev)
+static void ide_cd_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info = drive->driver_data;
ide_unregister_subdriver(drive, info->driver);
@@ -3274,8 +3265,6 @@ static int ide_cd_remove(struct device *dev)
del_gendisk(info->disk);
ide_cd_put(info);
-
- return 0;
}
static void ide_cd_release(struct kref *kref)
@@ -3299,7 +3288,7 @@ static void ide_cd_release(struct kref *kref)
kfree(info);
}
-static int ide_cd_probe(struct device *);
+static int ide_cd_probe(ide_drive_t *);
#ifdef CONFIG_PROC_FS
static int proc_idecd_read_capacity
@@ -3325,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
.name = "ide-cdrom",
.bus = &ide_bus_type,
- .probe = ide_cd_probe,
- .remove = ide_cd_remove,
},
+ .probe = ide_cd_probe,
+ .remove = ide_cd_remove,
.version = IDECD_VERSION,
.media = ide_cdrom,
.supports_dsc_overlap = 1,
@@ -3421,9 +3410,8 @@ static char *ignore = NULL;
module_param(ignore, charp, 0400);
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
-static int ide_cd_probe(struct device *dev)
+static int ide_cd_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info;
struct gendisk *g;
struct request_sense sense;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4b441720b6ba..ca25f9e3d0f4 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id)
&& id->lba_capacity_2;
}
-static inline void idedisk_check_hpa(ide_drive_t *drive)
+static void idedisk_check_hpa(ide_drive_t *drive)
{
unsigned long long capacity, set_max;
int lba48 = idedisk_supports_lba48(drive->id);
@@ -997,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t *drive)
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
}
-static int ide_disk_remove(struct device *dev)
+static void ide_disk_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp = drive->driver_data;
struct gendisk *g = idkp->disk;
@@ -1010,8 +1009,6 @@ static int ide_disk_remove(struct device *dev)
ide_cacheflush_p(drive);
ide_disk_put(idkp);
-
- return 0;
}
static void ide_disk_release(struct kref *kref)
@@ -1027,12 +1024,10 @@ static void ide_disk_release(struct kref *kref)
kfree(idkp);
}
-static int ide_disk_probe(struct device *dev);
+static int ide_disk_probe(ide_drive_t *drive);
-static void ide_device_shutdown(struct device *dev)
+static void ide_device_shutdown(ide_drive_t *drive)
{
- ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
-
#ifdef CONFIG_ALPHA
/* On Alpha, halt(8) doesn't actually turn the machine off,
it puts you into the sort of firmware monitor. Typically,
@@ -1054,7 +1049,7 @@ static void ide_device_shutdown(struct device *dev)
}
printk("Shutdown: %s\n", drive->name);
- dev->bus->suspend(dev, PMSG_SUSPEND);
+ drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
}
static ide_driver_t idedisk_driver = {
@@ -1062,10 +1057,10 @@ static ide_driver_t idedisk_driver = {
.owner = THIS_MODULE,
.name = "ide-disk",
.bus = &ide_bus_type,
- .probe = ide_disk_probe,
- .remove = ide_disk_remove,
- .shutdown = ide_device_shutdown,
},
+ .probe = ide_disk_probe,
+ .remove = ide_disk_remove,
+ .shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION,
.media = ide_disk,
.supports_dsc_overlap = 0,
@@ -1130,6 +1125,17 @@ static int idedisk_release(struct inode *inode, struct file *filp)
return 0;
}
+static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+ ide_drive_t *drive = idkp->drive;
+
+ geo->heads = drive->bios_head;
+ geo->sectors = drive->bios_sect;
+ geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+ return 0;
+}
+
static int idedisk_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -1164,15 +1170,15 @@ static struct block_device_operations idedisk_ops = {
.open = idedisk_open,
.release = idedisk_release,
.ioctl = idedisk_ioctl,
+ .getgeo = idedisk_getgeo,
.media_changed = idedisk_media_changed,
.revalidate_disk= idedisk_revalidate_disk
};
MODULE_DESCRIPTION("ATA DISK Driver");
-static int ide_disk_probe(struct device *dev)
+static int ide_disk_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp;
struct gendisk *g;
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index fba3fffc2d66..1f8db9ac05d1 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
idefloppy_add_settings(drive);
}
-static int ide_floppy_remove(struct device *dev)
+static void ide_floppy_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy = drive->driver_data;
struct gendisk *g = floppy->disk;
@@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev)
del_gendisk(g);
ide_floppy_put(floppy);
-
- return 0;
}
static void ide_floppy_release(struct kref *kref)
@@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = {
#endif /* CONFIG_PROC_FS */
-static int ide_floppy_probe(struct device *);
+static int ide_floppy_probe(ide_drive_t *);
static ide_driver_t idefloppy_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-floppy",
.bus = &ide_bus_type,
- .probe = ide_floppy_probe,
- .remove = ide_floppy_remove,
},
+ .probe = ide_floppy_probe,
+ .remove = ide_floppy_remove,
.version = IDEFLOPPY_VERSION,
.media = ide_floppy,
.supports_dsc_overlap = 0,
@@ -2031,6 +2028,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
return 0;
}
+static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ ide_drive_t *drive = floppy->drive;
+
+ geo->heads = drive->bios_head;
+ geo->sectors = drive->bios_sect;
+ geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+ return 0;
+}
+
static int idefloppy_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -2120,13 +2128,13 @@ static struct block_device_operations idefloppy_ops = {
.open = idefloppy_open,
.release = idefloppy_release,
.ioctl = idefloppy_ioctl,
+ .getgeo = idefloppy_getgeo,
.media_changed = idefloppy_media_changed,
.revalidate_disk= idefloppy_revalidate_disk
};
-static int ide_floppy_probe(struct device *dev)
+static int ide_floppy_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy;
struct gendisk *g;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index b5dc6df8e67d..8d50df4526a4 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -83,15 +83,12 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
if (!end_that_request_first(rq, uptodate, nr_sectors)) {
add_disk_randomness(rq->rq_disk);
-
- if (blk_rq_tagged(rq))
- blk_queue_end_tag(drive->queue, rq);
-
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
end_that_request_last(rq, uptodate);
ret = 0;
}
+
return ret;
}
EXPORT_SYMBOL(__ide_end_request);
@@ -113,6 +110,10 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
unsigned long flags;
int ret = 1;
+ /*
+ * room for locking improvements here, the calls below don't
+ * need the queue lock held at all
+ */
spin_lock_irqsave(&ide_lock, flags);
rq = HWGROUP(drive)->rq;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 02167a5b751d..e7425546b4b1 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -655,7 +655,7 @@ static void hwif_release_dev (struct device *dev)
{
ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
- up(&hwif->gendev_rel_sem);
+ complete(&hwif->gendev_rel_comp);
}
static void hwif_register (ide_hwif_t *hwif)
@@ -1325,7 +1325,7 @@ static void drive_release_dev (struct device *dev)
drive->queue = NULL;
spin_unlock_irq(&ide_lock);
- up(&drive->gendev_rel_sem);
+ complete(&drive->gendev_rel_comp);
}
/*
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index fab9b2b02504..0101d0def7c5 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
idetape_add_settings(drive);
}
-static int ide_tape_remove(struct device *dev)
+static void ide_tape_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape = drive->driver_data;
ide_unregister_subdriver(drive, tape->driver);
@@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev)
ide_unregister_region(tape->disk);
ide_tape_put(tape);
-
- return 0;
}
static void ide_tape_release(struct kref *kref)
@@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = {
#endif
-static int ide_tape_probe(struct device *);
+static int ide_tape_probe(ide_drive_t *);
static ide_driver_t idetape_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-tape",
.bus = &ide_bus_type,
- .probe = ide_tape_probe,
- .remove = ide_tape_remove,
},
+ .probe = ide_tape_probe,
+ .remove = ide_tape_remove,
.version = IDETAPE_VERSION,
.media = ide_tape,
.supports_dsc_overlap = 1,
@@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = {
.ioctl = idetape_ioctl,
};
-static int ide_tape_probe(struct device *dev)
+static int ide_tape_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape;
struct gendisk *g;
int minor;
@@ -4883,9 +4879,9 @@ 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);
+ MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
class_device_create(idetape_sysfs_class, NULL,
- MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
+ MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
S_IFCHR | S_IRUGO | S_IWUGO,
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 62ebefd6394a..9834dce4e20f 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -308,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
ide_pio_sector(drive, write);
}
-static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
unsigned int write)
{
if (rq->bio) /* fs request */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 4b524f6b3ecd..afeb02bbb722 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -222,7 +222,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
hwif->mwdma_mask = 0x80; /* disable all mwdma */
hwif->swdma_mask = 0x80; /* disable all swdma */
- sema_init(&hwif->gendev_rel_sem, 0);
+ init_completion(&hwif->gendev_rel_comp);
default_hwif_iops(hwif);
default_hwif_transport(hwif);
@@ -245,7 +245,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
drive->is_flash = 0;
drive->vdma = 0;
INIT_LIST_HEAD(&drive->list);
- sema_init(&drive->gendev_rel_sem, 0);
+ init_completion(&drive->gendev_rel_comp);
}
}
@@ -602,7 +602,7 @@ void ide_unregister(unsigned int index)
}
spin_unlock_irq(&ide_lock);
device_unregister(&drive->gendev);
- down(&drive->gendev_rel_sem);
+ wait_for_completion(&drive->gendev_rel_comp);
spin_lock_irq(&ide_lock);
}
hwif->present = 0;
@@ -662,7 +662,7 @@ void ide_unregister(unsigned int index)
/* More messed up locking ... */
spin_unlock_irq(&ide_lock);
device_unregister(&hwif->gendev);
- down(&hwif->gendev_rel_sem);
+ wait_for_completion(&hwif->gendev_rel_comp);
/*
* Remove us from the kernel's knowledge
@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
up(&ide_setting_sem);
switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry geom;
- if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
- geom.heads = drive->bios_head;
- geom.sectors = drive->bios_sect;
- geom.cylinders = (u16)drive->bios_cyl; /* truncate */
- geom.start = get_start_sect(bdev);
- if (copy_to_user(p, &geom, sizeof(struct hd_geometry)))
- return -EFAULT;
- return 0;
- }
-
case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY:
if (bdev != bdev->bd_contains)
@@ -1962,10 +1949,41 @@ static int ide_uevent(struct device *dev, char **envp, int num_envp,
return 0;
}
+static int generic_ide_probe(struct device *dev)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ return drv->probe ? drv->probe(drive) : -ENODEV;
+}
+
+static int generic_ide_remove(struct device *dev)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ if (drv->remove)
+ drv->remove(drive);
+
+ return 0;
+}
+
+static void generic_ide_shutdown(struct device *dev)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ if (dev->driver && drv->shutdown)
+ drv->shutdown(drive);
+}
+
struct bus_type ide_bus_type = {
.name = "ide",
.match = ide_bus_match,
.uevent = ide_uevent,
+ .probe = generic_ide_probe,
+ .remove = generic_ide_remove,
+ .shutdown = generic_ide_shutdown,
.dev_attrs = ide_dev_attrs,
.suspend = generic_ide_suspend,
.resume = generic_ide_resume,
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 242029c9c0ca..6439dec66881 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q)
enable_irq(HD_IRQ);
}
-static int hd_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
+static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
- struct hd_geometry g;
-
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- if (!loc)
- return -EINVAL;
- g.heads = disk->head;
- g.sectors = disk->sect;
- g.cylinders = disk->cyl;
- g.start = get_start_sect(inode->i_bdev);
- return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ struct hd_i_struct *disk = bdev->bd_disk->private_data;
+
+ geo->heads = disk->head;
+ geo->sectors = disk->sect;
+ geo->cylinders = disk->cyl;
+ return 0;
}
/*
@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
static struct block_device_operations hd_fops = {
- .ioctl = hd_ioctl,
+ .getgeo = hd_getgeo,
};
/*
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 211641a54398..fe06ebb0e5bf 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -39,7 +39,7 @@
#define PDC202_DEBUG_CABLE 0
-const static char *pdc_quirk_drives[] = {
+static const char *pdc_quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
"QUANTUM FIREBALLP KA6.4",
"QUANTUM FIREBALLP KA9.1",
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index ff2e217a8c84..0d3073f4eab4 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -69,7 +69,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
static u8 svwks_ratemask (ide_drive_t *drive)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
- u8 mode;
+ u8 mode = 0;
if (!svwks_revision)
pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 86fb1e0286d3..c85b87cb59d1 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -439,7 +439,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
hwif->speedproc = &via_set_drive;
-#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
+#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) {
hwif->irq = hwif->channel ? 15 : 14;
}
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 16b28357885b..5013b1285e22 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1271,7 +1271,7 @@ static int
pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
{
struct device_node *np = pmif->node;
- int *bidp, i;
+ int *bidp;
pmif->cable_80 = 0;
pmif->broken_dma = pmif->broken_dma_warn = 0;
@@ -1430,7 +1430,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
pmif = &pmac_ide[i];
hwif = &ide_hwifs[i];
- if (mdev->ofdev.node->n_addrs == 0) {
+ if (macio_resource_count(mdev) == 0) {
printk(KERN_WARNING "ide%d: no address for %s\n",
i, mdev->ofdev.node->full_name);
return -ENXIO;
@@ -1686,7 +1686,7 @@ pmac_ide_probe(void)
#else
macio_register_driver(&pmac_ide_macio_driver);
pci_register_driver(&pmac_ide_pci_driver);
-#endif
+#endif
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
deleted file mode 100644
index 75897509c401..000000000000
--- a/drivers/ieee1394/amdtp.c
+++ /dev/null
@@ -1,1298 +0,0 @@
-/* -*- c-basic-offset: 8 -*-
- *
- * amdtp.c - Audio and Music Data Transmission Protocol Driver
- * Copyright (C) 2001 Kristian Høgsberg
- *
- * This program is free software; you can redistribute 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.
- */
-
-/* OVERVIEW
- * --------
- *
- * The AMDTP driver is designed to expose the IEEE1394 bus as a
- * regular OSS soundcard, i.e. you can link /dev/dsp to /dev/amdtp and
- * then your favourite MP3 player, game or whatever sound program will
- * output to an IEEE1394 isochronous channel. The signal destination
- * could be a set of IEEE1394 loudspeakers (if and when such things
- * become available) or an amplifier with IEEE1394 input (like the
- * Sony STR-LSA1). The driver only handles the actual streaming, some
- * connection management is also required for this to actually work.
- * That is outside the scope of this driver, and furthermore it is not
- * really standardized yet.
- *
- * The Audio and Music Data Tranmission Protocol is available at
- *
- * http://www.1394ta.org/Download/Technology/Specifications/2001/AM20Final-jf2.pdf
- *
- *
- * TODO
- * ----
- *
- * - We should be able to change input sample format between LE/BE, as
- * we already shift the bytes around when we construct the iso
- * packets.
- *
- * - Fix DMA stop after bus reset!
- *
- * - Clean up iso context handling in ohci1394.
- *
- *
- * MAYBE TODO
- * ----------
- *
- * - Receive data for local playback or recording. Playback requires
- * soft syncing with the sound card.
- *
- * - Signal processing, i.e. receive packets, do some processing, and
- * transmit them again using the same packet structure and timestamps
- * offset by processing time.
- *
- * - Maybe make an ALSA interface, that is, create a file_ops
- * implementation that recognizes ALSA ioctls and uses defaults for
- * things that can't be controlled through ALSA (iso channel).
- *
- * Changes:
- *
- * - Audit copy_from_user in amdtp_write.
- * Daniele Bellucci <bellucda@tiscali.it>
- *
- */
-
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/wait.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/poll.h>
-#include <linux/ioctl32.h>
-#include <linux/compat.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-
-#include "hosts.h"
-#include "highlevel.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ohci1394.h"
-
-#include "amdtp.h"
-#include "cmp.h"
-
-#define FMT_AMDTP 0x10
-#define FDF_AM824 0x00
-#define FDF_SFC_32KHZ 0x00
-#define FDF_SFC_44K1HZ 0x01
-#define FDF_SFC_48KHZ 0x02
-#define FDF_SFC_88K2HZ 0x03
-#define FDF_SFC_96KHZ 0x04
-#define FDF_SFC_176K4HZ 0x05
-#define FDF_SFC_192KHZ 0x06
-
-struct descriptor_block {
- struct output_more_immediate {
- u32 control;
- u32 pad0;
- u32 skip;
- u32 pad1;
- u32 header[4];
- } header_desc;
-
- struct output_last {
- u32 control;
- u32 data_address;
- u32 branch;
- u32 status;
- } payload_desc;
-};
-
-struct packet {
- struct descriptor_block *db;
- dma_addr_t db_bus;
- struct iso_packet *payload;
- dma_addr_t payload_bus;
-};
-
-#include <asm/byteorder.h>
-
-#if defined __BIG_ENDIAN_BITFIELD
-
-struct iso_packet {
- /* First quadlet */
- unsigned int dbs : 8;
- unsigned int eoh0 : 2;
- unsigned int sid : 6;
-
- unsigned int dbc : 8;
- unsigned int fn : 2;
- unsigned int qpc : 3;
- unsigned int sph : 1;
- unsigned int reserved : 2;
-
- /* Second quadlet */
- unsigned int fdf : 8;
- unsigned int eoh1 : 2;
- unsigned int fmt : 6;
-
- unsigned int syt : 16;
-
- quadlet_t data[0];
-};
-
-#elif defined __LITTLE_ENDIAN_BITFIELD
-
-struct iso_packet {
- /* First quadlet */
- unsigned int sid : 6;
- unsigned int eoh0 : 2;
- unsigned int dbs : 8;
-
- unsigned int reserved : 2;
- unsigned int sph : 1;
- unsigned int qpc : 3;
- unsigned int fn : 2;
- unsigned int dbc : 8;
-
- /* Second quadlet */
- unsigned int fmt : 6;
- unsigned int eoh1 : 2;
- unsigned int fdf : 8;
-
- unsigned int syt : 16;
-
- quadlet_t data[0];
-};
-
-#else
-
-#error Unknown bitfield type
-
-#endif
-
-struct fraction {
- int integer;
- int numerator;
- int denominator;
-};
-
-#define PACKET_LIST_SIZE 256
-#define MAX_PACKET_LISTS 4
-
-struct packet_list {
- struct list_head link;
- int last_cycle_count;
- struct packet packets[PACKET_LIST_SIZE];
-};
-
-#define BUFFER_SIZE 128
-
-/* This implements a circular buffer for incoming samples. */
-
-struct buffer {
- size_t head, tail, length, size;
- unsigned char data[0];
-};
-
-struct stream {
- int iso_channel;
- int format;
- int rate;
- int dimension;
- int fdf;
- int mode;
- int sample_format;
- struct cmp_pcr *opcr;
-
- /* Input samples are copied here. */
- struct buffer *input;
-
- /* ISO Packer state */
- unsigned char dbc;
- struct packet_list *current_packet_list;
- int current_packet;
- struct fraction ready_samples, samples_per_cycle;
-
- /* We use these to generate control bits when we are packing
- * iec958 data.
- */
- int iec958_frame_count;
- int iec958_rate_code;
-
- /* The cycle_count and cycle_offset fields are used for the
- * synchronization timestamps (syt) in the cip header. They
- * are incremented by at least a cycle every time we put a
- * time stamp in a packet. As we don't time stamp all
- * packages, cycle_count isn't updated in every cycle, and
- * sometimes it's incremented by 2. Thus, we have
- * cycle_count2, which is simply incremented by one with each
- * packet, so we can compare it to the transmission time
- * written back in the dma programs.
- */
- atomic_t cycle_count, cycle_count2;
- struct fraction cycle_offset, ticks_per_syt_offset;
- int syt_interval;
- int stale_count;
-
- /* Theses fields control the sample output to the DMA engine.
- * The dma_packet_lists list holds packet lists currently
- * queued for dma; the head of the list is currently being
- * processed. The last program in a packet list generates an
- * interrupt, which removes the head from dma_packet_lists and
- * puts it back on the free list.
- */
- struct list_head dma_packet_lists;
- struct list_head free_packet_lists;
- wait_queue_head_t packet_list_wait;
- spinlock_t packet_list_lock;
- struct ohci1394_iso_tasklet iso_tasklet;
- struct pci_pool *descriptor_pool, *packet_pool;
-
- /* Streams at a host controller are chained through this field. */
- struct list_head link;
- struct amdtp_host *host;
-};
-
-struct amdtp_host {
- struct hpsb_host *host;
- struct ti_ohci *ohci;
- struct list_head stream_list;
- spinlock_t stream_list_lock;
-};
-
-static struct hpsb_highlevel amdtp_highlevel;
-
-
-/* FIXME: This doesn't belong here... */
-
-#define OHCI1394_CONTEXT_CYCLE_MATCH 0x80000000
-#define OHCI1394_CONTEXT_RUN 0x00008000
-#define OHCI1394_CONTEXT_WAKE 0x00001000
-#define OHCI1394_CONTEXT_DEAD 0x00000800
-#define OHCI1394_CONTEXT_ACTIVE 0x00000400
-
-static void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
- dma_addr_t first_cmd, int z, int cycle_match)
-{
- reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx);
- reg_write(ohci, OHCI1394_IsoXmitCommandPtr + ctx * 16, first_cmd | z);
- reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16, ~0);
- wmb();
- reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
- OHCI1394_CONTEXT_CYCLE_MATCH | (cycle_match << 16) |
- OHCI1394_CONTEXT_RUN);
-}
-
-static void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
-{
- reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
- OHCI1394_CONTEXT_WAKE);
-}
-
-static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
-{
- u32 control;
- int wait;
-
- reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << ctx);
- reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16,
- OHCI1394_CONTEXT_RUN);
- wmb();
-
- if (synchronous) {
- for (wait = 0; wait < 5; wait++) {
- control = reg_read(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16);
- if ((control & OHCI1394_CONTEXT_ACTIVE) == 0)
- break;
-
- schedule_timeout_interruptible(1);
- }
- }
-}
-
-/* Note: we can test if free_packet_lists is empty without aquiring
- * the packet_list_lock. The interrupt handler only adds to the free
- * list, there is no race condition between testing the list non-empty
- * and acquiring the lock.
- */
-
-static struct packet_list *stream_get_free_packet_list(struct stream *s)
-{
- struct packet_list *pl;
- unsigned long flags;
-
- if (list_empty(&s->free_packet_lists))
- return NULL;
-
- spin_lock_irqsave(&s->packet_list_lock, flags);
- pl = list_entry(s->free_packet_lists.next, struct packet_list, link);
- list_del(&pl->link);
- spin_unlock_irqrestore(&s->packet_list_lock, flags);
-
- return pl;
-}
-
-static void stream_start_dma(struct stream *s, struct packet_list *pl)
-{
- u32 syt_cycle, cycle_count, start_cycle;
-
- cycle_count = reg_read(s->host->ohci,
- OHCI1394_IsochronousCycleTimer) >> 12;
- syt_cycle = (pl->last_cycle_count - PACKET_LIST_SIZE + 1) & 0x0f;
-
- /* We program the DMA controller to start transmission at
- * least 17 cycles from now - this happens when the lower four
- * bits of cycle_count is 0x0f and syt_cycle is 0, in this
- * case the start cycle is cycle_count - 15 + 32. */
- start_cycle = (cycle_count & ~0x0f) + 32 + syt_cycle;
- if ((start_cycle & 0x1fff) >= 8000)
- start_cycle = start_cycle - 8000 + 0x2000;
-
- ohci1394_start_it_ctx(s->host->ohci, s->iso_tasklet.context,
- pl->packets[0].db_bus, 3,
- start_cycle & 0x7fff);
-}
-
-static void stream_put_dma_packet_list(struct stream *s,
- struct packet_list *pl)
-{
- unsigned long flags;
- struct packet_list *prev;
-
- /* Remember the cycle_count used for timestamping the last packet. */
- pl->last_cycle_count = atomic_read(&s->cycle_count2) - 1;
- pl->packets[PACKET_LIST_SIZE - 1].db->payload_desc.branch = 0;
-
- spin_lock_irqsave(&s->packet_list_lock, flags);
- list_add_tail(&pl->link, &s->dma_packet_lists);
- spin_unlock_irqrestore(&s->packet_list_lock, flags);
-
- prev = list_entry(pl->link.prev, struct packet_list, link);
- if (pl->link.prev != &s->dma_packet_lists) {
- struct packet *last = &prev->packets[PACKET_LIST_SIZE - 1];
- last->db->payload_desc.branch = pl->packets[0].db_bus | 3;
- last->db->header_desc.skip = pl->packets[0].db_bus | 3;
- ohci1394_wake_it_ctx(s->host->ohci, s->iso_tasklet.context);
- }
- else
- stream_start_dma(s, pl);
-}
-
-static void stream_shift_packet_lists(unsigned long l)
-{
- struct stream *s = (struct stream *) l;
- struct packet_list *pl;
- struct packet *last;
- int diff;
-
- if (list_empty(&s->dma_packet_lists)) {
- HPSB_ERR("empty dma_packet_lists in %s", __FUNCTION__);
- return;
- }
-
- /* Now that we know the list is non-empty, we can get the head
- * of the list without locking, because the process context
- * only adds to the tail.
- */
- pl = list_entry(s->dma_packet_lists.next, struct packet_list, link);
- last = &pl->packets[PACKET_LIST_SIZE - 1];
-
- /* This is weird... if we stop dma processing in the middle of
- * a packet list, the dma context immediately generates an
- * interrupt if we enable it again later. This only happens
- * when amdtp_release is interrupted while waiting for dma to
- * complete, though. Anyway, we detect this by seeing that
- * the status of the dma descriptor that we expected an
- * interrupt from is still 0.
- */
- if (last->db->payload_desc.status == 0) {
- HPSB_INFO("weird interrupt...");
- return;
- }
-
- /* If the last descriptor block does not specify a branch
- * address, we have a sample underflow.
- */
- if (last->db->payload_desc.branch == 0)
- HPSB_INFO("FIXME: sample underflow...");
-
- /* Here we check when (which cycle) the last packet was sent
- * and compare it to what the iso packer was using at the
- * time. If there is a mismatch, we adjust the cycle count in
- * the iso packer. However, there are still up to
- * MAX_PACKET_LISTS packet lists queued with bad time stamps,
- * so we disable time stamp monitoring for the next
- * MAX_PACKET_LISTS packet lists.
- */
- diff = (last->db->payload_desc.status - pl->last_cycle_count) & 0xf;
- if (diff > 0 && s->stale_count == 0) {
- atomic_add(diff, &s->cycle_count);
- atomic_add(diff, &s->cycle_count2);
- s->stale_count = MAX_PACKET_LISTS;
- }
-
- if (s->stale_count > 0)
- s->stale_count--;
-
- /* Finally, we move the packet list that was just processed
- * back to the free list, and notify any waiters.
- */
- spin_lock(&s->packet_list_lock);
- list_del(&pl->link);
- list_add_tail(&pl->link, &s->free_packet_lists);
- spin_unlock(&s->packet_list_lock);
-
- wake_up_interruptible(&s->packet_list_wait);
-}
-
-static struct packet *stream_current_packet(struct stream *s)
-{
- if (s->current_packet_list == NULL &&
- (s->current_packet_list = stream_get_free_packet_list(s)) == NULL)
- return NULL;
-
- return &s->current_packet_list->packets[s->current_packet];
-}
-
-static void stream_queue_packet(struct stream *s)
-{
- s->current_packet++;
- if (s->current_packet == PACKET_LIST_SIZE) {
- stream_put_dma_packet_list(s, s->current_packet_list);
- s->current_packet_list = NULL;
- s->current_packet = 0;
- }
-}
-
-/* Integer fractional math. When we transmit a 44k1Hz signal we must
- * send 5 41/80 samples per isochronous cycle, as these occur 8000
- * times a second. Of course, we must send an integral number of
- * samples in a packet, so we use the integer math to alternate
- * between sending 5 and 6 samples per packet.
- */
-
-static void fraction_init(struct fraction *f, int numerator, int denominator)
-{
- f->integer = numerator / denominator;
- f->numerator = numerator % denominator;
- f->denominator = denominator;
-}
-
-static __inline__ void fraction_add(struct fraction *dst,
- struct fraction *src1,
- struct fraction *src2)
-{
- /* assert: src1->denominator == src2->denominator */
-
- int sum, denom;
-
- /* We use these two local variables to allow gcc to optimize
- * the division and the modulo into only one division. */
-
- sum = src1->numerator + src2->numerator;
- denom = src1->denominator;
- dst->integer = src1->integer + src2->integer + sum / denom;
- dst->numerator = sum % denom;
- dst->denominator = denom;
-}
-
-static __inline__ void fraction_sub_int(struct fraction *dst,
- struct fraction *src, int integer)
-{
- dst->integer = src->integer - integer;
- dst->numerator = src->numerator;
- dst->denominator = src->denominator;
-}
-
-static __inline__ int fraction_floor(struct fraction *frac)
-{
- return frac->integer;
-}
-
-static __inline__ int fraction_ceil(struct fraction *frac)
-{
- return frac->integer + (frac->numerator > 0 ? 1 : 0);
-}
-
-static void packet_initialize(struct packet *p, struct packet *next)
-{
- /* Here we initialize the dma descriptor block for
- * transferring one iso packet. We use two descriptors per
- * packet: an OUTPUT_MORE_IMMMEDIATE descriptor for the
- * IEEE1394 iso packet header and an OUTPUT_LAST descriptor
- * for the payload.
- */
-
- p->db->header_desc.control =
- DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 8;
-
- if (next) {
- p->db->payload_desc.control =
- DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
- p->db->payload_desc.branch = next->db_bus | 3;
- p->db->header_desc.skip = next->db_bus | 3;
- }
- else {
- p->db->payload_desc.control =
- DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH |
- DMA_CTL_UPDATE | DMA_CTL_IRQ;
- p->db->payload_desc.branch = 0;
- p->db->header_desc.skip = 0;
- }
- p->db->payload_desc.data_address = p->payload_bus;
- p->db->payload_desc.status = 0;
-}
-
-static struct packet_list *packet_list_alloc(struct stream *s)
-{
- int i;
- struct packet_list *pl;
- struct packet *next;
-
- pl = kmalloc(sizeof *pl, SLAB_KERNEL);
- if (pl == NULL)
- return NULL;
-
- for (i = 0; i < PACKET_LIST_SIZE; i++) {
- struct packet *p = &pl->packets[i];
- p->db = pci_pool_alloc(s->descriptor_pool, SLAB_KERNEL,
- &p->db_bus);
- p->payload = pci_pool_alloc(s->packet_pool, SLAB_KERNEL,
- &p->payload_bus);
- }
-
- for (i = 0; i < PACKET_LIST_SIZE; i++) {
- if (i < PACKET_LIST_SIZE - 1)
- next = &pl->packets[i + 1];
- else
- next = NULL;
- packet_initialize(&pl->packets[i], next);
- }
-
- return pl;
-}
-
-static void packet_list_free(struct packet_list *pl, struct stream *s)
-{
- int i;
-
- for (i = 0; i < PACKET_LIST_SIZE; i++) {
- struct packet *p = &pl->packets[i];
- pci_pool_free(s->descriptor_pool, p->db, p->db_bus);
- pci_pool_free(s->packet_pool, p->payload, p->payload_bus);
- }
- kfree(pl);
-}
-
-static struct buffer *buffer_alloc(int size)
-{
- struct buffer *b;
-
- b = kmalloc(sizeof *b + size, SLAB_KERNEL);
- if (b == NULL)
- return NULL;
- b->head = 0;
- b->tail = 0;
- b->length = 0;
- b->size = size;
-
- return b;
-}
-
-static unsigned char *buffer_get_bytes(struct buffer *buffer, int size)
-{
- unsigned char *p;
-
- if (buffer->head + size > buffer->size)
- BUG();
-
- p = &buffer->data[buffer->head];
- buffer->head += size;
- if (buffer->head == buffer->size)
- buffer->head = 0;
- buffer->length -= size;
-
- return p;
-}
-
-static unsigned char *buffer_put_bytes(struct buffer *buffer,
- size_t max, size_t *actual)
-{
- size_t length;
- unsigned char *p;
-
- p = &buffer->data[buffer->tail];
- length = min(buffer->size - buffer->length, max);
- if (buffer->tail + length < buffer->size) {
- *actual = length;
- buffer->tail += length;
- }
- else {
- *actual = buffer->size - buffer->tail;
- buffer->tail = 0;
- }
-
- buffer->length += *actual;
- return p;
-}
-
-static u32 get_iec958_header_bits(struct stream *s, int sub_frame, u32 sample)
-{
- int csi, parity, shift;
- int block_start;
- u32 bits;
-
- switch (s->iec958_frame_count) {
- case 1:
- csi = s->format == AMDTP_FORMAT_IEC958_AC3;
- break;
- case 2:
- case 9:
- csi = 1;
- break;
- case 24 ... 27:
- csi = (s->iec958_rate_code >> (27 - s->iec958_frame_count)) & 0x01;
- break;
- default:
- csi = 0;
- break;
- }
-
- block_start = (s->iec958_frame_count == 0 && sub_frame == 0);
-
- /* The parity bit is the xor of the sample bits and the
- * channel status info bit. */
- for (shift = 16, parity = sample ^ csi; shift > 0; shift >>= 1)
- parity ^= (parity >> shift);
-
- bits = (block_start << 5) | /* Block start bit */
- ((sub_frame == 0) << 4) | /* Subframe bit */
- ((parity & 1) << 3) | /* Parity bit */
- (csi << 2); /* Channel status info bit */
-
- return bits;
-}
-
-static u32 get_header_bits(struct stream *s, int sub_frame, u32 sample)
-{
- switch (s->format) {
- case AMDTP_FORMAT_IEC958_PCM:
- case AMDTP_FORMAT_IEC958_AC3:
- return get_iec958_header_bits(s, sub_frame, sample);
-
- case AMDTP_FORMAT_RAW:
- return 0x40;
-
- default:
- return 0;
- }
-}
-
-static void fill_payload_le16(struct stream *s, quadlet_t *data, int nevents)
-{
- quadlet_t *event, sample, bits;
- unsigned char *p;
- int i, j;
-
- for (i = 0, event = data; i < nevents; i++) {
-
- for (j = 0; j < s->dimension; j++) {
- p = buffer_get_bytes(s->input, 2);
- sample = (p[1] << 16) | (p[0] << 8);
- bits = get_header_bits(s, j, sample);
- event[j] = cpu_to_be32((bits << 24) | sample);
- }
-
- event += s->dimension;
- if (++s->iec958_frame_count == 192)
- s->iec958_frame_count = 0;
- }
-}
-
-static void fill_packet(struct stream *s, struct packet *packet, int nevents)
-{
- int syt_index, syt, size;
- u32 control;
-
- size = (nevents * s->dimension + 2) * sizeof(quadlet_t);
-
- /* Update DMA descriptors */
- packet->db->payload_desc.status = 0;
- control = packet->db->payload_desc.control & 0xffff0000;
- packet->db->payload_desc.control = control | size;
-
- /* Fill IEEE1394 headers */
- packet->db->header_desc.header[0] =
- (IEEE1394_SPEED_100 << 16) | (0x01 << 14) |
- (s->iso_channel << 8) | (TCODE_ISO_DATA << 4);
- packet->db->header_desc.header[1] = size << 16;
-
- /* Calculate synchronization timestamp (syt). First we
- * determine syt_index, that is, the index in the packet of
- * the sample for which the timestamp is valid. */
- syt_index = (s->syt_interval - s->dbc) & (s->syt_interval - 1);
- if (syt_index < nevents) {
- syt = ((atomic_read(&s->cycle_count) << 12) |
- s->cycle_offset.integer) & 0xffff;
- fraction_add(&s->cycle_offset,
- &s->cycle_offset, &s->ticks_per_syt_offset);
-
- /* This next addition should be modulo 8000 (0x1f40),
- * but we only use the lower 4 bits of cycle_count, so
- * we don't need the modulo. */
- atomic_add(s->cycle_offset.integer / 3072, &s->cycle_count);
- s->cycle_offset.integer %= 3072;
- }
- else
- syt = 0xffff;
-
- atomic_inc(&s->cycle_count2);
-
- /* Fill cip header */
- packet->payload->eoh0 = 0;
- packet->payload->sid = s->host->host->node_id & 0x3f;
- packet->payload->dbs = s->dimension;
- packet->payload->fn = 0;
- packet->payload->qpc = 0;
- packet->payload->sph = 0;
- packet->payload->reserved = 0;
- packet->payload->dbc = s->dbc;
- packet->payload->eoh1 = 2;
- packet->payload->fmt = FMT_AMDTP;
- packet->payload->fdf = s->fdf;
- packet->payload->syt = cpu_to_be16(syt);
-
- switch (s->sample_format) {
- case AMDTP_INPUT_LE16:
- fill_payload_le16(s, packet->payload->data, nevents);
- break;
- }
-
- s->dbc += nevents;
-}
-
-static void stream_flush(struct stream *s)
-{
- struct packet *p;
- int nevents;
- struct fraction next;
-
- /* The AMDTP specifies two transmission modes: blocking and
- * non-blocking. In blocking mode you always transfer
- * syt_interval or zero samples, whereas in non-blocking mode
- * you send as many samples as you have available at transfer
- * time.
- *
- * The fraction samples_per_cycle specifies the number of
- * samples that become available per cycle. We add this to
- * the fraction ready_samples, which specifies the number of
- * leftover samples from the previous transmission. The sum,
- * stored in the fraction next, specifies the number of
- * samples available for transmission, and from this we
- * determine the number of samples to actually transmit.
- */
-
- while (1) {
- fraction_add(&next, &s->ready_samples, &s->samples_per_cycle);
- if (s->mode == AMDTP_MODE_BLOCKING) {
- if (fraction_floor(&next) >= s->syt_interval)
- nevents = s->syt_interval;
- else
- nevents = 0;
- }
- else
- nevents = fraction_floor(&next);
-
- p = stream_current_packet(s);
- if (s->input->length < nevents * s->dimension * 2 || p == NULL)
- break;
-
- fill_packet(s, p, nevents);
- stream_queue_packet(s);
-
- /* Now that we have successfully queued the packet for
- * transmission, we update the fraction ready_samples. */
- fraction_sub_int(&s->ready_samples, &next, nevents);
- }
-}
-
-static int stream_alloc_packet_lists(struct stream *s)
-{
- int max_nevents, max_packet_size, i;
-
- if (s->mode == AMDTP_MODE_BLOCKING)
- max_nevents = s->syt_interval;
- else
- max_nevents = fraction_ceil(&s->samples_per_cycle);
-
- max_packet_size = max_nevents * s->dimension * 4 + 8;
- s->packet_pool = pci_pool_create("packet pool", s->host->ohci->dev,
- max_packet_size, 0, 0);
-
- if (s->packet_pool == NULL)
- return -1;
-
- INIT_LIST_HEAD(&s->free_packet_lists);
- INIT_LIST_HEAD(&s->dma_packet_lists);
- for (i = 0; i < MAX_PACKET_LISTS; i++) {
- struct packet_list *pl = packet_list_alloc(s);
- if (pl == NULL)
- break;
- list_add_tail(&pl->link, &s->free_packet_lists);
- }
-
- return i < MAX_PACKET_LISTS ? -1 : 0;
-}
-
-static void stream_free_packet_lists(struct stream *s)
-{
- struct packet_list *packet_l, *packet_l_next;
-
- if (s->current_packet_list != NULL)
- packet_list_free(s->current_packet_list, s);
- list_for_each_entry_safe(packet_l, packet_l_next, &s->dma_packet_lists, link)
- packet_list_free(packet_l, s);
- list_for_each_entry_safe(packet_l, packet_l_next, &s->free_packet_lists, link)
- packet_list_free(packet_l, s);
- if (s->packet_pool != NULL)
- pci_pool_destroy(s->packet_pool);
-
- s->current_packet_list = NULL;
- INIT_LIST_HEAD(&s->free_packet_lists);
- INIT_LIST_HEAD(&s->dma_packet_lists);
- s->packet_pool = NULL;
-}
-
-static void plug_update(struct cmp_pcr *plug, void *data)
-{
- struct stream *s = data;
-
- HPSB_INFO("plug update: p2p_count=%d, channel=%d",
- plug->p2p_count, plug->channel);
- s->iso_channel = plug->channel;
- if (plug->p2p_count > 0) {
- struct packet_list *pl;
-
- pl = list_entry(s->dma_packet_lists.next, struct packet_list, link);
- stream_start_dma(s, pl);
- }
- else {
- ohci1394_stop_it_ctx(s->host->ohci, s->iso_tasklet.context, 0);
- }
-}
-
-static int stream_configure(struct stream *s, int cmd, struct amdtp_ioctl *cfg)
-{
- const int transfer_delay = 9000;
-
- if (cfg->format <= AMDTP_FORMAT_IEC958_AC3)
- s->format = cfg->format;
- else
- return -EINVAL;
-
- switch (cfg->rate) {
- case 32000:
- s->syt_interval = 8;
- s->fdf = FDF_SFC_32KHZ;
- s->iec958_rate_code = 0x0c;
- break;
- case 44100:
- s->syt_interval = 8;
- s->fdf = FDF_SFC_44K1HZ;
- s->iec958_rate_code = 0x00;
- break;
- case 48000:
- s->syt_interval = 8;
- s->fdf = FDF_SFC_48KHZ;
- s->iec958_rate_code = 0x04;
- break;
- case 88200:
- s->syt_interval = 16;
- s->fdf = FDF_SFC_88K2HZ;
- s->iec958_rate_code = 0x00;
- break;
- case 96000:
- s->syt_interval = 16;
- s->fdf = FDF_SFC_96KHZ;
- s->iec958_rate_code = 0x00;
- break;
- case 176400:
- s->syt_interval = 32;
- s->fdf = FDF_SFC_176K4HZ;
- s->iec958_rate_code = 0x00;
- break;
- case 192000:
- s->syt_interval = 32;
- s->fdf = FDF_SFC_192KHZ;
- s->iec958_rate_code = 0x00;
- break;
-
- default:
- return -EINVAL;
- }
-
- s->rate = cfg->rate;
- fraction_init(&s->samples_per_cycle, s->rate, 8000);
- fraction_init(&s->ready_samples, 0, 8000);
-
- /* The ticks_per_syt_offset is initialized to the number of
- * ticks between syt_interval events. The number of ticks per
- * second is 24.576e6, so the number of ticks between
- * syt_interval events is 24.576e6 * syt_interval / rate.
- */
- fraction_init(&s->ticks_per_syt_offset,
- 24576000 * s->syt_interval, s->rate);
- fraction_init(&s->cycle_offset, (transfer_delay % 3072) * s->rate, s->rate);
- atomic_set(&s->cycle_count, transfer_delay / 3072);
- atomic_set(&s->cycle_count2, 0);
-
- s->mode = cfg->mode;
- s->sample_format = AMDTP_INPUT_LE16;
-
- /* When using the AM824 raw subformat we can stream signals of
- * any dimension. The IEC958 subformat, however, only
- * supports 2 channels.
- */
- if (s->format == AMDTP_FORMAT_RAW || cfg->dimension == 2)
- s->dimension = cfg->dimension;
- else
- return -EINVAL;
-
- if (s->opcr != NULL) {
- cmp_unregister_opcr(s->host->host, s->opcr);
- s->opcr = NULL;
- }
-
- switch(cmd) {
- case AMDTP_IOC_PLUG:
- s->opcr = cmp_register_opcr(s->host->host, cfg->u.plug,
- /*payload*/ 12, plug_update, s);
- if (s->opcr == NULL)
- return -EINVAL;
- s->iso_channel = s->opcr->channel;
- break;
-
- case AMDTP_IOC_CHANNEL:
- if (cfg->u.channel >= 0 && cfg->u.channel < 64)
- s->iso_channel = cfg->u.channel;
- else
- return -EINVAL;
- break;
- }
-
- /* The ioctl settings were all valid, so we realloc the packet
- * lists to make sure the packet size is big enough.
- */
- if (s->packet_pool != NULL)
- stream_free_packet_lists(s);
-
- if (stream_alloc_packet_lists(s) < 0) {
- stream_free_packet_lists(s);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static struct stream *stream_alloc(struct amdtp_host *host)
-{
- struct stream *s;
- unsigned long flags;
-
- s = kmalloc(sizeof(struct stream), SLAB_KERNEL);
- if (s == NULL)
- return NULL;
-
- memset(s, 0, sizeof(struct stream));
- s->host = host;
-
- s->input = buffer_alloc(BUFFER_SIZE);
- if (s->input == NULL) {
- kfree(s);
- return NULL;
- }
-
- s->descriptor_pool = pci_pool_create("descriptor pool", host->ohci->dev,
- sizeof(struct descriptor_block),
- 16, 0);
-
- if (s->descriptor_pool == NULL) {
- kfree(s->input);
- kfree(s);
- return NULL;
- }
-
- INIT_LIST_HEAD(&s->free_packet_lists);
- INIT_LIST_HEAD(&s->dma_packet_lists);
-
- init_waitqueue_head(&s->packet_list_wait);
- spin_lock_init(&s->packet_list_lock);
-
- ohci1394_init_iso_tasklet(&s->iso_tasklet, OHCI_ISO_TRANSMIT,
- stream_shift_packet_lists,
- (unsigned long) s);
-
- if (ohci1394_register_iso_tasklet(host->ohci, &s->iso_tasklet) < 0) {
- pci_pool_destroy(s->descriptor_pool);
- kfree(s->input);
- kfree(s);
- return NULL;
- }
-
- spin_lock_irqsave(&host->stream_list_lock, flags);
- list_add_tail(&s->link, &host->stream_list);
- spin_unlock_irqrestore(&host->stream_list_lock, flags);
-
- return s;
-}
-
-static void stream_free(struct stream *s)
-{
- unsigned long flags;
-
- /* Stop the DMA. We wait for the dma packet list to become
- * empty and let the dma controller run out of programs. This
- * seems to be more reliable than stopping it directly, since
- * that sometimes generates an it transmit interrupt if we
- * later re-enable the context.
- */
- wait_event_interruptible(s->packet_list_wait,
- list_empty(&s->dma_packet_lists));
-
- ohci1394_stop_it_ctx(s->host->ohci, s->iso_tasklet.context, 1);
- ohci1394_unregister_iso_tasklet(s->host->ohci, &s->iso_tasklet);
-
- if (s->opcr != NULL)
- cmp_unregister_opcr(s->host->host, s->opcr);
-
- spin_lock_irqsave(&s->host->stream_list_lock, flags);
- list_del(&s->link);
- spin_unlock_irqrestore(&s->host->stream_list_lock, flags);
-
- kfree(s->input);
-
- stream_free_packet_lists(s);
- pci_pool_destroy(s->descriptor_pool);
-
- kfree(s);
-}
-
-/* File operations */
-
-static ssize_t amdtp_write(struct file *file, const char __user *buffer, size_t count,
- loff_t *offset_is_ignored)
-{
- struct stream *s = file->private_data;
- unsigned char *p;
- int i;
- size_t length;
-
- if (s->packet_pool == NULL)
- return -EBADFD;
-
- /* Fill the circular buffer from the input buffer and call the
- * iso packer when the buffer is full. The iso packer may
- * leave bytes in the buffer for two reasons: either the
- * remaining bytes wasn't enough to build a new packet, or
- * there were no free packet lists. In the first case we
- * re-fill the buffer and call the iso packer again or return
- * if we used all the data from userspace. In the second
- * case, the wait_event_interruptible will block until the irq
- * handler frees a packet list.
- */
-
- for (i = 0; i < count; i += length) {
- p = buffer_put_bytes(s->input, count - i, &length);
- if (copy_from_user(p, buffer + i, length))
- return -EFAULT;
- if (s->input->length < s->input->size)
- continue;
-
- stream_flush(s);
-
- if (s->current_packet_list != NULL)
- continue;
-
- if (file->f_flags & O_NONBLOCK)
- return i + length > 0 ? i + length : -EAGAIN;
-
- if (wait_event_interruptible(s->packet_list_wait,
- !list_empty(&s->free_packet_lists)))
- return -EINTR;
- }
-
- return count;
-}
-
-static long amdtp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct stream *s = file->private_data;
- struct amdtp_ioctl cfg;
- int err;
- lock_kernel();
- switch(cmd)
- {
- case AMDTP_IOC_PLUG:
- case AMDTP_IOC_CHANNEL:
- if (copy_from_user(&cfg, (struct amdtp_ioctl __user *) arg, sizeof cfg))
- err = -EFAULT;
- else
- err = stream_configure(s, cmd, &cfg);
- break;
-
- default:
- err = -EINVAL;
- break;
- }
- unlock_kernel();
- return err;
-}
-
-static unsigned int amdtp_poll(struct file *file, poll_table *pt)
-{
- struct stream *s = file->private_data;
-
- poll_wait(file, &s->packet_list_wait, pt);
-
- if (!list_empty(&s->free_packet_lists))
- return POLLOUT | POLLWRNORM;
- else
- return 0;
-}
-
-static int amdtp_open(struct inode *inode, struct file *file)
-{
- struct amdtp_host *host;
- int i = ieee1394_file_to_instance(file);
-
- host = hpsb_get_hostinfo_bykey(&amdtp_highlevel, i);
- if (host == NULL)
- return -ENODEV;
-
- file->private_data = stream_alloc(host);
- if (file->private_data == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-static int amdtp_release(struct inode *inode, struct file *file)
-{
- struct stream *s = file->private_data;
-
- stream_free(s);
-
- return 0;
-}
-
-static struct cdev amdtp_cdev;
-static struct file_operations amdtp_fops =
-{
- .owner = THIS_MODULE,
- .write = amdtp_write,
- .poll = amdtp_poll,
- .unlocked_ioctl = amdtp_ioctl,
- .compat_ioctl = amdtp_ioctl, /* All amdtp ioctls are compatible */
- .open = amdtp_open,
- .release = amdtp_release
-};
-
-/* IEEE1394 Subsystem functions */
-
-static void amdtp_add_host(struct hpsb_host *host)
-{
- struct amdtp_host *ah;
- int minor;
-
- if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0)
- return;
-
- ah = hpsb_create_hostinfo(&amdtp_highlevel, host, sizeof(*ah));
- if (!ah) {
- HPSB_ERR("amdtp: Unable able to alloc hostinfo");
- return;
- }
-
- ah->host = host;
- ah->ohci = host->hostdata;
-
- hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->host->id);
-
- minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->host->id;
-
- INIT_LIST_HEAD(&ah->stream_list);
- spin_lock_init(&ah->stream_list_lock);
-
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
- S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->host->id);
-}
-
-static void amdtp_remove_host(struct hpsb_host *host)
-{
- struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host);
-
- if (ah)
- devfs_remove("amdtp/%d", ah->host->id);
-
- return;
-}
-
-static struct hpsb_highlevel amdtp_highlevel = {
- .name = "amdtp",
- .add_host = amdtp_add_host,
- .remove_host = amdtp_remove_host,
-};
-
-/* Module interface */
-
-MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
-MODULE_DESCRIPTION("Driver for Audio & Music Data Transmission Protocol "
- "on OHCI boards.");
-MODULE_SUPPORTED_DEVICE("amdtp");
-MODULE_LICENSE("GPL");
-
-static int __init amdtp_init_module (void)
-{
- cdev_init(&amdtp_cdev, &amdtp_fops);
- amdtp_cdev.owner = THIS_MODULE;
- kobject_set_name(&amdtp_cdev.kobj, "amdtp");
- if (cdev_add(&amdtp_cdev, IEEE1394_AMDTP_DEV, 16)) {
- HPSB_ERR("amdtp: unable to add char device");
- return -EIO;
- }
-
- devfs_mk_dir("amdtp");
-
- hpsb_register_highlevel(&amdtp_highlevel);
-
- HPSB_INFO("Loaded AMDTP driver");
-
- return 0;
-}
-
-static void __exit amdtp_exit_module (void)
-{
- hpsb_unregister_highlevel(&amdtp_highlevel);
- devfs_remove("amdtp");
- cdev_del(&amdtp_cdev);
-
- HPSB_INFO("Unloaded AMDTP driver");
-}
-
-module_init(amdtp_init_module);
-module_exit(amdtp_exit_module);
diff --git a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h
deleted file mode 100644
index 531f28e3ab50..000000000000
--- a/drivers/ieee1394/amdtp.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- c-basic-offset: 8 -*- */
-
-#ifndef __AMDTP_H
-#define __AMDTP_H
-
-#include <asm/types.h>
-#include "ieee1394-ioctl.h"
-
-/* The userspace interface for the Audio & Music Data Transmission
- * Protocol driver is really simple. First, open /dev/amdtp, use the
- * ioctl to configure format, rate, dimension and either plug or
- * channel, then start writing samples.
- *
- * The formats supported by the driver are listed below.
- * AMDTP_FORMAT_RAW corresponds to the AM824 raw format, which can
- * carry any number of channels, so use this if you're streaming
- * multichannel audio. The AMDTP_FORMAT_IEC958_PCM corresponds to the
- * AM824 IEC958 encapsulation without the IEC958 data bit set, using
- * AMDTP_FORMAT_IEC958_AC3 will transmit the samples with the data bit
- * set, suitable for transmitting compressed AC-3 audio.
- *
- * The rate field specifies the transmission rate; supported values
- * are 32000, 44100, 48000, 88200, 96000, 176400 and 192000.
- *
- * The dimension field specifies the dimension of the signal, that is,
- * the number of audio channels. Only AMDTP_FORMAT_RAW supports
- * settings greater than 2.
- *
- * The mode field specifies which transmission mode to use. The AMDTP
- * specifies two different transmission modes: blocking and
- * non-blocking. The blocking transmission mode always send a fixed
- * number of samples, typically 8, 16 or 32. To exactly match the
- * transmission rate, the driver alternates between sending empty and
- * non-empty packets. In non-blocking mode, the driver transmits as
- * small packets as possible. For example, for a transmission rate of
- * 44100Hz, the driver should send 5 41/80 samples in every cycle, but
- * this is not possible so instead the driver alternates between
- * sending 5 and 6 samples.
- *
- * The last thing to specify is either the isochronous channel to use
- * or the output plug to connect to. If you know what channel the
- * destination device will listen on, you can specify the channel
- * directly and use the AMDTP_IOC_CHANNEL ioctl. However, if the
- * destination device chooses the channel and uses the IEC61883-1 plug
- * mechanism, you can specify an output plug to connect to. The
- * driver will pick up the channel number from the plug once the
- * destination device locks the output plug control register. In this
- * case set the plug field and use the AMDTP_IOC_PLUG ioctl.
- *
- * Having configured the interface, the driver now accepts writes of
- * regular 16 bit signed little endian samples, with the channels
- * interleaved. For example, 4 channels would look like:
- *
- * | sample 0 | sample 1 ...
- * | ch. 0 | ch. 1 | ch. 2 | ch. 3 | ch. 0 | ...
- * | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ...
- *
- */
-
-enum {
- AMDTP_FORMAT_RAW,
- AMDTP_FORMAT_IEC958_PCM,
- AMDTP_FORMAT_IEC958_AC3
-};
-
-enum {
- AMDTP_MODE_BLOCKING,
- AMDTP_MODE_NON_BLOCKING,
-};
-
-enum {
- AMDTP_INPUT_LE16,
- AMDTP_INPUT_BE16,
-};
-
-struct amdtp_ioctl {
- __u32 format;
- __u32 rate;
- __u32 dimension;
- __u32 mode;
- union { __u32 channel; __u32 plug; } u;
-};
-
-#endif /* __AMDTP_H */
diff --git a/drivers/ieee1394/cmp.c b/drivers/ieee1394/cmp.c
deleted file mode 100644
index 69aed26e83a1..000000000000
--- a/drivers/ieee1394/cmp.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/* -*- c-basic-offset: 8 -*-
- *
- * cmp.c - Connection Management Procedures
- * Copyright (C) 2001 Kristian Høgsberg
- *
- * This program is free software; you can redistribute 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.
- */
-
-/* TODO
- * ----
- *
- * - Implement IEC61883-1 output plugs and connection management.
- * This should probably be part of the general subsystem, as it could
- * be shared with dv1394.
- *
- * - Add IEC61883 unit directory when loading this module. This
- * requires a run-time changeable config rom.
- */
-
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-
-#include "hosts.h"
-#include "highlevel.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "cmp.h"
-
-struct plug {
- union {
- struct cmp_pcr pcr;
- quadlet_t quadlet;
- } u;
- void (*update)(struct cmp_pcr *plug, void *data);
- void *data;
-};
-
-struct cmp_host {
- struct hpsb_host *host;
-
- union {
- struct cmp_mpr ompr;
- quadlet_t ompr_quadlet;
- } u;
- struct plug opcr[2];
-
- union {
- struct cmp_mpr impr;
- quadlet_t impr_quadlet;
- } v;
- struct plug ipcr[2];
-};
-
-enum {
- CMP_P2P_CONNECTION,
- CMP_BC_CONNECTION
-};
-
-#define CSR_PCR_MAP 0x900
-#define CSR_PCR_MAP_END 0x9fc
-
-static struct hpsb_highlevel cmp_highlevel;
-
-static void cmp_add_host(struct hpsb_host *host);
-static void cmp_host_reset(struct hpsb_host *host);
-static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
- u64 addr, size_t length, u16 flags);
-static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
- u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags);
-
-static struct hpsb_highlevel cmp_highlevel = {
- .name = "cmp",
- .add_host = cmp_add_host,
- .host_reset = cmp_host_reset,
-};
-
-static struct hpsb_address_ops pcr_ops = {
- .read = pcr_read,
- .lock = pcr_lock,
-};
-
-
-struct cmp_pcr *
-cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
- void (*update)(struct cmp_pcr *pcr, void *data),
- void *data)
-{
- struct cmp_host *ch;
- struct plug *plug;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
-
- if (opcr_number >= ch->u.ompr.nplugs ||
- ch->opcr[opcr_number].update != NULL)
- return NULL;
-
- plug = &ch->opcr[opcr_number];
- plug->u.pcr.online = 1;
- plug->u.pcr.bcast_count = 0;
- plug->u.pcr.p2p_count = 0;
- plug->u.pcr.overhead = 0;
- plug->u.pcr.payload = payload;
- plug->update = update;
- plug->data = data;
-
- return &plug->u.pcr;
-}
-
-void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr)
-{
- struct cmp_host *ch;
- struct plug *plug;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
- plug = (struct plug *)opcr;
- if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG();
-
- plug->u.pcr.online = 0;
- plug->update = NULL;
-}
-
-static void reset_plugs(struct cmp_host *ch)
-{
- int i;
-
- ch->u.ompr.non_persistent_ext = 0xff;
- for (i = 0; i < ch->u.ompr.nplugs; i++) {
- ch->opcr[i].u.pcr.bcast_count = 0;
- ch->opcr[i].u.pcr.p2p_count = 0;
- ch->opcr[i].u.pcr.overhead = 0;
- }
-}
-
-static void cmp_add_host(struct hpsb_host *host)
-{
- struct cmp_host *ch = hpsb_create_hostinfo(&cmp_highlevel, host, sizeof (*ch));
-
- if (ch == NULL) {
- HPSB_ERR("Failed to allocate cmp_host");
- return;
- }
-
- hpsb_register_addrspace(&cmp_highlevel, host, &pcr_ops,
- CSR_REGISTER_BASE + CSR_PCR_MAP,
- CSR_REGISTER_BASE + CSR_PCR_MAP_END);
-
- ch->host = host;
- ch->u.ompr.rate = IEEE1394_SPEED_100;
- ch->u.ompr.bcast_channel_base = 63;
- ch->u.ompr.nplugs = 2;
-
- reset_plugs(ch);
-}
-
-static void cmp_host_reset(struct hpsb_host *host)
-{
- struct cmp_host *ch;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
- if (ch == NULL) {
- HPSB_ERR("cmp: Tried to reset unknown host");
- return;
- }
-
- reset_plugs(ch);
-}
-
-static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
- u64 addr, size_t length, u16 flags)
-{
- int csraddr = addr - CSR_REGISTER_BASE;
- int plug;
- struct cmp_host *ch;
-
- if (length != 4)
- return RCODE_TYPE_ERROR;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
- if (csraddr == 0x900) {
- *buf = cpu_to_be32(ch->u.ompr_quadlet);
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
- plug = (csraddr - 0x904) / 4;
- *buf = cpu_to_be32(ch->opcr[plug].u.quadlet);
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x980) {
- return RCODE_ADDRESS_ERROR;
- }
- else if (csraddr == 0x980) {
- *buf = cpu_to_be32(ch->v.impr_quadlet);
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
- plug = (csraddr - 0x984) / 4;
- *buf = cpu_to_be32(ch->ipcr[plug].u.quadlet);
- return RCODE_COMPLETE;
- }
- else
- return RCODE_ADDRESS_ERROR;
-}
-
-static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
- u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags)
-{
- int csraddr = addr - CSR_REGISTER_BASE;
- int plug;
- struct cmp_host *ch;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
-
- if (extcode != EXTCODE_COMPARE_SWAP)
- return RCODE_TYPE_ERROR;
-
- if (csraddr == 0x900) {
- /* FIXME: Ignore writes to bits 30-31 and 0-7 */
- *store = cpu_to_be32(ch->u.ompr_quadlet);
- if (arg == cpu_to_be32(ch->u.ompr_quadlet))
- ch->u.ompr_quadlet = be32_to_cpu(data);
-
- return RCODE_COMPLETE;
- }
- if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
- plug = (csraddr - 0x904) / 4;
- *store = cpu_to_be32(ch->opcr[plug].u.quadlet);
-
- if (arg == *store)
- ch->opcr[plug].u.quadlet = be32_to_cpu(data);
-
- if (be32_to_cpu(*store) != ch->opcr[plug].u.quadlet &&
- ch->opcr[plug].update != NULL)
- ch->opcr[plug].update(&ch->opcr[plug].u.pcr,
- ch->opcr[plug].data);
-
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x980) {
- return RCODE_ADDRESS_ERROR;
- }
- else if (csraddr == 0x980) {
- /* FIXME: Ignore writes to bits 24-31 and 0-7 */
- *store = cpu_to_be32(ch->u.ompr_quadlet);
- if (arg == cpu_to_be32(ch->u.ompr_quadlet))
- ch->u.ompr_quadlet = be32_to_cpu(data);
-
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
- plug = (csraddr - 0x984) / 4;
- *store = cpu_to_be32(ch->ipcr[plug].u.quadlet);
-
- if (arg == *store)
- ch->ipcr[plug].u.quadlet = be32_to_cpu(data);
-
- if (be32_to_cpu(*store) != ch->ipcr[plug].u.quadlet &&
- ch->ipcr[plug].update != NULL)
- ch->ipcr[plug].update(&ch->ipcr[plug].u.pcr,
- ch->ipcr[plug].data);
-
- return RCODE_COMPLETE;
- }
- else
- return RCODE_ADDRESS_ERROR;
-}
-
-
-/* Module interface */
-
-MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
-MODULE_DESCRIPTION("Connection Management Procedures (CMP)");
-MODULE_SUPPORTED_DEVICE("cmp");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cmp_register_opcr);
-EXPORT_SYMBOL(cmp_unregister_opcr);
-
-static int __init cmp_init_module (void)
-{
- hpsb_register_highlevel (&cmp_highlevel);
-
- HPSB_INFO("Loaded CMP driver");
-
- return 0;
-}
-
-static void __exit cmp_exit_module (void)
-{
- hpsb_unregister_highlevel(&cmp_highlevel);
-
- HPSB_INFO("Unloaded CMP driver");
-}
-
-module_init(cmp_init_module);
-module_exit(cmp_exit_module);
diff --git a/drivers/ieee1394/cmp.h b/drivers/ieee1394/cmp.h
deleted file mode 100644
index f9288bfcd494..000000000000
--- a/drivers/ieee1394/cmp.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __CMP_H
-#define __CMP_H
-
-struct cmp_mpr {
- u32 nplugs:5;
- u32 reserved:3;
- u32 persistent_ext:8;
- u32 non_persistent_ext:8;
- u32 bcast_channel_base:6;
- u32 rate:2;
-} __attribute__((packed));
-
-struct cmp_pcr {
- u32 payload:10;
- u32 overhead:4;
- u32 speed:2;
- u32 channel:6;
- u32 reserved:2;
- u32 p2p_count:6;
- u32 bcast_count:1;
- u32 online:1;
-} __attribute__((packed));
-
-struct cmp_pcr *cmp_register_opcr(struct hpsb_host *host, int plug,
- int payload,
- void (*update)(struct cmp_pcr *plug,
- void *data),
- void *data);
-void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *plug);
-
-#endif /* __CMP_H */
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 196db7439272..efeaa944bd0a 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -108,7 +108,6 @@
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/cdev.h>
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 608479b2df14..39fb88309e8e 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -48,7 +48,6 @@
#include <linux/vmalloc.h>
#include <linux/timex.h>
#include <linux/mm.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/cdev.h>
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 02110e00d145..2514de3480d8 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -308,10 +308,11 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
{
unsigned long flags;
int ret;
+ static int next_id;
do {
spin_lock_irqsave(&cm.lock, flags);
- ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1,
+ ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_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) );
@@ -684,6 +685,13 @@ retest:
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
break;
case IB_CM_REQ_SENT:
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
+ spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
+ &cm_id_priv->av.port->cm_dev->ca_guid,
+ sizeof cm_id_priv->av.port->cm_dev->ca_guid,
+ NULL, 0);
+ break;
case IB_CM_MRA_REQ_RCVD:
case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD:
@@ -694,10 +702,8 @@ retest:
case IB_CM_REP_RCVD:
case IB_CM_MRA_REP_SENT:
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
- &cm_id_priv->av.port->cm_dev->ca_guid,
- sizeof cm_id_priv->av.port->cm_dev->ca_guid,
- NULL, 0);
+ ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
+ NULL, 0, NULL, 0);
break;
case IB_CM_ESTABLISHED:
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@@ -850,7 +856,7 @@ static void cm_format_req(struct cm_req_msg *req_msg,
param->private_data_len);
}
-static inline int cm_validate_req_param(struct ib_cm_req_param *param)
+static int cm_validate_req_param(struct ib_cm_req_param *param)
{
/* peer-to-peer not supported */
if (param->peer_to_peer)
@@ -999,7 +1005,7 @@ static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
(be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn))));
}
-static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg,
+static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
struct ib_sa_path_rec *primary_path,
struct ib_sa_path_rec *alt_path)
{
@@ -3157,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);
-static __be64 cm_get_ca_guid(struct ib_device *device)
-{
- struct ib_device_attr *device_attr;
- __be64 guid;
- int ret;
-
- device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
- if (!device_attr)
- return 0;
-
- ret = ib_query_device(device, device_attr);
- guid = ret ? 0 : device_attr->node_guid;
- kfree(device_attr);
- return guid;
-}
-
static void cm_add_one(struct ib_device *device)
{
struct cm_device *cm_dev;
@@ -3194,9 +3184,7 @@ static void cm_add_one(struct ib_device *device)
return;
cm_dev->device = device;
- cm_dev->ca_guid = cm_get_ca_guid(device);
- if (!cm_dev->ca_guid)
- goto error1;
+ cm_dev->ca_guid = device->node_guid;
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= device->phys_port_cnt; i++) {
@@ -3211,11 +3199,11 @@ static void cm_add_one(struct ib_device *device)
cm_recv_handler,
port);
if (IS_ERR(port->mad_agent))
- goto error2;
+ goto error1;
ret = ib_modify_port(device, i, 0, &port_modify);
if (ret)
- goto error3;
+ goto error2;
}
ib_set_client_data(device, &cm_client, cm_dev);
@@ -3224,9 +3212,9 @@ static void cm_add_one(struct ib_device *device)
write_unlock_irqrestore(&cm.device_lock, flags);
return;
-error3:
- ib_unregister_mad_agent(port->mad_agent);
error2:
+ ib_unregister_mad_agent(port->mad_agent);
+error1:
port_modify.set_port_cap_mask = 0;
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) {
@@ -3234,7 +3222,6 @@ error2:
ib_modify_port(device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
}
-error1:
kfree(cm_dev);
}
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index e169e798354b..b2f3cb91d9bc 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -38,8 +38,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include "core_priv.h"
@@ -57,13 +56,13 @@ static LIST_HEAD(device_list);
static LIST_HEAD(client_list);
/*
- * device_sem protects access to both device_list and client_list.
+ * device_mutex protects access to both device_list and client_list.
* There's no real point to using multiple locks or something fancier
* like an rwsem: we always access both lists, and we're always
* modifying one list or the other list. In any case this is not a
* hot path so there's no point in trying to optimize.
*/
-static DECLARE_MUTEX(device_sem);
+static DEFINE_MUTEX(device_mutex);
static int ib_device_check_mandatory(struct ib_device *device)
{
@@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device)
{
int ret;
- down(&device_sem);
+ mutex_lock(&device_mutex);
if (strchr(device->name, '%')) {
ret = alloc_name(device->name);
@@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device)
}
out:
- up(&device_sem);
+ mutex_unlock(&device_mutex);
return ret;
}
EXPORT_SYMBOL(ib_register_device);
@@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device)
struct ib_client_data *context, *tmp;
unsigned long flags;
- down(&device_sem);
+ mutex_lock(&device_mutex);
list_for_each_entry_reverse(client, &client_list, list)
if (client->remove)
@@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device)
list_del(&device->core_list);
- up(&device_sem);
+ mutex_unlock(&device_mutex);
spin_lock_irqsave(&device->client_data_lock, flags);
list_for_each_entry_safe(context, tmp, &device->client_data_list, list)
@@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client)
{
struct ib_device *device;
- down(&device_sem);
+ mutex_lock(&device_mutex);
list_add_tail(&client->list, &client_list);
list_for_each_entry(device, &device_list, core_list)
if (client->add && !add_client_context(device, client))
client->add(device);
- up(&device_sem);
+ mutex_unlock(&device_mutex);
return 0;
}
@@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client)
struct ib_device *device;
unsigned long flags;
- down(&device_sem);
+ mutex_lock(&device_mutex);
list_for_each_entry(device, &device_list, core_list) {
if (client->remove)
@@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client)
}
list_del(&client->list);
- up(&device_sem);
+ mutex_unlock(&device_mutex);
}
EXPORT_SYMBOL(ib_unregister_client);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 1f1743c5c9a3..5982d687a000 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -445,13 +445,7 @@ static int ib_device_uevent(struct class_device *cdev, char **envp,
return -ENOMEM;
/*
- * It might be nice to pass the node GUID with the event, but
- * right now the only way to get it is to query the device
- * provider, and this can crash during device removal because
- * we are will be running after driver removal has started.
- * We could add a node_guid field to struct ib_device, or we
- * could just let userspace read the node GUID from sysfs when
- * devices are added.
+ * It would be nice to pass the node GUID with the event...
*/
envp[i] = NULL;
@@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
static ssize_t show_node_guid(struct class_device *cdev, char *buf)
{
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
- 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(((__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]));
+ be16_to_cpu(((__be16 *) &dev->node_guid)[0]),
+ be16_to_cpu(((__be16 *) &dev->node_guid)[1]),
+ be16_to_cpu(((__be16 *) &dev->node_guid)[2]),
+ be16_to_cpu(((__be16 *) &dev->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 6e15787d1de1..e95c4293a496 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -42,6 +42,7 @@
#include <linux/mount.h>
#include <linux/cdev.h>
#include <linux/idr.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -113,7 +114,7 @@ static struct ib_client ucm_client = {
.remove = ib_ucm_remove_one
};
-static DECLARE_MUTEX(ctx_id_mutex);
+static DEFINE_MUTEX(ctx_id_mutex);
static DEFINE_IDR(ctx_id_table);
static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES);
@@ -121,7 +122,7 @@ 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);
+ mutex_lock(&ctx_id_mutex);
ctx = idr_find(&ctx_id_table, id);
if (!ctx)
ctx = ERR_PTR(-ENOENT);
@@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
ctx = ERR_PTR(-EINVAL);
else
atomic_inc(&ctx->ref);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
return ctx;
}
@@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
if (!result)
goto error;
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
} while (result == -EAGAIN);
if (result)
@@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
err2:
ib_destroy_cm_id(ctx->cm_id);
err1:
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
idr_remove(&ctx_id_table, ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
kfree(ctx);
return result;
}
@@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
ctx = idr_find(&ctx_id_table, cmd.id);
if (!ctx)
ctx = ERR_PTR(-ENOENT);
@@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
ctx = ERR_PTR(-EINVAL);
else
idr_remove(&ctx_id_table, ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
struct ib_ucm_context, file_list);
up(&file->mutex);
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
idr_remove(&ctx_id_table, ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
ib_destroy_cm_id(ctx->cm_id);
ib_ucm_cleanup_events(ctx);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index eb7f52537ccc..c908de8db5a9 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -197,8 +197,8 @@ static void send_handler(struct ib_mad_agent *agent,
memcpy(timeout->mad.data, packet->mad.data,
sizeof (struct ib_mad_hdr));
- if (!queue_packet(file, agent, timeout))
- return;
+ if (queue_packet(file, agent, timeout))
+ kfree(timeout);
}
out:
kfree(packet);
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 7114e3fbab00..f7eecbc6af6c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -41,6 +41,7 @@
#include <linux/kref.h>
#include <linux/idr.h>
+#include <linux/mutex.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
@@ -88,7 +89,7 @@ struct ib_uverbs_event_file {
struct ib_uverbs_file {
struct kref ref;
- struct semaphore mutex;
+ struct mutex mutex;
struct ib_uverbs_device *device;
struct ib_ucontext *ucontext;
struct ib_event_handler event_handler;
@@ -131,7 +132,7 @@ struct ib_ucq_object {
u32 async_events_reported;
};
-extern struct semaphore ib_uverbs_idr_mutex;
+extern struct mutex ib_uverbs_idr_mutex;
extern struct idr ib_uverbs_pd_idr;
extern struct idr ib_uverbs_mr_idr;
extern struct idr ib_uverbs_mw_idr;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a57d021d435a..407b6284d7d5 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&file->mutex);
+ mutex_lock(&file->mutex);
if (file->ucontext) {
ret = -EINVAL;
@@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
fd_install(resp.async_fd, filp);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
return in_len;
@@ -131,7 +131,7 @@ err_free:
ibdev->dealloc_ucontext(ucontext);
err:
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
return ret;
}
@@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
memset(&resp, 0, sizeof resp);
resp.fw_ver = attr.fw_ver;
- resp.node_guid = attr.node_guid;
+ resp.node_guid = file->device->ib_dev->node_guid;
resp.sys_image_guid = attr.sys_image_guid;
resp.max_mr_size = attr.max_mr_size;
resp.page_size_cap = attr.page_size_cap;
@@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
pd->uobject = uobj;
atomic_set(&pd->usecnt, 0);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
retry:
if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
@@ -314,11 +314,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -326,7 +326,7 @@ err_idr:
idr_remove(&ib_uverbs_pd_idr, uobj->id);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
ib_dealloc_pd(pd);
err:
@@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
if (!pd || pd->uobject->context != file->ucontext)
@@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
kfree(uobj);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
obj->umem.virt_base = cmd.hca_va;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
if (!pd || pd->uobject->context != file->ucontext) {
@@ -476,11 +476,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -489,9 +489,10 @@ err_idr:
err_unreg:
ib_dereg_mr(mr);
+ atomic_dec(&pd->usecnt);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
ib_umem_release(file->device->ib_dev, &obj->umem);
@@ -512,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
if (!mr || mr->uobject->context != file->ucontext)
@@ -526,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&memobj->uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_umem_release(file->device->ib_dev, &memobj->umem);
kfree(memobj);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -593,13 +594,18 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
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;
+ if (cmd.comp_channel >= 0) {
+ ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
+ if (!ev_file) {
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
uobj->uobject.user_handle = cmd.user_handle;
uobj->uobject.context = file->ucontext;
uobj->uverbs_file = file;
@@ -622,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
cq->cq_context = ev_file;
atomic_set(&cq->usecnt, 0);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
retry:
if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
@@ -647,11 +653,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -659,10 +665,12 @@ err_idr:
idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
ib_destroy_cq(cq);
err:
+ if (ev_file)
+ ib_uverbs_release_ucq(file, ev_file, uobj);
kfree(uobj);
return ret;
}
@@ -693,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
goto out_wc;
}
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext) {
ret = -EINVAL;
@@ -723,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(resp);
out_wc:
@@ -742,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&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);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret;
}
@@ -771,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
memset(&resp, 0, sizeof resp);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext)
@@ -787,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_uverbs_release_ucq(file, ev_file, uobj);
@@ -803,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -837,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
@@ -922,11 +930,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -935,9 +943,14 @@ err_idr:
err_destroy:
ib_destroy_qp(qp);
+ atomic_dec(&pd->usecnt);
+ atomic_dec(&attr.send_cq->usecnt);
+ atomic_dec(&attr.recv_cq->usecnt);
+ if (attr.srq)
+ atomic_dec(&attr.srq->usecnt);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(uobj);
return ret;
@@ -959,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
if (!attr)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext) {
@@ -1020,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
ret = in_len;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(attr);
return ret;
@@ -1041,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
memset(&resp, 0, sizeof resp);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1060,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->uevent.uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_uverbs_release_uevent(file, &uobj->uevent);
@@ -1075,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1106,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
if (!user_wr)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1211,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
while (wr) {
next = wr->next;
@@ -1328,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
if (IS_ERR(wr))
return PTR_ERR(wr);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1349,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
while (wr) {
next = wr->next;
@@ -1379,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
if (IS_ERR(wr))
return PTR_ERR(wr);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
if (!srq || srq->uobject->context != file->ucontext)
@@ -1400,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
while (wr) {
next = wr->next;
@@ -1433,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
if (!pd || pd->uobject->context != file->ucontext) {
@@ -1448,6 +1461,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
attr.sl = cmd.attr.sl;
attr.src_path_bits = cmd.attr.src_path_bits;
attr.static_rate = cmd.attr.static_rate;
+ attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0;
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;
@@ -1484,11 +1498,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->ah_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -1499,7 +1513,7 @@ err_destroy:
ib_destroy_ah(ah);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(uobj);
return ret;
@@ -1516,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
if (!ah || ah->uobject->context != file->ucontext)
@@ -1530,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
kfree(uobj);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1555,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1588,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
kfree(mcast);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1606,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1627,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
}
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1659,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
@@ -1716,11 +1730,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -1729,9 +1743,10 @@ err_idr:
err_destroy:
ib_destroy_srq(srq);
+ atomic_dec(&pd->usecnt);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(uobj);
return ret;
@@ -1749,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
if (!srq || srq->uobject->context != file->ucontext) {
@@ -1763,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1781,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
memset(&resp, 0, sizeof resp);
@@ -1797,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_uverbs_release_uevent(file, uobj);
@@ -1812,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&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 81737bd6faea..96ea79b63df7 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -66,7 +66,7 @@ enum {
static struct class *uverbs_class;
-DECLARE_MUTEX(ib_uverbs_idr_mutex);
+DEFINE_MUTEX(ib_uverbs_idr_mutex);
DEFINE_IDR(ib_uverbs_pd_idr);
DEFINE_IDR(ib_uverbs_mr_idr);
DEFINE_IDR(ib_uverbs_mw_idr);
@@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
if (!context)
return 0;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
@@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uobj);
}
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return context->device->dealloc_ucontext(context);
}
@@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
file->ucontext = NULL;
file->async_file = NULL;
kref_init(&file->ref);
- init_MUTEX(&file->mutex);
+ mutex_init(&file->mutex);
filp->private_data = file;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 4c15e112736c..c857361be449 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -107,9 +107,9 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
if (wc->wc_flags & IB_WC_GRH) {
ah_attr.ah_flags = IB_AH_GRH;
- ah_attr.grh.dgid = grh->dgid;
+ ah_attr.grh.dgid = grh->sgid;
- ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num,
+ ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num,
&gid_index);
if (ret)
return ERR_PTR(ret);
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 22fdc446f25c..a14eed08a0fc 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah)
return 0;
}
+int mthca_ah_grh_present(struct mthca_ah *ah)
+{
+ return !!(ah->av->g_slid & 0x80);
+}
+
int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
struct ib_ud_header *header)
{
@@ -172,8 +177,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 = cpu_to_be16(ah->av->g_slid & 0x7f);
- if (ah->av->g_slid & 0x80) {
- header->grh_present = 1;
+ if (mthca_ah_grh_present(ah)) {
header->grh.traffic_class =
(be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff;
header->grh.flow_label =
@@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
&header->grh.source_gid);
memcpy(header->grh.destination_gid.raw,
ah->av->dgid, 16);
- } else {
- header->grh_present = 0;
}
return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 9ed34587fc5c..be1791be627b 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -606,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) {
+ for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) {
if (virt != -1) {
pages[nent * 2] = cpu_to_be64(virt);
virt += 1 << lg;
@@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
* system pages needed.
*/
dev->fw.arbel.fw_pages =
- (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >>
- (PAGE_SHIFT - 12);
+ ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >>
+ (PAGE_SHIFT - 12);
mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n",
(unsigned long long) dev->fw.arbel.clr_int_base,
@@ -937,10 +937,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
if (err)
goto out;
- MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
- 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) - 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);
@@ -1056,6 +1052,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
if (mthca_is_memfree(dev)) {
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
+ dev_lim->max_srq_sz = 1 << field;
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
+ dev_lim->max_qp_sz = 1 << field;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET);
dev_lim->hca.arbel.resize_srq = field & 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET);
@@ -1087,6 +1087,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
mthca_dbg(dev, "Max ICM size %lld MB\n",
(unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20);
} else {
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
+ 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) - 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET);
dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f);
dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE;
@@ -1441,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
* pages needed.
*/
*aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12);
+ *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12);
return 0;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 4a8adcef2079..96f1a86bf049 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -128,12 +128,12 @@ struct mthca_err_cqe {
__be32 my_qpn;
u32 reserved1[3];
u8 syndrome;
- u8 reserved2;
+ u8 vendor_err;
__be16 db_cnt;
- u32 reserved3;
+ u32 reserved2;
__be32 wqe;
u8 opcode;
- u8 reserved4[2];
+ u8 reserved3[2];
u8 owner;
};
@@ -253,6 +253,15 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
wake_up(&cq->wait);
}
+static inline int is_recv_cqe(struct mthca_cqe *cqe)
+{
+ if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
+ MTHCA_ERROR_CQE_OPCODE_MASK)
+ return !(cqe->opcode & 0x01);
+ else
+ return !(cqe->is_send & 0x80);
+}
+
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
struct mthca_srq *srq)
{
@@ -296,7 +305,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
while ((int) --prod_index - (int) cq->cons_index >= 0) {
cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
if (cqe->my_qpn == cpu_to_be32(qpn)) {
- if (srq)
+ if (srq && is_recv_cqe(cqe))
mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
++nfreed;
} else if (nfreed)
@@ -333,8 +342,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
}
/*
- * For completions in error, only work request ID, status (and
- * freed resource count for RD) have to be set.
+ * For completions in error, only work request ID, status, vendor error
+ * (and freed resource count for RD) have to be set.
*/
switch (cqe->syndrome) {
case SYNDROME_LOCAL_LENGTH_ERR:
@@ -396,6 +405,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
break;
}
+ entry->vendor_err = cqe->vendor_err;
+
/*
* 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.
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 497ff794ef6a..a104ab041ea3 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -43,6 +43,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/timer.h>
#include <asm/semaphore.h>
#include "mthca_provider.h"
@@ -519,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev,
int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah);
int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
struct ib_ud_header *header);
+int mthca_ah_grh_present(struct mthca_ah *ah);
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 34d68e5a72d8..2eabb27804cd 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -45,6 +45,7 @@
enum {
MTHCA_NUM_ASYNC_EQE = 0x80,
MTHCA_NUM_CMD_EQE = 0x80,
+ MTHCA_NUM_SPARE_EQE = 0x80,
MTHCA_EQ_ENTRY_SIZE = 0x20
};
@@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
{
struct mthca_eqe *eqe;
int disarm_cqn;
- int eqes_found = 0;
+ int eqes_found = 0;
+ int set_ci = 0;
while ((eqe = next_eqe_sw(eq))) {
- int set_ci = 0;
-
/*
* Make sure we read EQ entry contents after we've
* checked the ownership bit.
@@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
be16_to_cpu(eqe->event.cmd.token),
eqe->event.cmd.status,
be64_to_cpu(eqe->event.cmd.out_param));
- /*
- * cmd_event() may add more commands.
- * The card will think the queue has overflowed if
- * we don't tell it we've been processing events.
- */
- set_ci = 1;
break;
case MTHCA_EVENT_TYPE_PORT_CHANGE:
@@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
set_eqe_hw(eqe);
++eq->cons_index;
eqes_found = 1;
+ ++set_ci;
- if (unlikely(set_ci)) {
+ /*
+ * The HCA will think the queue has overflowed if we
+ * don't tell it we've been processing events. We
+ * create our EQs with MTHCA_NUM_SPARE_EQE extra
+ * entries, so we must update our consumer index at
+ * least that often.
+ */
+ if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) {
/*
* Conditional on hca_type is OK here because
* this is a rare case, not the fast path.
@@ -484,8 +486,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
u8 intr,
struct mthca_eq *eq)
{
- int npages = (nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
- PAGE_SIZE;
+ int npages;
u64 *dma_list = NULL;
dma_addr_t t;
struct mthca_mailbox *mailbox;
@@ -496,6 +497,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
eq->dev = dev;
eq->nent = roundup_pow_of_two(max(nent, 2));
+ npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE;
eq->page_list = kmalloc(npages * sizeof *eq->page_list,
GFP_KERNEL);
@@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
128 : dev->eq_table.inta_pin;
- err = mthca_create_eq(dev, dev->limits.num_cqs,
+ err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
&dev->eq_table.eq[MTHCA_EQ_COMP]);
if (err)
goto err_out_unmap;
- err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE,
+ err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
&dev->eq_table.eq[MTHCA_EQ_ASYNC]);
if (err)
goto err_out_comp;
- err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE,
+ err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr,
&dev->eq_table.eq[MTHCA_EQ_CMD]);
if (err)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 6f94b25f3acd..8b00d9a0f6f4 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -261,6 +261,10 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
}
err = mthca_dev_lim(mdev, &dev_lim);
+ if (err) {
+ mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ goto err_disable;
+ }
profile = default_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 2fc449da418d..77bc6c746f43 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -111,7 +111,8 @@ static int find_mgm(struct mthca_dev *dev,
goto out;
if (status) {
mthca_err(dev, "READ_MGM returned status %02x\n", status);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
if (!memcmp(mgm->gid, zero_gid, 16)) {
@@ -126,7 +127,7 @@ static int find_mgm(struct mthca_dev *dev,
goto out;
*prev = *index;
- *index = be32_to_cpu(mgm->next_gid_index) >> 5;
+ *index = be32_to_cpu(mgm->next_gid_index) >> 6;
} while (*index);
*index = -1;
@@ -153,8 +154,10 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem))
- return -EINTR;
+ if (down_interruptible(&dev->mcg_table.sem)) {
+ err = -EINTR;
+ goto err_sem;
+ }
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
@@ -181,9 +184,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
-
+ memset(mgm, 0, sizeof *mgm);
memcpy(mgm->gid, gid->raw, 16);
- mgm->next_gid_index = 0;
}
for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
@@ -209,6 +211,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (status) {
mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
err = -EINVAL;
+ goto out;
}
if (!link)
@@ -223,7 +226,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- mgm->next_gid_index = cpu_to_be32(index << 5);
+ mgm->next_gid_index = cpu_to_be32(index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
@@ -234,7 +237,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
}
out:
+ if (err && link && index != -1) {
+ BUG_ON(index < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, index);
+ }
up(&dev->mcg_table.sem);
+ err_sem:
mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -255,8 +263,10 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem))
- return -EINTR;
+ if (down_interruptible(&dev->mcg_table.sem)) {
+ err = -EINTR;
+ goto err_sem;
+ }
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
@@ -305,13 +315,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (i != 1)
goto out;
- goto out;
-
if (prev == -1) {
/* Remove entry from MGM */
- if (be32_to_cpu(mgm->next_gid_index) >> 5) {
- err = mthca_READ_MGM(dev,
- be32_to_cpu(mgm->next_gid_index) >> 5,
+ int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
+ if (amgm_index_to_free) {
+ err = mthca_READ_MGM(dev, amgm_index_to_free,
mailbox, &status);
if (err)
goto out;
@@ -332,9 +340,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
+ if (amgm_index_to_free) {
+ BUG_ON(amgm_index_to_free < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, amgm_index_to_free);
+ }
} else {
/* Remove entry from AMGM */
- index = be32_to_cpu(mgm->next_gid_index) >> 5;
+ int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
err = mthca_READ_MGM(dev, prev, mailbox, &status);
if (err)
goto out;
@@ -344,7 +356,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- mgm->next_gid_index = cpu_to_be32(index << 5);
+ mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
@@ -354,10 +366,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
+ BUG_ON(index < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, index);
}
out:
up(&dev->mcg_table.sem);
+ err_sem:
mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -365,11 +380,12 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
{
int err;
+ int table_size = dev->limits.num_mgms + dev->limits.num_amgms;
err = mthca_alloc_init(&dev->mcg_table.alloc,
- dev->limits.num_amgms,
- dev->limits.num_amgms - 1,
- 0);
+ table_size,
+ table_size - 1,
+ dev->limits.num_mgms);
if (err)
return err;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index d72fe95cba08..9fb985a016e9 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -233,7 +233,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj)
for (i = 0; i < chunk->npages; ++i) {
if (chunk->mem[i].length >= offset) {
page = chunk->mem[i].page;
- break;
+ goto out;
}
offset -= chunk->mem[i].length;
}
@@ -485,6 +485,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
put_page(db_tab->page[i].mem.page);
}
}
+
+ kfree(db_tab);
}
int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 4cc7e2846df1..484a7e6b7f8c 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -33,7 +33,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
- * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $
+ * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $
*/
#include <rdma/ib_smi.h>
@@ -45,6 +45,14 @@
#include "mthca_user.h"
#include "mthca_memfree.h"
+static void init_query_mad(struct ib_smp *mad)
+{
+ mad->base_version = 1;
+ mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+ mad->class_version = 1;
+ mad->method = IB_MGMT_METHOD_GET;
+}
+
static int mthca_query_device(struct ib_device *ibdev,
struct ib_device_attr *props)
{
@@ -55,7 +63,7 @@ static int mthca_query_device(struct ib_device *ibdev,
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
goto out;
@@ -64,12 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev,
props->fw_ver = mdev->fw_ver;
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
err = mthca_MAD_IFC(mdev, 1, 1,
1, NULL, NULL, in_mad, out_mad,
@@ -87,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev,
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->page_size_cap = mdev->limits.page_size_cap;
@@ -128,20 +131,16 @@ static int mthca_query_port(struct ib_device *ibdev,
int err = -ENOMEM;
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
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;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
- in_mad->attr_mod = cpu_to_be32(port);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
+ in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -220,18 +219,14 @@ static int mthca_query_pkey(struct ib_device *ibdev,
int err = -ENOMEM;
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
goto out;
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
- in_mad->attr_mod = cpu_to_be32(index / 32);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
+ in_mad->attr_mod = cpu_to_be32(index / 32);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -259,18 +254,14 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
int err = -ENOMEM;
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
goto out;
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
- in_mad->attr_mod = cpu_to_be32(port);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
+ in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -284,13 +275,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
memcpy(gid->raw, out_mad->data + 8, 8);
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
- in_mad->attr_mod = cpu_to_be32(index / 8);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
+ in_mad->attr_mod = cpu_to_be32(index / 8);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -458,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
if (pd->uobject) {
context = to_mucontext(pd->uobject->context);
- if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
- return ERR_PTR(-EFAULT);
+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
+ err = -EFAULT;
+ goto err_free;
+ }
err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
context->db_tab, ucmd.db_index,
@@ -535,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
if (pd->uobject) {
context = to_mucontext(pd->uobject->context);
- if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
+ kfree(qp);
return ERR_PTR(-EFAULT);
+ }
err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
context->db_tab,
@@ -783,24 +774,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd,
if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK))
return ERR_PTR(-EINVAL);
- if (num_phys_buf > 1 &&
- ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK))
- return ERR_PTR(-EINVAL);
-
mask = 0;
total_size = 0;
for (i = 0; i < num_phys_buf; ++i) {
- if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
- return ERR_PTR(-EINVAL);
- if (i != 0 && i != num_phys_buf - 1 &&
- (buffer_list[i].size & ~PAGE_MASK))
- return ERR_PTR(-EINVAL);
+ if (i != 0)
+ mask |= buffer_list[i].addr;
+ if (i != num_phys_buf - 1)
+ mask |= buffer_list[i].addr + buffer_list[i].size;
total_size += buffer_list[i].size;
- if (i > 0)
- mask |= buffer_list[i].addr;
}
+ if (mask & ~PAGE_MASK)
+ return ERR_PTR(-EINVAL);
+
/* Find largest page shift we can use to cover buffers */
for (shift = PAGE_SHIFT; shift < 31; ++shift)
if (num_phys_buf > 1) {
@@ -1070,11 +1057,48 @@ static struct class_device_attribute *mthca_class_attributes[] = {
&class_device_attr_board_id
};
+static int mthca_init_node_data(struct mthca_dev *dev)
+{
+ struct ib_smp *in_mad = NULL;
+ struct ib_smp *out_mad = NULL;
+ int err = -ENOMEM;
+ u8 status;
+
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
+ out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
+ if (!in_mad || !out_mad)
+ goto out;
+
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
+
+ err = mthca_MAD_IFC(dev, 1, 1,
+ 1, NULL, NULL, in_mad, out_mad,
+ &status);
+ if (err)
+ goto out;
+ if (status) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
+
+out:
+ kfree(in_mad);
+ kfree(out_mad);
+ return err;
+}
+
int mthca_register_device(struct mthca_dev *dev)
{
int ret;
int i;
+ ret = mthca_init_node_data(dev);
+ if (ret)
+ return ret;
+
strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
dev->ib_dev.owner = THIS_MODULE;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 7450550db736..fba608ed7df2 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -383,12 +383,10 @@ static const struct {
[UC] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX |
IB_QP_PATH_MIG_STATE),
[RC] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
[MLX] = (IB_QP_CUR_STATE |
@@ -476,9 +474,8 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = IB_QP_CUR_STATE,
- [RC] = (IB_QP_CUR_STATE |
- IB_QP_MIN_RNR_TIMER),
+ [UC] = (IB_QP_CUR_STATE |
+ IB_QP_ACCESS_FLAGS),
[MLX] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
}
@@ -522,6 +519,55 @@ static void init_port(struct mthca_dev *dev, int port)
mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
}
+static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr,
+ int attr_mask)
+{
+ u8 dest_rd_atomic;
+ u32 access_flags;
+ u32 hw_access_flags = 0;
+
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+ dest_rd_atomic = attr->max_dest_rd_atomic;
+ else
+ dest_rd_atomic = qp->resp_depth;
+
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ access_flags = attr->qp_access_flags;
+ else
+ access_flags = qp->atomic_rd_en;
+
+ if (!dest_rd_atomic)
+ access_flags &= IB_ACCESS_REMOTE_WRITE;
+
+ if (access_flags & IB_ACCESS_REMOTE_READ)
+ hw_access_flags |= MTHCA_QP_BIT_RRE;
+ if (access_flags & IB_ACCESS_REMOTE_ATOMIC)
+ hw_access_flags |= MTHCA_QP_BIT_RAE;
+ if (access_flags & IB_ACCESS_REMOTE_WRITE)
+ hw_access_flags |= MTHCA_QP_BIT_RWE;
+
+ return cpu_to_be32(hw_access_flags);
+}
+
+static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path)
+{
+ path->g_mylmc = ah->src_path_bits & 0x7f;
+ path->rlid = cpu_to_be16(ah->dlid);
+ path->static_rate = !!ah->static_rate;
+
+ if (ah->ah_flags & IB_AH_GRH) {
+ path->g_mylmc |= 1 << 7;
+ path->mgid_index = ah->grh.sgid_index;
+ path->hop_limit = ah->grh.hop_limit;
+ path->sl_tclass_flowlabel =
+ cpu_to_be32((ah->sl << 28) |
+ (ah->grh.traffic_class << 20) |
+ (ah->grh.flow_label));
+ memcpy(path->rgid, ah->grh.dgid.raw, 16);
+ } else
+ path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28);
+}
+
int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
@@ -591,6 +637,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
+ if ((attr_mask & IB_QP_PORT) &&
+ (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
+ mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
+ return -EINVAL;
+ }
+
+ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+ attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
+ mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
+ attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
+ return -EINVAL;
+ }
+
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+ attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
+ mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
+ attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
+ return -EINVAL;
+ }
+
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -665,28 +731,14 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_RNR_RETRY) {
- qp_context->pri_path.rnr_retry = attr->rnr_retry << 5;
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY);
+ qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry =
+ attr->rnr_retry << 5;
+ qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY |
+ MTHCA_QP_OPTPAR_ALT_RNR_RETRY);
}
if (attr_mask & IB_QP_AV) {
- qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f;
- qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid);
- qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate;
- if (attr->ah_attr.ah_flags & IB_AH_GRH) {
- qp_context->pri_path.g_mylmc |= 1 << 7;
- qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index;
- qp_context->pri_path.hop_limit = attr->ah_attr.grh.hop_limit;
- qp_context->pri_path.sl_tclass_flowlabel =
- cpu_to_be32((attr->ah_attr.sl << 28) |
- (attr->ah_attr.grh.traffic_class << 20) |
- (attr->ah_attr.grh.flow_label));
- memcpy(qp_context->pri_path.rgid,
- attr->ah_attr.grh.dgid.raw, 16);
- } else {
- qp_context->pri_path.sl_tclass_flowlabel =
- cpu_to_be32(attr->ah_attr.sl << 28);
- }
+ mthca_path_set(&attr->ah_attr, &qp_context->pri_path);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
}
@@ -695,7 +747,19 @@ 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_ACK_TIMEOUT);
}
- /* XXX alt_path */
+ if (attr_mask & IB_QP_ALT_PATH) {
+ if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) {
+ mthca_dbg(dev, "Alternate port number (%u) is invalid\n",
+ attr->alt_port_num);
+ return -EINVAL;
+ }
+
+ mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path);
+ qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
+ attr->alt_port_num << 24);
+ qp_context->alt_path.ackto = attr->alt_timeout << 3;
+ qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH);
+ }
/* leave rdd as 0 */
qp_context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pd_num);
@@ -703,9 +767,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->wqe_lkey = cpu_to_be32(qp->mr.ibmr.lkey);
qp_context->params1 = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) |
(MTHCA_FLIGHT_LIMIT << 24) |
- MTHCA_QP_BIT_SRE |
- MTHCA_QP_BIT_SWE |
- MTHCA_QP_BIT_SAE);
+ MTHCA_QP_BIT_SWE);
if (qp->sq_policy == IB_SIGNAL_ALL_WR)
qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC);
if (attr_mask & IB_QP_RETRY_CNT) {
@@ -714,9 +776,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
- qp_context->params1 |= cpu_to_be32(min(attr->max_rd_atomic ?
- ffs(attr->max_rd_atomic) - 1 : 0,
- 7) << 21);
+ if (attr->max_rd_atomic) {
+ qp_context->params1 |=
+ cpu_to_be32(MTHCA_QP_BIT_SRE |
+ MTHCA_QP_BIT_SAE);
+ qp_context->params1 |=
+ cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21);
+ }
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX);
}
@@ -729,71 +795,19 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->snd_db_index = cpu_to_be32(qp->sq.db_index);
}
- if (attr_mask & IB_QP_ACCESS_FLAGS) {
- qp_context->params2 |=
- cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ?
- MTHCA_QP_BIT_RWE : 0);
-
- /*
- * Only enable RDMA reads and atomics if we have
- * responder resources set to a non-zero value.
- */
- if (qp->resp_depth) {
- qp_context->params2 |=
- cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_READ ?
- MTHCA_QP_BIT_RRE : 0);
- qp_context->params2 |=
- cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC ?
- MTHCA_QP_BIT_RAE : 0);
- }
-
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
- MTHCA_QP_OPTPAR_RRE |
- MTHCA_QP_OPTPAR_RAE);
-
- qp->atomic_rd_en = attr->qp_access_flags;
- }
-
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
- u8 rra_max;
-
- if (qp->resp_depth && !attr->max_dest_rd_atomic) {
- /*
- * Lowering our responder resources to zero.
- * Turn off reads RDMA and atomics as responder.
- * (RRE/RAE in params2 already zero)
- */
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE |
- MTHCA_QP_OPTPAR_RAE);
- }
-
- if (!qp->resp_depth && attr->max_dest_rd_atomic) {
- /*
- * Increasing our responder resources from
- * zero. Turn on RDMA reads and atomics as
- * appropriate.
- */
+ if (attr->max_dest_rd_atomic)
qp_context->params2 |=
- cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_READ ?
- MTHCA_QP_BIT_RRE : 0);
- qp_context->params2 |=
- cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_ATOMIC ?
- MTHCA_QP_BIT_RAE : 0);
-
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE |
- MTHCA_QP_OPTPAR_RAE);
- }
+ cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21);
- for (rra_max = 0;
- 1 << rra_max < attr->max_dest_rd_atomic &&
- rra_max < dev->qp_table.rdb_shift;
- ++rra_max)
- ; /* nothing */
-
- qp_context->params2 |= cpu_to_be32(rra_max << 21);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX);
+ }
- qp->resp_depth = attr->max_dest_rd_atomic;
+ if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) {
+ qp_context->params2 |= get_hw_access_flags(qp, attr, attr_mask);
+ qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
+ MTHCA_QP_OPTPAR_RRE |
+ MTHCA_QP_OPTPAR_RAE);
}
qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
@@ -835,8 +849,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
err = -EINVAL;
}
- if (!err)
+ if (!err) {
qp->state = new_state;
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ qp->atomic_rd_en = attr->qp_access_flags;
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+ qp->resp_depth = attr->max_dest_rd_atomic;
+ }
mthca_free_mailbox(dev, mailbox);
@@ -885,18 +904,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return err;
}
-static void mthca_adjust_qp_caps(struct mthca_dev *dev,
- struct mthca_pd *pd,
- struct mthca_qp *qp)
+static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz)
{
- int max_data_size;
-
/*
* Calculate the maximum size of WQE s/g segments, excluding
* the next segment and other non-data segments.
*/
- max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) -
- sizeof (struct mthca_next_seg);
+ int max_data_size = desc_sz - sizeof (struct mthca_next_seg);
switch (qp->transport) {
case MLX:
@@ -915,11 +929,24 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev,
break;
}
+ return max_data_size;
+}
+
+static inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size)
+{
/* We don't support inline data for kernel QPs (yet). */
- if (!pd->ibpd.uobject)
- qp->max_inline_data = 0;
- else
- qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE;
+ return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0;
+}
+
+static void mthca_adjust_qp_caps(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_qp *qp)
+{
+ int max_data_size = mthca_max_data_size(dev, qp,
+ min(dev->limits.max_desc_sz,
+ 1 << qp->sq.wqe_shift));
+
+ qp->max_inline_data = mthca_max_inline_data(pd, max_data_size);
qp->sq.max_gs = min_t(int, dev->limits.max_sg,
max_data_size / sizeof (struct mthca_data_seg));
@@ -1186,13 +1213,23 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
}
static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
- struct mthca_qp *qp)
+ struct mthca_pd *pd, struct mthca_qp *qp)
{
+ int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz);
+
/* Sanity check QP size before proceeding */
- 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)
+ 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 ||
+ cap->max_inline_data > mthca_max_inline_data(pd, max_data_size))
+ return -EINVAL;
+
+ /*
+ * For MLX transport we need 2 extra S/G entries:
+ * one for the header and one for the checksum at the end
+ */
+ if (qp->transport == MLX && cap->max_recv_sge + 2 > dev->limits.max_sg)
return -EINVAL;
if (mthca_is_memfree(dev)) {
@@ -1211,14 +1248,6 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
MTHCA_INLINE_CHUNK_SIZE) /
sizeof (struct mthca_data_seg));
- /*
- * For MLX transport we need 2 extra S/G entries:
- * one for the header and one for the checksum at the end
- */
- if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) ||
- qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg)
- return -EINVAL;
-
return 0;
}
@@ -1233,7 +1262,7 @@ int mthca_alloc_qp(struct mthca_dev *dev,
{
int err;
- err = mthca_set_qp_size(dev, cap, qp);
+ err = mthca_set_qp_size(dev, cap, pd, qp);
if (err)
return err;
@@ -1276,7 +1305,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
int err;
- err = mthca_set_qp_size(dev, cap, &sqp->qp);
+ err = mthca_set_qp_size(dev, cap, pd, &sqp->qp);
if (err)
return err;
@@ -1405,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
u16 pkey;
ib_ud_header_init(256, /* assume a MAD */
- sqp->ud_header.grh_present,
+ mthca_ah_grh_present(to_mah(wr->wr.ud.ah)),
&sqp->ud_header);
err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index f7d234295efe..e7e153d9c4c6 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -201,7 +201,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
if (mthca_is_memfree(dev))
srq->max = roundup_pow_of_two(srq->max + 1);
- ds = min(64UL,
+ ds = max(64UL,
roundup_pow_of_two(sizeof (struct mthca_next_seg) +
srq->max_gs * sizeof (struct mthca_data_seg)));
srq->wqe_shift = long_log2(ds);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 9923a15a9996..e0a5412b7e68 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -45,11 +45,11 @@
#include <linux/config.h>
#include <linux/kref.h>
#include <linux/if_infiniband.h>
+#include <linux/mutex.h>
#include <net/neighbour.h>
#include <asm/atomic.h>
-#include <asm/semaphore.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
@@ -123,8 +123,8 @@ struct ipoib_dev_priv {
unsigned long flags;
- struct semaphore mcast_mutex;
- struct semaphore vlan_mutex;
+ struct mutex mcast_mutex;
+ struct mutex vlan_mutex;
struct rb_root path_tree;
struct list_head path_list;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 23885801b6d2..86bcdd72a107 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level,
#define IPOIB_OP_RECV (1ul << 31)
-static DECLARE_MUTEX(pkey_sem);
+static DEFINE_MUTEX(pkey_mutex);
struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
struct ib_pd *pd, struct ib_ah_attr *attr)
@@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev)
/* Shutdown the P_Key thread if still active */
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
- down(&pkey_sem);
+ mutex_lock(&pkey_mutex);
set_bit(IPOIB_PKEY_STOP, &priv->flags);
cancel_delayed_work(&priv->pkey_task);
- up(&pkey_sem);
+ mutex_unlock(&pkey_mutex);
flush_workqueue(ipoib_workqueue);
}
ipoib_mcast_stop_thread(dev, 1);
-
- /*
- * Flush the multicast groups first so we stop any multicast joins. The
- * completion thread may have already died and we may deadlock waiting
- * for the completion thread to finish some multicast joins.
- */
ipoib_mcast_dev_flush(dev);
- /* Delete broadcast and local addresses since they will be recreated */
- ipoib_mcast_dev_down(dev);
-
ipoib_flush_paths(dev);
return 0;
@@ -608,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev)
if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
ipoib_ib_dev_up(dev);
- down(&priv->vlan_mutex);
+ mutex_lock(&priv->vlan_mutex);
/* Flush any child interfaces too */
list_for_each_entry(cpriv, &priv->child_intfs, list)
ipoib_ib_dev_flush(&cpriv->dev);
- up(&priv->vlan_mutex);
+ mutex_unlock(&priv->vlan_mutex);
}
void ipoib_ib_dev_cleanup(struct net_device *dev)
@@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
ipoib_dbg(priv, "cleaning up ib_dev\n");
ipoib_mcast_stop_thread(dev, 1);
-
- /* Delete the broadcast address and the local address */
- ipoib_mcast_dev_down(dev);
+ ipoib_mcast_dev_flush(dev);
ipoib_transport_dev_cleanup(dev);
}
@@ -662,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr)
if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
ipoib_open(dev);
else {
- down(&pkey_sem);
+ mutex_lock(&pkey_mutex);
if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->pkey_task,
HZ);
- up(&pkey_sem);
+ mutex_unlock(&pkey_mutex);
}
}
@@ -681,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev)
/* P_Key value not assigned yet - start polling */
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
- down(&pkey_sem);
+ mutex_lock(&pkey_mutex);
clear_bit(IPOIB_PKEY_STOP, &priv->flags);
queue_delayed_work(ipoib_workqueue,
&priv->pkey_task,
HZ);
- up(&pkey_sem);
+ mutex_unlock(&pkey_mutex);
return 1;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 780009c7eaa6..fd3f5c862a5d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -105,7 +105,7 @@ int ipoib_open(struct net_device *dev)
struct ipoib_dev_priv *cpriv;
/* Bring up any child interfaces too */
- down(&priv->vlan_mutex);
+ mutex_lock(&priv->vlan_mutex);
list_for_each_entry(cpriv, &priv->child_intfs, list) {
int flags;
@@ -115,7 +115,7 @@ int ipoib_open(struct net_device *dev)
dev_change_flags(cpriv->dev, flags | IFF_UP);
}
- up(&priv->vlan_mutex);
+ mutex_unlock(&priv->vlan_mutex);
}
netif_start_queue(dev);
@@ -140,7 +140,7 @@ static int ipoib_stop(struct net_device *dev)
struct ipoib_dev_priv *cpriv;
/* Bring down any child interfaces too */
- down(&priv->vlan_mutex);
+ mutex_lock(&priv->vlan_mutex);
list_for_each_entry(cpriv, &priv->child_intfs, list) {
int flags;
@@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev)
dev_change_flags(cpriv->dev, flags & ~IFF_UP);
}
- up(&priv->vlan_mutex);
+ mutex_unlock(&priv->vlan_mutex);
}
return 0;
@@ -892,8 +892,8 @@ static void ipoib_setup(struct net_device *dev)
spin_lock_init(&priv->lock);
spin_lock_init(&priv->tx_lock);
- init_MUTEX(&priv->mcast_mutex);
- init_MUTEX(&priv->vlan_mutex);
+ mutex_init(&priv->mcast_mutex);
+ mutex_init(&priv->vlan_mutex);
INIT_LIST_HEAD(&priv->path_list);
INIT_LIST_HEAD(&priv->child_intfs);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ed0c2ead8bc1..98039da0caf0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level,
"Enable multicast debug tracing if > 0");
#endif
-static DECLARE_MUTEX(mcast_mutex);
+static DEFINE_MUTEX(mcast_mutex);
/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
struct ipoib_mcast {
@@ -97,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tmp;
unsigned long flags;
- LIST_HEAD(ah_list);
- struct ipoib_ah *ah, *tah;
ipoib_dbg_mcast(netdev_priv(dev),
"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -107,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
+ /*
+ * It's safe to call ipoib_put_ah() inside priv->lock
+ * here, because we know that mcast->ah will always
+ * hold one more reference, so ipoib_put_ah() will
+ * never do more than decrement the ref count.
+ */
if (neigh->ah)
- list_add_tail(&neigh->ah->list, &ah_list);
+ ipoib_put_ah(neigh->ah);
*to_ipoib_neigh(neigh->neighbour) = NULL;
neigh->neighbour->ops->destructor = NULL;
kfree(neigh);
@@ -116,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
spin_unlock_irqrestore(&priv->lock, flags);
- list_for_each_entry_safe(ah, tah, &ah_list, list)
- ipoib_put_ah(ah);
-
if (mcast->ah)
ipoib_put_ah(mcast->ah);
@@ -384,10 +385,10 @@ static void ipoib_mcast_join_complete(int status,
if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
mcast->backoff = 1;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
complete(&mcast->done);
return;
}
@@ -417,7 +418,7 @@ static void ipoib_mcast_join_complete(int status,
mcast->query = NULL;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
if (status == -ETIMEDOUT)
queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -426,7 +427,7 @@ static void ipoib_mcast_join_complete(int status,
mcast->backoff * HZ);
} else
complete(&mcast->done);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return;
}
@@ -481,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task,
mcast->backoff * HZ);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
} else
mcast->query_id = ret;
}
@@ -519,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr)
priv->broadcast = ipoib_mcast_alloc(dev, 1);
if (!priv->broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task, HZ);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return;
}
@@ -579,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
ipoib_dbg_mcast(priv, "starting multicast thread\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return 0;
}
@@ -594,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
cancel_delayed_work(&priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
if (flush)
flush_workqueue(ipoib_workqueue);
@@ -741,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
LIST_HEAD(remove_list);
- struct ipoib_mcast *mcast, *tmcast, *nmcast;
+ struct ipoib_mcast *mcast, *tmcast;
unsigned long flags;
ipoib_dbg_mcast(priv, "flushing multicast list\n");
spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
- nmcast = ipoib_mcast_alloc(dev, 0);
- if (nmcast) {
- nmcast->flags =
- mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY);
- nmcast->mcmember.mgid = mcast->mcmember.mgid;
-
- /* Add the new group in before the to-be-destroyed group */
- list_add_tail(&nmcast->list, &mcast->list);
- list_del_init(&mcast->list);
-
- rb_replace_node(&mcast->rb_node, &nmcast->rb_node,
- &priv->multicast_tree);
-
- list_add_tail(&mcast->list, &remove_list);
- } else {
- ipoib_warn(priv, "could not reallocate multicast group "
- IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
- }
+ list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
+ list_del(&mcast->list);
+ rb_erase(&mcast->rb_node, &priv->multicast_tree);
+ list_add_tail(&mcast->list, &remove_list);
}
if (priv->broadcast) {
- nmcast = ipoib_mcast_alloc(dev, 0);
- if (nmcast) {
- nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid;
-
- rb_replace_node(&priv->broadcast->rb_node,
- &nmcast->rb_node,
- &priv->multicast_tree);
-
- list_add_tail(&priv->broadcast->list, &remove_list);
- }
-
- priv->broadcast = nmcast;
+ rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
+ list_add_tail(&priv->broadcast->list, &remove_list);
+ priv->broadcast = NULL;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -793,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
}
}
-void ipoib_mcast_dev_down(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
-
- /* Delete broadcast since it will be recreated */
- if (priv->broadcast) {
- ipoib_dbg_mcast(priv, "deleting broadcast group\n");
-
- spin_lock_irqsave(&priv->lock, flags);
- rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
- spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_mcast_leave(dev, priv->broadcast);
- ipoib_mcast_free(priv->broadcast);
- priv->broadcast = NULL;
- }
-}
-
void ipoib_mcast_restart_task(void *dev_ptr)
{
struct net_device *dev = dev_ptr;
@@ -824,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
ipoib_mcast_stop_thread(dev, 0);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&dev->xmit_lock, flags);
+ spin_lock(&priv->lock);
/*
* Unfortunately, the networking core only gives us a list of all of
@@ -896,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr)
list_add_tail(&mcast->list, &remove_list);
}
}
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&dev->xmit_lock, flags);
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index e829e10400e3..faaf10e5fc7b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
}
/* attach QP to multicast group */
- down(&priv->mcast_mutex);
+ mutex_lock(&priv->mcast_mutex);
ret = ib_attach_mcast(priv->qp, mgid, mlid);
- up(&priv->mcast_mutex);
+ mutex_unlock(&priv->mcast_mutex);
if (ret)
ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret);
@@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
- down(&priv->mcast_mutex);
+ mutex_lock(&priv->mcast_mutex);
ret = ib_detach_mcast(priv->qp, mgid, mlid);
- up(&priv->mcast_mutex);
+ mutex_unlock(&priv->mcast_mutex);
if (ret)
ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index d280b341a37f..4ca175553f9f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
ppriv = netdev_priv(pdev);
- down(&ppriv->vlan_mutex);
+ mutex_lock(&ppriv->vlan_mutex);
/*
* First ensure this isn't a duplicate. We check the parent device and
@@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
list_add_tail(&priv->list, &ppriv->child_intfs);
- up(&ppriv->vlan_mutex);
+ mutex_unlock(&ppriv->vlan_mutex);
return 0;
@@ -139,7 +139,7 @@ device_init_failed:
free_netdev(priv->dev);
err:
- up(&ppriv->vlan_mutex);
+ mutex_unlock(&ppriv->vlan_mutex);
return result;
}
@@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
ppriv = netdev_priv(pdev);
- down(&ppriv->vlan_mutex);
+ mutex_lock(&ppriv->vlan_mutex);
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
unregister_netdev(priv->dev);
@@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
break;
}
}
- up(&ppriv->vlan_mutex);
+ mutex_unlock(&ppriv->vlan_mutex);
return ret;
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ee9fe226ae99..31207e664148 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -39,6 +39,7 @@
#include <linux/string.h>
#include <linux/parser.h>
#include <linux/random.h>
+#include <linux/jiffies.h>
#include <asm/atomic.h>
@@ -1515,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
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)
+static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
{
struct srp_host *host;
@@ -1531,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device,
host->port = port;
host->initiator_port_id[7] = port;
- memcpy(host->initiator_port_id + 8, &node_guid, 8);
+ memcpy(host->initiator_port_id + 8, &device->node_guid, 8);
host->pd = ib_alloc_pd(device);
if (IS_ERR(host->pd))
@@ -1579,22 +1579,11 @@ 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;
+ return;
INIT_LIST_HEAD(dev_list);
@@ -1607,15 +1596,12 @@ static void srp_add_one(struct ib_device *device)
}
for (p = s; p <= e; ++p) {
- host = srp_add_port(device, dev_attr->node_guid, p);
+ host = srp_add_port(device, 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)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a1e660e3531d..745979f33dc2 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -146,6 +146,7 @@ static int evdev_open(struct inode * inode, struct file * file)
}
#ifdef CONFIG_COMPAT
+
struct input_event_compat {
struct compat_timeval time;
__u16 type;
@@ -153,10 +154,12 @@ struct input_event_compat {
__s32 value;
};
+/* Note to the author of this code: did it ever occur to
+ you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
-# define COMPAT_TEST test_thread_flag(TIF_IA32)
+# define COMPAT_TEST is_compat_task()
#elif defined(CONFIG_IA64)
-# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
+# define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
#elif defined(CONFIG_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
#elif defined(CONFIG_MIPS)
@@ -165,98 +168,107 @@ struct input_event_compat {
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
-static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static inline size_t evdev_event_size(void)
{
- struct evdev_list *list = file->private_data;
- struct input_event_compat event;
- int retval = 0;
+ return COMPAT_TEST ?
+ sizeof(struct input_event_compat) : sizeof(struct input_event);
+}
- while (retval < count) {
- if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
+static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+{
+ if (COMPAT_TEST) {
+ struct input_event_compat compat_event;
+
+ if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat)))
+ return -EFAULT;
+
+ event->time.tv_sec = compat_event.time.tv_sec;
+ event->time.tv_usec = compat_event.time.tv_usec;
+ event->type = compat_event.type;
+ event->code = compat_event.code;
+ event->value = compat_event.value;
+
+ } else {
+ if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
- retval += sizeof(struct input_event_compat);
}
- return retval;
+ return 0;
}
-#endif
-static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
{
- struct evdev_list *list = file->private_data;
- struct input_event event;
- int retval = 0;
-
- if (!list->evdev->exist) return -ENODEV;
+ if (COMPAT_TEST) {
+ struct input_event_compat compat_event;
-#ifdef CONFIG_COMPAT
- if (COMPAT_TEST)
- return evdev_write_compat(file, buffer, count, ppos);
-#endif
+ compat_event.time.tv_sec = event->time.tv_sec;
+ compat_event.time.tv_usec = event->time.tv_usec;
+ compat_event.type = event->type;
+ compat_event.code = event->code;
+ compat_event.value = event->value;
- while (retval < count) {
+ if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat)))
+ return -EFAULT;
- if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
+ } else {
+ if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
- retval += sizeof(struct input_event);
}
- return retval;
+ return 0;
}
-#ifdef CONFIG_COMPAT
-static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+#else
+
+static inline size_t evdev_event_size(void)
{
- struct evdev_list *list = file->private_data;
- int retval;
+ return sizeof(struct input_event);
+}
- if (count < sizeof(struct input_event_compat))
- return -EINVAL;
+static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+{
+ if (copy_from_user(event, buffer, sizeof(struct input_event)))
+ return -EFAULT;
- if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
- return -EAGAIN;
+ return 0;
+}
- retval = wait_event_interruptible(list->evdev->wait,
- list->head != list->tail || (!list->evdev->exist));
+static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
+{
+ if (copy_to_user(buffer, event, sizeof(struct input_event)))
+ return -EFAULT;
- if (retval)
- return retval;
+ return 0;
+}
+
+#endif /* CONFIG_COMPAT */
+
+static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+{
+ struct evdev_list *list = file->private_data;
+ struct input_event event;
+ int retval = 0;
if (!list->evdev->exist)
return -ENODEV;
- while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
- struct input_event *event = (struct input_event *) list->buffer + list->tail;
- struct input_event_compat event_compat;
- event_compat.time.tv_sec = event->time.tv_sec;
- event_compat.time.tv_usec = event->time.tv_usec;
- event_compat.type = event->type;
- event_compat.code = event->code;
- event_compat.value = event->value;
-
- if (copy_to_user(buffer + retval, &event_compat,
- sizeof(struct input_event_compat))) return -EFAULT;
- list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct input_event_compat);
+ while (retval < count) {
+
+ if (evdev_event_from_user(buffer + retval, &event))
+ return -EFAULT;
+ input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+ retval += evdev_event_size();
}
return retval;
}
-#endif
static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
int retval;
-#ifdef CONFIG_COMPAT
- if (COMPAT_TEST)
- return evdev_read_compat(file, buffer, count, ppos);
-#endif
-
- if (count < sizeof(struct input_event))
+ if (count < evdev_event_size())
return -EINVAL;
if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
@@ -271,11 +283,15 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
if (!list->evdev->exist)
return -ENODEV;
- while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail,
- sizeof(struct input_event))) return -EFAULT;
+ while (list->head != list->tail && retval + evdev_event_size() <= count) {
+
+ struct input_event *event = (struct input_event *) list->buffer + list->tail;
+
+ if (evdev_event_to_user(buffer + retval, event))
+ return -EFAULT;
+
list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct input_event);
+ retval += evdev_event_size();
}
return retval;
@@ -290,17 +306,95 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
}
-static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#ifdef CONFIG_COMPAT
+
+#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
+#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
+
+#ifdef __BIG_ENDIAN
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p, int compat)
+{
+ int len, i;
+
+ if (compat) {
+ len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
+ if (len < maxlen)
+ len = maxlen;
+
+ for (i = 0; i < len / sizeof(compat_long_t); i++)
+ if (copy_to_user((compat_long_t __user *) p + i,
+ (compat_long_t *) bits +
+ i + 1 - ((i % 2) << 1),
+ sizeof(compat_long_t)))
+ return -EFAULT;
+ } else {
+ len = NBITS(maxbit) * sizeof(long);
+ if (len > maxlen)
+ len = maxlen;
+
+ if (copy_to_user(p, bits, len))
+ return -EFAULT;
+ }
+
+ return len;
+}
+#else
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p, int compat)
+{
+ int len = compat ?
+ NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
+ NBITS(maxbit) * sizeof(long);
+
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_to_user(p, bits, len) ? -EFAULT : len;
+}
+#endif /* __BIG_ENDIAN */
+
+#else
+
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p, int compat)
+{
+ int len = NBITS(maxbit) * sizeof(long);
+
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_to_user(p, bits, len) ? -EFAULT : len;
+}
+
+#endif /* CONFIG_COMPAT */
+
+static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
+{
+ int len;
+
+ if (!str)
+ return -ENOENT;
+
+ len = strlen(str) + 1;
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_to_user(p, str, len) ? -EFAULT : len;
+}
+
+static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
+ void __user *p, int compat_mode)
{
struct evdev_list *list = file->private_data;
struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
- void __user *p = (void __user *)arg;
- int __user *ip = (int __user *)arg;
+ int __user *ip = (int __user *)p;
int i, t, u, v;
- if (!evdev->exist) return -ENODEV;
+ if (!evdev->exist)
+ return -ENODEV;
switch (cmd) {
@@ -308,26 +402,39 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return put_user(EV_VERSION, ip);
case EVIOCGID:
- return copy_to_user(p, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0;
+ if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
+ return -EFAULT;
+
+ return 0;
case EVIOCGKEYCODE:
- if (get_user(t, ip)) return -EFAULT;
- if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
- if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT;
+ if (get_user(t, ip))
+ return -EFAULT;
+ if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
+ return -EINVAL;
+ if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
+ return -EFAULT;
return 0;
case EVIOCSKEYCODE:
- if (get_user(t, ip)) return -EFAULT;
- 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 (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
+ if (get_user(t, ip))
+ return -EFAULT;
+ 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 (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);
for (i = 0; i < dev->keycodemax; i++)
- if (INPUT_KEYCODE(dev,i) == u)
+ if (INPUT_KEYCODE(dev, i) == u)
set_bit(u, dev->keybit);
+
return 0;
case EVIOCSFF:
@@ -338,17 +445,17 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (copy_from_user(&effect, p, sizeof(effect)))
return -EFAULT;
err = dev->upload_effect(dev, &effect);
- if (put_user(effect.id, &(((struct ff_effect __user *)arg)->id)))
+ if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
return -EFAULT;
return err;
- }
- else return -ENOSYS;
+ } else
+ return -ENOSYS;
case EVIOCRMFF:
- if (dev->erase_effect) {
- return dev->erase_effect(dev, (int)arg);
- }
- else return -ENOSYS;
+ if (!dev->erase_effect)
+ return -ENOSYS;
+
+ return dev->erase_effect(dev, (int)(unsigned long) p);
case EVIOCGEFFECTS:
if (put_user(dev->ff_effects_max, ip))
@@ -356,7 +463,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return 0;
case EVIOCGRAB:
- if (arg) {
+ if (p) {
if (evdev->grab)
return -EBUSY;
if (input_grab_device(&evdev->handle))
@@ -395,62 +502,33 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case EV_SW: bits = dev->swbit; len = SW_MAX; break;
default: return -EINVAL;
}
- len = NBITS(len) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, bits, len) ? -EFAULT : len;
+ return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
}
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
- int len;
- len = NBITS(KEY_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->key, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
+ return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
- int len;
- len = NBITS(LED_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->led, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
+ return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
- int len;
- len = NBITS(SND_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+ return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- 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(EVIOCGSW(0)))
+ return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
- int len;
- if (!dev->name) return -ENOENT;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->name, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
+ return str_to_user(dev->name, _IOC_SIZE(cmd), p);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
- int len;
- if (!dev->phys) return -ENOENT;
- len = strlen(dev->phys) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
+ return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
- int len;
- if (!dev->uniq) return -ENOENT;
- len = strlen(dev->uniq) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
+ return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
@@ -492,158 +570,15 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EINVAL;
}
-#ifdef CONFIG_COMPAT
-
-#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
-#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT)
-#define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x))
-#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT)
-#define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1)
-
-#ifdef __BIG_ENDIAN
-#define bit_to_user(bit, max) \
-do { \
- int i; \
- 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 __user *) p + i, \
- (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
- sizeof(compat_long_t))) \
- return -EFAULT; \
- return len; \
-} while (0)
-#else
-#define bit_to_user(bit, max) \
-do { \
- int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
- return copy_to_user(p, (bit), len) ? -EFAULT : len; \
-} while (0)
-#endif
+static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0);
+}
+#ifdef CONFIG_COMPAT
static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct evdev_list *list = file->private_data;
- struct evdev *evdev = list->evdev;
- struct input_dev *dev = evdev->handle.dev;
- struct input_absinfo abs;
- void __user *p = compat_ptr(arg);
-
- if (!evdev->exist) return -ENODEV;
-
- switch (cmd) {
-
- case EVIOCGVERSION:
- case EVIOCGID:
- case EVIOCGKEYCODE:
- case EVIOCSKEYCODE:
- case EVIOCSFF:
- case EVIOCRMFF:
- case EVIOCGEFFECTS:
- case EVIOCGRAB:
- return evdev_ioctl(file, cmd, (unsigned long) p);
-
- default:
-
- if (_IOC_TYPE(cmd) != 'E')
- return -EINVAL;
-
- if (_IOC_DIR(cmd) == _IOC_READ) {
-
- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
- long *bits;
- int max;
-
- switch (_IOC_NR(cmd) & EV_MAX) {
- case 0: bits = dev->evbit; max = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; max = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
- 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);
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
- bit_to_user(dev->key, KEY_MAX);
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
- bit_to_user(dev->led, LED_MAX);
-
- 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;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->name, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
- int len;
- if (!dev->phys) return -ENOENT;
- len = strlen(dev->phys) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
- int len;
- if (!dev->uniq) return -ENOENT;
- len = strlen(dev->uniq) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
- }
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
-
- int t = _IOC_NR(cmd) & ABS_MAX;
-
- abs.value = dev->abs[t];
- abs.minimum = dev->absmin[t];
- abs.maximum = dev->absmax[t];
- abs.fuzz = dev->absfuzz[t];
- abs.flat = dev->absflat[t];
-
- if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
- return -EFAULT;
-
- return 0;
- }
- }
-
- if (_IOC_DIR(cmd) == _IOC_WRITE) {
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
-
- int t = _IOC_NR(cmd) & ABS_MAX;
-
- if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
- return -EFAULT;
-
- dev->abs[t] = abs.value;
- dev->absmin[t] = abs.minimum;
- dev->absmax[t] = abs.maximum;
- dev->absfuzz[t] = abs.fuzz;
- dev->absflat[t] = abs.flat;
-
- return 0;
- }
- }
- }
- return -EINVAL;
+ return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
}
#endif
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
index 7524bd7d8b8f..d279454a5c9e 100644
--- a/drivers/input/gameport/Kconfig
+++ b/drivers/input/gameport/Kconfig
@@ -52,5 +52,12 @@ config GAMEPORT_EMU10K1
config GAMEPORT_FM801
tristate "ForteMedia FM801 gameport support"
depends on PCI
+ help
+ Say Y here if you have ForteMedia FM801 PCI audio controller
+ (Abit AU10, Genius Sound Maker, HP Workstation zx2000,
+ and others), and want to use its gameport.
+
+ To compile this driver as a module, choose M here: the
+ module will be called fm801-gp.
endif
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index caac6d63d46f..b765a155c008 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem);
static LIST_HEAD(gameport_list);
-static struct bus_type gameport_bus = {
- .name = "gameport",
-};
+static struct bus_type gameport_bus;
static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport);
@@ -703,11 +701,15 @@ static int gameport_driver_remove(struct device *dev)
return 0;
}
+static struct bus_type gameport_bus = {
+ .name = "gameport",
+ .probe = gameport_driver_probe,
+ .remove = gameport_driver_remove,
+};
+
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
{
drv->driver.bus = &gameport_bus;
- drv->driver.probe = gameport_driver_probe;
- drv->driver.remove = gameport_driver_remove;
gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ef5824c8846b..4fe3da3c667a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -477,8 +477,8 @@ static int __init input_proc_init(void)
entry->owner = THIS_MODULE;
input_fileops = *entry->proc_fops;
+ input_fileops.poll = input_devices_poll;
entry->proc_fops = &input_fileops;
- entry->proc_fops->poll = input_devices_poll;
entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
if (!entry)
@@ -528,40 +528,56 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
INPUT_DEV_STRING_ATTR_SHOW(uniq);
-static int print_modalias_bits(char *buf, char prefix, unsigned long *arr,
+static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr,
unsigned int min, unsigned int max)
{
int len, i;
- len = sprintf(buf, "%c", prefix);
+ len = snprintf(buf, size, "%c", prefix);
for (i = min; i < max; i++)
if (arr[LONG(i)] & BIT(i))
- len += sprintf(buf+len, "%X,", i);
+ len += snprintf(buf + len, size - len, "%X,", i);
return len;
}
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static int print_modalias(char *buf, int size, struct input_dev *id)
{
- struct input_dev *id = to_input_dev(dev);
- ssize_t len = 0;
+ int len;
- len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-",
+ len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-",
id->id.bustype,
id->id.vendor,
id->id.product,
id->id.version);
- len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX);
- len += print_modalias_bits(buf+len, 'k', id->keybit,
+ len += print_modalias_bits(buf + len, size - len, 'e', id->evbit,
+ 0, EV_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'k', id->keybit,
KEY_MIN_INTERESTING, KEY_MAX);
- len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX);
- len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX);
- len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX);
- len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX);
- len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX);
- len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX);
- len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX);
- len += sprintf(buf+len, "\n");
+ len += print_modalias_bits(buf + len, size - len, 'r', id->relbit,
+ 0, REL_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'a', id->absbit,
+ 0, ABS_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit,
+ 0, MSC_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit,
+ 0, LED_MAX);
+ len += print_modalias_bits(buf + len, size - len, 's', id->sndbit,
+ 0, SND_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit,
+ 0, FF_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'w', id->swbit,
+ 0, SW_MAX);
+ return len;
+}
+
+static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+{
+ struct input_dev *id = to_input_dev(dev);
+ ssize_t len;
+
+ len = print_modalias(buf, PAGE_SIZE, id);
+ len += snprintf(buf + len, PAGE_SIZE-len, "\n");
return len;
}
static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
@@ -728,8 +744,11 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
- envp[i] = NULL;
+ envp[i++] = buffer + len;
+ len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
+ len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
+ envp[i] = NULL;
return 0;
}
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 8558a99f6635..ec55a29fc861 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -64,8 +64,8 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
if (amijoy[i]) {
switch (i) {
- case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
- case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
+ case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
+ case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
}
input_regs(amijoy_dev[i], fp);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 51a912222e85..62438944a69a 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -53,17 +53,8 @@ struct grip_port {
struct grip_mp {
struct gameport *gameport;
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? */
};
/*
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4a917748fd9f..3b0ac3b43c54 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -143,16 +143,6 @@ config KEYBOARD_SPITZ
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
- help
- Say Y here if you have a DreamCast console running Linux and have
- a keyboard attached to its Maple bus.
-
- To compile this driver as a module, choose M here: the
- module will be called maple_keyb.
-
config KEYBOARD_AMIGA
tristate "Amiga keyboard"
depends on AMIGA
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 9ce0b87f2fac..6e0afbb22383 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -5,7 +5,6 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
-obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index a0256f8de8ef..ffacf6eca5f5 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
switch (code) {
case ATKBD_RET_BAT:
atkbd->enabled = 0;
- serio_rescan(atkbd->ps2dev.serio);
+ serio_reconnect(atkbd->ps2dev.serio);
goto out;
case ATKBD_RET_EMUL0:
atkbd->emul = 1;
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 64672d491222..e301ee4ca264 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -19,7 +19,6 @@
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <asm/irq.h>
#include <asm/arch/corgi.h>
#include <asm/arch/hardware.h>
@@ -343,10 +342,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
- SA_INTERRUPT, "corgikbd", corgikbd))
+ SA_INTERRUPT | SA_TRIGGER_RISING,
+ "corgikbd", corgikbd))
printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
- else
- set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING);
}
/* Set Strobe lines as outputs - set high */
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 6a15fe3bc527..83999d583122 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -19,7 +19,6 @@
#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>
@@ -407,10 +406,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
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))
+ SA_INTERRUPT|SA_TRIGGER_RISING,
+ "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 */
@@ -422,15 +420,18 @@ static int __init spitzkbd_probe(struct platform_device *dev)
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);
+ request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd Sync", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd PwrOn", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd SWA", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd SWB", spitzkbd);
printk(KERN_INFO "input: Spitz Keyboard Registered\n");
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 1cd7657f7e42..1be963961c15 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -60,8 +60,6 @@ static struct fasync_struct *hp_sdc_rtc_async_queue;
static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
-static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin);
-
static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
size_t count, loff_t *ppos);
@@ -387,11 +385,6 @@ static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
return 0;
}
-static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin)
-{
- return -ESPIPE;
-}
-
static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
size_t count, loff_t *ppos) {
ssize_t retval;
@@ -679,7 +672,7 @@ static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
static struct file_operations hp_sdc_rtc_fops = {
.owner = THIS_MODULE,
- .llseek = hp_sdc_rtc_llseek,
+ .llseek = no_llseek,
.read = hp_sdc_rtc_read,
.poll = hp_sdc_rtc_poll,
.ioctl = hp_sdc_rtc_ioctl,
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 04489ad7702a..8d6c3837badb 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -24,7 +25,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
MODULE_DESCRIPTION("m68k beeper driver");
MODULE_LICENSE("GPL");
-static struct input_dev *m68kspkr_dev;
+static struct platform_device *m68kspkr_platform_device;
static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -47,36 +48,103 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
return 0;
}
+static int __devinit m68kspkr_probe(struct platform_device *dev)
+{
+ struct input_dev *input_dev;
+ int err;
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "m68k beeper";
+ input_dev->phys = "m68k/generic";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x001f;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &dev->dev;
+
+ input_dev->evbit[0] = BIT(EV_SND);
+ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->event = m68kspkr_event;
+
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+
+ platform_set_drvdata(dev, input_dev);
+
+ return 0;
+}
+
+static int __devexit m68kspkr_remove(struct platform_device *dev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+
+ input_unregister_device(input_dev);
+ platform_set_drvdata(dev, NULL);
+ /* turn off the speaker */
+ m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static void m68kspkr_shutdown(struct platform_device *dev)
+{
+ /* turn off the speaker */
+ m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver m68kspkr_platform_driver = {
+ .driver = {
+ .name = "m68kspkr",
+ .owner = THIS_MODULE,
+ },
+ .probe = m68kspkr_probe,
+ .remove = __devexit_p(m68kspkr_remove),
+ .shutdown = m68kspkr_shutdown,
+};
+
static int __init m68kspkr_init(void)
{
- if (!mach_beep) {
+ int err;
+
+ if (!mach_beep) {
printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
return -ENODEV;
}
- m68kspkr_dev = input_allocate_device();
- if (!m68kspkr_dev)
- return -ENOMEM;
-
- 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;
+ err = platform_driver_register(&m68kspkr_platform_driver);
+ if (err)
+ return err;
- m68kspkr_dev->evbit[0] = BIT(EV_SND);
- m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- m68kspkr_dev->event = m68kspkr_event;
+ m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
+ if (!m68kspkr_platform_device) {
+ err = -ENOMEM;
+ goto err_unregister_driver;
+ }
- input_register_device(m68kspkr_dev);
+ err = platform_device_add(m68kspkr_platform_device);
+ if (err)
+ goto err_free_device;
return 0;
+
+ err_free_device:
+ platform_device_put(m68kspkr_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&m68kspkr_platform_driver);
+
+ return err;
}
static void __exit m68kspkr_exit(void)
{
- input_unregister_device(m68kspkr_dev);
+ platform_device_unregister(m68kspkr_platform_device);
+ platform_driver_unregister(&m68kspkr_platform_driver);
}
module_init(m68kspkr_init);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 68ac97f101b0..1ef477f4469c 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include <asm/8253pit.h>
#include <asm/io.h>
@@ -23,8 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
-static struct input_dev *pcspkr_dev;
-
+static struct platform_device *pcspkr_platform_device;
static DEFINE_SPINLOCK(i8253_beep_lock);
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -64,8 +64,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
return 0;
}
-static int __init pcspkr_init(void)
+static int __devinit pcspkr_probe(struct platform_device *dev)
{
+ struct input_dev *pcspkr_dev;
+ int err;
+
pcspkr_dev = input_allocate_device();
if (!pcspkr_dev)
return -ENOMEM;
@@ -76,22 +79,93 @@ static int __init pcspkr_init(void)
pcspkr_dev->id.vendor = 0x001f;
pcspkr_dev->id.product = 0x0001;
pcspkr_dev->id.version = 0x0100;
+ pcspkr_dev->cdev.dev = &dev->dev;
pcspkr_dev->evbit[0] = BIT(EV_SND);
pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
pcspkr_dev->event = pcspkr_event;
- input_register_device(pcspkr_dev);
+ err = input_register_device(pcspkr_dev);
+ if (err) {
+ input_free_device(pcspkr_dev);
+ return err;
+ }
+
+ platform_set_drvdata(dev, pcspkr_dev);
return 0;
}
-static void __exit pcspkr_exit(void)
+static int __devexit pcspkr_remove(struct platform_device *dev)
+{
+ struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
+
+ input_unregister_device(pcspkr_dev);
+ platform_set_drvdata(dev, NULL);
+ /* turn off the speaker */
+ pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
+{
+ pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static void pcspkr_shutdown(struct platform_device *dev)
{
- input_unregister_device(pcspkr_dev);
/* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
}
+static struct platform_driver pcspkr_platform_driver = {
+ .driver = {
+ .name = "pcspkr",
+ .owner = THIS_MODULE,
+ },
+ .probe = pcspkr_probe,
+ .remove = __devexit_p(pcspkr_remove),
+ .suspend = pcspkr_suspend,
+ .shutdown = pcspkr_shutdown,
+};
+
+
+static int __init pcspkr_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&pcspkr_platform_driver);
+ if (err)
+ return err;
+
+ pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
+ if (!pcspkr_platform_device) {
+ err = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ err = platform_device_add(pcspkr_platform_device);
+ if (err)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(pcspkr_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&pcspkr_platform_driver);
+
+ return err;
+}
+
+static void __exit pcspkr_exit(void)
+{
+ platform_device_unregister(pcspkr_platform_device);
+ platform_driver_unregister(&pcspkr_platform_driver);
+}
+
module_init(pcspkr_init);
module_exit(pcspkr_exit);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 29d97b12be7a..f0fd2c4740f1 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/ebus.h>
@@ -20,22 +21,10 @@ MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
MODULE_DESCRIPTION("Sparc Speaker beeper driver");
MODULE_LICENSE("GPL");
+const char *beep_name;
static unsigned long beep_iobase;
-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 = "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 (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+static DEFINE_SPINLOCK(beep_lock);
static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -59,39 +48,16 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in
/* EBUS speaker only has on/off state, the frequency does not
* appear to be programmable.
*/
- if (count) {
- if (beep_iobase & 0x2UL)
- outb(1, beep_iobase);
- else
- outl(1, beep_iobase);
- } else {
- if (beep_iobase & 0x2UL)
- outb(0, beep_iobase);
- else
- outl(0, beep_iobase);
- }
+ if (beep_iobase & 0x2UL)
+ outb(!!count, beep_iobase);
+ else
+ outl(!!count, beep_iobase);
spin_unlock_irqrestore(&beep_lock, flags);
return 0;
}
-static int __init init_ebus_beep(struct linux_ebus_device *edev)
-{
- beep_iobase = edev->resource[0].start;
-
- sparcspkr_dev = input_allocate_device();
- if (!sparcspkr_dev)
- return -ENOMEM;
-
- sparcspkr_dev->name = "Sparc EBUS Speaker";
- sparcspkr_dev->event = ebus_spkr_event;
-
- input_register_device(sparcspkr_dev);
-
- return 0;
-}
-
#ifdef CONFIG_SPARC64
static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -129,30 +95,103 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
return 0;
}
+#endif
-static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
+static int __devinit sparcspkr_probe(struct platform_device *dev)
{
- beep_iobase = isa_dev->resource.start;
+ struct input_dev *input_dev;
+ int error;
- sparcspkr_dev = input_allocate_device();
- if (!sparcspkr_dev)
+ input_dev = input_allocate_device();
+ if (!input_dev)
return -ENOMEM;
- init_sparcspkr_struct();
+ input_dev->name = beep_name;
+ input_dev->phys = "sparc/input0";
+ input_dev->id.bustype = BUS_ISA;
+ input_dev->id.vendor = 0x001f;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &dev->dev;
- sparcspkr_dev->name = "Sparc ISA Speaker";
- sparcspkr_dev->event = isa_spkr_event;
+ input_dev->evbit[0] = BIT(EV_SND);
+ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- input_register_device(sparcspkr_dev);
+ input_dev->event = beep_event;
+
+ error = input_register_device(input_dev);
+ if (error) {
+ input_free_device(input_dev);
+ return error;
+ }
+
+ platform_set_drvdata(dev, input_dev);
return 0;
}
-#endif
+
+static int __devexit sparcspkr_remove(struct platform_device *dev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+
+ input_unregister_device(input_dev);
+ platform_set_drvdata(dev, NULL);
+ /* turn off the speaker */
+ beep_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static void sparcspkr_shutdown(struct platform_device *dev)
+{
+ /* turn off the speaker */
+ beep_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver sparcspkr_platform_driver = {
+ .driver = {
+ .name = "sparcspkr",
+ .owner = THIS_MODULE,
+ },
+ .probe = sparcspkr_probe,
+ .remove = __devexit_p(sparcspkr_remove),
+ .shutdown = sparcspkr_shutdown,
+};
+
+static struct platform_device *sparcspkr_platform_device;
+
+static int __init sparcspkr_drv_init(void)
+{
+ int error;
+
+ error = platform_driver_register(&sparcspkr_platform_driver);
+ if (error)
+ return error;
+
+ sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1);
+ if (!sparcspkr_platform_device) {
+ error = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ error = platform_device_add(sparcspkr_platform_device);
+ if (error)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(sparcspkr_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&sparcspkr_platform_driver);
+
+ return error;
+}
static int __init sparcspkr_init(void)
{
struct linux_ebus *ebus;
- struct linux_ebus_device *edev = NULL;
+ struct linux_ebus_device *edev;
#ifdef CONFIG_SPARC64
struct sparc_isa_bridge *isa_br;
struct sparc_isa_device *isa_dev;
@@ -160,8 +199,12 @@ static int __init sparcspkr_init(void)
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_name, "beep"))
- return init_ebus_beep(edev);
+ if (!strcmp(edev->prom_name, "beep")) {
+ beep_name = "Sparc EBUS Speaker";
+ beep_event = ebus_spkr_event;
+ beep_iobase = edev->resource[0].start;
+ return sparcspkr_drv_init();
+ }
}
}
#ifdef CONFIG_SPARC64
@@ -170,8 +213,12 @@ static int __init sparcspkr_init(void)
/* A hack, the beep device's base lives in
* the DMA isa node.
*/
- if (!strcmp(isa_dev->prom_name, "dma"))
- return init_isa_beep(isa_dev);
+ if (!strcmp(isa_dev->prom_name, "dma")) {
+ beep_name = "Sparc ISA Speaker";
+ beep_event = isa_spkr_event,
+ beep_iobase = isa_dev->resource.start;
+ return sparcspkr_drv_init();
+ }
}
}
#endif
@@ -181,7 +228,8 @@ static int __init sparcspkr_init(void)
static void __exit sparcspkr_exit(void)
{
- input_unregister_device(sparcspkr_dev);
+ platform_device_unregister(sparcspkr_platform_device);
+ platform_driver_unregister(&sparcspkr_platform_driver);
}
module_init(sparcspkr_init);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index bac3085185fe..4b415d9b0123 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -92,11 +92,11 @@ static void call_bios(struct regs *regs)
preempt_enable();
}
-static size_t __init locate_wistron_bios(void __iomem *base)
+static ssize_t __init locate_wistron_bios(void __iomem *base)
{
static const unsigned char __initdata signature[] =
{ 0x42, 0x21, 0x55, 0x30 };
- size_t offset;
+ ssize_t offset;
for (offset = 0; offset < 0x10000; offset += 0x10) {
if (check_signature(base + offset, signature,
@@ -109,7 +109,7 @@ static size_t __init locate_wistron_bios(void __iomem *base)
static int __init map_bios(void)
{
void __iomem *base;
- size_t offset;
+ ssize_t offset;
u32 entry_point;
base = ioremap(0xF0000, 0x10000); /* Can't fail */
@@ -174,7 +174,7 @@ static u16 bios_pop_queue(void)
return regs.eax;
}
-static void __init bios_attach(void)
+static void __devinit bios_attach(void)
{
struct regs regs;
@@ -194,7 +194,7 @@ static void bios_detach(void)
call_bios(&regs);
}
-static u8 __init bios_get_cmos_address(void)
+static u8 __devinit bios_get_cmos_address(void)
{
struct regs regs;
@@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void)
return regs.ecx;
}
-static u16 __init bios_get_default_setting(u8 subsys)
+static u16 __devinit bios_get_default_setting(u8 subsys)
{
struct regs regs;
@@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = {
{ KE_END, 0 }
};
+static struct key_entry keymap_acer_travelmate_240[] = {
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_BLUETOOTH, 0x44, 0 },
+ { KE_WIFI, 0x30, 0 },
+ { KE_END, 0 }
+};
+
/*
* If your machine is not here (which is currently rather likely), please send
* a list of buttons and their key codes (reported when loading this module
@@ -320,6 +330,15 @@ static struct dmi_system_id dmi_ids[] = {
},
.driver_data = keymap_acer_aspire_1500
},
+ {
+ .callback = dmi_matched,
+ .ident = "Acer TravelMate 240",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
+ },
+ .driver_data = keymap_acer_travelmate_240
+ },
{ NULL, }
};
@@ -348,7 +367,7 @@ static int __init select_keymap(void)
static struct input_dev *input_dev;
-static int __init setup_input_dev(void)
+static int __devinit setup_input_dev(void)
{
const struct key_entry *key;
int error;
@@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard)
mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
}
+static int __devinit wistron_probe(struct platform_device *dev)
+{
+ int err = setup_input_dev();
+ if (err)
+ return err;
+
+ bios_attach();
+ cmos_address = bios_get_cmos_address();
+
+ if (have_wifi) {
+ u16 wifi = bios_get_default_setting(WIFI);
+ if (wifi & 1)
+ wifi_enabled = (wifi & 2) ? 1 : 0;
+ else
+ have_wifi = 0;
+
+ if (have_wifi)
+ bios_set_state(WIFI, wifi_enabled);
+ }
+
+ if (have_bluetooth) {
+ u16 bt = bios_get_default_setting(BLUETOOTH);
+ if (bt & 1)
+ bluetooth_enabled = (bt & 2) ? 1 : 0;
+ else
+ have_bluetooth = 0;
+
+ if (have_bluetooth)
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
+ }
+
+ poll_bios(1); /* Flush stale event queue and arm timer */
+
+ return 0;
+}
+
+static int __devexit wistron_remove(struct platform_device *dev)
+{
+ del_timer_sync(&poll_timer);
+ input_unregister_device(input_dev);
+ bios_detach();
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
{
del_timer_sync(&poll_timer);
@@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev)
return 0;
}
+#else
+#define wistron_suspend NULL
+#define wistron_resume NULL
+#endif
static struct platform_driver wistron_driver = {
- .suspend = wistron_suspend,
- .resume = wistron_resume,
.driver = {
.name = "wistron-bios",
+ .owner = THIS_MODULE,
},
+ .probe = wistron_probe,
+ .remove = __devexit_p(wistron_remove),
+ .suspend = wistron_suspend,
+ .resume = wistron_resume,
};
static int __init wb_module_init(void)
@@ -493,55 +565,27 @@ static int __init wb_module_init(void)
if (err)
return err;
- bios_attach();
- cmos_address = bios_get_cmos_address();
-
err = platform_driver_register(&wistron_driver);
if (err)
- goto err_detach_bios;
+ goto err_unmap_bios;
- wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0);
- if (IS_ERR(wistron_device)) {
- err = PTR_ERR(wistron_device);
+ wistron_device = platform_device_alloc("wistron-bios", -1);
+ if (!wistron_device) {
+ err = -ENOMEM;
goto err_unregister_driver;
}
- if (have_wifi) {
- u16 wifi = bios_get_default_setting(WIFI);
- if (wifi & 1)
- wifi_enabled = (wifi & 2) ? 1 : 0;
- else
- have_wifi = 0;
-
- if (have_wifi)
- bios_set_state(WIFI, wifi_enabled);
- }
-
- if (have_bluetooth) {
- u16 bt = bios_get_default_setting(BLUETOOTH);
- if (bt & 1)
- bluetooth_enabled = (bt & 2) ? 1 : 0;
- else
- have_bluetooth = 0;
-
- if (have_bluetooth)
- bios_set_state(BLUETOOTH, bluetooth_enabled);
- }
-
- err = setup_input_dev();
+ err = platform_device_add(wistron_device);
if (err)
- goto err_unregister_device;
-
- poll_bios(1); /* Flush stale event queue and arm timer */
+ goto err_free_device;
return 0;
- err_unregister_device:
- platform_device_unregister(wistron_device);
+ err_free_device:
+ platform_device_put(wistron_device);
err_unregister_driver:
platform_driver_unregister(&wistron_driver);
- err_detach_bios:
- bios_detach();
+ err_unmap_bios:
unmap_bios();
return err;
@@ -549,11 +593,8 @@ static int __init wb_module_init(void)
static void __exit wb_module_exit(void)
{
- del_timer_sync(&poll_timer);
- input_unregister_device(input_dev);
platform_device_unregister(wistron_device);
platform_driver_unregister(&wistron_driver);
- bios_detach();
unmap_bios();
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 574b18a523af..f15ccf781688 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -86,16 +86,6 @@ config MOUSE_PC110PAD
To compile this driver as a module, choose M here: the
module will be called pc110pad.
-config MOUSE_MAPLE
- tristate "Maple bus mouse"
- depends on SH_DREAMCAST && MAPLE
- help
- Say Y if you have a DreamCast console and a mouse attached to
- its Maple bus.
-
- To compile this driver as a module, choose M here: the
- module will be called maplemouse.
-
config MOUSE_AMIGA
tristate "Amiga mouse"
depends on AMIGA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 82b330bbf068..21a1de61a79b 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
-obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4f41ec3e4332..2141501e9f2e 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -40,6 +40,7 @@ static struct alps_model_info alps_model_data[] = {
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
+ { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */
{ { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
@@ -347,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable)
return 0;
}
+/*
+ * alps_poll() - poll the touchpad for current motion packet.
+ * Used in resync.
+ */
+static int alps_poll(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+ unsigned char buf[6];
+ int poll_failed;
+
+ if (priv->i->flags & ALPS_PASS)
+ alps_passthrough_mode(psmouse, 1);
+
+ poll_failed = ps2_command(&psmouse->ps2dev, buf,
+ PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
+
+ if (priv->i->flags & ALPS_PASS)
+ alps_passthrough_mode(psmouse, 0);
+
+ if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0)
+ return -1;
+
+ if ((psmouse->badbyte & 0xc8) == 0x08) {
+/*
+ * Poll the track stick ...
+ */
+ if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
+ return -1;
+ }
+
+ memcpy(psmouse->packet, buf, sizeof(buf));
+ return 0;
+}
+
static int alps_reconnect(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
@@ -450,10 +485,14 @@ int alps_init(struct psmouse *psmouse)
input_register_device(priv->dev2);
psmouse->protocol_handler = alps_process_byte;
+ psmouse->poll = alps_poll;
psmouse->disconnect = alps_disconnect;
psmouse->reconnect = alps_reconnect;
psmouse->pktsize = 6;
+ /* We are having trouble resyncing ALPS touchpads so disable it for now */
+ psmouse->resync_time = 0;
+
return 0;
init_fail:
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index d13d4c8fe3c5..c8b2cc9f184c 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -41,7 +41,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
unsigned short joy0dat, potgor;
int nx, ny, dx, dy;
- joy0dat = custom.joy0dat;
+ joy0dat = amiga_custom.joy0dat;
nx = joy0dat & 0xff;
ny = joy0dat >> 8;
@@ -57,7 +57,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
amimouse_lastx = nx;
amimouse_lasty = ny;
- potgor = custom.potgor;
+ potgor = amiga_custom.potgor;
input_regs(amimouse_dev, fp);
@@ -77,7 +77,7 @@ static int amimouse_open(struct input_dev *dev)
{
unsigned short joy0dat;
- joy0dat = custom.joy0dat;
+ joy0dat = amiga_custom.joy0dat;
amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8;
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 55991424ac91..5ccc3ef3b89e 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -27,6 +27,13 @@ static struct dmi_system_id lifebook_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
},
},
+ {
+ .ident = "Lifebook B142",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
+ },
+
+ },
{ }
};
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 31a59f7abfaf..c88520d3d13c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
if (psmouse_sliced_command(psmouse, command))
return -1;
- if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL))
+ if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))
return -1;
return 0;
@@ -226,7 +226,9 @@ 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 },
+ { 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
deleted file mode 100644
index b5b34fe4fee8..000000000000
--- a/drivers/input/mouse/maplemouse.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $
- * SEGA Dreamcast mouse driver
- * Based on drivers/usb/usbmouse.c
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/maple.h>
-
-MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
-MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
-
-static void dc_mouse_callback(struct mapleq *mq)
-{
- int buttons, relx, rely, relz;
- struct maple_device *mapledev = mq->dev;
- struct input_dev *dev = mapledev->private_data;
- unsigned char *res = mq->recvbuf;
-
- buttons = ~res[8];
- relx = *(unsigned short *)(res + 12) - 512;
- rely = *(unsigned short *)(res + 14) - 512;
- relz = *(unsigned short *)(res + 16) - 512;
-
- input_report_key(dev, BTN_LEFT, buttons & 4);
- input_report_key(dev, BTN_MIDDLE, buttons & 9);
- input_report_key(dev, BTN_RIGHT, buttons & 2);
- input_report_rel(dev, REL_X, relx);
- input_report_rel(dev, REL_Y, rely);
- input_report_rel(dev, REL_WHEEL, relz);
- input_sync(dev);
-}
-
-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;
-
- dev->private_data = input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
-
- dev->private_data = 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);
-
- input_dev->name = dev->product_name;
- input_dev->id.bustype = BUS_MAPLE;
-
- input_register_device(input_dev);
-
- maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
-
- return 0;
-}
-
-
-static void dc_mouse_disconnect(struct maple_device *dev)
-{
- struct input_dev *input_dev = dev->private_data;
-
- input_unregister_device(input_dev);
-}
-
-
-static struct maple_driver dc_mouse_driver = {
- .function = MAPLE_FUNC_MOUSE,
- .name = "Dreamcast mouse",
- .connect = dc_mouse_connect,
- .disconnect = dc_mouse_disconnect,
-};
-
-
-static int __init dc_mouse_init(void)
-{
- maple_register_driver(&dc_mouse_driver);
- return 0;
-}
-
-
-static void __exit dc_mouse_exit(void)
-{
- maple_unregister_driver(&dc_mouse_driver);
-}
-
-
-module_init(dc_mouse_init);
-module_exit(dc_mouse_exit);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 6ee9999a2eaa..7665fd9ce559 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
-static unsigned int psmouse_resetafter;
+static unsigned int psmouse_resetafter = 5;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
+static unsigned int psmouse_resync_time = 5;
+module_param_named(resync_time, psmouse_resync_time, uint, 0644);
+MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never).");
+
PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
NULL,
psmouse_attr_show_protocol, psmouse_attr_set_protocol);
@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
(void *) offsetof(struct psmouse, resetafter),
psmouse_show_int_attr, psmouse_set_int_attr);
+PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, resync_time),
+ 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,
+ &psmouse_attr_resync_time.dattr.attr,
NULL
};
@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate=");
*/
static DECLARE_MUTEX(psmouse_sem);
+static struct workqueue_struct *kpsmoused_wq;
+
struct psmouse_protocol {
enum psmouse_type type;
char *name;
@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg
}
/*
- * psmouse_interrupt() handles incoming characters, either gathering them into
- * packets or passing them to the command routine as command output.
+ * __psmouse_set_state() sets new psmouse state and resets all flags.
+ */
+
+static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+ psmouse->state = new_state;
+ psmouse->pktcnt = psmouse->out_of_sync = 0;
+ psmouse->ps2dev.flags = 0;
+ psmouse->last = jiffies;
+}
+
+
+/*
+ * psmouse_set_state() sets new psmouse state and resets all flags and
+ * counters while holding serio lock so fighting with interrupt handler
+ * is not a concern.
+ */
+
+static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+ serio_pause_rx(psmouse->ps2dev.serio);
+ __psmouse_set_state(psmouse, new_state);
+ serio_continue_rx(psmouse->ps2dev.serio);
+}
+
+/*
+ * psmouse_handle_byte() processes one byte of the input data stream
+ * by calling corresponding protocol handler.
+ */
+
+static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs)
+{
+ psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs);
+
+ switch (rc) {
+ case PSMOUSE_BAD_DATA:
+ if (psmouse->state == PSMOUSE_ACTIVATED) {
+ printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
+ psmouse->name, psmouse->phys, psmouse->pktcnt);
+ if (++psmouse->out_of_sync == psmouse->resetafter) {
+ __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+ serio_reconnect(psmouse->ps2dev.serio);
+ return -1;
+ }
+ }
+ psmouse->pktcnt = 0;
+ break;
+
+ case PSMOUSE_FULL_PACKET:
+ psmouse->pktcnt = 0;
+ if (psmouse->out_of_sync) {
+ psmouse->out_of_sync = 0;
+ printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
+ psmouse->name, psmouse->phys);
+ }
+ break;
+
+ case PSMOUSE_GOOD_DATA:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * psmouse_interrupt() handles incoming characters, either passing them
+ * for normal processing or gathering them as command response.
*/
static irqreturn_t psmouse_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
struct psmouse *psmouse = serio_get_drvdata(serio);
- psmouse_ret_t rc;
if (psmouse->state == PSMOUSE_IGNORE)
goto out;
@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (ps2_handle_response(&psmouse->ps2dev, data))
goto out;
- if (psmouse->state == PSMOUSE_INITIALIZING)
+ if (psmouse->state <= PSMOUSE_RESYNCING)
goto out;
if (psmouse->state == PSMOUSE_ACTIVATED &&
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
- printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
+ printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
psmouse->name, psmouse->phys, psmouse->pktcnt);
- psmouse->pktcnt = 0;
+ psmouse->badbyte = psmouse->packet[0];
+ __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
+ queue_work(kpsmoused_wq, &psmouse->resync_work);
+ goto out;
}
- psmouse->last = jiffies;
psmouse->packet[psmouse->pktcnt++] = data;
-
- if (psmouse->packet[0] == PSMOUSE_RET_BAT) {
+/*
+ * Check if this is a new device announcement (0xAA 0x00)
+ */
+ if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
if (psmouse->pktcnt == 1)
goto out;
- if (psmouse->pktcnt == 2) {
- if (psmouse->packet[1] == PSMOUSE_RET_ID) {
- psmouse->state = PSMOUSE_IGNORE;
- serio_reconnect(serio);
- goto out;
- }
- if (psmouse->type == PSMOUSE_SYNAPTICS) {
- /* neither 0xAA nor 0x00 are valid first bytes
- * for a packet in absolute mode
- */
- psmouse->pktcnt = 0;
- goto out;
- }
+ if (psmouse->packet[1] == PSMOUSE_RET_ID) {
+ __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ serio_reconnect(serio);
+ goto out;
}
- }
-
- rc = psmouse->protocol_handler(psmouse, regs);
+/*
+ * Not a new device, try processing first byte normally
+ */
+ psmouse->pktcnt = 1;
+ if (psmouse_handle_byte(psmouse, regs))
+ goto out;
- switch (rc) {
- case PSMOUSE_BAD_DATA:
- printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
- psmouse->name, psmouse->phys, psmouse->pktcnt);
- psmouse->pktcnt = 0;
+ psmouse->packet[psmouse->pktcnt++] = data;
+ }
- if (++psmouse->out_of_sync == psmouse->resetafter) {
- psmouse->state = PSMOUSE_IGNORE;
- printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
- serio_reconnect(psmouse->ps2dev.serio);
- }
- break;
+/*
+ * See if we need to force resync because mouse was idle for too long
+ */
+ if (psmouse->state == PSMOUSE_ACTIVATED &&
+ psmouse->pktcnt == 1 && psmouse->resync_time &&
+ time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
+ psmouse->badbyte = psmouse->packet[0];
+ __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
+ queue_work(kpsmoused_wq, &psmouse->resync_work);
+ goto out;
+ }
- case PSMOUSE_FULL_PACKET:
- psmouse->pktcnt = 0;
- if (psmouse->out_of_sync) {
- psmouse->out_of_sync = 0;
- printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
- psmouse->name, psmouse->phys);
- }
- break;
+ psmouse->last = jiffies;
+ psmouse_handle_byte(psmouse, regs);
- case PSMOUSE_GOOD_DATA:
- break;
- }
-out:
+ out:
return IRQ_HANDLED;
}
@@ -527,11 +592,15 @@ static int psmouse_extensions(struct psmouse *psmouse,
if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
return PSMOUSE_PS2PP;
+ if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_TRACKPOINT;
+
/*
* Reset to defaults in case the device got confused by extended
- * protocol probes.
+ * protocol probes. Note that we do full reset becuase some mice
+ * put themselves to sleep when see PSMOUSE_RESET_DIS.
*/
- ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
+ psmouse_reset(psmouse);
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
return PSMOUSE_IMEX;
@@ -540,12 +609,6 @@ 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.
*/
@@ -559,7 +622,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
* extensions.
*/
psmouse_reset(psmouse);
- ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
}
return PSMOUSE_PS2;
@@ -755,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse)
}
/*
- * psmouse_set_state() sets new psmouse state and resets all flags and
- * counters while holding serio lock so fighting with interrupt handler
- * is not a concern.
- */
-
-static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
-{
- serio_pause_rx(psmouse->ps2dev.serio);
- psmouse->state = new_state;
- psmouse->pktcnt = psmouse->out_of_sync = 0;
- psmouse->ps2dev.flags = 0;
- serio_continue_rx(psmouse->ps2dev.serio);
-}
-
-/*
* psmouse_activate() enables the mouse so that we get motion reports from it.
*/
@@ -797,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
}
+/*
+ * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
+ */
+
+static int psmouse_poll(struct psmouse *psmouse)
+{
+ return ps2_command(&psmouse->ps2dev, psmouse->packet,
+ PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
+}
+
+
+/*
+ * psmouse_resync() attempts to re-validate current protocol.
+ */
+
+static void psmouse_resync(void *p)
+{
+ struct psmouse *psmouse = p, *parent = NULL;
+ struct serio *serio = psmouse->ps2dev.serio;
+ psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
+ int failed = 0, enabled = 0;
+ int i;
+
+ down(&psmouse_sem);
+
+ if (psmouse->state != PSMOUSE_RESYNCING)
+ goto out;
+
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
+ psmouse_deactivate(parent);
+ }
+
+/*
+ * Some mice don't ACK commands sent while they are in the middle of
+ * transmitting motion packet. To avoid delay we use ps2_sendbyte()
+ * instead of ps2_command() which would wait for 200ms for an ACK
+ * that may never come.
+ * As an additional quirk ALPS touchpads may not only forget to ACK
+ * disable command but will stop reporting taps, so if we see that
+ * mouse at least once ACKs disable we will do full reconnect if ACK
+ * is missing.
+ */
+ psmouse->num_resyncs++;
+
+ if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) {
+ if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command)
+ failed = 1;
+ } else
+ psmouse->acks_disable_command = 1;
+
+/*
+ * Poll the mouse. If it was reset the packet will be shorter than
+ * psmouse->pktsize and ps2_command will fail. We do not expect and
+ * do not handle scenario when mouse "upgrades" its protocol while
+ * disconnected since it would require additional delay. If we ever
+ * see a mouse that does it we'll adjust the code.
+ */
+ if (!failed) {
+ if (psmouse->poll(psmouse))
+ failed = 1;
+ else {
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ for (i = 0; i < psmouse->pktsize; i++) {
+ psmouse->pktcnt++;
+ rc = psmouse->protocol_handler(psmouse, NULL);
+ if (rc != PSMOUSE_GOOD_DATA)
+ break;
+ }
+ if (rc != PSMOUSE_FULL_PACKET)
+ failed = 1;
+ psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
+ }
+ }
+/*
+ * Now try to enable mouse. We try to do that even if poll failed and also
+ * repeat our attempts 5 times, otherwise we may be left out with disabled
+ * mouse.
+ */
+ for (i = 0; i < 5; i++) {
+ if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
+ enabled = 1;
+ break;
+ }
+ msleep(200);
+ }
+
+ if (!enabled) {
+ printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
+ failed = 1;
+ }
+
+ if (failed) {
+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
+ serio_reconnect(serio);
+ } else
+ psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+
+ if (parent)
+ psmouse_activate(parent);
+ out:
+ up(&psmouse_sem);
+}
/*
* psmouse_cleanup() resets the mouse into power-on state.
@@ -825,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ /* make sure we don't have a resync in progress */
+ up(&psmouse_sem);
+ flush_workqueue(kpsmoused_wq);
+ down(&psmouse_sem);
+
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
@@ -862,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution;
+ psmouse->poll = psmouse_poll;
psmouse->protocol_handler = psmouse_process_byte;
psmouse->pktsize = 3;
@@ -877,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
else
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
+ /*
+ * If mouse's packet size is 3 there is no point in polling the
+ * device in hopes to detect protocol reset - we won't get less
+ * than 3 bytes response anyhow.
+ */
+ if (psmouse->pktsize == 3)
+ psmouse->resync_time = 0;
+
+ /*
+ * Some smart KVMs fake response to POLL command returning just
+ * 3 bytes and messing up our resync logic, so if initial poll
+ * fails we won't try polling the device anymore. Hopefully
+ * such KVM will maintain initially selected protocol.
+ */
+ if (psmouse->resync_time && psmouse->poll(psmouse))
+ psmouse->resync_time = 0;
+
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
@@ -917,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
goto out;
ps2_init(&psmouse->ps2dev, serio);
+ INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
psmouse->dev = input_dev;
sprintf(psmouse->phys, "%s/input0", serio->phys);
@@ -937,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse->rate = psmouse_rate;
psmouse->resolution = psmouse_resolution;
psmouse->resetafter = psmouse_resetafter;
+ psmouse->resync_time = parent ? 0 : psmouse_resync_time;
psmouse->smartscroll = psmouse_smartscroll;
psmouse_switch_protocol(psmouse, NULL);
@@ -1281,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
static int __init psmouse_init(void)
{
+ kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
+ if (!kpsmoused_wq) {
+ printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
+ return -ENOMEM;
+ }
+
serio_register_driver(&psmouse_drv);
+
return 0;
}
static void __exit psmouse_exit(void)
{
serio_unregister_driver(&psmouse_drv);
+ destroy_workqueue(kpsmoused_wq);
}
module_init(psmouse_init);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 7c4192bd1279..4d9107fba6a1 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -7,7 +7,7 @@
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_SETPOLL 0x00f0
-#define PSMOUSE_CMD_POLL 0x03eb
+#define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
@@ -23,6 +23,7 @@
enum psmouse_state {
PSMOUSE_IGNORE,
PSMOUSE_INITIALIZING,
+ PSMOUSE_RESYNCING,
PSMOUSE_CMD_MODE,
PSMOUSE_ACTIVATED,
};
@@ -38,15 +39,19 @@ struct psmouse {
void *private;
struct input_dev *dev;
struct ps2dev ps2dev;
+ struct work_struct resync_work;
char *vendor;
char *name;
unsigned char packet[8];
+ unsigned char badbyte;
unsigned char pktcnt;
unsigned char pktsize;
unsigned char type;
+ unsigned char acks_disable_command;
unsigned int model;
unsigned long last;
unsigned long out_of_sync;
+ unsigned long num_resyncs;
enum psmouse_state state;
char devname[64];
char phys[32];
@@ -54,6 +59,7 @@ struct psmouse {
unsigned int rate;
unsigned int resolution;
unsigned int resetafter;
+ unsigned int resync_time;
unsigned int smartscroll; /* Logitech only */
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
@@ -62,6 +68,7 @@ struct psmouse {
int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
+ int (*poll)(struct psmouse *psmouse);
void (*pt_activate)(struct psmouse *psmouse);
void (*pt_deactivate)(struct psmouse *psmouse);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 97cdfd6acaca..2051bec2c394 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse)
psmouse->disconnect = synaptics_disconnect;
psmouse->reconnect = synaptics_reconnect;
psmouse->pktsize = 6;
+ /* Synaptics can usually stay in sync without extra help */
+ psmouse->resync_time = 0;
if (SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 2d0af44ac4b9..81fd7a97a93d 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -40,15 +40,15 @@ MODULE_LICENSE("GPL");
#endif
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
-module_param(xres, uint, 0);
+module_param(xres, uint, 0644);
MODULE_PARM_DESC(xres, "Horizontal screen resolution");
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
-module_param(yres, uint, 0);
+module_param(yres, uint, 0644);
MODULE_PARM_DESC(yres, "Vertical screen resolution");
static unsigned tap_time = 200;
-module_param(tap_time, uint, 0);
+module_param(tap_time, uint, 0644);
MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
struct mousedev_hw_data {
@@ -155,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
switch (code) {
case ABS_X:
size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
- if (size == 0) size = xres;
+ if (size == 0) size = xres ? : 1;
if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
@@ -164,7 +164,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
case ABS_Y:
size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
- if (size == 0) size = yres;
+ if (size == 0) size = yres ? : 1;
if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 9b1ab5e7a98d..3df5eedf8f31 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -19,12 +19,12 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/kmi.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_kmi.h>
-#include <asm/hardware/clock.h>
#define KMI_BASE (kmi->base)
@@ -72,13 +72,9 @@ static int amba_kmi_open(struct serio *io)
unsigned int divisor;
int ret;
- ret = clk_use(kmi->clk);
- if (ret)
- goto out;
-
ret = clk_enable(kmi->clk);
if (ret)
- goto clk_unuse;
+ goto out;
divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
writeb(divisor, KMICLKDIV);
@@ -97,8 +93,6 @@ static int amba_kmi_open(struct serio *io)
clk_disable:
clk_disable(kmi->clk);
- clk_unuse:
- clk_unuse(kmi->clk);
out:
return ret;
}
@@ -111,7 +105,6 @@ static void amba_kmi_close(struct serio *io)
free_irq(kmi->irq, kmi);
clk_disable(kmi->clk);
- clk_unuse(kmi->clk);
}
static int amba_kmi_probe(struct amba_device *dev, void *id)
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 4da6c86b5d76..096b6a0b5cca 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -154,7 +154,7 @@ static int ct82c710_write(struct serio *port, unsigned char c)
* See if we can find a 82C710 device. Read mouse address.
*/
-static int __init ct82c710_probe(void)
+static int __init ct82c710_detect(void)
{
outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
outb_p(0xaa, 0x3fa); /* Inverse of 55 */
@@ -163,7 +163,7 @@ static int __init ct82c710_probe(void)
outb_p(0x1b, 0x2fa); /* Inverse of e4 */
outb_p(0x0f, 0x390); /* Write index */
if (inb_p(0x391) != 0xe4) /* Config address found? */
- return -1; /* No: no 82C710 here */
+ return -ENODEV; /* No: no 82C710 here */
outb_p(0x0d, 0x390); /* Write index */
ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
@@ -175,51 +175,88 @@ static int __init ct82c710_probe(void)
return 0;
}
-static struct serio * __init ct82c710_allocate_port(void)
+static int __devinit ct82c710_probe(struct platform_device *dev)
{
- struct serio *serio;
-
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->open = ct82c710_open;
- serio->close = ct82c710_close;
- serio->write = ct82c710_write;
- serio->dev.parent = &ct82c710_device->dev;
- strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
- snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
- }
+ ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!ct82c710_port)
+ return -ENOMEM;
+
+ ct82c710_port->id.type = SERIO_8042;
+ ct82c710_port->dev.parent = &dev->dev;
+ ct82c710_port->open = ct82c710_open;
+ ct82c710_port->close = ct82c710_close;
+ ct82c710_port->write = ct82c710_write;
+ strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
+ sizeof(ct82c710_port->name));
+ snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
+ "isa%04lx/serio0", CT82C710_DATA);
+
+ serio_register_port(ct82c710_port);
+
+ return 0;
+}
+
+static int __devexit ct82c710_remove(struct platform_device *dev)
+{
+ serio_unregister_port(ct82c710_port);
- return serio;
+ return 0;
}
+static struct platform_driver ct82c710_driver = {
+ .driver = {
+ .name = "ct82c710",
+ .owner = THIS_MODULE,
+ },
+ .probe = ct82c710_probe,
+ .remove = __devexit_p(ct82c710_remove),
+};
+
+
static int __init ct82c710_init(void)
{
- if (ct82c710_probe())
- return -ENODEV;
+ int error;
- ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
- if (IS_ERR(ct82c710_device))
- return PTR_ERR(ct82c710_device);
+ error = ct82c710_detect();
+ if (error)
+ return error;
- if (!(ct82c710_port = ct82c710_allocate_port())) {
- platform_device_unregister(ct82c710_device);
- return -ENOMEM;
+ error = platform_driver_register(&ct82c710_driver);
+ if (error)
+ return error;
+
+ ct82c710_device = platform_device_alloc("ct82c710", -1);
+ if (!ct82c710_device) {
+ error = -ENOMEM;
+ goto err_unregister_driver;
}
+ error = platform_device_add_resources(ct82c710_device, &ct82c710_iores, 1);
+ if (error)
+ goto err_free_device;
+
+ error = platform_device_add(ct82c710_device);
+ if (error)
+ goto err_free_device;
+
serio_register_port(ct82c710_port);
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
CT82C710_DATA, CT82C710_IRQ);
return 0;
+
+ err_free_device:
+ platform_device_put(ct82c710_device);
+ err_unregister_driver:
+ platform_driver_unregister(&ct82c710_driver);
+ return error;
}
static void __exit ct82c710_exit(void)
{
- serio_unregister_port(ct82c710_port);
platform_device_unregister(ct82c710_device);
+ platform_driver_unregister(&ct82c710_driver);
}
module_init(ct82c710_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 273bb3b08cfa..a4c6f3522723 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -84,6 +84,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
},
},
+ {
+ .ident = "OQO Model 01",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
+ },
+ },
{ }
};
@@ -158,6 +166,20 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
},
},
+ {
+ .ident = "Sharp Actius MM20",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
+ },
+ },
+ {
+ .ident = "Sony Vaio FS-115b",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index ac86c1d1d83e..a7d91d5356a5 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -572,7 +572,7 @@ static int i8042_enable_mux_ports(void)
* LCS/Telegraphics.
*/
-static int __init i8042_check_mux(void)
+static int __devinit i8042_check_mux(void)
{
unsigned char mux_version;
@@ -600,7 +600,7 @@ static int __init i8042_check_mux(void)
* the presence of an AUX interface.
*/
-static int __init i8042_check_aux(void)
+static int __devinit i8042_check_aux(void)
{
unsigned char param;
static int i8042_check_aux_cookie;
@@ -678,7 +678,7 @@ static int __init i8042_check_aux(void)
* registers it, and reports to the user.
*/
-static int __init i8042_port_register(struct i8042_port *port)
+static int __devinit i8042_port_register(struct i8042_port *port)
{
i8042_ctr &= ~port->disable;
@@ -956,7 +956,6 @@ static int i8042_resume(struct platform_device *dev)
panic_blink = i8042_panic_blink;
return 0;
-
}
/*
@@ -969,16 +968,7 @@ static void i8042_shutdown(struct platform_device *dev)
i8042_controller_cleanup();
}
-static struct platform_driver i8042_driver = {
- .suspend = i8042_suspend,
- .resume = i8042_resume,
- .shutdown = i8042_shutdown,
- .driver = {
- .name = "i8042",
- },
-};
-
-static int __init i8042_create_kbd_port(void)
+static int __devinit i8042_create_kbd_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
@@ -1003,7 +993,7 @@ static int __init i8042_create_kbd_port(void)
return i8042_port_register(port);
}
-static int __init i8042_create_aux_port(void)
+static int __devinit i8042_create_aux_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
@@ -1028,7 +1018,7 @@ static int __init i8042_create_aux_port(void)
return i8042_port_register(port);
}
-static int __init i8042_create_mux_port(int index)
+static int __devinit i8042_create_mux_port(int index)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
@@ -1057,37 +1047,16 @@ static int __init i8042_create_mux_port(int index)
return i8042_port_register(port);
}
-static int __init i8042_init(void)
+static int __devinit i8042_probe(struct platform_device *dev)
{
int i, have_ports = 0;
int err;
- dbg_init();
-
init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func;
- 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()) {
- err = -ENODEV;
- goto err_platform_exit;
- }
-
- err = platform_driver_register(&i8042_driver);
- if (err)
- goto err_controller_cleanup;
-
- i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
- if (IS_ERR(i8042_platform_device)) {
- err = PTR_ERR(i8042_platform_device);
- goto err_unregister_driver;
- }
+ if (i8042_controller_init())
+ return -ENODEV;
if (!i8042_noaux && !i8042_check_aux()) {
if (!i8042_nomux && !i8042_check_mux()) {
@@ -1113,30 +1082,23 @@ static int __init i8042_init(void)
if (!have_ports) {
err = -ENODEV;
- goto err_unregister_device;
+ goto err_controller_cleanup;
}
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:
- platform_driver_unregister(&i8042_driver);
err_controller_cleanup:
i8042_controller_cleanup();
- err_platform_exit:
- i8042_platform_exit();
return err;
}
-static void __exit i8042_exit(void)
+static int __devexit i8042_remove(struct platform_device *dev)
{
int i;
@@ -1148,6 +1110,62 @@ static void __exit i8042_exit(void)
del_timer_sync(&i8042_timer);
+ return 0;
+}
+
+static struct platform_driver i8042_driver = {
+ .driver = {
+ .name = "i8042",
+ .owner = THIS_MODULE,
+ },
+ .probe = i8042_probe,
+ .remove = __devexit_p(i8042_remove),
+ .suspend = i8042_suspend,
+ .resume = i8042_resume,
+ .shutdown = i8042_shutdown,
+};
+
+static int __init i8042_init(void)
+{
+ int err;
+
+ dbg_init();
+
+ 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;
+
+ err = platform_driver_register(&i8042_driver);
+ if (err)
+ goto err_platform_exit;
+
+ i8042_platform_device = platform_device_alloc("i8042", -1);
+ if (!i8042_platform_device) {
+ err = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ err = platform_device_add(i8042_platform_device);
+ if (err)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(i8042_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&i8042_driver);
+ err_platform_exit:
+ i8042_platform_exit();
+
+ return err;
+}
+
+static void __exit i8042_exit(void)
+{
platform_device_unregister(i8042_platform_device);
platform_driver_unregister(&i8042_driver);
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index d857f7081adb..f08a5d0cd5fa 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -118,13 +118,12 @@ static void maceps2_close(struct serio *dev)
}
-static struct serio * __init maceps2_allocate_port(int idx)
+static struct serio * __devinit maceps2_allocate_port(int idx)
{
struct serio *serio;
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
- memset(serio, 0, sizeof(struct serio));
serio->id.type = SERIO_8042;
serio->write = maceps2_write;
serio->open = maceps2_open;
@@ -138,24 +137,13 @@ static struct serio * __init maceps2_allocate_port(int idx)
return serio;
}
-
-static int __init maceps2_init(void)
+static int __devinit maceps2_probe(struct platform_device *dev)
{
- maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
- if (IS_ERR(maceps2_device))
- return PTR_ERR(maceps2_device);
-
- port_data[0].port = &mace->perif.ps2.keyb;
- port_data[0].irq = MACEISA_KEYB_IRQ;
- port_data[1].port = &mace->perif.ps2.mouse;
- port_data[1].irq = MACEISA_MOUSE_IRQ;
-
maceps2_port[0] = maceps2_allocate_port(0);
maceps2_port[1] = maceps2_allocate_port(1);
if (!maceps2_port[0] || !maceps2_port[1]) {
kfree(maceps2_port[0]);
kfree(maceps2_port[1]);
- platform_device_unregister(maceps2_device);
return -ENOMEM;
}
@@ -165,11 +153,59 @@ static int __init maceps2_init(void)
return 0;
}
-static void __exit maceps2_exit(void)
+static int __devexit maceps2_remove(struct platform_device *dev)
{
serio_unregister_port(maceps2_port[0]);
serio_unregister_port(maceps2_port[1]);
+
+ return 0;
+}
+
+static struct platform_driver maceps2_driver = {
+ .driver = {
+ .name = "maceps2",
+ .owner = THIS_MODULE,
+ },
+ .probe = maceps2_probe,
+ .remove = __devexit_p(maceps2_remove),
+};
+
+static int __init maceps2_init(void)
+{
+ int error;
+
+ error = platform_driver_register(&maceps2_driver);
+ if (error)
+ return error;
+
+ maceps2_device = platform_device_alloc("maceps2", -1);
+ if (!maceps2_device) {
+ error = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ port_data[0].port = &mace->perif.ps2.keyb;
+ port_data[0].irq = MACEISA_KEYB_IRQ;
+ port_data[1].port = &mace->perif.ps2.mouse;
+ port_data[1].irq = MACEISA_MOUSE_IRQ;
+
+ error = platform_device_add(maceps2_device);
+ if (error)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(maceps2_device);
+ err_unregister_driver:
+ platform_driver_unregister(&maceps2_driver);
+ return error;
+}
+
+static void __exit maceps2_exit(void)
+{
platform_device_unregister(maceps2_device);
+ platform_driver_unregister(&maceps2_driver);
}
module_init(maceps2_init);
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index b44d255596c2..d3827c5fe119 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -75,13 +75,13 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void q40kbd_flush(void)
{
- int maxread = 100;
+ int maxread = 100;
unsigned long flags;
spin_lock_irqsave(&q40kbd_lock, flags);
- while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
- master_inb(KEYCODE_REG);
+ while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
+ master_inb(KEYCODE_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags);
}
@@ -97,14 +97,14 @@ static int q40kbd_open(struct serio *port)
if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
- return -1;
+ return -EBUSY;
}
- /* off we go */
- master_outb(-1, KEYBOARD_UNLOCK_REG);
- master_outb(1, KEY_IRQ_ENABLE_REG);
+ /* off we go */
+ master_outb(-1, KEYBOARD_UNLOCK_REG);
+ master_outb(1, KEY_IRQ_ENABLE_REG);
- return 0;
+ return 0;
}
static void q40kbd_close(struct serio *port)
@@ -116,48 +116,73 @@ static void q40kbd_close(struct serio *port)
q40kbd_flush();
}
-static struct serio * __init q40kbd_allocate_port(void)
+static int __devinit q40kbd_probe(struct platform_device *dev)
{
- struct serio *serio;
-
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->open = q40kbd_open;
- serio->close = q40kbd_close;
- serio->dev.parent = &q40kbd_device->dev;
- strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
- strlcpy(serio->phys, "Q40", sizeof(serio->phys));
- }
+ q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!q40kbd_port)
+ return -ENOMEM;
+
+ q40kbd_port->id.type = SERIO_8042;
+ q40kbd_port->open = q40kbd_open;
+ q40kbd_port->close = q40kbd_close;
+ q40kbd_port->dev.parent = &dev->dev;
+ strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name));
+ strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys));
+
+ serio_register_port(q40kbd_port);
+ printk(KERN_INFO "serio: Q40 kbd registered\n");
- return serio;
+ return 0;
}
+static int __devexit q40kbd_remove(struct platform_device *dev)
+{
+ serio_unregister_port(q40kbd_port);
+
+ return 0;
+}
+
+static struct platform_driver q40kbd_driver = {
+ .driver = {
+ .name = "q40kbd",
+ .owner = THIS_MODULE,
+ },
+ .probe = q40kbd_probe,
+ .remove = __devexit_p(q40kbd_remove),
+};
+
static int __init q40kbd_init(void)
{
+ int error;
+
if (!MACH_IS_Q40)
return -EIO;
- q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
- if (IS_ERR(q40kbd_device))
- return PTR_ERR(q40kbd_device);
+ error = platform_driver_register(&q40kbd_driver);
+ if (error)
+ return error;
- if (!(q40kbd_port = q40kbd_allocate_port())) {
- platform_device_unregister(q40kbd_device);
- return -ENOMEM;
- }
+ q40kbd_device = platform_device_alloc("q40kbd", -1);
+ if (!q40kbd_device)
+ goto err_unregister_driver;
- serio_register_port(q40kbd_port);
- printk(KERN_INFO "serio: Q40 kbd registered\n");
+ error = platform_device_add(q40kbd_device);
+ if (error)
+ goto err_free_device;
return 0;
+
+ err_free_device:
+ platform_device_put(q40kbd_device);
+ err_unregister_driver:
+ platform_driver_unregister(&q40kbd_driver);
+ return error;
}
static void __exit q40kbd_exit(void)
{
- serio_unregister_port(q40kbd_port);
platform_device_unregister(q40kbd_device);
+ platform_driver_unregister(&q40kbd_driver);
}
module_init(q40kbd_init);
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 3f0df3330fb2..ebd9976fc811 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -20,7 +20,6 @@
#include <linux/spinlock.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/system.h>
#include <asm/hardware/sa1111.h>
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 8e530cc970e1..2f76813c3a64 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem);
static LIST_HEAD(serio_list);
-static struct bus_type serio_bus = {
- .name = "serio",
-};
+static struct bus_type serio_bus;
static void serio_add_port(struct serio *serio);
static void serio_destroy_port(struct serio *serio);
@@ -750,11 +748,15 @@ static int serio_driver_remove(struct device *dev)
return 0;
}
+static struct bus_type serio_bus = {
+ .name = "serio",
+ .probe = serio_driver_probe,
+ .remove = serio_driver_remove,
+};
+
void __serio_register_driver(struct serio_driver *drv, struct module *owner)
{
drv->driver.bus = &serio_bus;
- drv->driver.probe = serio_driver_probe;
- drv->driver.remove = serio_driver_remove;
serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
}
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 1bd88fca0542..54a680cc704d 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -96,6 +96,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
init_waitqueue_head(&serport->wait);
tty->disc_data = serport;
+ tty->receive_room = 256;
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
return 0;
@@ -140,17 +141,6 @@ out:
}
/*
- * serport_ldisc_room() reports how much room we do have for receiving data.
- * Although we in fact have infinite room, we need to specify some value
- * here, and 256 seems to be reasonable.
- */
-
-static int serport_ldisc_room(struct tty_struct *tty)
-{
- return 256;
-}
-
-/*
* serport_ldisc_read() just waits indefinitely if everything goes well.
* However, when the serio driver closes the serio port, it finishes,
* returning 0 characters.
@@ -237,7 +227,6 @@ static struct tty_ldisc serport_ldisc = {
.read = serport_ldisc_read,
.ioctl = serport_ldisc_ioctl,
.receive_buf = serport_ldisc_receive,
- .receive_room = serport_ldisc_room,
.write_wakeup = serport_ldisc_write_wakeup
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 21d55ed4b88a..b1b14f8d4dd6 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN
if INPUT_TOUCHSCREEN
+config TOUCHSCREEN_ADS7846
+ tristate "ADS 7846 based touchscreens"
+ depends on SPI_MASTER
+ help
+ Say Y here if you have a touchscreen interface using the
+ ADS7846 controller, and your board-specific initialization
+ code includes that in its table of SPI devices.
+
+ If unsure, say N (but it's safe to say "Y").
+
+ To compile this driver as a module, choose M here: the
+ module will be called ads7846.
+
config TOUCHSCREEN_BITSY
tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
depends on SA1100_BITSY
@@ -85,7 +98,7 @@ config TOUCHSCREEN_MK712
config TOUCHSCREEN_HP600
tristate "HP Jornada 680/690 touchscreen"
- depends on SH_HP600 && SH_ADC
+ depends on SH_HP6XX && SH_ADC
help
Say Y here if you have a HP Jornada 680 or 690 and want to
support the built-in touchscreen.
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6842869c9a26..5e5557c43121 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -4,6 +4,7 @@
# Each configuration option enables a list of files.
+obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
new file mode 100644
index 000000000000..dd8c6a9ffc76
--- /dev/null
+++ b/drivers/input/touchscreen/ads7846.c
@@ -0,0 +1,625 @@
+/*
+ * ADS7846 based touchscreen and sensor driver
+ *
+ * Copyright (c) 2005 David Brownell
+ *
+ * Using code from:
+ * - corgi_ts.c
+ * Copyright (C) 2004-2005 Richard Purdie
+ * - omap_ts.[hc], ads7846.h, ts_osk.c
+ * Copyright (C) 2002 MontaVista Software
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2005 Dirk Behme
+ *
+ * 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/device.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#ifdef CONFIG_ARM
+#include <asm/mach-types.h>
+#ifdef CONFIG_ARCH_OMAP
+#include <asm/arch/gpio.h>
+#endif
+
+#else
+#define set_irq_type(irq,type) do{}while(0)
+#endif
+
+
+/*
+ * This code has been lightly tested on an ads7846.
+ * Support for ads7843 and ads7845 has only been stubbed in.
+ *
+ * Not yet done: investigate the values reported. Are x/y/pressure
+ * event values sane enough for X11? How accurate are the temperature
+ * and voltage readings? (System-specific calibration should support
+ * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
+ *
+ * app note sbaa036 talks in more detail about accurate sampling...
+ * that ought to help in situations like LCDs inducing noise (which
+ * can also be helped by using synch signals) and more generally.
+ */
+
+#define TS_POLL_PERIOD msecs_to_jiffies(10)
+
+struct ts_event {
+ /* For portability, we can't read 12 bit values using SPI (which
+ * would make the controller deliver them as native byteorder u16
+ * with msbs zeroed). Instead, we read them as two 8-byte values,
+ * which need byteswapping then range adjustment.
+ */
+ __be16 x;
+ __be16 y;
+ __be16 z1, z2;
+};
+
+struct ads7846 {
+ struct input_dev input;
+ char phys[32];
+
+ struct spi_device *spi;
+ u16 model;
+ u16 vref_delay_usecs;
+ u16 x_plate_ohms;
+
+ struct ts_event tc;
+
+ struct spi_transfer xfer[8];
+ struct spi_message msg;
+
+ spinlock_t lock;
+ struct timer_list timer; /* P: lock */
+ unsigned pendown:1; /* P: lock */
+ unsigned pending:1; /* P: lock */
+// FIXME remove "irq_disabled"
+ unsigned irq_disabled:1; /* P: lock */
+};
+
+/* leave chip selected when we're done, for quicker re-select? */
+#if 0
+#define CS_CHANGE(xfer) ((xfer).cs_change = 1)
+#else
+#define CS_CHANGE(xfer) ((xfer).cs_change = 0)
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+/* The ADS7846 has touchscreen and other sensors.
+ * Earlier ads784x chips are somewhat compatible.
+ */
+#define ADS_START (1 << 7)
+#define ADS_A2A1A0_d_y (1 << 4) /* differential */
+#define ADS_A2A1A0_d_z1 (3 << 4) /* differential */
+#define ADS_A2A1A0_d_z2 (4 << 4) /* differential */
+#define ADS_A2A1A0_d_x (5 << 4) /* differential */
+#define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */
+#define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */
+#define ADS_A2A1A0_vaux (6 << 4) /* non-differential */
+#define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */
+#define ADS_8_BIT (1 << 3)
+#define ADS_12_BIT (0 << 3)
+#define ADS_SER (1 << 2) /* non-differential */
+#define ADS_DFR (0 << 2) /* differential */
+#define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */
+#define ADS_PD10_ADC_ON (1 << 0) /* ADC on */
+#define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */
+#define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */
+
+#define MAX_12BIT ((1<<12)-1)
+
+/* leave ADC powered up (disables penirq) between differential samples */
+#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
+ | ADS_12_BIT | ADS_DFR)
+
+static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON;
+static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON;
+static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON;
+static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
+
+/* single-ended samples need to first power up reference voltage;
+ * we leave both ADC and VREF powered
+ */
+#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
+ | ADS_12_BIT | ADS_SER)
+
+static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON;
+static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Non-touchscreen sensors only use single-ended conversions.
+ */
+
+struct ser_req {
+ u8 command;
+ u16 scratch;
+ __be16 sample;
+ struct spi_message msg;
+ struct spi_transfer xfer[6];
+};
+
+static int ads7846_read12_ser(struct device *dev, unsigned command)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL);
+ int status;
+ int sample;
+ int i;
+
+ if (!req)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&req->msg.transfers);
+
+ /* activate reference, so it has time to settle; */
+ req->xfer[0].tx_buf = &ref_on;
+ req->xfer[0].len = 1;
+ req->xfer[1].rx_buf = &req->scratch;
+ req->xfer[1].len = 2;
+
+ /*
+ * for external VREF, 0 usec (and assume it's always on);
+ * for 1uF, use 800 usec;
+ * no cap, 100 usec.
+ */
+ req->xfer[1].delay_usecs = ts->vref_delay_usecs;
+
+ /* take sample */
+ req->command = (u8) command;
+ req->xfer[2].tx_buf = &req->command;
+ req->xfer[2].len = 1;
+ req->xfer[3].rx_buf = &req->sample;
+ req->xfer[3].len = 2;
+
+ /* REVISIT: take a few more samples, and compare ... */
+
+ /* turn off reference */
+ req->xfer[4].tx_buf = &ref_off;
+ req->xfer[4].len = 1;
+ req->xfer[5].rx_buf = &req->scratch;
+ req->xfer[5].len = 2;
+
+ CS_CHANGE(req->xfer[5]);
+
+ /* group all the transfers together, so we can't interfere with
+ * reading touchscreen state; disable penirq while sampling
+ */
+ for (i = 0; i < 6; i++)
+ spi_message_add_tail(&req->xfer[i], &req->msg);
+
+ disable_irq(spi->irq);
+ status = spi_sync(spi, &req->msg);
+ enable_irq(spi->irq);
+
+ if (req->msg.status)
+ status = req->msg.status;
+ sample = be16_to_cpu(req->sample);
+ sample = sample >> 4;
+ kfree(req);
+
+ return status ? status : sample;
+}
+
+#define SHOW(name) static ssize_t \
+name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ ssize_t v = ads7846_read12_ser(dev, \
+ READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \
+ if (v < 0) \
+ return v; \
+ return sprintf(buf, "%u\n", (unsigned) v); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
+
+SHOW(temp0)
+SHOW(temp1)
+SHOW(vaux)
+SHOW(vbatt)
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
+ * to retrieve touchscreen status.
+ *
+ * The SPI transfer completion callback does the real work. It reports
+ * touchscreen events and reactivates the timer (or IRQ) as appropriate.
+ */
+
+static void ads7846_rx(void *ads)
+{
+ struct ads7846 *ts = ads;
+ unsigned Rt;
+ unsigned sync = 0;
+ u16 x, y, z1, z2;
+ unsigned long flags;
+
+ /* adjust: 12 bit samples (left aligned), built from
+ * two 8 bit values writen msb-first.
+ */
+ x = be16_to_cpu(ts->tc.x) >> 4;
+ y = be16_to_cpu(ts->tc.y) >> 4;
+ z1 = be16_to_cpu(ts->tc.z1) >> 4;
+ z2 = be16_to_cpu(ts->tc.z2) >> 4;
+
+ /* range filtering */
+ if (x == MAX_12BIT)
+ x = 0;
+
+ if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+ /* compute touch pressure resistance using equation #2 */
+ Rt = z2;
+ Rt -= z1;
+ Rt *= x;
+ Rt *= ts->x_plate_ohms;
+ Rt /= z1;
+ Rt = (Rt + 2047) >> 12;
+ } else
+ Rt = 0;
+
+ /* NOTE: "pendown" is inferred from pressure; we don't rely on
+ * being able to check nPENIRQ status, or "friendly" trigger modes
+ * (both-edges is much better than just-falling or low-level).
+ *
+ * REVISIT: some boards may require reading nPENIRQ; it's
+ * needed on 7843. and 7845 reads pressure differently...
+ *
+ * REVISIT: the touchscreen might not be connected; this code
+ * won't notice that, even if nPENIRQ never fires ...
+ */
+ if (!ts->pendown && Rt != 0) {
+ input_report_key(&ts->input, BTN_TOUCH, 1);
+ sync = 1;
+ } else if (ts->pendown && Rt == 0) {
+ input_report_key(&ts->input, BTN_TOUCH, 0);
+ sync = 1;
+ }
+
+ if (Rt) {
+ input_report_abs(&ts->input, ABS_X, x);
+ input_report_abs(&ts->input, ABS_Y, y);
+ input_report_abs(&ts->input, ABS_PRESSURE, Rt);
+ sync = 1;
+ }
+ if (sync)
+ input_sync(&ts->input);
+
+#ifdef VERBOSE
+ if (Rt || ts->pendown)
+ pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
+ x, y, Rt, Rt ? "" : " UP");
+#endif
+
+ /* don't retrigger while we're suspended */
+ spin_lock_irqsave(&ts->lock, flags);
+
+ ts->pendown = (Rt != 0);
+ ts->pending = 0;
+
+ if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+ if (ts->pendown)
+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+ else if (ts->irq_disabled) {
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+ }
+ }
+
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void ads7846_timer(unsigned long handle)
+{
+ struct ads7846 *ts = (void *)handle;
+ int status = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->lock, flags);
+ if (!ts->pending) {
+ ts->pending = 1;
+ if (!ts->irq_disabled) {
+ ts->irq_disabled = 1;
+ disable_irq(ts->spi->irq);
+ }
+ status = spi_async(ts->spi, &ts->msg);
+ if (status)
+ dev_err(&ts->spi->dev, "spi_async --> %d\n",
+ status);
+ }
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
+{
+ ads7846_timer((unsigned long) handle);
+ return IRQ_HANDLED;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int
+ads7846_suspend(struct spi_device *spi, pm_message_t message)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->lock, flags);
+
+ spi->dev.power.power_state = message;
+
+ /* are we waiting for IRQ, or polling? */
+ if (!ts->pendown) {
+ if (!ts->irq_disabled) {
+ ts->irq_disabled = 1;
+ disable_irq(ts->spi->irq);
+ }
+ } else {
+ /* polling; force a final SPI completion;
+ * that will clean things up neatly
+ */
+ if (!ts->pending)
+ mod_timer(&ts->timer, jiffies);
+
+ while (ts->pendown || ts->pending) {
+ spin_unlock_irqrestore(&ts->lock, flags);
+ udelay(10);
+ spin_lock_irqsave(&ts->lock, flags);
+ }
+ }
+
+ /* we know the chip's in lowpower mode since we always
+ * leave it that way after every request
+ */
+
+ spin_unlock_irqrestore(&ts->lock, flags);
+ return 0;
+}
+
+static int ads7846_resume(struct spi_device *spi)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+ spi->dev.power.power_state = PMSG_ON;
+ return 0;
+}
+
+static int __devinit ads7846_probe(struct spi_device *spi)
+{
+ struct ads7846 *ts;
+ struct ads7846_platform_data *pdata = spi->dev.platform_data;
+ struct spi_transfer *x;
+ int i;
+
+ if (!spi->irq) {
+ dev_dbg(&spi->dev, "no IRQ?\n");
+ return -ENODEV;
+ }
+
+ if (!pdata) {
+ dev_dbg(&spi->dev, "no platform data?\n");
+ return -ENODEV;
+ }
+
+ /* don't exceed max specified sample rate */
+ if (spi->max_speed_hz > (125000 * 16)) {
+ dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+ (spi->max_speed_hz/16)/1000);
+ return -EINVAL;
+ }
+
+ /* We'd set the wordsize to 12 bits ... except that some controllers
+ * will then treat the 8 bit command words as 12 bits (and drop the
+ * four MSBs of the 12 bit result). Result: inputs must be shifted
+ * to discard the four garbage LSBs.
+ */
+
+ if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL)))
+ return -ENOMEM;
+
+ dev_set_drvdata(&spi->dev, ts);
+
+ ts->spi = spi;
+ spi->dev.power.power_state = PMSG_ON;
+
+ init_timer(&ts->timer);
+ ts->timer.data = (unsigned long) ts;
+ ts->timer.function = ads7846_timer;
+
+ ts->model = pdata->model ? : 7846;
+ ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
+ ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+
+ init_input_dev(&ts->input);
+
+ ts->input.dev = &spi->dev;
+ ts->input.name = "ADS784x Touchscreen";
+ snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id);
+ ts->input.phys = ts->phys;
+
+ ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(&ts->input, ABS_X,
+ pdata->x_min ? : 0,
+ pdata->x_max ? : MAX_12BIT,
+ 0, 0);
+ input_set_abs_params(&ts->input, ABS_Y,
+ pdata->y_min ? : 0,
+ pdata->y_max ? : MAX_12BIT,
+ 0, 0);
+ input_set_abs_params(&ts->input, ABS_PRESSURE,
+ pdata->pressure_min, pdata->pressure_max, 0, 0);
+
+ input_register_device(&ts->input);
+
+ /* set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
+ x = ts->xfer;
+
+ /* y- still on; turn on only y+ (and ADC) */
+ x->tx_buf = &read_y;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.y;
+ x->len = 2;
+ x++;
+
+ /* turn y+ off, x- on; we'll use formula #2 */
+ if (ts->model == 7846) {
+ x->tx_buf = &read_z1;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.z1;
+ x->len = 2;
+ x++;
+
+ x->tx_buf = &read_z2;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.z2;
+ x->len = 2;
+ x++;
+ }
+
+ /* turn y- off, x+ on, then leave in lowpower */
+ x->tx_buf = &read_x;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.x;
+ x->len = 2;
+ x++;
+
+ CS_CHANGE(x[-1]);
+
+ for (i = 0; i < x - ts->xfer; i++)
+ spi_message_add_tail(&ts->xfer[i], &ts->msg);
+ ts->msg.complete = ads7846_rx;
+ ts->msg.context = ts;
+
+ if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM,
+ spi->dev.bus_id, ts)) {
+ dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
+ input_unregister_device(&ts->input);
+ kfree(ts);
+ return -EBUSY;
+ }
+ set_irq_type(spi->irq, IRQT_FALLING);
+
+ dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
+
+ /* take a first sample, leaving nPENIRQ active; avoid
+ * the touchscreen, in case it's not connected.
+ */
+ (void) ads7846_read12_ser(&spi->dev,
+ READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+
+ /* ads7843/7845 don't have temperature sensors, and
+ * use the other sensors a bit differently too
+ */
+ if (ts->model == 7846) {
+ device_create_file(&spi->dev, &dev_attr_temp0);
+ device_create_file(&spi->dev, &dev_attr_temp1);
+ }
+ if (ts->model != 7845)
+ device_create_file(&spi->dev, &dev_attr_vbatt);
+ device_create_file(&spi->dev, &dev_attr_vaux);
+
+ return 0;
+}
+
+static int __devexit ads7846_remove(struct spi_device *spi)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+ ads7846_suspend(spi, PMSG_SUSPEND);
+ free_irq(ts->spi->irq, ts);
+ if (ts->irq_disabled)
+ enable_irq(ts->spi->irq);
+
+ if (ts->model == 7846) {
+ device_remove_file(&spi->dev, &dev_attr_temp0);
+ device_remove_file(&spi->dev, &dev_attr_temp1);
+ }
+ if (ts->model != 7845)
+ device_remove_file(&spi->dev, &dev_attr_vbatt);
+ device_remove_file(&spi->dev, &dev_attr_vaux);
+
+ input_unregister_device(&ts->input);
+ kfree(ts);
+
+ dev_dbg(&spi->dev, "unregistered touchscreen\n");
+ return 0;
+}
+
+static struct spi_driver ads7846_driver = {
+ .driver = {
+ .name = "ads7846",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ads7846_probe,
+ .remove = __devexit_p(ads7846_remove),
+ .suspend = ads7846_suspend,
+ .resume = ads7846_resume,
+};
+
+static int __init ads7846_init(void)
+{
+ /* grr, board-specific init should stay out of drivers!! */
+
+#ifdef CONFIG_ARCH_OMAP
+ if (machine_is_omap_osk()) {
+ /* GPIO4 = PENIRQ; GPIO6 = BUSY */
+ omap_request_gpio(4);
+ omap_set_gpio_direction(4, 1);
+ omap_request_gpio(6);
+ omap_set_gpio_direction(6, 1);
+ }
+ // also TI 1510 Innovator, bitbanging through FPGA
+ // also Nokia 770
+ // also Palm Tungsten T2
+#endif
+
+ // PXA:
+ // also Dell Axim X50
+ // also HP iPaq H191x/H192x/H415x/H435x
+ // also Intel Lubbock (additional to UCB1400; as temperature sensor)
+ // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
+
+ // Atmel at91sam9261-EK uses ads7843
+
+ // also various AMD Au1x00 devel boards
+
+ return spi_register_driver(&ads7846_driver);
+}
+module_init(ads7846_init);
+
+static void __exit ads7846_exit(void)
+{
+ spi_unregister_driver(&ads7846_driver);
+
+#ifdef CONFIG_ARCH_OMAP
+ if (machine_is_omap_osk()) {
+ omap_free_gpio(4);
+ omap_free_gpio(6);
+ }
+#endif
+
+}
+module_exit(ads7846_exit);
+
+MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index b091d1a54125..d4c50512a1ff 100644
--- a/drivers/isdn/act2000/act2000.h
+++ b/drivers/isdn/act2000/act2000.h
@@ -181,17 +181,17 @@ typedef struct act2000_card {
char regname[35]; /* Name used for request_region */
} act2000_card;
-extern __inline__ void act2000_schedule_tx(act2000_card *card)
+static inline void act2000_schedule_tx(act2000_card *card)
{
schedule_work(&card->snd_tq);
}
-extern __inline__ void act2000_schedule_rx(act2000_card *card)
+static inline void act2000_schedule_rx(act2000_card *card)
{
schedule_work(&card->rcv_tq);
}
-extern __inline__ void act2000_schedule_poll(act2000_card *card)
+static inline void act2000_schedule_poll(act2000_card *card)
{
schedule_work(&card->poll_tq);
}
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h
index f6d5f530b86b..49f453c53c64 100644
--- a/drivers/isdn/act2000/capi.h
+++ b/drivers/isdn/act2000/capi.h
@@ -78,29 +78,29 @@ typedef union actcapi_infoel { /* info element */
typedef struct actcapi_msn {
__u8 eaz;
__u8 len; /* Length of MSN */
- __u8 msn[15] __attribute__ ((packed));
-} actcapi_msn;
+ __u8 msn[15];
+} __attribute__((packed)) actcapi_msn;
typedef struct actcapi_dlpd {
__u8 len; /* Length of structure */
- __u16 dlen __attribute__ ((packed)); /* Data Length */
- __u8 laa __attribute__ ((packed)); /* Link Address A */
+ __u16 dlen; /* Data Length */
+ __u8 laa; /* Link Address A */
__u8 lab; /* Link Address B */
__u8 modulo; /* Modulo Mode */
__u8 win; /* Window size */
__u8 xid[100]; /* XID Information */
-} actcapi_dlpd;
+} __attribute__((packed)) actcapi_dlpd;
typedef struct actcapi_ncpd {
__u8 len; /* Length of structure */
- __u16 lic __attribute__ ((packed));
- __u16 hic __attribute__ ((packed));
- __u16 ltc __attribute__ ((packed));
- __u16 htc __attribute__ ((packed));
- __u16 loc __attribute__ ((packed));
- __u16 hoc __attribute__ ((packed));
- __u8 modulo __attribute__ ((packed));
-} actcapi_ncpd;
+ __u16 lic;
+ __u16 hic;
+ __u16 ltc;
+ __u16 htc;
+ __u16 loc;
+ __u16 hoc;
+ __u8 modulo;
+} __attribute__((packed)) actcapi_ncpd;
#define actcapi_ncpi actcapi_ncpd
/*
@@ -168,19 +168,19 @@ typedef struct actcapi_msg {
__u16 manuf_msg;
__u16 controller;
actcapi_msn msnmap;
- } manufacturer_req_msn;
+ } __attribute ((packed)) manufacturer_req_msn;
/* TODO: TraceInit-req/conf/ind/resp and
* TraceDump-req/conf/ind/resp
*/
struct connect_req {
__u8 controller;
__u8 bchan;
- __u32 infomask __attribute__ ((packed));
+ __u32 infomask;
__u8 si1;
__u8 si2;
__u8 eaz;
actcapi_addr addr;
- } connect_req;
+ } __attribute__ ((packed)) connect_req;
struct connect_conf {
__u16 plci;
__u16 info;
@@ -192,7 +192,7 @@ typedef struct actcapi_msg {
__u8 si2;
__u8 eaz;
actcapi_addr addr;
- } connect_ind;
+ } __attribute__ ((packed)) connect_ind;
struct connect_resp {
__u16 plci;
__u8 rejectcause;
@@ -200,14 +200,14 @@ typedef struct actcapi_msg {
struct connect_active_ind {
__u16 plci;
actcapi_addr addr;
- } connect_active_ind;
+ } __attribute__ ((packed)) connect_active_ind;
struct connect_active_resp {
__u16 plci;
} connect_active_resp;
struct connect_b3_req {
__u16 plci;
actcapi_ncpi ncpi;
- } connect_b3_req;
+ } __attribute__ ((packed)) connect_b3_req;
struct connect_b3_conf {
__u16 plci;
__u16 ncci;
@@ -217,12 +217,12 @@ typedef struct actcapi_msg {
__u16 ncci;
__u16 plci;
actcapi_ncpi ncpi;
- } connect_b3_ind;
+ } __attribute__ ((packed)) connect_b3_ind;
struct connect_b3_resp {
__u16 ncci;
__u8 rejectcause;
- actcapi_ncpi ncpi __attribute__ ((packed));
- } connect_b3_resp;
+ actcapi_ncpi ncpi;
+ } __attribute__ ((packed)) connect_b3_resp;
struct disconnect_req {
__u16 plci;
__u8 cause;
@@ -241,14 +241,14 @@ typedef struct actcapi_msg {
struct connect_b3_active_ind {
__u16 ncci;
actcapi_ncpi ncpi;
- } connect_b3_active_ind;
+ } __attribute__ ((packed)) connect_b3_active_ind;
struct connect_b3_active_resp {
__u16 ncci;
} connect_b3_active_resp;
struct disconnect_b3_req {
__u16 ncci;
actcapi_ncpi ncpi;
- } disconnect_b3_req;
+ } __attribute__ ((packed)) disconnect_b3_req;
struct disconnect_b3_conf {
__u16 ncci;
__u16 info;
@@ -257,7 +257,7 @@ typedef struct actcapi_msg {
__u16 ncci;
__u16 info;
actcapi_ncpi ncpi;
- } disconnect_b3_ind;
+ } __attribute__ ((packed)) disconnect_b3_ind;
struct disconnect_b3_resp {
__u16 ncci;
} disconnect_b3_resp;
@@ -265,7 +265,7 @@ typedef struct actcapi_msg {
__u16 plci;
actcapi_infonr nr;
actcapi_infoel el;
- } info_ind;
+ } __attribute__ ((packed)) info_ind;
struct info_resp {
__u16 plci;
} info_resp;
@@ -279,8 +279,8 @@ typedef struct actcapi_msg {
struct select_b2_protocol_req {
__u16 plci;
__u8 protocol;
- actcapi_dlpd dlpd __attribute__ ((packed));
- } select_b2_protocol_req;
+ actcapi_dlpd dlpd;
+ } __attribute__ ((packed)) select_b2_protocol_req;
struct select_b2_protocol_conf {
__u16 plci;
__u16 info;
@@ -288,49 +288,49 @@ typedef struct actcapi_msg {
struct select_b3_protocol_req {
__u16 plci;
__u8 protocol;
- actcapi_ncpd ncpd __attribute__ ((packed));
- } select_b3_protocol_req;
+ actcapi_ncpd ncpd;
+ } __attribute__ ((packed)) select_b3_protocol_req;
struct select_b3_protocol_conf {
__u16 plci;
__u16 info;
} select_b3_protocol_conf;
struct listen_req {
__u8 controller;
- __u32 infomask __attribute__ ((packed));
- __u16 eazmask __attribute__ ((packed));
- __u16 simask __attribute__ ((packed));
- } listen_req;
+ __u32 infomask;
+ __u16 eazmask;
+ __u16 simask;
+ } __attribute__ ((packed)) listen_req;
struct listen_conf {
__u8 controller;
- __u16 info __attribute__ ((packed));
- } listen_conf;
+ __u16 info;
+ } __attribute__ ((packed)) listen_conf;
struct data_b3_req {
__u16 fakencci;
__u16 datalen;
__u32 unused;
__u8 blocknr;
- __u16 flags __attribute__ ((packed));
- } data_b3_req;
+ __u16 flags;
+ } __attribute ((packed)) data_b3_req;
struct data_b3_ind {
__u16 fakencci;
__u16 datalen;
__u32 unused;
__u8 blocknr;
- __u16 flags __attribute__ ((packed));
- } data_b3_ind;
+ __u16 flags;
+ } __attribute__ ((packed)) data_b3_ind;
struct data_b3_resp {
__u16 ncci;
__u8 blocknr;
- } data_b3_resp;
+ } __attribute__ ((packed)) data_b3_resp;
struct data_b3_conf {
__u16 ncci;
__u8 blocknr;
- __u16 info __attribute__ ((packed));
- } data_b3_conf;
+ __u16 info;
+ } __attribute__ ((packed)) data_b3_conf;
} msg;
-} actcapi_msg;
+} __attribute__ ((packed)) actcapi_msg;
-extern __inline__ unsigned short
+static inline unsigned short
actcapi_nextsmsg(act2000_card *card)
{
unsigned long flags;
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 11ae0fddea04..623adbb0d13a 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -463,8 +463,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
#endif
goto bad;
}
- if (ld->receive_room &&
- ld->receive_room(mp->tty) < datalen) {
+ if (mp->tty->receive_room < datalen) {
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
printk(KERN_DEBUG "capi: no room in tty\n");
#endif
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 7b564c0dd996..0a37aded4b54 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -17,6 +17,8 @@
#include <linux/ctype.h>
#include <linux/sched.h> /* current */
+#include "capifs.h"
+
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
@@ -136,7 +138,7 @@ static struct dentry *get_node(int num)
{
char s[10];
struct dentry *root = capifs_root;
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
return lookup_one_len(s, root, sprintf(s, "%d", num));
}
@@ -157,7 +159,7 @@ void capifs_new_ncci(unsigned int number, dev_t device)
dentry = get_node(number);
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
- up(&capifs_root->d_inode->i_sem);
+ mutex_unlock(&capifs_root->d_inode->i_mutex);
}
void capifs_free_ncci(unsigned int number)
@@ -173,7 +175,7 @@ void capifs_free_ncci(unsigned int number)
}
dput(dentry);
}
- up(&capifs_root->d_inode->i_sem);
+ mutex_unlock(&capifs_root->d_inode->i_mutex);
}
static int __init capifs_init(void)
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
index cccfabc1117d..11e6f937c1e4 100644
--- a/drivers/isdn/hardware/eicon/os_4bri.c
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -16,6 +16,7 @@
#include "diva_pci.h"
#include "mi_pc.h"
#include "dsrv4bri.h"
+#include "helpers.h"
static void *diva_xdiLoadFileFile = NULL;
static dword diva_xdiLoadFileLength = 0;
@@ -815,7 +816,7 @@ diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
return (ret);
}
-void *xdiLoadFile(char *FileName, unsigned long *FileLength,
+void *xdiLoadFile(char *FileName, dword *FileLength,
unsigned long lim)
{
void *ret = diva_xdiLoadFileFile;
diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c
index 4cc44a5dd1db..f31bba5b16ff 100644
--- a/drivers/isdn/hardware/eicon/os_bri.c
+++ b/drivers/isdn/hardware/eicon/os_bri.c
@@ -16,6 +16,7 @@
#include "diva_pci.h"
#include "mi_pc.h"
#include "pc_maint.h"
+#include "dsrv_bri.h"
/*
** IMPORTS
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
index 8ac207f75e54..a296a846f296 100644
--- a/drivers/isdn/hardware/eicon/os_pri.c
+++ b/drivers/isdn/hardware/eicon/os_pri.c
@@ -18,6 +18,7 @@
#include "pc_maint.h"
#include "dsp_tst.h"
#include "diva_dma.h"
+#include "dsrv_pri.h"
/* --------------------------------------------------------------------------
OS Dependent part of XDI driver for DIVA PRI Adapter
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index c82105920d71..0ef560144be3 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -110,7 +110,7 @@ config HISAX_16_3
config HISAX_TELESPCI
bool "Teles PCI"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the Teles PCI.
See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -238,7 +238,7 @@ config HISAX_MIC
config HISAX_NETJET
bool "NETjet card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the NetJet from Traverse
Technologies.
@@ -249,7 +249,7 @@ config HISAX_NETJET
config HISAX_NETJET_U
bool "NETspider U card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the Netspider U interface ISDN card
from Traverse Technologies.
@@ -317,7 +317,7 @@ config HISAX_GAZEL
config HISAX_HFC_PCI
bool "HFC PCI-Bus cards"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
@@ -344,7 +344,7 @@ config HISAX_HFC_SX
config HISAX_ENTERNOW_PCI
bool "Formula-n enter:now PCI card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the Formula-n enter:now PCI
ISDN card.
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 5d8ee7368f7b..4abe5ff10e72 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -358,7 +358,7 @@ hdlc_fill_fifo(struct BCState *bcs)
}
}
-static inline void
+static void
HDLC_irq(struct BCState *bcs, u_int stat) {
int len;
struct sk_buff *skb;
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index b62d6b30b72b..b0ff1cc97d7c 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -476,7 +476,7 @@ Memhscx_fill_fifo(struct BCState *bcs)
}
}
-static inline void
+static void
Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
{
u_char r;
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 26c545fa223b..1b85ce166af8 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -396,17 +396,17 @@ struct isar_hw {
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
- u_char fill __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char cmd __attribute__((packed));
+ u_char fill;
+ u_char mode;
+ u_char xml;
+ u_char cmd;
#else
- u_char cmd __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char fill __attribute__((packed));
+ u_char cmd;
+ u_char xml;
+ u_char mode;
+ u_char fill;
#endif
-};
+} __attribute__((packed));
struct hdlc_hw {
union {
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.h b/drivers/isdn/hisax/hisax_fcpcipnp.h
index bd8a22e4d6a2..21fbcedf3a94 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.h
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.h
@@ -12,17 +12,17 @@ enum {
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
- u_char fill __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char cmd __attribute__((packed));
+ u_char fill;
+ u_char mode;
+ u_char xml;
+ u_char cmd;
#else
- u_char cmd __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char fill __attribute__((packed));
+ u_char cmd;
+ u_char xml;
+ u_char mode;
+ u_char fill;
#endif
-};
+} __attribute__((packed));
struct fritz_bcs {
struct hisax_b_if b_if;
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index 5fe9d42d03a3..7b1ad5e4ecda 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -119,7 +119,7 @@ hscx_fill_fifo(struct BCState *bcs)
}
}
-static inline void
+static void
hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
{
u_char r;
@@ -221,7 +221,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
}
}
-static inline void
+static void
hscx_int_main(struct IsdnCardState *cs, u_char val)
{
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
index 08563400e4fd..1f201af15a0f 100644
--- a/drivers/isdn/hisax/jade_irq.c
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -110,7 +110,7 @@ jade_fill_fifo(struct BCState *bcs)
}
-static inline void
+static void
jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
{
u_char r;
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4643df097bfe..22759c01746a 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -857,6 +857,118 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
return count;
}
+/*
+ * isdn_readbchan_tty() tries to get data from the read-queue.
+ * It MUST be called with interrupts off.
+ *
+ * Be aware that this is not an atomic operation when sleep != 0, even though
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he
+ */
+int
+isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack)
+{
+ int count;
+ int count_pull;
+ int count_put;
+ int dflag;
+ struct sk_buff *skb;
+ char last = 0;
+ int len;
+
+ if (!dev->drv[di])
+ return 0;
+ if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
+ return 0;
+
+ len = tty_buffer_request_room(tty, dev->drv[di]->rcvcount[channel]);
+ if(len == 0)
+ return len;
+
+ count = 0;
+ while (len) {
+ if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
+ break;
+#ifdef CONFIG_ISDN_AUDIO
+ if (ISDN_AUDIO_SKB_LOCK(skb))
+ break;
+ ISDN_AUDIO_SKB_LOCK(skb) = 1;
+ if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
+ char *p = skb->data;
+ unsigned long DLEmask = (1 << channel);
+
+ dflag = 0;
+ count_pull = count_put = 0;
+ while ((count_pull < skb->len) && (len > 0)) {
+ len--;
+ if (dev->drv[di]->DLEflag & DLEmask) {
+ last = DLE;
+ dev->drv[di]->DLEflag &= ~DLEmask;
+ } else {
+ last = *p;
+ if (last == DLE) {
+ dev->drv[di]->DLEflag |= DLEmask;
+ (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
+ }
+ p++;
+ count_pull++;
+ }
+ count_put++;
+ }
+ if (count_pull >= skb->len)
+ dflag = 1;
+ } else {
+#endif
+ /* No DLE's in buff, so simply copy it */
+ dflag = 1;
+ if ((count_pull = skb->len) > len) {
+ count_pull = len;
+ dflag = 0;
+ }
+ count_put = count_pull;
+ if(count_put > 1)
+ tty_insert_flip_string(tty, skb->data, count_put - 1);
+ last = skb->data[count_put] - 1;
+ len -= count_put;
+#ifdef CONFIG_ISDN_AUDIO
+ }
+#endif
+ count += count_put;
+ if (dflag) {
+ /* We got all the data in this buff.
+ * Now we can dequeue it.
+ */
+ if(cisco_hack)
+ tty_insert_flip_char(tty, last, 0xFF);
+ else
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
+ dev_kfree_skb(skb);
+ } else {
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+ /* Not yet emptied this buff, so it
+ * must stay in the queue, for further calls
+ * but we pull off the data we got until now.
+ */
+ skb_pull(skb, count_pull);
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ }
+ dev->drv[di]->rcvcount[channel] -= count_put;
+ }
+ return count;
+}
+
+
static __inline int
isdn_minor2drv(int minor)
{
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index e27e9c3a81ed..082735dbb412 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -37,6 +37,7 @@ extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+extern int isdn_readbchan_tty(int, int, struct tty_struct *, int);
extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 8c404b4e2482..f190a99604f0 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -64,37 +64,42 @@ isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
int c;
int len;
struct tty_struct *tty;
+ char last;
if (info->online) {
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
len = skb->len
#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_DLECOUNT(skb)
#endif
;
+
+ c = tty_buffer_request_room(tty, len);
if (c >= len) {
#ifdef CONFIG_ISDN_AUDIO
- if (ISDN_AUDIO_SKB_DLECOUNT(skb))
- while (skb->len--) {
+ if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+ int l = skb->len;
+ unsigned char *dp = skb->data;
+ while (--l) {
if (*skb->data == DLE)
tty_insert_flip_char(tty, DLE, 0);
- tty_insert_flip_char(tty, *skb->data++, 0);
+ tty_insert_flip_char(tty, *dp++, 0);
+ }
+ last = *dp;
} else {
#endif
- memcpy(tty->flip.char_buf_ptr,
- skb->data, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
+ if(len > 1)
+ tty_insert_flip_string(tty, skb->data, len - 1);
+ last = skb->data[len - 1];
#ifdef CONFIG_ISDN_AUDIO
}
#endif
if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
- tty->flip.flag_buf_ptr[len - 1] = 0xff;
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_insert_flip_char(tty, last, 0xFF);
+ else
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+ tty_flip_buffer_push(tty);
kfree_skb(skb);
return 1;
}
@@ -114,7 +119,6 @@ isdn_tty_readmodem(void)
int resched = 0;
int midx;
int i;
- int c;
int r;
struct tty_struct *tty;
modem_info *info;
@@ -131,20 +135,13 @@ isdn_tty_readmodem(void)
#endif
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
- if (c > 0) {
- r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
- tty->flip.char_buf_ptr,
- tty->flip.flag_buf_ptr, c, NULL);
- /* CISCO AsyncPPP Hack */
- if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
- memset(tty->flip.flag_buf_ptr, 0, r);
- tty->flip.count += r;
- tty->flip.flag_buf_ptr += r;
- tty->flip.char_buf_ptr += r;
- if (r)
- schedule_delayed_work(&tty->flip.work, 1);
- }
+ /* CISCO AsyncPPP Hack */
+ if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
+ r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0);
+ else
+ r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1);
+ if (r)
+ tty_flip_buffer_push(tty);
} else
r = 1;
} else
@@ -249,7 +246,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
}
#endif
#endif
- /* Try to deliver directly via tty-flip-buf if queue is empty */
+ /* Try to deliver directly via tty-buf if queue is empty */
spin_lock_irqsave(&info->readlock, flags);
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
if (isdn_tty_try_read(info, skb)) {
@@ -534,7 +531,7 @@ isdn_tty_senddown(modem_info * info)
/* The next routine is called once from within timer-interrupt
* triggered within isdn_tty_modem_ncarrier(). It calls
* isdn_tty_modem_result() to stuff a "NO CARRIER" Message
- * into the tty's flip-buffer.
+ * into the tty's buffer.
*/
static void
isdn_tty_modem_do_ncarrier(unsigned long data)
@@ -2347,6 +2344,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
u_long flags;
struct sk_buff *skb = NULL;
char *sp = NULL;
+ int l = strlen(msg);
if (!msg) {
printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
@@ -2359,16 +2357,16 @@ isdn_tty_at_cout(char *msg, modem_info * info)
return;
}
- /* use queue instead of direct flip, if online and */
- /* data is in queue or flip buffer is full */
- if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
- (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
- skb = alloc_skb(strlen(msg), GFP_ATOMIC);
+ /* use queue instead of direct, if online and */
+ /* data is in queue or buffer is full */
+ if ((info->online && tty_buffer_request_room(tty, l) < l) ||
+ (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
+ skb = alloc_skb(l, GFP_ATOMIC);
if (!skb) {
spin_unlock_irqrestore(&info->readlock, flags);
return;
}
- sp = skb_put(skb, strlen(msg));
+ sp = skb_put(skb, l);
#ifdef CONFIG_ISDN_AUDIO
ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
ISDN_AUDIO_SKB_LOCK(skb) = 0;
@@ -2392,9 +2390,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
if (skb) {
*sp++ = c;
} else {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ if(tty_insert_flip_char(tty, c, TTY_NORMAL) == 0)
break;
- tty_insert_flip_char(tty, c, 0);
}
}
if (skb) {
@@ -2402,12 +2399,12 @@ isdn_tty_at_cout(char *msg, modem_info * info)
dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
spin_unlock_irqrestore(&info->readlock, flags);
/* Schedule dequeuing */
- if ((dev->modempoll) && (info->rcvsched))
+ if (dev->modempoll && info->rcvsched)
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
} else {
spin_unlock_irqrestore(&info->readlock, flags);
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_flip_buffer_push(tty);
}
}
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index 19f2fcf0ae4a..b4b24335f716 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -43,7 +43,6 @@ extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
RspMessage *, int);
extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int *);
-extern inline void pullphone(char *, char *);
#ifdef DEBUG
/*
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index a0ea44c3e8b1..7d4a0ac28c06 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -149,14 +149,14 @@ config MAC_EMUMOUSEBTN
config THERM_WINDTUNNEL
tristate "Support for thermal management on Windtunnel G4s"
- depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64
+ depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64
help
This driver provides some thermostat and fan control for the desktop
G4 "Windtunnel"
config THERM_ADT746X
tristate "Support for thermal mgmnt on laptops with ADT 746x chipset"
- depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64
+ depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64
help
This driver provides some thermostat and fan control for the
iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty
@@ -164,7 +164,7 @@ config THERM_ADT746X
config THERM_PM72
tristate "Support for thermal management on PowerMac G5"
- depends on I2C && I2C_KEYWEST && PPC_PMAC64
+ depends on I2C && I2C_POWERMAC && PPC_PMAC64
help
This driver provides thermostat and fan control for the desktop
G5 machines.
@@ -175,14 +175,14 @@ config WINDFARM
config WINDFARM_PM81
tristate "Support for thermal management on iMac G5"
depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
- select I2C_PMAC_SMU
+ select I2C_POWERMAC
help
This driver provides thermal control for the iMacG5
config WINDFARM_PM91
tristate "Support for thermal management on PowerMac9,1"
depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
- select I2C_PMAC_SMU
+ select I2C_POWERMAC
help
This driver provides thermal control for the PowerMac9,1
which is the recent (SMU based) single CPU desktop G5
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index 71aeb912ec61..d56d400b6aaa 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -239,7 +239,7 @@ static int adb_iop_write(struct adb_request *req)
local_irq_save(flags);
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
req->reply_len = 0;
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index cf6a6f2248ac..314fc0830d90 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -17,6 +17,7 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <linux/init.h>
+#include <linux/ioport.h>
struct preg {
unsigned char r;
@@ -88,24 +89,26 @@ int macio_probe(void)
int macio_init(void)
{
struct device_node *adbs;
+ struct resource r;
adbs = find_compatible_devices("adb", "chrp,adb0");
if (adbs == 0)
return -ENXIO;
#if 0
- { int i;
+ { int i = 0;
printk("macio_adb_init: node = %p, addrs =", adbs->node);
- for (i = 0; i < adbs->n_addrs; ++i)
- printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size);
+ while(!of_address_to_resource(adbs, i, &r))
+ printk(" %x(%x)", r.start, r.end - r.start);
printk(", intrs =");
for (i = 0; i < adbs->n_intrs; ++i)
printk(" %x", adbs->intrs[i].line);
printk("\n"); }
#endif
-
- adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs));
+ if (of_address_to_resource(adbs, 0, &r))
+ return -ENXIO;
+ adb = ioremap(r.start, sizeof(struct adb_regs));
out_8(&adb->ctrl.r, 0);
out_8(&adb->intr.r, 0);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 228e1852a836..ed6d3174d660 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -3,6 +3,13 @@
* a MacIO ASIC. Interface to new driver model mostly
* stolen from the PCI version.
*
+ * Copyright (C) 2005 Ben. Herrenschmidt (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.
+ *
* TODO:
*
* - Don't probe below media bay by default, but instead provide
@@ -204,6 +211,9 @@ struct bus_type macio_bus_type = {
.name = "macio",
.match = macio_bus_match,
.uevent = macio_uevent,
+ .probe = macio_device_probe,
+ .remove = macio_device_remove,
+ .shutdown = macio_device_shutdown,
.suspend = macio_device_suspend,
.resume = macio_device_resume,
.dev_attrs = macio_dev_attrs,
@@ -218,12 +228,14 @@ postcore_initcall(macio_bus_driver_init);
/**
- * macio_release_dev - free a macio device structure when all users of it are finished.
+ * macio_release_dev - free a macio device structure when all users of it are
+ * finished.
* @dev: device that's been disconnected
*
- * Will be called only by the device core when all users of this macio device are
- * done. This currently means never as we don't hot remove any macio device yet,
- * though that will happen with mediabay based devices in a later implementation.
+ * Will be called only by the device core when all users of this macio device
+ * are done. This currently means never as we don't hot remove any macio
+ * device yet, though that will happen with mediabay based devices in a later
+ * implementation.
*/
static void macio_release_dev(struct device *dev)
{
@@ -242,49 +254,114 @@ static void macio_release_dev(struct device *dev)
* If this routine returns non-null, then the resource is completely
* skipped.
*/
-static int macio_resource_quirks(struct device_node *np, struct resource *res, int index)
+static int macio_resource_quirks(struct device_node *np, struct resource *res,
+ int index)
{
if (res->flags & IORESOURCE_MEM) {
/* Grand Central has too large resource 0 on some machines */
- if (index == 0 && !strcmp(np->name, "gc")) {
- np->addrs[0].size = 0x20000;
+ if (index == 0 && !strcmp(np->name, "gc"))
res->end = res->start + 0x1ffff;
- }
+
/* Airport has bogus resource 2 */
if (index >= 2 && !strcmp(np->name, "radio"))
return 1;
+
+#ifndef CONFIG_PPC64
/* DBDMAs may have bogus sizes */
- if ((res->start & 0x0001f000) == 0x00008000) {
- np->addrs[index].size = 0x100;
+ if ((res->start & 0x0001f000) == 0x00008000)
res->end = res->start + 0xff;
- }
- /* ESCC parent eats child resources. We could have added a level of hierarchy,
- * but I don't really feel the need for it */
+#endif /* CONFIG_PPC64 */
+
+ /* ESCC parent eats child resources. We could have added a
+ * level of hierarchy, but I don't really feel the need
+ * for it
+ */
if (!strcmp(np->name, "escc"))
return 1;
+
/* ESCC has bogus resources >= 3 */
- if (index >= 3 && !(strcmp(np->name, "ch-a") && strcmp(np->name, "ch-b")))
+ if (index >= 3 && !(strcmp(np->name, "ch-a") &&
+ strcmp(np->name, "ch-b")))
return 1;
+
/* Media bay has too many resources, keep only first one */
if (index > 0 && !strcmp(np->name, "media-bay"))
return 1;
+
/* Some older IDE resources have bogus sizes */
if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") &&
strcmp(np->type, "ide") && strcmp(np->type, "ata"))) {
- if (index == 0 && np->addrs[0].size > 0x1000) {
- np->addrs[0].size = 0x1000;
+ if (index == 0 && (res->end - res->start) > 0xfff)
res->end = res->start + 0xfff;
- }
- if (index == 1 && np->addrs[1].size > 0x100) {
- np->addrs[1].size = 0x100;
+ if (index == 1 && (res->end - res->start) > 0xff)
res->end = res->start + 0xff;
- }
}
}
return 0;
}
+static void macio_setup_interrupts(struct macio_dev *dev)
+{
+ struct device_node *np = dev->ofdev.node;
+ int i,j;
+
+ /* For now, we use pre-parsed entries in the device-tree for
+ * interrupt routing and addresses, but we should change that
+ * to dynamically parsed entries and so get rid of most of the
+ * clutter in struct device_node
+ */
+ for (i = j = 0; i < np->n_intrs; i++) {
+ struct resource *res = &dev->interrupt[j];
+
+ if (j >= MACIO_DEV_COUNT_IRQS)
+ break;
+ res->start = np->intrs[i].line;
+ res->flags = IORESOURCE_IO;
+ if (np->intrs[j].sense)
+ res->flags |= IORESOURCE_IRQ_LOWLEVEL;
+ else
+ res->flags |= IORESOURCE_IRQ_HIGHEDGE;
+ res->name = dev->ofdev.dev.bus_id;
+ if (macio_resource_quirks(np, res, i))
+ memset(res, 0, sizeof(struct resource));
+ else
+ j++;
+ }
+ dev->n_interrupts = j;
+}
+
+static void macio_setup_resources(struct macio_dev *dev,
+ struct resource *parent_res)
+{
+ struct device_node *np = dev->ofdev.node;
+ struct resource r;
+ int index;
+
+ for (index = 0; of_address_to_resource(np, index, &r) == 0; index++) {
+ struct resource *res = &dev->resource[index];
+ if (index >= MACIO_DEV_COUNT_RESOURCES)
+ break;
+ *res = r;
+ res->name = dev->ofdev.dev.bus_id;
+
+ if (macio_resource_quirks(np, res, index)) {
+ memset(res, 0, sizeof(struct resource));
+ continue;
+ }
+ /* Currently, we consider failure as harmless, this may
+ * change in the future, once I've found all the device
+ * tree bugs in older machines & worked around them
+ */
+ if (insert_resource(parent_res, res)) {
+ printk(KERN_WARNING "Can't request resource "
+ "%d for MacIO device %s\n",
+ index, dev->ofdev.dev.bus_id);
+ }
+ }
+ dev->n_resources = index;
+}
+
/**
* macio_add_one_device - Add one device from OF node to the device tree
* @chip: pointer to the macio_chip holding the device
@@ -294,12 +371,13 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, i
* When media-bay is changed to hotswap drivers, this function will
* be exposed to the bay driver some way...
*/
-static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct device *parent,
- struct device_node *np, struct macio_dev *in_bay,
+static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
+ struct device *parent,
+ struct device_node *np,
+ struct macio_dev *in_bay,
struct resource *parent_res)
{
struct macio_dev *dev;
- int i, j;
u32 *reg;
if (np == NULL)
@@ -326,7 +404,8 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d
/* MacIO itself has a different reg, we use it's PCI base */
if (np == chip->of_node) {
- sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", chip->lbus.index,
+ sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s",
+ chip->lbus.index,
#ifdef CONFIG_PCI
pci_resource_start(chip->lbus.pdev, 0),
#else
@@ -335,57 +414,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d
MAX_NODE_NAME_SIZE, np->name);
} else {
reg = (u32 *)get_property(np, "reg", NULL);
- sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index,
+ sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
+ chip->lbus.index,
reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name);
}
- /* For now, we use pre-parsed entries in the device-tree for
- * interrupt routing and addresses, but we should change that
- * to dynamically parsed entries and so get rid of most of the
- * clutter in struct device_node
- */
- for (i = j = 0; i < np->n_intrs; i++) {
- struct resource *res = &dev->interrupt[j];
-
- if (j >= MACIO_DEV_COUNT_IRQS)
- break;
- res->start = np->intrs[i].line;
- res->flags = IORESOURCE_IO;
- if (np->intrs[j].sense)
- res->flags |= IORESOURCE_IRQ_LOWLEVEL;
- else
- res->flags |= IORESOURCE_IRQ_HIGHEDGE;
- res->name = dev->ofdev.dev.bus_id;
- if (macio_resource_quirks(np, res, i))
- memset(res, 0, sizeof(struct resource));
- else
- j++;
- }
- dev->n_interrupts = j;
- for (i = j = 0; i < np->n_addrs; i++) {
- struct resource *res = &dev->resource[j];
-
- if (j >= MACIO_DEV_COUNT_RESOURCES)
- break;
- res->start = np->addrs[i].address;
- res->end = np->addrs[i].address + np->addrs[i].size - 1;
- res->flags = IORESOURCE_MEM;
- res->name = dev->ofdev.dev.bus_id;
- if (macio_resource_quirks(np, res, i))
- memset(res, 0, sizeof(struct resource));
- else {
- j++;
- /* Currently, we consider failure as harmless, this may
- * change in the future, once I've found all the device
- * tree bugs in older machines & worked around them
- */
- if (insert_resource(parent_res, res))
- printk(KERN_WARNING "Can't request resource %d for MacIO"
- " device %s\n", i, dev->ofdev.dev.bus_id);
- }
- }
- dev->n_resources = j;
+ /* Setup interrupts & resources */
+ macio_setup_interrupts(dev);
+ macio_setup_resources(dev, parent_res);
+ /* Register with core */
if (of_device_register(&dev->ofdev) != 0) {
printk(KERN_DEBUG"macio: device registration error for %s!\n",
dev->ofdev.dev.bus_id);
@@ -442,36 +480,42 @@ static void macio_pci_add_devices(struct macio_chip *chip)
/* First scan 1st level */
for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
- if (!macio_skip_device(np)) {
- of_node_get(np);
- mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, root_res);
- if (mdev == NULL)
- of_node_put(np);
- else if (strncmp(np->name, "media-bay", 9) == 0)
- mbdev = mdev;
- else if (strncmp(np->name, "escc", 4) == 0)
- sdev = mdev;
- }
+ if (macio_skip_device(np))
+ continue;
+ of_node_get(np);
+ mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL,
+ root_res);
+ if (mdev == NULL)
+ of_node_put(np);
+ else if (strncmp(np->name, "media-bay", 9) == 0)
+ mbdev = mdev;
+ else if (strncmp(np->name, "escc", 4) == 0)
+ sdev = mdev;
}
/* Add media bay devices if any */
if (mbdev)
- for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) != NULL;)
- if (!macio_skip_device(np)) {
- of_node_get(np);
- if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, mbdev,
- root_res) == NULL)
- of_node_put(np);
- }
+ for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np))
+ != NULL;) {
+ if (macio_skip_device(np))
+ continue;
+ of_node_get(np);
+ if (macio_add_one_device(chip, &mbdev->ofdev.dev, np,
+ mbdev, root_res) == NULL)
+ of_node_put(np);
+ }
+
/* Add serial ports if any */
if (sdev) {
- for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) != NULL;)
- if (!macio_skip_device(np)) {
- of_node_get(np);
- if (macio_add_one_device(chip, &sdev->ofdev.dev, np, NULL,
- root_res) == NULL)
- of_node_put(np);
- }
+ for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np))
+ != NULL;) {
+ if (macio_skip_device(np))
+ continue;
+ of_node_get(np);
+ if (macio_add_one_device(chip, &sdev->ofdev.dev, np,
+ NULL, root_res) == NULL)
+ of_node_put(np);
+ }
}
}
@@ -487,9 +531,6 @@ int macio_register_driver(struct macio_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &macio_bus_type;
- drv->driver.probe = macio_device_probe;
- drv->driver.remove = macio_device_remove;
- drv->driver.shutdown = macio_device_shutdown;
/* register with core */
count = driver_register(&drv->driver);
@@ -519,7 +560,8 @@ void macio_unregister_driver(struct macio_driver *drv)
* Returns 0 on success, or %EBUSY on error. A warning
* message is also printed on failure.
*/
-int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name)
+int macio_request_resource(struct macio_dev *dev, int resource_no,
+ const char *name)
{
if (macio_resource_len(dev, resource_no) == 0)
return 0;
@@ -606,20 +648,20 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi
if (ent->vendor != PCI_VENDOR_ID_APPLE)
return -ENODEV;
- /* Note regarding refcounting: We assume pci_device_to_OF_node() is ported
- * to new OF APIs and returns a node with refcount incremented. This isn't
- * the case today, but on the other hand ppc32 doesn't do refcounting. This
- * will have to be fixed when going to ppc64. --BenH.
+ /* Note regarding refcounting: We assume pci_device_to_OF_node() is
+ * ported to new OF APIs and returns a node with refcount incremented.
*/
np = pci_device_to_OF_node(pdev);
if (np == NULL)
return -ENODEV;
- /* This assumption is wrong, fix that here for now until I fix the arch */
+ /* The above assumption is wrong !!!
+ * fix that here for now until I fix the arch code
+ */
of_node_get(np);
- /* We also assume that pmac_feature will have done a get() on nodes stored
- * in the macio chips array
+ /* We also assume that pmac_feature will have done a get() on nodes
+ * stored in the macio chips array
*/
chip = macio_find(np, macio_unknown);
of_node_put(np);
@@ -639,9 +681,9 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi
/*
* HACK ALERT: The WallStreet PowerBook and some OHare based machines
- * have 2 macio ASICs. I must probe the "main" one first or IDE ordering
- * will be incorrect. So I put on "hold" the second one since it seem to
- * appear first on PCI
+ * have 2 macio ASICs. I must probe the "main" one first or IDE
+ * ordering will be incorrect. So I put on "hold" the second one since
+ * it seem to appear first on PCI
*/
if (chip->type == macio_gatwick || chip->type == macio_ohareII)
if (macio_chips[0].lbus.pdev == NULL) {
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index b856bb67169c..8dbf2852bae0 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -647,6 +647,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
struct media_bay_info* bay;
u32 __iomem *regbase;
struct device_node *ofnode;
+ unsigned long base;
int i;
ofnode = mdev->ofdev.node;
@@ -656,10 +657,11 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
if (macio_request_resources(mdev, "media-bay"))
return -EBUSY;
/* Media bay registers are located at the beginning of the
- * mac-io chip, we get the parent address for now (hrm...)
+ * mac-io chip, for now, we trick and align down the first
+ * resource passed in
*/
- regbase = (u32 __iomem *)
- ioremap(ofnode->parent->addrs[0].address, 0x100);
+ base = macio_resource_start(mdev, 0) & 0xffff0000u;
+ regbase = (u32 __iomem *)ioremap(base, 0x100);
if (regbase == NULL) {
macio_release_resources(mdev);
return -ENOMEM;
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index e8378274d710..db2ae71d07ef 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -53,7 +53,7 @@
#undef DEBUG_SMU
#ifdef DEBUG_SMU
-#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0)
+#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
#else
#define DPRINTK(fmt, args...) do { } while (0)
#endif
@@ -94,6 +94,8 @@ struct smu_device {
static struct smu_device *smu;
static DECLARE_MUTEX(smu_part_access);
+static void smu_i2c_retry(unsigned long data);
+
/*
* SMU driver low level stuff
*/
@@ -469,7 +471,6 @@ int __init smu_init (void)
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
@@ -544,6 +545,10 @@ static int smu_late_init(void)
if (!smu)
return 0;
+ init_timer(&smu->i2c_timer);
+ smu->i2c_timer.function = smu_i2c_retry;
+ smu->i2c_timer.data = (unsigned long)smu;
+
/*
* Try to request the interrupts
*/
@@ -570,7 +575,10 @@ static int smu_late_init(void)
return 0;
}
-arch_initcall(smu_late_init);
+/* This has to be before arch_initcall as the low i2c stuff relies on the
+ * above having been done before we reach arch_initcalls
+ */
+core_initcall(smu_late_init);
/*
* sysfs visibility
@@ -580,20 +588,10 @@ 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);
- }
+ for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;)
if (device_is_compatible(np, "smu-sensors"))
- of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev);
- }
-
+ of_platform_device_create(np, "smu-sensors",
+ &smu->of_dev->dev);
}
static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
@@ -712,13 +710,13 @@ static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
static void smu_i2c_retry(unsigned long data)
{
- struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data;
+ struct smu_i2c_cmd *cmd = smu->cmd_i2c_cur;
DPRINTK("SMU: i2c failure, requeuing...\n");
/* requeue command simply by resetting reply_len */
cmd->pdata[0] = 0xff;
- cmd->scmd.reply_len = 0x10;
+ cmd->scmd.reply_len = sizeof(cmd->pdata);
smu_queue_cmd(&cmd->scmd);
}
@@ -747,10 +745,8 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
*/
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);
+ BUG_ON(cmd != smu->cmd_i2c_cur);
+ mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
return;
}
@@ -764,7 +760,7 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
/* Ok, initial command complete, now poll status */
scmd->reply_buf = cmd->pdata;
- scmd->reply_len = 0x10;
+ scmd->reply_len = sizeof(cmd->pdata);
scmd->data_buf = cmd->pdata;
scmd->data_len = 1;
cmd->pdata[0] = 0;
@@ -786,7 +782,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd)
cmd->scmd.done = smu_i2c_low_completion;
cmd->scmd.misc = cmd;
cmd->scmd.reply_buf = cmd->pdata;
- cmd->scmd.reply_len = 0x10;
+ cmd->scmd.reply_len = sizeof(cmd->pdata);
cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
cmd->scmd.status = 1;
cmd->stage = 0;
@@ -909,10 +905,13 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id)
struct property *prop;
/* First query the partition info */
+ DPRINTK("SMU: Query partition infos ... (irq=%d)\n", smu->db_irq);
smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2,
smu_done_complete, &comp,
SMU_CMD_PARTITION_LATEST, id);
wait_for_completion(&comp);
+ DPRINTK("SMU: done, status: %d, reply_len: %d\n",
+ cmd.cmd.status, cmd.cmd.reply_len);
/* Partition doesn't exist (or other error) */
if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6)
@@ -975,6 +974,8 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
sprintf(pname, "sdb-partition-%02x", id);
+ DPRINTK("smu_get_sdb_partition(%02x)\n", id);
+
if (interruptible) {
int rc;
rc = down_interruptible(&smu_part_access);
@@ -986,6 +987,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
part = (struct smu_sdbp_header *)get_property(smu->of_node,
pname, size);
if (part == NULL) {
+ DPRINTK("trying to extract from SMU ...\n");
part = smu_create_sdb_partition(id);
if (part != NULL && size)
*size = part->len << 2;
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 8d0958c38b6b..4f50ee5767a2 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -630,12 +630,12 @@ static int read_eeprom(int cpu, struct mpu_data *out)
sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0);
np = of_find_node_by_path(nodename);
if (np == NULL) {
- printk(KERN_ERR "therm_pm72: Failed to retreive cpuid node from device-tree\n");
+ printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n");
return -ENODEV;
}
data = (u8 *)get_property(np, "cpuid", &len);
if (data == NULL) {
- printk(KERN_ERR "therm_pm72: Failed to retreive cpuid property from device-tree\n");
+ printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n");
of_node_put(np);
return -ENODEV;
}
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index d843a6c9c6df..2d9d79150403 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -127,39 +127,34 @@ struct adb_driver via_cuda_driver = {
#endif /* CONFIG_ADB */
#ifdef CONFIG_PPC
-int __init
-find_via_cuda(void)
+int __init find_via_cuda(void)
{
- int err;
struct adb_request req;
+ phys_addr_t taddr;
+ u32 *reg;
+ int err;
if (vias != 0)
return 1;
- vias = find_devices("via-cuda");
+ vias = of_find_node_by_name(NULL, "via-cuda");
if (vias == 0)
return 0;
- if (vias->next != 0)
- printk(KERN_WARNING "Warning: only using 1st via-cuda\n");
-
-#if 0
- { int i;
-
- printk("find_via_cuda: node = %p, addrs =", vias->node);
- for (i = 0; i < vias->n_addrs; ++i)
- printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size);
- printk(", intrs =");
- for (i = 0; i < vias->n_intrs; ++i)
- printk(" %x", vias->intrs[i].line);
- printk("\n"); }
-#endif
- if (vias->n_addrs != 1 || vias->n_intrs != 1) {
- printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n",
- vias->n_addrs, vias->n_intrs);
- if (vias->n_addrs < 1 || vias->n_intrs < 1)
- return 0;
+ reg = (u32 *)get_property(vias, "reg", NULL);
+ if (reg == NULL) {
+ printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
+ goto fail;
+ }
+ taddr = of_translate_address(vias, reg);
+ if (taddr == 0) {
+ printk(KERN_ERR "via-cuda: Can't translate address !\n");
+ goto fail;
+ }
+ via = ioremap(taddr, 0x2000);
+ if (via == NULL) {
+ printk(KERN_ERR "via-cuda: Can't map address !\n");
+ goto fail;
}
- via = ioremap(vias->addrs->address, 0x2000);
cuda_state = idle;
sys_ctrler = SYS_CTRLER_CUDA;
@@ -185,6 +180,11 @@ find_via_cuda(void)
cuda_poll();
return 1;
+
+ fail:
+ of_node_put(vias);
+ vias = NULL;
+ return 0;
}
#endif /* CONFIG_PPC */
@@ -193,10 +193,6 @@ static int __init via_cuda_start(void)
if (via == NULL)
return -ENODEV;
-#ifdef CONFIG_PPC
- request_OF_resource(vias, 0, NULL);
-#endif
-
if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ);
return -EAGAIN;
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index e9a159ad3022..2a2ffe060169 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -260,7 +260,7 @@ static int macii_write(struct adb_request *req)
return -EINVAL;
}
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
req->reply_len = 0;
@@ -295,7 +295,7 @@ static void macii_poll(void)
unsigned long flags;
local_irq_save(flags);
- if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0);
+ if (via[IFR] & SR_INT) macii_interrupt(0, NULL, NULL);
local_irq_restore(flags);
}
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index a1966975d58f..0129fcc3b183 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -294,6 +294,24 @@ static void maciisi_sync(struct adb_request *req)
printk(KERN_ERR "maciisi_send_request: poll timed out!\n");
}
+int
+maciisi_request(struct adb_request *req, void (*done)(struct adb_request *),
+ int nbytes, ...)
+{
+ va_list list;
+ int i;
+
+ req->nbytes = nbytes;
+ req->done = done;
+ req->reply_expected = 0;
+ va_start(list, nbytes);
+ for (i = 0; i < nbytes; i++)
+ req->data[i++] = va_arg(list, int);
+ va_end(list);
+
+ return maciisi_send_request(req, 1);
+}
+
/* Enqueue a request, and run the queue if possible */
static int
maciisi_write(struct adb_request* req)
@@ -308,7 +326,7 @@ maciisi_write(struct adb_request* req)
req->complete = 1;
return -EINVAL;
}
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
req->reply_len = 0;
@@ -403,7 +421,7 @@ maciisi_poll(void)
local_irq_save(flags);
if (via[IFR] & SR_INT) {
- maciisi_interrupt(0, 0, 0);
+ maciisi_interrupt(0, NULL, NULL);
}
else /* avoid calling this function too quickly in a loop */
udelay(ADB_DELAY);
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 564043508569..6eb93e45fcd3 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -55,6 +55,8 @@
#include <asm/sections.h>
#include <asm/irq.h>
#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+#include <asm/pmac_low_i2c.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/cputable.h>
@@ -147,6 +149,7 @@ static struct device_node *vias;
static int pmu_kind = PMU_UNKNOWN;
static int pmu_fully_inited = 0;
static int pmu_has_adb;
+static struct device_node *gpio_node;
static unsigned char __iomem *gpio_reg = NULL;
static int gpio_irq = -1;
static int gpio_irq_enabled = -1;
@@ -157,8 +160,8 @@ static int pmu_version;
static int drop_interrupts;
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
static int option_lid_wakeup = 1;
-static int sleep_in_progress;
#endif /* CONFIG_PM && CONFIG_PPC32 */
+static int sleep_in_progress;
static unsigned long async_req_locks;
static unsigned int pmu_irq_stats[11];
@@ -196,7 +199,6 @@ static int pmu_adb_reset_bus(void);
#endif /* CONFIG_ADB */
static int init_pmu(void);
-static int pmu_queue_request(struct adb_request *req);
static void pmu_start(void);
static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
@@ -295,22 +297,26 @@ static struct backlight_controller pmu_backlight_controller = {
};
#endif /* CONFIG_PMAC_BACKLIGHT */
-int
-find_via_pmu(void)
+int __init find_via_pmu(void)
{
+ u64 taddr;
+ u32 *reg;
+
if (via != 0)
return 1;
- vias = find_devices("via-pmu");
- if (vias == 0)
+ vias = of_find_node_by_name(NULL, "via-pmu");
+ if (vias == NULL)
return 0;
- if (vias->next != 0)
- printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
- if (vias->n_addrs < 1 || vias->n_intrs < 1) {
- printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n",
- vias->n_addrs, vias->n_intrs);
- if (vias->n_addrs < 1 || vias->n_intrs < 1)
- return 0;
+ reg = (u32 *)get_property(vias, "reg", NULL);
+ if (reg == NULL) {
+ printk(KERN_ERR "via-pmu: No \"reg\" property !\n");
+ goto fail;
+ }
+ taddr = of_translate_address(vias, reg);
+ if (taddr == OF_BAD_ADDR) {
+ printk(KERN_ERR "via-pmu: Can't translate address !\n");
+ goto fail;
}
spin_lock_init(&pmu_lock);
@@ -331,7 +337,8 @@ find_via_pmu(void)
pmu_kind = PMU_HEATHROW_BASED;
else if (device_is_compatible(vias->parent, "Keylargo")
|| device_is_compatible(vias->parent, "K2-Keylargo")) {
- struct device_node *gpio, *gpiop;
+ struct device_node *gpiop;
+ u64 gaddr = OF_BAD_ADDR;
pmu_kind = PMU_KEYLARGO_BASED;
pmu_has_adb = (find_type_devices("adb") != NULL);
@@ -341,19 +348,24 @@ find_via_pmu(void)
PMU_INT_TICK |
PMU_INT_ENVIRONMENT;
- gpiop = find_devices("gpio");
- if (gpiop && gpiop->n_addrs) {
- gpio_reg = ioremap(gpiop->addrs->address, 0x10);
- gpio = find_devices("extint-gpio1");
- if (gpio == NULL)
- gpio = find_devices("pmu-interrupt");
- if (gpio && gpio->parent == gpiop && gpio->n_intrs)
- gpio_irq = gpio->intrs[0].line;
+ gpiop = of_find_node_by_name(NULL, "gpio");
+ if (gpiop) {
+ reg = (u32 *)get_property(gpiop, "reg", NULL);
+ if (reg)
+ gaddr = of_translate_address(gpiop, reg);
+ if (gaddr != OF_BAD_ADDR)
+ gpio_reg = ioremap(gaddr, 0x10);
}
+ if (gpio_reg == NULL)
+ printk(KERN_ERR "via-pmu: Can't find GPIO reg !\n");
} else
pmu_kind = PMU_UNKNOWN;
- via = ioremap(vias->addrs->address, 0x2000);
+ via = ioremap(taddr, 0x2000);
+ if (via == NULL) {
+ printk(KERN_ERR "via-pmu: Can't map address !\n");
+ goto fail;
+ }
out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */
out_8(&via[IFR], 0x7f); /* clear IFR */
@@ -365,23 +377,25 @@ find_via_pmu(void)
return 0;
}
- printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n",
+ printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n",
PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
sys_ctrler = SYS_CTRLER_PMU;
return 1;
+ fail:
+ of_node_put(vias);
+ vias = NULL;
+ return 0;
}
#ifdef CONFIG_ADB
-static int
-pmu_probe(void)
+static int pmu_probe(void)
{
return vias == NULL? -ENODEV: 0;
}
-static int __init
-pmu_init(void)
+static int __init pmu_init(void)
{
if (vias == NULL)
return -ENODEV;
@@ -405,7 +419,7 @@ static int __init via_pmu_start(void)
bright_req_2.complete = 1;
batt_req.complete = 1;
-#if defined(CONFIG_PPC32) && !defined(CONFIG_PPC_MERGE)
+#ifndef CONFIG_PPC_MERGE
if (pmu_kind == PMU_KEYLARGO_BASED)
openpic_set_irq_priority(vias->intrs[0].line,
OPENPIC_PRIORITY_DEFAULT + 1);
@@ -418,10 +432,22 @@ static int __init via_pmu_start(void)
return -EAGAIN;
}
- if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) {
- if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0))
- printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq);
- gpio_irq_enabled = 1;
+ if (pmu_kind == PMU_KEYLARGO_BASED) {
+ gpio_node = of_find_node_by_name(NULL, "extint-gpio1");
+ if (gpio_node == NULL)
+ gpio_node = of_find_node_by_name(NULL,
+ "pmu-interrupt");
+ if (gpio_node && gpio_node->n_intrs > 0)
+ gpio_irq = gpio_node->intrs[0].line;
+
+ if (gpio_irq != -1) {
+ if (request_irq(gpio_irq, gpio1_interrupt, 0,
+ "GPIO1 ADB", (void *)0))
+ printk(KERN_ERR "pmu: can't get irq %d"
+ " (GPIO1)\n", gpio_irq);
+ else
+ gpio_irq_enabled = 1;
+ }
}
/* Enable interrupts */
@@ -454,9 +480,6 @@ static int __init via_pmu_dev_init(void)
if (vias == NULL)
return -ENODEV;
-#ifndef CONFIG_PPC64
- request_OF_resource(vias, 0, NULL);
-#endif
#ifdef CONFIG_PMAC_BACKLIGHT
/* Enable backlight */
register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
@@ -1371,7 +1394,6 @@ next:
}
pmu_done(req);
} else {
-#if defined(CONFIG_XMON) && !defined(CONFIG_PPC64)
if (len == 4 && data[1] == 0x2c) {
extern int xmon_wants_key, xmon_adb_keycode;
if (xmon_wants_key) {
@@ -1379,7 +1401,6 @@ next:
return;
}
}
-#endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */
#ifdef CONFIG_ADB
/*
* XXX On the [23]400 the PMU gives us an up
@@ -1782,258 +1803,6 @@ pmu_present(void)
return via != 0;
}
-struct pmu_i2c_hdr {
- u8 bus;
- u8 mode;
- u8 bus2;
- u8 address;
- u8 sub_addr;
- u8 comb_addr;
- u8 count;
-};
-
-int
-pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_COMBINED;
- hdr->bus2 = 0;
- hdr->sub_addr = subaddr;
- hdr->comb_addr = addr | 1;
- hdr->count = len;
-
- req.nbytes = sizeof(struct pmu_i2c_hdr) + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) {
- memcpy(data, &req.reply[1], req.reply_len - 1);
- return req.reply_len - 1;
- }
- }
- return -1;
-}
-
-int
-pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_STDSUB;
- hdr->bus2 = 0;
- hdr->sub_addr = subaddr;
- hdr->comb_addr = addr & 0xfe;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len);
- req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- return len;
- }
- return -1;
-}
-
-int
-pmu_i2c_simple_read(int bus, int addr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr | 1;
- hdr->mode = PMU_I2C_MODE_SIMPLE;
- hdr->bus2 = 0;
- hdr->sub_addr = 0;
- hdr->comb_addr = 0;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- req.nbytes = sizeof(struct pmu_i2c_hdr) + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) {
- memcpy(data, &req.reply[1], req.reply_len - 1);
- return req.reply_len - 1;
- }
- }
- return -1;
-}
-
-int
-pmu_i2c_simple_write(int bus, int addr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_SIMPLE;
- hdr->bus2 = 0;
- hdr->sub_addr = 0;
- hdr->comb_addr = 0;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len);
- req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- return len;
- }
- return -1;
-}
-
#ifdef CONFIG_PM
static LIST_HEAD(sleep_notifiers);
@@ -2338,8 +2107,9 @@ pmac_suspend_devices(void)
return -EBUSY;
}
- /* Disable clock spreading on some machines */
- pmac_tweak_clock_spreading(0);
+ /* Call platform functions marked "on sleep" */
+ pmac_pfunc_i2c_suspend();
+ pmac_pfunc_base_suspend();
/* Stop preemption */
preempt_disable();
@@ -2411,8 +2181,9 @@ pmac_wakeup_devices(void)
mdelay(10);
preempt_enable();
- /* Re-enable clock spreading on some machines */
- pmac_tweak_clock_spreading(1);
+ /* Call platform functions marked "on wake" */
+ pmac_pfunc_base_resume();
+ pmac_pfunc_i2c_resume();
/* Resume devices */
device_resume();
@@ -3130,16 +2901,13 @@ static int __init init_pmu_sysfs(void)
subsys_initcall(init_pmu_sysfs);
EXPORT_SYMBOL(pmu_request);
+EXPORT_SYMBOL(pmu_queue_request);
EXPORT_SYMBOL(pmu_poll);
EXPORT_SYMBOL(pmu_poll_adb);
EXPORT_SYMBOL(pmu_wait_complete);
EXPORT_SYMBOL(pmu_suspend);
EXPORT_SYMBOL(pmu_resume);
EXPORT_SYMBOL(pmu_unlock);
-EXPORT_SYMBOL(pmu_i2c_combined_read);
-EXPORT_SYMBOL(pmu_i2c_stdsub_write);
-EXPORT_SYMBOL(pmu_i2c_simple_read);
-EXPORT_SYMBOL(pmu_i2c_simple_write);
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
EXPORT_SYMBOL(pmu_enable_irled);
EXPORT_SYMBOL(pmu_battery_count);
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 6f80d76ac17c..f08e52f2107b 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -493,7 +493,7 @@ pmu_queue_request(struct adb_request *req)
return -EINVAL;
}
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
local_irq_save(flags);
@@ -717,7 +717,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
printk(KERN_ERR "PMU: extra ADB reply\n");
return;
}
- req_awaiting_reply = 0;
+ req_awaiting_reply = NULL;
if (len <= 2)
req->reply_len = 0;
else {
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 57460e46c89f..906d3ecae6e6 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -21,6 +21,7 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/sections.h>
+#include <asm/pmac_low_i2c.h>
#include "windfarm.h"
@@ -157,53 +158,21 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
static int wf_lm75_attach(struct i2c_adapter *adapter)
{
- u8 bus_id;
- struct device_node *smu, *bus, *dev;
-
- /* We currently only deal with LM75's hanging off the SMU
- * i2c busses. If we extend that driver to other/older
- * machines, we should split this function into SMU-i2c,
- * keywest-i2c, PMU-i2c, ...
- */
+ struct device_node *busnode, *dev;
+ struct pmac_i2c_bus *bus;
DBG("wf_lm75: adapter %s detected\n", adapter->name);
- if (strncmp(adapter->name, "smu-i2c-", 8) != 0)
- return 0;
- smu = of_find_node_by_type(NULL, "smu");
- if (smu == NULL)
- return 0;
-
- /* Look for the bus in the device-tree */
- bus_id = (u8)simple_strtoul(adapter->name + 8, NULL, 16);
-
- DBG("wf_lm75: bus ID is %x\n", bus_id);
-
- /* Look for sensors subdir */
- for (bus = NULL;
- (bus = of_get_next_child(smu, bus)) != NULL;) {
- u32 *reg;
-
- if (strcmp(bus->name, "i2c"))
- continue;
- reg = (u32 *)get_property(bus, "reg", NULL);
- if (reg == NULL)
- continue;
- if (bus_id == *reg)
- break;
- }
- of_node_put(smu);
- if (bus == NULL) {
- printk(KERN_WARNING "windfarm: SMU i2c bus 0x%x not found"
- " in device-tree !\n", bus_id);
- return 0;
- }
+ bus = pmac_i2c_adapter_to_bus(adapter);
+ if (bus == NULL)
+ return -ENODEV;
+ busnode = pmac_i2c_get_bus_node(bus);
DBG("wf_lm75: bus found, looking for device...\n");
/* Now look for lm75(s) in there */
for (dev = NULL;
- (dev = of_get_next_child(bus, dev)) != NULL;) {
+ (dev = of_get_next_child(busnode, dev)) != NULL;) {
const char *loc =
get_property(dev, "hwsensor-location", NULL);
u32 *reg = (u32 *)get_property(dev, "reg", NULL);
@@ -217,9 +186,6 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
else if (device_is_compatible(dev, "ds1775"))
wf_lm75_create(adapter, *reg, 1, loc);
}
-
- of_node_put(bus);
-
return 0;
}
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index 80ddf9776bde..eb69a601e765 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -26,7 +26,7 @@
* (typically the drive fan)
* - the main control (first control) gets the target value scaled with
* the first pair of factors, and is then modified as below
- * - the value of the target of the CPU Fan control loop is retreived,
+ * - the value of the target of the CPU Fan control loop is retrieved,
* scaled with the second pair of factors, and the max of that and
* the scaled target is applied to the main control.
*
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 2c3158c81ff2..4d811600bdab 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/completion.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c
index b558cc209d49..1a00d9c75a23 100644
--- a/drivers/macintosh/windfarm_smu_sensors.c
+++ b/drivers/macintosh/windfarm_smu_sensors.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/completion.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 76a189ceb529..eae4473eadde 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -200,7 +200,7 @@ out:
/* if page is completely empty, put it back on the free list, or dealloc it */
/* if page was hijacked, unmark the flag so it might get alloced next time */
/* Note: lock should be held when calling this */
-static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
{
char *ptr;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a601a427885c..e7a650f9ca07 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = {
};
-static inline int
+static int
crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
struct scatterlist *in, unsigned int length,
int write, sector_t sector)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 561bda5011e0..1235135b384b 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -598,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size)
/*
* Always use UUID for lookups if it's present, otherwise use name or dev.
*/
-static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
+static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
{
if (*param->uuid)
return __get_uuid_cell(param->uuid);
@@ -608,7 +608,7 @@ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
return dm_get_mdptr(huge_decode_dev(param->dev));
}
-static inline struct mapped_device *find_device(struct dm_ioctl *param)
+static struct mapped_device *find_device(struct dm_ioctl *param)
{
struct hash_cell *hc;
struct mapped_device *md = NULL;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 4b9dd8fb1e5c..87727d84dbba 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -691,7 +691,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context)
/*
* Dispatches the copy operation to kcopyd.
*/
-static inline void start_copy(struct pending_exception *pe)
+static void start_copy(struct pending_exception *pe)
{
struct dm_snapshot *s = pe->snap;
struct io_region src, dest;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 0e481512f918..8c16359f8b01 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -293,7 +293,7 @@ struct dm_table *dm_get_table(struct mapped_device *md)
* Decrements the number of outstanding ios that a bio has been
* cloned into, completing the original io if necc.
*/
-static inline void dec_pending(struct dm_io *io, int error)
+static void dec_pending(struct dm_io *io, int error)
{
if (error)
io->error = error;
@@ -768,6 +768,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
md->queue->backing_dev_info.congested_fn = dm_any_congested;
md->queue->backing_dev_info.congested_data = md;
blk_queue_make_request(md->queue, dm_request);
+ blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
md->queue->unplug_fn = dm_unplug_all;
md->queue->issue_flush_fn = dm_flush_all;
@@ -837,9 +838,9 @@ static void __set_size(struct mapped_device *md, sector_t size)
{
set_capacity(md->disk, size);
- down(&md->suspended_bdev->bd_inode->i_sem);
+ mutex_lock(&md->suspended_bdev->bd_inode->i_mutex);
i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
- up(&md->suspended_bdev->bd_inode->i_sem);
+ mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex);
}
static int __bind(struct mapped_device *md, struct dm_table *t)
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index ca99979c868a..8b3515f394a6 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -8,6 +8,7 @@
* completion notification.
*/
+#include <asm/types.h>
#include <asm/atomic.h>
#include <linux/blkdev.h>
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1b76fb29fb70..7145cd150f7b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1238,6 +1238,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
mdk_rdev_t *same_pdev;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
struct kobject *ko;
+ char *s;
if (rdev->mddev) {
MD_BUG();
@@ -1277,6 +1278,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
bdevname(rdev->bdev,b);
if (kobject_set_name(&rdev->kobj, "dev-%s", b) < 0)
return -ENOMEM;
+ while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL)
+ *s = '!';
list_add(&rdev->same_set, &mddev->disks);
rdev->mddev = mddev;
@@ -3392,6 +3395,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->ctime = get_seconds();
mddev->level = info->level;
+ mddev->clevel[0] = 0;
mddev->size = info->size;
mddev->raid_disks = info->raid_disks;
/* don't set md_minor, it is determined by which /dev/md* was
@@ -3460,9 +3464,9 @@ static int update_size(mddev_t *mddev, unsigned long size)
bdev = bdget_disk(mddev->gendisk, 0);
if (bdev) {
- down(&bdev->bd_inode->i_sem);
+ mutex_lock(&bdev->bd_inode->i_mutex);
i_size_write(bdev->bd_inode, mddev->array_size << 10);
- up(&bdev->bd_inode->i_sem);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
bdput(bdev);
}
}
@@ -3486,9 +3490,9 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
bdev = bdget_disk(mddev->gendisk, 0);
if (bdev) {
- down(&bdev->bd_inode->i_sem);
+ mutex_lock(&bdev->bd_inode->i_mutex);
i_size_write(bdev->bd_inode, mddev->array_size << 10);
- up(&bdev->bd_inode->i_sem);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
bdput(bdev);
}
}
@@ -3598,12 +3602,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
return 0;
}
+static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ mddev_t *mddev = bdev->bd_disk->private_data;
+
+ geo->heads = 2;
+ geo->sectors = 4;
+ geo->cylinders = get_capacity(mddev->gendisk) / 8;
+ return 0;
+}
+
static int md_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int err = 0;
void __user *argp = (void __user *)arg;
- struct hd_geometry __user *loc = argp;
mddev_t *mddev = NULL;
if (!capable(CAP_SYS_ADMIN))
@@ -3765,24 +3778,6 @@ static int md_ioctl(struct inode *inode, struct file *file,
* 4 sectors (with a BIG number of cylinders...). This drives
* dosfs just mad... ;-)
*/
- case HDIO_GETGEO:
- if (!loc) {
- err = -EINVAL;
- goto abort_unlock;
- }
- err = put_user (2, (char __user *) &loc->heads);
- if (err)
- goto abort_unlock;
- err = put_user (4, (char __user *) &loc->sectors);
- if (err)
- goto abort_unlock;
- err = put_user(get_capacity(mddev->gendisk)/8,
- (short __user *) &loc->cylinders);
- if (err)
- goto abort_unlock;
- err = put_user (get_start_sect(inode->i_bdev),
- (long __user *) &loc->start);
- goto done_unlock;
}
/*
@@ -3911,6 +3906,7 @@ static struct block_device_operations md_fops =
.open = md_open,
.release = md_release,
.ioctl = md_ioctl,
+ .getgeo = md_getgeo,
.media_changed = md_media_changed,
.revalidate_disk= md_revalidate,
};
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index e6aa309a66d7..96f7af4ae400 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -303,6 +303,7 @@ static void print_multipath_conf (multipath_conf_t *conf)
static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
multipath_conf_t *conf = mddev->private;
+ struct request_queue *q;
int found = 0;
int path;
struct multipath_info *p;
@@ -311,8 +312,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
for (path=0; path<mddev->raid_disks; path++)
if ((p=conf->multipaths+path)->rdev == NULL) {
- blk_queue_stack_limits(mddev->queue,
- rdev->bdev->bd_disk->queue);
+ q = rdev->bdev->bd_disk->queue;
+ blk_queue_stack_limits(mddev->queue, q);
/* as we don't honour merge_bvec_fn, we must never risk
* violating it, so limit ->max_sector to one PAGE, as
@@ -320,7 +321,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
* (Note: it is very unlikely that a device with
* merge_bvec_fn will be involved in multipath.)
*/
- if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+ if (q->merge_bvec_fn &&
mddev->queue->max_sectors > (PAGE_SIZE>>9))
blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index abbca150202b..d03f99cf4b7d 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -306,9 +306,6 @@ static int raid0_run (mddev_t *mddev)
printk("raid0 : conf->hash_spacing is %llu blocks.\n",
(unsigned long long)conf->hash_spacing);
{
-#if __GNUC__ < 3
- volatile
-#endif
sector_t s = mddev->array_size;
sector_t space = conf->hash_spacing;
int round;
@@ -439,9 +436,6 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
{
-#if __GNUC__ < 3
- volatile
-#endif
sector_t x = block >> conf->preshift;
sector_div(x, (u32)conf->hash_spacing);
zone = conf->hash_table[x];
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index a06ff91f27e2..d39f584cd8b3 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
}
}
-static inline void free_r1bio(r1bio_t *r1_bio)
+static void free_r1bio(r1bio_t *r1_bio)
{
conf_t *conf = mddev_to_conf(r1_bio->mddev);
@@ -190,7 +190,7 @@ static inline void free_r1bio(r1bio_t *r1_bio)
mempool_free(r1_bio, conf->r1bio_pool);
}
-static inline void put_buf(r1bio_t *r1_bio)
+static void put_buf(r1bio_t *r1_bio)
{
conf_t *conf = mddev_to_conf(r1_bio->mddev);
int i;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9e658e519a27..9130d051b474 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
}
}
-static inline void free_r10bio(r10bio_t *r10_bio)
+static void free_r10bio(r10bio_t *r10_bio)
{
conf_t *conf = mddev_to_conf(r10_bio->mddev);
@@ -190,7 +190,7 @@ static inline void free_r10bio(r10bio_t *r10_bio)
mempool_free(r10_bio, conf->r10bio_pool);
}
-static inline void put_buf(r10bio_t *r10_bio)
+static void put_buf(r10bio_t *r10_bio)
{
conf_t *conf = mddev_to_conf(r10_bio->mddev);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 54f4a9847e38..25976bfb6f9c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -69,7 +69,7 @@
static void print_raid5_conf (raid5_conf_t *conf);
-static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
if (!list_empty(&sh->lru))
@@ -118,7 +118,7 @@ static inline void remove_hash(struct stripe_head *sh)
hlist_del_init(&sh->hash);
}
-static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
{
struct hlist_head *hp = stripe_hash(conf, sh->sector);
@@ -178,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
static void raid5_build_block (struct stripe_head *sh, int i);
-static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
{
raid5_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks, i;
@@ -1415,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh)
}
}
-static inline void raid5_activate_delayed(raid5_conf_t *conf)
+static void raid5_activate_delayed(raid5_conf_t *conf)
{
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
while (!list_empty(&conf->delayed_list)) {
@@ -1431,7 +1431,7 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
}
}
-static inline void activate_bit_delay(raid5_conf_t *conf)
+static void activate_bit_delay(raid5_conf_t *conf)
{
/* device_lock is held */
struct list_head head;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 8c823d686a60..f618a53b98be 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -88,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks)
static void print_raid6_conf (raid6_conf_t *conf);
-static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
if (!list_empty(&sh->lru))
@@ -197,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
static void raid6_build_block (struct stripe_head *sh, int i);
-static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
{
raid6_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks, i;
@@ -1577,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
}
}
-static inline void raid6_activate_delayed(raid6_conf_t *conf)
+static void raid6_activate_delayed(raid6_conf_t *conf)
{
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
while (!list_empty(&conf->delayed_list)) {
@@ -1593,7 +1593,7 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
}
}
-static inline void activate_bit_delay(raid6_conf_t *conf)
+static void activate_bit_delay(raid6_conf_t *conf)
{
/* device_lock is held */
struct list_head head;
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 2899d34e5f7e..04c1938b9c91 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -109,10 +109,9 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
struct page *pg;
int i;
- sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
+ sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
- memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
@@ -306,15 +305,13 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
struct saa7146_dev *dev;
int err = -ENOMEM;
- dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
+ /* clear out mem for sure */
+ dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
if (!dev) {
ERR(("out of memory.\n"));
goto out;
}
- /* clear out mem for sure */
- memset(dev, 0x0, sizeof(struct saa7146_dev));
-
DEB_EE(("pci:%p\n",pci));
err = pci_enable_device(pci);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 09ec964dec5c..f8cf73ed49ad 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -239,13 +239,12 @@ static int fops_open(struct inode *inode, struct file *file)
}
/* allocate per open data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh) {
DEB_S(("cannot allocate memory for per open data.\n"));
result = -ENOMEM;
goto out;
}
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
@@ -253,7 +252,10 @@ static int fops_open(struct inode *inode, struct file *file)
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
DEB_S(("initializing vbi...\n"));
- result = saa7146_vbi_uops.open(dev,file);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ result = saa7146_vbi_uops.open(dev,file);
+ if (dev->ext_vv_data->vbi_fops.open)
+ dev->ext_vv_data->vbi_fops.open(inode, file);
} else {
DEB_S(("initializing video...\n"));
result = saa7146_video_uops.open(dev,file);
@@ -289,7 +291,10 @@ static int fops_release(struct inode *inode, struct file *file)
return -ERESTARTSYS;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- saa7146_vbi_uops.release(dev,file);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ saa7146_vbi_uops.release(dev,file);
+ if (dev->ext_vv_data->vbi_fops.release)
+ dev->ext_vv_data->vbi_fops.release(inode, file);
} else {
saa7146_video_uops.release(dev,file);
}
@@ -332,6 +337,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
BUG();
return 0;
}
+
return videobuf_mmap_mapper(q,vma);
}
@@ -381,7 +387,10 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
}
case V4L2_BUF_TYPE_VBI_CAPTURE: {
// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
- return saa7146_vbi_uops.read(file,data,count,ppos);
+ if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ return saa7146_vbi_uops.read(file,data,count,ppos);
+ else
+ return -EINVAL;
}
break;
default:
@@ -390,12 +399,31 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
}
}
+static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return -EINVAL;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (fh->dev->ext_vv_data->vbi_fops.write)
+ return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
+ else
+ return -EINVAL;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+}
+
static struct file_operations video_fops =
{
.owner = THIS_MODULE,
.open = fops_open,
.release = fops_release,
.read = fops_read,
+ .write = fops_write,
.poll = fops_poll,
.mmap = fops_mmap,
.ioctl = fops_ioctl,
@@ -435,12 +463,11 @@ static struct video_device device_template =
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
{
- struct saa7146_vv *vv = kmalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
+ struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
if( NULL == vv ) {
ERR(("out of memory. aborting.\n"));
return -1;
}
- memset(vv, 0x0, sizeof(*vv));
DEB_EE(("dev:%p\n",dev));
@@ -467,7 +494,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
saa7146_video_uops.init(dev,vv);
- saa7146_vbi_uops.init(dev,vv);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ saa7146_vbi_uops.init(dev,vv);
dev->vv_data = vv;
dev->vv_callback = &vv_callback;
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index ec52dff8cb69..33bec8a6843b 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -562,19 +562,26 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int
int b_depth = vv->ov_fmt->depth;
int b_bpl = vv->ov_fb.fmt.bytesperline;
- u32 base = (u32)vv->ov_fb.base;
+ /* The unsigned long cast is to remove a 64-bit compile warning since
+ it looks like a 64-bit address is cast to a 32-bit value, even
+ though the base pointer is really a 32-bit physical address that
+ goes into a 32-bit DMA register.
+ FIXME: might not work on some 64-bit platforms, but see the FIXME
+ in struct v4l2_framebuffer (videodev2.h) for that.
+ */
+ u32 base = (u32)(unsigned long)vv->ov_fb.base;
struct saa7146_video_dma vdma1;
/* calculate memory offsets for picture, look if we shall top-down-flip */
vdma1.pitch = 2*b_bpl;
if ( 0 == vv->vflip ) {
- vdma1.base_even = (u32)base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+ vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
}
else {
- vdma1.base_even = (u32)base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+ vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
}
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index 063986ec16b5..468d3c959075 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -500,9 +500,9 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
}
struct saa7146_use_ops saa7146_vbi_uops = {
- .init = vbi_init,
- .open = vbi_open,
+ .init = vbi_init,
+ .open = vbi_open,
.release = vbi_close,
.irq_done = vbi_irq_done,
- .read = vbi_read,
+ .read = vbi_read,
};
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 1d961023b837..7ebac7949df3 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -151,8 +151,8 @@ static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
if (V4L2_FIELD_ANY == field) {
field = (win->w.height > maxh/2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_TOP;
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_TOP;
}
switch (field) {
case V4L2_FIELD_TOP:
@@ -1114,10 +1114,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
return 0;
}
case VIDIOC_OVERLAY:
-
-
-
-
{
int on = *(int *)arg;
int err = 0;
@@ -1359,7 +1355,6 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
}
-
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct file *file = q->priv_data;
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 21a9045b3ef6..0b940e152b79 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -298,7 +298,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
}
static int lgdt3303_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+ struct dvb_frontend_parameters* params)
{
struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4];
@@ -485,12 +485,16 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
/* try to figure out the frontend, each card/box can have on of the following list */
int flexcop_frontend_init(struct flexcop_device *fc)
{
+ struct dvb_frontend_ops *ops;
+
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
- fc->fe->ops->set_voltage = flexcop_set_voltage;
+ ops = fc->fe->ops;
+
+ ops->set_voltage = flexcop_set_voltage;
- fc->fe_sleep = fc->fe->ops->sleep;
- fc->fe->ops->sleep = flexcop_sleep;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY;
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
@@ -522,15 +526,17 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
- fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
- fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst;
- fc->fe->ops->set_tone = flexcop_set_tone;
- fc->fe->ops->set_voltage = flexcop_set_voltage;
+ ops = fc->fe->ops;
+
+ ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+ ops->diseqc_send_burst = flexcop_diseqc_send_burst;
+ ops->set_tone = flexcop_set_tone;
+ ops->set_voltage = flexcop_set_voltage;
- fc->fe_sleep = fc->fe->ops->sleep;
- fc->fe->ops->sleep = flexcop_sleep;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
- fc->dev_type = FC_SKY_OLD;
+ fc->dev_type = FC_SKY_OLD;
info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
}
@@ -540,8 +546,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else {
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!");
- if (fc->fe->ops->release != NULL)
- fc->fe->ops->release(fc->fe);
+ ops = fc->fe->ops;
+ if (ops->release != NULL)
+ ops->release(fc->fe);
fc->fe = NULL;
return -EINVAL;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 23cc6431e2b8..3153f9513c63 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -39,11 +39,13 @@ extern const char *flexcop_device_names[];
/* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h"
-#elif defined(__BIG_ENDIAN)
+#else
+#if defined(__BIG_ENDIAN)
#include "flexcop_ibi_value_be.h"
#else
#error no endian defined
#endif
+#endif
#define fc_data_Tag_ID_DVB 0x3e
#define fc_data_Tag_ID_ATSC 0x3f
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 123ed96f6faa..56ba52470676 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -220,20 +220,18 @@ EXPORT_SYMBOL(flexcop_reset_block_300);
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
{
void *bus;
- struct flexcop_device *fc = kmalloc(sizeof(struct flexcop_device), GFP_KERNEL);
+ struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), GFP_KERNEL);
if (!fc) {
err("no memory");
return NULL;
}
- memset(fc, 0, sizeof(struct flexcop_device));
- bus = kmalloc(bus_specific_len, GFP_KERNEL);
+ bus = kzalloc(bus_specific_len, GFP_KERNEL);
if (!bus) {
err("no memory");
kfree(fc);
return NULL;
}
- memset(bus, 0, bus_specific_len);
fc->bus_specific = bus;
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index f29571450038..a04bb61f21f4 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -542,7 +542,7 @@ static struct pci_driver bt878_pci_driver = {
.remove = bt878_remove,
};
-static int bt878_pci_driver_registered = 0;
+static int bt878_pci_driver_registered;
/*******************************/
/* Module management functions */
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 8977c7a313df..3a2ff1cc24b7 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1341,30 +1341,40 @@ 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,
+ unsigned int mode_flags,
+ int *delay,
+ fe_status_t *status)
{
struct dst_state *state = fe->demodulator_priv;
- dst_set_freq(state, p->frequency);
- dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+ if (p != NULL) {
+ dst_set_freq(state, p->frequency);
+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
- 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);
- dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
-
- } 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) {
- 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);
+ 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);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+ } 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) {
+ 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);
+ }
+ dst_write_tuna(fe);
}
- dst_write_tuna(fe);
+ if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+ dst_read_status(fe, status);
+
+ *delay = HZ/10;
return 0;
}
@@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 2239651969c8..c650b4bf7f5f 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -283,16 +283,17 @@ 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;
}
-
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) {
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 77977e9c013e..ea27b15007e9 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -600,7 +600,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
struct dst_state* state = NULL;
switch(type) {
-#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
if (card->fe != NULL) {
@@ -608,22 +607,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
card->fe->ops->info.frequency_max = 862000000;
}
break;
-#endif
-#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
lgdt330x_reset(card);
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL)
dprintk ("dvb_bt8xx: lgdt330x detected\n");
break;
-#endif
-#ifdef BTTV_BOARD_TWINHAN_VP3021
- case BTTV_BOARD_TWINHAN_VP3021:
-#else
case BTTV_BOARD_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.
@@ -787,17 +779,15 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
return 0;
}
-static int dvb_bt8xx_probe(struct device *dev)
+static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
{
- struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
struct dvb_bt8xx_card *card;
struct pci_dev* bttv_pci_dev;
int ret;
- if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
+ if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
return -ENOMEM;
- memset(card, 0, sizeof(*card));
init_MUTEX(&card->lock);
card->bttv_nr = sub->core->nr;
strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
@@ -812,9 +802,7 @@ static int dvb_bt8xx_probe(struct device *dev)
card->irq_err_ignore = 0;
break;
-#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
-#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
@@ -823,19 +811,13 @@ static int dvb_bt8xx_probe(struct device *dev)
* DA_APP(parallel) */
break;
-#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
-#endif
card->gpio_mode = 0x0400c060;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
break;
-#ifdef BTTV_BOARD_TWINHAN_VP3021
- case BTTV_BOARD_TWINHAN_VP3021:
-#else
case BTTV_BOARD_NEBULA_DIGITV:
-#endif
case BTTV_BOARD_AVDVBT_761:
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;
@@ -907,13 +889,13 @@ static int dvb_bt8xx_probe(struct device *dev)
return ret;
}
- dev_set_drvdata(dev, card);
+ dev_set_drvdata(&sub->dev, card);
return 0;
}
-static int dvb_bt8xx_remove(struct device *dev)
+static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
{
- struct dvb_bt8xx_card *card = dev_get_drvdata(dev);
+ struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);
dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
@@ -929,21 +911,19 @@ static int dvb_bt8xx_remove(struct device *dev)
dvb_unregister_adapter(&card->dvb_adapter);
kfree(card);
-
- return 0;
}
static struct bttv_sub_driver driver = {
.drv = {
.name = "dvb-bt8xx",
- .probe = dvb_bt8xx_probe,
- .remove = dvb_bt8xx_remove,
- /* FIXME:
- * .shutdown = dvb_bt8xx_shutdown,
- * .suspend = dvb_bt8xx_suspend,
- * .resume = dvb_bt8xx_resume,
- */
},
+ .probe = dvb_bt8xx_probe,
+ .remove = dvb_bt8xx_remove,
+ /* FIXME:
+ * .shutdown = dvb_bt8xx_shutdown,
+ * .suspend = dvb_bt8xx_suspend,
+ * .resume = dvb_bt8xx_resume,
+ */
};
static int __init dvb_bt8xx_init(void)
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 7cf4c4a888ec..6018fcdba1e6 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -21,35 +21,35 @@ config DVB_CINERGYT2_TUNING
config DVB_CINERGYT2_STREAM_URB_COUNT
int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
depends on DVB_CINERGYT2_TUNING
- default "32"
+ default "32"
help
USB Request Blocks for Highspeed Stream transfers are scheduled in
a queue for the Host Controller.
Usually the default value is a safe choice.
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
+ You may increase this number if you are using this device in a
+ Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_STREAM_BUF_SIZE
int "Size of URB Stream Buffers for Highspeed Transfers"
depends on DVB_CINERGYT2_TUNING
- default "512"
+ default "512"
help
Should be a multiple of native buffer size of 512 bytes.
Default value is a safe choice.
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
+ You may increase this number if you are using this device in a
+ Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_QUERY_INTERVAL
int "Status update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING
- default "250"
+ default "250"
help
This is the interval for status readouts from the demodulator.
You may try lower values if you need more responsive signal quality
@@ -64,9 +64,9 @@ config DVB_CINERGYT2_QUERY_INTERVAL
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING
- default "yes"
+ default "yes"
help
- Enable this option if you want to use the onboard Infrared Remote
+ Enable this option if you want to use the onboard Infrared Remote
Control Receiver as Linux-Input device.
Right now only the keycode table for the default Remote Control
@@ -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 "50"
+ 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 1d69bf031fb9..c4b4c5b6b7c8 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -131,6 +131,8 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
+ int disconnect_pending;
+ atomic_t inuse;
void *streambuf;
dma_addr_t streambuf_dmahandle;
@@ -343,7 +345,7 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (cinergyt2->streaming == 0)
@@ -359,7 +361,7 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (--cinergyt2->streaming == 0)
@@ -479,23 +481,37 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- int err;
+ int err = -ERESTARTSYS;
- if ((err = dvb_generic_open(inode, file)))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+
+ if ((err = dvb_generic_open(inode, file))) {
+ up(&cinergyt2->sem);
return err;
+ }
- if (down_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
cinergyt2_sleep(cinergyt2, 0);
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
+ atomic_inc(&cinergyt2->inuse);
+
up(&cinergyt2->sem);
return 0;
}
+static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
+{
+ dvb_unregister_device(cinergyt2->fedev);
+ dvb_unregister_adapter(&cinergyt2->adapter);
+
+ cinergyt2_free_stream_urbs(cinergyt2);
+ kfree(cinergyt2);
+}
+
static int cinergyt2_release (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
@@ -504,7 +520,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work);
flush_scheduled_work();
cinergyt2_sleep(cinergyt2, 1);
@@ -512,6 +528,11 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
up(&cinergyt2->sem);
+ if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
+ warn("delayed unregister in release");
+ cinergyt2_unregister(cinergyt2);
+ }
+
return dvb_generic_release(inode, file);
}
@@ -519,7 +540,14 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
+
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+
poll_wait(file, &cinergyt2->poll_wq, wait);
+
+ up(&cinergyt2->sem);
+
return (POLLIN | POLLRDNORM | POLLPRI);
}
@@ -564,10 +592,15 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
(__u16 __user *) arg);
case FE_READ_UNCORRECTED_BLOCKS:
- /* UNC are already converted to host byte order... */
- return put_user(stat->uncorrected_block_count,
- (__u32 __user *) arg);
+ {
+ uint32_t unc_count;
+
+ unc_count = stat->uncorrected_block_count;
+ stat->uncorrected_block_count = 0;
+ /* UNC are already converted to host byte order... */
+ return put_user(unc_count,(__u32 __user *) arg);
+ }
case FE_SET_FRONTEND:
{
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
@@ -580,7 +613,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
return -EFAULT;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
@@ -691,7 +724,7 @@ static void cinergyt2_query_rc (void *data)
struct cinergyt2_rc_event rc_events[12];
int n, len, i;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
@@ -786,7 +819,6 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
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);
}
@@ -817,7 +849,7 @@ static void cinergyt2_query (void *data)
uint8_t lock_bits;
uint32_t unc;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
unc = s->uncorrected_block_count;
@@ -917,28 +949,25 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (down_interruptible(&cinergyt2->sem))
- return;
+ flush_scheduled_work();
cinergyt2_unregister_rc(cinergyt2);
+ cancel_delayed_work(&cinergyt2->query_work);
+ wake_up_interruptible(&cinergyt2->poll_wq);
+
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
- dvb_net_release(&cinergyt2->dvbnet);
- dvb_dmxdev_release(&cinergyt2->dmxdev);
- dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_device(cinergyt2->fedev);
- dvb_unregister_adapter(&cinergyt2->adapter);
+ cinergyt2->disconnect_pending = 1;
- cinergyt2_free_stream_urbs(cinergyt2);
- up(&cinergyt2->sem);
- kfree(cinergyt2);
+ if (!atomic_read(&cinergyt2->inuse))
+ cinergyt2_unregister(cinergyt2);
}
static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (state.event > PM_EVENT_ON) {
@@ -961,7 +990,7 @@ static int cinergyt2_resume (struct usb_interface *intf)
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (!cinergyt2->sleeping) {
@@ -1014,4 +1043,3 @@ module_exit (cinergyt2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
-
diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig
index a9a7b3421048..12ee912a5705 100644
--- a/drivers/media/dvb/dvb-core/Kconfig
+++ b/drivers/media/dvb/dvb-core/Kconfig
@@ -5,7 +5,7 @@ config DVB_CORE
help
DVB core utility functions for device handling, software fallbacks etc.
Say Y when you have a DVB card and want to use it. Say Y if your want
- to build your drivers outside the kernel, but need the DVB core. All
+ to build your drivers outside the kernel, but need the DVB core. All
in-kernel drivers will select this automatically if needed.
If unsure say N.
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index c6baac20f529..7adb50c1e8eb 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -3,7 +3,7 @@
#
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_ca_en50221.o dvb_frontend.o \
+ dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 5956c35d34ac..00347a750681 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1649,21 +1649,17 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
return -EINVAL;
/* initialise the system data */
- if ((ca =
- (struct dvb_ca_private *) kmalloc(sizeof(struct dvb_ca_private),
- GFP_KERNEL)) == NULL) {
+ if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto error;
}
- memset(ca, 0, sizeof(struct dvb_ca_private));
ca->pub = pubca;
ca->flags = flags;
ca->slot_count = slot_count;
- if ((ca->slot_info = kmalloc(sizeof(struct dvb_ca_slot) * slot_count, GFP_KERNEL)) == NULL) {
+ if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto error;
}
- memset(ca->slot_info, 0, sizeof(struct dvb_ca_slot) * slot_count);
init_waitqueue_head(&ca->wait_queue);
ca->thread_pid = 0;
init_waitqueue_head(&ca->thread_queue);
@@ -1745,9 +1741,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
- if (ca->slot_info[i].rx_buffer.data != NULL) {
- vfree(ca->slot_info[i].rx_buffer.data);
- }
+ vfree(ca->slot_info[i].rx_buffer.data);
}
kfree(ca->slot_info);
dvb_unregister_device(ca->dvbdev);
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c
index c49fd0bd7181..772003fb1821 100644
--- a/drivers/media/dvb/dvb-core/dvb_filter.c
+++ b/drivers/media/dvb/dvb-core/dvb_filter.c
@@ -409,16 +409,16 @@ static u8 *skip_pes_header(u8 **bufp)
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
- pts = buf+9;
+ pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
- if (buf == inbuf + 6 + 16) {
- break;
- }
+ if (buf == inbuf + 6 + 16) {
+ break;
+ }
if ((*buf & 0xc0) == 0x40)
- buf += 2;
+ buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
@@ -529,9 +529,9 @@ static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_t
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
- | ( INIT_VERTICAL_SIZE << 8 )
- | ( INIT_ASPECT_RATIO << 4 )
- | ( INIT_FRAME_RATE );
+ | ( INIT_VERTICAL_SIZE << 8 )
+ | ( INIT_ASPECT_RATIO << 4 )
+ | ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 95ea5095e07e..771f32d889e6 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex);
struct dvb_frontend_private {
+ /* thread/frontend values */
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters;
struct dvb_fe_events events;
@@ -100,20 +101,25 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue;
pid_t thread_pid;
unsigned long release_jiffies;
- int state;
- int bending;
- int lnb_drift;
- int inversion;
- int auto_step;
- int auto_sub_step;
- int started_auto_step;
- int min_delay;
- int max_drift;
- int step_size;
- int exit;
- int wakeup;
+ unsigned int exit;
+ unsigned int wakeup;
fe_status_t status;
- fe_sec_tone_mode_t tone;
+ unsigned long tune_mode_flags;
+ unsigned int delay;
+
+ /* swzigzag values */
+ unsigned int state;
+ unsigned int bending;
+ int lnb_drift;
+ unsigned int inversion;
+ unsigned int auto_step;
+ unsigned int auto_sub_step;
+ unsigned int started_auto_step;
+ unsigned int min_delay;
+ unsigned int max_drift;
+ unsigned int step_size;
+ int quality;
+ unsigned int check_wrapped;
};
@@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe);
}
-static void update_delay(int *quality, int *delay, int min_delay, int locked)
+static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{
- int q2;
+ int q2;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __FUNCTION__);
- if (locked)
- (*quality) = (*quality * 220 + 36*256) / 256;
- else
- (*quality) = (*quality * 220 + 0) / 256;
+ if (locked)
+ (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+ else
+ (fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
- q2 = *quality - 128;
- q2 *= q2;
+ q2 = fepriv->quality - 128;
+ q2 *= q2;
- *delay = min_delay + q2 * HZ / (128*128);
+ fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
}
/**
@@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked)
* @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
* @returns Number of complete iterations that have been performed.
*/
-static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
+static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{
int autoinversion;
int ready = 0;
@@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
return 0;
}
+static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+{
+ fe_status_t s;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+ /* if we've got no parameters, just keep idling */
+ if (fepriv->state & FESTATE_IDLE) {
+ fepriv->delay = 3*HZ;
+ fepriv->quality = 0;
+ return;
+ }
+
+ /* in SCAN mode, we just set the frontend when asked and leave it alone */
+ if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
+ if (fepriv->state & FESTATE_RETUNE) {
+ if (fe->ops->set_frontend)
+ fe->ops->set_frontend(fe, &fepriv->parameters);
+ fepriv->state = FESTATE_TUNED;
+ }
+ fepriv->delay = 3*HZ;
+ fepriv->quality = 0;
+ return;
+ }
+
+ /* get the frontend status */
+ if (fepriv->state & FESTATE_RETUNE) {
+ s = 0;
+ } else {
+ if (fe->ops->read_status)
+ fe->ops->read_status(fe, &s);
+ if (s != fepriv->status) {
+ dvb_frontend_add_event(fe, s);
+ fepriv->status = s;
+ }
+ }
+
+ /* if we're not tuned, and we have a lock, move to the TUNED state */
+ if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ fepriv->state = FESTATE_TUNED;
+
+ /* if we're tuned, then we have determined the correct inversion */
+ if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+ (fepriv->parameters.inversion == INVERSION_AUTO)) {
+ fepriv->parameters.inversion = fepriv->inversion;
+ }
+ return;
+ }
+
+ /* if we are tuned already, check we're still locked */
+ if (fepriv->state & FESTATE_TUNED) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ /* we're tuned, and the lock is still good... */
+ if (s & FE_HAS_LOCK) {
+ return;
+ } else { /* if we _WERE_ tuned, but now don't have a lock */
+ fepriv->state = FESTATE_ZIGZAG_FAST;
+ fepriv->started_auto_step = fepriv->auto_step;
+ fepriv->check_wrapped = 0;
+ }
+ }
+
+ /* don't actually do anything if we're in the LOSTLOCK state,
+ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
+ if ((fepriv->state & FESTATE_LOSTLOCK) &&
+ (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ return;
+ }
+
+ /* don't do anything if we're in the DISEQC state, since this
+ * might be someone with a motorized dish controlled by DISEQC.
+ * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
+ if (fepriv->state & FESTATE_DISEQC) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ return;
+ }
+
+ /* if we're in the RETUNE state, set everything up for a brand
+ * new scan, keeping the current inversion setting, as the next
+ * tune is _very_ likely to require the same */
+ if (fepriv->state & FESTATE_RETUNE) {
+ fepriv->lnb_drift = 0;
+ fepriv->auto_step = 0;
+ fepriv->auto_sub_step = 0;
+ fepriv->started_auto_step = 0;
+ fepriv->check_wrapped = 0;
+ }
+
+ /* fast zigzag. */
+ if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
+ fepriv->delay = fepriv->min_delay;
+
+ /* peform a tune */
+ if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
+ /* OK, if we've run out of trials at the fast speed.
+ * Drop back to slow for the _next_ attempt */
+ fepriv->state = FESTATE_SEARCHING_SLOW;
+ fepriv->started_auto_step = fepriv->auto_step;
+ return;
+ }
+ fepriv->check_wrapped = 1;
+
+ /* if we've just retuned, enter the ZIGZAG_FAST state.
+ * This ensures we cannot return from an
+ * FE_SET_FRONTEND ioctl before the first frontend tune
+ * occurs */
+ if (fepriv->state & FESTATE_RETUNE) {
+ fepriv->state = FESTATE_TUNING_FAST;
+ }
+ }
+
+ /* slow zigzag */
+ if (fepriv->state & FESTATE_SEARCHING_SLOW) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ /* Note: don't bother checking for wrapping; we stay in this
+ * state until we get a lock */
+ dvb_frontend_swzigzag_autotune(fe, 0);
+ }
+}
+
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -330,7 +459,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
if (fepriv->dvbdev->writers == 1)
if (time_after(jiffies, fepriv->release_jiffies +
- dvb_shutdown_timeout * HZ))
+ dvb_shutdown_timeout * HZ))
return 1;
return 0;
@@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
wake_up_interruptible(&fepriv->wait_queue);
}
-/*
- * FIXME: use linux/kthread.h
- */
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
- int quality = 0, delay = 3*HZ;
fe_status_t s;
- int check_wrapped = 0;
+ struct dvb_frontend_parameters *params;
dprintk("%s\n", __FUNCTION__);
@@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data)
sigfillset(&current->blocked);
unlock_kernel();
+ fepriv->check_wrapped = 0;
+ fepriv->quality = 0;
+ fepriv->delay = 3*HZ;
fepriv->status = 0;
dvb_frontend_init(fe);
fepriv->wakeup = 0;
@@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data)
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe),
- delay);
+ fepriv->delay);
if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
@@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data)
if (down_interruptible(&fepriv->sem))
break;
- /* if we've got no parameters, just keep idling */
- if (fepriv->state & FESTATE_IDLE) {
- delay = 3*HZ;
- quality = 0;
- continue;
- }
+ /* do an iteration of the tuning loop */
+ if (fe->ops->tune) {
+ /* have we been asked to retune? */
+ params = NULL;
+ if (fepriv->state & FESTATE_RETUNE) {
+ params = &fepriv->parameters;
+ fepriv->state = FESTATE_TUNED;
+ }
- /* get the frontend status */
- if (fepriv->state & FESTATE_RETUNE) {
- s = 0;
- } else {
- if (fe->ops->read_status)
- fe->ops->read_status(fe, &s);
+ fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
- }
- /* if we're not tuned, and we have a lock, move to the TUNED state */
- if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- fepriv->state = FESTATE_TUNED;
-
- /* if we're tuned, then we have determined the correct inversion */
- if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
- (fepriv->parameters.inversion == INVERSION_AUTO)) {
- fepriv->parameters.inversion = fepriv->inversion;
- }
- continue;
- }
-
- /* if we are tuned already, check we're still locked */
- if (fepriv->state & FESTATE_TUNED) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
-
- /* we're tuned, and the lock is still good... */
- if (s & FE_HAS_LOCK)
- continue;
- else { /* if we _WERE_ tuned, but now don't have a lock */
- fepriv->state = FESTATE_ZIGZAG_FAST;
- fepriv->started_auto_step = fepriv->auto_step;
- check_wrapped = 0;
- }
- }
-
- /* don't actually do anything if we're in the LOSTLOCK state,
- * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
- if ((fepriv->state & FESTATE_LOSTLOCK) &&
- (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- continue;
- }
-
- /* don't do anything if we're in the DISEQC state, since this
- * might be someone with a motorized dish controlled by DISEQC.
- * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
- if (fepriv->state & FESTATE_DISEQC) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- continue;
- }
-
- /* if we're in the RETUNE state, set everything up for a brand
- * new scan, keeping the current inversion setting, as the next
- * tune is _very_ likely to require the same */
- if (fepriv->state & FESTATE_RETUNE) {
- fepriv->lnb_drift = 0;
- fepriv->auto_step = 0;
- fepriv->auto_sub_step = 0;
- fepriv->started_auto_step = 0;
- check_wrapped = 0;
- }
-
- /* fast zigzag. */
- if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
- delay = fepriv->min_delay;
-
- /* peform a tune */
- if (dvb_frontend_autotune(fe, check_wrapped)) {
- /* OK, if we've run out of trials at the fast speed.
- * Drop back to slow for the _next_ attempt */
- fepriv->state = FESTATE_SEARCHING_SLOW;
- fepriv->started_auto_step = fepriv->auto_step;
- continue;
- }
- check_wrapped = 1;
-
- /* if we've just retuned, enter the ZIGZAG_FAST state.
- * This ensures we cannot return from an
- * FE_SET_FRONTEND ioctl before the first frontend tune
- * occurs */
- if (fepriv->state & FESTATE_RETUNE) {
- fepriv->state = FESTATE_TUNING_FAST;
- }
- }
-
- /* slow zigzag */
- if (fepriv->state & FESTATE_SEARCHING_SLOW) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
-
- /* Note: don't bother checking for wrapping; we stay in this
- * state until we get a lock */
- dvb_frontend_autotune(fe, 0);
+ } else {
+ dvb_frontend_swzigzag(fe);
}
}
@@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
- fepriv->tone = (fe_sec_tone_mode_t) parg;
}
break;
@@ -747,7 +788,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_DISHNETWORK_SEND_LEGACY_CMD:
if (fe->ops->dishnetwork_send_legacy_command) {
- err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
+ err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} else if (fe->ops->set_voltage) {
@@ -767,13 +808,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
- unsigned int cmd = ((unsigned int) parg) << 1;
+ unsigned long cmd = ((unsigned long) parg) << 1;
struct timeval nexttime;
struct timeval tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
- printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd);
+ printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -814,7 +855,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_ENABLE_HIGH_LNB_VOLTAGE:
if (fe->ops->enable_high_lnb_voltage)
- err = fe->ops->enable_high_lnb_voltage(fe, (int) parg);
+ err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
break;
case FE_SET_FRONTEND: {
@@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
}
break;
+
+ case FE_SET_FRONTEND_TUNE_MODE:
+ fepriv->tune_mode_flags = (unsigned long) parg;
+ break;
};
up (&fepriv->sem);
@@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
+
+ /* normal tune mode when opened R/W */
+ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
}
return ret;
@@ -976,13 +1024,12 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
if (down_interruptible (&frontend_mutex))
return -ERESTARTSYS;
- fe->frontend_priv = kmalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
+ fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
if (fe->frontend_priv == NULL) {
up(&frontend_mutex);
return -ENOMEM;
}
fepriv = fe->frontend_priv;
- memset(fe->frontend_priv, 0, sizeof(struct dvb_frontend_private));
init_MUTEX (&fepriv->sem);
init_waitqueue_head (&fepriv->wait_queue);
@@ -990,7 +1037,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
init_MUTEX (&fepriv->events.sem);
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
- fepriv->tone = SEC_TONE_OFF;
printk ("DVB: registering frontend %i (%s)...\n",
fe->dvb->num,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 1e0840d02f1f..70a6d14efda7 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -58,10 +58,19 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
+ /* if this is set, it overrides the default swzigzag */
+ int (*tune)(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ unsigned int mode_flags,
+ int *delay,
+ fe_status_t *status);
+
+ /* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
- int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
+ int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
@@ -74,8 +83,9 @@ struct dvb_frontend_ops {
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg);
- int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+ int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
+ int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
+ int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
};
#define MAX_EVENT 8
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 86bba81e851e..6711eb6a058c 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1222,7 +1222,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
return if_num;
}
-static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
+static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num)
{
struct net_device *net = dvbnet->device[num];
struct dvb_net_priv *priv;
@@ -1296,9 +1296,9 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if ((unsigned int) parg >= DVB_NET_DEVICES_MAX)
+ if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
return -EINVAL;
- ret = dvb_net_remove_if(dvbnet, (unsigned int) parg);
+ ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
if (!ret)
module_put(dvbdev->adapter->module);
return ret;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 283c6e9339a4..77ad2410f4d3 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -112,10 +112,10 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
if (!usermem)
- memcpy(buf, rbuf->data+rbuf->pread, split);
+ memcpy(buf, rbuf->data+rbuf->pread, split);
else
- if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+ return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
@@ -124,7 +124,7 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
memcpy(buf, rbuf->data+rbuf->pread, todo);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
- return -EFAULT;
+ return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
@@ -167,7 +167,7 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
}
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem)
+ int offset, u8* buf, size_t len, int usermem)
{
size_t todo;
size_t split;
@@ -183,10 +183,10 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
if (!usermem)
- memcpy(buf, rbuf->data+idx, split);
+ memcpy(buf, rbuf->data+idx, split);
else
- if (copy_to_user(buf, rbuf->data+idx, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+idx, split))
+ return -EFAULT;
buf += split;
todo -= split;
idx = 0;
@@ -195,7 +195,7 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
memcpy(buf, rbuf->data+idx, todo);
else
if (copy_to_user(buf, rbuf->data+idx, todo))
- return -EFAULT;
+ return -EFAULT;
return len;
}
@@ -209,12 +209,12 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
// clean up disposed packets
while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
- pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
- pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
- DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
+ pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
+ pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
+ DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
} else {
- // first packet is not disposed, so we stop cleaning now
- break;
+ // first packet is not disposed, so we stop cleaning now
+ break;
}
}
}
@@ -242,8 +242,8 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
if (curpktstatus == PKT_READY) {
- *pktlen = curpktlen;
- return idx;
+ *pktlen = curpktlen;
+ return idx;
}
consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index fa476f662f82..6d2560972771 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -106,7 +106,7 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
- size_t len, int usermem);
+ size_t len, int usermem);
/* write routines & macros */
@@ -121,7 +121,7 @@ extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
- size_t len);
+ size_t len);
/**
@@ -133,7 +133,7 @@ extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
*/
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
- size_t len);
+ size_t len);
/**
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
@@ -149,7 +149,7 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
* returns Number of bytes read, or -EFAULT.
*/
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem);
+ int offset, u8* buf, size_t len, int usermem);
/**
* Dispose of a packet in the ring buffer.
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index a4aee8665854..54f8b95717b0 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -33,7 +33,7 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/cdev.h>
-
+#include <linux/mutex.h>
#include "dvbdev.h"
static int dvbdev_debug;
@@ -44,7 +44,7 @@ MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
#define dprintk if (dvbdev_debug) printk
static LIST_HEAD(dvb_adapter_list);
-static DECLARE_MUTEX(dvbdev_register_lock);
+static DEFINE_MUTEX(dvbdev_register_lock);
static const char * const dnames[] = {
"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
@@ -92,10 +92,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
old_fops = file->f_op;
file->f_op = fops_get(dvbdev->fops);
if(file->f_op->open)
- err = file->f_op->open(inode,file);
+ err = file->f_op->open(inode,file);
if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
@@ -202,11 +202,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
struct dvb_device *dvbdev;
int id;
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
if ((id = dvbdev_get_free_id (adap, type)) < 0) {
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
printk ("%s: could get find free device id...\n", __FUNCTION__);
return -ENFILE;
@@ -215,11 +215,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
if (!dvbdev) {
- up(&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
memcpy(dvbdev, template, sizeof(struct dvb_device));
dvbdev->type = type;
@@ -289,11 +289,11 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
{
int num;
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
if ((num = dvbdev_get_free_adapter_num ()) < 0) {
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return -ENFILE;
}
@@ -309,7 +309,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
list_add_tail (&adap->list_head, &dvb_adapter_list);
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return num;
}
@@ -320,10 +320,10 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
{
devfs_remove("dvb/adapter%d", adap->num);
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
list_del (&adap->list_head);
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return 0;
}
EXPORT_SYMBOL(dvb_unregister_adapter);
@@ -356,18 +356,18 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
- parg = sbuf;
+ parg = sbuf;
} else {
- /* too big to allocate from stack */
- mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
- if (NULL == mbuf)
- return -ENOMEM;
- parg = mbuf;
+ /* too big to allocate from stack */
+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+ if (NULL == mbuf)
+ return -ENOMEM;
+ parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
- goto out;
+ goto out;
break;
}
@@ -384,7 +384,7 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
- err = -EFAULT;
+ err = -EFAULT;
break;
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 0cc6e4a0e27c..74ed5853f0fb 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -97,7 +97,7 @@ we simply define out own dvb_usercopy(), which will hopefully become
generic_usercopy() someday... */
extern int dvb_usercopy(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
+ unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 54e2b29076b1..90a69d343b79 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -37,16 +37,16 @@ config DVB_USB_DIBUSB_MB
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
Devices supported by this driver:
- TwinhanDTV USB-Ter (VP7041)
- TwinhanDTV Magic Box (VP7041e)
- KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
- Hama DVB-T USB1.1-Box
- DiBcom USB1.1 reference devices (non-public)
- Ultima Electronic/Artec T1 USB TVBOX
+ Artec T1 USB1.1 boxes
+ Avermedia AverTV DVBT USB1.1
Compro Videomate DVB-U2000 - DVB-T USB
+ DiBcom USB1.1 reference devices (non-public)
Grandtec DVB-T USB
- Avermedia AverTV DVBT USB1.1
- Artec T1 USB1.1 boxes
+ Hama DVB-T USB1.1-Box
+ KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
+ TwinhanDTV Magic Box (VP7041e)
+ TwinhanDTV USB-Ter (VP7041)
+ Ultima Electronic/Artec T1 USB TVBOX
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
@@ -54,6 +54,12 @@ config DVB_USB_DIBUSB_MB
Say Y if you own such a device and want to use it. You should build it as
a module.
+config DVB_USB_DIBUSB_MB_FAULTY
+ bool "Support faulty USB IDs"
+ depends on DVB_USB_DIBUSB_MB
+ help
+ Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
+
config DVB_USB_DIBUSB_MC
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
depends on DVB_USB
@@ -63,8 +69,8 @@ config DVB_USB_DIBUSB_MC
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
Devices supported by this driver:
- DiBcom USB2.0 reference devices (non-public)
Artec T1 USB2.0 boxes
+ DiBcom USB2.0 reference devices (non-public)
Say Y if you own such a device and want to use it. You should build it as
a module.
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index d05fab01cccd..a7fb06f4cd34 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -11,10 +11,11 @@
* design, so it can be reused for the "analogue-only" device (if it will
* appear at all).
*
- * TODO: check if the cx25840-driver (from ivtv) can be used for the analogue
- * part
+ * TODO: Use the cx25840-driver for the analogue part
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
+ * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,6 +26,9 @@
#include "cxusb.h"
#include "cx22702.h"
+#include "lgdt330x.h"
+#include "mt352.h"
+#include "mt352_priv.h"
/* debug */
int dvb_usb_cxusb_debug;
@@ -156,6 +160,119 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
+static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ u8 ircode[4];
+ int i;
+
+ cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == ircode[2] &&
+ keymap[i].data == ircode[3]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+ { 0xfe, 0x02, KEY_TV },
+ { 0xfe, 0x0e, KEY_MP3 },
+ { 0xfe, 0x1a, KEY_DVD },
+ { 0xfe, 0x1e, KEY_FAVORITES },
+ { 0xfe, 0x16, KEY_SETUP },
+ { 0xfe, 0x46, KEY_POWER2 },
+ { 0xfe, 0x0a, KEY_EPG },
+ { 0xfe, 0x49, KEY_BACK },
+ { 0xfe, 0x4d, KEY_MENU },
+ { 0xfe, 0x51, KEY_UP },
+ { 0xfe, 0x5b, KEY_LEFT },
+ { 0xfe, 0x5f, KEY_RIGHT },
+ { 0xfe, 0x53, KEY_DOWN },
+ { 0xfe, 0x5e, KEY_OK },
+ { 0xfe, 0x59, KEY_INFO },
+ { 0xfe, 0x55, KEY_TAB },
+ { 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */
+ { 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */
+ { 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */
+ { 0xfe, 0x15, KEY_VOLUMEUP },
+ { 0xfe, 0x05, KEY_VOLUMEDOWN },
+ { 0xfe, 0x11, KEY_CHANNELUP },
+ { 0xfe, 0x09, KEY_CHANNELDOWN },
+ { 0xfe, 0x52, KEY_CAMERA },
+ { 0xfe, 0x5a, KEY_TUNER }, /* Live */
+ { 0xfe, 0x19, KEY_OPEN },
+ { 0xfe, 0x0b, KEY_1 },
+ { 0xfe, 0x17, KEY_2 },
+ { 0xfe, 0x1b, KEY_3 },
+ { 0xfe, 0x07, KEY_4 },
+ { 0xfe, 0x50, KEY_5 },
+ { 0xfe, 0x54, KEY_6 },
+ { 0xfe, 0x48, KEY_7 },
+ { 0xfe, 0x4c, KEY_8 },
+ { 0xfe, 0x58, KEY_9 },
+ { 0xfe, 0x13, KEY_ANGLE }, /* Aspect */
+ { 0xfe, 0x03, KEY_0 },
+ { 0xfe, 0x1f, KEY_ZOOM },
+ { 0xfe, 0x43, KEY_REWIND },
+ { 0xfe, 0x47, KEY_PLAYPAUSE },
+ { 0xfe, 0x4f, KEY_FASTFORWARD },
+ { 0xfe, 0x57, KEY_MUTE },
+ { 0xfe, 0x0d, KEY_STOP },
+ { 0xfe, 0x01, KEY_RECORD },
+ { 0xfe, 0x4e, KEY_POWER },
+};
+
+static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
+static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
+{ /* used in both lgz201 and th7579 */
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+ return 0;
+}
+
struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
@@ -165,17 +282,68 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c,
};
+struct lgdt330x_config cxusb_lgdt330x_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .pll_set = dvb_usb_pll_set_i2c,
+};
+
+struct mt352_config cxusb_dee1601_config = {
+ .demod_address = 0x0f,
+ .demod_init = cxusb_dee1601_demod_init,
+ .pll_set = dvb_usb_pll_set,
+};
+
+struct mt352_config cxusb_mt352_config = {
+ /* used in both lgz201 and th7579 */
+ .demod_address = 0x0f,
+ .demod_init = cxusb_mt352_demod_init,
+ .pll_set = dvb_usb_pll_set,
+};
+
/* Callbacks for DVB USB */
-static int cxusb_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
{
u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
d->pll_addr = 0x61;
- memcpy(d->pll_init,bpll,4);
+ memcpy(d->pll_init, bpll, 4);
d->pll_desc = &dvb_pll_fmd1216me;
return 0;
}
-static int cxusb_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
+{
+ u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
+ /* bpll[2] : unset bit 3, set bits 4&5
+ bpll[3] : 0x50 - digital, 0x20 - analog */
+ d->pll_addr = 0x61;
+ memcpy(d->pll_init, bpll, 4);
+ d->pll_desc = &dvb_pll_tdvs_tua6034;
+ return 0;
+}
+
+static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_thomson_dtt7579;
+ return 0;
+}
+
+static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_lg_z201;
+ return 0;
+}
+
+static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x60;
+ d->pll_desc = &dvb_pll_thomson_dtt7579;
+ return 0;
+}
+
+static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
{
u8 b;
if (usb_set_interface(d->udev,0,6) < 0)
@@ -189,22 +357,107 @@ static int cxusb_frontend_attach(struct dvb_usb_device *d)
return -EIO;
}
+static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d)
+{
+ if (usb_set_interface(d->udev,0,7) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d)
+{ /* used in both lgz201 and th7579 */
+ if (usb_set_interface(d->udev,0,0) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = mt352_attach(&cxusb_mt352_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
+{
+ if (usb_set_interface(d->udev,0,0) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+/*
+ * DViCO bluebird firmware needs the "warm" product ID to be patched into the
+ * firmware file before download.
+ */
+
+#define BLUEBIRD_01_ID_OFFSET 6638
+static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
+{
+ if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
+ return -EINVAL;
+
+ if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
+ fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
+
+ /* FIXME: are we allowed to change the fw-data ? */
+ fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
+
+ return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
+ }
+
+ return -EINVAL;
+}
+
/* DVB USB Driver stuff */
-static struct dvb_usb_properties cxusb_properties;
+static struct dvb_usb_properties cxusb_medion_properties;
+static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties;
+static struct dvb_usb_properties cxusb_bluebird_dee1601_properties;
+static struct dvb_usb_properties cxusb_bluebird_lgz201_properties;
+static struct dvb_usb_properties cxusb_bluebird_dtt7579_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,NULL);
+ if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) {
+ return 0;
+ }
+
+ return -EINVAL;
}
static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_WARM) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
-static struct dvb_usb_properties cxusb_properties = {
+static struct dvb_usb_properties cxusb_medion_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
@@ -213,8 +466,8 @@ static struct dvb_usb_properties cxusb_properties = {
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
- .frontend_attach = cxusb_frontend_attach,
- .tuner_attach = cxusb_tuner_attach,
+ .frontend_attach = cxusb_cx22702_frontend_attach,
+ .tuner_attach = cxusb_fmd1216me_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
@@ -240,6 +493,175 @@ static struct dvb_usb_properties cxusb_properties = {
}
};
+static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_lgdt330x_frontend_attach,
+ .tuner_attach = cxusb_lgh064f_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV5 USB Gold",
+ { &cxusb_table[1], NULL },
+ { &cxusb_table[2], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_dee1601_frontend_attach,
+ .tuner_attach = cxusb_dee1601_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .rc_interval = 150,
+ .rc_key_map = dvico_mce_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
+ .rc_query = cxusb_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T Dual USB",
+ { &cxusb_table[3], NULL },
+ { &cxusb_table[4], NULL },
+ },
+ { "DigitalNow DVB-T Dual USB",
+ { &cxusb_table[9], NULL },
+ { &cxusb_table[10], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_mt352_frontend_attach,
+ .tuner_attach = cxusb_lgz201_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T USB (LGZ201)",
+ { &cxusb_table[5], NULL },
+ { &cxusb_table[6], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_mt352_frontend_attach,
+ .tuner_attach = cxusb_dtt7579_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T USB (TH7579)",
+ { &cxusb_table[7], NULL },
+ { &cxusb_table[8], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
@@ -269,6 +691,8 @@ module_init (cxusb_module_init);
module_exit (cxusb_module_exit);
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
MODULE_VERSION("1.0-alpha");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 135c2a81f581..087c99427853 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug;
#define CMD_STREAMING_ON 0x36
#define CMD_STREAMING_OFF 0x37
+#define CMD_GET_IR_CODE 0x47
+
#define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index 52ac3e5adf5d..dd5a13195886 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -65,11 +65,11 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
if (b2[0] == 0xfe) {
- info("this device has the Thomson Cable onboard. Which is default.");
+ info("This device has the Thomson Cable onboard. Which is default.");
dibusb_thomson_tuner_attach(d);
} else {
u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
- info("this device has the Panasonic ENV77H11D5 onboard.");
+ info("This device has the Panasonic ENV77H11D5 onboard.");
d->pll_addr = 0x60;
memcpy(d->pll_init,bpll,4);
d->pll_desc = &dvb_pll_tda665x;
@@ -98,15 +98,15 @@ static int dibusb_probe(struct usb_interface *intf,
/* do not change the order of the ID table */
static struct usb_device_id dibusb_dib3000mb_table [] = {
-/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
-/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) },
/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
-/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
-/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
+/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
+/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
@@ -117,27 +117,34 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
-/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
-/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
-/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
-/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */
/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
-/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
-/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
+/* 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) },
-/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
+/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
-// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+/*
+ * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices
+ * we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that
+ * have been left on the device. If you don't have such a device but an Artec
+ * device that's supposed to work with this driver but is not detected by it,
+ * free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config.
+ */
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
+
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
@@ -257,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
}
},
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
.num_device_descs = 2,
#else
.num_device_descs = 1,
@@ -267,11 +274,12 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
{ &dibusb_dib3000mb_table[20], NULL },
{ &dibusb_dib3000mb_table[21], NULL },
},
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
{ &dibusb_dib3000mb_table[30], NULL },
{ NULL },
},
+ { NULL },
#endif
}
};
@@ -323,6 +331,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
{ &dibusb_dib3000mb_table[27], NULL },
{ NULL }
},
+ { NULL },
}
};
@@ -369,6 +378,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
{ &dibusb_dib3000mb_table[28], NULL },
{ &dibusb_dib3000mb_table[29], NULL },
},
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 450417a9e64b..e6c55c9c9417 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -32,7 +32,7 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d,
sndbuf[1] = vv;
sndbuf[2] = wo ? wlen : rlen;
- if (!wo) {
+ if (wo) {
memcpy(&sndbuf[3],wbuf,wlen);
dvb_usb_generic_write(d,sndbuf,7);
} else {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index 0a94ec22aeb8..cd21ddbfd054 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -156,10 +156,9 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
struct dtt200u_fe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct dtt200u_fe_state*) kmalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct dtt200u_fe_state));
deb_info("attaching frontend dtt200u\n");
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 6e2bac873445..130ea7f21f5e 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
- { NULL },
+ { 0 },
}
};
@@ -160,7 +160,7 @@ static struct dvb_usb_properties wt220u_properties = {
.pid_filter_count = 15,
.usb_ctrl = CYPRESS_FX2,
- .firmware = "dvb-usb-wt220u-01.fw",
+ .firmware = "dvb-usb-wt220u-02.fw",
.power_ctrl = dtt200u_power_ctrl,
.streaming_ctrl = dtt200u_streaming_ctrl,
@@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = {
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
- { NULL },
+ { 0 },
}
};
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
index 6f1f3042e21a..005b0a7df358 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.h
+++ b/drivers/media/dvb/dvb-usb/dtt200u.h
@@ -13,6 +13,7 @@
#define _DVB_USB_DTT200U_H_
#define DVB_USB_LOG_PREFIX "dtt200u"
+
#include "dvb-usb.h"
extern int dvb_usb_dtt200u_debug;
@@ -25,15 +26,15 @@ extern int dvb_usb_dtt200u_debug;
* 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
*/
-#define GET_SPEED 0x00
-#define GET_TUNE_STATUS 0x81
-#define GET_RC_CODE 0x84
-#define GET_CONFIGURATION 0x88
-#define GET_AGC 0x89
-#define GET_SNR 0x8a
-#define GET_VIT_ERR_CNT 0x8c
-#define GET_RS_ERR_CNT 0x8d
-#define GET_RS_UNCOR_BLK_CNT 0x8e
+#define GET_SPEED 0x00
+#define GET_TUNE_STATUS 0x81
+#define GET_RC_CODE 0x84
+#define GET_CONFIGURATION 0x88
+#define GET_AGC 0x89
+#define GET_SNR 0x8a
+#define GET_VIT_ERR_CNT 0x8c
+#define GET_RS_ERR_CNT 0x8d
+#define GET_RS_UNCOR_BLK_CNT 0x8e
/* write
* 01 - init
@@ -44,12 +45,12 @@ extern int dvb_usb_dtt200u_debug;
* 08 - transfer switch
*/
-#define SET_INIT 0x01
-#define SET_RF_FREQ 0x02
-#define SET_BANDWIDTH 0x03
-#define SET_PID_FILTER 0x04
-#define RESET_PID_FILTER 0x05
-#define SET_STREAMING 0x08
+#define SET_INIT 0x01
+#define SET_RF_FREQ 0x02
+#define SET_BANDWIDTH 0x03
+#define SET_PID_FILTER 0x04
+#define RESET_PID_FILTER 0x05
+#define SET_STREAMING 0x08
extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
index 7300489d3e24..a3460bf2d9fa 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -24,7 +24,7 @@ extern int dvb_usb_disable_rc_polling;
#define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args)
/* commonly used methods */
-extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
+extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_properties *);
extern int dvb_usb_urb_submit(struct dvb_usb_device *);
extern int dvb_usb_urb_kill(struct dvb_usb_device *);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 5244e39770a0..8535895819fb 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -9,7 +9,6 @@
*/
#include "dvb-usb-common.h"
-#include <linux/firmware.h>
#include <linux/usb.h>
struct usb_cypress_controller {
@@ -19,9 +18,10 @@ struct usb_cypress_controller {
};
static struct usb_cypress_controller cypress[] = {
- { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
- { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
- { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
+ { .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 },
+ { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
};
/*
@@ -30,71 +30,117 @@ static struct usb_cypress_controller cypress[] = {
static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
{
return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+ 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
}
-int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
+int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
{
- const struct firmware *fw = NULL;
- u16 addr;
- u8 *b,*p;
- int ret = 0,i;
+ struct hexline hx;
+ u8 reset;
+ int ret,pos=0;
- if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
- err("did not find the firmware file. (%s) "
- "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
- filename);
+ /* stop the CPU */
+ reset = 1;
+ if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+ err("could not stop the USB controller CPU.");
+
+ while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
+ deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
+ ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
+
+ if (ret != hx.len) {
+ err("error while transferring firmware "
+ "(transferred size: %d, block size: %d)",
+ ret,hx.len);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ if (ret < 0) {
+ err("firmware download failed at %d with %d",pos,ret);
return ret;
}
- info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
-
- p = kmalloc(fw->size,GFP_KERNEL);
- if (p != NULL) {
- u8 reset;
- /*
- * you cannot use the fw->data as buffer for
- * usb_control_msg, a new buffer has to be
- * created
- */
- memcpy(p,fw->data,fw->size);
-
- /* stop the CPU */
- reset = 1;
- if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
- err("could not stop the USB controller CPU.");
- for(i = 0; p[i+3] == 0 && i < fw->size; ) {
- b = (u8 *) &p[i];
- addr = cpu_to_le16( *((u16 *) &b[1]) );
-
- deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
-
- ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
-
- if (ret != b[0]) {
- err("error while transferring firmware "
- "(transferred size: %d, block size: %d)",
- ret,b[0]);
- ret = -EINVAL;
- break;
- }
- i += 5 + b[0];
- }
- /* length in ret */
- if (ret > 0)
- ret = 0;
+ if (ret == 0) {
/* restart the CPU */
reset = 0;
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
+ } else
+ ret = -EIO;
- kfree(p);
- } else {
- ret = -ENOMEM;
+ return ret;
+}
+EXPORT_SYMBOL(usb_cypress_load_firmware);
+
+int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props)
+{
+ int ret;
+ const struct firmware *fw = NULL;
+
+ if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+ props->firmware,ret);
+ return ret;
}
- release_firmware(fw);
+ info("downloading firmware from file '%s'",props->firmware);
+
+ switch (props->usb_ctrl) {
+ case CYPRESS_AN2135:
+ case CYPRESS_AN2235:
+ case CYPRESS_FX2:
+ ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl);
+ break;
+ case DEVICE_SPECIFIC:
+ if (props->download_firmware)
+ ret = props->download_firmware(udev,fw);
+ else {
+ err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one.");
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ release_firmware(fw);
return ret;
}
+
+int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
+{
+ u8 *b = (u8 *) &fw->data[*pos];
+ int data_offs = 4;
+ if (*pos >= fw->size)
+ return 0;
+
+ memset(hx,0,sizeof(struct hexline));
+
+ hx->len = b[0];
+
+ if ((*pos + hx->len + 4) >= fw->size)
+ return -EINVAL;
+
+ hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
+ hx->type = b[3];
+
+ if (hx->type == 0x04) {
+ /* b[4] and b[5] are the Extended linear address record data field */
+ hx->addr |= (b[4] << 24) | (b[5] << 16);
+/* hx->len -= 2;
+ data_offs += 2; */
+ }
+ memcpy(hx->data,&b[data_offs],hx->len);
+ hx->chk = b[hx->len + data_offs];
+
+ *pos += hx->len + 5;
+
+ return *pos;
+}
+EXPORT_SYMBOL(dvb_usb_get_hexline);
+
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index da970947dfc7..9b254532af4d 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -52,9 +52,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
int ret = 0;
- /* if there is nothing to initialize */
- if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
- d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
+ /* if pll_desc is not used */
+ if (d->pll_desc == NULL)
return 0;
if (d->tuner_pass_ctrl)
@@ -80,6 +79,9 @@ int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep
{
struct dvb_usb_device *d = fe->dvb->priv;
+ if (d->pll_desc == NULL)
+ return 0;
+
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
b[0] = d->pll_addr << 1;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 6be99e537e12..4a1b9e77e339 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -86,11 +86,17 @@
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_NEBULA_DIGITV 0x0201
-#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00
-#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
-#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
-#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
+#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
+#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01
+#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10
+#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11
+#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD 0xdb50
+#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM 0xdb51
+#define USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_COLD 0xdb54
+#define USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_WARM 0xdb55
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index dd8e0b94edba..716f8bf528cd 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -138,6 +138,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
int ret = -ENOMEM,cold=0;
+ if (du != NULL)
+ *du = NULL;
+
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
return -ENODEV;
@@ -145,38 +148,38 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
if (cold) {
info("found a '%s' in cold state, will try to load a firmware",desc->name);
- ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
- } else {
- info("found a '%s' in warm state.",desc->name);
- d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
- if (d == NULL) {
- err("no memory for 'struct dvb_usb_device'");
+ ret = dvb_usb_download_firmware(udev,props);
+ if (!props->no_reconnect)
return ret;
+ }
+
+ info("found a '%s' in warm state.",desc->name);
+ d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
+ if (d == NULL) {
+ err("no memory for 'struct dvb_usb_device'");
+ return ret;
+ }
+
+ d->udev = udev;
+ memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
+ d->desc = desc;
+ d->owner = owner;
+
+ if (d->props.size_of_priv > 0) {
+ d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
+ if (d->priv == NULL) {
+ err("no memory for priv in 'struct dvb_usb_device'");
+ kfree(d);
+ return -ENOMEM;
}
- memset(d,0,sizeof(struct dvb_usb_device));
-
- d->udev = udev;
- memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
- d->desc = desc;
- d->owner = owner;
-
- if (d->props.size_of_priv > 0) {
- d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
- if (d->priv == NULL) {
- err("no memory for priv in 'struct dvb_usb_device'");
- kfree(d);
- return -ENOMEM;
- }
- memset(d->priv,0,d->props.size_of_priv);
- }
+ }
- usb_set_intfdata(intf, d);
+ usb_set_intfdata(intf, d);
- if (du != NULL)
- *du = d;
+ if (du != NULL)
+ *du = d;
- ret = dvb_usb_init(d);
- }
+ ret = dvb_usb_init(d);
if (ret == 0)
info("%s successfully initialized and connected.",desc->name);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index 36b7048c02d2..ee821974dc60 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -175,15 +175,13 @@ static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, un
deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
- if ((d->buf_list = kmalloc(num*sizeof(u8 *), GFP_ATOMIC)) == NULL)
+ if ((d->buf_list = kcalloc(num, sizeof(u8 *), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- if ((d->dma_addr = kmalloc(num*sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
+ if ((d->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
kfree(d->buf_list);
return -ENOMEM;
}
- memset(d->buf_list,0,num*sizeof(u8 *));
- memset(d->dma_addr,0,num*sizeof(dma_addr_t));
d->state |= DVB_USB_STATE_URB_BUF;
@@ -285,10 +283,9 @@ int dvb_usb_urb_init(struct dvb_usb_device *d)
usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
/* allocate the array for the data transfer URBs */
- d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
+ d->urb_list = kzalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
if (d->urb_list == NULL)
return -ENOMEM;
- memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
d->state |= DVB_USB_STATE_URB_LIST;
switch (d->props.urb.type) {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index b4a1a98006c7..dd568396e594 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -10,8 +10,8 @@
#include <linux/config.h>
#include <linux/input.h>
-#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/firmware.h>
#include "dvb_frontend.h"
#include "dvb_demux.h"
@@ -94,7 +94,11 @@ struct dvb_usb_device;
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
* download.
* @firmware: name of the firmware file.
- *
+ * @download_firmware: called to download the firmware when the usb_ctrl is
+ * DEVICE_SPECIFIC.
+ * @no_reconnect: device doesn't do a reconnect after downloading the firmware,
+ so do the warm initialization right after it
+
* @size_of_priv: how many bytes shall be allocated for the private field
* of struct dvb_usb_device.
*
@@ -142,11 +146,14 @@ struct dvb_usb_properties {
int caps;
int pid_filter_count;
-#define CYPRESS_AN2135 0
-#define CYPRESS_AN2235 1
-#define CYPRESS_FX2 2
+#define DEVICE_SPECIFIC 0
+#define CYPRESS_AN2135 1
+#define CYPRESS_AN2235 2
+#define CYPRESS_FX2 3
int usb_ctrl;
- const char *firmware;
+ const char firmware[FIRMWARE_NAME_MAX];
+ int (*download_firmware) (struct usb_device *, const struct firmware *);
+ int no_reconnect;
int size_of_priv;
@@ -326,5 +333,15 @@ extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+/* commonly used firmware download types and function */
+struct hexline {
+ u8 len;
+ u32 addr;
+ u8 type;
+ u8 data[255];
+ u8 chk;
+};
+extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
+extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index fac48fc7a4ac..412039d8dbae 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -129,10 +129,6 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
dibusb_read_eeprom_byte(d,i, &b);
mac[5 - (i - 136)] = b;
-
-/* deb_ee("%02x ",b);
- if ((i+1) % 16 == 0)
- deb_ee("\n");*/
}
return 0;
@@ -153,7 +149,7 @@ static struct usb_device_id nova_t_table [] = {
/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, nova_t_table);
+MODULE_DEVICE_TABLE(usb, nova_t_table);
static struct dvb_usb_properties nova_t_properties = {
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
@@ -198,6 +194,7 @@ static struct dvb_usb_properties nova_t_properties = {
{ &nova_t_table[0], NULL },
{ &nova_t_table[1], NULL },
},
+ { NULL },
}
};
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index 104b5d016c7b..b6d95e1c9c52 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -190,7 +190,7 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
}
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *m)
+ struct dvb_diseqc_master_cmd *m)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
u8 cmd[8],ibuf[10];
@@ -281,10 +281,9 @@ 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);
+ struct vp702x_fe_state *s = kzalloc(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;
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index 4a3e8c7eca2b..a808d48e7bf2 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -13,47 +13,47 @@ extern int dvb_usb_vp702x_debug;
/* commands are read and written with USB control messages */
/* consecutive read/write operation */
-#define REQUEST_OUT 0xB2
-#define REQUEST_IN 0xB3
+#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
+#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
+#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
+#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 */
+ * N/A 0 0 b[1] == b[2] == 0 -> success, failure otherwise */
-#define SET_LNB_POWER 0x09
+#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 */
+ * N/A 0 0 b[1] == b[2] == 0 -> success failure otherwise */
-#define GET_MAC_ADDRESS 0x0A
+#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
+#define SET_PID_FILTER 0x11
/* additional in buffer:
* 0 1 ... 14 15 16
* PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
@@ -64,39 +64,38 @@ extern int dvb_usb_vp702x_debug;
* freq0 freq1 divstep srate0 srate1 srate2 flag chksum
*/
-
/* one direction requests */
-#define READ_REMOTE_REQ 0xB4
+#define READ_REMOTE_REQ 0xB4
/* IN i: 0; v: 0; b[0] == request, b[1] == key */
-#define READ_PID_NUMBER_REQ 0xB5
+#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
+#define WRITE_EEPROM_REQ 0xB6
/* OUT i: offset; v: value to write; no extra buffer */
-#define READ_EEPROM_REQ 0xB7
+#define READ_EEPROM_REQ 0xB7
/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
-#define READ_STATUS 0xB8
+#define READ_STATUS 0xB8
/* IN i: 0; v: 0; bufferlen 10 */
-#define READ_TUNER_REG_REQ 0xB9
+#define READ_TUNER_REG_REQ 0xB9
/* IN i: 0; v: register; b[0] = value */
-#define READ_FX2_REG_REQ 0xBA
+#define READ_FX2_REG_REQ 0xBA
/* IN i: offset; v: 0; b[0] = value */
-#define WRITE_FX2_REG_REQ 0xBB
+#define WRITE_FX2_REG_REQ 0xBB
/* OUT i: offset; v: value to write; 1 byte extra buffer */
-#define SET_TUNER_POWER_REQ 0xBC
+#define SET_TUNER_POWER_REQ 0xBC
/* IN i: 0 = power off, 1 = power on */
-#define WRITE_TUNER_REG_REQ 0xBD
+#define WRITE_TUNER_REG_REQ 0xBD
/* IN i: register, v: value to write, no extra buffer */
-#define RESET_TUNER 0xBE
+#define RESET_TUNER 0xBE
/* IN i: 0, v: 0, no extra buffer */
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 83f1de1e7e57..5242cca5db4a 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -145,10 +145,9 @@ static struct dvb_frontend_ops vp7045_fe_ops;
struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
{
- struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
+ struct vp7045_fe_state *s = kzalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
if (s == NULL)
goto error;
- memset(s,0,sizeof(struct vp7045_fe_state));
s->d = d;
s->fe.ops = &vp7045_fe_ops;
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 3835235b68df..028204956bb0 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
- { NULL },
+ { 0 },
}
};
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 8e269e1c1f9d..db3a8b40031e 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -16,6 +16,12 @@ config DVB_CX24110
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_CX24123
+ tristate "Conexant CX24123 based"
+ depends on DVB_CORE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
config DVB_TDA8083
tristate "Philips TDA8083 based"
depends on DVB_CORE
@@ -50,18 +56,19 @@ comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
config DVB_SP8870
- tristate "Spase sp8870 based"
+ tristate "Spase sp8870 based"
depends on DVB_CORE
select FW_LOADER
help
- A DVB-T tuner module. Say Y when you want to support this frontend.
+ A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_SP887X
- tristate "Spase sp887x based"
+ tristate "Spase sp887x based"
depends on DVB_CORE
select FW_LOADER
help
@@ -69,7 +76,8 @@ config DVB_SP887X
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_CX22700
tristate "Conexant CX22700 based"
@@ -78,10 +86,10 @@ config DVB_CX22700
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_CX22702
- tristate "Conexant cx22702 demodulator (OFDM)"
- depends on DVB_CORE
- help
- A DVB-T tuner module. Say Y when you want to support this frontend.
+ tristate "Conexant cx22702 demodulator (OFDM)"
+ depends on DVB_CORE
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_L64781
tristate "LSI L64781"
@@ -98,8 +106,9 @@ config DVB_TDA1004X
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_NXT6000
tristate "NxtWave Communications NXT6000 based"
@@ -140,13 +149,13 @@ config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_TDA10021
tristate "Philips TDA10021 based"
depends on DVB_CORE
help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_STV0297
tristate "ST STV0297 based"
@@ -164,6 +173,11 @@ config DVB_NXT2002
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE
@@ -172,6 +186,12 @@ config DVB_NXT200X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_OR51211
tristate "or51211 based (pcHDTV HD2000 card)"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index a98760fe08a1..615ec830e1c9 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+obj-$(CONFIG_DVB_CX24123) += cx24123.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index 8ceb9a33c7af..caaee893ca76 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -255,7 +255,7 @@ static int bcm3510_bert_reset(struct bcm3510_state *st)
bcm3510_register_value b;
int ret;
- if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
+ if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
return ret;
b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
@@ -623,13 +623,13 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
return ret;
}
- deb_info("got firmware: %d\n",fw->size);
+ deb_info("got firmware: %zd\n",fw->size);
b = fw->data;
for (i = 0; i < fw->size;) {
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
- deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
+ deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
err("firmware download failed: %d\n",ret);
return ret;
@@ -782,10 +782,9 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
bcm3510_register_value v;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct bcm3510_state));
/* setup the state */
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 5de0e6d350b1..0fc899f81c5e 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -195,6 +195,16 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
return 0;
}
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct cx22702_state* state = fe->demodulator_priv;
+ dprintk ("%s(%d)\n", __FUNCTION__, enable);
+ if (enable)
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ else
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
+}
+
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
@@ -202,7 +212,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
struct cx22702_state* state = fe->demodulator_priv;
/* set PLL */
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
+ cx22702_i2c_gate_ctrl(fe, 1);
if (state->config->pll_set) {
state->config->pll_set(fe, p);
} else if (state->config->pll_desc) {
@@ -216,7 +226,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
} else {
BUG();
}
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
+ cx22702_i2c_gate_ctrl(fe, 0);
/* set inversion */
cx22702_set_inversion (state, p->inversion);
@@ -349,11 +359,10 @@ static int cx22702_init (struct dvb_frontend* fe)
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
/* init PLL */
- if (state->config->pll_init) {
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe);
+ if (state->config->pll_init)
state->config->pll_init(fe);
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
- }
+
+ cx22702_i2c_gate_ctrl(fe, 0);
return 0;
}
@@ -531,6 +540,7 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_signal_strength = cx22702_read_signal_strength,
.read_snr = cx22702_read_snr,
.read_ucblocks = cx22702_read_ucblocks,
+ .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 0c4db80ec332..d15d32c51dc5 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "cx24110.h"
@@ -56,7 +55,7 @@ static int debug;
static struct {u8 reg; u8 data;} cx24110_regdata[]=
/* Comments beginning with @ denote this value should
- be the default */
+ be the default */
{{0x09,0x01}, /* SoftResetAll */
{0x09,0x00}, /* release reset */
{0x01,0xe8}, /* MSB of code rate 27.5MS/s */
@@ -67,26 +66,26 @@ static struct {u8 reg; u8 data;} cx24110_regdata[]=
{0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
{0x0a,0x00}, /* @ partial chip disables, do not set */
{0x0b,0x01}, /* set output clock in gapped mode, start signal low
- active for first byte */
+ active for first byte */
{0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
{0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
{0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
- to avoid starting the BER counter. Reset the
- CRC test bit. Finite counting selected */
+ to avoid starting the BER counter. Reset the
+ CRC test bit. Finite counting selected */
{0x15,0xff}, /* @ size of the limited time window for RS BER
- estimation. It is <value>*256 RS blocks, this
- gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
+ estimation. It is <value>*256 RS blocks, this
+ gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
{0x16,0x00}, /* @ enable all RS output ports */
{0x17,0x04}, /* @ time window allowed for the RS to sync */
{0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
- for automatically */
+ for automatically */
/* leave the current code rate and normalization
- registers as they are after reset... */
+ registers as they are after reset... */
{0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
- only once */
+ only once */
{0x23,0x18}, /* @ size of the limited time window for Viterbi BER
- estimation. It is <value>*65536 channel bits, i.e.
- approx. 38ms at 27.5MS/s, rate 3/4 */
+ estimation. It is <value>*65536 channel bits, i.e.
+ approx. 38ms at 27.5MS/s, rate 3/4 */
{0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
/* leave front-end AGC parameters at default values */
/* leave decimation AGC parameters at default values */
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
new file mode 100644
index 000000000000..d661c6f9cbe5
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -0,0 +1,889 @@
+/*
+ Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+ Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+
+ Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24123.h"
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk (KERN_DEBUG "cx24123: " args); \
+ } while (0)
+
+struct cx24123_state
+{
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+ const struct cx24123_config* config;
+
+ struct dvb_frontend frontend;
+
+ u32 lastber;
+ u16 snr;
+ u8 lnbreg;
+
+ /* Some PLL specifics for tuning */
+ u32 VCAarg;
+ u32 VGAarg;
+ u32 bandselectarg;
+ u32 pllarg;
+
+ /* The Demod/Tuner can't easily provide these, we cache them */
+ u32 currentfreq;
+ u32 currentsymbolrate;
+};
+
+/* Various tuner defaults need to be established for a given symbol rate Sps */
+static struct
+{
+ u32 symbolrate_low;
+ u32 symbolrate_high;
+ u32 VCAslope;
+ u32 VCAoffset;
+ u32 VGA1offset;
+ u32 VGA2offset;
+ u32 VCAprogdata;
+ u32 VGAprogdata;
+} cx24123_AGC_vals[] =
+{
+ {
+ .symbolrate_low = 1000000,
+ .symbolrate_high = 4999999,
+ .VCAslope = 0x07,
+ .VCAoffset = 0x0f,
+ .VGA1offset = 0x1f8,
+ .VGA2offset = 0x1f8,
+ .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
+ },
+ {
+ .symbolrate_low = 5000000,
+ .symbolrate_high = 14999999,
+ .VCAslope = 0x1f,
+ .VCAoffset = 0x1f,
+ .VGA1offset = 0x1e0,
+ .VGA2offset = 0x180,
+ .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
+ },
+ {
+ .symbolrate_low = 15000000,
+ .symbolrate_high = 45000000,
+ .VCAslope = 0x3f,
+ .VCAoffset = 0x3f,
+ .VGA1offset = 0x180,
+ .VGA2offset = 0x100,
+ .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
+ },
+};
+
+/*
+ * Various tuner defaults need to be established for a given frequency kHz.
+ * fixme: The bounds on the bands do not match the doc in real life.
+ * fixme: Some of them have been moved, other might need adjustment.
+ */
+static struct
+{
+ u32 freq_low;
+ u32 freq_high;
+ u32 bandselect;
+ u32 VCOdivider;
+ u32 VCOnumber;
+ u32 progdata;
+} cx24123_bandselect_vals[] =
+{
+ {
+ .freq_low = 950000,
+ .freq_high = 1018999,
+ .bandselect = 0x40,
+ .VCOdivider = 4,
+ .VCOnumber = 7,
+ .progdata = (0 << 18) | (0 << 9) | 0x40,
+ },
+ {
+ .freq_low = 1019000,
+ .freq_high = 1074999,
+ .bandselect = 0x80,
+ .VCOdivider = 4,
+ .VCOnumber = 8,
+ .progdata = (0 << 18) | (0 << 9) | 0x80,
+ },
+ {
+ .freq_low = 1075000,
+ .freq_high = 1227999,
+ .bandselect = 0x01,
+ .VCOdivider = 2,
+ .VCOnumber = 1,
+ .progdata = (0 << 18) | (1 << 9) | 0x01,
+ },
+ {
+ .freq_low = 1228000,
+ .freq_high = 1349999,
+ .bandselect = 0x02,
+ .VCOdivider = 2,
+ .VCOnumber = 2,
+ .progdata = (0 << 18) | (1 << 9) | 0x02,
+ },
+ {
+ .freq_low = 1350000,
+ .freq_high = 1481999,
+ .bandselect = 0x04,
+ .VCOdivider = 2,
+ .VCOnumber = 3,
+ .progdata = (0 << 18) | (1 << 9) | 0x04,
+ },
+ {
+ .freq_low = 1482000,
+ .freq_high = 1595999,
+ .bandselect = 0x08,
+ .VCOdivider = 2,
+ .VCOnumber = 4,
+ .progdata = (0 << 18) | (1 << 9) | 0x08,
+ },
+ {
+ .freq_low = 1596000,
+ .freq_high = 1717999,
+ .bandselect = 0x10,
+ .VCOdivider = 2,
+ .VCOnumber = 5,
+ .progdata = (0 << 18) | (1 << 9) | 0x10,
+ },
+ {
+ .freq_low = 1718000,
+ .freq_high = 1855999,
+ .bandselect = 0x20,
+ .VCOdivider = 2,
+ .VCOnumber = 6,
+ .progdata = (0 << 18) | (1 << 9) | 0x20,
+ },
+ {
+ .freq_low = 1856000,
+ .freq_high = 2035999,
+ .bandselect = 0x40,
+ .VCOdivider = 2,
+ .VCOnumber = 7,
+ .progdata = (0 << 18) | (1 << 9) | 0x40,
+ },
+ {
+ .freq_low = 2036000,
+ .freq_high = 2149999,
+ .bandselect = 0x80,
+ .VCOdivider = 2,
+ .VCOnumber = 8,
+ .progdata = (0 << 18) | (1 << 9) | 0x80,
+ },
+};
+
+static struct {
+ u8 reg;
+ u8 data;
+} cx24123_regdata[] =
+{
+ {0x00, 0x03}, /* Reset system */
+ {0x00, 0x00}, /* Clear reset */
+ {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */
+ {0x03, 0x07},
+ {0x04, 0x10},
+ {0x05, 0x04},
+ {0x06, 0x31},
+ {0x0d, 0x02},
+ {0x0e, 0x03},
+ {0x0f, 0xfe},
+ {0x10, 0x01},
+ {0x14, 0x01},
+ {0x15, 0x98},
+ {0x16, 0x00},
+ {0x17, 0x01},
+ {0x1b, 0x05},
+ {0x1c, 0x80},
+ {0x1d, 0x00},
+ {0x1e, 0x00},
+ {0x20, 0x41},
+ {0x21, 0x15},
+ {0x27, 0x14},
+ {0x28, 0x46},
+ {0x29, 0x00},
+ {0x2a, 0xb0},
+ {0x2b, 0x73},
+ {0x2c, 0x00},
+ {0x2d, 0x00},
+ {0x2e, 0x00},
+ {0x2f, 0x00},
+ {0x30, 0x00},
+ {0x31, 0x00},
+ {0x32, 0x8c},
+ {0x33, 0x00},
+ {0x34, 0x00},
+ {0x35, 0x03},
+ {0x36, 0x02},
+ {0x37, 0x3a},
+ {0x3a, 0x00}, /* Enable AGC accumulator */
+ {0x44, 0x00},
+ {0x45, 0x00},
+ {0x46, 0x05},
+ {0x56, 0x41},
+ {0x57, 0xff},
+ {0x67, 0x83},
+};
+
+static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writereg error(err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ /* fixme: put the intersil addr int the config */
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ /* cache the write, no way to read back */
+ state->lnbreg = data;
+
+ return 0;
+}
+
+static int cx24123_readreg(struct cx24123_state* state, u8 reg)
+{
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+ printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
+ return ret;
+ }
+
+ return b1[0];
+}
+
+static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
+{
+ return state->lnbreg;
+}
+
+static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+{
+ switch (inversion) {
+ case INVERSION_OFF:
+ cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ break;
+ case INVERSION_ON:
+ cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ break;
+ case INVERSION_AUTO:
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
+{
+ u8 val;
+
+ val = cx24123_readreg(state, 0x1b) >> 7;
+
+ if (val == 0)
+ *inversion = INVERSION_OFF;
+ else
+ *inversion = INVERSION_ON;
+
+ return 0;
+}
+
+static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+{
+ if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
+ fec = FEC_AUTO;
+
+ /* Hardware has 5/11 and 3/5 but are never unused */
+ switch (fec) {
+ case FEC_NONE:
+ return cx24123_writereg(state, 0x0f, 0x01);
+ case FEC_1_2:
+ return cx24123_writereg(state, 0x0f, 0x02);
+ case FEC_2_3:
+ return cx24123_writereg(state, 0x0f, 0x04);
+ case FEC_3_4:
+ return cx24123_writereg(state, 0x0f, 0x08);
+ case FEC_5_6:
+ return cx24123_writereg(state, 0x0f, 0x20);
+ case FEC_7_8:
+ return cx24123_writereg(state, 0x0f, 0x80);
+ case FEC_AUTO:
+ return cx24123_writereg(state, 0x0f, 0xae);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+{
+ int ret;
+ u8 val;
+
+ ret = cx24123_readreg (state, 0x1b);
+ if (ret < 0)
+ return ret;
+ val = ret & 0x07;
+ switch (val) {
+ case 1:
+ *fec = FEC_1_2;
+ break;
+ case 3:
+ *fec = FEC_2_3;
+ break;
+ case 4:
+ *fec = FEC_3_4;
+ break;
+ case 5:
+ *fec = FEC_4_5;
+ break;
+ case 6:
+ *fec = FEC_5_6;
+ break;
+ case 7:
+ *fec = FEC_7_8;
+ break;
+ case 2: /* *fec = FEC_3_5; break; */
+ case 0: /* *fec = FEC_5_11; break; */
+ *fec = FEC_AUTO;
+ break;
+ default:
+ *fec = FEC_NONE; // can't happen
+ }
+
+ return 0;
+}
+
+/* fixme: Symbol rates < 3MSps may not work because of precision loss */
+static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+{
+ u32 val;
+
+ val = (srate / 1185) * 100;
+
+ /* Compensate for scaling up, by removing 17 symbols per 1Msps */
+ val = val - (17 * (srate / 1000000));
+
+ cx24123_writereg(state, 0x08, (val >> 16) & 0xff );
+ cx24123_writereg(state, 0x09, (val >> 8) & 0xff );
+ cx24123_writereg(state, 0x0a, (val ) & 0xff );
+
+ return 0;
+}
+
+/*
+ * Based on the required frequency and symbolrate, the tuner AGC has to be configured
+ * and the correct band selected. Calculate those values
+ */
+static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u32 ndiv = 0, adiv = 0, vco_div = 0;
+ int i = 0;
+
+ /* Defaults for low freq, low rate */
+ state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
+ state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
+ state->bandselectarg = cx24123_bandselect_vals[0].progdata;
+ vco_div = cx24123_bandselect_vals[0].VCOdivider;
+
+ /* For the given symbolerate, determine the VCA and VGA programming bits */
+ for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
+ {
+ if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
+ (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
+ state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
+ state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
+ }
+ }
+
+ /* For the given frequency, determine the bandselect programming bits */
+ for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
+ {
+ if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
+ (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
+ state->bandselectarg = cx24123_bandselect_vals[i].progdata;
+ vco_div = cx24123_bandselect_vals[i].VCOdivider;
+ }
+ }
+
+ /* Determine the N/A dividers for the requested lband freq (in kHz). */
+ /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */
+ ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff;
+ adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f;
+
+ if (adiv == 0)
+ adiv++;
+
+ /* determine the correct pll frequency values. */
+ /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */
+ state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14);
+ state->pllarg |= (ndiv << 5) | adiv;
+
+ return 0;
+}
+
+/*
+ * Tuner data is 21 bits long, must be left-aligned in data.
+ * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
+ */
+static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ unsigned long timeout;
+
+ /* align the 21 bytes into to bit23 boundary */
+ data = data << 3;
+
+ /* Reset the demod pll word length to 0x15 bits */
+ cx24123_writereg(state, 0x21, 0x15);
+
+ /* write the msb 8 bits, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* send another 8 bytes, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x80)) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* Trigger the demod to configure the tuner */
+ cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2);
+ cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd);
+
+ return 0;
+}
+
+static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (cx24123_pll_calculate(fe, p) != 0) {
+ printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
+ return -EINVAL;
+ }
+
+ /* Write the new VCO/VGA */
+ cx24123_pll_writereg(fe, p, state->VCAarg);
+ cx24123_pll_writereg(fe, p, state->VGAarg);
+
+ /* Write the new bandselect and pll args */
+ cx24123_pll_writereg(fe, p, state->bandselectarg);
+ cx24123_pll_writereg(fe, p, state->pllarg);
+
+ return 0;
+}
+
+static int cx24123_initfe(struct dvb_frontend* fe)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i;
+
+ /* Configure the demod to a good set of defaults */
+ for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
+ cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+
+ if (state->config->pll_init)
+ state->config->pll_init(fe);
+
+ /* Configure the LNB for 14V */
+ if (state->config->use_isl6421)
+ cx24123_writelnbreg(state, 0x0, 0x2a);
+
+ return 0;
+}
+
+static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ switch (state->config->use_isl6421) {
+
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
+ case SEC_VOLTAGE_18:
+ return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
+ case SEC_VOLTAGE_OFF:
+ return cx24123_writelnbreg(state, 0x0, val & 0x30);
+ default:
+ return -EINVAL;
+ };
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val | 0x80);
+ case SEC_VOLTAGE_18:
+ dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val & 0x7f);
+ case SEC_VOLTAGE_OFF:
+ dprintk("%s: setting voltage off\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 0);
+ return 0;
+ default:
+ return -EINVAL;
+ };
+ }
+
+ return 0;
+}
+
+static int cx24123_send_diseqc_msg(struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd *cmd)
+{
+ /* fixme: Implement diseqc */
+ printk("%s: No support yet\n",__FUNCTION__);
+
+ return -ENOTSUPP;
+}
+
+static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ int sync = cx24123_readreg(state, 0x14);
+ int lock = cx24123_readreg(state, 0x20);
+
+ *status = 0;
+ if (lock & 0x01)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ if (sync & 0x04)
+ *status |= FE_HAS_VITERBI;
+ if (sync & 0x08)
+ *status |= FE_HAS_CARRIER;
+ if (sync & 0x80)
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+ return 0;
+}
+
+/*
+ * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
+ * is available, so this value doubles up to satisfy both measurements
+ */
+static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ state->lastber =
+ ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+ (cx24123_readreg(state, 0x1d) << 8 |
+ cx24123_readreg(state, 0x1e));
+
+ /* Do the signal quality processing here, it's derived from the BER. */
+ /* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
+ if (state->lastber < 5000)
+ state->snr = 655*100;
+ else if ( (state->lastber >= 5000) && (state->lastber < 55000) )
+ state->snr = 655*90;
+ else if ( (state->lastber >= 55000) && (state->lastber < 150000) )
+ state->snr = 655*80;
+ else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
+ state->snr = 655*70;
+ else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
+ state->snr = 655*65;
+ else
+ state->snr = 0;
+
+ *ber = state->lastber;
+
+ return 0;
+}
+
+static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+
+ return 0;
+}
+
+static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *snr = state->snr;
+
+ return 0;
+}
+
+static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *ucblocks = state->lastber;
+
+ return 0;
+}
+
+static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+
+ state->currentfreq=p->frequency;
+ state->currentsymbolrate = p->u.qpsk.symbol_rate;
+
+ cx24123_set_inversion(state, p->inversion);
+ cx24123_set_fec(state, p->u.qpsk.fec_inner);
+ cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ cx24123_pll_tune(fe, p);
+
+ /* Enable automatic aquisition and reset cycle */
+ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+ cx24123_writereg(state, 0x00, 0x10);
+ cx24123_writereg(state, 0x00, 0);
+
+ return 0;
+}
+
+static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (cx24123_get_inversion(state, &p->inversion) != 0) {
+ printk("%s: Failed to get inversion status\n",__FUNCTION__);
+ return -EREMOTEIO;
+ }
+ if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+ printk("%s: Failed to get fec status\n",__FUNCTION__);
+ return -EREMOTEIO;
+ }
+ p->frequency = state->currentfreq;
+ p->u.qpsk.symbol_rate = state->currentsymbolrate;
+
+ return 0;
+}
+
+static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ switch (state->config->use_isl6421) {
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ return cx24123_writelnbreg(state, 0x0, val | 0x10);
+ case SEC_TONE_OFF:
+ return cx24123_writelnbreg(state, 0x0, val & 0x2f);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: setting tone on\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val | 0x10);
+ case SEC_TONE_OFF:
+ dprintk("%s: setting tone off\n",__FUNCTION__);
+ return cx24123_writereg(state, 0x29, val & 0xef);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void cx24123_release(struct dvb_frontend* fe)
+{
+ struct cx24123_state* state = fe->demodulator_priv;
+ dprintk("%s\n",__FUNCTION__);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops cx24123_ops;
+
+struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct cx24123_state* state = NULL;
+ int ret;
+
+ dprintk("%s\n",__FUNCTION__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+ if (state == NULL) {
+ printk("Unable to kmalloc\n");
+ goto error;
+ }
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ state->lastber = 0;
+ state->snr = 0;
+ state->lnbreg = 0;
+ state->VCAarg = 0;
+ state->VGAarg = 0;
+ state->bandselectarg = 0;
+ state->pllarg = 0;
+ state->currentfreq = 0;
+ state->currentsymbolrate = 0;
+
+ /* check if the demod is there */
+ ret = cx24123_readreg(state, 0x00);
+ if ((ret != 0xd1) && (ret != 0xe1)) {
+ printk("Version != d1 or e1\n");
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+
+ return NULL;
+}
+
+static struct dvb_frontend_ops cx24123_ops = {
+
+ .info = {
+ .name = "Conexant CX24123/CX24109",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */
+ .frequency_tolerance = 29500,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_RECOVER
+ },
+
+ .release = cx24123_release,
+
+ .init = cx24123_initfe,
+ .set_frontend = cx24123_set_frontend,
+ .get_frontend = cx24123_get_frontend,
+ .read_status = cx24123_read_status,
+ .read_ber = cx24123_read_ber,
+ .read_signal_strength = cx24123_read_signal_strength,
+ .read_snr = cx24123_read_snr,
+ .read_ucblocks = cx24123_read_ucblocks,
+ .diseqc_send_master_cmd = cx24123_send_diseqc_msg,
+ .set_tone = cx24123_set_tone,
+ .set_voltage = cx24123_set_voltage,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cx24123_attach);
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
new file mode 100644
index 000000000000..0c922b5e9263
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -0,0 +1,51 @@
+/*
+ Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+ Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef CX24123_H
+#define CX24123_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24123_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /*
+ cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
+ for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
+ from register 0x29 of the CX24123 demodulator
+ */
+ int use_isl6421;
+
+ /* PLL maintenance */
+ int (*pll_init)(struct dvb_frontend* fe);
+ 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);
+
+ void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
+};
+
+extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c);
+
+#endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index 6b0553608610..ae589adb1c0a 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -700,10 +700,9 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct dib3000_state* state = NULL;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct dib3000_state));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index c024fad17337..3b303dbb6156 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -832,10 +832,9 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
u16 devid;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct dib3000_state));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index f857b869616c..1b9934ea5b06 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -107,18 +107,19 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = {
};
EXPORT_SYMBOL(dvb_pll_microtune_4042);
-struct dvb_pll_desc dvb_pll_thomson_dtt7611 = {
- .name = "Thomson dtt7611",
- .min = 44000000,
- .max = 958000000,
+struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson dtt761x",
+ .min = 57000000,
+ .max = 863000000,
.count = 3,
.entries = {
- { 157250000, 44000000, 62500, 0x8e, 0x39 },
- { 454000000, 44000000, 62500, 0x8e, 0x3a },
+ { 147000000, 44000000, 62500, 0x8e, 0x39 },
+ { 417000000, 44000000, 62500, 0x8e, 0x3a },
{ 999999999, 44000000, 62500, 0x8e, 0x3c },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt7611);
+EXPORT_SYMBOL(dvb_pll_thomson_dtt761x);
struct dvb_pll_desc dvb_pll_unknown_1 = {
.name = "unknown 1", /* used by dntv live dvb-t */
@@ -332,7 +333,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
.name = "Samsung TBMV30111IN",
.min = 54000000,
.max = 860000000,
- .count = 4,
+ .count = 6,
.entries = {
{ 172000000, 44000000, 166666, 0xb4, 0x01 },
{ 214000000, 44000000, 166666, 0xb4, 0x02 },
@@ -344,6 +345,23 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
};
EXPORT_SYMBOL(dvb_pll_tbmv30111in);
+/*
+ * Philips SD1878 Tuner.
+ */
+struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+ .name = "Philips SD1878",
+ .min = 950000,
+ .max = 2150000,
+ .count = 4,
+ .entries = {
+ { 1250000, 499, 500, 0xc4, 0x00},
+ { 1550000, 499, 500, 0xc4, 0x40},
+ { 2050000, 499, 500, 0xc4, 0x80},
+ { 2150000, 499, 500, 0xc4, 0xc0},
+ },
+};
+EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261);
+
/* ----------------------------------------------------------- */
/* code */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 497d31dcf41e..f682c09189b3 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -25,7 +25,7 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt759x;
extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
extern struct dvb_pll_desc dvb_pll_lg_z201;
extern struct dvb_pll_desc dvb_pll_microtune_4042;
-extern struct dvb_pll_desc dvb_pll_thomson_dtt7611;
+extern struct dvb_pll_desc dvb_pll_thomson_dtt761x;
extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;
@@ -39,6 +39,7 @@ extern struct dvb_pll_desc dvb_pll_tded4;
extern struct dvb_pll_desc dvb_pll_tuv1236d;
extern struct dvb_pll_desc dvb_pll_tdhu2;
extern struct dvb_pll_desc dvb_pll_tbmv30111in;
+extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
u32 freq, int bandwidth);
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index cb5301865d07..4691ac54bc1d 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -27,6 +27,7 @@
* DViCO FusionHDTV 3 Gold-T
* DViCO FusionHDTV 5 Gold
* DViCO FusionHDTV 5 Lite
+ * DViCO FusionHDTV 5 USB Gold
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
*
* TODO:
@@ -402,6 +403,8 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
state->config->pll_set(fe, param);
/* Keep track of the new frequency */
+ /* FIXME this is the wrong way to do this... */
+ /* The tuner is shared with the video4linux analog API */
state->current_frequency = param->frequency;
lgdt330x_SwReset(state);
@@ -711,10 +714,9 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
u8 buf[1];
/* Allocate memory for the internal state */
- state = (struct lgdt330x_state*) kmalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(*state));
/* Setup the state */
state->config = config;
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 8d672283c93d..ec4e641acc64 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -501,7 +501,8 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
case ID_VP310:
// For now we will do this only for the VP310.
// It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03
- if ((ret = mt312_readreg(state, CONFIG, &config_val) < 0))
+ ret = mt312_readreg(state, CONFIG, &config_val);
+ if (ret < 0)
return ret;
if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
{
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index f0c610f2c2df..aaaec909ddf8 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -535,9 +535,8 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct mt352_state* state = NULL;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct mt352_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct mt352_state), GFP_KERNEL);
if (state == NULL) goto error;
- memset(state,0,sizeof(*state));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index 52c416043a62..4f263e65ba14 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
#define CRC_CCIT_MASK 0x1021
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index aeafef46e3eb..78d2b93d35b9 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -1110,10 +1110,9 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
u8 buf [] = {0,0,0,0,0};
/* allocate memory for the internal state */
- state = (struct nxt200x_state*) kmalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(*state));
/* setup the state */
state->config = config;
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a458a3bfff70..a16eeba0020d 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -574,11 +574,11 @@ static struct dvb_frontend_ops nxt6000_ops = {
.symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO,
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO,
},
.release = nxt6000_release,
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 531f76246e5f..7c3aed1f546b 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -25,7 +25,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
@@ -112,7 +113,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
u8 tudata[585];
int i;
- dprintk("Firmware is %d bytes\n",fw->size);
+ dprintk("Firmware is %zd bytes\n",fw->size);
/* Get eprom data */
tudata[0] = 17;
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 18715091aed8..d69477596921 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -521,8 +521,8 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
case FEC_3_4:
s5h1420_writereg(state, 0x30, 0x04);
- s5h1420_writereg(state, 0x31, 0x12 | inversion);
- break;
+ s5h1420_writereg(state, 0x31, 0x12 | inversion);
+ break;
case FEC_5_6:
s5h1420_writereg(state, 0x30, 0x08);
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index fc06cd6b46c3..73829e647e50 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index e3b665782243..eb8a602198ca 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -5,7 +5,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
@@ -581,7 +582,7 @@ static struct dvb_frontend_ops sp887x_ops = {
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
- FE_CAN_RECOVER
+ FE_CAN_RECOVER
},
.release = sp887x_release,
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 177d71d56b67..5bcd00f792e6 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -131,6 +131,13 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : ret;
}
+int stv0299_enable_plli2c (struct dvb_frontend* fe)
+{
+ struct stv0299_state* state = fe->demodulator_priv;
+
+ return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
+}
+
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@@ -387,7 +394,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
-static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
+static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 reg0x08;
@@ -407,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
cmd = cmd << 1;
if (debug_legacy_dish_switch)
- printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+ printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
do_gettimeofday (&nexttime);
if (debug_legacy_dish_switch)
@@ -717,5 +724,6 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(stv0299_enable_plli2c);
EXPORT_SYMBOL(stv0299_writereg);
EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 9af3d71c89db..32c87b4c2f13 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -94,6 +94,7 @@ struct stv0299_config
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
+extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 425cd19136fe..21255cac9793 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -95,7 +95,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
u8 b0 [] = { reg };
u8 b1 [] = { 0 };
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
int ret;
ret = i2c_transfer (state->i2c, msg, 2);
@@ -434,7 +434,7 @@ static struct dvb_frontend_ops tda10021_ops = {
.frequency_max = 858000000,
.symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
.symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
- #if 0
+#if 0
.frequency_tolerance = ???,
.symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
#endif
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index dd02aff467fe..c63e9a5084eb 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -23,7 +23,8 @@
* This driver needs external firmware. Please use the commands
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- * download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ * download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
@@ -271,32 +272,57 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state,
static int tda10046h_set_bandwidth(struct tda1004x_state *state,
fe_bandwidth_t bandwidth)
{
- static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e };
- static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 };
- static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd };
-
+ static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
+ static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
+ static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
+
+ static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
+ static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
+ static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
+ int tda10046_clk53m;
+
+ if ((state->config->if_freq == TDA10046_FREQ_045) ||
+ (state->config->if_freq == TDA10046_FREQ_052))
+ tda10046_clk53m = 0;
+ else
+ tda10046_clk53m = 1;
switch (bandwidth) {
case BANDWIDTH_6_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
+ sizeof(bandwidth_6mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
+ sizeof(bandwidth_6mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
}
break;
case BANDWIDTH_7_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
+ sizeof(bandwidth_7mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
+ sizeof(bandwidth_7mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
}
break;
case BANDWIDTH_8_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
+ sizeof(bandwidth_8mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
+ sizeof(bandwidth_8mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
}
break;
@@ -418,9 +444,22 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
static void tda10046_init_plls(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
+ int tda10046_clk53m;
+
+ if ((state->config->if_freq == TDA10046_FREQ_045) ||
+ (state->config->if_freq == TDA10046_FREQ_052))
+ tda10046_clk53m = 0;
+ else
+ tda10046_clk53m = 1;
tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
- tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10
+ if(tda10046_clk53m) {
+ printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
+ } else {
+ printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
+ }
if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
@@ -428,26 +467,32 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
}
- tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
+ if(tda10046_clk53m)
+ tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
+ else
+ tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
+ /* Note clock frequency is handled implicitly */
switch (state->config->if_freq) {
- case TDA10046_FREQ_3617:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
- break;
- case TDA10046_FREQ_3613:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x13);
- break;
case TDA10046_FREQ_045:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
break;
case TDA10046_FREQ_052:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
+ break;
+ case TDA10046_FREQ_3617:
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
+ break;
+ case TDA10046_FREQ_3613:
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
break;
}
tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
+ /* let the PLLs settle */
+ msleep(120);
}
static int tda10046_fwupload(struct dvb_frontend* fe)
@@ -462,13 +507,13 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
/* let the clocks recover from sleep */
msleep(5);
+ /* The PLLs need to be reprogrammed after sleep */
+ tda10046_init_plls(fe);
+
/* don't re-upload unless necessary */
if (tda1004x_check_upload_ok(state) == 0)
return 0;
- /* set parameters */
- tda10046_init_plls(fe);
-
if (state->config->request_firmware != NULL) {
/* request the firmware, this will block until someone uploads it */
printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
@@ -484,7 +529,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
return ret;
} else {
/* boot from firmware eeprom */
- /* Hac Note: we might need to do some GPIO Magic here */
printk(KERN_INFO "tda1004x: booting from eeprom\n");
tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
msleep(300);
@@ -606,10 +650,9 @@ static int tda10046_init(struct dvb_frontend* fe)
// tda setup
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
- tda1004x_write_byteI(state, TDA1004X_AUTO, 7); // select HP stream
- tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
+ tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream
+ tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
- tda10046_init_plls(fe);
switch (state->config->agc_config) {
case TDA10046_AGC_DEFAULT:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
@@ -626,25 +669,22 @@ static int tda10046_init(struct dvb_frontend* fe)
case TDA10046_AGC_TDA827X:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
- tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize
- tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+ tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
+ tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
break;
}
+ tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // }
- tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1
+ tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
- tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup
- tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config
- tda1004x_write_byteI(state, TDA10046H_GPIO_SELECT, 8); // GPIO select
-
state->initialised = 1;
return 0;
}
@@ -686,9 +726,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// Set standard params.. or put them to auto
if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
- (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
- (fe_params->u.ofdm.constellation == QAM_AUTO) ||
- (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
+ (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
+ (fe_params->u.ofdm.constellation == QAM_AUTO) ||
+ (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
@@ -851,6 +891,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
{
struct tda1004x_state* state = fe->demodulator_priv;
+
dprintk("%s\n", __FUNCTION__);
// inversion status
@@ -875,16 +916,18 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
break;
}
break;
-
case TDA1004X_DEMOD_TDA10046:
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
- case 0x60:
+ case 0x5c:
+ case 0x54:
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
break;
- case 0x6e:
+ case 0x6a:
+ case 0x60:
fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
break;
- case 0x80:
+ case 0x7b:
+ case 0x70:
fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
break;
}
diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig
index f02842be0d60..84f8f9f52869 100644
--- a/drivers/media/dvb/pluto2/Kconfig
+++ b/drivers/media/dvb/pluto2/Kconfig
@@ -8,7 +8,7 @@ config DVB_PLUTO2
Support for PCI cards based on the Pluto2 FPGA like the Satelco
Easywatch Mobile Terrestrial DVB-T Receiver.
- Since these cards have no MPEG decoder onboard, they transmit
+ Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
an external software decoder to watch TV on your computer.
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index bbebd1c4caca..1c5316e209ef 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -584,11 +584,10 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
struct dmx_demux *dmx;
int ret = -ENOMEM;
- pluto = kmalloc(sizeof(struct pluto), GFP_KERNEL);
+ pluto = kzalloc(sizeof(struct pluto), GFP_KERNEL);
if (!pluto)
goto out;
- memset(pluto, 0, sizeof(struct pluto));
pluto->pdev = pdev;
ret = pci_enable_device(pdev);
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index fa5034a9ecf5..5b2aadb8385c 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -18,9 +18,10 @@ config DVB_AV7110
This driver only supports the fullfeatured cards with
onboard MPEG2 decoder.
- This driver needs an external firmware. Please use the script
- "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ This driver needs an external firmware. Please use the script
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a card and want to use it.
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index 825ab1c38a4f..a690730ac39d 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -16,7 +16,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
hostprogs-y := fdump
ifdef CONFIG_DVB_AV7110_FIRMWARE
-$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
+$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
$(obj)/av7110_firm.h:
$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 7dae91e5863c..27494901975f 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -81,7 +81,7 @@ static int adac = DVB_ADAC_TI;
static int hw_sections;
static int rgb_on;
static int volume = 255;
-static int budgetpatch = 0;
+static int budgetpatch;
module_param_named(debug, av7110_debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -103,7 +103,7 @@ MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0
static void restart_feeds(struct av7110 *av7110);
-static int av7110_num = 0;
+static int av7110_num;
#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
{\
@@ -133,7 +133,13 @@ static void init_av7110_av(struct av7110 *av7110)
/* remaining inits according to card and frontend type */
av7110->analog_tuner_flags = 0;
av7110->current_input = 0;
- if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
+ if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
+ printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_MSP34x5;
+ av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
+ }
+ else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_CRYSTAL;
@@ -156,10 +162,10 @@ static void init_av7110_av(struct av7110 *av7110)
else {
av7110->adac_type = adac;
printk("dvb-ttpci: adac type set to %d @ card %d\n",
- av7110->dvb_adapter.num, av7110->adac_type);
+ av7110->adac_type, av7110->dvb_adapter.num);
}
- if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {
+ if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
// switch DVB SCART on
ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
if (ret < 0)
@@ -190,17 +196,15 @@ static void recover_arm(struct av7110 *av7110)
av7110_bootarm(av7110);
msleep(100);
- restart_feeds(av7110);
- av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
-}
-static void arm_error(struct av7110 *av7110)
-{
- dprintk(4, "%p\n",av7110);
+ init_av7110_av(av7110);
+
+ /* card-specific recovery */
+ if (av7110->recover)
+ av7110->recover(av7110);
- av7110->arm_errors++;
- av7110->arm_ready = 0;
- recover_arm(av7110);
+ restart_feeds(av7110);
+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
}
static void av7110_arm_sync(struct av7110 *av7110)
@@ -240,26 +244,22 @@ static int arm_thread(void *data)
if (down_interruptible(&av7110->dcomlock))
break;
-
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
up(&av7110->dcomlock);
- if (newloops == av7110->arm_loops) {
+ if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
av7110->dvb_adapter.num);
- arm_error(av7110);
- av7710_set_video_mode(av7110, vidmode);
-
- init_av7110_av(av7110);
+ recover_arm(av7110);
if (down_interruptible(&av7110->dcomlock))
break;
-
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
up(&av7110->dcomlock);
}
av7110->arm_loops = newloops;
+ av7110->arm_errors = 0;
}
av7110->arm_thread = NULL;
@@ -510,10 +510,6 @@ static void gpioirq(unsigned long data)
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
av7110->video_size.h = h_ar & 0xfff;
- dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
- av7110->video_size.w,
- av7110->video_size.h,
- av7110->video_size.aspect_ratio);
event.type = VIDEO_EVENT_SIZE_CHANGED;
event.u.size.w = av7110->video_size.w;
@@ -535,6 +531,11 @@ static void gpioirq(unsigned long data)
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
}
+
+ dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
+ av7110->video_size.w, av7110->video_size.h,
+ av7110->video_size.aspect_ratio);
+
dvb_video_add_event(av7110, &event);
break;
}
@@ -714,6 +715,8 @@ static struct dvb_device dvbdev_osd = {
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid)
{
+ u16 aflags = 0;
+
dprintk(4, "%p\n", av7110);
if (vpid == 0x1fff || apid == 0x1fff ||
@@ -725,8 +728,11 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
av7110->pids[DMX_PES_PCR] = 0;
}
- return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5,
- pcrpid, vpid, apid, ttpid, subpid);
+ if (av7110->audiostate.bypass_mode)
+ aflags |= 0x8000;
+
+ return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
+ pcrpid, vpid, apid, ttpid, subpid, aflags);
}
int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
@@ -1043,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110)
struct dvb_demux *dvbdmx = &av7110->demux;
struct dvb_demux_feed *feed;
int mode;
- int i;
+ int i, j;
dprintk(4, "%p\n", av7110);
@@ -1051,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110)
av7110->playing = 0;
av7110->rec_mode = 0;
- for (i = 0; i < dvbdmx->filternum; i++) {
+ for (i = 0; i < dvbdmx->feednum; i++) {
feed = &dvbdmx->feed[i];
- if (feed->state == DMX_STATE_GO)
+ if (feed->state == DMX_STATE_GO) {
+ if (feed->type == DMX_TYPE_SEC) {
+ for (j = 0; j < dvbdmx->filternum; j++) {
+ if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
+ continue;
+ if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
+ continue;
+ if (dvbdmx->filter[j].state == DMX_STATE_GO)
+ dvbdmx->filter[j].state = DMX_STATE_READY;
+ }
+ }
av7110_start_feed(feed);
+ }
}
if (mode)
@@ -1483,9 +1500,9 @@ static int get_firmware(struct av7110* av7110)
if (ret == -ENOENT) {
printk(KERN_ERR "dvb-ttpci: could not load firmware,"
" file not found: dvb-ttpci-01.fw\n");
- printk(KERN_ERR "dvb-ttpci: usually this should be in"
- " /usr/lib/hotplug/firmware\n");
- printk(KERN_ERR "dvb-ttpci: and can be downloaded here"
+ printk(KERN_ERR "dvb-ttpci: usually this should be in "
+ "/usr/lib/hotplug/firmware or /lib/firmware\n");
+ printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
" http://www.linuxtv.org/download/dvb/firmware/\n");
} else
printk(KERN_ERR "dvb-ttpci: cannot request firmware"
@@ -2110,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_fe_params = *params;
ret = av7110->fe_set_frontend(fe, params);
+ }
return ret;
}
@@ -2153,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_master_cmd = *cmd;
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
+ }
return ret;
}
@@ -2163,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_minicmd = minicmd;
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
+ }
return ret;
}
@@ -2173,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_tone = tone;
ret = av7110->fe_set_tone(fe, tone);
+ }
return ret;
}
@@ -2183,12 +2208,14 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_voltage = voltage;
ret = av7110->fe_set_voltage(fe, voltage);
+ }
return ret;
}
-static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd)
+static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -2198,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un
return ret;
}
+static void dvb_s_recover(struct av7110* av7110)
+{
+ av7110_fe_init(av7110->fe);
+
+ av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
+ if (av7110->saved_master_cmd.msg_len) {
+ msleep(20);
+ av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
+ }
+ msleep(20);
+ av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
+ msleep(20);
+ av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
+
+ av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
+}
+
static u8 read_pwm(struct av7110* av7110)
{
u8 b = 0xff;
@@ -2235,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
@@ -2244,15 +2289,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
// Try the grundig 29504-451
- av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
@@ -2274,12 +2321,12 @@ static int frontend_init(struct av7110 *av7110)
case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
// ALPS TDLB7
- av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+ av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
break;
case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
- av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+ av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break;
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
@@ -2289,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
}
break;
@@ -2314,8 +2362,11 @@ static int frontend_init(struct av7110 *av7110)
case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
/* ALPS BSBE1 */
av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
- if (av7110->fe)
+ if (av7110->fe) {
av7110->fe->ops->set_voltage = lnbp21_set_voltage;
+ av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
+ av7110->recover = dvb_s_recover;
+ }
break;
}
}
@@ -2514,14 +2565,12 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
}
/* prepare the av7110 device struct */
- av7110 = kmalloc(sizeof(struct av7110), GFP_KERNEL);
+ av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
if (!av7110) {
dprintk(1, "out of memory\n");
return -ENOMEM;
}
- memset(av7110, 0, sizeof(struct av7110));
-
av7110->card_name = (char*) pci_ext->ext_priv;
av7110->dev = dev;
dev->ext_priv = av7110;
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index cce00ef293e9..6ea30df2e823 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -98,7 +98,8 @@ struct av7110 {
int adac_type; /* audio DAC type */
#define DVB_ADAC_TI 0
#define DVB_ADAC_CRYSTAL 1
-#define DVB_ADAC_MSP 2
+#define DVB_ADAC_MSP34x0 2
+#define DVB_ADAC_MSP34x5 3
#define DVB_ADAC_NONE -1
@@ -228,6 +229,9 @@ struct av7110 {
struct dvb_video_events video_events;
video_size_t video_size;
+ u16 wssMode;
+ u16 wssData;
+
u32 ir_config;
u32 ir_command;
void (*ir_handler)(struct av7110 *av7110, u32 ircom);
@@ -245,6 +249,15 @@ struct av7110 {
struct dvb_frontend* fe;
fe_status_t fe_status;
+
+ /* crash recovery */
+ void (*recover)(struct av7110* av7110);
+ struct dvb_frontend_parameters saved_fe_params;
+ fe_sec_voltage_t saved_voltage;
+ fe_sec_tone_mode_t saved_tone;
+ struct dvb_diseqc_master_cmd saved_master_cmd;
+ fe_sec_mini_cmd_t saved_minicmd;
+
int (*fe_init)(struct dvb_frontend* fe);
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
@@ -252,7 +265,7 @@ struct av7110 {
int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+ int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 0696a5a4f855..400facec7407 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -309,7 +309,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
i2c_writereg(av7110, 0x20, 0x04, volright);
return 0;
- case DVB_ADAC_MSP:
+ case DVB_ADAC_MSP34x0:
vol = (volleft > volright) ? volleft : volright;
val = (vol * 0x73 / 255) << 8;
if (vol > 0)
@@ -1256,7 +1256,9 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_SET_BYPASS_MODE:
- ret = -EINVAL;
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ ret = -EINVAL;
+ av7110->audiostate.bypass_mode = (int)arg;
break;
case AUDIO_CHANNEL_SELECT:
@@ -1295,7 +1297,11 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_GET_CAPABILITIES:
- *(int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ else
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
+ AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
break;
case AUDIO_CLEAR_BUFFER:
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 87106e8bf35b..b2e63e9fc053 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -146,52 +146,52 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
{
int i;
int blocks, rest;
- u32 base, bootblock = BOOT_BLOCK;
+ u32 base, bootblock = AV7110_BOOT_BLOCK;
dprintk(4, "%p\n", av7110);
- blocks = len / BOOT_MAX_SIZE;
- rest = len % BOOT_MAX_SIZE;
+ blocks = len / AV7110_BOOT_MAX_SIZE;
+ rest = len % AV7110_BOOT_MAX_SIZE;
base = DRAM_START_CODE;
for (i = 0; i < blocks; i++) {
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
return -ETIMEDOUT;
}
dprintk(4, "writing DRAM block %d\n", i);
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
bootblock ^= 0x1400;
- iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
- base += BOOT_MAX_SIZE;
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ base += AV7110_BOOT_MAX_SIZE;
}
if (rest > 0) {
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
return -ETIMEDOUT;
}
if (rest > 4)
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE, rest);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
else
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
- iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
}
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
return -ETIMEDOUT;
}
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
return -ETIMEDOUT;
}
@@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110)
dprintk(4, "%p\n", av7110);
+ av7110->arm_ready = 0;
+
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
/* Disable DEBI and GPIO irq */
@@ -260,7 +262,7 @@ int av7110_bootarm(struct av7110 *av7110)
//saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
@@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
+ av7110->arm_errors++;
return -ETIMEDOUT;
}
msleep(1);
@@ -1206,9 +1209,9 @@ int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
switch (cap->cmd) {
case OSD_CAP_MEMSIZE:
if (FW_4M_SDRAM(av7110->arm_app))
- cap->val = 1000000;
+ cap->val = 1000000;
else
- cap->val = 92000;
+ cap->val = 92000;
return 0;
default:
return -EINVAL;
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 2a5e87ba1052..4e173c67fbb2 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -18,7 +18,7 @@ enum av7110_bootstate
{
BOOTSTATE_BUFFER_EMPTY = 0,
BOOTSTATE_BUFFER_FULL = 1,
- BOOTSTATE_BOOT_COMPLETE = 2
+ BOOTSTATE_AV7110_BOOT_COMPLETE = 2
};
enum av7110_type_rec_play_format
@@ -167,7 +167,8 @@ enum av7110_encoder_command {
LoadVidCode,
SetMonitorType,
SetPanScanType,
- SetFreezeMode
+ SetFreezeMode,
+ SetWSSConfig
};
enum av7110_rec_play_state {
@@ -294,11 +295,11 @@ enum av7110_command_type {
#define DPRAM_BASE 0x4000
/* boot protocol area */
-#define BOOT_STATE (DPRAM_BASE + 0x3F8)
-#define BOOT_SIZE (DPRAM_BASE + 0x3FA)
-#define BOOT_BASE (DPRAM_BASE + 0x3FC)
-#define BOOT_BLOCK (DPRAM_BASE + 0x400)
-#define BOOT_MAX_SIZE 0xc00
+#define AV7110_BOOT_STATE (DPRAM_BASE + 0x3F8)
+#define AV7110_BOOT_SIZE (DPRAM_BASE + 0x3FA)
+#define AV7110_BOOT_BASE (DPRAM_BASE + 0x3FC)
+#define AV7110_BOOT_BLOCK (DPRAM_BASE + 0x400)
+#define AV7110_BOOT_MAX_SIZE 0xc00
/* firmware command protocol area */
#define IRQ_STATE (DPRAM_BASE + 0x0F4)
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index f5e59fc924af..9138132ad25f 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -17,6 +17,8 @@ static int av_cnt;
static struct av7110 *av_list[4];
static struct input_dev *input_dev;
+static u8 delay_timer_finished;
+
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
@@ -112,13 +114,16 @@ static void av7110_emit_key(unsigned long parm)
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
+ delay_timer_finished = 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);
-
- } else
+ if (delay_timer_finished)
+ input_event(input_dev, EV_KEY, keycode, 2);
+ } else {
+ delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keycode, !0);
+ }
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
@@ -145,7 +150,8 @@ static void input_register_keys(void)
static void input_repeat_key(unsigned long data)
{
- /* dummy routine to disable autorepeat in the input driver */
+ /* called by the input driver after rep[REP_DELAY] ms */
+ delay_timer_finished = 1;
}
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index b5aea4129fa7..94cf38c7e8a8 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -490,6 +490,58 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
break;
}
+ case VIDIOC_G_SLICED_VBI_CAP:
+ {
+ struct v4l2_sliced_vbi_cap *cap = arg;
+ dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
+ memset(cap, 0, sizeof *cap);
+ if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+ cap->service_set = V4L2_SLICED_WSS_625;
+ cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
+ }
+ break;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ dprintk(2, "VIDIOC_G_FMT:\n");
+ if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
+ FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EAGAIN; /* handled by core driver */
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ if (av7110->wssMode) {
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
+ }
+ break;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ dprintk(2, "VIDIOC_S_FMT\n");
+ if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
+ FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EAGAIN; /* handled by core driver */
+ if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
+ f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ /* WSS controlled by firmware */
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
+ SetWSSConfig, 1, 0);
+ } else {
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
+ /* WSS controlled by userspace */
+ av7110->wssMode = 1;
+ av7110->wssData = 0;
+ }
+ break;
+ }
default:
printk("no such ioctl\n");
return -ENOIOCTLCMD;
@@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
+static int av7110_vbi_reset(struct inode *inode, struct file *file)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+
+ dprintk(2, "%s\n", __FUNCTION__);
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ return 0;
+ else
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+}
+
+static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+ struct v4l2_sliced_vbi_data d;
+ int rc;
+
+ dprintk(2, "%s\n", __FUNCTION__);
+ if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
+ return -EINVAL;
+ if (copy_from_user(&d, data, count))
+ return -EFAULT;
+ if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
+ return -EINVAL;
+ if (d.id) {
+ av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig,
+ 2, 1, av7110->wssData);
+ } else {
+ av7110->wssData = 0;
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+ }
+ return (rc < 0) ? rc : count;
+}
/****************************************************************************
* INITIALIZATION
@@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
+ { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
+ { VIDIOC_G_FMT, SAA7146_BEFORE },
+ { VIDIOC_S_FMT, SAA7146_BEFORE },
{ 0, 0 }
};
@@ -587,7 +682,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
av7110->dvb_adapter.num);
- av7110->adac_type = DVB_ADAC_MSP;
+ av7110->adac_type = DVB_ADAC_MSP34x0;
msleep(100); // the probing above resets the msp...
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
@@ -692,12 +787,11 @@ int av7110_init_v4l(struct av7110 *av7110)
saa7146_vv_release(dev);
return -ENODEV;
}
- if (av7110->analog_tuner_flags) {
- if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
- } else {
+ if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
+ ERR(("cannot register vbi v4l2 device. skipping.\n"));
+ } else {
+ if (av7110->analog_tuner_flags)
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
- }
}
return 0;
}
@@ -778,7 +872,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
static struct saa7146_ext_vv av7110_vv_data_st = {
.inputs = 1,
.audios = 1,
- .capabilities = 0,
+ .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = 0,
.stds = &standard[0],
@@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
};
static struct saa7146_ext_vv av7110_vv_data_c = {
.inputs = 1,
.audios = 1,
- .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
+ .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0],
@@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
};
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9f51bae7194c..1465c04e49aa 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -37,6 +37,7 @@
#include "stv0299.h"
#include "tda10021.h"
#include "tda1004x.h"
+#include "dvb-pll.h"
#include <media/saa7146_vv.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -127,7 +128,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
- result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
+ result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@@ -145,7 +146,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
- result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
+ result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@@ -192,7 +193,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 = 500; // 5 seconds (4.4.6 Ready)
+ int timeout = 50; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
@@ -256,19 +257,37 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
+ int cam_present = 0;
if (slot != 0)
return -EINVAL;
- if (!budget_av->slot_status) {
+ if (!budget_av->slot_status)
+ {
+ // first of all test the card detect line
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
if (saa7146_read(saa, PSR) & MASK_06)
{
+ cam_present = 1;
+ }
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+
+ // that is unreliable however, so try and read from IO memory
+ if (!cam_present)
+ {
+ saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+ if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
+ {
+ cam_present = 1;
+ }
+ }
+
+ // did we find something?
+ if (cam_present) {
printk(KERN_INFO "budget-av: cam inserted\n");
budget_av->slot_status = 1;
}
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
} else if (!open) {
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
@@ -484,6 +503,140 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
return 0;
}
+#define MIN2(a,b) ((a) < (b) ? (a) : (b))
+#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
+
+static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dvb_frontend_parameters *params)
+{
+ u8 reg0 [2] = { 0x00, 0x00 };
+ u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
+ u8 reg2 [3] = { 0x02, 0x00, 0x00 };
+ int _fband;
+ int first_ZF;
+ int R, A, N, P, M;
+ struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
+ int freq = params->frequency;
+
+ first_ZF = (freq) / 1000;
+
+ if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) <
+ abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890))))
+ _fband = 2;
+ else
+ _fband = 3;
+
+ if (_fband == 2) {
+ if (((first_ZF >= 950) && (first_ZF < 1350)) ||
+ ((first_ZF >= 1430) && (first_ZF < 1950)))
+ reg0[1] = 0x07;
+ else if (((first_ZF >= 1350) && (first_ZF < 1430)) ||
+ ((first_ZF >= 1950) && (first_ZF < 2150)))
+ reg0[1] = 0x0B;
+ }
+
+ if(_fband == 3) {
+ if (((first_ZF >= 950) && (first_ZF < 1350)) ||
+ ((first_ZF >= 1455) && (first_ZF < 1950)))
+ reg0[1] = 0x07;
+ else if (((first_ZF >= 1350) && (first_ZF < 1420)) ||
+ ((first_ZF >= 1950) && (first_ZF < 2150)))
+ reg0[1] = 0x0B;
+ else if ((first_ZF >= 1420) && (first_ZF < 1455))
+ reg0[1] = 0x0F;
+ }
+
+ if (first_ZF > 1525)
+ reg1[1] |= 0x80;
+ else
+ reg1[1] &= 0x7F;
+
+ if (_fband == 2) {
+ if (first_ZF > 1430) { /* 1430MHZ */
+ reg1[1] &= 0xCF; /* N2 */
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ } else {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ }
+ }
+
+ if (_fband == 3) {
+ if ((first_ZF >= 1455) &&
+ (first_ZF < 1630)) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ } else {
+ if (first_ZF < 1455) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ } else {
+ if (first_ZF >= 1630) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ }
+ }
+ }
+ }
+
+ /* set ports, enable P0 for symbol rates > 4Ms/s */
+ if (params->u.qpsk.symbol_rate >= 4000000)
+ reg1[1] |= 0x0c;
+ else
+ reg1[1] |= 0x04;
+
+ reg2[1] |= 0x0c;
+
+ R = 64;
+ A = 64;
+ P = 64; //32
+
+ M = (freq * R) / 4; /* in Mhz */
+ N = (M - A * 1000) / (P * 1000);
+
+ reg1[1] |= (N >> 9) & 0x03;
+ reg1[2] = (N >> 1) & 0xff;
+ reg1[3] = (N << 7) & 0x80;
+
+ reg2[1] |= (R >> 8) & 0x03;
+ reg2[2] = R & 0xFF; /* R */
+
+ reg1[3] |= A & 0x7f; /* A */
+
+ if (P == 64)
+ reg1[1] |= 0x40; /* Prescaler 64/65 */
+
+ reg0[1] |= 0x03;
+
+ /* already enabled - do not reenable i2c repeater or TX fails */
+ msg.buf = reg0;
+ msg.len = sizeof(reg0);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ stv0299_enable_plli2c(fe);
+ msg.buf = reg1;
+ msg.len = sizeof(reg1);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ stv0299_enable_plli2c(fe);
+ msg.buf = reg2;
+ msg.len = sizeof(reg2);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+
static u8 typhoon_cinergy1200s_inittab[] = {
0x01, 0x15,
0x02, 0x30,
@@ -553,6 +706,18 @@ static struct stv0299_config cinergy_1200s_config = {
.pll_set = philips_su1278_ty_ci_pll_set,
};
+static struct stv0299_config cinergy_1200s_1894_0010_config = {
+ .demod_address = 0x68,
+ .inittab = typhoon_cinergy1200s_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0229_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+ .pll_set = philips_su1278sh2_tua6100_pll_set,
+};
static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
@@ -700,8 +865,117 @@ static struct tda1004x_config philips_tu1216_config = {
.request_firmware = philips_tu1216_request_firmware,
};
+static u8 philips_sd1878_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7d,
+ 0x05, 0x35,
+ 0x06, 0x40,
+ 0x07, 0x00,
+ 0x08, 0x43,
+ 0x09, 0x02,
+ 0x0C, 0x51,
+ 0x0D, 0x82,
+ 0x0E, 0x23,
+ 0x10, 0x3f,
+ 0x11, 0x84,
+ 0x12, 0xb9,
+ 0x15, 0xc9,
+ 0x16, 0x19,
+ 0x17, 0x8c,
+ 0x18, 0x59,
+ 0x19, 0xf8,
+ 0x1a, 0xfe,
+ 0x1c, 0x7f,
+ 0x1d, 0x00,
+ 0x1e, 0x00,
+ 0x1f, 0x50,
+ 0x20, 0x00,
+ 0x21, 0x00,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x28, 0x00,
+ 0x29, 0x28,
+ 0x2a, 0x14,
+ 0x2b, 0x0f,
+ 0x2c, 0x09,
+ 0x2d, 0x09,
+ 0x31, 0x1f,
+ 0x32, 0x19,
+ 0x33, 0xfc,
+ 0x34, 0x93,
+ 0xff, 0xff
+};
+
+static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dvb_frontend_parameters *params)
+{
+ u8 buf[4];
+ int rc;
+ struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
+
+ if((params->frequency < 950000) || (params->frequency > 2150000))
+ return -EINVAL;
+
+ rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
+ params->frequency, 0);
+ if(rc < 0) return rc;
+
+ if(i2c_transfer(i2c, &tuner_msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
+ u32 srate, u32 ratio)
+{
+ u8 aclk = 0;
+ u8 bclk = 0;
+ u8 m1;
+ aclk = 0xb5;
+ if (srate < 2000000)
+ bclk = 0x86;
+ else if (srate < 5000000)
+ bclk = 0x89;
+ else if (srate < 15000000)
+ bclk = 0x8f;
+ else if (srate < 45000000)
+ bclk = 0x95;
+
+ m1 = 0x14;
+ if (srate < 4000000)
+ m1 = 0x10;
+
+ stv0299_writereg(fe, 0x0e, 0x23);
+ stv0299_writereg(fe, 0x0f, 0x94);
+ stv0299_writereg(fe, 0x10, 0x39);
+ stv0299_writereg(fe, 0x13, aclk);
+ stv0299_writereg(fe, 0x14, bclk);
+ stv0299_writereg(fe, 0x15, 0xc9);
+ stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+ stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+ stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+ stv0299_writereg(fe, 0x0f, 0x80 | m1);
+
+ return 0;
+}
+
+static struct stv0299_config philips_sd1878_config = {
+ .demod_address = 0x68,
+ .inittab = philips_sd1878_inittab,
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+ .lock_output = STV0229_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
+ .pll_set = philips_sd1878_tda8261_pll_set,
+};
static u8 read_pwm(struct budget_av *budget_av)
{
@@ -722,7 +996,10 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_KNC1_PLUS 0x0011
#define SUBID_DVBS_TYPHOON 0x4f56
#define SUBID_DVBS_CINERGY1200 0x1154
+#define SUBID_DVBS_CYNERGY1200N 0x1155
+#define SUBID_DVBS_TV_STAR 0x0014
+#define SUBID_DVBS_TV_STAR_CI 0x0016
#define SUBID_DVBC_KNC1 0x0020
#define SUBID_DVBC_KNC1_PLUS 0x0021
#define SUBID_DVBC_CINERGY1200 0x1156
@@ -749,6 +1026,22 @@ static void frontend_init(struct budget_av *budget_av)
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1:
+ if (saa->pci->subsystem_vendor == 0x1894) {
+ fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
+ &budget_av->budget.i2c_adap);
+ } else {
+ fe = stv0299_attach(&typhoon_config,
+ &budget_av->budget.i2c_adap);
+ }
+ break;
+
+ case SUBID_DVBS_TV_STAR:
+ case SUBID_DVBS_TV_STAR_CI:
+ case SUBID_DVBS_CYNERGY1200N:
+ fe = stv0299_attach(&philips_sd1878_config,
+ &budget_av->budget.i2c_adap);
+ break;
+
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBS_TYPHOON:
fe = stv0299_attach(&typhoon_config,
@@ -854,11 +1147,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
dprintk(2, "dev: %p\n", dev);
- if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
+ if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
return -ENOMEM;
- memset(budget_av, 0, sizeof(struct budget_av));
-
budget_av->has_saa7113 = 0;
budget_av->budget.ci_present = 0;
@@ -993,22 +1284,28 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
+MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
+MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
+ MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
+ MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
+ MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
+ MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
{
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 017fcbccb8cc..633e68c341c8 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -404,9 +404,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
/* frontend power on */
- if (bi->type == BUDGET_FS_ACTIVY)
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
- else
+ if (bi->type != BUDGET_FS_ACTIVY)
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
if (budget_register(budget) == 0) {
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index fafe6407b3d0..238c77b52f89 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -112,6 +112,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
* Routines for the Fujitsu Siemens Activy budget card
* 22 kHz tone and DiSEqC are handled by the frontend.
* Voltage must be set here.
+ * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
*/
static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
{
@@ -121,11 +122,16 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
switch (voltage) {
case SEC_VOLTAGE_13:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
break;
case SEC_VOLTAGE_18:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
break;
+ case SEC_VOLTAGE_OFF:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
+ break;
default:
return -EINVAL;
}
@@ -206,7 +212,7 @@ static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
return 0;
}
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, long arg)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 buf;
@@ -580,6 +586,7 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
if (lnbp21_init(budget)) {
printk("%s: No LNBP21 found!\n", __FUNCTION__);
goto error_out;
@@ -624,7 +631,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- break;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
@@ -632,7 +639,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- break;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index c8d48cfba277..c7bb63c4d98d 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -95,6 +95,7 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_KNC1SP 11
#define BUDGET_KNC1CP 12
#define BUDGET_KNC1TP 13
+#define BUDGET_TVSTAR 14
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
index 18aa22b5478d..1f31e91195b0 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -13,7 +13,7 @@
Holger Waechtler Convergence
Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de>
- Metzler Brothers Systementwicklung GbR
+ Metzler Brothers Systementwicklung GbR
This 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/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index c6c1d41a2efb..914587d52b57 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -10,7 +10,7 @@ config DVB_TTUSB_BUDGET
Support for external USB adapters designed by Technotrend and
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
- These devices don't have a MPEG decoder built in, so you need
+ These devices don't have a MPEG decoder built in, so you need
an external software decoder to watch TV.
Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 104df610dbe1..5a13c4744f61 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1489,11 +1489,9 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV;
- if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))
+ if (!(ttusb = kzalloc(sizeof(struct ttusb), GFP_KERNEL)))
return -ENOMEM;
- memset(ttusb, 0, sizeof(struct ttusb));
-
ttusb->dev = udev;
ttusb->c = 0;
ttusb->mux_state = 0;
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index c334526af66f..83611012ef34 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -8,14 +8,15 @@ config DVB_TTUSB_DEC
produced by Hauppauge, shipped under the brand name 'DEC2000-t'
and 'DEC3000-s'.
- Even if these devices have a MPEG decoder built in, they transmit
+ Even if these devices have a MPEG decoder built in, they transmit
only compressed MPEG data over the USB bus, so you need
an external software decoder to watch TV on your computer.
- This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
- download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 8abc21890129..df831171e03c 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -369,7 +369,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
{
- struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+ struct ttusb_dec *dec = priv;
dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->audio_filter->feed->feed.ts,
@@ -380,7 +380,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
{
- struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+ struct ttusb_dec *dec = priv;
dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->video_filter->feed->feed.ts,
@@ -965,8 +965,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
case DMX_TS_PES_TELETEXT:
dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
- dprintk(" pes_type: DMX_TS_PES_TELETEXT\n");
- break;
+ dprintk(" pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
+ return -ENOSYS;
case DMX_TS_PES_PCR:
dprintk(" pes_type: DMX_TS_PES_PCR\n");
@@ -975,8 +975,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
break;
case DMX_TS_PES_OTHER:
- dprintk(" pes_type: DMX_TS_PES_OTHER\n");
- break;
+ dprintk(" pes_type: DMX_TS_PES_OTHER(not supported)\n");
+ return -ENOSYS;
default:
dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
@@ -1182,7 +1182,7 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
-static int 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 };
@@ -1203,13 +1203,12 @@ static int ttusb_init_rc(struct ttusb_dec *dec)
input_dev->keycode = rc_keys;
for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
- set_bit(rc_keys[i], input_dev->keybit);
+ set_bit(rc_keys[i], input_dev->keybit);
input_register_device(input_dev);
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);
@@ -1395,6 +1394,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
/* We can't trust the USB IDs that some firmwares
give the box */
switch (model) {
+ case 0x00070001:
case 0x00070008:
case 0x0007000c:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
@@ -1588,7 +1588,7 @@ static int fe_send_command(struct dvb_frontend* fe, const u8 command,
int param_length, const u8 params[],
int *result_length, u8 cmd_result[])
{
- struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
+ struct ttusb_dec* dec = fe->dvb->priv;
return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
}
@@ -1606,15 +1606,13 @@ static int ttusb_dec_probe(struct usb_interface *intf,
udev = interface_to_usbdev(intf);
- if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+ if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
printk("%s: couldn't allocate memory.\n", __FUNCTION__);
return -ENOMEM;
}
usb_set_intfdata(intf, (void *)dec);
- memset(dec, 0, sizeof(struct ttusb_dec));
-
switch (le16_to_cpu(id->idProduct)) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 725af3af5b27..a5a46175fa09 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -42,8 +42,39 @@ struct ttusbdecfe_state {
static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
- FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ struct ttusbdecfe_state* state = fe->demodulator_priv;
+ u8 b[] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ u8 result[4];
+ int len, ret;
+
+ *status=0;
+
+ ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
+ if(ret)
+ return ret;
+
+ if(len != 4) {
+ printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ switch(result[3]) {
+ case 1: /* not tuned yet */
+ case 2: /* no signal/no lock*/
+ break;
+ case 3: /* signal found and locked*/
+ *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ break;
+ case 4:
+ *status = FE_TIMEDOUT;
+ break;
+ default:
+ pr_info("%s: returned unknown value: %d\n",
+ __FUNCTION__, result[3]);
+ return -EIO;
+ }
return 0;
}
@@ -64,6 +95,16 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
return 0;
}
+static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings)
+{
+ fesettings->min_delay_ms = 1500;
+ /* Drift compensation makes no sense for DVB-T */
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
@@ -212,6 +253,8 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
.set_frontend = ttusbdecfe_dvbt_set_frontend,
+ .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
+
.read_status = ttusbdecfe_read_status,
};
@@ -223,11 +266,11 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125,
+ .symbol_rate_min = 1000000, /* guessed */
+ .symbol_rate_max = 45000000, /* guessed */
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO,
+ FE_CAN_QPSK
},
.release = ttusbdecfe_release,
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index c2ebe8754a95..dc292da2605f 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -220,6 +220,7 @@ static struct file_operations pcm20_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = pcm20_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 877c770558e9..914deab4e044 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -299,6 +299,7 @@ static struct file_operations rtrack_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = rt_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 5319a9c9a979..523be820f9c6 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -256,6 +256,7 @@ static struct file_operations aztech_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = az_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 9b0406318f2d..f1b5ac81e9d2 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -490,6 +490,7 @@ static struct file_operations cadet_fops = {
.release = cadet_release,
.read = cadet_read,
.ioctl = cadet_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 630cc786d0a4..8e499b8f64c7 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -301,6 +301,7 @@ static struct file_operations gemtek_pci_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = gemtek_pci_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -317,11 +318,10 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
struct gemtek_pci_card *card;
struct video_device *devradio;
- if ( (card = kmalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) {
+ if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) {
printk( KERN_ERR "gemtek_pci: out of memory\n" );
return -ENOMEM;
}
- memset( card, 0, sizeof( struct gemtek_pci_card ) );
if ( pci_enable_device( pci_dev ) )
goto err_pci;
@@ -394,7 +394,7 @@ static struct pci_driver gemtek_pci_driver =
static int __init gemtek_pci_init_module( void )
{
- return pci_module_init( &gemtek_pci_driver );
+ return pci_register_driver( &gemtek_pci_driver );
}
static void __exit gemtek_pci_cleanup_module( void )
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 6418f03b9ce4..47173be97b9f 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -233,6 +233,7 @@ static struct file_operations gemtek_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = gemtek_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index e5e2021a7312..36c9f5bf8cdd 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -27,34 +27,30 @@
#include <linux/pci.h>
#include <linux/videodev.h>
-#define DRIVER_VERSION "0.04"
+#define DRIVER_VERSION "0.05"
-#define PCI_VENDOR_ESS 0x125D
-#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 /* Maestro 2 */
-#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 /* Maestro 2E */
-
-#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */
+#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */
#define IO_MASK 4 /* mask register offset from GPIO_DATA
bits 1=unmask write to given bit */
#define IO_DIR 8 /* direction register offset from GPIO_DATA
bits 0/1=read/write direction */
-#define GPIO6 0x0040 /* mask bits for GPIO lines */
-#define GPIO7 0x0080
-#define GPIO8 0x0100
-#define GPIO9 0x0200
+#define GPIO6 0x0040 /* mask bits for GPIO lines */
+#define GPIO7 0x0080
+#define GPIO8 0x0100
+#define GPIO9 0x0200
-#define STR_DATA GPIO6 /* radio TEA5757 pins and GPIO bits */
-#define STR_CLK GPIO7
-#define STR_WREN GPIO8
-#define STR_MOST GPIO9
+#define STR_DATA GPIO6 /* radio TEA5757 pins and GPIO bits */
+#define STR_CLK GPIO7
+#define STR_WREN GPIO8
+#define STR_MOST GPIO9
#define FREQ_LO 50*16000
#define FREQ_HI 150*16000
-#define FREQ_IF 171200 /* 10.7*16000 */
-#define FREQ_STEP 200 /* 12.5*16 */
+#define FREQ_IF 171200 /* 10.7*16000 */
+#define FREQ_STEP 200 /* 12.5*16 */
#define FREQ2BITS(x) ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
/(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
@@ -65,39 +61,58 @@ static int radio_nr = -1;
module_param(radio_nr, int, 0);
static int radio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
+static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void maestro_remove(struct pci_dev *pdev);
+
+static struct pci_device_id maestro_r_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00 },
+ { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl);
+
+static struct pci_driver maestro_r_driver = {
+ .name = "maestro_radio",
+ .id_table = maestro_r_pci_tbl,
+ .probe = maestro_probe,
+ .remove = __devexit_p(maestro_remove),
+};
static struct file_operations maestro_fops = {
.owner = THIS_MODULE,
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
-static struct video_device maestro_radio=
-{
- .owner = THIS_MODULE,
+static struct video_device maestro_radio = {
.name = "Maestro radio",
.type = VID_TYPE_TUNER,
.hardware = VID_HARDWARE_SF16MI,
- .fops = &maestro_fops,
+ .fops = &maestro_fops,
};
-static struct radio_device
-{
- __u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
+struct radio_device {
+ u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
muted, /* VIDEO_AUDIO_MUTE */
stereo, /* VIDEO_TUNER_STEREO_ON */
tuned; /* signal strength (0 or 0xffff) */
- struct semaphore lock;
-} radio_unit = {0, 0, 0, 0, };
+ struct semaphore lock;
+};
-static __u32 radio_bits_get(struct radio_device *dev)
+static u32 radio_bits_get(struct radio_device *dev)
{
- register __u16 io=dev->io, l, rdata;
- register __u32 data=0;
- __u16 omask;
+ register u16 io=dev->io, l, rdata;
+ register u32 data=0;
+ u16 omask;
+
omask = inw(io + IO_MASK);
outw(~(STR_CLK | STR_WREN), io + IO_MASK);
outw(0, io);
@@ -120,17 +135,21 @@ static __u32 radio_bits_get(struct radio_device *dev)
data++;
udelay(2);
}
+
if(dev->muted)
outw(STR_WREN, io);
+
udelay(4);
outw(omask, io + IO_MASK);
+
return data & 0x3ffe;
}
-static void radio_bits_set(struct radio_device *dev, __u32 data)
+static void radio_bits_set(struct radio_device *dev, u32 data)
{
- register __u16 io=dev->io, l, bits;
- __u16 omask, odir;
+ register u16 io=dev->io, l, bits;
+ u16 omask, odir;
+
omask = inw(io + IO_MASK);
odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
outw(odir | STR_DATA, io + IO_DIR);
@@ -146,8 +165,10 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
outw(bits, io); /* LO level */
udelay(4);
}
+
if(!dev->muted)
outw(0, io);
+
udelay(4);
outw(omask, io + IO_MASK);
outw(odir, io + IO_DIR);
@@ -155,141 +176,103 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
}
static inline int radio_function(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+ unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
-
- switch(cmd) {
- case VIDIOCGCAP: {
- struct video_capability *v = arg;
- memset(v,0,sizeof(*v));
- strcpy(v->name, "Maestro radio");
- v->type=VID_TYPE_TUNER;
- v->channels=v->audios=1;
- return 0;
- }
- case VIDIOCGTUNER: {
- struct video_tuner *v = arg;
- if(v->tuner)
- return -EINVAL;
- (void)radio_bits_get(card);
- v->flags = VIDEO_TUNER_LOW | card->stereo;
- v->signal = card->tuned;
- strcpy(v->name, "FM");
- v->rangelow = FREQ_LO;
- v->rangehigh = FREQ_HI;
- v->mode = VIDEO_MODE_AUTO;
- return 0;
- }
- case VIDIOCSTUNER: {
- struct video_tuner *v = arg;
- if(v->tuner!=0)
- return -EINVAL;
- return 0;
- }
- case VIDIOCGFREQ: {
- unsigned long *freq = arg;
- *freq = BITS2FREQ(radio_bits_get(card));
- return 0;
- }
- case VIDIOCSFREQ: {
- unsigned long *freq = arg;
- if (*freq<FREQ_LO || *freq>FREQ_HI )
- return -EINVAL;
- radio_bits_set(card, FREQ2BITS(*freq));
+ struct radio_device *card = video_get_drvdata(dev);
+
+ switch (cmd) {
+ case VIDIOCGCAP: {
+ struct video_capability *v = arg;
+ memset(v, 0, sizeof(*v));
+ strcpy(v->name, "Maestro radio");
+ v->type = VID_TYPE_TUNER;
+ v->channels = v->audios = 1;
+ return 0;
+ } case VIDIOCGTUNER: {
+ struct video_tuner *v = arg;
+ if (v->tuner)
+ return -EINVAL;
+ (void)radio_bits_get(card);
+ v->flags = VIDEO_TUNER_LOW | card->stereo;
+ v->signal = card->tuned;
+ strcpy(v->name, "FM");
+ v->rangelow = FREQ_LO;
+ v->rangehigh = FREQ_HI;
+ v->mode = VIDEO_MODE_AUTO;
+ return 0;
+ } case VIDIOCSTUNER: {
+ struct video_tuner *v = arg;
+ if (v->tuner != 0)
+ return -EINVAL;
+ return 0;
+ } case VIDIOCGFREQ: {
+ unsigned long *freq = arg;
+ *freq = BITS2FREQ(radio_bits_get(card));
+ return 0;
+ } case VIDIOCSFREQ: {
+ unsigned long *freq = arg;
+ if (*freq < FREQ_LO || *freq > FREQ_HI)
+ return -EINVAL;
+ radio_bits_set(card, FREQ2BITS(*freq));
+ return 0;
+ } case VIDIOCGAUDIO: {
+ struct video_audio *v = arg;
+ memset(v, 0, sizeof(*v));
+ strcpy(v->name, "Radio");
+ v->flags = VIDEO_AUDIO_MUTABLE | card->muted;
+ v->mode = VIDEO_SOUND_STEREO;
+ return 0;
+ } case VIDIOCSAUDIO: {
+ struct video_audio *v = arg;
+ if (v->audio)
+ return -EINVAL;
+ {
+ register u16 io = card->io;
+ register u16 omask = inw(io + IO_MASK);
+ outw(~STR_WREN, io + IO_MASK);
+ outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ?
+ STR_WREN : 0, io);
+ udelay(4);
+ outw(omask, io + IO_MASK);
+ msleep(125);
return 0;
}
- case VIDIOCGAUDIO: {
- struct video_audio *v = arg;
- memset(v,0,sizeof(*v));
- strcpy(v->name, "Radio");
- v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
- v->mode=VIDEO_SOUND_STEREO;
- return 0;
- }
- case VIDIOCSAUDIO: {
- struct video_audio *v = arg;
- if(v->audio)
- return -EINVAL;
- {
- register __u16 io=card->io;
- register __u16 omask = inw(io + IO_MASK);
- outw(~STR_WREN, io + IO_MASK);
- outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
- ? STR_WREN : 0, io);
- udelay(4);
- outw(omask, io + IO_MASK);
- msleep(125);
- return 0;
- }
- }
- case VIDIOCGUNIT: {
- struct video_unit *v = arg;
- v->video=VIDEO_NO_UNIT;
- v->vbi=VIDEO_NO_UNIT;
- v->radio=dev->minor;
- v->audio=0;
- v->teletext=VIDEO_NO_UNIT;
- return 0;
- }
- default: return -ENOIOCTLCMD;
+ } case VIDIOCGUNIT: {
+ struct video_unit *v = arg;
+ v->video = VIDEO_NO_UNIT;
+ v->vbi = VIDEO_NO_UNIT;
+ v->radio = dev->minor;
+ v->audio = 0;
+ v->teletext = VIDEO_NO_UNIT;
+ return 0;
+ } default:
+ return -ENOIOCTLCMD;
}
}
static int radio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_get_drvdata(dev);
int ret;
down(&card->lock);
ret = video_usercopy(inode, file, cmd, arg, radio_function);
up(&card->lock);
- return ret;
-}
-static __u16 radio_install(struct pci_dev *pcidev);
-
-MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
-MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
-MODULE_LICENSE("GPL");
-
-static void __exit maestro_radio_exit(void)
-{
- video_unregister_device(&maestro_radio);
+ return ret;
}
-static int __init maestro_radio_init(void)
+static u16 __devinit radio_power_on(struct radio_device *dev)
{
- register __u16 found=0;
- struct pci_dev *pcidev = NULL;
- while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
- PCI_DEVICE_ID_ESS_ESS1968,
- pcidev)))
- found |= radio_install(pcidev);
- while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
- PCI_DEVICE_ID_ESS_ESS1978,
- pcidev)))
- found |= radio_install(pcidev);
- if(!found) {
- printk(KERN_INFO "radio-maestro: no devices found.\n");
- return -ENODEV;
- }
- return 0;
-}
+ register u16 io = dev->io;
+ register u32 ofreq;
+ u16 omask, odir;
-module_init(maestro_radio_init);
-module_exit(maestro_radio_exit);
-
-static inline __u16 radio_power_on(struct radio_device *dev)
-{
- register __u16 io=dev->io;
- register __u32 ofreq;
- __u16 omask, odir;
omask = inw(io + IO_MASK);
- odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
+ odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
outw(odir & ~STR_WREN, io + IO_DIR);
dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE;
outw(odir, io + IO_DIR);
@@ -298,35 +281,101 @@ static inline __u16 radio_power_on(struct radio_device *dev)
udelay(16);
outw(omask, io + IO_MASK);
ofreq = radio_bits_get(dev);
- if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
+
+ if ((ofreq < FREQ2BITS(FREQ_LO)) || (ofreq > FREQ2BITS(FREQ_HI)))
ofreq = FREQ2BITS(FREQ_LO);
radio_bits_set(dev, ofreq);
+
return (ofreq == radio_bits_get(dev));
}
-static __u16 radio_install(struct pci_dev *pcidev)
+static int __devinit maestro_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
- return 0;
-
- radio_unit.io = pcidev->resource[0].start + GPIO_DATA;
- maestro_radio.priv = &radio_unit;
- init_MUTEX(&radio_unit.lock);
-
- if(radio_power_on(&radio_unit)) {
- if(video_register_device(&maestro_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
- printk("radio-maestro: can't register device!");
- return 0;
- }
- printk(KERN_INFO "radio-maestro: version "
- DRIVER_VERSION
- " time "
- __TIME__ " "
- __DATE__
- "\n");
- printk(KERN_INFO "radio-maestro: radio chip initialized\n");
- return 1;
- } else
- return 0;
+ struct radio_device *radio_unit;
+ struct video_device *maestro_radio_inst;
+ int retval;
+
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ dev_err(&pdev->dev, "enabling pci device failed!\n");
+ goto err;
+ }
+
+ retval = -ENOMEM;
+
+ radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL);
+ if (radio_unit == NULL) {
+ dev_err(&pdev->dev, "not enough memory\n");
+ goto err;
+ }
+
+ radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
+ init_MUTEX(&radio_unit->lock);
+
+ maestro_radio_inst = video_device_alloc();
+ if (maestro_radio_inst == NULL) {
+ dev_err(&pdev->dev, "not enough memory\n");
+ goto errfr;
+ }
+
+ memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio));
+ video_set_drvdata(maestro_radio_inst, radio_unit);
+ pci_set_drvdata(pdev, maestro_radio_inst);
+
+ retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO,
+ radio_nr);
+ if (retval) {
+ printk(KERN_ERR "can't register video device!\n");
+ goto errfr1;
+ }
+
+ if (!radio_power_on(radio_unit)) {
+ retval = -EIO;
+ goto errunr;
+ }
+
+ dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " "
+ __DATE__ "\n");
+ dev_info(&pdev->dev, "radio chip initialized\n");
+
+ return 0;
+errunr:
+ video_unregister_device(maestro_radio_inst);
+errfr1:
+ kfree(maestro_radio_inst);
+errfr:
+ kfree(radio_unit);
+err:
+ return retval;
+
+}
+
+static void __devexit maestro_remove(struct pci_dev *pdev)
+{
+ struct video_device *vdev = pci_get_drvdata(pdev);
+
+ video_unregister_device(vdev);
}
+static int __init maestro_radio_init(void)
+{
+ int retval = pci_register_driver(&maestro_r_driver);
+
+ if (retval)
+ printk(KERN_ERR "error during registration pci driver\n");
+
+ return retval;
+}
+
+static void __exit maestro_radio_exit(void)
+{
+ pci_unregister_driver(&maestro_r_driver);
+}
+
+module_init(maestro_radio_init);
+module_exit(maestro_radio_exit);
+
+MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
+MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 02d39a50d5ed..c975ddd86cd5 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -80,6 +80,7 @@ static struct file_operations maxiradio_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device maxiradio_radio =
@@ -337,7 +338,7 @@ static struct pci_driver maxiradio_driver = {
static int __init maxiradio_radio_init(void)
{
- return pci_module_init(&maxiradio_driver);
+ return pci_register_driver(&maxiradio_driver);
}
static void __exit maxiradio_radio_exit(void)
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index b2256d675b44..28a47c9e7a81 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -199,6 +199,7 @@ static struct file_operations rtrack2_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = rt_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 6f03ce4dd7b0..0229f792a059 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -225,6 +225,7 @@ static struct file_operations fmi_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = fmi_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 71971e9bb342..099ffb3b9c71 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -48,7 +48,7 @@ static int io = 0x384;
static int radio_nr = -1;
/* hw precision is 12.5 kHz
- * It is only usefull to give freq in intervall of 200 (=0.0125Mhz),
+ * It is only useful to give freq in intervall of 200 (=0.0125Mhz),
* other bits will be truncated
*/
#define RSF16_ENCODE(x) ((x)/200+856)
@@ -356,6 +356,7 @@ static struct file_operations fmr2_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = fmr2_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index b03573c6840e..fcfde2e4f195 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -276,6 +276,7 @@ static struct file_operations terratec_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = tt_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index b300bedf7c74..5a099a50d4d0 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -255,6 +255,7 @@ static struct file_operations trust_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = tr_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index f304f3c14763..8ac9a8ef9094 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -261,6 +261,7 @@ static struct file_operations typhoon_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = typhoon_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 4c6d6fb49034..d590e80c922e 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -313,6 +313,7 @@ static struct file_operations zoltrix_fops =
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = zol_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index fc87efc5049c..d82c8a30ba44 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -7,6 +7,15 @@ menu "Video For Linux"
comment "Video Adapters"
+config VIDEO_ADV_DEBUG
+ bool "Enable advanced debug functionality"
+ depends on VIDEO_DEV
+ default n
+ ---help---
+ Say Y here to enable advanced debugging functionality on some
+ V4L devices.
+ In doubt, say N.
+
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C
@@ -174,7 +183,7 @@ config VIDEO_STRADIS
help
Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
driver for PCI. There is a product page at
- <http://www.stradis.com/decoder.html>.
+ <http://www.stradis.com/>.
config VIDEO_ZORAN
tristate "Zoran ZR36057/36067 Video For Linux"
@@ -342,6 +351,6 @@ config VIDEO_DECODER
depends on VIDEO_DEV && I2C && EXPERIMENTAL
---help---
Say Y here to compile drivers for SAA7115, SAA7127 and CX25840
- video decoders.
+ video decoders.
endmenu
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 82060f9909d8..faf728366c4e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -3,15 +3,20 @@
#
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
- bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o
+ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
+ bttv-input.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.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
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
+tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
+ mt20xx.o tda8290.o tea5767.o
+
+msp3400-objs := msp3400-driver.o msp3400-kthreads.o
+
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
- tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o
+ tda7432.o tda9875.o ir-kbd-i2c.o
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index e61003de1d5f..4ce07ae62dac 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -413,10 +413,9 @@ adv7170_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_adv7170;
@@ -433,12 +432,11 @@ adv7170_detect_client (struct i2c_adapter *adapter,
}
strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct adv7170), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct adv7170));
encoder->norm = VIDEO_MODE_NTSC;
encoder->input = 0;
encoder->enable = 1;
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 6d9536a71ee4..4e218f22b214 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -463,10 +463,9 @@ adv7175_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_adv7175;
@@ -483,12 +482,11 @@ adv7175_detect_client (struct i2c_adapter *adapter,
}
strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct adv7175), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct adv7175));
encoder->norm = VIDEO_MODE_PAL;
encoder->input = 0;
encoder->enable = 1;
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 881cdcb1875d..994b75fe165a 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -129,9 +129,9 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES];
static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */
static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */
static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */
-MODULE_PARM(freq, "i");
-MODULE_PARM(vga, "i");
-MODULE_PARM(vga_interlace, "i");
+module_param(freq, int, 0);
+module_param(vga, int, 0);
+module_param(vga_interlace, int, 0);
static int ar_initialize(struct video_device *dev);
@@ -749,6 +749,7 @@ static struct file_operations ar_fops = {
.release = video_exclusive_release,
.read = ar_read,
.ioctl = ar_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 560b99891753..d6447791d0e5 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -528,21 +528,18 @@ bt819_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_bt819;
- decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
-
- memset(decoder, 0, sizeof(struct bt819));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index 1c3ff5f38a6d..cc54b62f4601 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -30,8 +30,9 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
-
#include <media/audiochip.h>
+#include <media/v4l2-common.h>
+
#include "bttv.h"
#include "bt832.h"
@@ -42,9 +43,10 @@ static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
-/* ---------------------------------------------------------------------- */
+int debug; /* debug output */
+module_param(debug, int, 0644);
-#define dprintk if (debug) printk
+/* ---------------------------------------------------------------------- */
static int bt832_detach(struct i2c_client *client);
@@ -61,23 +63,26 @@ int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf)
int i,rc;
buf[0]=0x80; // start at register 0 with auto-increment
if (1 != (rc = i2c_master_send(i2c_client_s,buf,1)))
- printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc);
for(i=0;i<65;i++)
buf[i]=0;
if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65)))
- printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc);
// Note: On READ the first byte is the current index
// (e.g. 0x80, what we just wrote)
- if(1) {
+ if(debug>1) {
int i;
- printk("BT832 hexdump:\n");
+ v4l_dbg(2, debug,i2c_client_s,"hexdump:");
for(i=1;i<65;i++) {
if(i!=1) {
- if(((i-1)%8)==0) printk(" ");
- if(((i-1)%16)==0) printk("\n");
+ if(((i-1)%8)==0) printk(" ");
+ if(((i-1)%16)==0) {
+ printk("\n");
+ v4l_dbg(2, debug,i2c_client_s,"hexdump:");
+ }
}
printk(" %02x",buf[i]);
}
@@ -96,56 +101,56 @@ int bt832_init(struct i2c_client *i2c_client_s)
bt832_hexdump(i2c_client_s,buf);
if(buf[0x40] != 0x31) {
- printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
+ v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
kfree(buf);
return 0;
}
- printk("Write 0 tp VPSTATUS\n");
+ v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n");
buf[0]=BT832_VP_STATUS; // Reg.52
buf[1]= 0x00;
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
// Leave low power mode:
- printk("Bt832: leave low power mode.\n");
+ v4l_err(i2c_client_s,"leave low power mode.\n");
buf[0]=BT832_CAM_SETUP0; //0x39 57
buf[1]=0x08;
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
- printk("Write 0 tp VPSTATUS\n");
+ v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n");
buf[0]=BT832_VP_STATUS; // Reg.52
buf[1]= 0x00;
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
// Enable Output
- printk("Enable Output\n");
+ v4l_info(i2c_client_s,"Enable Output\n");
buf[0]=BT832_VP_CONTROL1; // Reg.40
buf[1]= 0x27 & (~0x01); // Default | !skip
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
// for testing (even works when no camera attached)
- printk("bt832: *** Generate NTSC M Bars *****\n");
+ v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n");
buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42
buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
+ v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
- printk("Bt832: Camera Present: %s\n",
+ v4l_info(i2c_client_s,"Camera Present: %s\n",
(buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no");
bt832_hexdump(i2c_client_s,buf);
@@ -159,20 +164,18 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct bt832 *t;
- printk("bt832_attach\n");
-
client_template.adapter = adap;
client_template.addr = addr;
- printk("bt832: chip found @ 0x%x\n", addr<<1);
-
- if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
+ if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
- memset(t,0,sizeof(*t));
t->client = client_template;
i2c_set_clientdata(&t->client, t);
i2c_attach_client(&t->client);
+ v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1);
+
+
if(! bt832_init(&t->client)) {
bt832_detach(&t->client);
return -1;
@@ -183,13 +186,8 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
static int bt832_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, bt832_attach);
-#else
- if (adap->id == I2C_HW_B_BT848)
- return i2c_probe(adap, &addr_data, bt832_attach);
-#endif
return 0;
}
@@ -197,7 +195,7 @@ static int bt832_detach(struct i2c_client *client)
{
struct bt832 *t = i2c_get_clientdata(client);
- printk("bt832: detach.\n");
+ v4l_info(&t->client,"dettach\n");
i2c_detach_client(client);
kfree(t);
return 0;
@@ -208,7 +206,8 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct bt832 *t = i2c_get_clientdata(client);
- printk("bt832: command %x\n",cmd);
+ if (debug>1)
+ v4l_i2c_print_ioctl(&t->client,cmd);
switch (cmd) {
case BT832_HEXDUMP: {
@@ -219,7 +218,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
break;
case BT832_REATTACH:
- printk("bt832: re-attach\n");
+ v4l_info(&t->client,"re-attach\n");
i2c_del_driver(&driver);
i2c_add_driver(&driver);
break;
@@ -231,9 +230,9 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
static struct i2c_driver driver = {
.driver = {
- .name = "i2c bt832 driver",
+ .name = "bt832",
},
- .id = -1, /* FIXME */
+ .id = 0, /* FIXME */
.attach_adapter = bt832_probe,
.detach_client = bt832_detach,
.command = bt832_command,
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 60508069bbed..909b593530ed 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -316,21 +316,19 @@ bt856_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_bt856;
strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct bt856));
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index a48de3c0e3f0..b4aca7249276 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");
-static unsigned int debug = 0;
+static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 012be639aa18..9749d6ed6231 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -38,6 +38,7 @@
#include <asm/io.h>
#include "bttvp.h"
+#include <media/v4l2-common.h>
/* fwd decl */
static void boot_msp34xx(struct bttv *btv, int pin);
@@ -91,8 +92,8 @@ static void identify_by_eeprom(struct bttv *btv,
static int __devinit pvr_boot(struct bttv *btv);
/* config variables */
-static unsigned int triton1=0;
-static unsigned int vsfx=0;
+static unsigned int triton1;
+static unsigned int vsfx;
static unsigned int latency = UNSET;
int no_overlay=-1;
@@ -105,7 +106,7 @@ static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
#ifdef MODULE
static unsigned int autoload = 1;
#else
-static unsigned int autoload = 0;
+static unsigned int autoload;
#endif
static unsigned int gpiomask = UNSET;
static unsigned int audioall = UNSET;
@@ -292,6 +293,9 @@ static struct CARD {
/* likely broken, vendor id doesn't match the other magic views ...
* { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+ /* Duplicate PCI ID, reconfigure for this board during the eeprom read.
+ * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */
+
/* DVB cards (using pci function .1 for mpeg data xfer) */
{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
@@ -317,7 +321,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -329,8 +333,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0, 0, 0, 10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 0, 10 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -343,8 +347,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -357,8 +361,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 4, 0, 2, 3, 1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 4, 0, 2, 3, 1 },
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
@@ -376,7 +380,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 2,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
@@ -390,8 +394,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 3,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 0, 1, 0, 1, 3},
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0, 1, 0, 1, 3 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -403,9 +407,9 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 3,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.gpiomask = 0x0f,
- .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0},
+ .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0 },
/* 0x04 for some cards ?? */
.needs_tvaudio = 1,
.tuner_type = -1,
@@ -421,8 +425,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 3,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 0, 0},
- .audiomux = {0 },
+ .muxsel = { 2, 3, 1, 0, 0 },
+ .audiomux = { 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -437,8 +441,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xc00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -452,8 +456,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 3,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 1, 1, 2, 3, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 1, 2, 3, 0 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
@@ -467,8 +471,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x0f, /* old: 7 */
- .muxsel = { 2, 0, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 0, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -482,8 +486,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x3014f,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x20001,0x10001, 0, 0,10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x20001,0x10001, 0, 0,10 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -498,8 +502,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 13, 14, 11, 7, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 13, 14, 11, 7, 0, 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -512,8 +516,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 13, 14, 11, 7, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 13, 14, 11, 7, 0, 0 },
.needs_tvaudio = 1,
.msp34xx_alt = 1,
.pll = PLL_28,
@@ -530,8 +534,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 2, 1, 3, 4}, /* old: { 0, 1, 2, 3, 4} */
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 2, 1, 3, 4 }, /* old: {0, 1, 2, 3, 4} */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -545,8 +549,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {0 , 0, 1 , 0, 10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0 , 0, 1 , 0, 10 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -561,7 +565,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x01fe00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
#if 0
/* old */
.audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },
@@ -580,8 +584,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x8300f8,
- .muxsel = { 2, 3, 1, 1,0},
- .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},
+ .muxsel = { 2, 3, 1, 1,0 },
+ .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -596,8 +600,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0,
- .muxsel = {2, 3, 1, 1},
- .audiomux = {1, 0, 0, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 0, 0, 0, 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -610,7 +614,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = -1,
.gpiomask = 0x8dff00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0 },
.no_msp34xx = 1,
.tuner_type = -1,
@@ -625,7 +629,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 3,
.tuner = 0,
.svhs = 2,
- .muxsel = {2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -637,8 +641,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
@@ -651,8 +655,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xc00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {0, 1, 0x800, 0x400, 0xc00, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 0x800, 0x400, 0xc00, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -684,8 +688,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xe00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -700,8 +704,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1f0fff,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000 },
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -715,8 +719,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 3,
.gpiomask = 7,
- .muxsel = { 2, 0, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 0, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -729,8 +733,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_SECAM,
.tuner_addr = ADDR_UNSET,
@@ -745,8 +749,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1f0fff,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000 },
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -808,7 +812,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800, /* 0x8dfe00 */
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
@@ -822,7 +826,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 3,
.gpiomask = 1,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 1, 0, 0, 0, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -838,7 +842,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 2,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
@@ -852,8 +856,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xffff00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x500, 0, 0x300, 0x900, 0x900},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x500, 0, 0x300, 0x900, 0x900 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -866,7 +870,7 @@ struct tvcard bttv_tvcards[] = {
.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 */
#if 0
.gpiomask = 0xc33000,
.audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 },
@@ -902,8 +906,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -918,7 +922,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
@@ -948,7 +952,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x551e00,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -964,8 +968,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x03000F,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0xd0001, 0, 0, 1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0xd0001, 0, 0, 1 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
@@ -981,8 +985,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 4, 0, 2, 3, 1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 4, 0, 2, 3, 1 },
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
@@ -998,8 +1002,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 13, 4, 11, 7, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 13, 4, 11, 7, 0, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1031,8 +1035,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xe00b,
- .muxsel = {2, 3, 1, 1},
- .audiomux = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc },
.no_msp34xx = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -1047,8 +1051,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 3,
- .muxsel = {2, 3, 1, 1},
- .audiomux = {1, 1, 0, 2, 3},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 1, 0, 2, 3 },
.no_msp34xx = 1,
.pll = PLL_NONE,
.tuner_type = -1,
@@ -1062,8 +1066,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 3,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 0, 0},
- .audiomux = {0 },
+ .muxsel = { 2, 3, 1, 0, 0 },
+ .audiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1077,8 +1081,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xbcf03f,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 21,
@@ -1092,7 +1096,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x70000,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 },
.needs_tvaudio = 1,
.no_msp34xx = 1,
@@ -1111,8 +1115,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {2,0,0,0,1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = {2,0,0,0,1 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1126,8 +1130,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x010f00,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0x10000, 0, 0x10000, 0, 0, 0},
+ .muxsel = {2, 3, 0, 0 },
+ .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
@@ -1168,8 +1172,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 0, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 0, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.pll = PLL_28,
.tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */,
.tuner_addr = ADDR_UNSET,
@@ -1185,8 +1189,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 3,
.gpiomask = 0x03000F,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 1, 0xd0001, 0, 0, 10},
+ .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)
0= ext. Audio IN
@@ -1211,7 +1215,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1c,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0, 0x10, 8, 4 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -1232,7 +1236,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x18e0,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
/* For cards with tda9820/tda9821:
0x0000: Tuner normal stereo
@@ -1252,8 +1256,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xF,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 2, 0, 0, 0, 10},
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 2, 0, 0, 0, 10 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
@@ -1270,7 +1274,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = 5,
@@ -1320,8 +1324,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x03000F,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 2,0,0,0,1 },
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 2, 0, 0, 0, 1 },
.pll = PLL_28,
.tuner_type = 0,
.tuner_addr = ADDR_UNSET,
@@ -1337,8 +1341,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 11,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0, 0, 1, 8},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 1, 8 },
.pll = PLL_35,
.tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1352,7 +1356,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 1,
.gpiomask = 0xF,
- .muxsel = { 2, 2},
+ .muxsel = { 2, 2 },
.audiomux = { },
.no_msp34xx = 1,
.needs_tvaudio = 0,
@@ -1371,8 +1375,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xFF,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 1, 0, 4, 4, 9},
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 1, 0, 4, 4, 9 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1388,7 +1392,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xf03f,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe},
+ .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe },
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1404,8 +1408,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 1,
- .muxsel = { 2, 3, 0, 1},
- .audiomux = { 0, 0, 1, 0, 0},
+ .muxsel = { 2, 3, 0, 1 },
+ .audiomux = { 0, 0, 1, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
@@ -1420,7 +1424,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x18e0,
- .muxsel = { 2, 3, 0, 1},
+ .muxsel = { 2, 3, 0, 1 },
/* Radio changed from 1e80 to 0x800 to make
FlyVideo2000S in .hu happy (gm)*/
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
@@ -1441,8 +1445,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xffff00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x500, 0x500, 0x300, 0x900, 0x900},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x500, 0x500, 0x300, 0x900, 0x900 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1458,8 +1462,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x010f00,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0x10000, 0, 0x10000, 0, 0, 0},
+ .muxsel = {2, 3, 0, 0 },
+ .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
@@ -1483,7 +1487,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
/* tvtuner, radio, external,internal, mute, stereo
* tuner, Composit, SVid, Composit-on-Svid-adapter */
- .muxsel = { 2, 3 ,0 ,1},
+ .muxsel = { 2, 3 ,0 ,1 },
.tuner_type = TUNER_MT2032,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1511,8 +1515,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */
+ .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,
@@ -1533,7 +1537,7 @@ struct tvcard bttv_tvcards[] = {
.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,
@@ -1579,7 +1583,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 4,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 0, 0},
+ .muxsel = { 2, 3, 1, 0, 0 },
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = -1,
@@ -1692,7 +1696,7 @@ struct tvcard bttv_tvcards[] = {
.name = "DSP Design TCVIDEO",
.video_inputs = 4,
.svhs = -1,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -1706,7 +1710,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 0, 1, 1},
+ .muxsel = { 2, 0, 1, 1 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1723,7 +1727,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x0f0f80,
- .muxsel = {2, 3, 1, 0},
+ .muxsel = {2, 3, 1, 0 },
.audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0},
.no_msp34xx = 1,
.pll = PLL_28,
@@ -1940,7 +1944,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
- .muxsel = { 3, 0, 1, 2},
+ .muxsel = { 3, 0, 1, 2 },
.pll = PLL_28,
.no_gpioirq = 1,
.has_dvb = 1,
@@ -1953,7 +1957,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 2,
/* TV, Comp1, Composite over SVID con, SVID */
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 2, 2, 0, 0, 0 },
.pll = PLL_28,
.has_radio = 1,
@@ -2070,7 +2074,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */
+ .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */
.gpiomask = 0,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2124,7 +2128,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 1,
.tuner = -1,
.svhs = -1,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2136,7 +2140,6 @@ struct tvcard bttv_tvcards[] = {
.has_remote = 1,
.gpiomask = 0x1b,
.no_gpioirq = 1,
- .any_irq = 1,
},
[BTTV_BOARD_PV143] = {
/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
@@ -2163,7 +2166,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1, /* card has no tuner */
.svhs = 3,
.gpiomask = 0x00,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -2178,7 +2181,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1, /* card has no tuner */
.svhs = 3,
.gpiomask = 0x00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -2265,7 +2268,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = TUNER_PHILIPS_ATSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2288,7 +2291,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0,
.svhs = 1,
.tuner = -1,
- .muxsel = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */
+ .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2304,8 +2307,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 3,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 1, 1, 1, 1, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 1, 1, 1, 0 },
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -2324,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.pll = PLL_28,
- .muxsel = { 2, 2, 2, 2},
+ .muxsel = { 2, 2, 2, 2 },
.gpiomask = 0x3F,
.muxsel_hook = gvc1100_muxsel,
},
@@ -2335,8 +2338,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x008007,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0, 0, 0, 0, 0x000003, 0},
+ .muxsel = { 2, 3, 0, 0 },
+ .audiomux = { 0, 0, 0, 0, 0x000003, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -2371,7 +2374,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.needs_tvaudio = 0,
.gpiomask = 0x68,
- .muxsel = { 2, 3, 1},
+ .muxsel = { 2, 3, 1 },
.audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 },
.pll = PLL_28,
},
@@ -2430,7 +2433,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x0000000f,
.muxsel = { 2, 1, 1 },
- .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00},
+ .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00 },
.tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2463,7 +2466,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.tuner = -1,
.svhs = 1,
- .muxsel = { 3, 1, 2, 0}, /* Comp0, S-Video, ?, ? */
+ .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2520,8 +2523,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 0xFF,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0, 0, 0, 10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 0, 10 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -2554,8 +2557,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x3f,
- .muxsel = {2, 3, 1, 0},
- .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31},
+ .muxsel = {2, 3, 1, 0 },
+ .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
@@ -2573,12 +2576,12 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.gpiomask = 0x008007,
- .audiomux = { 0, 0x000001,0,0, 0},
+ .audiomux = { 0, 0x000001,0,0, 0 },
.needs_tvaudio = 1,
.has_radio = 1,
},
@@ -2669,7 +2672,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2703,7 +2706,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x01fe00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -2791,8 +2794,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {2,0,0,0,1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 0, 1 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 2,
@@ -2807,8 +2810,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x108007,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 100000, 100002, 100002, 100000},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 100000, 100002, 100002, 100000 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2817,6 +2820,45 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.has_radio = 1,
},
+ /* ---- card 0x8f ---------------------------------- */
+ [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
+ .name = "Hauppauge ImpactVCB (bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0x0f, /* old: 7 */
+ .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ },
+ [BTTV_BOARD_MACHTV_MAGICTV] = {
+ /* Julian Calaby <julian.calaby@gmail.com>
+ * Slightly different from original MachTV definition (0x60)
+
+ * FIXME: RegSpy says gpiomask should be "0x001c800f", but it
+ * stuffs up remote chip. Bug is a pin on the jaecs is not set
+ * properly (methinks) causing no keyup bits being set */
+
+ .name = "MagicTV", /* rebranded MachTV */
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 7,
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
+ .tuner_type = TUNER_TEMIC_4009FR5_PAL,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ .has_radio = 1,
+ .has_remote = 1,
+ },
};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3037,26 +3079,33 @@ static void miro_pinnacle_gpio(struct bttv *btv)
switch (id) {
case 1:
info = "PAL / mono";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
case 2:
info = "PAL+SECAM / stereo";
btv->has_radio = 1;
+ btv->tda9887_conf = TDA9887_QSS;
break;
case 3:
info = "NTSC / stereo";
btv->has_radio = 1;
+ btv->tda9887_conf = TDA9887_QSS;
break;
case 4:
info = "PAL+SECAM / mono";
+ btv->tda9887_conf = TDA9887_QSS;
break;
case 5:
info = "NTSC / mono";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
case 6:
info = "NTSC / stereo";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
case 7:
info = "PAL / stereo";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
default:
info = "oops: unknown card";
@@ -3067,8 +3116,7 @@ static void miro_pinnacle_gpio(struct bttv *btv)
printk(KERN_INFO
"bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
- btv->tuner_type = 33;
- btv->pinnacle_id = id;
+ btv->tuner_type = TUNER_MT2032;
}
}
@@ -3370,9 +3418,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
}
- if (btv->pinnacle_id != UNSET) {
- bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE,
- &btv->pinnacle_id);
+ if (btv->tda9887_conf) {
+ bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG,
+ &btv->tda9887_conf);
}
btv->svhs = bttv_tvcards[btv->c.type].svhs;
@@ -3387,8 +3435,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->has_remote=1;
if (!bttv_tvcards[btv->c.type].no_gpioirq)
btv->gpioirq=1;
- if (bttv_tvcards[btv->c.type].any_irq)
- btv->any_irq = 1;
if (bttv_tvcards[btv->c.type].audio_hook)
btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook;
@@ -3424,7 +3470,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
/* tuner modules */
tda9887 = 0;
- if (btv->pinnacle_id != UNSET)
+ if (btv->tda9887_conf)
tda9887 = 1;
if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0)
@@ -3471,6 +3517,21 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
btv->tuner_type = tv.tuner_type;
btv->has_radio = tv.has_radio;
+
+ printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
+ btv->c.nr, tv.model);
+
+ /*
+ * Some of the 878 boards have duplicate PCI IDs. Switch the board
+ * type based on model #.
+ */
+ if(tv.model == 64900) {
+ printk("bttv%d: Switching board type from %s to %s\n",
+ btv->c.nr,
+ bttv_tvcards[btv->c.type].name,
+ bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
+ btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB;
+ }
}
static int terratec_active_radio_upgrade(struct bttv *btv)
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 1ddf9ba613ef..aa4c4c521880 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -34,60 +34,60 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/kdev_t.h>
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/byteorder.h>
-#include "bttvp.h"
-
#include "rds.h"
unsigned int bttv_num; /* number of Bt848s in use */
struct bttv bttvs[BTTV_MAX];
-unsigned int bttv_debug = 0;
+unsigned int bttv_debug;
unsigned int bttv_verbose = 1;
-unsigned int bttv_gpio = 0;
+unsigned int bttv_gpio;
/* config variables */
#ifdef __BIG_ENDIAN
static unsigned int bigendian=1;
#else
-static unsigned int bigendian=0;
+static unsigned int bigendian;
#endif
static unsigned int radio[BTTV_MAX];
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
static unsigned int gbuffers = 8;
static unsigned int gbufsize = 0x208000;
static int video_nr = -1;
static int radio_nr = -1;
static int vbi_nr = -1;
-static int debug_latency = 0;
+static int debug_latency;
-static unsigned int fdsr = 0;
+static unsigned int fdsr;
/* options */
-static unsigned int combfilter = 0;
-static unsigned int lumafilter = 0;
+static unsigned int combfilter;
+static unsigned int lumafilter;
static unsigned int automute = 1;
-static unsigned int chroma_agc = 0;
+static unsigned int chroma_agc;
static unsigned int adc_crush = 1;
static unsigned int whitecrush_upper = 0xCF;
static unsigned int whitecrush_lower = 0x7F;
-static unsigned int vcr_hack = 0;
-static unsigned int irq_iswitch = 0;
+static unsigned int vcr_hack;
+static unsigned int irq_iswitch;
static unsigned int uv_ratio = 50;
-static unsigned int full_luma_range = 0;
-static unsigned int coring = 0;
+static unsigned int full_luma_range;
+static unsigned int coring;
extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
-
/* insmod args */
module_param(bttv_verbose, int, 0644);
module_param(bttv_gpio, int, 0644);
@@ -210,6 +210,9 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x20,
.vbipack = 255,
.sram = 0,
+ /* ITU-R frame line number of the first VBI line
+ we can capture, of the first and second field. */
+ .vbistart = { 7,320 },
},{
.v4l2_id = V4L2_STD_NTSC_M,
.name = "NTSC",
@@ -226,6 +229,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x1a,
.vbipack = 144,
.sram = 1,
+ .vbistart = { 10, 273 },
},{
.v4l2_id = V4L2_STD_SECAM,
.name = "SECAM",
@@ -242,6 +246,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x20,
.vbipack = 255,
.sram = 0, /* like PAL, correct? */
+ .vbistart = { 7, 320 },
},{
.v4l2_id = V4L2_STD_PAL_Nc,
.name = "PAL-Nc",
@@ -258,6 +263,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x1a,
.vbipack = 144,
.sram = -1,
+ .vbistart = { 7, 320 },
},{
.v4l2_id = V4L2_STD_PAL_M,
.name = "PAL-M",
@@ -274,6 +280,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x1a,
.vbipack = 144,
.sram = -1,
+ .vbistart = { 10, 273 },
},{
.v4l2_id = V4L2_STD_PAL_N,
.name = "PAL-N",
@@ -290,6 +297,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x20,
.vbipack = 144,
.sram = -1,
+ .vbistart = { 7, 320},
},{
.v4l2_id = V4L2_STD_NTSC_M_JP,
.name = "NTSC-JP",
@@ -306,6 +314,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x16,
.vbipack = 144,
.sram = -1,
+ .vbistart = {10, 273},
},{
/* that one hopefully works with the strange timing
* which video recorders produce when playing a NTSC
@@ -326,6 +335,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vbipack = 255,
.vtotal = 524,
.sram = -1,
+ .vbistart = { 10, 273 },
}
};
static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
@@ -674,16 +684,16 @@ int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
return 1;
/* is it free? */
- down(&btv->reslock);
+ mutex_lock(&btv->reslock);
if (btv->resources & bit) {
/* no, someone else uses it */
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
return 0;
}
/* it's free, grab it */
fh->resources |= bit;
btv->resources |= bit;
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
return 1;
}
@@ -706,10 +716,10 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
/* trying to free ressources not allocated by us ... */
printk("bttv: BUG! (btres)\n");
}
- down(&btv->reslock);
+ mutex_lock(&btv->reslock);
fh->resources &= ~bits;
btv->resources &= ~bits;
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
}
/* ----------------------------------------------------------------------- */
@@ -1510,14 +1520,6 @@ static struct videobuf_queue_ops bttv_video_qops = {
.buf_release = buffer_release,
};
-static const char *v4l1_ioctls[] = {
- "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
{
switch (cmd) {
@@ -1534,12 +1536,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
case VIDIOCSFREQ:
{
unsigned long *freq = arg;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->freq=*freq;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,*freq);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1569,10 +1571,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (v->mode >= BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_tvnorm(btv,v->mode);
bttv_call_i2c_clients(btv,cmd,v);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1609,17 +1611,17 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (v->norm >= BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
if (channel == btv->input &&
v->norm == btv->tvnorm) {
/* nothing to do */
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
btv->tvnorm = v->norm;
set_input(btv,v->channel);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1632,14 +1634,14 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
v->flags |= VIDEO_AUDIO_MUTABLE;
v->mode = VIDEO_SOUND_MONO;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */
if (btv->audio_hook)
btv->audio_hook(btv,v,0);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOCSAUDIO:
@@ -1650,7 +1652,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (audio >= bttv_tvcards[btv->c.type].audio_inputs)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
bttv_call_i2c_clients(btv,cmd,v);
@@ -1658,7 +1660,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (btv->audio_hook)
btv->audio_hook(btv,v,1);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1692,10 +1694,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (i == BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_tvnorm(btv,i);
i2c_vidiocschan(btv);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_QUERYSTD:
@@ -1753,9 +1755,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (*i > bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_input(btv,*i);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1767,7 +1769,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
memset(t,0,sizeof(*t));
strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
@@ -1802,7 +1804,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
}
/* FIXME: fill capability+audmode */
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_S_TUNER:
@@ -1813,7 +1815,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
{
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
@@ -1830,7 +1832,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (btv->audio_hook)
btv->audio_hook(btv,&va,1);
}
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1851,12 +1853,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->freq = f->frequency;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,btv->freq);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_LOG_STATUS:
@@ -2206,22 +2208,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
unsigned long flags;
int retval = 0;
- if (bttv_debug > 1) {
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
- btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
- btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
- break;
- default:
- printk("bttv%d: ioctl 0x%x (???)\n",
- btv->c.nr, cmd);
- }
- }
+ if (bttv_debug > 1)
+ v4l_print_ioctl(btv->c.name, cmd);
+
if (btv->errors)
bttv_reinit_bt848(btv);
@@ -2570,10 +2559,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
fmt->count[0] = fmt2.fmt.vbi.count[0];
fmt->start[1] = fmt2.fmt.vbi.start[1];
fmt->count[1] = fmt2.fmt.vbi.count[1];
- if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
- fmt->flags |= V4L2_VBI_UNSYNC;
- if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
- fmt->flags |= V4L2_VBI_INTERLACED;
+ if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
+ fmt->flags |= VBI_UNSYNC;
+ if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
+ fmt->flags |= VBI_INTERLACED;
return 0;
}
case VIDIOCSVBIFMT:
@@ -3120,6 +3109,7 @@ static struct file_operations bttv_fops =
.open = bttv_open,
.release = bttv_release,
.ioctl = bttv_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
.read = bttv_read,
.mmap = bttv_mmap,
@@ -3166,7 +3156,7 @@ static int radio_open(struct inode *inode, struct file *file)
return -ENODEV;
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->radio_user++;
@@ -3175,7 +3165,7 @@ static int radio_open(struct inode *inode, struct file *file)
bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
audio_mux(btv,AUDIO_RADIO);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -3229,6 +3219,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCSFREQ:
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
+ case VIDIOC_LOG_STATUS:
return bttv_common_ioctls(btv,cmd,arg);
default:
@@ -3701,8 +3692,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
btv=(struct bttv *)dev_id;
- if (btv->any_irq)
- handled = bttv_any_irq(&btv->c);
+ if (btv->custom_irq)
+ handled = btv->custom_irq(btv);
count=0;
while (1) {
@@ -3738,9 +3729,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
if (astat&BT848_INT_VSYNC)
btv->field_count++;
- if (astat & BT848_INT_GPINT) {
+ if ((astat & BT848_INT_GPINT) && btv->remote) {
wake_up(&btv->gpioq);
- bttv_gpio_irq(&btv->c);
+ bttv_input_irq(btv);
}
if (astat & BT848_INT_I2CDONE) {
@@ -3929,8 +3920,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
sprintf(btv->c.name,"bttv%d",btv->c.nr);
/* initialize structs / fill in defaults */
- init_MUTEX(&btv->lock);
- init_MUTEX(&btv->reslock);
+ mutex_init(&btv->lock);
+ mutex_init(&btv->reslock);
spin_lock_init(&btv->s_lock);
spin_lock_init(&btv->gpio_lock);
init_waitqueue_head(&btv->gpioq);
@@ -3946,7 +3937,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
btv->i2c_rc = -1;
btv->tuner_type = UNSET;
- btv->pinnacle_id = UNSET;
btv->new_input = UNSET;
btv->has_radio=radio[btv->c.nr];
@@ -4065,11 +4055,11 @@ static int __devinit bttv_probe(struct pci_dev *dev,
}
/* add subdevices */
- if (btv->has_remote)
- bttv_sub_add_device(&btv->c, "remote");
if (bttv_tvcards[btv->c.type].has_dvb)
bttv_sub_add_device(&btv->c, "dvb");
+ bttv_input_init(btv);
+
/* everything is fine */
bttv_num++;
return 0;
@@ -4104,6 +4094,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
/* tell gpio modules we are leaving ... */
btv->shutdown=1;
wake_up(&btv->gpioq);
+ bttv_input_fini(btv);
bttv_sub_del_devices(&btv->c);
/* unregister i2c_bus + input */
@@ -4253,7 +4244,7 @@ static int bttv_init_module(void)
bttv_check_chipset();
bus_register(&bttv_sub_bus_type);
- return pci_module_init(&bttv_pci_driver);
+ return pci_register_driver(&bttv_pci_driver);
}
static void bttv_cleanup_module(void)
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index 616a5b7e510c..c4d5e2b70c28 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
+static int bttv_sub_probe(struct device *dev)
+{
+ struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+ struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+ return sub->probe ? sub->probe(sdev) : -ENODEV;
+}
+
+static int bttv_sub_remove(struct device *dev)
+{
+ struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+ struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+ if (sub->remove)
+ sub->remove(sdev);
+ return 0;
+}
+
struct bus_type bttv_sub_bus_type = {
- .name = "bttv-sub",
- .match = &bttv_sub_bus_match,
+ .name = "bttv-sub",
+ .match = &bttv_sub_bus_match,
+ .probe = bttv_sub_probe,
+ .remove = bttv_sub_remove,
};
EXPORT_SYMBOL(bttv_sub_bus_type);
@@ -64,10 +84,9 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
struct bttv_sub_device *sub;
int err;
- sub = kmalloc(sizeof(*sub),GFP_KERNEL);
+ sub = kzalloc(sizeof(*sub),GFP_KERNEL);
if (NULL == sub)
return -ENOMEM;
- memset(sub,0,sizeof(*sub));
sub->core = core;
sub->dev.parent = &core->pci->dev;
@@ -113,24 +132,6 @@ void bttv_gpio_irq(struct bttv_core *core)
}
}
-int bttv_any_irq(struct bttv_core *core)
-{
- struct bttv_sub_driver *drv;
- struct bttv_sub_device *dev;
- struct list_head *item;
- int handled = 0;
-
- list_for_each(item,&core->subs) {
- dev = list_entry(item,struct bttv_sub_device,list);
- drv = to_bttv_sub_drv(dev->dev.driver);
- if (drv && drv->any_irq) {
- if (drv->any_irq(dev))
- handled = 1;
- }
- }
- return handled;
-}
-
/* ----------------------------------------------------------------------- */
/* external: sub-driver register/unregister */
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index d6418c023d39..614c12018557 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -28,10 +28,11 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
static struct i2c_algo_bit_data bttv_i2c_algo_bit_template;
static struct i2c_adapter bttv_i2c_adap_sw_template;
@@ -40,9 +41,9 @@ static struct i2c_client bttv_i2c_client_template;
static int attach_inform(struct i2c_client *client);
-static int i2c_debug = 0;
-static int i2c_hw = 0;
-static int i2c_scan = 0;
+static int i2c_debug;
+static int i2c_hw;
+static int i2c_scan;
module_param(i2c_debug, int, 0644);
module_param(i2c_hw, int, 0444);
module_param(i2c_scan, int, 0444);
@@ -105,10 +106,8 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
static struct i2c_adapter bttv_i2c_adap_sw_template = {
.owner = THIS_MODULE,
-#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
-#endif
- .name = "bt848",
+ .name = "bttv",
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
@@ -275,10 +274,8 @@ static struct i2c_algorithm bttv_algo = {
};
static struct i2c_adapter bttv_i2c_adap_hw_template = {
- .owner = THIS_MODULE,
-#ifdef I2C_CLASS_TV_ANALOG
+ .owner = THIS_MODULE,
.class = I2C_CLASS_TV_ANALOG,
-#endif
.name = "bt878",
.id = I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
@@ -441,12 +438,10 @@ int __devinit init_bttv_i2c(struct bttv *btv)
i2c_set_adapdata(&btv->c.i2c_adap, btv);
btv->i2c_client.adapter = &btv->c.i2c_adap;
-#ifdef I2C_CLASS_TV_ANALOG
if (bttv_tvcards[btv->c.type].no_video)
btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG;
if (bttv_tvcards[btv->c.type].has_dvb)
btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
-#endif
if (btv->use_i2c_hw) {
btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/bttv-input.c
index de1385e5d05e..221b36e7f392 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/bttv-input.c
@@ -24,11 +24,9 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/input.h>
-#include <linux/pci.h>
-
-#include <media/ir-common.h>
#include "bttv.h"
+#include "bttvp.h"
/* ---------------------------------------------------------------------- */
@@ -156,9 +154,6 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
/* ---------------------------------------------------------------------- */
-/* Ricardo Cerqueira <v4l@cerqueira.org> */
-/* Weird matching, since the remote has "uncommon" keys */
-
static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = {
[ 30 ] = KEY_POWER, // power
@@ -279,34 +274,6 @@ static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
[0x36] = KEY_PC
};
-struct IR {
- struct bttv_sub_device *sub;
- struct input_dev *input;
- struct ir_input_state ir;
- char name[32];
- char phys[32];
-
- /* Usual gpio signalling */
-
- u32 mask_keycode;
- u32 mask_keydown;
- u32 mask_keyup;
- u32 polling;
- u32 last_gpio;
- struct work_struct work;
- struct timer_list timer;
-
- /* RC5 gpio */
- u32 rc5_gpio;
- struct timer_list timer_end; /* timer_end for code completion */
- struct timer_list timer_keyup; /* timer_end for key release */
- u32 last_rc5; /* last good rc5 code */
- u32 last_bit; /* last raw bit seen */
- u32 code; /* raw code under construction */
- struct timeval base_time; /* time of last seen code */
- int active; /* building raw code */
-};
-
static int debug;
module_param(debug, int, 0644); /* debug level (0,1,2) */
static int repeat_delay = 500;
@@ -314,31 +281,17 @@ module_param(repeat_delay, int, 0644);
static int repeat_period = 33;
module_param(repeat_period, int, 0644);
-#define DEVNAME "ir-kbd-gpio"
-#define dprintk(fmt, arg...) if (debug) \
- printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
-
-static void ir_irq(struct bttv_sub_device *sub);
-static int ir_probe(struct device *dev);
-static int ir_remove(struct device *dev);
-
-static struct bttv_sub_driver driver = {
- .drv = {
- .name = DEVNAME,
- .probe = ir_probe,
- .remove = ir_remove,
- },
- .gpio_irq = ir_irq,
-};
+#define DEVNAME "bttv-input"
/* ---------------------------------------------------------------------- */
-static void ir_handle_key(struct IR *ir)
+static void ir_handle_key(struct bttv *btv)
{
+ struct bttv_ir *ir = btv->remote;
u32 gpio,data;
/* read gpio value */
- gpio = bttv_gpio_read(ir->sub->core);
+ gpio = bttv_gpio_read(&btv->c);
if (ir->polling) {
if (ir->last_gpio == gpio)
return;
@@ -347,56 +300,36 @@ static void ir_handle_key(struct IR *ir)
/* extract data */
data = ir_extract_bits(gpio, ir->mask_keycode);
- dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
+ dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
gpio, data,
ir->polling ? "poll" : "irq",
(gpio & ir->mask_keydown) ? " down" : "",
(gpio & ir->mask_keyup) ? " up" : "");
- if (ir->mask_keydown) {
- /* bit set on keydown */
- if (gpio & ir->mask_keydown) {
- ir_input_keydown(ir->input, &ir->ir, data, data);
- } else {
- 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);
- } else {
- ir_input_nokey(ir->input, &ir->ir);
- }
-
+ 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);
} else {
- /* can't disturgissh keydown/up :-/ */
- ir_input_keydown(ir->input, &ir->ir, data, data);
- ir_input_nokey(ir->input, &ir->ir);
+ ir_input_nokey(ir->dev,&ir->ir);
}
-}
-static void ir_irq(struct bttv_sub_device *sub)
-{
- struct IR *ir = dev_get_drvdata(&sub->dev);
-
- if (!ir->polling)
- ir_handle_key(ir);
}
-static void ir_timer(unsigned long data)
+void bttv_input_irq(struct bttv *btv)
{
- struct IR *ir = (struct IR*)data;
+ struct bttv_ir *ir = btv->remote;
- schedule_work(&ir->work);
+ if (!ir->polling)
+ ir_handle_key(btv);
}
-static void ir_work(void *data)
+static void bttv_input_timer(unsigned long data)
{
- struct IR *ir = data;
+ struct bttv *btv = (struct bttv*)data;
+ struct bttv_ir *ir = btv->remote;
unsigned long timeout;
- ir_handle_key(ir);
+ ir_handle_key(btv);
timeout = jiffies + (ir->polling * HZ / 1000);
mod_timer(&ir->timer, timeout);
}
@@ -435,26 +368,26 @@ static u32 rc5_decode(unsigned int code)
rc5 |= 1;
break;
case 3:
- dprintk("bad code: %x\n", org_code);
+ dprintk(KERN_WARNING "bad code: %x\n", org_code);
return 0;
}
}
- dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+ dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
"instr=%x\n", rc5, org_code, RC5_START(rc5),
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
return rc5;
}
-static int ir_rc5_irq(struct bttv_sub_device *sub)
+static int bttv_rc5_irq(struct bttv *btv)
{
- struct IR *ir = dev_get_drvdata(&sub->dev);
+ struct bttv_ir *ir = btv->remote;
struct timeval tv;
u32 gpio;
u32 gap;
unsigned long current_jiffies, timeout;
/* read gpio port */
- gpio = bttv_gpio_read(ir->sub->core);
+ gpio = bttv_gpio_read(&btv->c);
/* remote IRQ? */
if (!(gpio & 0x20))
@@ -493,14 +426,15 @@ static int ir_rc5_irq(struct bttv_sub_device *sub)
}
/* toggle GPIO pin 4 to reset the irq */
- bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4));
- bttv_gpio_write(ir->sub->core, gpio | (1 << 4));
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+ bttv_gpio_write(&btv->c, gpio | (1 << 4));
return 1;
}
-static void ir_rc5_timer_end(unsigned long data)
+
+static void bttv_rc5_timer_end(unsigned long data)
{
- struct IR *ir = (struct IR *)data;
+ struct bttv_ir *ir = (struct bttv_ir *)data;
struct timeval tv;
unsigned long current_jiffies, timeout;
u32 gap;
@@ -519,20 +453,20 @@ static void ir_rc5_timer_end(unsigned long data)
/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
if (gap < 28000) {
- dprintk("spurious timer_end\n");
+ dprintk(KERN_WARNING "spurious timer_end\n");
return;
}
ir->active = 0;
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
- dprintk("short code: %x\n", ir->code);
+ dprintk(KERN_WARNING "short code: %x\n", ir->code);
} else {
u32 rc5 = rc5_decode(ir->code);
/* two start bits? */
if (RC5_START(rc5) != 3) {
- dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5));
+ dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5));
/* right address? */
} else if (RC5_ADDR(rc5) == 0x0) {
@@ -542,10 +476,10 @@ static void ir_rc5_timer_end(unsigned long data)
/* Good code, decide if repeat/repress */
if (toggle != RC5_TOGGLE(ir->last_rc5) ||
instr != RC5_INSTR(ir->last_rc5)) {
- dprintk("instruction %x, toggle %x\n", instr,
+ dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr,
toggle);
- ir_input_nokey(ir->input, &ir->ir);
- ir_input_keydown(ir->input, &ir->ir, instr,
+ ir_input_nokey(ir->dev, &ir->ir);
+ ir_input_keydown(ir->dev, &ir->ir, instr,
instr);
}
@@ -560,34 +494,37 @@ static void ir_rc5_timer_end(unsigned long data)
}
}
-static void ir_rc5_timer_keyup(unsigned long data)
+static void bttv_rc5_timer_keyup(unsigned long data)
{
- struct IR *ir = (struct IR *)data;
+ struct bttv_ir *ir = (struct bttv_ir *)data;
- dprintk("key released\n");
- ir_input_nokey(ir->input, &ir->ir);
+ dprintk(KERN_DEBUG "key released\n");
+ ir_input_nokey(ir->dev, &ir->ir);
}
/* ---------------------------------------------------------------------- */
-static int ir_probe(struct device *dev)
+int bttv_input_init(struct bttv *btv)
{
- struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
- struct IR *ir;
- struct input_dev *input_dev;
+ struct bttv_ir *ir;
IR_KEYTAB_TYPE *ir_codes = NULL;
+ struct input_dev *input_dev;
int ir_type = IR_TYPE_OTHER;
- ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ if (!btv->has_remote)
+ return -ENODEV;
+
+ 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) {
+ switch (btv->c.type) {
case BTTV_BOARD_AVERMEDIA:
case BTTV_BOARD_AVPHONE98:
case BTTV_BOARD_AVERMEDIA98:
@@ -643,12 +580,18 @@ static int ir_probe(struct device *dev)
break;
case BTTV_BOARD_NEBULA_DIGITV:
ir_codes = ir_codes_nebula;
- driver.any_irq = ir_rc5_irq;
- driver.gpio_irq = NULL;
+ btv->custom_irq = bttv_rc5_irq;
ir->rc5_gpio = 1;
break;
+ case BTTV_BOARD_MACHTV_MAGICTV:
+ ir_codes = ir_codes_apac_viewcomp;
+ ir->mask_keycode = 0x001F00;
+ ir->mask_keyup = 0x004000;
+ ir->polling = 50; /* ms */
+ break;
}
if (NULL == ir_codes) {
+ dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
kfree(ir);
input_free_device(input_dev);
return -ENODEV;
@@ -657,109 +600,92 @@ static int ir_probe(struct device *dev)
if (ir->rc5_gpio) {
u32 gpio;
/* enable remote irq */
- bttv_gpio_inout(sub->core, (1 << 4), 1 << 4);
- gpio = bttv_gpio_read(sub->core);
- bttv_gpio_write(sub->core, gpio & ~(1 << 4));
- bttv_gpio_write(sub->core, gpio | (1 << 4));
+ bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
+ gpio = bttv_gpio_read(&btv->c);
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+ bttv_gpio_write(&btv->c, gpio | (1 << 4));
} else {
/* init hardware-specific stuff */
- bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0);
+ bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0);
}
/* init input device */
+ ir->dev = input_dev;
+
snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
- sub->core->type);
+ btv->c.type);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
- pci_name(sub->core->pci));
+ pci_name(btv->c.pci));
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) {
- input_dev->id.vendor = sub->core->pci->subsystem_vendor;
- input_dev->id.product = sub->core->pci->subsystem_device;
+ if (btv->c.pci->subsystem_vendor) {
+ input_dev->id.vendor = btv->c.pci->subsystem_vendor;
+ input_dev->id.product = btv->c.pci->subsystem_device;
} else {
- input_dev->id.vendor = sub->core->pci->vendor;
- input_dev->id.product = sub->core->pci->device;
+ input_dev->id.vendor = btv->c.pci->vendor;
+ input_dev->id.product = btv->c.pci->device;
}
- input_dev->cdev.dev = &sub->core->pci->dev;
-
- ir->input = input_dev;
- ir->sub = sub;
+ input_dev->cdev.dev = &btv->c.pci->dev;
+ btv->remote = ir;
if (ir->polling) {
- INIT_WORK(&ir->work, ir_work, ir);
init_timer(&ir->timer);
- ir->timer.function = ir_timer;
- ir->timer.data = (unsigned long)ir;
- schedule_work(&ir->work);
+ ir->timer.function = bttv_input_timer;
+ ir->timer.data = (unsigned long)btv;
+ ir->timer.expires = jiffies + HZ;
+ add_timer(&ir->timer);
} else if (ir->rc5_gpio) {
/* set timer_end for code completion */
init_timer(&ir->timer_end);
- ir->timer_end.function = ir_rc5_timer_end;
+ ir->timer_end.function = bttv_rc5_timer_end;
ir->timer_end.data = (unsigned long)ir;
init_timer(&ir->timer_keyup);
- ir->timer_keyup.function = ir_rc5_timer_keyup;
+ ir->timer_keyup.function = bttv_rc5_timer_keyup;
ir->timer_keyup.data = (unsigned long)ir;
}
/* all done */
- dev_set_drvdata(dev, ir);
- input_register_device(ir->input);
+ input_register_device(btv->remote->dev);
+ printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
/* the remote isn't as bouncy as a keyboard */
- ir->input->rep[REP_DELAY] = repeat_delay;
- ir->input->rep[REP_PERIOD] = repeat_period;
+ ir->dev->rep[REP_DELAY] = repeat_delay;
+ ir->dev->rep[REP_PERIOD] = repeat_period;
return 0;
}
-static int ir_remove(struct device *dev)
+void bttv_input_fini(struct bttv *btv)
{
- struct IR *ir = dev_get_drvdata(dev);
+ if (btv->remote == NULL)
+ return;
- if (ir->polling) {
- del_timer(&ir->timer);
+ if (btv->remote->polling) {
+ del_timer_sync(&btv->remote->timer);
flush_scheduled_work();
}
- if (ir->rc5_gpio) {
+
+ if (btv->remote->rc5_gpio) {
u32 gpio;
- del_timer(&ir->timer_end);
+ del_timer_sync(&btv->remote->timer_end);
flush_scheduled_work();
- gpio = bttv_gpio_read(ir->sub->core);
- bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4));
+ gpio = bttv_gpio_read(&btv->c);
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
}
- input_unregister_device(ir->input);
- kfree(ir);
- return 0;
+ input_unregister_device(btv->remote->dev);
+ kfree(btv->remote);
+ btv->remote = NULL;
}
-/* ---------------------------------------------------------------------- */
-
-MODULE_AUTHOR("Gerd Knorr, Pavel Machek");
-MODULE_DESCRIPTION("input driver for bt8x8 gpio IR remote controls");
-MODULE_LICENSE("GPL");
-
-static int ir_init(void)
-{
- return bttv_sub_register(&driver, "remote");
-}
-
-static void ir_fini(void)
-{
- bttv_sub_unregister(&driver);
-}
-
-module_init(ir_init);
-module_exit(ir_fini);
-
/*
* Local variables:
diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
index f4f58c60f152..72afdd64b882 100644
--- a/drivers/media/video/bttv-vbi.c
+++ b/drivers/media/video/bttv-vbi.c
@@ -31,6 +31,12 @@
#include <asm/io.h>
#include "bttvp.h"
+/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
+ bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
+ HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
+ of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
+#define VBI_OFFSET ((64 + 0) * 2)
+
#define VBI_DEFLINES 16
#define VBI_MAXLINES 32
@@ -163,40 +169,30 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
{
const struct bttv_tvnorm *tvnorm;
- u32 start0,start1;
- s32 count0,count1,count;
+ s64 count0,count1,count;
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
f->fmt.vbi.samples_per_line = 2048;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
- f->fmt.vbi.offset = 244;
+ f->fmt.vbi.offset = VBI_OFFSET;
f->fmt.vbi.flags = 0;
- switch (fh->btv->tvnorm) {
- case 1: /* NTSC */
- start0 = 10;
- start1 = 273;
- break;
- case 0: /* PAL */
- case 2: /* SECAM */
- default:
- start0 = 7;
- start1 = 320;
- }
- count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0;
- count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1;
- count = max(count0,count1);
- if (count > VBI_MAXLINES)
- count = VBI_MAXLINES;
- if (count < 1)
- count = 1;
+ /* s64 to prevent overflow. */
+ count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0]
+ - tvnorm->vbistart[0];
+ count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
+ - tvnorm->vbistart[1];
+ count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
- f->fmt.vbi.start[0] = start0;
- f->fmt.vbi.start[1] = start1;
+ f->fmt.vbi.start[0] = tvnorm->vbistart[0];
+ f->fmt.vbi.start[1] = tvnorm->vbistart[1];
f->fmt.vbi.count[0] = count;
f->fmt.vbi.count[1] = count;
+
+ f->fmt.vbi.reserved[0] = 0;
+ f->fmt.vbi.reserved[1] = 0;
}
void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
@@ -209,21 +205,12 @@ void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
f->fmt.vbi.samples_per_line = 2048;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
- f->fmt.vbi.offset = 244;
+ f->fmt.vbi.offset = VBI_OFFSET;
+ f->fmt.vbi.start[0] = tvnorm->vbistart[0];
+ f->fmt.vbi.start[1] = tvnorm->vbistart[1];
f->fmt.vbi.count[0] = fh->lines;
f->fmt.vbi.count[1] = fh->lines;
f->fmt.vbi.flags = 0;
- switch (fh->btv->tvnorm) {
- case 1: /* NTSC */
- f->fmt.vbi.start[0] = 10;
- f->fmt.vbi.start[1] = 273;
- break;
- case 0: /* PAL */
- case 2: /* SECAM */
- default:
- f->fmt.vbi.start[0] = 7;
- f->fmt.vbi.start[1] = 319;
- }
}
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 93298f06e019..9908c8e0c951 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -16,6 +16,8 @@
#include <linux/videodev.h>
#include <linux/i2c.h>
+#include <media/ir-common.h>
+#include <media/ir-kbd-i2c.h>
/* ---------------------------------------------------------- */
/* exported by bttv-cards.c */
@@ -163,6 +165,8 @@
#define BTTV_BOARD_OSPREY440 0x8c
#define BTTV_BOARD_ASOUND_SKYEYE 0x8d
#define BTTV_BOARD_SABRENT_TVFM 0x8e
+#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f
+#define BTTV_BOARD_MACHTV_MAGICTV 0x90
/* i2c address list */
#define I2C_TSA5522 0xc2
@@ -210,6 +214,34 @@ struct bttv_core {
struct bttv;
+
+struct bttv_ir {
+ struct input_dev *dev;
+ struct ir_input_state ir;
+ char name[32];
+ char phys[32];
+
+ /* Usual gpio signalling */
+
+ u32 mask_keycode;
+ u32 mask_keydown;
+ u32 mask_keyup;
+ u32 polling;
+ u32 last_gpio;
+ struct work_struct work;
+ struct timer_list timer;
+
+ /* RC5 gpio */
+ u32 rc5_gpio;
+ struct timer_list timer_end; /* timer_end for code completion */
+ struct timer_list timer_keyup; /* timer_end for key release */
+ u32 last_rc5; /* last good rc5 code */
+ u32 last_bit; /* last raw bit seen */
+ u32 code; /* raw code under construction */
+ struct timeval base_time; /* time of last seen code */
+ int active; /* building raw code */
+};
+
struct tvcard
{
char *name;
@@ -235,7 +267,6 @@ struct tvcard
unsigned int has_dvb:1;
unsigned int has_remote:1;
unsigned int no_gpioirq:1;
- unsigned int any_irq:1;
/* other settings */
unsigned int pll;
@@ -334,8 +365,9 @@ struct bttv_sub_device {
struct bttv_sub_driver {
struct device_driver drv;
char wanted[BUS_ID_SIZE];
+ int (*probe)(struct bttv_sub_device *sub);
+ void (*remove)(struct bttv_sub_device *sub);
void (*gpio_irq)(struct bttv_sub_device *sub);
- int (*any_irq)(struct bttv_sub_device *sub);
};
#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
@@ -363,6 +395,10 @@ extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
unsigned char b2, int both);
extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
+extern int bttv_input_init(struct bttv *dev);
+extern void bttv_input_fini(struct bttv *dev);
+extern void bttv_input_irq(struct bttv *dev);
+
#endif /* _BTTV_H_ */
/*
* Local variables:
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 1e6a5632c3c7..9cb72f176f7d 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -35,6 +35,7 @@
#include <linux/videodev.h>
#include <linux/pci.h>
#include <linux/input.h>
+#include <linux/mutex.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
@@ -73,6 +74,8 @@
#define UNSET (-1U)
+#define clamp(x, low, high) min (max (low, x), high)
+
/* ---------------------------------------------------------- */
struct bttv_tvnorm {
@@ -88,6 +91,9 @@ struct bttv_tvnorm {
u8 vbipack;
u16 vtotal;
int sram;
+ /* ITU-R frame line number of the first VBI line we can
+ capture, of the first and second field. */
+ u16 vbistart[2];
};
extern const struct bttv_tvnorm bttv_tvnorms[];
@@ -209,7 +215,6 @@ extern struct bus_type bttv_sub_bus_type;
int bttv_sub_add_device(struct bttv_core *core, char *name);
int bttv_sub_del_devices(struct bttv_core *core);
void bttv_gpio_irq(struct bttv_core *core);
-int bttv_any_irq(struct bttv_core *core);
/* ---------------------------------------------------------- */
@@ -270,12 +275,13 @@ struct bttv {
/* card configuration info */
unsigned int cardid; /* pci subsystem id (bt878 based ones) */
unsigned int tuner_type; /* tuner chip type */
- unsigned int pinnacle_id;
+ unsigned int tda9887_conf;
unsigned int svhs;
struct bttv_pll_info pll;
int triton1;
int gpioirq;
- int any_irq;
+ int (*custom_irq)(struct bttv *btv);
+
int use_i2c_hw;
/* old gpio interface */
@@ -300,13 +306,13 @@ struct bttv {
/* infrared remote */
int has_remote;
- struct bttv_input *remote;
+ struct bttv_ir *remote;
/* locking */
spinlock_t s_lock;
- struct semaphore lock;
+ struct mutex lock;
int resources;
- struct semaphore reslock;
+ struct mutex reslock;
#ifdef VIDIOC_G_PRIORITY
struct v4l2_prio_state prio;
#endif
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 0065d0c240d1..6bad93ef969f 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -875,6 +875,7 @@ static struct file_operations qcam_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = qcam_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = qcam_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 75442ec49f35..9976db4f6da8 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -687,6 +687,7 @@ static struct file_operations qcam_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = qcam_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = qcam_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
new file mode 100644
index 000000000000..297c32ab51e3
--- /dev/null
+++ b/drivers/media/video/compat_ioctl32.c
@@ -0,0 +1,879 @@
+/*
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
+ *
+ * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
+ * Copyright (C) 2003 Pavel Machek (pavel@suse.cz)
+ * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * ioctls.
+ */
+
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <media/v4l2-common.h>
+
+#ifdef CONFIG_COMPAT
+
+
+struct video_tuner32 {
+ compat_int_t tuner;
+ char name[32];
+ compat_ulong_t rangelow, rangehigh;
+ u32 flags; /* It is really u32 in videodev.h */
+ u16 mode, signal;
+};
+
+static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
+{
+ if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
+ get_user(kp->tuner, &up->tuner) ||
+ copy_from_user(kp->name, up->name, 32) ||
+ get_user(kp->rangelow, &up->rangelow) ||
+ get_user(kp->rangehigh, &up->rangehigh) ||
+ get_user(kp->flags, &up->flags) ||
+ get_user(kp->mode, &up->mode) ||
+ get_user(kp->signal, &up->signal))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
+ put_user(kp->tuner, &up->tuner) ||
+ copy_to_user(up->name, kp->name, 32) ||
+ put_user(kp->rangelow, &up->rangelow) ||
+ put_user(kp->rangehigh, &up->rangehigh) ||
+ put_user(kp->flags, &up->flags) ||
+ put_user(kp->mode, &up->mode) ||
+ put_user(kp->signal, &up->signal))
+ return -EFAULT;
+ return 0;
+}
+
+struct video_buffer32 {
+ compat_caddr_t base;
+ compat_int_t height, width, depth, bytesperline;
+};
+
+static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
+{
+ u32 tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
+ get_user(tmp, &up->base) ||
+ get_user(kp->height, &up->height) ||
+ get_user(kp->width, &up->width) ||
+ get_user(kp->depth, &up->depth) ||
+ get_user(kp->bytesperline, &up->bytesperline))
+ return -EFAULT;
+
+ /* This is actually a physical address stored
+ * as a void pointer.
+ */
+ kp->base = (void *)(unsigned long) tmp;
+
+ return 0;
+}
+
+static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
+{
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
+ put_user(tmp, &up->base) ||
+ put_user(kp->height, &up->height) ||
+ put_user(kp->width, &up->width) ||
+ put_user(kp->depth, &up->depth) ||
+ put_user(kp->bytesperline, &up->bytesperline))
+ return -EFAULT;
+ return 0;
+}
+
+struct video_clip32 {
+ s32 x, y, width, height; /* Its really s32 in videodev.h */
+ compat_caddr_t next;
+};
+
+struct video_window32 {
+ u32 x, y, width, height, chromakey, flags;
+ compat_caddr_t clips;
+ compat_int_t clipcount;
+};
+
+static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ if (file->f_op->unlocked_ioctl)
+ ret = file->f_op->unlocked_ioctl(file, cmd, arg);
+ else if (file->f_op->ioctl) {
+ lock_kernel();
+ ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
+ unlock_kernel();
+ }
+
+ return ret;
+}
+
+
+/* You get back everything except the clips... */
+static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
+ put_user(kp->x, &up->x) ||
+ put_user(kp->y, &up->y) ||
+ put_user(kp->width, &up->width) ||
+ put_user(kp->height, &up->height) ||
+ put_user(kp->chromakey, &up->chromakey) ||
+ put_user(kp->flags, &up->flags) ||
+ put_user(kp->clipcount, &up->clipcount))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_clip32
+{
+ struct v4l2_rect c;
+ compat_caddr_t next;
+};
+
+struct v4l2_window32
+{
+ struct v4l2_rect w;
+ enum v4l2_field field;
+ __u32 chromakey;
+ compat_caddr_t clips; /* actually struct v4l2_clip32 * */
+ __u32 clipcount;
+ compat_caddr_t bitmap;
+};
+
+static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+ copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+ get_user(kp->field, &up->field) ||
+ get_user(kp->chromakey, &up->chromakey) ||
+ get_user(kp->clipcount, &up->clipcount))
+ return -EFAULT;
+ if (kp->clipcount > 2048)
+ return -EINVAL;
+ if (kp->clipcount) {
+ struct v4l2_clip32 *uclips = compat_ptr(up->clips);
+ struct v4l2_clip *kclips;
+ int n = kp->clipcount;
+
+ kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+ kp->clips = kclips;
+ while (--n >= 0) {
+ if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) ||
+ copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+ kclips->next = n ? kclips + 1 : 0;
+ uclips += 1;
+ kclips += 1;
+ }
+ } else
+ kp->clips = 0;
+ return 0;
+}
+
+static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) ||
+ copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
+ put_user(kp->field, &up->field) ||
+ put_user(kp->chromakey, &up->chromakey) ||
+ put_user(kp->clipcount, &up->clipcount))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_format32
+{
+ enum v4l2_buf_type type;
+ union
+ {
+ struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
+ struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
+ struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
+ __u8 raw_data[200]; // user-defined
+ } fmt;
+};
+
+static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+ get_user(kp->type, &up->type))
+ return -EFAULT;
+ switch (kp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+ default:
+ printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n",
+ kp->type);
+ return -ENXIO;
+ }
+}
+
+static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ put_user(kp->type, &up->type))
+ return -EFAULT;
+ switch (kp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+ default:
+ return -ENXIO;
+ }
+}
+
+static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_standard)))
+ return -EFAULT;
+ return 0;
+
+}
+
+static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_standard)))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_standard32
+{
+ __u32 index;
+ __u32 id[2]; /* __u64 would get the alignment wrong */
+ __u8 name[24];
+ struct v4l2_fract frameperiod; /* Frames, not fields */
+ __u32 framelines;
+ __u32 reserved[4];
+};
+
+static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+{
+ /* other fields are not set by the user, nor used by the driver */
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+ get_user(kp->index, &up->index))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+ put_user(kp->index, &up->index) ||
+ copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
+ copy_to_user(up->name, kp->name, 24) ||
+ copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
+ put_user(kp->framelines, &up->framelines) ||
+ copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
+ return 0;
+
+}
+
+static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_buffer32
+{
+ __u32 index;
+ enum v4l2_buf_type type;
+ __u32 bytesused;
+ __u32 flags;
+ enum v4l2_field field;
+ struct compat_timeval timestamp;
+ struct v4l2_timecode timecode;
+ __u32 sequence;
+
+ /* memory location */
+ enum v4l2_memory memory;
+ union {
+ __u32 offset;
+ compat_long_t userptr;
+ } m;
+ __u32 length;
+ __u32 input;
+ __u32 reserved;
+};
+
+static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+{
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
+ get_user(kp->index, &up->index) ||
+ get_user(kp->type, &up->type) ||
+ get_user(kp->flags, &up->flags) ||
+ get_user(kp->memory, &up->memory) ||
+ get_user(kp->input, &up->input))
+ return -EFAULT;
+ switch(kp->memory) {
+ case V4L2_MEMORY_MMAP:
+ break;
+ case V4L2_MEMORY_USERPTR:
+ {
+ unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
+
+ if(get_user(kp->length, &up->length) ||
+ get_user(kp->m.userptr, &tmp))
+ return -EFAULT;
+ }
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ if(get_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ }
+ return 0;
+}
+
+static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
+ put_user(kp->index, &up->index) ||
+ put_user(kp->type, &up->type) ||
+ put_user(kp->flags, &up->flags) ||
+ put_user(kp->memory, &up->memory) ||
+ put_user(kp->input, &up->input))
+ return -EFAULT;
+ switch(kp->memory) {
+ case V4L2_MEMORY_MMAP:
+ if (put_user(kp->length, &up->length) ||
+ put_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+ if (put_user(kp->length, &up->length) ||
+ put_user(kp->m.userptr, &up->m.userptr))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ if (put_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ }
+ if (put_user(kp->bytesused, &up->bytesused) ||
+ put_user(kp->field, &up->field) ||
+ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+ put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
+ copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
+ put_user(kp->sequence, &up->sequence) ||
+ put_user(kp->reserved, &up->reserved))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_framebuffer32
+{
+ __u32 capability;
+ __u32 flags;
+ compat_caddr_t base;
+ struct v4l2_pix_format fmt;
+};
+
+static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+{
+ u32 tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
+ get_user(tmp, &up->base) ||
+ get_user(kp->capability, &up->capability) ||
+ get_user(kp->flags, &up->flags))
+ return -EFAULT;
+ kp->base = compat_ptr(tmp);
+ get_v4l2_pix_format(&kp->fmt, &up->fmt);
+ return 0;
+}
+
+static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+{
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
+ put_user(tmp, &up->base) ||
+ put_user(kp->capability, &up->capability) ||
+ put_user(kp->flags, &up->flags))
+ return -EFAULT;
+ put_v4l2_pix_format(&kp->fmt, &up->fmt);
+ return 0;
+}
+
+static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_input)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_input)))
+ return -EFAULT;
+ return 0;
+}
+
+#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
+#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
+#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
+#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)
+#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)
+#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
+#define VIDIOCGFREQ32 _IOR('v',14, u32)
+#define VIDIOCSFREQ32 _IOW('v',15, u32)
+
+/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
+#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
+#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32)
+#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32)
+#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32)
+#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
+#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
+/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */
+#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t)
+#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32)
+#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32)
+#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t)
+#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t)
+#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32)
+/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */
+#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control)
+#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t)
+#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t)
+#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32)
+
+enum {
+ MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
+};
+
+static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_window32 __user *up = compat_ptr(arg);
+ struct video_window __user *vw;
+ struct video_clip __user *p;
+ int nclips;
+ u32 n;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
+ return -EFAULT;
+
+ if (get_user(nclips, &up->clipcount))
+ return -EFAULT;
+
+ /* Peculiar interface... */
+ if (nclips < 0)
+ nclips = VIDEO_CLIPMAP_SIZE;
+
+ if (nclips > MaxClips)
+ return -ENOMEM;
+
+ vw = compat_alloc_user_space(sizeof(struct video_window) +
+ nclips * sizeof(struct video_clip));
+
+ p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
+
+ if (get_user(n, &up->x) || put_user(n, &vw->x) ||
+ get_user(n, &up->y) || put_user(n, &vw->y) ||
+ get_user(n, &up->width) || put_user(n, &vw->width) ||
+ get_user(n, &up->height) || put_user(n, &vw->height) ||
+ get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
+ get_user(n, &up->flags) || put_user(n, &vw->flags) ||
+ get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
+ get_user(n, &up->clips) || put_user(p, &vw->clips))
+ return -EFAULT;
+
+ if (nclips) {
+ struct video_clip32 __user *u = compat_ptr(n);
+ int i;
+ if (!u)
+ return -EINVAL;
+ for (i = 0; i < nclips; i++, u++, p++) {
+ s32 v;
+ if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) ||
+ !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) ||
+ get_user(v, &u->x) ||
+ put_user(v, &p->x) ||
+ get_user(v, &u->y) ||
+ put_user(v, &p->y) ||
+ get_user(v, &u->width) ||
+ put_user(v, &p->width) ||
+ get_user(v, &u->height) ||
+ put_user(v, &p->height) ||
+ put_user(NULL, &p->next))
+ return -EFAULT;
+ }
+ }
+
+ return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
+}
+
+static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ union {
+ struct video_tuner vt;
+ struct video_buffer vb;
+ struct video_window vw;
+ struct v4l2_format v2f;
+ struct v4l2_buffer v2b;
+ struct v4l2_framebuffer v2fb;
+ struct v4l2_standard v2s;
+ struct v4l2_input v2i;
+ struct v4l2_tuner v2t;
+ unsigned long vx;
+ } karg;
+ void __user *up = compat_ptr(arg);
+ int compatible_arg = 1;
+ int err = 0;
+ int realcmd = cmd;
+
+ /* First, convert the command. */
+ switch(cmd) {
+ case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
+ case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
+ case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
+ case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
+ case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
+ case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
+ case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+ case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
+ case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
+ case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
+ case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
+ case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
+ case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
+ case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
+ case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
+ case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
+ case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
+ case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;
+ case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;
+ case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break;
+ case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
+ case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
+ case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
+ };
+
+ switch(cmd) {
+ case VIDIOCSTUNER:
+ case VIDIOCGTUNER:
+ err = get_video_tuner32(&karg.vt, up);
+ compatible_arg = 0;
+
+ break;
+
+ case VIDIOCSFBUF:
+ err = get_video_buffer32(&karg.vb, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOCSFREQ:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_OVERLAY:
+ case VIDIOC_STREAMON:
+ case VIDIOC_STREAMOFF:
+ err = get_user(karg.vx, (u32 __user *)up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_S_FBUF:
+ err = get_v4l2_framebuffer32(&karg.v2fb, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ err = get_v4l2_format32(&karg.v2f, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+ err = get_v4l2_buffer32(&karg.v2b, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMSTD:
+ err = get_v4l2_standard(&karg.v2s, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMSTD32:
+ err = get_v4l2_standard32(&karg.v2s, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMINPUT:
+ err = get_v4l2_input(&karg.v2i, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMINPUT32:
+ err = get_v4l2_input32(&karg.v2i, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ err = get_v4l2_tuner(&karg.v2t, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOCGWIN:
+ case VIDIOCGFBUF:
+ case VIDIOCGFREQ:
+ case VIDIOC_G_FBUF:
+ case VIDIOC_G_INPUT:
+ compatible_arg = 0;
+ };
+
+ if(err)
+ goto out;
+
+ if(compatible_arg)
+ err = native_ioctl(file, realcmd, (unsigned long)up);
+ else {
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ err = native_ioctl(file, realcmd, (unsigned long)&karg);
+ set_fs(old_fs);
+ }
+ if(err == 0) {
+ switch(cmd) {
+ case VIDIOCGTUNER:
+ err = put_video_tuner32(&karg.vt, up);
+ break;
+
+ case VIDIOCGWIN:
+ err = put_video_window32(&karg.vw, up);
+ break;
+
+ case VIDIOCGFBUF:
+ err = put_video_buffer32(&karg.vb, up);
+ break;
+
+ case VIDIOC_G_FBUF:
+ err = put_v4l2_framebuffer32(&karg.v2fb, up);
+ break;
+
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ err = put_v4l2_format32(&karg.v2f, up);
+ break;
+
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+ err = put_v4l2_buffer32(&karg.v2b, up);
+ break;
+
+ case VIDIOC_ENUMSTD:
+ err = put_v4l2_standard(&karg.v2s, up);
+ break;
+
+ case VIDIOC_ENUMSTD32:
+ err = put_v4l2_standard32(&karg.v2s, up);
+ break;
+
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ err = put_v4l2_tuner(&karg.v2t, up);
+ break;
+
+ case VIDIOC_ENUMINPUT:
+ err = put_v4l2_input(&karg.v2i, up);
+ break;
+
+ case VIDIOC_ENUMINPUT32:
+ err = put_v4l2_input32(&karg.v2i, up);
+ break;
+
+ case VIDIOCGFREQ:
+ case VIDIOC_G_INPUT:
+ err = put_user(((u32)karg.vx), (u32 __user *)up);
+ break;
+ };
+ }
+out:
+ return err;
+}
+
+long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ if (!file->f_op->ioctl)
+ return ret;
+
+ switch (cmd) {
+ case VIDIOCSWIN32:
+ ret = do_set_window(file, cmd, arg);
+ break;
+ case VIDIOCGTUNER32:
+ case VIDIOCSTUNER32:
+ case VIDIOCGWIN32:
+ case VIDIOCGFBUF32:
+ case VIDIOCSFBUF32:
+ case VIDIOCGFREQ32:
+ case VIDIOCSFREQ32:
+ case VIDIOC_QUERYCAP:
+ case VIDIOC_ENUM_FMT:
+ case VIDIOC_G_FMT32:
+ case VIDIOC_S_FMT32:
+ case VIDIOC_REQBUFS:
+ case VIDIOC_QUERYBUF32:
+ case VIDIOC_G_FBUF32:
+ case VIDIOC_S_FBUF32:
+ case VIDIOC_OVERLAY32:
+ case VIDIOC_QBUF32:
+ case VIDIOC_DQBUF32:
+ case VIDIOC_STREAMON32:
+ case VIDIOC_STREAMOFF32:
+ case VIDIOC_G_PARM:
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_ENUMSTD32:
+ case VIDIOC_ENUMINPUT:
+ case VIDIOC_ENUMINPUT32:
+ case VIDIOC_G_CTRL:
+ case VIDIOC_S_CTRL32:
+ case VIDIOC_QUERYCTRL:
+ case VIDIOC_G_INPUT32:
+ case VIDIOC_S_INPUT32:
+ case VIDIOC_TRY_FMT32:
+ ret = do_video_ioctl(file, cmd, arg);
+ break;
+
+ /* Little v, the video4linux ioctls (conflict?) */
+ case VIDIOCGCAP:
+ case VIDIOCGCHAN:
+ case VIDIOCSCHAN:
+ case VIDIOCGPICT:
+ case VIDIOCSPICT:
+ case VIDIOCCAPTURE:
+ case VIDIOCKEY:
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ case VIDIOCSYNC:
+ case VIDIOCMCAPTURE:
+ case VIDIOCGMBUF:
+ case VIDIOCGUNIT:
+ case VIDIOCGCAPTURE:
+ case VIDIOCSCAPTURE:
+
+ /* BTTV specific... */
+ case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
+ case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
+ case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
+ case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
+ ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+ break;
+ default:
+ v4l_print_ioctl("compat_ioctl32", cmd);
+ }
+ return ret;
+}
+#else
+long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+#endif
+EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index b7ec9bf45085..9f59541155d9 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3807,6 +3807,7 @@ static struct file_operations cpia_fops = {
.read = cpia_read,
.mmap = cpia_mmap,
.ioctl = cpia_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index 6861d408f1b3..74cff626e044 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -702,12 +702,11 @@ static int cpia_pp_register(struct parport *port)
return -ENXIO;
}
- cam = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
+ cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
if (cam == NULL) {
LOG("failed to allocate camera structure\n");
return -ENOMEM;
}
- memset(cam,0,sizeof(struct pp_cam_entry));
pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
NULL, 0, cam);
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 1439cb752874..03275c37c5d3 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -499,14 +499,12 @@ static int cpia_probe(struct usb_interface *intf,
printk(KERN_INFO "USB CPiA camera found\n");
- ucpia = kmalloc(sizeof(*ucpia), GFP_KERNEL);
+ ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL);
if (!ucpia) {
printk(KERN_ERR "couldn't kmalloc cpia struct\n");
return -ENOMEM;
}
- memset(ucpia, 0, sizeof(*ucpia));
-
ucpia->dev = udev;
ucpia->iface = interface->desc.bInterfaceNumber;
init_waitqueue_head(&ucpia->wq_stream);
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index 643ead1a87ee..8739c64785ef 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -27,7 +27,7 @@
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
MODULE_AUTHOR("Martin Vaughan");
@@ -39,21 +39,6 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
-#define cs53l32a_dbg(fmt, arg...) \
- do { \
- if (debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define cs53l32a_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define cs53l32a_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
@@ -74,50 +59,59 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg)
static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
- int *input = arg;
+ struct v4l2_audio *input = arg;
+ struct v4l2_control *ctrl = arg;
switch (cmd) {
- case AUDC_SET_INPUT:
- switch (*input) {
- case AUDIO_TUNER:
- cs53l32a_write(client, 0x01, 0x01);
- break;
- case AUDIO_EXTERN:
- cs53l32a_write(client, 0x01, 0x21);
- break;
- case AUDIO_MUTE:
- cs53l32a_write(client, 0x03, 0xF0);
- break;
- case AUDIO_UNMUTE:
- cs53l32a_write(client, 0x03, 0x30);
- break;
- default:
- cs53l32a_err("Invalid input %d.\n", *input);
+ case VIDIOC_S_AUDIO:
+ /* There are 2 physical inputs, but the second input can be
+ placed in two modes, the first mode bypasses the PGA (gain),
+ the second goes through the PGA. Hence there are three
+ possible inputs to choose from. */
+ if (input->index > 2) {
+ v4l_err(client, "Invalid input %d.\n", input->index);
return -EINVAL;
}
+ cs53l32a_write(client, 0x01, 0x01 + (input->index << 4));
+ break;
+
+ case VIDIOC_G_AUDIO:
+ memset(input, 0, sizeof(*input));
+ input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
+ break;
+
+ case VIDIOC_G_CTRL:
+ if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
+ ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0;
+ break;
+ }
+ if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
+ return -EINVAL;
+ ctrl->value = (s8)cs53l32a_read(client, 0x04);
break;
case VIDIOC_S_CTRL:
- {
- struct v4l2_control *ctrl = arg;
-
- if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
- return -EINVAL;
- if (ctrl->value > 12 || ctrl->value < -90)
- return -EINVAL;
- cs53l32a_write(client, 0x04, (u8) ctrl->value);
- cs53l32a_write(client, 0x05, (u8) ctrl->value);
+ if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
+ cs53l32a_write(client, 0x03, ctrl->value ? 0xf0 : 0x30);
break;
}
+ if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
+ return -EINVAL;
+ if (ctrl->value > 12 || ctrl->value < -96)
+ return -EINVAL;
+ cs53l32a_write(client, 0x04, (u8) ctrl->value);
+ cs53l32a_write(client, 0x05, (u8) ctrl->value);
+ break;
case VIDIOC_LOG_STATUS:
{
u8 v = cs53l32a_read(client, 0x01);
u8 m = cs53l32a_read(client, 0x03);
+ s8 vol = cs53l32a_read(client, 0x04);
- cs53l32a_info("Input: %s%s\n",
- v == 0x21 ? "external line in" : "tuner",
+ v4l_info(client, "Input: %d%s\n", (v >> 4) & 3,
(m & 0xC0) ? " (muted)" : "");
+ v4l_info(client, "Volume: %d dB\n", vol);
break;
}
@@ -147,22 +141,21 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver;
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
- cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
for (i = 1; i <= 7; i++) {
u8 v = cs53l32a_read(client, i);
- cs53l32a_dbg("Read Reg %d %02x\n", i, v);
+ v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v);
}
/* Set cs53l32a internal register for Adaptec 2010/2410 setup */
@@ -180,7 +173,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
for (i = 1; i <= 7; i++) {
u8 v = cs53l32a_read(client, i);
- cs53l32a_dbg("Read Reg %d %02x\n", i, v);
+ v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v);
}
i2c_attach_client(client);
@@ -190,11 +183,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
static int cs53l32a_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, cs53l32a_attach);
return 0;
}
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 740908f8027d..cb9a7981e408 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -23,11 +23,13 @@
#include "cx25840.h"
-inline static int set_audclk_freq(struct i2c_client *client,
- enum v4l2_audio_clock_freq freq)
+static int set_audclk_freq(struct i2c_client *client, u32 freq)
{
struct cx25840_state *state = i2c_get_clientdata(client);
+ if (freq != 32000 && freq != 44100 && freq != 48000)
+ return -EINVAL;
+
/* assert soft reset */
cx25840_and_or(client, 0x810, ~0x1, 0x01);
@@ -35,10 +37,9 @@ inline static int set_audclk_freq(struct i2c_client *client,
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
cx25840_write(client, 0x127, 0x50);
- switch (state->audio_input) {
- case AUDIO_TUNER:
+ if (state->aud_input != CX25840_AUDIO_SERIAL) {
switch (freq) {
- case V4L2_AUDCLK_32_KHZ:
+ case 32000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040610);
@@ -51,7 +52,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x7ff70108);
break;
- case V4L2_AUDCLK_441_KHZ:
+ case 44100:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040910);
@@ -64,7 +65,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x596d0108);
break;
- case V4L2_AUDCLK_48_KHZ:
+ case 48000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040a10);
@@ -77,14 +78,9 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0xaa4f0108);
break;
}
- break;
-
- case AUDIO_EXTERN_1:
- case AUDIO_EXTERN_2:
- case AUDIO_INTERN:
- case AUDIO_RADIO:
+ } else {
switch (freq) {
- case V4L2_AUDCLK_32_KHZ:
+ case 32000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f04081e);
@@ -103,7 +99,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write(client, 0x127, 0x54);
break;
- case V4L2_AUDCLK_441_KHZ:
+ case 44100:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040918);
@@ -119,7 +115,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x85730108);
break;
- case V4L2_AUDCLK_48_KHZ:
+ case 48000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040a18);
@@ -135,7 +131,6 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x55550108);
break;
}
- break;
}
/* deassert soft reset */
@@ -146,51 +141,36 @@ inline static int set_audclk_freq(struct i2c_client *client,
return 0;
}
-static int set_input(struct i2c_client *client, int audio_input)
+void cx25840_audio_set_path(struct i2c_client *client)
{
struct cx25840_state *state = i2c_get_clientdata(client);
- cx25840_dbg("set audio input (%d)\n", audio_input);
-
/* stop microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0);
/* Mute everything to prevent the PFFT! */
cx25840_write(client, 0x8d3, 0x1f);
- switch (audio_input) {
- case AUDIO_TUNER:
- /* Set Path1 to Analog Demod Main Channel */
- cx25840_write4(client, 0x8d0, 0x7038061f);
-
- /* When the microcontroller detects the
- * audio format, it will unmute the lines */
- cx25840_and_or(client, 0x803, ~0x10, 0x10);
- break;
-
- case AUDIO_EXTERN_1:
- case AUDIO_EXTERN_2:
- case AUDIO_INTERN:
- case AUDIO_RADIO:
+ if (state->aud_input == CX25840_AUDIO_SERIAL) {
/* Set Path1 to Serial Audio Input */
cx25840_write4(client, 0x8d0, 0x12100101);
/* The microcontroller should not be started for the
* non-tuner inputs: autodetection is specific for
* TV audio. */
- break;
+ } else {
+ /* Set Path1 to Analog Demod Main Channel */
+ cx25840_write4(client, 0x8d0, 0x7038061f);
- default:
- cx25840_dbg("Invalid audio input selection %d\n", audio_input);
- return -EINVAL;
+ /* When the microcontroller detects the
+ * audio format, it will unmute the lines */
+ cx25840_and_or(client, 0x803, ~0x10, 0x10);
}
- state->audio_input = audio_input;
-
- return set_audclk_freq(client, state->audclk_freq);
+ set_audclk_freq(client, state->audclk_freq);
}
-inline static int get_volume(struct i2c_client *client)
+static int get_volume(struct i2c_client *client)
{
/* Volume runs +18dB to -96dB in 1/2dB steps
* change to fit the msp3400 -114dB to +12dB range */
@@ -201,7 +181,7 @@ inline static int get_volume(struct i2c_client *client)
return vol << 9;
}
-inline static void set_volume(struct i2c_client *client, int volume)
+static void set_volume(struct i2c_client *client, int volume)
{
/* First convert the volume to msp3400 values (0-127) */
int vol = volume >> 9;
@@ -218,7 +198,7 @@ inline static void set_volume(struct i2c_client *client, int volume)
cx25840_write(client, 0x8d4, 228 - (vol * 2));
}
-inline static int get_bass(struct i2c_client *client)
+static int get_bass(struct i2c_client *client)
{
/* bass is 49 steps +12dB to -12dB */
@@ -228,13 +208,13 @@ inline static int get_bass(struct i2c_client *client)
return bass;
}
-inline static void set_bass(struct i2c_client *client, int bass)
+static void set_bass(struct i2c_client *client, int bass)
{
/* PATH1_EQ_BASS_VOL */
cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
}
-inline static int get_treble(struct i2c_client *client)
+static int get_treble(struct i2c_client *client)
{
/* treble is 49 steps +12dB to -12dB */
@@ -244,13 +224,13 @@ inline static int get_treble(struct i2c_client *client)
return treble;
}
-inline static void set_treble(struct i2c_client *client, int treble)
+static void set_treble(struct i2c_client *client, int treble)
{
/* PATH1_EQ_TREBLE_VOL */
cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
}
-inline static int get_balance(struct i2c_client *client)
+static int get_balance(struct i2c_client *client)
{
/* balance is 7 bit, 0 to -96dB */
@@ -264,7 +244,7 @@ inline static int get_balance(struct i2c_client *client)
return balance << 8;
}
-inline static void set_balance(struct i2c_client *client, int balance)
+static void set_balance(struct i2c_client *client, int balance)
{
int bal = balance >> 8;
if (bal > 0x80) {
@@ -280,17 +260,17 @@ inline static void set_balance(struct i2c_client *client, int balance)
}
}
-inline static int get_mute(struct i2c_client *client)
+static int get_mute(struct i2c_client *client)
{
/* check SRC1_MUTE_EN */
return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0;
}
-inline static void set_mute(struct i2c_client *client, int mute)
+static void set_mute(struct i2c_client *client, int mute)
{
struct cx25840_state *state = i2c_get_clientdata(client);
- if (state->audio_input == AUDIO_TUNER) {
+ if (state->aud_input != CX25840_AUDIO_SERIAL) {
/* Must turn off microcontroller in order to mute sound.
* Not sure if this is the best method, but it does work.
* If the microcontroller is running, then it will undo any
@@ -314,10 +294,9 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
struct v4l2_control *ctrl = arg;
switch (cmd) {
- case AUDC_SET_INPUT:
- return set_input(client, *(int *)arg);
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
- return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg);
+ return set_audclk_freq(client, *(u32 *)arg);
+
case VIDIOC_G_CTRL:
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
@@ -339,6 +318,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
return -EINVAL;
}
break;
+
case VIDIOC_S_CTRL:
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
@@ -360,6 +340,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
return -EINVAL;
}
break;
+
default:
return -EINVAL;
}
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 3b09f46dddf6..c66c2c1f4809 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -43,11 +43,11 @@ MODULE_LICENSE("GPL");
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
-int cx25840_debug = 0;
+static int cx25840_debug;
-module_param(cx25840_debug, bool, 0644);
+module_param_named(debug,cx25840_debug, int, 0644);
-MODULE_PARM_DESC(cx25840_debug, "Debugging messages [0=Off (default) 1=On]");
+MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
I2C_CLIENT_INSMOD;
@@ -115,13 +115,13 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
/* ----------------------------------------------------------------------- */
-static int set_input(struct i2c_client *, enum cx25840_input);
-static void input_change(struct i2c_client *);
+static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
+ enum cx25840_audio_input aud_input);
static void log_status(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
-static inline void init_dll1(struct i2c_client *client)
+static void init_dll1(struct i2c_client *client)
{
/* This is the Hauppauge sequence used to
* initialize the Delay Lock Loop 1 (ADC DLL). */
@@ -135,7 +135,7 @@ static inline void init_dll1(struct i2c_client *client)
cx25840_write(client, 0x15b, 0x10);
}
-static inline void init_dll2(struct i2c_client *client)
+static void init_dll2(struct i2c_client *client)
{
/* This is the Hauppauge sequence used to
* initialize the Delay Lock Loop 2 (ADC DLL). */
@@ -195,10 +195,8 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
/* AC97 shift */
cx25840_write(client, 0x8cf, 0x0f);
- /* (re)set video input */
- set_input(client, state->input);
- /* (re)set audio input */
- cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input);
+ /* (re)set input */
+ set_input(client, state->vid_input, state->aud_input);
/* start microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0x10);
@@ -223,7 +221,7 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_NTSC) {
/* NTSC */
- if (state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
+ if (state->pvr150_workaround) {
/* Certain Hauppauge PVR150 models have a hardware bug
that causes audio to drop out. For these models the
audio standard must be set explicitly.
@@ -259,72 +257,68 @@ static void input_change(struct i2c_client *client)
}
}
-static int set_input(struct i2c_client *client, enum cx25840_input input)
+static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
+ enum cx25840_audio_input aud_input)
{
struct cx25840_state *state = i2c_get_clientdata(client);
+ u8 is_composite = (vid_input >= CX25840_COMPOSITE1 &&
+ vid_input <= CX25840_COMPOSITE8);
+ u8 reg;
- cx25840_dbg("decoder set input (%d)\n", input);
+ v4l_dbg(1, cx25840_debug, client, "decoder set video input %d, audio input %d\n",
+ vid_input, aud_input);
- switch (input) {
- case CX25840_TUNER:
- cx25840_dbg("now setting Tuner input\n");
-
- if (state->cardtype == CARDTYPE_PVR150 ||
- state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
- /* CH_SEL_ADC2=1 */
- cx25840_and_or(client, 0x102, ~0x2, 0x02);
- }
-
- /* Video Input Control */
- if (state->cardtype == CARDTYPE_PG600) {
- cx25840_write(client, 0x103, 0x11);
- } else {
- cx25840_write(client, 0x103, 0x46);
- }
-
- /* INPUT_MODE=0 */
- cx25840_and_or(client, 0x401, ~0x6, 0x00);
- break;
-
- case CX25840_COMPOSITE0:
- case CX25840_COMPOSITE1:
- cx25840_dbg("now setting Composite input\n");
+ if (is_composite) {
+ reg = 0xf0 + (vid_input - CX25840_COMPOSITE1);
+ } else {
+ int luma = vid_input & 0xf0;
+ int chroma = vid_input & 0xf00;
- /* Video Input Control */
- if (state->cardtype == CARDTYPE_PG600) {
- cx25840_write(client, 0x103, 0x00);
- } else {
- cx25840_write(client, 0x103, 0x02);
+ if ((vid_input & ~0xff0) ||
+ luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 ||
+ chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
+ v4l_err(client, "0x%04x is not a valid video input!\n", vid_input);
+ return -EINVAL;
}
-
- /* INPUT_MODE=0 */
- cx25840_and_or(client, 0x401, ~0x6, 0x00);
- break;
-
- case CX25840_SVIDEO0:
- case CX25840_SVIDEO1:
- cx25840_dbg("now setting S-Video input\n");
-
- /* CH_SEL_ADC2=0 */
- cx25840_and_or(client, 0x102, ~0x2, 0x00);
-
- /* Video Input Control */
- if (state->cardtype == CARDTYPE_PG600) {
- cx25840_write(client, 0x103, 0x02);
+ reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4);
+ if (chroma >= CX25840_SVIDEO_CHROMA7) {
+ reg &= 0x3f;
+ reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2;
} else {
- cx25840_write(client, 0x103, 0x10);
+ reg &= 0xcf;
+ reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4;
}
+ }
- /* INPUT_MODE=1 */
- cx25840_and_or(client, 0x401, ~0x6, 0x02);
+ switch (aud_input) {
+ case CX25840_AUDIO_SERIAL:
+ /* do nothing, use serial audio input */
break;
+ case CX25840_AUDIO4: reg &= ~0x30; break;
+ case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
+ case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
+ case CX25840_AUDIO7: reg &= ~0xc0; break;
+ case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
default:
- cx25840_err("%d is not a valid input!\n", input);
+ v4l_err(client, "0x%04x is not a valid audio input!\n", aud_input);
return -EINVAL;
}
- state->input = input;
+ cx25840_write(client, 0x103, reg);
+ /* Set INPUT_MODE to Composite (0) or S-Video (1) */
+ cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
+ /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+ cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+ /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+ if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
+ cx25840_and_or(client, 0x102, ~0x4, 4);
+ else
+ cx25840_and_or(client, 0x102, ~0x4, 0);
+
+ state->vid_input = vid_input;
+ state->aud_input = aud_input;
+ cx25840_audio_set_path(client);
input_change(client);
return 0;
}
@@ -395,23 +389,14 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
struct cx25840_state *state = i2c_get_clientdata(client);
switch (ctrl->id) {
- case CX25840_CID_CARDTYPE:
- switch (ctrl->value) {
- case CARDTYPE_PVR150:
- case CARDTYPE_PVR150_WORKAROUND:
- case CARDTYPE_PG600:
- state->cardtype = ctrl->value;
- break;
- default:
- return -ERANGE;
- }
-
- set_input(client, state->input);
+ case CX25840_CID_ENABLE_PVR150_WORKAROUND:
+ state->pvr150_workaround = ctrl->value;
+ set_input(client, state->vid_input, state->aud_input);
break;
case V4L2_CID_BRIGHTNESS:
if (ctrl->value < 0 || ctrl->value > 255) {
- cx25840_err("invalid brightness setting %d\n",
+ v4l_err(client, "invalid brightness setting %d\n",
ctrl->value);
return -ERANGE;
}
@@ -421,7 +406,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_CONTRAST:
if (ctrl->value < 0 || ctrl->value > 127) {
- cx25840_err("invalid contrast setting %d\n",
+ v4l_err(client, "invalid contrast setting %d\n",
ctrl->value);
return -ERANGE;
}
@@ -431,7 +416,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_SATURATION:
if (ctrl->value < 0 || ctrl->value > 127) {
- cx25840_err("invalid saturation setting %d\n",
+ v4l_err(client, "invalid saturation setting %d\n",
ctrl->value);
return -ERANGE;
}
@@ -442,7 +427,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_HUE:
if (ctrl->value < -127 || ctrl->value > 127) {
- cx25840_err("invalid hue setting %d\n", ctrl->value);
+ v4l_err(client, "invalid hue setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -455,6 +440,9 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_MUTE:
return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -465,11 +453,11 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
struct cx25840_state *state = i2c_get_clientdata(client);
switch (ctrl->id) {
- case CX25840_CID_CARDTYPE:
- ctrl->value = state->cardtype;
+ case CX25840_CID_ENABLE_PVR150_WORKAROUND:
+ ctrl->value = state->pvr150_workaround;
break;
case V4L2_CID_BRIGHTNESS:
- ctrl->value = cx25840_read(client, 0x414) + 128;
+ ctrl->value = (s8)cx25840_read(client, 0x414) + 128;
break;
case V4L2_CID_CONTRAST:
ctrl->value = cx25840_read(client, 0x415) >> 1;
@@ -478,7 +466,7 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
ctrl->value = cx25840_read(client, 0x420) >> 1;
break;
case V4L2_CID_HUE:
- ctrl->value = cx25840_read(client, 0x422);
+ ctrl->value = (s8)cx25840_read(client, 0x422);
break;
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BASS:
@@ -527,7 +515,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
- cx25840_err("%dx%d is not a valid size!\n",
+ v4l_err(client, "%dx%d is not a valid size!\n",
pix->width, pix->height);
return -ERANGE;
}
@@ -545,7 +533,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
else
filter = 3;
- cx25840_dbg("decoder set size %dx%d -> scale %ux%u\n",
+ v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
pix->width, pix->height, HSC, VSC);
/* HSCALE=HSC */
@@ -574,17 +562,98 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
/* ----------------------------------------------------------------------- */
+static struct v4l2_queryctrl cx25840_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 128,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 58880,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_BASS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Bass",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ }, {
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Treble",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ },
+};
+
+/* ----------------------------------------------------------------------- */
+
static int cx25840_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
struct cx25840_state *state = i2c_get_clientdata(client);
struct v4l2_tuner *vt = arg;
- int result = 0;
switch (cmd) {
- case 0:
- break;
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct access to the
* cx25840 registers for testing */
@@ -615,18 +684,16 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
return cx25840_vbi(client, cmd, arg);
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
- case AUDC_SET_INPUT:
- result = cx25840_audio(client, cmd, arg);
- break;
+ return cx25840_audio(client, cmd, arg);
case VIDIOC_STREAMON:
- cx25840_dbg("enable output\n");
+ v4l_dbg(1, cx25840_debug, client, "enable output\n");
cx25840_write(client, 0x115, 0x8c);
cx25840_write(client, 0x116, 0x07);
break;
case VIDIOC_STREAMOFF:
- cx25840_dbg("disable output\n");
+ v4l_dbg(1, cx25840_debug, client, "disable output\n");
cx25840_write(client, 0x115, 0x00);
cx25840_write(client, 0x116, 0x00);
break;
@@ -636,28 +703,58 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
case VIDIOC_G_CTRL:
- result = get_v4lctrl(client, (struct v4l2_control *)arg);
- break;
+ return get_v4lctrl(client, (struct v4l2_control *)arg);
case VIDIOC_S_CTRL:
- result = set_v4lctrl(client, (struct v4l2_control *)arg);
- break;
+ return set_v4lctrl(client, (struct v4l2_control *)arg);
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++)
+ if (qc->id && qc->id == cx25840_qctrl[i].id) {
+ memcpy(qc, &cx25840_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
case VIDIOC_G_STD:
*(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
break;
case VIDIOC_S_STD:
- result = set_v4lstd(client, *(v4l2_std_id *)arg);
+ state->radio = 0;
+ return set_v4lstd(client, *(v4l2_std_id *)arg);
+
+ case AUDC_SET_RADIO:
+ state->radio = 1;
break;
case VIDIOC_G_INPUT:
- *(int *)arg = state->input;
+ *(int *)arg = state->vid_input;
break;
case VIDIOC_S_INPUT:
- result = set_input(client, *(int *)arg);
+ return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);
+
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *input = arg;
+
+ return set_input(client, state->vid_input, input->index);
+ }
+
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *input = arg;
+
+ memset(input, 0, sizeof(*input));
+ input->index = state->aud_input;
break;
+ }
case VIDIOC_S_FREQUENCY:
input_change(client);
@@ -670,6 +767,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
u8 vpres = cx25840_read(client, 0x80a) & 0x10;
int val = 0;
+ if (state->radio)
+ break;
+
vt->capability |=
V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
@@ -724,12 +824,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
case VIDIOC_G_FMT:
- result = get_v4lfmt(client, (struct v4l2_format *)arg);
- break;
+ return get_v4lfmt(client, (struct v4l2_format *)arg);
case VIDIOC_S_FMT:
- result = set_v4lfmt(client, (struct v4l2_format *)arg);
- break;
+ return set_v4lfmt(client, (struct v4l2_format *)arg);
case VIDIOC_INT_RESET:
cx25840_initialize(client, 0);
@@ -741,11 +839,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
default:
- cx25840_err("invalid ioctl %x\n", cmd);
return -EINVAL;
}
- return result;
+ return 0;
}
/* ----------------------------------------------------------------------- */
@@ -765,17 +862,16 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_cx25840;
snprintf(client->name, sizeof(client->name) - 1, "cx25840");
- cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", address << 1);
device_id = cx25840_read(client, 0x101) << 8;
device_id |= cx25840_read(client, 0x100);
@@ -783,12 +879,12 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
/* The high byte of the device ID should be
* 0x84 if chip is present */
if ((device_id & 0xff00) != 0x8400) {
- cx25840_dbg("cx25840 not found\n");
+ v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
kfree(client);
return 0;
}
- cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n",
+ v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
(device_id & 0xfff0) >> 4,
(device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
address << 1, adapter->name);
@@ -801,10 +897,10 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
i2c_set_clientdata(client, state);
memset(state, 0, sizeof(struct cx25840_state));
- state->input = CX25840_TUNER;
- state->audclk_freq = V4L2_AUDCLK_48_KHZ;
- state->audio_input = AUDIO_TUNER;
- state->cardtype = CARDTYPE_PVR150;
+ state->vid_input = CX25840_COMPOSITE7;
+ state->aud_input = CX25840_AUDIO8;
+ state->audclk_freq = 48000;
+ state->pvr150_workaround = 0;
cx25840_initialize(client, 1);
@@ -815,11 +911,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
static int cx25840_attach_adapter(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, &cx25840_detect_client);
return 0;
}
@@ -846,9 +938,7 @@ static struct i2c_driver i2c_driver_cx25840 = {
.driver = {
.name = "cx25840",
},
-
.id = I2C_DRIVERID_CX25840,
-
.attach_adapter = cx25840_attach_adapter,
.detach_client = cx25840_detach_client,
.command = cx25840_command,
@@ -892,11 +982,13 @@ static void log_status(struct i2c_client *client)
u8 pref_mode = cx25840_read(client, 0x809);
u8 afc0 = cx25840_read(client, 0x80b);
u8 mute_ctl = cx25840_read(client, 0x8d3);
+ int vid_input = state->vid_input;
+ int aud_input = state->aud_input;
char *p;
- cx25840_info("Video signal: %spresent\n",
+ v4l_info(client, "Video signal: %spresent\n",
(microctrl_vidfmt & 0x10) ? "" : "not ");
- cx25840_info("Detected format: %s\n",
+ v4l_info(client, "Detected format: %s\n",
fmt_strs[gen_stat1 & 0xf]);
switch (mod_det_stat0) {
@@ -911,7 +1003,7 @@ static void log_status(struct i2c_client *client)
case 0xfe: p = "forced mode"; break;
default: p = "not defined";
}
- cx25840_info("Detected audio mode: %s\n", p);
+ v4l_info(client, "Detected audio mode: %s\n", p);
switch (mod_det_stat1) {
case 0x00: p = "not defined"; break;
@@ -937,10 +1029,10 @@ static void log_status(struct i2c_client *client)
case 0xff: p = "no detected audio standard"; break;
default: p = "not defined";
}
- cx25840_info("Detected audio standard: %s\n", p);
- cx25840_info("Audio muted: %s\n",
+ v4l_info(client, "Detected audio standard: %s\n", p);
+ v4l_info(client, "Audio muted: %s\n",
(mute_ctl & 0x2) ? "yes" : "no");
- cx25840_info("Audio microcontroller: %s\n",
+ v4l_info(client, "Audio microcontroller: %s\n",
(download_ctl & 0x10) ? "running" : "stopped");
switch (audio_config >> 4) {
@@ -962,7 +1054,7 @@ static void log_status(struct i2c_client *client)
case 0x0f: p = "automatic detection"; break;
default: p = "undefined";
}
- cx25840_info("Configured audio standard: %s\n", p);
+ v4l_info(client, "Configured audio standard: %s\n", p);
if ((audio_config >> 4) < 0xF) {
switch (audio_config & 0xF) {
@@ -979,7 +1071,7 @@ static void log_status(struct i2c_client *client)
case 0x0a: p = "SAP"; break;
default: p = "undefined";
}
- cx25840_info("Configured audio mode: %s\n", p);
+ v4l_info(client, "Configured audio mode: %s\n", p);
} else {
switch (audio_config & 0xF) {
case 0x00: p = "BG"; break;
@@ -995,30 +1087,27 @@ static void log_status(struct i2c_client *client)
case 0x0f: p = "automatic standard and mode detection"; break;
default: p = "undefined";
}
- cx25840_info("Configured audio system: %s\n", p);
+ v4l_info(client, "Configured audio system: %s\n", p);
}
- cx25840_info("Specified standard: %s\n",
+ v4l_info(client, "Specified standard: %s\n",
vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
- switch (state->input) {
- case CX25840_COMPOSITE0: p = "Composite 0"; break;
- case CX25840_COMPOSITE1: p = "Composite 1"; break;
- case CX25840_SVIDEO0: p = "S-Video 0"; break;
- case CX25840_SVIDEO1: p = "S-Video 1"; break;
- case CX25840_TUNER: p = "Tuner"; break;
+ if (vid_input >= CX25840_COMPOSITE1 &&
+ vid_input <= CX25840_COMPOSITE8) {
+ v4l_info(client, "Specified video input: Composite %d\n",
+ vid_input - CX25840_COMPOSITE1 + 1);
+ } else {
+ v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
+ (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
}
- cx25840_info("Specified input: %s\n", p);
- cx25840_info("Specified audio input: %s\n",
- state->audio_input == 0 ? "Tuner" : "External");
-
- switch (state->audclk_freq) {
- case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break;
- case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break;
- case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break;
- default: p = "undefined";
+ if (aud_input) {
+ v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input);
+ } else {
+ v4l_info(client, "Specified audio input: External\n");
}
- cx25840_info("Specified audioclock freq: %s\n", p);
+
+ v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
switch (pref_mode & 0xf) {
case 0: p = "mono/language A"; break;
@@ -1031,7 +1120,7 @@ static void log_status(struct i2c_client *client)
case 7: p = "language AB"; break;
default: p = "undefined";
}
- cx25840_info("Preferred audio mode: %s\n", p);
+ v4l_info(client, "Preferred audio mode: %s\n", p);
if ((audio_config & 0xf) == 0xf) {
switch ((afc0 >> 3) & 0x3) {
@@ -1040,7 +1129,7 @@ static void log_status(struct i2c_client *client)
case 2: p = "autodetect"; break;
default: p = "undefined";
}
- cx25840_info("Selected 65 MHz format: %s\n", p);
+ v4l_info(client, "Selected 65 MHz format: %s\n", p);
switch (afc0 & 0x7) {
case 0: p = "chroma"; break;
@@ -1050,6 +1139,6 @@ static void log_status(struct i2c_client *client)
case 4: p = "autodetect"; break;
default: p = "undefined";
}
- cx25840_info("Selected 45 MHz format: %s\n", p);
+ v4l_info(client, "Selected 45 MHz format: %s\n", p);
}
}
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
index df9d50a75542..e1a7823d82cd 100644
--- a/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/drivers/media/video/cx25840/cx25840-firmware.c
@@ -15,7 +15,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
@@ -38,7 +37,7 @@ module_param(firmware, charp, 0444);
MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]");
MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]");
-static inline void set_i2c_delay(struct i2c_client *client, int delay)
+static void set_i2c_delay(struct i2c_client *client, int delay)
{
struct i2c_algo_bit_data *algod = client->adapter->algo_data;
@@ -52,7 +51,7 @@ static inline void set_i2c_delay(struct i2c_client *client, int delay)
}
}
-static inline void start_fw_load(struct i2c_client *client)
+static void start_fw_load(struct i2c_client *client)
{
/* DL_ADDR_LB=0 DL_ADDR_HB=0 */
cx25840_write(client, 0x800, 0x00);
@@ -66,7 +65,7 @@ static inline void start_fw_load(struct i2c_client *client)
set_i2c_delay(client, 3);
}
-static inline void end_fw_load(struct i2c_client *client)
+static void end_fw_load(struct i2c_client *client)
{
if (fastfw)
set_i2c_delay(client, 10);
@@ -77,38 +76,47 @@ static inline void end_fw_load(struct i2c_client *client)
cx25840_write(client, 0x803, 0x03);
}
-static inline int check_fw_load(struct i2c_client *client, int size)
+static int check_fw_load(struct i2c_client *client, int size)
{
/* DL_ADDR_HB DL_ADDR_LB */
int s = cx25840_read(client, 0x801) << 8;
s |= cx25840_read(client, 0x800);
if (size != s) {
- cx25840_err("firmware %s load failed\n", firmware);
+ v4l_err(client, "firmware %s load failed\n", firmware);
return -EINVAL;
}
- cx25840_info("loaded %s firmware (%d bytes)\n", firmware, size);
+ v4l_info(client, "loaded %s firmware (%d bytes)\n", firmware, size);
return 0;
}
-static inline int fw_write(struct i2c_client *client, u8 * data, int size)
+static int fw_write(struct i2c_client *client, u8 * data, int size)
{
- if (i2c_master_send(client, data, size) < size) {
+ int sent;
+
+ if ((sent = i2c_master_send(client, data, size)) < size) {
if (fastfw) {
- cx25840_err("333MHz i2c firmware load failed\n");
+ v4l_err(client, "333MHz i2c firmware load failed\n");
fastfw = 0;
set_i2c_delay(client, 10);
+ if (sent > 2) {
+ u16 dl_addr = cx25840_read(client, 0x801) << 8;
+ dl_addr |= cx25840_read(client, 0x800);
+ dl_addr -= sent - 2;
+ cx25840_write(client, 0x801, dl_addr >> 8);
+ cx25840_write(client, 0x800, dl_addr & 0xff);
+ }
+
if (i2c_master_send(client, data, size) < size) {
- cx25840_err
- ("100MHz i2c firmware load failed\n");
+ v4l_err(client, "100MHz i2c firmware load failed\n");
return -ENOSYS;
}
} else {
- cx25840_err("firmware load i2c failure\n");
+ v4l_err(client, "firmware load i2c failure\n");
return -ENOSYS;
}
@@ -124,7 +132,7 @@ int cx25840_loadfw(struct i2c_client *client)
int size, send, retval;
if (request_firmware(&fw, firmware, FWDEV(client)) != 0) {
- cx25840_err("unable to open firmware %s\n", firmware);
+ v4l_err(client, "unable to open firmware %s\n", firmware);
return -EINVAL;
}
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 13ba4e15ddea..04d879da7d63 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -22,7 +22,7 @@
#include "cx25840.h"
-static inline int odd_parity(u8 c)
+static int odd_parity(u8 c)
{
c ^= (c >> 4);
c ^= (c >> 2);
@@ -31,7 +31,7 @@ static inline int odd_parity(u8 c)
return c & 1;
}
-static inline int decode_vps(u8 * dst, u8 * p)
+static int decode_vps(u8 * dst, u8 * p)
{
static const u8 biphase_tbl[] = {
0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h
index 40aa59f9c525..fd22f30dcc1b 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840.h
@@ -24,48 +24,60 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
-extern int cx25840_debug;
-
-#define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define cx25840_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define cx25840_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0)
-
-/* The CARDTYPE_PVR150_WORKAROUND cardtype activates a workaround for a
- hardware bug that is present in PVR150 (and possible PVR500) cards that
- have certain NTSC tuners (tveeprom model numbers 85, 99 and 112). The
+/* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
+ present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
+ certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
audio autodetect fails on some channels for these models and the workaround
is to select the audio standard explicitly. Many thanks to Hauppauge for
providing this information. */
-enum cx25840_cardtype {
- CARDTYPE_PVR150,
- CARDTYPE_PG600,
- CARDTYPE_PVR150_WORKAROUND,
+#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
+
+enum cx25840_video_input {
+ /* Composite video inputs In1-In8 */
+ CX25840_COMPOSITE1 = 1,
+ CX25840_COMPOSITE2,
+ CX25840_COMPOSITE3,
+ CX25840_COMPOSITE4,
+ CX25840_COMPOSITE5,
+ CX25840_COMPOSITE6,
+ CX25840_COMPOSITE7,
+ CX25840_COMPOSITE8,
+
+ /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+ chroma input (In5-In8) */
+ CX25840_SVIDEO_LUMA1 = 0x10,
+ CX25840_SVIDEO_LUMA2 = 0x20,
+ CX25840_SVIDEO_LUMA3 = 0x30,
+ CX25840_SVIDEO_LUMA4 = 0x40,
+ CX25840_SVIDEO_CHROMA4 = 0x400,
+ CX25840_SVIDEO_CHROMA5 = 0x500,
+ CX25840_SVIDEO_CHROMA6 = 0x600,
+ CX25840_SVIDEO_CHROMA7 = 0x700,
+ CX25840_SVIDEO_CHROMA8 = 0x800,
+
+ /* S-Video aliases for common luma/chroma combinations */
+ CX25840_SVIDEO1 = 0x510,
+ CX25840_SVIDEO2 = 0x620,
+ CX25840_SVIDEO3 = 0x730,
+ CX25840_SVIDEO4 = 0x840,
};
-enum cx25840_input {
- CX25840_TUNER,
- CX25840_COMPOSITE0,
- CX25840_COMPOSITE1,
- CX25840_SVIDEO0,
- CX25840_SVIDEO1
+enum cx25840_audio_input {
+ /* Audio inputs: serial or In4-In8 */
+ CX25840_AUDIO_SERIAL,
+ CX25840_AUDIO4 = 4,
+ CX25840_AUDIO5,
+ CX25840_AUDIO6,
+ CX25840_AUDIO7,
+ CX25840_AUDIO8,
};
struct cx25840_state {
- enum cx25840_cardtype cardtype;
- enum cx25840_input input;
- int audio_input;
- enum v4l2_audio_clock_freq audclk_freq;
+ int pvr150_workaround;
+ int radio;
+ enum cx25840_video_input vid_input;
+ enum cx25840_audio_input aud_input;
+ u32 audclk_freq;
};
/* ----------------------------------------------------------------------- */
@@ -84,6 +96,7 @@ int cx25840_loadfw(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
/* cx25850-audio.c */
int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg);
+void cx25840_audio_set_path(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
/* cx25850-vbi.c */
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 85ba4106dc79..53308911ae6e 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -29,6 +29,20 @@ config VIDEO_CX88_DVB
You must also select one or more DVB/ATSC demodulators.
If you are unsure which you need, choose all of them.
+config VIDEO_CX88_ALSA
+ tristate "ALSA DMA audio support"
+ depends on VIDEO_CX88 && SND && EXPERIMENTAL
+ ---help---
+ This is a video4linux driver for direct (DMA) audio on
+ Conexant 2388x based TV cards.
+ It only works with boards with function 01 enabled.
+ To check if your board supports, use lspci -n.
+ If supported, you should see 1471:8801 or 1471:8811
+ PCI device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cx88-alsa.
+
config VIDEO_CX88_DVB_ALL_FRONTENDS
bool "Build all supported frontends for cx2388x based TV cards"
default y
@@ -38,6 +52,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_CX22702
select DVB_LGDT330X
select DVB_NXT200X
+ select DVB_CX24123
---help---
This builds cx88-dvb with all currently supported frontend
demodulators. If you wish to tweak your configuration, and
@@ -89,3 +104,12 @@ config VIDEO_CX88_DVB_NXT200X
---help---
This adds ATSC 8VSB and QAM64/256 support for cards based on the
Connexant 2388x chip and the NXT2002/NXT2004 demodulator.
+
+config VIDEO_CX88_DVB_CX24123
+ bool "Conexant CX24123 DVB-S Support"
+ default y
+ depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
+ select DVB_CX24123
+ ---help---
+ This adds DVB-S support for cards based on the
+ Connexant 2388x chip and the CX24123 demodulator.
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 54401b02b7ce..6e5eaa22619e 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -4,7 +4,8 @@ cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
+obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -16,5 +17,7 @@ extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1
extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
+extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1
+extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
new file mode 100644
index 000000000000..a2e36a1e5f59
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -0,0 +1,847 @@
+/*
+ *
+ * Support for audio capture
+ * PCI function #1 of the cx2388x.
+ *
+ * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
+ * (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+ * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
+ * Based on dummy.c by Jaroslav Kysela <perex@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <asm/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
+
+#define dprintk_core(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
+
+
+/****************************************************************************
+ Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+/* These can be replaced after done */
+#define MIXER_ADDR_LAST MAX_CX88_INPUT
+
+struct cx88_audio_dev {
+ struct cx88_core *core;
+ struct cx88_dmaqueue q;
+
+ /* pci i/o */
+ struct pci_dev *pci;
+ unsigned char pci_rev,pci_lat;
+
+ /* audio controls */
+ int irq;
+
+ snd_card_t *card;
+
+ spinlock_t reg_lock;
+
+ unsigned int dma_size;
+ unsigned int period_size;
+ unsigned int num_periods;
+
+ struct videobuf_dmabuf dma_risc;
+
+ int mixer_volume[MIXER_ADDR_LAST+1][2];
+ int capture_source[MIXER_ADDR_LAST+1][2];
+
+ long int read_count;
+ long int read_offset;
+
+ struct cx88_buffer *buf;
+
+ long opened;
+ snd_pcm_substream_t *substream;
+
+};
+typedef struct cx88_audio_dev snd_cx88_card_t;
+
+
+
+/****************************************************************************
+ Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static snd_card_t *snd_cx88_cards[SNDRV_CARDS];
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
+
+
+/****************************************************************************
+ Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Ricardo Cerqueira");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
+ "{{Conexant,23882},"
+ "{{Conexant,23883}");
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages");
+
+/****************************************************************************
+ Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+{
+ struct cx88_buffer *buf = chip->buf;
+ struct cx88_core *core=chip->core;
+ struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
+
+
+ dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start);
+
+ /* setup fifo + format - out channel */
+ cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25],
+ buf->bpl, buf->risc.dma);
+
+ /* sets bpl size */
+ cx_write(MO_AUDD_LNGTH, buf->bpl);
+
+ /* reset counter */
+ cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET);
+
+ dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02));
+ /* enable irqs */
+ cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02);
+
+
+ /* Enables corresponding bits at AUD_INT_STAT */
+ cx_write(MO_AUD_INTMSK,
+ (1<<16)|
+ (1<<12)|
+ (1<<4)|
+ (1<<0)
+ );
+
+ /* start dma */
+ cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+ cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
+
+ if (debug)
+ cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+
+ return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+{
+ struct cx88_core *core=chip->core;
+ dprintk(1, "Stopping audio DMA\n");
+
+ /* stop dma */
+ cx_clear(MO_AUD_DMACNTRL, 0x11);
+
+ /* disable irqs */
+ cx_clear(MO_PCI_INTMSK, 0x02);
+ cx_clear(MO_AUD_INTMSK,
+ (1<<16)|
+ (1<<12)|
+ (1<<4)|
+ (1<<0)
+ );
+
+ if (debug)
+ cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+
+ return 0;
+}
+
+#define MAX_IRQ_LOOP 10
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx88_aud_irqs[32] = {
+ "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
+ NULL, /* reserved */
+ "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
+ NULL, /* reserved */
+ "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
+ NULL, /* reserved */
+ "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
+ NULL, /* reserved */
+ "opc_err", "par_err", "rip_err", /* 16-18 */
+ "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx8801_aud_irq(snd_cx88_card_t *chip)
+{
+ struct cx88_core *core = chip->core;
+ u32 status, mask;
+ u32 count;
+
+ status = cx_read(MO_AUD_INTSTAT);
+ mask = cx_read(MO_AUD_INTMSK);
+ if (0 == (status & mask)) {
+ spin_unlock(&chip->reg_lock);
+ return;
+ }
+ cx_write(MO_AUD_INTSTAT, status);
+ if (debug > 1 || (status & mask & ~0xff))
+ cx88_print_irqbits(core->name, "irq aud",
+ cx88_aud_irqs, status, mask);
+ /* risc op code error */
+ if (status & (1 << 16)) {
+ printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name);
+ cx_clear(MO_AUD_DMACNTRL, 0x11);
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
+ }
+
+ /* risc1 downstream */
+ if (status & 0x01) {
+ spin_lock(&chip->reg_lock);
+ count = cx_read(MO_AUDD_GPCNT);
+ spin_unlock(&chip->reg_lock);
+ if (chip->read_count == 0)
+ chip->read_count += chip->dma_size;
+ }
+
+ if (chip->read_count >= chip->period_size) {
+ dprintk(2, "Elapsing period\n");
+ snd_pcm_period_elapsed(chip->substream);
+ }
+
+ dprintk(3,"Leaving audio IRQ handler...\n");
+
+ /* FIXME: Any other status should deserve a special handling? */
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ snd_cx88_card_t *chip = dev_id;
+ struct cx88_core *core = chip->core;
+ u32 status;
+ int loop, handled = 0;
+
+ for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02);
+ if (0 == status)
+ goto out;
+ dprintk( 3, "cx8801_irq\n" );
+ dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP );
+ dprintk( 3, " status: %d\n", status );
+ handled = 1;
+ cx_write(MO_PCI_INTSTAT, status);
+
+ if (status & 0x02)
+ {
+ dprintk( 2, " ALSA IRQ handling\n" );
+ cx8801_aud_irq(chip);
+ }
+ };
+
+ if (MAX_IRQ_LOOP == loop) {
+ dprintk( 0, "clearing mask\n" );
+ dprintk(1,"%s/0: irq loop -- clearing mask\n",
+ core->name);
+ cx_clear(MO_PCI_INTMSK,0x02);
+ }
+
+ out:
+ return IRQ_RETVAL(handled);
+}
+
+
+static int dsp_buffer_free(snd_cx88_card_t *chip)
+{
+ BUG_ON(!chip->dma_size);
+
+ dprintk(2,"Freeing buffer\n");
+ videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc);
+ videobuf_dma_free(&chip->dma_risc);
+ btcx_riscmem_free(chip->pci,&chip->buf->risc);
+ kfree(chip->buf);
+
+ chip->dma_size = 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+static snd_pcm_hardware_t snd_cx88_digital_hw = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (2*2048),
+ .period_bytes_min = 2048,
+ .period_bytes_max = 2048,
+ .periods_min = 2,
+ .periods_max = 2,
+};
+
+/*
+ * audio pcm capture runtime free
+ */
+static void snd_card_cx88_runtime_free(snd_pcm_runtime_t *runtime)
+{
+}
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx88_pcm_open(snd_pcm_substream_t *substream)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int err;
+
+ if (test_and_set_bit(0, &chip->opened))
+ return -EBUSY;
+
+ err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
+ goto _error;
+
+ chip->substream = substream;
+
+ chip->read_count = 0;
+ chip->read_offset = 0;
+
+ runtime->private_free = snd_card_cx88_runtime_free;
+ runtime->hw = snd_cx88_digital_hw;
+
+ return 0;
+_error:
+ dprintk(1,"Error opening PCM!\n");
+ clear_bit(0, &chip->opened);
+ smp_mb__after_clear_bit();
+ return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx88_close(snd_pcm_substream_t *substream)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+
+ clear_bit(0, &chip->opened);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx88_hw_params(snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ struct cx88_buffer *buf;
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+
+ chip->period_size = params_period_bytes(hw_params);
+ chip->num_periods = params_periods(hw_params);
+ chip->dma_size = chip->period_size * params_periods(hw_params);
+
+ BUG_ON(!chip->dma_size);
+
+ dprintk(1,"Setting buffer\n");
+
+ buf = kmalloc(sizeof(*buf),GFP_KERNEL);
+ if (NULL == buf)
+ return -ENOMEM;
+ memset(buf,0,sizeof(*buf));
+
+
+ buf->vb.memory = V4L2_MEMORY_MMAP;
+ buf->vb.width = chip->period_size;
+ buf->vb.height = chip->num_periods;
+ buf->vb.size = chip->dma_size;
+ buf->vb.field = V4L2_FIELD_NONE;
+
+ videobuf_dma_init(&buf->vb.dma);
+ videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE,
+ (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
+
+ videobuf_dma_pci_map(chip->pci,&buf->vb.dma);
+
+
+ cx88_risc_databuffer(chip->pci, &buf->risc,
+ buf->vb.dma.sglist,
+ buf->vb.width, buf->vb.height);
+
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ buf->vb.state = STATE_PREPARED;
+
+ buf->bpl = chip->period_size;
+ chip->buf = buf;
+ chip->dma_risc = buf->vb.dma;
+
+ dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages);
+ substream->runtime->dma_area = chip->dma_risc.vmalloc;
+ return 0;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx88_hw_free(snd_pcm_substream_t * substream)
+{
+
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx88_prepare(snd_pcm_substream_t *substream)
+{
+ return 0;
+}
+
+
+/*
+ * trigger callback
+ */
+static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ int err;
+
+ spin_lock(&chip->reg_lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ err=_cx88_start_audio_dma(chip);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ err=_cx88_stop_audio_dma(chip);
+ break;
+ default:
+ err=-EINVAL;
+ break;
+ }
+
+ spin_unlock(&chip->reg_lock);
+
+ return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+
+ if (chip->read_count) {
+ chip->read_count -= snd_pcm_lib_period_bytes(substream);
+ chip->read_offset += snd_pcm_lib_period_bytes(substream);
+ if (chip->read_offset == chip->dma_size)
+ chip->read_offset = 0;
+ }
+
+ dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count);
+ return bytes_to_frames(runtime, chip->read_offset);
+
+}
+
+/*
+ * operators
+ */
+static snd_pcm_ops_t snd_cx88_pcm_ops = {
+ .open = snd_cx88_pcm_open,
+ .close = snd_cx88_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cx88_hw_params,
+ .hw_free = snd_cx88_hw_free,
+ .prepare = snd_cx88_prepare,
+ .trigger = snd_cx88_card_trigger,
+ .pointer = snd_cx88_pointer,
+};
+
+/*
+ * create a PCM device
+ */
+static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name)
+{
+ int err;
+ snd_pcm_t *pcm;
+
+ err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, name);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);
+
+ return 0;
+}
+
+/****************************************************************************
+ CONTROL INTERFACE
+ ****************************************************************************/
+static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)
+{
+ info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ info->count = 1;
+ info->value.integer.min = 0;
+ info->value.integer.max = 0x3f;
+
+ return 0;
+}
+
+/* OK - TODO: test it */
+static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+{
+ snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cx88_core *core=chip->core;
+
+ value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
+
+ return 0;
+}
+
+/* OK - TODO: test it */
+static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+{
+ snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cx88_core *core=chip->core;
+ int v;
+ u32 old_control;
+
+ spin_lock_irq(&chip->reg_lock);
+ old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
+ v = 0x3f - (value->value.integer.value[0] & 0x3f);
+ cx_andor(AUD_VOL_CTL, 0x3f, v);
+ spin_unlock_irq(&chip->reg_lock);
+
+ return v != old_control;
+}
+
+static snd_kcontrol_new_t snd_cx88_capture_volume = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Volume",
+ .info = snd_cx88_capture_volume_info,
+ .get = snd_cx88_capture_volume_get,
+ .put = snd_cx88_capture_volume_put,
+};
+
+
+/****************************************************************************
+ Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+struct pci_device_id cx88_audio_pci_tbl[] = {
+ {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {0, }
+};
+MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
+
+/*
+ * Chip-specific destructor
+ */
+
+static int snd_cx88_free(snd_cx88_card_t *chip)
+{
+
+ if (chip->irq >= 0){
+ synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ }
+
+ cx88_core_put(chip->core,chip->pci);
+
+ pci_disable_device(chip->pci);
+ return 0;
+}
+
+/*
+ * Component Destructor
+ */
+static void snd_cx88_dev_free(snd_card_t * card)
+{
+ snd_cx88_card_t *chip = card->private_data;
+
+ snd_cx88_free(chip);
+}
+
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+static int devno;
+static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci,
+ snd_cx88_card_t **rchip)
+{
+ snd_cx88_card_t *chip;
+ struct cx88_core *core;
+ int err;
+
+ *rchip = NULL;
+
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+
+ pci_set_master(pci);
+
+ chip = (snd_cx88_card_t *) card->private_data;
+
+ core = cx88_core_get(pci);
+
+ if (!pci_dma_supported(pci,0xffffffff)) {
+ dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
+ err = -EIO;
+ cx88_core_put(core,pci);
+ return err;
+ }
+
+
+ /* pci init */
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ spin_lock_init(&chip->reg_lock);
+
+ cx88_reset(core);
+ if (NULL == core) {
+ err = -EINVAL;
+ kfree (chip);
+ return err;
+ }
+ chip->core = core;
+
+ /* get irq */
+ err = request_irq(chip->pci->irq, cx8801_irq,
+ SA_SHIRQ | SA_INTERRUPT, chip->core->name, chip);
+ if (err < 0) {
+ dprintk(0, "%s: can't get IRQ %d\n",
+ chip->core->name, chip->pci->irq);
+ return err;
+ }
+
+ /* print pci info */
+ pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev);
+ pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat);
+
+ dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
+ "latency: %d, mmio: 0x%lx\n", core->name, devno,
+ pci_name(pci), chip->pci_rev, pci->irq,
+ chip->pci_lat,pci_resource_start(pci,0));
+
+ chip->irq = pci->irq;
+ synchronize_irq(chip->irq);
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+
+ return 0;
+}
+
+static int __devinit cx88_audio_initdev(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ snd_card_t *card;
+ snd_cx88_card_t *chip;
+ int err;
+
+ if (devno >= SNDRV_CARDS)
+ return (-ENODEV);
+
+ if (!enable[devno]) {
+ ++devno;
+ return (-ENOENT);
+ }
+
+ card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t));
+ if (!card)
+ return (-ENOMEM);
+
+ card->private_free = snd_cx88_dev_free;
+
+ err = snd_cx88_create(card, pci, &chip);
+ if (err < 0)
+ return (err);
+
+ err = snd_cx88_pcm(chip, 0, "CX88 Digital");
+
+ if (err < 0) {
+ snd_card_free(card);
+ return (err);
+ }
+
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
+ if (err < 0) {
+ snd_card_free(card);
+ return (err);
+ }
+
+ strcpy (card->driver, "CX88x");
+ sprintf(card->shortname, "Conexant CX%x", pci->device);
+ sprintf(card->longname, "%s at %#lx",
+ card->shortname, pci_resource_start(pci, 0));
+ strcpy (card->mixername, "CX88");
+
+ dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
+ card->driver,devno);
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ snd_card_free(card);
+ return (err);
+ }
+ snd_cx88_cards[devno] = card;
+
+ pci_set_drvdata(pci,card);
+
+ devno++;
+ return 0;
+}
+/*
+ * ALSA destructor
+ */
+static void __devexit cx88_audio_finidev(struct pci_dev *pci)
+{
+ struct cx88_audio_dev *card = pci_get_drvdata(pci);
+
+ snd_card_free((void *)card);
+
+ pci_set_drvdata(pci, NULL);
+
+ devno--;
+}
+
+/*
+ * PCI driver definition
+ */
+
+static struct pci_driver cx88_audio_pci_driver = {
+ .name = "cx88_audio",
+ .id_table = cx88_audio_pci_tbl,
+ .probe = cx88_audio_initdev,
+ .remove = cx88_audio_finidev,
+};
+
+/****************************************************************************
+ LINUX MODULE INIT
+ ****************************************************************************/
+
+/*
+ * module init
+ */
+static int cx88_audio_init(void)
+{
+ printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",
+ (CX88_VERSION_CODE >> 16) & 0xff,
+ (CX88_VERSION_CODE >> 8) & 0xff,
+ CX88_VERSION_CODE & 0xff);
+#ifdef SNAPSHOT
+ printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
+ SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
+#endif
+ return pci_register_driver(&cx88_audio_pci_driver);
+}
+
+/*
+ * module remove
+ */
+static void cx88_audio_fini(void)
+{
+
+ pci_unregister_driver(&cx88_audio_pci_driver);
+}
+
+module_init(cx88_audio_init);
+module_exit(cx88_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 74e57a53116f..a502a4d6e4ae 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -32,10 +32,10 @@
#include <linux/firmware.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
-MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
static unsigned int mpegbufs = 32;
@@ -1375,7 +1375,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
struct cx88_core *core = dev->core;
if (debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
@@ -1539,10 +1539,9 @@ static int mpeg_open(struct inode *inode, struct file *file)
dprintk(1,"open minor=%d\n",minor);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
@@ -1678,10 +1677,9 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
goto fail_core;
err = -ENOMEM;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
goto fail_core;
- memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
dev->width = 720;
@@ -1689,6 +1687,18 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params));
memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params));
+ if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) {
+
+ if (core->tuner_formats & V4L2_STD_525_60) {
+ dev->height = 480;
+ dev->params.vi_frame_rate = 30;
+ } else {
+ dev->height = 576;
+ dev->params.vi_frame_rate = 25;
+ }
+
+ }
+
err = cx8802_init_common(dev);
if (0 != err)
goto fail_free;
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 951709aa88ba..ad2f565f522c 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -611,12 +611,12 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0xed12, /* internal decoder */
+ .gpio0 = 0xed1a,
.gpio2 = 0x00ff,
},{
.type = CX88_VMUX_DEBUG,
.vmux = 0,
- .gpio0 = 0xff01, /* mono from tuner chip */
+ .gpio0 = 0xff01,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -708,7 +708,7 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
.name = "DViCO FusionHDTV 3 Gold-T",
- .tuner_type = TUNER_THOMSON_DTT7611,
+ .tuner_type = TUNER_THOMSON_DTT761X,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -897,6 +897,158 @@ struct cx88_board cx88_boards[] = {
.gpio3 = 0x0000,
}},
},
+ [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
+ .name = "Hauppauge Nova-S-Plus DVB-S",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
+ .name = "Hauppauge Nova-SE2 DVB-S",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_KWORLD_DVBS_100] = {
+ .name = "KWorld DVB-S 100",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_HVR1100] = {
+ .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ /* fixme: Add radio support */
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
+ .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ }},
+ /* fixme: Add radio support */
+ .dvb = 1,
+ },
+ [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
+ .name = "digitalnow DNTV Live! DVB-T Pro",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+ TDA9887_PORT2_ACTIVE,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xf80808,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xf80808,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xf80808,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xf80808,
+ },
+ .dvb = 1,
+ },
+ [CX88_BOARD_KWORLD_DVB_T_CX22702] = {
+ /* Kworld V-stream Xpert DVB-T with Thomson tuner */
+ /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */
+ /* Manenti Marco <marco_manenti@colman.it> */
+ .name = "KWorld/VStream XPert DVB-T with cx22702",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
+ .name = "DViCO FusionHDTV DVB-T Dual Digital",
+ .tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x000027df,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x000027df,
+ }},
+ .dvb = 1,
+ },
+
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -1044,6 +1196,59 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x1461,
.subdevice = 0x000a,
.card = CX88_BOARD_AVERTV_303,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9200,
+ .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9201,
+ .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9202,
+ .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+ },{
+ .subvendor = 0x17de,
+ .subdevice = 0x08b2,
+ .card = CX88_BOARD_KWORLD_DVBS_100,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9400,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9402,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9800,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9802,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9001,
+ .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
+ },{
+ .subvendor = 0x1822,
+ .subdevice = 0x0025,
+ .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+ },{
+ .subvendor = 0x17de,
+ .subdevice = 0x08a1,
+ .card = CX88_BOARD_KWORLD_DVB_T_CX22702,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xdb50,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xdb11,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ /* Re-branded DViCO: UltraView DVB-T Plus */
},
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -1075,20 +1280,19 @@ static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
core->name, core->tuner_type, eeprom_data[0]);
}
-
-/* ----------------------------------------------------------------------- */
-
static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
struct tveeprom tv;
tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
core->tuner_type = tv.tuner_type;
+ core->tuner_formats = tv.tuner_formats;
core->has_radio = tv.has_radio;
/* Make sure we support the board model */
switch (tv.model)
{
+ case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
case 90002: /* Nova-T-PCI (9002) */
case 92001: /* Nova-S-Plus (Video and IR) */
case 92002: /* Nova-S-Plus (Video and IR) */
@@ -1096,7 +1300,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
case 90500: /* Nova-T-PCI (oem) */
case 90501: /* Nova-T-PCI (oem/IR) */
case 92000: /* Nova-SE2 (OEM, No Video or IR) */
-
+ case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
+ case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
+ case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
/* known */
break;
default:
@@ -1211,12 +1417,21 @@ void cx88_card_setup(struct cx88_core *core)
if (0 == core->i2c_rc)
leadtek_eeprom(core,eeprom);
break;
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
+ case CX88_BOARD_HAUPPAUGE_HVR1100LP:
if (0 == core->i2c_rc)
hauppauge_eeprom(core,eeprom);
break;
+ case CX88_BOARD_KWORLD_DVBS_100:
+ cx_write(MO_GP0_IO, 0x000007f8);
+ cx_write(MO_GP1_IO, 0x00000001);
+ break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
/* GPIO0:0 is hooked to mt352 reset pin */
cx_set(MO_GP0_IO, 0x00000101);
cx_clear(MO_GP0_IO, 0x00000001);
@@ -1232,6 +1447,9 @@ void cx88_card_setup(struct cx88_core *core)
cx_clear(MO_GP0_IO, 0x00000007);
cx_set(MO_GP2_IO, 0x00000101);
break;
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+ cx_write(MO_GP0_IO, 0x00080808);
+ break;
case CX88_BOARD_ATI_HDTVWONDER:
if (0 == core->i2c_rc) {
/* enable tuner */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index bb6eb54e19ce..8d6d6a6cf785 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -32,8 +32,10 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
+#include <linux/mutex.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -74,62 +76,8 @@ MODULE_PARM_DESC(nocomb,"disable comb filter");
static unsigned int cx88_devcount;
static LIST_HEAD(cx88_devlist);
-static DECLARE_MUTEX(devlist);
+static DEFINE_MUTEX(devlist);
-/* ------------------------------------------------------------------ */
-/* debug help functions */
-
-static const char *v4l1_ioctls[] = {
- "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
- "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
- "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
- "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
- "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
- "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
- "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
- "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
- "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
- "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
- "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void cx88_print_ioctl(char *name, unsigned int cmd)
-{
- char *dir;
-
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "??"; break;
- }
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "???");
- break;
- default:
- printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- }
-}
-
-/* ------------------------------------------------------------------ */
#define NO_SYNC_LINE (-1U)
static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
@@ -291,9 +239,9 @@ cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
* channel 22 (u video) - 2.0k
* channel 23 (v video) - 2.0k
* channel 24 (vbi) - 4.0k
- * channels 25+26 (audio) - 0.5k
+ * channels 25+26 (audio) - 4.0k
* channel 28 (mpeg) - 4.0k
- * TOTAL = 25.5k
+ * TOTAL = 29.0k
*
* Every channel has 160 bytes control data (64 bytes instruction
* queue and 6 CDT entries), which is close to 2k total.
@@ -359,7 +307,7 @@ struct sram_channel cx88_sram_channels[] = {
.ctrl_start = 0x180680,
.cdt = 0x180680 + 64,
.fifo_start = 0x185400,
- .fifo_size = 0x000200,
+ .fifo_size = 0x001000,
.ptr1_reg = MO_DMA25_PTR1,
.ptr2_reg = MO_DMA25_PTR2,
.cnt1_reg = MO_DMA25_CNT1,
@@ -371,7 +319,7 @@ struct sram_channel cx88_sram_channels[] = {
.ctrl_start = 0x180720,
.cdt = 0x180680 + 64, /* same as audio IN */
.fifo_start = 0x185400, /* same as audio IN */
- .fifo_size = 0x000200, /* same as audio IN */
+ .fifo_size = 0x001000, /* same as audio IN */
.ptr1_reg = MO_DMA26_PTR1,
.ptr2_reg = MO_DMA26_PTR2,
.cnt1_reg = MO_DMA26_CNT1,
@@ -382,7 +330,7 @@ struct sram_channel cx88_sram_channels[] = {
.cmds_start = 0x180200,
.ctrl_start = 0x1807C0,
.cdt = 0x1807C0 + 64,
- .fifo_start = 0x185600,
+ .fifo_start = 0x186400,
.fifo_size = 0x001000,
.ptr1_reg = MO_DMA28_PTR1,
.ptr2_reg = MO_DMA28_PTR2,
@@ -848,7 +796,6 @@ int cx88_start_audio_dma(struct cx88_core *core)
/* start dma */
cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
-
return 0;
}
@@ -1090,7 +1037,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
struct list_head *item;
int i;
- down(&devlist);
+ mutex_lock(&devlist);
list_for_each(item,&cx88_devlist) {
core = list_entry(item, struct cx88_core, devlist);
if (pci->bus->number != core->pci_bus)
@@ -1101,14 +1048,13 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
if (0 != get_ressources(core,pci))
goto fail_unlock;
atomic_inc(&core->refcount);
- up(&devlist);
+ mutex_unlock(&devlist);
return core;
}
- core = kmalloc(sizeof(*core),GFP_KERNEL);
+ core = kzalloc(sizeof(*core),GFP_KERNEL);
if (NULL == core)
goto fail_unlock;
- memset(core,0,sizeof(*core));
atomic_inc(&core->refcount);
core->pci_bus = pci->bus->number;
core->pci_slot = PCI_SLOT(pci->devfn);
@@ -1177,13 +1123,13 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
cx88_card_setup(core);
cx88_ir_init(core,pci);
- up(&devlist);
+ mutex_unlock(&devlist);
return core;
fail_free:
kfree(core);
fail_unlock:
- up(&devlist);
+ mutex_unlock(&devlist);
return NULL;
}
@@ -1195,20 +1141,19 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
if (!atomic_dec_and_test(&core->refcount))
return;
- down(&devlist);
+ mutex_lock(&devlist);
cx88_ir_fini(core);
if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap);
list_del(&core->devlist);
iounmap(core->lmmio);
cx88_devcount--;
- up(&devlist);
+ mutex_unlock(&devlist);
kfree(core);
}
/* ------------------------------------------------------------------ */
-EXPORT_SYMBOL(cx88_print_ioctl);
EXPORT_SYMBOL(cx88_print_irqbits);
EXPORT_SYMBOL(cx88_core_irq);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 99ea955f5987..e48aa3f6e500 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -3,7 +3,7 @@
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
*
- * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* This program is free software; you can redistribute it and/or modify
@@ -31,10 +31,14 @@
#include "cx88.h"
#include "dvb-pll.h"
+#include <media/v4l2-common.h>
#ifdef HAVE_MT352
# include "mt352.h"
# include "mt352_priv.h"
+# ifdef HAVE_VP3054_I2C
+# include "cx88-vp3054-i2c.h"
+# endif
#endif
#ifdef HAVE_CX22702
# include "cx22702.h"
@@ -48,6 +52,9 @@
#ifdef HAVE_NXT200X
# include "nxt200x.h"
#endif
+#ifdef HAVE_CX24123
+# include "cx24123.h"
+#endif
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -125,6 +132,27 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
return 0;
}
+static int dvico_dual_demod_init(struct dvb_frontend *fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { 0x89, 0x38, 0x39 };
@@ -172,6 +200,98 @@ static struct mt352_config dntv_live_dvbt_config = {
.demod_init = dntv_live_dvbt_demod_init,
.pll_set = mt352_pll_set,
};
+
+static struct mt352_config dvico_fusionhdtv_dual = {
+ .demod_address = 0x0F,
+ .demod_init = dvico_dual_demod_init,
+ .pll_set = mt352_pll_set,
+};
+
+#ifdef HAVE_VP3054_I2C
+static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
+{
+ static u8 clock_config [] = { 0x89, 0x38, 0x38 };
+ static u8 reset [] = { 0x50, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
+ 0x00, 0xFF, 0x00, 0x40, 0x40 };
+ static u8 dntv_extra[] = { 0xB5, 0x7A };
+ static u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(2000);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ udelay(2000);
+ mt352_write(fe, dntv_extra, sizeof(dntv_extra));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
+static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+
+ /* this message is to set up ATC and ALC */
+ static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
+ struct i2c_msg msg =
+ { .addr = dev->core->pll_addr, .flags = 0,
+ .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
+ int err;
+
+ if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ u8* pllbuf)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct i2c_msg msg =
+ { .addr = dev->core->pll_addr, .flags = 0,
+ .buf = pllbuf+1, .len = 4 };
+ int err;
+
+ /* Switch PLL to DVB mode */
+ err = philips_fmd1216_pll_init(fe);
+ if (err)
+ return err;
+
+ /* Tune PLL */
+ pllbuf[0] = dev->core->pll_addr << 1;
+ dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+ params->frequency,
+ params->u.ofdm.bandwidth);
+ if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "cx88-dvb: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, pllbuf[0], pllbuf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static struct mt352_config dntv_live_dvbt_pro_config = {
+ .demod_address = 0x0f,
+ .no_tuner = 1,
+ .demod_init = dntv_live_dvbt_pro_demod_init,
+ .pll_set = dntv_live_dvbt_pro_pll_set,
+};
+#endif
#endif
#ifdef HAVE_CX22702
@@ -188,6 +308,12 @@ static struct cx22702_config hauppauge_novat_config = {
.pll_address = 0x61,
.pll_desc = &dvb_pll_thomson_dtt759x,
};
+static struct cx22702_config hauppauge_hvr1100_config = {
+ .demod_address = 0x63,
+ .output_mode = CX22702_SERIAL_OUTPUT,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_fmd1216me,
+};
#endif
#ifdef HAVE_OR51132
@@ -314,6 +440,40 @@ static struct nxt200x_config ati_hdtvwonder = {
};
#endif
+#ifdef HAVE_CX24123
+static int cx24123_set_ts_param(struct dvb_frontend* fe,
+ int is_punctured)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ dev->ts_gen_cntrl = 0x2;
+ return 0;
+}
+
+static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx88_core *core = dev->core;
+
+ if (on)
+ cx_write(MO_GP0_IO, 0x000006f9);
+ else
+ cx_write(MO_GP0_IO, 0x000006fB);
+}
+
+static struct cx24123_config hauppauge_novas_config = {
+ .demod_address = 0x55,
+ .use_isl6421 = 1,
+ .set_ts_params = cx24123_set_ts_param,
+};
+
+static struct cx24123_config kworld_dvbs_100_config = {
+ .demod_address = 0x15,
+ .use_isl6421 = 0,
+ .set_ts_params = cx24123_set_ts_param,
+ .enable_lnb_voltage = cx24123_enable_lnb_voltage,
+};
+#endif
+
static int dvb_register(struct cx8802_dev *dev)
{
/* init struct videobuf_dvb */
@@ -329,10 +489,16 @@ static int dvb_register(struct cx8802_dev *dev)
break;
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
case CX88_BOARD_CONEXANT_DVB_T1:
+ case CX88_BOARD_KWORLD_DVB_T_CX22702:
case CX88_BOARD_WINFAST_DTV1000:
dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
&dev->core->i2c_adap);
break;
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
+ case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+ dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
+ &dev->core->i2c_adap);
+ break;
#endif
#ifdef HAVE_MT352
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
@@ -355,6 +521,24 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
&dev->core->i2c_adap);
break;
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+#ifdef HAVE_VP3054_I2C
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_fmd1216me;
+ dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
+ &((struct vp3054_i2c_state *)dev->card_priv)->adap);
+#else
+ printk("%s: built without vp3054 support\n", dev->core->name);
+#endif
+ break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ /* The tin box says DEE1601, but it seems to be DTT7579
+ * compatible, with a slightly different MT352 AGC gain. */
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
+ &dev->core->i2c_adap);
+ break;
#endif
#ifdef HAVE_OR51132
case CX88_BOARD_PCHDTV_HD3000:
@@ -393,7 +577,7 @@ static int dvb_register(struct cx8802_dev *dev)
cx_set(MO_GP0_IO, 9);
mdelay(200);
dev->core->pll_addr = 0x61;
- dev->core->pll_desc = &dvb_pll_thomson_dtt7611;
+ dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
&dev->core->i2c_adap);
}
@@ -421,6 +605,17 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
break;
#endif
+#ifdef HAVE_CX24123
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
+ &dev->core->i2c_adap);
+ break;
+ case CX88_BOARD_KWORLD_DVBS_100:
+ dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
+ &dev->core->i2c_adap);
+ break;
+#endif
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->core->name);
@@ -462,10 +657,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
goto fail_core;
err = -ENOMEM;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
goto fail_core;
- memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
@@ -473,6 +667,12 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
if (0 != err)
goto fail_free;
+#ifdef HAVE_VP3054_I2C
+ err = vp3054_i2c_probe(dev);
+ if (0 != err)
+ goto fail_free;
+#endif
+
/* dvb stuff */
printk("%s/2: cx2388x based dvb card\n", core->name);
videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
@@ -484,6 +684,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
err = dvb_register(dev);
if (0 != err)
goto fail_fini;
+
+ /* Maintain a reference to cx88-video can query the 8802 device. */
+ core->dvbdev = dev;
return 0;
fail_fini:
@@ -499,9 +702,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+ /* Destroy any 8802 reference. */
+ dev->core->dvbdev = NULL;
+
/* dvb */
videobuf_dvb_unregister(&dev->dvb);
+#ifdef HAVE_VP3054_I2C
+ vp3054_i2c_remove(dev);
+#endif
+
/* common */
cx8802_fini_common(dev);
cx88_core_put(dev->core,dev->pci);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 4a8fb161b16a..f720901e9638 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -30,6 +30,7 @@
#include <asm/io.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
static unsigned int i2c_debug = 0;
module_param(i2c_debug, int, 0644);
@@ -135,7 +136,17 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
if (0 != core->i2c_rc)
return;
- i2c_clients_command(&core->i2c_adap, cmd, arg);
+
+ if (core->dvbdev) {
+ if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
+ core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
+
+ i2c_clients_command(&core->i2c_adap, cmd, arg);
+
+ if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
+ core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
+ } else
+ i2c_clients_command(&core->i2c_adap, cmd, arg);
}
static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 461019dca901..da2ad5c4b553 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2003 Pavel Machek
* Copyright (c) 2004 Gerd Knorr
- * Copyright (c) 2004 Chris Pascoe
+ * Copyright (c) 2004, 2005 Chris Pascoe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,9 +29,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <media/ir-common.h>
-
#include "cx88.h"
+#include <media/ir-common.h>
/* ---------------------------------------------------------------------- */
@@ -258,6 +257,114 @@ static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
/* ---------------------------------------------------------------------- */
+/* AVERTV STUDIO 303 Remote */
+static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = {
+ [ 0x2a ] = KEY_KP1,
+ [ 0x32 ] = KEY_KP2,
+ [ 0x3a ] = KEY_KP3,
+ [ 0x4a ] = KEY_KP4,
+ [ 0x52 ] = KEY_KP5,
+ [ 0x5a ] = KEY_KP6,
+ [ 0x6a ] = KEY_KP7,
+ [ 0x72 ] = KEY_KP8,
+ [ 0x7a ] = KEY_KP9,
+ [ 0x0e ] = KEY_KP0,
+
+ [ 0x02 ] = KEY_POWER,
+ [ 0x22 ] = KEY_VIDEO,
+ [ 0x42 ] = KEY_AUDIO,
+ [ 0x62 ] = KEY_ZOOM,
+ [ 0x0a ] = KEY_TV,
+ [ 0x12 ] = KEY_CD,
+ [ 0x1a ] = KEY_TEXT,
+
+ [ 0x16 ] = KEY_SUBTITLE,
+ [ 0x1e ] = KEY_REWIND,
+ [ 0x06 ] = KEY_PRINT,
+
+ [ 0x2e ] = KEY_SEARCH,
+ [ 0x36 ] = KEY_SLEEP,
+ [ 0x3e ] = KEY_SHUFFLE,
+ [ 0x26 ] = KEY_MUTE,
+
+ [ 0x4e ] = KEY_RECORD,
+ [ 0x56 ] = KEY_PAUSE,
+ [ 0x5e ] = KEY_STOP,
+ [ 0x46 ] = KEY_PLAY,
+
+ [ 0x6e ] = KEY_RED,
+ [ 0x0b ] = KEY_GREEN,
+ [ 0x66 ] = KEY_YELLOW,
+ [ 0x03 ] = KEY_BLUE,
+
+ [ 0x76 ] = KEY_LEFT,
+ [ 0x7e ] = KEY_RIGHT,
+ [ 0x13 ] = KEY_DOWN,
+ [ 0x1b ] = KEY_UP,
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* DigitalNow DNTV Live! DVB-T Pro Remote */
+static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = {
+ [ 0x16 ] = KEY_POWER,
+ [ 0x5b ] = KEY_HOME,
+
+ [ 0x55 ] = KEY_TV, /* live tv */
+ [ 0x58 ] = KEY_TUNER, /* digital Radio */
+ [ 0x5a ] = KEY_RADIO, /* FM radio */
+ [ 0x59 ] = KEY_DVD, /* dvd menu */
+ [ 0x03 ] = KEY_1,
+ [ 0x01 ] = KEY_2,
+ [ 0x06 ] = KEY_3,
+ [ 0x09 ] = KEY_4,
+ [ 0x1d ] = KEY_5,
+ [ 0x1f ] = KEY_6,
+ [ 0x0d ] = KEY_7,
+ [ 0x19 ] = KEY_8,
+ [ 0x1b ] = KEY_9,
+ [ 0x0c ] = KEY_CANCEL,
+ [ 0x15 ] = KEY_0,
+ [ 0x4a ] = KEY_CLEAR,
+ [ 0x13 ] = KEY_BACK,
+ [ 0x00 ] = KEY_TAB,
+ [ 0x4b ] = KEY_UP,
+ [ 0x4e ] = KEY_LEFT,
+ [ 0x4f ] = KEY_OK,
+ [ 0x52 ] = KEY_RIGHT,
+ [ 0x51 ] = KEY_DOWN,
+ [ 0x1e ] = KEY_VOLUMEUP,
+ [ 0x0a ] = KEY_VOLUMEDOWN,
+ [ 0x02 ] = KEY_CHANNELDOWN,
+ [ 0x05 ] = KEY_CHANNELUP,
+ [ 0x11 ] = KEY_RECORD,
+ [ 0x14 ] = KEY_PLAY,
+ [ 0x4c ] = KEY_PAUSE,
+ [ 0x1a ] = KEY_STOP,
+ [ 0x40 ] = KEY_REWIND,
+ [ 0x12 ] = KEY_FASTFORWARD,
+ [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */
+ [ 0x42 ] = KEY_NEXTSONG, /* skip >| */
+ [ 0x54 ] = KEY_CAMERA, /* capture */
+ [ 0x50 ] = KEY_LANGUAGE, /* sap */
+ [ 0x47 ] = KEY_TV2, /* pip */
+ [ 0x4d ] = KEY_SCREEN,
+ [ 0x43 ] = KEY_SUBTITLE,
+ [ 0x10 ] = KEY_MUTE,
+ [ 0x49 ] = KEY_AUDIO, /* l/r */
+ [ 0x07 ] = KEY_SLEEP,
+ [ 0x08 ] = KEY_VIDEO, /* a/v */
+ [ 0x0e ] = KEY_PREVIOUS, /* recall */
+ [ 0x45 ] = KEY_ZOOM, /* zoom + */
+ [ 0x46 ] = KEY_ANGLE, /* zoom - */
+ [ 0x56 ] = KEY_RED,
+ [ 0x57 ] = KEY_GREEN,
+ [ 0x5c ] = KEY_YELLOW,
+ [ 0x5d ] = KEY_BLUE,
+};
+
+/* ---------------------------------------------------------------------- */
+
struct cx88_IR {
struct cx88_core *core;
struct input_dev *input;
@@ -266,7 +373,7 @@ struct cx88_IR {
char phys[32];
/* sample from gpio pin 16 */
- int sampling;
+ u32 sampling;
u32 samples[16];
int scount;
unsigned long release;
@@ -384,10 +491,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
ir_codes = ir_codes_cinergy_1400;
ir_type = IR_TYPE_PD;
- ir->sampling = 1;
+ ir->sampling = 0xeb04; /* address */
break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
ir_codes = ir_codes_hauppauge_new;
ir_type = IR_TYPE_RC5;
ir->sampling = 1;
@@ -427,6 +537,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->mask_keyup = 0x40;
ir->polling = 1; /* ms */
break;
+ case CX88_BOARD_AVERTV_303:
+ case CX88_BOARD_AVERTV_STUDIO_303:
+ ir_codes = ir_codes_avertv_303;
+ ir->gpio_addr = MO_GP2_IO;
+ ir->mask_keycode = 0xfb;
+ ir->mask_keydown = 0x02;
+ ir->polling = 50; /* ms */
+ break;
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+ ir_codes = ir_codes_dntv_live_dvbt_pro;
+ ir_type = IR_TYPE_PD;
+ ir->sampling = 0xff00; /* address */
+ break;
}
if (NULL == ir_codes) {
@@ -484,6 +607,10 @@ int cx88_ir_fini(struct cx88_core *core)
if (NULL == ir)
return 0;
+ if (ir->sampling) {
+ cx_write(MO_DDSCFG_IO, 0x0);
+ core->pci_irqmask &= ~(1 << 18);
+ }
if (ir->polling) {
del_timer(&ir->timer);
flush_scheduled_work();
@@ -535,6 +662,7 @@ void cx88_ir_irq(struct cx88_core *core)
/* decode it */
switch (core->board) {
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
if (ircode == 0xffffffff) { /* decoding error */
@@ -550,7 +678,7 @@ void cx88_ir_irq(struct cx88_core *core)
break;
}
- if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
+ if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
ir_dprintk("pulse distance decoded wrong address\n");
break;
}
@@ -567,6 +695,9 @@ void cx88_ir_irq(struct cx88_core *core)
break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
if ((ircode & 0xfffff000) != 0x3000)
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 35e6d0c2b872..c79cc1d2bf8b 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -78,6 +78,11 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
cx_write(TS_SOP_STAT, 1<<13);
break;
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
+ udelay(100);
+ break;
default:
cx_write(TS_SOP_STAT, 0x00);
break;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index a1b120c8a9b5..da8d97ce0c4b 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -60,6 +60,11 @@ static unsigned int audio_debug = 0;
module_param(audio_debug, int, 0644);
MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
+static unsigned int always_analog = 0;
+module_param(always_analog,int,0644);
+MODULE_PARM_DESC(always_analog,"force analog audio out");
+
+
#define dprintk(fmt, arg...) if (audio_debug) \
printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
@@ -132,14 +137,22 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
{
u32 volume;
+#ifndef USING_CX88_ALSA
/* restart dma; This avoids buzz in NICAM and is good in others */
cx88_stop_audio_dma(core);
+#endif
cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
+#ifndef USING_CX88_ALSA
cx88_start_audio_dma(core);
+#endif
if (cx88_boards[core->board].blackbird) {
/* sets sound input from external adc */
- cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+ if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN)
+ cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+ else
+ cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+
cx_write(AUD_I2SINPUTCNTL, 4);
cx_write(AUD_BAUDRATE, 1);
/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
@@ -147,7 +160,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
cx_write(AUD_I2SOUTPUTCNTL, 1);
cx_write(AUD_I2SCNTL, 0);
/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
- } else {
+ }
+ if ((always_analog) || (!cx88_boards[core->board].blackbird)) {
ctl |= EN_DAC_ENABLE;
cx_write(AUD_CTL, ctl);
}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 24a48f8a48c1..073494ceab0f 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -33,6 +33,7 @@
#include <asm/div64.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
/* Include V4L1 specific functions. Should be removed soon */
#include <linux/videodev.h>
@@ -240,7 +241,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.minimum = 0,
.maximum = 0xff,
.step = 1,
- .default_value = 0,
+ .default_value = 0x3f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 0,
@@ -271,7 +272,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.minimum = 0,
.maximum = 0xff,
.step = 1,
- .default_value = 0,
+ .default_value = 0x7f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 0,
@@ -285,6 +286,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.name = "Mute",
.minimum = 0,
.maximum = 1,
+ .default_value = 1,
.type = V4L2_CTRL_TYPE_BOOLEAN,
},
.reg = AUD_VOL_CTL,
@@ -298,7 +300,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.minimum = 0,
.maximum = 0x3f,
.step = 1,
- .default_value = 0,
+ .default_value = 0x1f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.reg = AUD_VOL_CTL,
@@ -748,10 +750,9 @@ static int video_open(struct inode *inode, struct file *file)
minor,radio,v4l2_type_names[type]);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -917,6 +918,9 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
break;
}
+ printk("get_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+ ctl->id, c->reg, ctl->value,
+ c->mask, c->sreg ? " [shadowed]" : "");
return 0;
}
@@ -925,13 +929,13 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
{
/* struct cx88_core *core = dev->core; */
struct cx88_ctrl *c = NULL;
- u32 v_sat_value;
- u32 value;
+ u32 value,mask;
int i;
-
- for (i = 0; i < CX8800_CTLS; i++)
- if (cx8800_ctls[i].v.id == ctl->id)
+ for (i = 0; i < CX8800_CTLS; i++) {
+ if (cx8800_ctls[i].v.id == ctl->id) {
c = &cx8800_ctls[i];
+ }
+ }
if (NULL == c)
return -EINVAL;
@@ -939,6 +943,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
ctl->value = c->v.minimum;
if (ctl->value > c->v.maximum)
ctl->value = c->v.maximum;
+ mask=c->mask;
switch (ctl->id) {
case V4L2_CID_AUDIO_BALANCE:
value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
@@ -948,56 +953,44 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
break;
case V4L2_CID_SATURATION:
/* special v_sat handling */
- v_sat_value = ctl->value - (0x7f - 0x5a);
- if (v_sat_value > 0xff)
- v_sat_value = 0xff;
- if (v_sat_value < 0x00)
- v_sat_value = 0x00;
- cx_andor(MO_UV_SATURATION, 0xff00, v_sat_value << 8);
- /* fall through to default route for u_sat */
+
+ value = ((ctl->value - c->off) << c->shift) & c->mask;
+
+ if (core->tvnorm->id & V4L2_STD_SECAM) {
+ /* For SECAM, both U and V sat should be equal */
+ value=value<<8|value;
+ } else {
+ /* Keeps U Saturation proportional to V Sat */
+ value=(value*0x5a)/0x7f<<8|value;
+ }
+ mask=0xffff;
+ break;
default:
value = ((ctl->value - c->off) << c->shift) & c->mask;
break;
}
- dprintk(1,"set_control id=0x%X reg=0x%x val=0x%x%s\n",
- ctl->id, c->reg, value, c->sreg ? " [shadowed]" : "");
+ printk("set_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+ ctl->id, c->reg, value,
+ mask, c->sreg ? " [shadowed]" : "");
if (c->sreg) {
- cx_sandor(c->sreg, c->reg, c->mask, value);
+ cx_sandor(c->sreg, c->reg, mask, value);
} else {
- cx_andor(c->reg, c->mask, value);
+ cx_andor(c->reg, mask, value);
}
return 0;
}
-/* 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,
- .value = 1,
- };
- static struct v4l2_control volume = {
- .id = V4L2_CID_AUDIO_VOLUME,
- .value = 0x3f,
- };
- static struct v4l2_control hue = {
- .id = V4L2_CID_HUE,
- .value = 0x80,
- };
- static struct v4l2_control contrast = {
- .id = V4L2_CID_CONTRAST,
- .value = 0x80,
- };
- static struct v4l2_control brightness = {
- .id = V4L2_CID_BRIGHTNESS,
- .value = 0x80,
- };
+ struct v4l2_control ctrl;
+ int i;
- set_control(core,&mute);
- set_control(core,&volume);
- set_control(core,&hue);
- set_control(core,&contrast);
- set_control(core,&brightness);
+ for (i = 0; i < CX8800_CTLS; i++) {
+ ctrl.id=cx8800_ctls[i].v.id;
+ ctrl.value=cx8800_ctls[i].v.default_value
+ +cx8800_ctls[i].off;
+ set_control(core, &ctrl);
+ }
}
/* ------------------------------------------------------------------ */
@@ -1125,7 +1118,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
int err;
if (video_debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
/* --- capabilities ------------------------------------------ */
@@ -1261,7 +1254,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
dprintk( 1, "CORE IOCTL: 0x%x\n", cmd );
if (video_debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
/* ---------- tv norms ---------- */
@@ -1481,7 +1474,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
struct cx88_core *core = dev->core;
if (video_debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
@@ -1740,6 +1733,7 @@ static struct file_operations video_fops =
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -1767,6 +1761,7 @@ static struct file_operations radio_fops =
.open = video_open,
.release = video_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -1813,10 +1808,9 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
struct cx88_core *core;
int err;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
return -ENOMEM;
- memset(dev,0,sizeof(*dev));
/* pci init */
dev->pci = pci_dev;
@@ -1928,8 +1922,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
/* initial device configuration */
down(&core->lock);
- init_controls(core);
cx88_set_tvnorm(core,tvnorms);
+ init_controls(core);
video_mux(core,0);
up(&core->lock);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
new file mode 100644
index 000000000000..751a754a45e9
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -0,0 +1,177 @@
+/*
+
+ cx88-vp3054-i2c.c -- support for the secondary I2C bus of the
+ DNTV Live! DVB-T Pro (VP-3054), wired as:
+ GPIO[0] -> SCL, GPIO[1] -> SDA
+
+ (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "cx88.h"
+#include "cx88-vp3054-i2c.h"
+
+
+MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_LICENSE("GPL");
+
+/* ----------------------------------------------------------------------- */
+
+static void vp3054_bit_setscl(void *data, int state)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+ if (state) {
+ vp3054_i2c->state |= 0x0001; /* SCL high */
+ vp3054_i2c->state &= ~0x0100; /* external pullup */
+ } else {
+ vp3054_i2c->state &= ~0x0001; /* SCL low */
+ vp3054_i2c->state |= 0x0100; /* drive pin */
+ }
+ cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
+ cx_read(MO_GP0_IO);
+}
+
+static void vp3054_bit_setsda(void *data, int state)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+ if (state) {
+ vp3054_i2c->state |= 0x0002; /* SDA high */
+ vp3054_i2c->state &= ~0x0200; /* tristate pin */
+ } else {
+ vp3054_i2c->state &= ~0x0002; /* SDA low */
+ vp3054_i2c->state |= 0x0200; /* drive pin */
+ }
+ cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
+ cx_read(MO_GP0_IO);
+}
+
+static int vp3054_bit_getscl(void *data)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ u32 state;
+
+ state = cx_read(MO_GP0_IO);
+ return (state & 0x01) ? 1 : 0;
+}
+
+static int vp3054_bit_getsda(void *data)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ u32 state;
+
+ state = cx_read(MO_GP0_IO);
+ return (state & 0x02) ? 1 : 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
+ .setsda = vp3054_bit_setsda,
+ .setscl = vp3054_bit_setscl,
+ .getsda = vp3054_bit_getsda,
+ .getscl = vp3054_bit_getscl,
+ .udelay = 16,
+ .mdelay = 10,
+ .timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter vp3054_i2c_adap_template = {
+ .name = "cx2388x",
+ .owner = THIS_MODULE,
+ .id = I2C_HW_B_CX2388x,
+};
+
+static struct i2c_client vp3054_i2c_client_template = {
+ .name = "VP-3054",
+};
+
+int vp3054_i2c_probe(struct cx8802_dev *dev)
+{
+ struct cx88_core *core = dev->core;
+ struct vp3054_i2c_state *vp3054_i2c;
+ int rc;
+
+ if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+ return 0;
+
+ dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
+ if (dev->card_priv == NULL)
+ return -ENOMEM;
+ vp3054_i2c = dev->card_priv;
+
+ memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template,
+ sizeof(vp3054_i2c->adap));
+ memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
+ sizeof(vp3054_i2c->algo));
+ memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template,
+ sizeof(vp3054_i2c->client));
+
+ vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL;
+
+ vp3054_i2c->adap.dev.parent = &dev->pci->dev;
+ strlcpy(vp3054_i2c->adap.name, core->name,
+ sizeof(vp3054_i2c->adap.name));
+ vp3054_i2c->algo.data = dev;
+ i2c_set_adapdata(&vp3054_i2c->adap, dev);
+ vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
+ vp3054_i2c->client.adapter = &vp3054_i2c->adap;
+
+ vp3054_bit_setscl(dev,1);
+ vp3054_bit_setsda(dev,1);
+
+ rc = i2c_bit_add_bus(&vp3054_i2c->adap);
+ if (0 != rc) {
+ printk("%s: vp3054_i2c register FAILED\n", core->name);
+
+ kfree(dev->card_priv);
+ dev->card_priv = NULL;
+ }
+
+ return rc;
+}
+
+void vp3054_i2c_remove(struct cx8802_dev *dev)
+{
+ struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+ if (vp3054_i2c == NULL ||
+ dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+ return;
+
+ i2c_bit_del_bus(&vp3054_i2c->adap);
+ kfree(vp3054_i2c);
+}
+
+EXPORT_SYMBOL(vp3054_i2c_probe);
+EXPORT_SYMBOL(vp3054_i2c_remove);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h
new file mode 100644
index 000000000000..b7a0a04d2423
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h
@@ -0,0 +1,35 @@
+/*
+
+ cx88-vp3054-i2c.h -- support for the secondary I2C bus of the
+ DNTV Live! DVB-T Pro (VP-3054), wired as:
+ GPIO[0] -> SCL, GPIO[1] -> SDA
+
+ (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+ This program is free software; you can redistribute 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.
+
+*/
+
+/* ----------------------------------------------------------------------- */
+struct vp3054_i2c_state {
+ struct i2c_adapter adap;
+ struct i2c_algo_bit_data algo;
+ struct i2c_client client;
+ u32 state;
+};
+
+/* ----------------------------------------------------------------------- */
+int vp3054_i2c_probe(struct cx8802_dev *dev);
+void vp3054_i2c_remove(struct cx8802_dev *dev);
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 77beafc5c327..e9fd55b57fa6 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -179,6 +179,14 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_ATI_HDTVWONDER 34
#define CX88_BOARD_WINFAST_DTV1000 35
#define CX88_BOARD_AVERTV_303 36
+#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37
+#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38
+#define CX88_BOARD_KWORLD_DVBS_100 39
+#define CX88_BOARD_HAUPPAUGE_HVR1100 40
+#define CX88_BOARD_HAUPPAUGE_HVR1100LP 41
+#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42
+#define CX88_BOARD_KWORLD_DVB_T_CX22702 43
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -280,6 +288,9 @@ struct cx88_core {
unsigned int tda9887_conf;
unsigned int has_radio;
+ /* Supported V4L _STD_ tuner formats */
+ unsigned int tuner_formats;
+
/* config info -- dvb */
struct dvb_pll_desc *pll_desc;
unsigned int pll_addr;
@@ -301,6 +312,9 @@ struct cx88_core {
/* various v4l controls */
u32 freq;
+
+ /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
+ struct cx8802_dev *dvbdev;
};
struct cx8800_dev;
@@ -411,6 +425,8 @@ struct cx8802_dev {
struct videobuf_dvb dvb;
void* fe_handle;
int (*fe_release)(void *handle);
+
+ void *card_priv;
/* for switching modulation types */
unsigned char ts_gen_cntrl;
@@ -447,7 +463,6 @@ struct cx8802_dev {
extern void cx88_print_irqbits(char *name, char *tag, char **strings,
u32 bits, u32 mask);
-extern void cx88_print_ioctl(char *name, unsigned int cmd);
extern int cx88_core_irq(struct cx88_core *core, u32 status);
extern void cx88_wakeup(struct cx88_core *core,
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
index da9481198c53..2831bdd12057 100644
--- a/drivers/media/video/dpc7146.c
+++ b/drivers/media/video/dpc7146.c
@@ -94,12 +94,11 @@ static int dpc_probe(struct saa7146_dev* dev)
struct i2c_client *client;
struct list_head *item;
- dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL);
+ dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
if( NULL == dpc ) {
printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
return -ENOMEM;
}
- memset(dpc, 0x0, sizeof(struct dpc));
/* FIXME: enable i2c-port pins, video-port-pins
video port pins should be enabled here ?! */
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 57779e63f35d..58f7b4194a0d 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -30,6 +30,7 @@
#include <media/tuner.h>
#include <media/audiochip.h>
#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
#include "msp3400.h"
#include "em28xx.h"
@@ -261,7 +262,6 @@ void em28xx_card_setup(struct em28xx *dev)
/* request some modules */
if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) {
struct tveeprom tv;
- struct v4l2_audioout ao;
#ifdef CONFIG_MODULES
request_module("tveeprom");
request_module("ir-kbd-i2c");
@@ -274,12 +274,8 @@ void em28xx_card_setup(struct em28xx *dev)
dev->tuner_type= tv.tuner_type;
if (tv.audio_processor == AUDIO_CHIP_MSP34XX) {
+ dev->i2s_speed=2048000;
dev->has_msp34xx=1;
- memset (&ao,0,sizeof(ao));
-
- ao.index=2;
- ao.mode=V4L2_AUDMODE_32BITS;
- em28xx_i2c_call_clients(dev, VIDIOC_S_AUDOUT, &ao);
} else
dev->has_msp34xx=0;
}
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 0cfe75416ec6..dff3893f32fd 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -32,7 +32,7 @@
/* #define ENABLE_DEBUG_ISOC_FRAMES */
-static unsigned int core_debug;
+static unsigned int core_debug = 0;
module_param(core_debug,int,0644);
MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
printk(KERN_INFO "%s %s :"fmt, \
dev->name, __FUNCTION__ , ##arg); } while (0)
-static unsigned int reg_debug;
+static unsigned int reg_debug = 0;
module_param(reg_debug,int,0644);
MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
@@ -50,7 +50,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
printk(KERN_INFO "%s %s :"fmt, \
dev->name, __FUNCTION__ , ##arg); } while (0)
-static unsigned int isoc_debug;
+static unsigned int isoc_debug = 0;
module_param(isoc_debug,int,0644);
MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
@@ -63,59 +63,6 @@ static int alt = EM28XX_PINOUT;
module_param(alt, int, 0644);
MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
-/* ------------------------------------------------------------------ */
-/* debug help functions */
-
-static const char *v4l1_ioctls[] = {
- "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
- "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
- "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
- "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
- "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
- "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
- "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
- "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
- "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
- "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
- "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void em28xx_print_ioctl(char *name, unsigned int cmd)
-{
- char *dir;
-
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "??"; break;
- }
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "???");
- break;
- default:
- printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- }
-}
-
/*
* em28xx_request_buffers()
@@ -126,7 +73,7 @@ u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
void *buff = NULL;
u32 i;
- em28xx_coredbg("requested %i buffers with size %zd", count, imagesize);
+ em28xx_coredbg("requested %i buffers with size %zi", count, imagesize);
if (count > EM28XX_NUM_FRAMES)
count = EM28XX_NUM_FRAMES;
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index d14bcf4ceaea..0591a705b7a1 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -28,6 +28,7 @@
#include <linux/video_decoder.h>
#include "em28xx.h"
+#include <media/v4l2-common.h>
#include <media/tuner.h>
/* ----------------------------------------------------------- */
@@ -486,9 +487,7 @@ static struct i2c_adapter em28xx_adap_template = {
.inc_use = inc_use,
.dec_use = dec_use,
#endif
-#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
-#endif
.name = "em28xx",
.id = I2C_HW_B_EM28XX,
.algo = &em28xx_algo,
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 9b94f77d6fd7..30dfa5370c73 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -76,6 +76,58 @@ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
[ 0x40 ] = KEY_ZOOM,
};
+static IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
+ [ 0x3a ] = KEY_KP0,
+ [ 0x31 ] = KEY_KP1,
+ [ 0x32 ] = KEY_KP2,
+ [ 0x33 ] = KEY_KP3,
+ [ 0x34 ] = KEY_KP4,
+ [ 0x35 ] = KEY_KP5,
+ [ 0x36 ] = KEY_KP6,
+ [ 0x37 ] = KEY_KP7,
+ [ 0x38 ] = KEY_KP8,
+ [ 0x39 ] = KEY_KP9,
+
+ [ 0x2f ] = KEY_POWER,
+
+ [ 0x2e ] = KEY_P,
+ [ 0x1f ] = KEY_L,
+ [ 0x2b ] = KEY_I,
+
+ [ 0x2d ] = KEY_ZOOM,
+ [ 0x1e ] = KEY_ZOOM,
+ [ 0x1b ] = KEY_VOLUMEUP,
+ [ 0x0f ] = KEY_VOLUMEDOWN,
+ [ 0x17 ] = KEY_CHANNELUP,
+ [ 0x1c ] = KEY_CHANNELDOWN,
+ [ 0x25 ] = KEY_INFO,
+
+ [ 0x3c ] = KEY_MUTE,
+
+ [ 0x3d ] = KEY_LEFT,
+ [ 0x3b ] = KEY_RIGHT,
+
+ [ 0x3f ] = KEY_UP,
+ [ 0x3e ] = KEY_DOWN,
+ [ 0x1a ] = KEY_PAUSE,
+
+ [ 0x1d ] = KEY_MENU,
+ [ 0x19 ] = KEY_PLAY,
+ [ 0x16 ] = KEY_REWIND,
+ [ 0x13 ] = KEY_FORWARD,
+ [ 0x15 ] = KEY_PAUSE,
+ [ 0x0e ] = KEY_REWIND,
+ [ 0x0d ] = KEY_PLAY,
+ [ 0x0b ] = KEY_STOP,
+ [ 0x07 ] = KEY_FORWARD,
+ [ 0x27 ] = KEY_RECORD,
+ [ 0x26 ] = KEY_TUNER,
+ [ 0x29 ] = KEY_TEXT,
+ [ 0x2a ] = KEY_MEDIA,
+ [ 0x18 ] = KEY_EPG,
+ [ 0x27 ] = KEY_RECORD,
+};
+
/* ----------------------------------------------------------------------- */
static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
@@ -138,6 +190,28 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char buf[3];
+
+ /* poll IR chip */
+
+ if (3 != i2c_master_recv(&ir->c,buf,3)) {
+ dprintk("read error\n");
+ return -EIO;
+ }
+
+ dprintk("key %02x\n", buf[2]&0x3f);
+ if (buf[0]!=0x00){
+ return 0;
+ }
+
+ *ir_key = buf[2]&0x3f;
+ *ir_raw = buf[2]&0x3f;
+
+ return 1;
+}
+
/* ----------------------------------------------------------------------- */
void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
{
@@ -159,6 +233,9 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
break;
case (EM2820_BOARD_PINNACLE_USB_2):
+ ir->ir_codes = ir_codes_em_pinnacle_usb;
+ ir->get_key = get_key_pinnacle_usb;
+ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
ir->ir_codes = ir_codes_hauppauge_new;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 3a56120397ae..eea304f75176 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -29,9 +29,11 @@
#include <linux/i2c.h>
#include <linux/version.h>
#include <linux/video_decoder.h>
+#include <linux/mutex.h>
#include "em28xx.h"
#include <media/tuner.h>
+#include <media/v4l2-common.h>
#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
"Markus Rechberger <mrechberger@gmail.com>, " \
@@ -106,8 +108,32 @@ static const unsigned char saa7114_i2c_init[] = {
#define TVNORMS ARRAY_SIZE(tvnorms)
/* supported controls */
+/* Common to all boards */
static struct v4l2_queryctrl em28xx_qctrl[] = {
{
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Volume",
+ .minimum = 0x0,
+ .maximum = 0x1f,
+ .step = 0x1,
+ .default_value = 0x1f,
+ .flags = 0,
+ },{
+ .id = V4L2_CID_AUDIO_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ }
+};
+
+/* FIXME: These are specific to saa711x - should be moved to its code */
+static struct v4l2_queryctrl saa711x_qctrl[] = {
+ {
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
@@ -135,24 +161,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
.default_value = 0x10,
.flags = 0,
},{
- .id = V4L2_CID_AUDIO_VOLUME,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Volume",
- .minimum = 0x0,
- .maximum = 0x1f,
- .step = 0x1,
- .default_value = 0x1f,
- .flags = 0,
- },{
- .id = V4L2_CID_AUDIO_MUTE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 1,
- .flags = 0,
- },{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red chroma balance",
@@ -179,12 +187,12 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
.step = 0x1,
.default_value = 0x20,
.flags = 0,
- }
+ }
};
static struct usb_driver em28xx_usb_driver;
-static DECLARE_MUTEX(em28xx_sysfs_lock);
+static DEFINE_MUTEX(em28xx_sysfs_lock);
static DECLARE_RWSEM(em28xx_disconnect);
/********************* v4l2 interface ******************************************/
@@ -280,6 +288,8 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
if (dev->has_msp34xx) {
+ if (dev->i2s_speed)
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput);
ainput = EM28XX_AUDIO_SRC_TUNER;
em28xx_audio_source(dev, ainput);
@@ -385,7 +395,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
*/
static void em28xx_release_resources(struct em28xx *dev)
{
- down(&em28xx_sysfs_lock);
+ mutex_lock(&em28xx_sysfs_lock);
em28xx_info("V4L2 device /dev/video%d deregistered\n",
dev->vdev->minor);
@@ -394,7 +404,7 @@ static void em28xx_release_resources(struct em28xx *dev)
/* video_unregister_device(dev->vbi_dev); */
em28xx_i2c_unregister(dev);
usb_put_dev(dev->udev);
- up(&em28xx_sysfs_lock);
+ mutex_unlock(&em28xx_sysfs_lock);
}
/*
@@ -674,7 +684,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
*/
static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
{
- s32 tmp;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
ctrl->value = dev->mute;
@@ -682,6 +691,16 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
case V4L2_CID_AUDIO_VOLUME:
ctrl->value = dev->volume;
return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*FIXME: should be moved to saa711x */
+static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
+{
+ s32 tmp;
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if ((tmp = em28xx_brightness_get(dev)) < 0)
return -EIO;
@@ -731,6 +750,15 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
case V4L2_CID_AUDIO_VOLUME:
dev->volume = ctrl->value;
return em28xx_audio_analog_set(dev);
+ default:
+ return -EINVAL;
+ }
+}
+
+/*FIXME: should be moved to saa711x */
+static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
+{
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
return em28xx_brightness_set(dev, ctrl->value);
case V4L2_CID_CONTRAST:
@@ -994,14 +1022,34 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
- u8 i, n;
- n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]);
- for (i = 0; i < n; i++)
- if (qc->id && qc->id == em28xx_qctrl[i].id) {
- memcpy(qc, &(em28xx_qctrl[i]),
+ int i, id=qc->id;
+
+ memset(qc,0,sizeof(*qc));
+ qc->id=id;
+
+ if (!dev->has_msp34xx) {
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (qc->id && qc->id == em28xx_qctrl[i].id) {
+ memcpy(qc, &(em28xx_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+ }
+ }
+ if (dev->decoder == EM28XX_TVP5150) {
+ em28xx_i2c_call_clients(dev,cmd,qc);
+ if (qc->type)
+ return 0;
+ else
+ return -EINVAL;
+ }
+ for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {
+ if (qc->id && qc->id == saa711x_qctrl[i].id) {
+ memcpy(qc, &(saa711x_qctrl[i]),
sizeof(*qc));
return 0;
}
+ }
return -EINVAL;
}
@@ -1009,29 +1057,64 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
+ int retval=-EINVAL;
+ if (!dev->has_msp34xx)
+ retval=em28xx_get_ctrl(dev, ctrl);
+ if (retval==-EINVAL) {
+ if (dev->decoder == EM28XX_TVP5150) {
+ em28xx_i2c_call_clients(dev,cmd,arg);
+ return 0;
+ }
- return em28xx_get_ctrl(dev, ctrl);
+ return saa711x_get_ctrl(dev, ctrl);
+ } else return retval;
}
- case VIDIOC_S_CTRL_OLD: /* ??? */
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
- u8 i, n;
-
-
- n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]);
- for (i = 0; i < n; i++)
- if (ctrl->id == em28xx_qctrl[i].id) {
- if (ctrl->value <
- em28xx_qctrl[i].minimum
- || ctrl->value >
- em28xx_qctrl[i].maximum)
- return -ERANGE;
+ u8 i;
+
+ if (!dev->has_msp34xx){
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (ctrl->id == em28xx_qctrl[i].id) {
+ if (ctrl->value <
+ em28xx_qctrl[i].minimum
+ || ctrl->value >
+ em28xx_qctrl[i].maximum)
+ return -ERANGE;
+ return em28xx_set_ctrl(dev, ctrl);
+ }
+ }
+ }
- return em28xx_set_ctrl(dev, ctrl);
+ if (dev->decoder == EM28XX_TVP5150) {
+ em28xx_i2c_call_clients(dev,cmd,arg);
+ return 0;
+ } else if (!dev->has_msp34xx) {
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (ctrl->id == em28xx_qctrl[i].id) {
+ if (ctrl->value <
+ em28xx_qctrl[i].minimum
+ || ctrl->value >
+ em28xx_qctrl[i].maximum)
+ return -ERANGE;
+ return em28xx_set_ctrl(dev, ctrl);
+ }
}
+ for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {
+ if (ctrl->id == saa711x_qctrl[i].id) {
+ if (ctrl->value <
+ saa711x_qctrl[i].minimum
+ || ctrl->value >
+ saa711x_qctrl[i].maximum)
+ return -ERANGE;
+ return saa711x_set_ctrl(dev, ctrl);
+ }
+ }
+ }
+
return -EINVAL;
}
@@ -1187,7 +1270,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
return -ENODEV;
if (video_debug > 1)
- em28xx_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
@@ -1564,6 +1647,8 @@ static struct file_operations em28xx_v4l_fops = {
.poll = em28xx_v4l2_poll,
.mmap = em28xx_v4l2_mmap,
.llseek = no_llseek,
+ .compat_ioctl = v4l_compat_ioctl32,
+
};
/******************************** usb interface *****************************************/
@@ -1777,12 +1862,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
}
/* allocate memory for our device state and initialize it */
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n");
return -ENOMEM;
}
- memset(dev, 0, sizeof(*dev));
/* compute alternate max packet sizes */
uif = udev->actconfig->interface[0];
@@ -1848,9 +1932,12 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
struct em28xx *dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
+/*FIXME: IR should be disconnected */
+
if (!dev)
return;
+
down_write(&em28xx_disconnect);
down(&dev->lock);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 5c7a41ce69f3..33de9d846af5 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -1,5 +1,5 @@
/*
- em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+ em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it>
@@ -216,6 +216,8 @@ struct em28xx {
unsigned int has_msp34xx:1;
unsigned int has_tda9887:1;
+ u32 i2s_speed; /* I2S speed for audio digital stream */
+
enum em28xx_decoder decoder;
int tuner_type; /* type of the tuner */
@@ -293,8 +295,6 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir);
/* Provided by em28xx-core.c */
-void em28xx_print_ioctl(char *name, unsigned int cmd);
-
u32 em28xx_request_buffers(struct em28xx *dev, u32 count);
void em28xx_queue_unusedframes(struct em28xx *dev);
void em28xx_release_buffers(struct em28xx *dev);
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index c9b00eafefde..e7bbeb11553d 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -240,12 +240,11 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
DEB_EE((".\n"));
- hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
+ hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
return -ENOMEM;
}
- memset(hexium, 0x0, sizeof(struct hexium));
dev->ext_priv = hexium;
/* enable i2c-port pins */
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 42a9414155c3..0b6c2096ec66 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -224,12 +224,11 @@ static int hexium_probe(struct saa7146_dev *dev)
return -EFAULT;
}
- hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
+ hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
return -ENOMEM;
}
- memset(hexium, 0x0, sizeof(struct hexium));
/* enable i2c-port pins */
saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index bb5cbecffcc3..7420b79e987a 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -289,18 +289,15 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
printk(KERN_INFO "SGI IndyCam driver version %s\n",
INDYCAM_MODULE_VERSION);
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- camera = kmalloc(sizeof(struct indycam), GFP_KERNEL);
+ camera = kzalloc(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;
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 3cc1d6a6019b..58b0e6982822 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -279,7 +279,7 @@ static int ir_probe(struct i2c_adapter *adap);
static struct i2c_driver driver = {
.driver = {
- .name = "ir remote kbd driver",
+ .name = "ir-kbd-i2c",
},
.id = I2C_DRIVERID_INFRARED,
.attach_adapter = ir_probe,
@@ -304,18 +304,20 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
- kfree(ir);
input_free_device(input_dev);
+ kfree(ir);
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;
ir->c.addr = addr;
+ i2c_set_clientdata(&ir->c, ir);
+
switch(addr) {
case 0x64:
name = "Pixelview";
@@ -378,13 +380,15 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir->c.dev.bus_id);
/* init + register input device */
- 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;
+ ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->name = ir->c.name;
+ input_dev->phys = ir->phys;
/* register event device */
input_register_device(ir->input);
+ printk(DEVNAME ": %s detected at %s [%s]\n",
+ ir->input->name,ir->input->phys,adap->name);
/* start polling via eventd */
INIT_WORK(&ir->work, ir_work, ir);
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 3f2a882bc20a..2869464aee0d 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1754,6 +1754,7 @@ static struct file_operations meye_fops = {
.release = meye_release,
.mmap = meye_mmap,
.ioctl = meye_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.poll = meye_poll,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
new file mode 100644
index 000000000000..69ed369c2f48
--- /dev/null
+++ b/drivers/media/video/msp3400-driver.c
@@ -0,0 +1,1274 @@
+/*
+ * Programming the mspx4xx sound processor family
+ *
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * what works and what doesn't:
+ *
+ * AM-Mono
+ * Support for Hauppauge cards added (decoding handled by tuner) added by
+ * Frederic Crozat <fcrozat@mail.dotcom.fr>
+ *
+ * FM-Mono
+ * should work. The stereo modes are backward compatible to FM-mono,
+ * therefore FM-Mono should be allways available.
+ *
+ * FM-Stereo (B/G, used in germany)
+ * should work, with autodetect
+ *
+ * FM-Stereo (satellite)
+ * should work, no autodetect (i.e. default is mono, but you can
+ * switch to stereo -- untested)
+ *
+ * NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
+ * should work, with autodetect. Support for NICAM was added by
+ * Pekka Pietikainen <pp@netppl.fi>
+ *
+ * TODO:
+ * - better SAT support
+ *
+ * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * using soundcore instead of OSS
+ *
+ * This program is free software; you can redistribute 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/audiochip.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
+#include "msp3400.h"
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+/* module parameters */
+static int opmode = OPMODE_AUTO;
+int msp_debug; /* msp_debug output */
+int msp_once; /* no continous stereo monitoring */
+int msp_amsound; /* hard-wire AM sound at 6.5 Hz (france),
+ the autoscan seems work well only with FM... */
+int msp_standard = 1; /* Override auto detect of audio msp_standard, if needed. */
+int msp_dolby;
+
+int msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual
+ (msp34xxg only) 0x00a0-0x03c0 */
+
+/* read-only */
+module_param(opmode, int, 0444);
+
+/* read-write */
+module_param_named(once,msp_once, bool, 0644);
+module_param_named(debug,msp_debug, int, 0644);
+module_param_named(stereo_threshold,msp_stereo_thresh, int, 0644);
+module_param_named(standard,msp_standard, int, 0644);
+module_param_named(amsound,msp_amsound, bool, 0644);
+module_param_named(dolby,msp_dolby, bool, 0644);
+
+MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Autodetect, 2=Autodetect and autoselect");
+MODULE_PARM_DESC(once, "No continuous stereo monitoring");
+MODULE_PARM_DESC(debug, "Enable debug messages [0-3]");
+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");
+
+/* ---------------------------------------------------------------------- */
+
+/* control subaddress */
+#define I2C_MSP_CONTROL 0x00
+/* demodulator unit subaddress */
+#define I2C_MSP_DEM 0x10
+/* DSP unit subaddress */
+#define I2C_MSP_DSP 0x12
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END };
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+/* functions for talking to the MSP3400C Sound processor */
+
+int msp_reset(struct i2c_client *client)
+{
+ /* reset and read revision code */
+ static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 };
+ static u8 reset_on[3] = { I2C_MSP_CONTROL, 0x00, 0x00 };
+ static u8 write[3] = { I2C_MSP_DSP + 1, 0x00, 0x1e };
+ u8 read[2];
+ struct i2c_msg reset[2] = {
+ { client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
+ { client->addr, I2C_M_IGNORE_NAK, 3, reset_on },
+ };
+ struct i2c_msg test[2] = {
+ { client->addr, 0, 3, write },
+ { client->addr, I2C_M_RD, 2, read },
+ };
+
+ v4l_dbg(3, msp_debug, client, "msp_reset\n");
+ if (i2c_transfer(client->adapter, &reset[0], 1) != 1 ||
+ i2c_transfer(client->adapter, &reset[1], 1) != 1 ||
+ i2c_transfer(client->adapter, test, 2) != 2) {
+ v4l_err(client, "chip reset failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int msp_read(struct i2c_client *client, int dev, int addr)
+{
+ int err, retval;
+ u8 write[3];
+ u8 read[2];
+ struct i2c_msg msgs[2] = {
+ { client->addr, 0, 3, write },
+ { client->addr, I2C_M_RD, 2, read }
+ };
+
+ write[0] = dev + 1;
+ write[1] = addr >> 8;
+ write[2] = addr & 0xff;
+
+ for (err = 0; err < 3; err++) {
+ if (i2c_transfer(client->adapter, msgs, 2) == 2)
+ break;
+ v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
+ dev, addr);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(msecs_to_jiffies(10));
+ }
+ if (err == 3) {
+ v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
+ msp_reset(client);
+ return -1;
+ }
+ retval = read[0] << 8 | read[1];
+ v4l_dbg(3, msp_debug, client, "msp_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval);
+ return retval;
+}
+
+int msp_read_dem(struct i2c_client *client, int addr)
+{
+ return msp_read(client, I2C_MSP_DEM, addr);
+}
+
+int msp_read_dsp(struct i2c_client *client, int addr)
+{
+ return msp_read(client, I2C_MSP_DSP, addr);
+}
+
+static int msp_write(struct i2c_client *client, int dev, int addr, int val)
+{
+ int err;
+ u8 buffer[5];
+
+ buffer[0] = dev;
+ buffer[1] = addr >> 8;
+ buffer[2] = addr & 0xff;
+ buffer[3] = val >> 8;
+ buffer[4] = val & 0xff;
+
+ v4l_dbg(3, msp_debug, client, "msp_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val);
+ for (err = 0; err < 3; err++) {
+ if (i2c_master_send(client, buffer, 5) == 5)
+ break;
+ v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
+ dev, addr);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(msecs_to_jiffies(10));
+ }
+ if (err == 3) {
+ v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
+ msp_reset(client);
+ return -1;
+ }
+ return 0;
+}
+
+int msp_write_dem(struct i2c_client *client, int addr, int val)
+{
+ return msp_write(client, I2C_MSP_DEM, addr, val);
+}
+
+int msp_write_dsp(struct i2c_client *client, int addr, int val)
+{
+ return msp_write(client, I2C_MSP_DSP, addr, val);
+}
+
+/* ----------------------------------------------------------------------- *
+ * bits 9 8 5 - SCART DSP input Select:
+ * 0 0 0 - SCART 1 to DSP input (reset position)
+ * 0 1 0 - MONO to DSP input
+ * 1 0 0 - SCART 2 to DSP input
+ * 1 1 1 - Mute DSP input
+ *
+ * bits 11 10 6 - SCART 1 Output Select:
+ * 0 0 0 - undefined (reset position)
+ * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS)
+ * 1 0 0 - MONO input to SCART 1 Output
+ * 1 1 0 - SCART 1 DA to SCART 1 Output
+ * 0 0 1 - SCART 2 DA to SCART 1 Output
+ * 0 1 1 - SCART 1 Input to SCART 1 Output
+ * 1 1 1 - Mute SCART 1 Output
+ *
+ * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART):
+ * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position)
+ * 0 1 0 - SCART 1 Input to SCART 2 Output
+ * 1 0 0 - MONO input to SCART 2 Output
+ * 0 0 1 - SCART 2 DA to SCART 2 Output
+ * 0 1 1 - SCART 2 Input to SCART 2 Output
+ * 1 1 0 - Mute SCART 2 Output
+ *
+ * Bits 4 to 0 should be zero.
+ * ----------------------------------------------------------------------- */
+
+static int scarts[3][9] = {
+ /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */
+ /* SCART DSP Input select */
+ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 },
+ /* SCART1 Output select */
+ { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
+ /* SCART2 Output select */
+ { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
+};
+
+static char *scart_names[] = {
+ "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute"
+};
+
+void msp_set_scart(struct i2c_client *client, int in, int out)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ state->in_scart=in;
+
+ if (in >= 1 && in <= 8 && out >= 0 && out <= 2) {
+ if (-1 == scarts[out][in])
+ return;
+
+ state->acb &= ~scarts[out][SCART_MASK];
+ state->acb |= scarts[out][in];
+ } else
+ state->acb = 0xf60; /* Mute Input and SCART 1 Output */
+
+ v4l_dbg(1, msp_debug, client, "scart switch: %s => %d (ACB=0x%04x)\n",
+ scart_names[in], out, state->acb);
+ msp_write_dsp(client, 0x13, state->acb);
+
+ /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
+ msp_write_dem(client, 0x40, state->i2s_mode);
+}
+
+void msp_set_mute(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ v4l_dbg(1, msp_debug, client, "mute audio\n");
+ msp_write_dsp(client, 0x0000, 0);
+ msp_write_dsp(client, 0x0007, 1);
+ if (state->has_scart2_out_volume)
+ msp_write_dsp(client, 0x0040, 1);
+ if (state->has_headphones)
+ msp_write_dsp(client, 0x0006, 0);
+}
+
+void msp_set_audio(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int bal = 0, bass, treble, loudness;
+ int val = 0;
+
+ if (!state->muted)
+ val = (state->volume * 0x7f / 65535) << 8;
+
+ v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n",
+ state->muted ? "on" : "off", state->volume);
+
+ msp_write_dsp(client, 0x0000, val);
+ msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
+ if (state->has_scart2_out_volume)
+ msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
+ if (state->has_headphones)
+ msp_write_dsp(client, 0x0006, val);
+ if (!state->has_sound_processing)
+ return;
+
+ if (val)
+ bal = (u8)((state->balance / 256) - 128);
+ bass = ((state->bass - 32768) * 0x60 / 65535) << 8;
+ treble = ((state->treble - 32768) * 0x60 / 65535) << 8;
+ loudness = state->loudness ? ((5 * 4) << 8) : 0;
+
+ v4l_dbg(1, msp_debug, client, "balance=%d bass=%d treble=%d loudness=%d\n",
+ state->balance, state->bass, state->treble, state->loudness);
+
+ msp_write_dsp(client, 0x0001, bal << 8);
+ msp_write_dsp(client, 0x0002, bass);
+ msp_write_dsp(client, 0x0003, treble);
+ msp_write_dsp(client, 0x0004, loudness);
+ if (!state->has_headphones)
+ return;
+ msp_write_dsp(client, 0x0030, bal << 8);
+ msp_write_dsp(client, 0x0031, bass);
+ msp_write_dsp(client, 0x0032, treble);
+ msp_write_dsp(client, 0x0033, loudness);
+}
+
+int msp_modus(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (state->radio) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to Radio\n");
+ return 0x0003;
+ }
+
+ if (state->v4l2_std & V4L2_STD_PAL) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to PAL\n");
+
+#if 1
+ /* experimental: not sure this works with all chip versions */
+ return 0x7003;
+#else
+ /* previous value, try this if it breaks ... */
+ return 0x1003;
+#endif
+ }
+ if (state->v4l2_std & V4L2_STD_NTSC) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to NTSC\n");
+ return 0x2003;
+ }
+ if (state->v4l2_std & V4L2_STD_SECAM) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to SECAM\n");
+ return 0x0003;
+ }
+ return 0x0003;
+}
+
+/* ------------------------------------------------------------------------ */
+
+
+static void msp_wake_thread(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (NULL == state->kthread)
+ return;
+ msp_set_mute(client);
+ state->watch_stereo = 0;
+ state->restart = 1;
+ wake_up_interruptible(&state->wq);
+}
+
+int msp_sleep(struct msp_state *state, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&state->wq, &wait);
+ if (!kthread_should_stop()) {
+ if (timeout < 0) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ } else {
+ schedule_timeout_interruptible
+ (msecs_to_jiffies(timeout));
+ }
+ }
+
+ remove_wait_queue(&state->wq, &wait);
+ try_to_freeze();
+ return state->restart;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int msp_mode_v4l2_to_v4l1(int rxsubchans)
+{
+ int mode = 0;
+
+ if (rxsubchans & V4L2_TUNER_SUB_STEREO)
+ mode |= VIDEO_SOUND_STEREO;
+ if (rxsubchans & V4L2_TUNER_SUB_LANG2)
+ mode |= VIDEO_SOUND_LANG2;
+ if (rxsubchans & V4L2_TUNER_SUB_LANG1)
+ mode |= VIDEO_SOUND_LANG1;
+ if (mode == 0)
+ mode |= VIDEO_SOUND_MONO;
+ return mode;
+}
+
+static int msp_mode_v4l1_to_v4l2(int mode)
+{
+ if (mode & VIDEO_SOUND_STEREO)
+ return V4L2_TUNER_MODE_STEREO;
+ if (mode & VIDEO_SOUND_LANG2)
+ return V4L2_TUNER_MODE_LANG2;
+ if (mode & VIDEO_SOUND_LANG1)
+ return V4L2_TUNER_MODE_LANG1;
+ return V4L2_TUNER_MODE_MONO;
+}
+
+static void msp_any_detect_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ case OPMODE_AUTODETECT:
+ autodetect_stereo(client);
+ break;
+ case OPMODE_AUTOSELECT:
+ msp34xxg_detect_stereo(client);
+ break;
+ }
+}
+
+static struct v4l2_queryctrl msp_qctrl_std[] = {
+ {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 58880,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+};
+
+static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
+ {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_BASS,
+ .name = "Bass",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .name = "Treble",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_LOUDNESS,
+ .name = "Loudness",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+};
+
+
+static void msp_any_set_audmode(struct i2c_client *client, int audmode)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ case OPMODE_AUTODETECT:
+ state->watch_stereo = 0;
+ msp3400c_setstereo(client, audmode);
+ break;
+ case OPMODE_AUTOSELECT:
+ msp34xxg_set_audmode(client, audmode);
+ break;
+ }
+}
+
+static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = state->volume;
+ break;
+
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = state->muted;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->balance;
+ break;
+
+ case V4L2_CID_AUDIO_BASS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->bass;
+ break;
+
+ case V4L2_CID_AUDIO_TREBLE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->treble;
+ break;
+
+ case V4L2_CID_AUDIO_LOUDNESS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->loudness;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ state->volume = ctrl->value;
+ if (state->volume == 0)
+ state->balance = 32768;
+ break;
+
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value < 0 || ctrl->value >= 2)
+ return -ERANGE;
+ state->muted = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_BASS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->bass = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_TREBLE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->treble = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_LOUDNESS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->loudness = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->balance = ctrl->value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ msp_set_audio(client);
+ return 0;
+}
+
+static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ u16 *sarg = arg;
+ int scart = 0;
+
+ if (msp_debug >= 2)
+ v4l_i2c_print_ioctl(client, cmd);
+
+ switch (cmd) {
+ case AUDC_SET_INPUT:
+ if (*sarg == state->input)
+ break;
+ state->input = *sarg;
+ switch (*sarg) {
+ case AUDIO_RADIO:
+ /* Hauppauge uses IN2 for the radio */
+ state->mode = MSP_MODE_FM_RADIO;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_EXTERN_1:
+ /* IN1 is often used for external input ... */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN1;
+ break;
+ case AUDIO_EXTERN_2:
+ /* ... sometimes it is IN2 through ;) */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_TUNER:
+ state->mode = -1;
+ break;
+ default:
+ if (*sarg & AUDIO_MUTE)
+ msp_set_scart(client, SCART_MUTE, 0);
+ break;
+ }
+ if (scart) {
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ msp_set_scart(client, scart, 0);
+ msp_write_dsp(client, 0x000d, 0x1900);
+ if (state->opmode != OPMODE_AUTOSELECT)
+ msp3400c_setstereo(client, state->audmode);
+ }
+ msp_wake_thread(client);
+ break;
+
+ case AUDC_SET_RADIO:
+ if (state->radio)
+ return 0;
+ state->radio = 1;
+ v4l_dbg(1, msp_debug, client, "switching to radio mode\n");
+ state->watch_stereo = 0;
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ /* set msp3400 to FM radio mode */
+ msp3400c_setmode(client, MSP_MODE_FM_RADIO);
+ msp3400c_setcarrier(client, MSP_CARRIER(10.7),
+ MSP_CARRIER(10.7));
+ msp_set_audio(client);
+ break;
+ case OPMODE_AUTODETECT:
+ case OPMODE_AUTOSELECT:
+ /* the thread will do for us */
+ msp_wake_thread(client);
+ break;
+ }
+ break;
+
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *va = arg;
+
+ va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;
+ if (state->has_sound_processing)
+ va->flags |= VIDEO_AUDIO_BALANCE |
+ VIDEO_AUDIO_BASS |
+ VIDEO_AUDIO_TREBLE;
+ if (state->muted)
+ va->flags |= VIDEO_AUDIO_MUTE;
+ va->volume = state->volume;
+ va->balance = state->volume ? state->balance : 32768;
+ va->bass = state->bass;
+ va->treble = state->treble;
+
+ if (state->radio)
+ break;
+ if (state->opmode == OPMODE_AUTOSELECT)
+ msp_any_detect_stereo(client);
+ va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
+ break;
+ }
+
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio *va = arg;
+
+ state->muted = (va->flags & VIDEO_AUDIO_MUTE);
+ state->volume = va->volume;
+ state->balance = va->balance;
+ state->bass = va->bass;
+ state->treble = va->treble;
+ msp_set_audio(client);
+
+ if (va->mode != 0 && state->radio == 0)
+ msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode));
+ break;
+ }
+
+ case VIDIOCSCHAN:
+ {
+ struct video_channel *vc = arg;
+ int update = 0;
+ v4l2_std_id std;
+
+ if (state->radio)
+ update = 1;
+ state->radio = 0;
+ if (vc->norm == VIDEO_MODE_PAL)
+ std = V4L2_STD_PAL;
+ else if (vc->norm == VIDEO_MODE_SECAM)
+ std = V4L2_STD_SECAM;
+ else
+ std = V4L2_STD_NTSC;
+ if (std != state->v4l2_std) {
+ state->v4l2_std = std;
+ update = 1;
+ }
+ if (update)
+ msp_wake_thread(client);
+ break;
+ }
+
+ case VIDIOCSFREQ:
+ case VIDIOC_S_FREQUENCY:
+ {
+ /* new channel -- kick audio carrier scan */
+ msp_wake_thread(client);
+ break;
+ }
+
+ /* msp34xx specific */
+ case MSP_SET_MATRIX:
+ {
+ struct msp_matrix *mspm = arg;
+
+ msp_set_scart(client, mspm->input, mspm->output);
+ break;
+ }
+
+ /* --- v4l2 ioctls --- */
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ int update = state->radio || state->v4l2_std != *id;
+
+ state->v4l2_std = *id;
+ state->radio = 0;
+ if (update)
+ msp_wake_thread(client);
+ return 0;
+ }
+
+ case VIDIOC_ENUMINPUT:
+ {
+ struct v4l2_input *i = arg;
+
+ if (i->index != 0)
+ return -EINVAL;
+
+ i->type = V4L2_INPUT_TYPE_TUNER;
+ switch (i->index) {
+ case AUDIO_RADIO:
+ strcpy(i->name, "Radio");
+ break;
+ case AUDIO_EXTERN_1:
+ strcpy(i->name, "Extern 1");
+ break;
+ case AUDIO_EXTERN_2:
+ strcpy(i->name, "Extern 2");
+ break;
+ case AUDIO_TUNER:
+ strcpy(i->name, "Television");
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *a = arg;
+
+ memset(a, 0, sizeof(*a));
+
+ switch (a->index) {
+ case AUDIO_RADIO:
+ strcpy(a->name, "Radio");
+ break;
+ case AUDIO_EXTERN_1:
+ strcpy(a->name, "Extern 1");
+ break;
+ case AUDIO_EXTERN_2:
+ strcpy(a->name, "Extern 2");
+ break;
+ case AUDIO_TUNER:
+ strcpy(a->name, "Television");
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ msp_any_detect_stereo(client);
+ if (state->audmode == V4L2_TUNER_MODE_STEREO) {
+ a->capability = V4L2_AUDCAP_STEREO;
+ }
+
+ break;
+ }
+
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *sarg = arg;
+
+ switch (sarg->index) {
+ case AUDIO_RADIO:
+ /* Hauppauge uses IN2 for the radio */
+ state->mode = MSP_MODE_FM_RADIO;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_EXTERN_1:
+ /* IN1 is often used for external input ... */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN1;
+ break;
+ case AUDIO_EXTERN_2:
+ /* ... sometimes it is IN2 through ;) */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_TUNER:
+ state->mode = -1;
+ break;
+ }
+ if (scart) {
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ msp_set_scart(client, scart, 0);
+ msp_write_dsp(client, 0x000d, 0x1900);
+ }
+ if (sarg->capability == V4L2_AUDCAP_STEREO) {
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ } else {
+ state->audmode &= ~V4L2_TUNER_MODE_STEREO;
+ }
+ msp_any_set_audmode(client, state->audmode);
+ msp_wake_thread(client);
+ break;
+ }
+
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *vt = arg;
+
+ if (state->radio)
+ break;
+ if (state->opmode == OPMODE_AUTOSELECT)
+ msp_any_detect_stereo(client);
+ vt->audmode = state->audmode;
+ vt->rxsubchans = state->rxsubchans;
+ vt->capability = V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+ break;
+ }
+
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+
+ if (state->radio)
+ break;
+ /* only set audmode */
+ if (vt->audmode != -1 && vt->audmode != 0)
+ msp_any_set_audmode(client, vt->audmode);
+ break;
+ }
+
+ case VIDIOC_G_AUDOUT:
+ {
+ struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
+ int idx = a->index;
+
+ memset(a, 0, sizeof(*a));
+
+ switch (idx) {
+ case 0:
+ strcpy(a->name, "Scart1 Out");
+ break;
+ case 1:
+ strcpy(a->name, "Scart2 Out");
+ break;
+ case 2:
+ strcpy(a->name, "I2S Out");
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ }
+
+ case VIDIOC_S_AUDOUT:
+ {
+ struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
+
+ if (a->index < 0 || a->index > 2)
+ return -EINVAL;
+
+ v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index);
+ msp_set_scart(client, state->in_scart, a->index + 1);
+
+ break;
+ }
+
+ case VIDIOC_INT_I2S_CLOCK_FREQ:
+ {
+ u32 *a = (u32 *)arg;
+
+ v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", *a);
+
+ switch (*a) {
+ case 1024000:
+ state->i2s_mode = 0;
+ break;
+ case 2048000:
+ state->i2s_mode = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
+ if (qc->id && qc->id == msp_qctrl_std[i].id) {
+ memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
+ return 0;
+ }
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
+ if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
+ memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_G_CTRL:
+ return msp_get_ctrl(client, arg);
+
+ case VIDIOC_S_CTRL:
+ return msp_set_ctrl(client, arg);
+
+ case VIDIOC_LOG_STATUS:
+ {
+ const char *p;
+
+ if (state->opmode == OPMODE_AUTOSELECT)
+ msp_any_detect_stereo(client);
+ v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
+ client->name, state->rev1, state->rev2);
+ v4l_info(client, "Audio: volume %d%s\n",
+ state->volume, state->muted ? " (muted)" : "");
+ if (state->has_sound_processing) {
+ v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n",
+ state->balance, state->bass, state->treble,
+ state->loudness ? "on" : "off");
+ }
+ switch (state->mode) {
+ case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
+ case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
+ case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono + FM-stereo"; break;
+ case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break;
+ case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break;
+ case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break;
+ case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break;
+ case MSP_MODE_BTSC: p = "BTSC"; break;
+ case MSP_MODE_EXTERN: p = "External input"; break;
+ default: p = "unknown"; break;
+ }
+ if (state->opmode == OPMODE_MANUAL) {
+ v4l_info(client, "Mode: %s (%s%s)\n", p,
+ (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
+ (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
+ } else {
+ v4l_info(client, "Mode: %s\n", p);
+ v4l_info(client, "Standard: %s (%s%s)\n",
+ msp_standard_std_name(state->std),
+ (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
+ (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
+ }
+ v4l_info(client, "ACB: 0x%04x\n", state->acb);
+ break;
+ }
+
+ default:
+ /* unknown */
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msp_suspend(struct device * dev, pm_message_t state)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ v4l_dbg(1, msp_debug, client, "suspend\n");
+ msp_reset(client);
+ return 0;
+}
+
+static int msp_resume(struct device * dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ v4l_dbg(1, msp_debug, client, "resume\n");
+ msp_wake_thread(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver i2c_driver;
+
+static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct msp_state *state;
+ int (*thread_func)(void *data) = NULL;
+ int msp_hard;
+ int msp_family;
+ int msp_revision;
+ int msp_product, msp_prod_hi, msp_prod_lo;
+ int msp_rom;
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memset(client, 0, sizeof(*client));
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "msp3400");
+
+ if (msp_reset(client) == -1) {
+ v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
+ kfree(client);
+ return -1;
+ }
+
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, state);
+
+ memset(state, 0, sizeof(*state));
+ state->v4l2_std = V4L2_STD_NTSC;
+ state->volume = 58880; /* 0db gain */
+ state->balance = 32768; /* 0db gain */
+ state->bass = 32768;
+ state->treble = 32768;
+ state->loudness = 0;
+ state->input = -1;
+ state->muted = 0;
+ state->i2s_mode = 0;
+ init_waitqueue_head(&state->wq);
+
+ state->rev1 = msp_read_dsp(client, 0x1e);
+ if (state->rev1 != -1)
+ state->rev2 = msp_read_dsp(client, 0x1f);
+ v4l_dbg(1, msp_debug, client, "rev1=0x%04x, rev2=0x%04x\n", state->rev1, state->rev2);
+ if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) {
+ v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n");
+ kfree(state);
+ kfree(client);
+ return -1;
+ }
+
+ msp_set_audio(client);
+
+ msp_family = ((state->rev1 >> 4) & 0x0f) + 3;
+ msp_product = (state->rev2 >> 8) & 0xff;
+ msp_prod_hi = msp_product / 10;
+ msp_prod_lo = msp_product % 10;
+ msp_revision = (state->rev1 & 0x0f) + '@';
+ msp_hard = ((state->rev1 >> 8) & 0xff) + '@';
+ msp_rom = state->rev2 & 0x1f;
+ snprintf(client->name, sizeof(client->name), "MSP%d4%02d%c-%c%d",
+ msp_family, msp_product,
+ msp_revision, msp_hard, msp_rom);
+
+ /* Has NICAM support: all mspx41x and mspx45x products have NICAM */
+ state->has_nicam = msp_prod_hi == 1 || msp_prod_hi == 5;
+ /* Has radio support: was added with revision G */
+ state->has_radio = msp_revision >= 'G';
+ /* Has headphones output: not for stripped down products */
+ state->has_headphones = msp_prod_lo < 5;
+ /* Has scart4 input: not in pre D revisions, not in stripped D revs */
+ state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
+ /* Has scart2 and scart3 inputs and scart2 output: not in stripped
+ down products of the '3' family */
+ state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
+ /* Has scart2 a volume control? Not in pre-D revisions. */
+ state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
+ /* Has a configurable i2s out? */
+ state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7;
+ /* Has subwoofer output: not in pre-D revs and not in stripped down products */
+ state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5;
+ /* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in
+ stripped down products */
+ state->has_sound_processing = msp_prod_lo < 7;
+ /* Has Virtual Dolby Surround: only in msp34x1 */
+ state->has_virtual_dolby_surround = msp_revision == 'G' && msp_prod_lo == 1;
+ /* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */
+ state->has_dolby_pro_logic = msp_revision == 'G' && msp_prod_lo == 2;
+
+ state->opmode = opmode;
+ if (state->opmode == OPMODE_AUTO) {
+ /* MSP revision G and up have both autodetect and autoselect */
+ if (msp_revision >= 'G')
+ state->opmode = OPMODE_AUTOSELECT;
+ /* MSP revision D and up have autodetect */
+ else if (msp_revision >= 'D')
+ state->opmode = OPMODE_AUTODETECT;
+ else
+ state->opmode = OPMODE_MANUAL;
+ }
+
+ /* hello world :-) */
+ v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, address << 1, adapter->name);
+ v4l_info(client, "%s ", client->name);
+ if (state->has_nicam && state->has_radio)
+ printk("supports nicam and radio, ");
+ else if (state->has_nicam)
+ printk("supports nicam, ");
+ else if (state->has_radio)
+ printk("supports radio, ");
+ printk("mode is ");
+
+ /* version-specific initialization */
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ printk("manual");
+ thread_func = msp3400c_thread;
+ break;
+ case OPMODE_AUTODETECT:
+ printk("autodetect");
+ thread_func = msp3410d_thread;
+ break;
+ case OPMODE_AUTOSELECT:
+ printk("autodetect and autoselect");
+ thread_func = msp34xxg_thread;
+ break;
+ }
+ printk("\n");
+
+ /* startup control thread if needed */
+ if (thread_func) {
+ state->kthread = kthread_run(thread_func, client, "msp34xx");
+
+ if (state->kthread == NULL)
+ v4l_warn(client, "kernel_thread() failed\n");
+ msp_wake_thread(client);
+ }
+
+ /* done */
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int msp_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, msp_attach);
+ return 0;
+}
+
+static int msp_detach(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int err;
+
+ /* shutdown control thread */
+ if (state->kthread) {
+ state->restart = 1;
+ kthread_stop(state->kthread);
+ }
+ msp_reset(client);
+
+ err = i2c_detach_client(client);
+ if (err) {
+ return err;
+ }
+
+ kfree(state);
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .id = I2C_DRIVERID_MSP3400,
+ .attach_adapter = msp_probe,
+ .detach_client = msp_detach,
+ .command = msp_command,
+ .driver = {
+ .name = "msp3400",
+ .suspend = msp_suspend,
+ .resume = msp_resume,
+ },
+};
+
+static int __init msp3400_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit msp3400_cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(msp3400_init_module);
+module_exit(msp3400_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/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
new file mode 100644
index 000000000000..2072c3efebb3
--- /dev/null
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -0,0 +1,1010 @@
+/*
+ * Programming the mspx4xx sound processor family
+ *
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/audiochip.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
+#include "msp3400.h"
+
+/* this one uses the automatic sound standard detection of newer msp34xx
+ chip versions */
+static struct {
+ int retval;
+ int main, second;
+ char *name;
+} msp_stdlist[] = {
+ { 0x0000, 0, 0, "could not detect sound standard" },
+ { 0x0001, 0, 0, "autodetect start" },
+ { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" },
+ { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" },
+ { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
+ { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
+ { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
+ { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
+ { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
+ { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
+ { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
+ { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
+ { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
+ { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
+ { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
+ { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" },
+ { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" },
+ { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" },
+ { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" },
+ { -1, 0, 0, NULL }, /* EOF */
+};
+
+static struct msp3400c_init_data_dem {
+ int fir1[6];
+ int fir2[6];
+ int cdo1;
+ int cdo2;
+ int ad_cv;
+ int mode_reg;
+ int dsp_src;
+ int dsp_matrix;
+} msp3400c_init_data[] = {
+ { /* AM (for carrier detect / msp3400) */
+ {75, 19, 36, 35, 39, 40},
+ {75, 19, 36, 35, 39, 40},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0500, 0x0020, 0x3000
+ },{ /* AM (for carrier detect / msp3410) */
+ {-1, -1, -8, 2, 59, 126},
+ {-1, -1, -8, 2, 59, 126},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0100, 0x0020, 0x3000
+ },{ /* FM Radio */
+ {-8, -8, 4, 6, 78, 107},
+ {-8, -8, 4, 6, 78, 107},
+ MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+ 0x00d0, 0x0480, 0x0020, 0x3000
+ },{ /* Terrestial FM-mono + FM-stereo */
+ {3, 18, 27, 48, 66, 72},
+ {3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0480, 0x0030, 0x3000
+ },{ /* Sat FM-mono */
+ { 1, 9, 14, 24, 33, 37},
+ { 3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+ 0x00c6, 0x0480, 0x0000, 0x3000
+ },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */
+ {-2, -8, -10, 10, 50, 86},
+ {3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0040, 0x0120, 0x3000
+ },{ /* NICAM/FM -- I (6.0/6.552) */
+ {2, 4, -6, -4, 40, 94},
+ {3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(6.0), MSP_CARRIER(6.0),
+ 0x00d0, 0x0040, 0x0120, 0x3000
+ },{ /* NICAM/AM -- L (6.5/5.85) */
+ {-2, -8, -10, 10, 50, 86},
+ {-4, -12, -9, 23, 79, 126},
+ MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+ 0x00c6, 0x0140, 0x0120, 0x7c03
+ },
+};
+
+struct msp3400c_carrier_detect {
+ int cdo;
+ char *name;
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = {
+ /* main carrier */
+ { MSP_CARRIER(4.5), "4.5 NTSC" },
+ { MSP_CARRIER(5.5), "5.5 PAL B/G" },
+ { MSP_CARRIER(6.0), "6.0 PAL I" },
+ { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = {
+ /* PAL B/G */
+ { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
+ { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = {
+ /* PAL SAT / SECAM */
+ { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" },
+ { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
+ { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
+ { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
+ { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
+ { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
+};
+
+/* ------------------------------------------------------------------------ */
+
+const char *msp_standard_std_name(int std)
+{
+ int i;
+
+ for (i = 0; msp_stdlist[i].name != NULL; i++)
+ if (msp_stdlist[i].retval == std)
+ return msp_stdlist[i].name;
+ return "unknown";
+}
+
+void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2)
+{
+ msp_write_dem(client, 0x0093, cdo1 & 0xfff);
+ msp_write_dem(client, 0x009b, cdo1 >> 12);
+ msp_write_dem(client, 0x00a3, cdo2 & 0xfff);
+ msp_write_dem(client, 0x00ab, cdo2 >> 12);
+ msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/
+}
+
+void msp3400c_setmode(struct i2c_client *client, int type)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int i;
+
+ v4l_dbg(1, msp_debug, client, "setmode: %d\n", type);
+ state->mode = type;
+ state->audmode = V4L2_TUNER_MODE_MONO;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+ msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv);
+
+ for (i = 5; i >= 0; i--) /* fir 1 */
+ msp_write_dem(client, 0x0001, msp3400c_init_data[type].fir1[i]);
+
+ msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */
+ msp_write_dem(client, 0x0005, 0x0040);
+ msp_write_dem(client, 0x0005, 0x0000);
+ for (i = 5; i >= 0; i--)
+ msp_write_dem(client, 0x0005, msp3400c_init_data[type].fir2[i]);
+
+ msp_write_dem(client, 0x0083, msp3400c_init_data[type].mode_reg);
+
+ msp3400c_setcarrier(client, msp3400c_init_data[type].cdo1,
+ msp3400c_init_data[type].cdo2);
+
+ msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/
+
+ if (msp_dolby) {
+ msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */
+ msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */
+ msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src);
+ } else {
+ msp_write_dsp(client, 0x0008, msp3400c_init_data[type].dsp_src);
+ msp_write_dsp(client, 0x0009, msp3400c_init_data[type].dsp_src);
+ msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src);
+ }
+ msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src);
+ msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix);
+
+ if (state->has_nicam) {
+ /* nicam prescale */
+ msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */
+ }
+}
+
+/* turn on/off nicam + stereo */
+void msp3400c_setstereo(struct i2c_client *client, int mode)
+{
+ static char *strmode[] = { "mono", "stereo", "lang2", "lang1" };
+ struct msp_state *state = i2c_get_clientdata(client);
+ int nicam = 0; /* channel source: FM/AM or nicam */
+ int src = 0;
+
+ if (state->opmode == OPMODE_AUTOSELECT) {
+ /* this method would break everything, let's make sure
+ * it's never called
+ */
+ v4l_dbg(1, msp_debug, client, "setstereo called with mode=%d instead of set_source (ignored)\n",
+ mode);
+ return;
+ }
+
+ /* switch demodulator */
+ switch (state->mode) {
+ case MSP_MODE_FM_TERRA:
+ v4l_dbg(1, msp_debug, client, "FM setstereo: %s\n", strmode[mode]);
+ msp3400c_setcarrier(client, state->second, state->main);
+ switch (mode) {
+ case V4L2_TUNER_MODE_STEREO:
+ msp_write_dsp(client, 0x000e, 0x3001);
+ break;
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ case V4L2_TUNER_MODE_LANG2:
+ msp_write_dsp(client, 0x000e, 0x3000);
+ break;
+ }
+ break;
+ case MSP_MODE_FM_SAT:
+ v4l_dbg(1, msp_debug, client, "SAT setstereo: %s\n", strmode[mode]);
+ switch (mode) {
+ case V4L2_TUNER_MODE_MONO:
+ msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+ break;
+ }
+ break;
+ case MSP_MODE_FM_NICAM1:
+ case MSP_MODE_FM_NICAM2:
+ case MSP_MODE_AM_NICAM:
+ v4l_dbg(1, msp_debug, client, "NICAM setstereo: %s\n",strmode[mode]);
+ msp3400c_setcarrier(client,state->second,state->main);
+ if (state->nicam_on)
+ nicam=0x0100;
+ break;
+ case MSP_MODE_BTSC:
+ v4l_dbg(1, msp_debug, client, "BTSC setstereo: %s\n",strmode[mode]);
+ nicam=0x0300;
+ break;
+ case MSP_MODE_EXTERN:
+ v4l_dbg(1, msp_debug, client, "extern setstereo: %s\n",strmode[mode]);
+ nicam = 0x0200;
+ break;
+ case MSP_MODE_FM_RADIO:
+ v4l_dbg(1, msp_debug, client, "FM-Radio setstereo: %s\n",strmode[mode]);
+ break;
+ default:
+ v4l_dbg(1, msp_debug, client, "mono setstereo\n");
+ return;
+ }
+
+ /* switch audio */
+ switch (mode) {
+ case V4L2_TUNER_MODE_STEREO:
+ src = 0x0020 | nicam;
+ break;
+ case V4L2_TUNER_MODE_MONO:
+ if (state->mode == MSP_MODE_AM_NICAM) {
+ v4l_dbg(1, msp_debug, client, "switching to AM mono\n");
+ /* AM mono decoding is handled by tuner, not MSP chip */
+ /* SCART switching control register */
+ msp_set_scart(client, SCART_MONO, 0);
+ src = 0x0200;
+ break;
+ }
+ case V4L2_TUNER_MODE_LANG1:
+ src = 0x0000 | nicam;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ src = 0x0010 | nicam;
+ break;
+ }
+ v4l_dbg(1, msp_debug, client, "setstereo final source/matrix = 0x%x\n", src);
+
+ if (msp_dolby) {
+ msp_write_dsp(client, 0x0008, 0x0520);
+ msp_write_dsp(client, 0x0009, 0x0620);
+ msp_write_dsp(client, 0x000a, src);
+ msp_write_dsp(client, 0x000b, src);
+ } else {
+ msp_write_dsp(client, 0x0008, src);
+ msp_write_dsp(client, 0x0009, src);
+ msp_write_dsp(client, 0x000a, src);
+ msp_write_dsp(client, 0x000b, src);
+ msp_write_dsp(client, 0x000c, src);
+ if (state->has_scart23_in_scart2_out)
+ msp_write_dsp(client, 0x0041, src);
+ }
+}
+
+static void msp3400c_print_mode(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (state->main == state->second) {
+ v4l_dbg(1, msp_debug, client, "mono sound carrier: %d.%03d MHz\n",
+ state->main / 910000, (state->main / 910) % 1000);
+ } else {
+ v4l_dbg(1, msp_debug, client, "main sound carrier: %d.%03d MHz\n",
+ state->main / 910000, (state->main / 910) % 1000);
+ }
+ if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2)
+ v4l_dbg(1, msp_debug, client, "NICAM/FM carrier : %d.%03d MHz\n",
+ state->second / 910000, (state->second/910) % 1000);
+ if (state->mode == MSP_MODE_AM_NICAM)
+ v4l_dbg(1, msp_debug, client, "NICAM/AM carrier : %d.%03d MHz\n",
+ state->second / 910000, (state->second / 910) % 1000);
+ if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) {
+ v4l_dbg(1, msp_debug, client, "FM-stereo carrier : %d.%03d MHz\n",
+ state->second / 910000, (state->second / 910) % 1000);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+int autodetect_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int val;
+ int rxsubchans = state->rxsubchans;
+ int newnicam = state->nicam_on;
+ int update = 0;
+
+ switch (state->mode) {
+ case MSP_MODE_FM_TERRA:
+ val = msp_read_dsp(client, 0x18);
+ if (val > 32767)
+ val -= 65536;
+ v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
+ if (val > 4096) {
+ rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+ } else if (val < -4096) {
+ rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ } else {
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ }
+ newnicam = 0;
+ break;
+ case MSP_MODE_FM_NICAM1:
+ case MSP_MODE_FM_NICAM2:
+ case MSP_MODE_AM_NICAM:
+ val = msp_read_dem(client, 0x23);
+ v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n",
+ val & 1, (val & 0x1e) >> 1);
+
+ if (val & 1) {
+ /* nicam synced */
+ switch ((val & 0x1e) >> 1) {
+ case 0:
+ case 8:
+ rxsubchans = V4L2_TUNER_SUB_STEREO;
+ break;
+ case 1:
+ case 9:
+ rxsubchans = V4L2_TUNER_SUB_MONO
+ | V4L2_TUNER_SUB_LANG1;
+ break;
+ case 2:
+ case 10:
+ rxsubchans = V4L2_TUNER_SUB_MONO
+ | V4L2_TUNER_SUB_LANG1
+ | V4L2_TUNER_SUB_LANG2;
+ break;
+ default:
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ break;
+ }
+ newnicam = 1;
+ } else {
+ newnicam = 0;
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ }
+ break;
+ case MSP_MODE_BTSC:
+ val = msp_read_dem(client, 0x200);
+ v4l_dbg(2, msp_debug, client, "status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
+ val,
+ (val & 0x0002) ? "no" : "yes",
+ (val & 0x0004) ? "no" : "yes",
+ (val & 0x0040) ? "stereo" : "mono",
+ (val & 0x0080) ? ", nicam 2nd mono" : "",
+ (val & 0x0100) ? ", bilingual/SAP" : "");
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1;
+ break;
+ }
+ if (rxsubchans != state->rxsubchans) {
+ update = 1;
+ v4l_dbg(1, msp_debug, client, "watch: rxsubchans %d => %d\n",
+ state->rxsubchans,rxsubchans);
+ state->rxsubchans = rxsubchans;
+ }
+ if (newnicam != state->nicam_on) {
+ update = 1;
+ v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n",
+ state->nicam_on,newnicam);
+ state->nicam_on = newnicam;
+ }
+ return update;
+}
+
+/*
+ * A kernel thread for msp3400 control -- we don't want to block the
+ * in the ioctl while doing the sound carrier & stereo detect
+ */
+/* stereo/multilang monitoring */
+static void watch_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (autodetect_stereo(client)) {
+ if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO);
+ else if (state->rxsubchans & V4L2_TUNER_SUB_LANG1)
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1);
+ else
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ }
+
+ if (msp_once)
+ state->watch_stereo = 0;
+}
+
+int msp3400c_thread(void *data)
+{
+ struct i2c_client *client = data;
+ struct msp_state *state = i2c_get_clientdata(client);
+ struct msp3400c_carrier_detect *cd;
+ int count, max1,max2,val1,val2, val,this;
+
+
+ v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+ for (;;) {
+ v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
+ msp_sleep(state, -1);
+ v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n");
+
+ restart:
+ v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+ state->restart = 0;
+ if (kthread_should_stop())
+ break;
+
+ if (state->radio || MSP_MODE_EXTERN == state->mode) {
+ /* no carrier scan, just unmute */
+ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ msp_set_audio(client);
+ continue;
+ }
+
+ /* mute */
+ msp_set_mute(client);
+ msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
+ val1 = val2 = 0;
+ max1 = max2 = -1;
+ state->watch_stereo = 0;
+
+ /* some time for the tuner to sync */
+ if (msp_sleep(state,200))
+ goto restart;
+
+ /* carrier detect pass #1 -- main carrier */
+ cd = msp3400c_carrier_detect_main;
+ count = ARRAY_SIZE(msp3400c_carrier_detect_main);
+
+ if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
+ /* autodetect doesn't work well with AM ... */
+ max1 = 3;
+ count = 0;
+ v4l_dbg(1, msp_debug, client, "AM sound override\n");
+ }
+
+ for (this = 0; this < count; this++) {
+ msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
+ if (msp_sleep(state,100))
+ goto restart;
+ val = msp_read_dsp(client, 0x1b);
+ if (val > 32767)
+ val -= 65536;
+ if (val1 < val)
+ val1 = val, max1 = this;
+ v4l_dbg(1, msp_debug, client, "carrier1 val: %5d / %s\n", val,cd[this].name);
+ }
+
+ /* carrier detect pass #2 -- second (stereo) carrier */
+ switch (max1) {
+ case 1: /* 5.5 */
+ cd = msp3400c_carrier_detect_55;
+ count = ARRAY_SIZE(msp3400c_carrier_detect_55);
+ break;
+ case 3: /* 6.5 */
+ cd = msp3400c_carrier_detect_65;
+ count = ARRAY_SIZE(msp3400c_carrier_detect_65);
+ break;
+ case 0: /* 4.5 */
+ case 2: /* 6.0 */
+ default:
+ cd = NULL;
+ count = 0;
+ break;
+ }
+
+ if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
+ /* autodetect doesn't work well with AM ... */
+ cd = NULL;
+ count = 0;
+ max2 = 0;
+ }
+ for (this = 0; this < count; this++) {
+ msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
+ if (msp_sleep(state,100))
+ goto restart;
+ val = msp_read_dsp(client, 0x1b);
+ if (val > 32767)
+ val -= 65536;
+ if (val2 < val)
+ val2 = val, max2 = this;
+ v4l_dbg(1, msp_debug, client, "carrier2 val: %5d / %s\n", val,cd[this].name);
+ }
+
+ /* program the msp3400 according to the results */
+ state->main = msp3400c_carrier_detect_main[max1].cdo;
+ switch (max1) {
+ case 1: /* 5.5 */
+ if (max2 == 0) {
+ /* B/G FM-stereo */
+ state->second = msp3400c_carrier_detect_55[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_TERRA);
+ state->nicam_on = 0;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ state->watch_stereo = 1;
+ } else if (max2 == 1 && state->has_nicam) {
+ /* B/G NICAM */
+ state->second = msp3400c_carrier_detect_55[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
+ state->nicam_on = 1;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->watch_stereo = 1;
+ } else {
+ goto no_second;
+ }
+ break;
+ case 2: /* 6.0 */
+ /* PAL I NICAM */
+ state->second = MSP_CARRIER(6.552);
+ msp3400c_setmode(client, MSP_MODE_FM_NICAM2);
+ state->nicam_on = 1;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->watch_stereo = 1;
+ break;
+ case 3: /* 6.5 */
+ if (max2 == 1 || max2 == 2) {
+ /* D/K FM-stereo */
+ state->second = msp3400c_carrier_detect_65[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_TERRA);
+ state->nicam_on = 0;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ state->watch_stereo = 1;
+ } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
+ /* L NICAM or AM-mono */
+ state->second = msp3400c_carrier_detect_65[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_AM_NICAM);
+ state->nicam_on = 0;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ msp3400c_setcarrier(client, state->second, state->main);
+ /* volume prescale for SCART (AM mono input) */
+ msp_write_dsp(client, 0x000d, 0x1900);
+ state->watch_stereo = 1;
+ } else if (max2 == 0 && state->has_nicam) {
+ /* D/K NICAM */
+ state->second = msp3400c_carrier_detect_65[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
+ state->nicam_on = 1;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->watch_stereo = 1;
+ } else {
+ goto no_second;
+ }
+ break;
+ case 0: /* 4.5 */
+ default:
+ no_second:
+ state->second = msp3400c_carrier_detect_main[max1].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_TERRA);
+ state->nicam_on = 0;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ break;
+ }
+
+ /* unmute */
+ msp_set_audio(client);
+
+ if (msp_debug)
+ msp3400c_print_mode(client);
+
+ /* monitor tv audio mode */
+ while (state->watch_stereo) {
+ if (msp_sleep(state,5000))
+ goto restart;
+ watch_stereo(client);
+ }
+ }
+ v4l_dbg(1, msp_debug, client, "thread: exit\n");
+ return 0;
+}
+
+
+int msp3410d_thread(void *data)
+{
+ struct i2c_client *client = data;
+ struct msp_state *state = i2c_get_clientdata(client);
+ int val, i, std;
+
+ v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+
+ for (;;) {
+ v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
+ msp_sleep(state,-1);
+ v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n");
+
+ restart:
+ v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+ state->restart = 0;
+ if (kthread_should_stop())
+ break;
+
+ if (state->mode == MSP_MODE_EXTERN) {
+ /* no carrier scan needed, just unmute */
+ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ msp_set_audio(client);
+ continue;
+ }
+
+ /* put into sane state (and mute) */
+ msp_reset(client);
+
+ /* some time for the tuner to sync */
+ if (msp_sleep(state,200))
+ goto restart;
+
+ /* start autodetect */
+ if (state->radio)
+ std = 0x40;
+ else
+ std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
+ state->watch_stereo = 0;
+
+ if (msp_debug)
+ v4l_dbg(1, msp_debug, client, "setting standard: %s (0x%04x)\n",
+ msp_standard_std_name(std), std);
+
+ if (std != 1) {
+ /* programmed some specific mode */
+ val = std;
+ } else {
+ /* triggered autodetect */
+ msp_write_dem(client, 0x20, std);
+ for (;;) {
+ if (msp_sleep(state, 100))
+ goto restart;
+
+ /* check results */
+ val = msp_read_dem(client, 0x7e);
+ if (val < 0x07ff)
+ break;
+ v4l_dbg(1, msp_debug, client, "detection still in progress\n");
+ }
+ }
+ for (i = 0; msp_stdlist[i].name != NULL; i++)
+ if (msp_stdlist[i].retval == val)
+ break;
+ v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
+ msp_standard_std_name(val), val);
+ state->main = msp_stdlist[i].main;
+ state->second = msp_stdlist[i].second;
+ state->std = val;
+
+ if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
+ (val != 0x0009)) {
+ /* autodetection has failed, let backup */
+ v4l_dbg(1, msp_debug, client, "autodetection failed,"
+ " switching to backup standard: %s (0x%04x)\n",
+ msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val);
+ val = 0x0009;
+ msp_write_dem(client, 0x20, val);
+ }
+
+ /* set various prescales */
+ msp_write_dsp(client, 0x0d, 0x1900); /* scart */
+ msp_write_dsp(client, 0x0e, 0x2403); /* FM */
+ msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
+
+ /* set stereo */
+ switch (val) {
+ case 0x0008: /* B/G NICAM */
+ case 0x000a: /* I NICAM */
+ if (val == 0x0008)
+ state->mode = MSP_MODE_FM_NICAM1;
+ else
+ state->mode = MSP_MODE_FM_NICAM2;
+ /* just turn on stereo */
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->nicam_on = 1;
+ state->watch_stereo = 1;
+ msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
+ break;
+ case 0x0009:
+ state->mode = MSP_MODE_AM_NICAM;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+ state->nicam_on = 1;
+ msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO);
+ state->watch_stereo = 1;
+ break;
+ case 0x0020: /* BTSC */
+ /* just turn on stereo */
+ state->mode = MSP_MODE_BTSC;
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->nicam_on = 0;
+ state->watch_stereo = 1;
+ msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
+ break;
+ case 0x0040: /* FM radio */
+ state->mode = MSP_MODE_FM_RADIO;
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ state->nicam_on = 0;
+ state->watch_stereo = 0;
+ /* not needed in theory if we have radio, but
+ short programming enables carrier mute */
+ msp3400c_setmode(client, MSP_MODE_FM_RADIO);
+ msp3400c_setcarrier(client, MSP_CARRIER(10.7),
+ MSP_CARRIER(10.7));
+ /* scart routing */
+ msp_set_scart(client,SCART_IN2,0);
+ /* msp34xx does radio decoding */
+ msp_write_dsp(client, 0x08, 0x0020);
+ msp_write_dsp(client, 0x09, 0x0020);
+ msp_write_dsp(client, 0x0b, 0x0020);
+ break;
+ case 0x0003:
+ case 0x0004:
+ case 0x0005:
+ state->mode = MSP_MODE_FM_TERRA;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+ state->audmode = V4L2_TUNER_MODE_MONO;
+ state->nicam_on = 0;
+ state->watch_stereo = 1;
+ break;
+ }
+
+ /* unmute, restore misc registers */
+ msp_set_audio(client);
+ msp_write_dsp(client, 0x13, state->acb);
+ if (state->has_i2s_conf)
+ msp_write_dem(client, 0x40, state->i2s_mode);
+
+ /* monitor tv audio mode */
+ while (state->watch_stereo) {
+ if (msp_sleep(state,5000))
+ goto restart;
+ watch_stereo(client);
+ }
+ }
+ v4l_dbg(1, msp_debug, client, "thread: exit\n");
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* msp34xxG + (autoselect no-thread) */
+/* this one uses both automatic standard detection and automatic sound */
+/* select which are available in the newer G versions */
+/* struct msp: only norm, acb and source are really used in this mode */
+
+/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
+ * the value for source is the same as bit 15:8 of DSP registers 0x08,
+ * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
+ *
+ * this function replaces msp3400c_setstereo
+ */
+static void msp34xxg_set_source(struct i2c_client *client, int source)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ /* fix matrix mode to stereo and let the msp choose what
+ * to output according to 'source', as recommended
+ * for MONO (source==0) downmixing set bit[7:0] to 0x30
+ */
+ int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20);
+
+ v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value);
+ /* Loudspeaker Output */
+ msp_write_dsp(client, 0x08, value);
+ /* SCART1 DA Output */
+ msp_write_dsp(client, 0x0a, value);
+ /* Quasi-peak detector */
+ msp_write_dsp(client, 0x0c, value);
+ /*
+ * set identification threshold. Personally, I
+ * I set it to a higher value that the default
+ * of 0x190 to ignore noisy stereo signals.
+ * this needs tuning. (recommended range 0x00a0-0x03c0)
+ * 0x7f0 = forced mono mode
+ */
+ /* a2 threshold for stereo/bilingual */
+ msp_write_dem(client, 0x22, msp_stereo_thresh);
+ state->source = source;
+}
+
+/* (re-)initialize the msp34xxg, according to the current norm in state->norm
+ * return 0 if it worked, -1 if it failed
+ */
+static int msp34xxg_reset(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int modus, std;
+
+ if (msp_reset(client))
+ return -1;
+
+ /* make sure that input/output is muted (paranoid mode) */
+ /* ACB, mute DSP input, mute SCART 1 */
+ if (msp_write_dsp(client, 0x13, 0x0f20))
+ return -1;
+
+ if (state->has_i2s_conf)
+ msp_write_dem(client, 0x40, state->i2s_mode);
+
+ /* step-by-step initialisation, as described in the manual */
+ modus = msp_modus(client);
+ if (state->radio)
+ std = 0x40;
+ else
+ std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
+ modus &= ~0x03; /* STATUS_CHANGE = 0 */
+ modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */
+ if (msp_write_dem(client, 0x30, modus))
+ return -1;
+ if (msp_write_dem(client, 0x20, std))
+ return -1;
+
+ /* write the dsps that may have an influence on
+ standard/audio autodetection right now */
+ msp34xxg_set_source(client, state->source);
+
+ /* AM/FM Prescale [15:8] 75khz deviation */
+ if (msp_write_dsp(client, 0x0e, 0x3000))
+ return -1;
+
+ /* NICAM Prescale 9db gain (as recommended) */
+ if (msp_write_dsp(client, 0x10, 0x5a00))
+ return -1;
+
+ return 0;
+}
+
+int msp34xxg_thread(void *data)
+{
+ struct i2c_client *client = data;
+ struct msp_state *state = i2c_get_clientdata(client);
+ int val, std, i;
+
+ v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+
+ state->source = 1; /* default */
+ for (;;) {
+ v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
+ msp_sleep(state, -1);
+ v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n");
+
+ restart:
+ v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+ state->restart = 0;
+ if (kthread_should_stop())
+ break;
+
+ /* setup the chip*/
+ msp34xxg_reset(client);
+ std = msp_standard;
+ if (std != 0x01)
+ goto unmute;
+
+ /* watch autodetect */
+ v4l_dbg(1, msp_debug, client, "triggered autodetect, waiting for result\n");
+ for (i = 0; i < 10; i++) {
+ if (msp_sleep(state, 100))
+ goto restart;
+
+ /* check results */
+ val = msp_read_dem(client, 0x7e);
+ if (val < 0x07ff) {
+ std = val;
+ break;
+ }
+ v4l_dbg(2, msp_debug, client, "detection still in progress\n");
+ }
+ if (std == 1) {
+ v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n");
+ continue;
+ }
+
+ unmute:
+ state->std = std;
+ v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
+ msp_standard_std_name(std), std);
+
+ /* unmute: dispatch sound to scart output, set scart volume */
+ msp_set_audio(client);
+
+ /* restore ACB */
+ if (msp_write_dsp(client, 0x13, state->acb))
+ return -1;
+
+ msp_write_dem(client, 0x40, state->i2s_mode);
+ }
+ v4l_dbg(1, msp_debug, client, "thread: exit\n");
+ return 0;
+}
+
+void msp34xxg_detect_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ int status = msp_read_dem(client, 0x0200);
+ int is_bilingual = status & 0x100;
+ int is_stereo = status & 0x40;
+
+ state->rxsubchans = 0;
+ if (is_stereo)
+ state->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ else
+ state->rxsubchans |= V4L2_TUNER_SUB_MONO;
+ if (is_bilingual) {
+ state->rxsubchans |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ /* I'm supposed to check whether it's SAP or not
+ * and set only LANG2/SAP in this case. Yet, the MSP
+ * does a lot of work to hide this and handle everything
+ * the same way. I don't want to work around it so unless
+ * this is a problem, I'll handle SAP just like lang1/lang2.
+ */
+ }
+ v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
+ status, is_stereo, is_bilingual, state->rxsubchans);
+}
+
+void msp34xxg_set_audmode(struct i2c_client *client, int audmode)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int source;
+
+ switch (audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ source = 0; /* mono only */
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
+ /* problem: that could also mean 2 (scart input) */
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ source = 3; /* stereo or A */
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ source = 4; /* stereo or B */
+ break;
+ default:
+ audmode = 0;
+ source = 1;
+ break;
+ }
+ state->audmode = audmode;
+ msp34xxg_set_source(client, source);
+}
+
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
deleted file mode 100644
index 183253e2dd91..000000000000
--- a/drivers/media/video/msp3400.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/*
- * programming the msp34* sound processor family
- *
- * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
- *
- * what works and what doesn't:
- *
- * AM-Mono
- * Support for Hauppauge cards added (decoding handled by tuner) added by
- * Frederic Crozat <fcrozat@mail.dotcom.fr>
- *
- * FM-Mono
- * should work. The stereo modes are backward compatible to FM-mono,
- * therefore FM-Mono should be allways available.
- *
- * FM-Stereo (B/G, used in germany)
- * should work, with autodetect
- *
- * FM-Stereo (satellite)
- * should work, no autodetect (i.e. default is mono, but you can
- * switch to stereo -- untested)
- *
- * NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
- * should work, with autodetect. Support for NICAM was added by
- * Pekka Pietikainen <pp@netppl.fi>
- *
- *
- * TODO:
- * - better SAT support
- *
- *
- * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch)
- * using soundcore instead of OSS
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/kthread.h>
-#include <linux/suspend.h>
-#include <asm/semaphore.h>
-#include <asm/pgtable.h>
-
-#include <media/audiochip.h>
-#include "msp3400.h"
-
-#define msp3400_dbg(fmt, arg...) \
- do { \
- if (debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-/* Medium volume debug. */
-#define msp3400_dbg_mediumvol(fmt, arg...) \
- do { \
- if (debug >= 2) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-/* High volume debug. Use with care. */
-#define msp3400_dbg_highvol(fmt, arg...) \
- do { \
- if (debug >= 16) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define msp3400_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define msp3400_warn(fmt, arg...) do { \
- printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define msp3400_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define OPMODE_AUTO -1
-#define OPMODE_MANUAL 0
-#define OPMODE_SIMPLE 1 /* use short programming (>= msp3410 only) */
-#define OPMODE_SIMPLER 2 /* use shorter programming (>= msp34xxG) */
-
-/* insmod parameters */
-static int opmode = OPMODE_AUTO;
-static int debug = 0; /* debug output */
-static int once = 0; /* no continous stereo monitoring */
-static int amsound = 0; /* hard-wire AM sound at 6.5 Hz (france),
- the autoscan seems work well only with FM... */
-static int standard = 1; /* Override auto detect of audio standard, if needed. */
-static int dolby = 0;
-
-static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual
- (msp34xxg only) 0x00a0-0x03c0 */
-#define DFP_COUNT 0x41
-static const int bl_dfp[] = {
- 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a,
- 0x0b, 0x0d, 0x0e, 0x10
-};
-
-#define IS_MSP34XX_G(msp) ((msp)->opmode==2)
-
-struct msp3400c {
- int rev1,rev2;
-
- int opmode;
- int nicam;
- int mode;
- int norm;
- int stereo;
- int nicam_on;
- int acb;
- int in_scart;
- int i2s_mode;
- int main, second; /* sound carrier */
- int input;
- int source; /* see msp34xxg_set_source */
-
- /* v4l2 */
- int audmode;
- int rxsubchans;
-
- int muted;
- int left, right; /* volume */
- int bass, treble;
-
- /* shadow register set */
- int dfp_regs[DFP_COUNT];
-
- /* thread */
- struct task_struct *kthread;
- wait_queue_head_t wq;
- int restart:1;
- int watch_stereo:1;
-};
-
-#define MIN(a,b) (((a)>(b))?(b):(a))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-#define HAVE_NICAM(msp) (((msp->rev2>>8) & 0xff) != 00)
-#define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@')
-#define HAVE_SIMPLER(msp) ((msp->rev1 & 0xff) >= 'G'-'@')
-#define HAVE_RADIO(msp) ((msp->rev1 & 0xff) >= 'G'-'@')
-
-#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
-
-/* ---------------------------------------------------------------------- */
-
-/* read-only */
-module_param(opmode, int, 0444);
-
-/* read-write */
-module_param(once, int, 0644);
-module_param(debug, int, 0644);
-module_param(stereo_threshold, int, 0644);
-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");
-
-/* ---------------------------------------------------------------------- */
-
-#define I2C_MSP3400C 0x80
-#define I2C_MSP3400C_ALT 0x88
-
-#define I2C_MSP3400C_DEM 0x10
-#define I2C_MSP3400C_DFP 0x12
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {
- I2C_MSP3400C >> 1,
- I2C_MSP3400C_ALT >> 1,
- I2C_CLIENT_END
-};
-I2C_CLIENT_INSMOD;
-
-MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-/* ----------------------------------------------------------------------- */
-/* functions for talking to the MSP3400C Sound processor */
-
-static int msp3400c_reset(struct i2c_client *client)
-{
- /* reset and read revision code */
- static char reset_off[3] = { 0x00, 0x80, 0x00 };
- static char reset_on[3] = { 0x00, 0x00, 0x00 };
- static char write[3] = { I2C_MSP3400C_DFP + 1, 0x00, 0x1e };
- char read[2];
- struct i2c_msg reset[2] = {
- { client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
- { client->addr, I2C_M_IGNORE_NAK, 3, reset_on },
- };
- struct i2c_msg test[2] = {
- { client->addr, 0, 3, write },
- { client->addr, I2C_M_RD, 2, read },
- };
-
- msp3400_dbg_highvol("msp3400c_reset\n");
- if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) ||
- (1 != i2c_transfer(client->adapter,&reset[1],1)) ||
- (2 != i2c_transfer(client->adapter,test,2)) ) {
- msp3400_err("chip reset failed\n");
- return -1;
- }
- return 0;
-}
-
-static int msp3400c_read(struct i2c_client *client, int dev, int addr)
-{
- int err,retval;
-
- unsigned char write[3];
- unsigned char read[2];
- struct i2c_msg msgs[2] = {
- { client->addr, 0, 3, write },
- { client->addr, I2C_M_RD, 2, read }
- };
-
- write[0] = dev+1;
- write[1] = addr >> 8;
- write[2] = addr & 0xff;
-
- for (err = 0; err < 3;) {
- if (2 == i2c_transfer(client->adapter,msgs,2))
- break;
- err++;
- msp3400_warn("I/O error #%d (read 0x%02x/0x%02x)\n", err,
- dev, addr);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(msecs_to_jiffies(10));
- }
- if (3 == err) {
- msp3400_warn("giving up, resetting chip. Sound will go off, sorry folks :-|\n");
- msp3400c_reset(client);
- return -1;
- }
- retval = read[0] << 8 | read[1];
- msp3400_dbg_highvol("msp3400c_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval);
- return retval;
-}
-
-static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val)
-{
- int err;
- unsigned char buffer[5];
-
- buffer[0] = dev;
- buffer[1] = addr >> 8;
- buffer[2] = addr & 0xff;
- buffer[3] = val >> 8;
- buffer[4] = val & 0xff;
-
- msp3400_dbg_highvol("msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val);
- for (err = 0; err < 3;) {
- if (5 == i2c_master_send(client, buffer, 5))
- break;
- err++;
- msp3400_warn("I/O error #%d (write 0x%02x/0x%02x)\n", err,
- dev, addr);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(msecs_to_jiffies(10));
- }
- if (3 == err) {
- msp3400_warn("giving up, reseting chip. Sound will go off, sorry folks :-|\n");
- msp3400c_reset(client);
- return -1;
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-
-/* This macro is allowed for *constants* only, gcc must calculate it
- at compile time. Remember -- no floats in kernel mode */
-#define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24)))
-
-#define MSP_MODE_AM_DETECT 0
-#define MSP_MODE_FM_RADIO 2
-#define MSP_MODE_FM_TERRA 3
-#define MSP_MODE_FM_SAT 4
-#define MSP_MODE_FM_NICAM1 5
-#define MSP_MODE_FM_NICAM2 6
-#define MSP_MODE_AM_NICAM 7
-#define MSP_MODE_BTSC 8
-#define MSP_MODE_EXTERN 9
-
-static struct MSP_INIT_DATA_DEM {
- int fir1[6];
- int fir2[6];
- int cdo1;
- int cdo2;
- int ad_cv;
- int mode_reg;
- int dfp_src;
- int dfp_matrix;
-} msp_init_data[] = {
- { /* AM (for carrier detect / msp3400) */
- {75, 19, 36, 35, 39, 40},
- {75, 19, 36, 35, 39, 40},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0500, 0x0020, 0x3000
- },{ /* AM (for carrier detect / msp3410) */
- {-1, -1, -8, 2, 59, 126},
- {-1, -1, -8, 2, 59, 126},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0100, 0x0020, 0x3000
- },{ /* FM Radio */
- {-8, -8, 4, 6, 78, 107},
- {-8, -8, 4, 6, 78, 107},
- MSP_CARRIER(10.7), MSP_CARRIER(10.7),
- 0x00d0, 0x0480, 0x0020, 0x3000
- },{ /* Terrestial FM-mono + FM-stereo */
- {3, 18, 27, 48, 66, 72},
- {3, 18, 27, 48, 66, 72},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0480, 0x0030, 0x3000
- },{ /* Sat FM-mono */
- { 1, 9, 14, 24, 33, 37},
- { 3, 18, 27, 48, 66, 72},
- MSP_CARRIER(6.5), MSP_CARRIER(6.5),
- 0x00c6, 0x0480, 0x0000, 0x3000
- },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */
- {-2, -8, -10, 10, 50, 86},
- {3, 18, 27, 48, 66, 72},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0040, 0x0120, 0x3000
- },{ /* NICAM/FM -- I (6.0/6.552) */
- {2, 4, -6, -4, 40, 94},
- {3, 18, 27, 48, 66, 72},
- MSP_CARRIER(6.0), MSP_CARRIER(6.0),
- 0x00d0, 0x0040, 0x0120, 0x3000
- },{ /* NICAM/AM -- L (6.5/5.85) */
- {-2, -8, -10, 10, 50, 86},
- {-4, -12, -9, 23, 79, 126},
- MSP_CARRIER(6.5), MSP_CARRIER(6.5),
- 0x00c6, 0x0140, 0x0120, 0x7c03
- },
-};
-
-struct CARRIER_DETECT {
- int cdo;
- char *name;
-};
-
-static struct CARRIER_DETECT carrier_detect_main[] = {
- /* main carrier */
- { MSP_CARRIER(4.5), "4.5 NTSC" },
- { MSP_CARRIER(5.5), "5.5 PAL B/G" },
- { MSP_CARRIER(6.0), "6.0 PAL I" },
- { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
-};
-
-static struct CARRIER_DETECT carrier_detect_55[] = {
- /* PAL B/G */
- { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
- { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
-};
-
-static struct CARRIER_DETECT carrier_detect_65[] = {
- /* PAL SAT / SECAM */
- { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" },
- { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
- { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
- { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
- { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
- { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
-};
-
-#define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT))
-
-/* ----------------------------------------------------------------------- *
- * bits 9 8 5 - SCART DSP input Select:
- * 0 0 0 - SCART 1 to DSP input (reset position)
- * 0 1 0 - MONO to DSP input
- * 1 0 0 - SCART 2 to DSP input
- * 1 1 1 - Mute DSP input
- *
- * bits 11 10 6 - SCART 1 Output Select:
- * 0 0 0 - undefined (reset position)
- * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS)
- * 1 0 0 - MONO input to SCART 1 Output
- * 1 1 0 - SCART 1 DA to SCART 1 Output
- * 0 0 1 - SCART 2 DA to SCART 1 Output
- * 0 1 1 - SCART 1 Input to SCART 1 Output
- * 1 1 1 - Mute SCART 1 Output
- *
- * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART):
- * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position)
- * 0 1 0 - SCART 1 Input to SCART 2 Output
- * 1 0 0 - MONO input to SCART 2 Output
- * 0 0 1 - SCART 2 DA to SCART 2 Output
- * 0 1 1 - SCART 2 Input to SCART 2 Output
- * 1 1 0 - Mute SCART 2 Output
- *
- * Bits 4 to 0 should be zero.
- * ----------------------------------------------------------------------- */
-
-static int scarts[3][9] = {
- /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */
- /* SCART DSP Input select */
- { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 },
- /* SCART1 Output select */
- { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
- /* SCART2 Output select */
- { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
-};
-
-static char *scart_names[] = {
- "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute"
-};
-
-static void msp3400c_set_scart(struct i2c_client *client, int in, int out)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- msp->in_scart=in;
-
- if (in >= 1 && in <= 8 && out >= 0 && out <= 2) {
- if (-1 == scarts[out][in])
- return;
-
- msp->acb &= ~scarts[out][SCART_MASK];
- msp->acb |= scarts[out][in];
- } else
- msp->acb = 0xf60; /* Mute Input and SCART 1 Output */
-
- msp3400_dbg("scart switch: %s => %d (ACB=0x%04x)\n",
- scart_names[in], out, msp->acb);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb);
-
- /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
-}
-
-/* ------------------------------------------------------------------------ */
-
-static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2)
-{
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0093, cdo1 & 0xfff);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
-}
-
-static void msp3400c_setvolume(struct i2c_client *client,
- int muted, int left, int right)
- {
- int vol = 0, val = 0, balance = 0;
-
- if (!muted) {
- /* 0x7f instead if 0x73 here has sound quality issues,
- * probably due to overmodulation + clipping ... */
- vol = (left > right) ? left : right;
- val = (vol * 0x73 / 65535) << 8;
- }
- if (vol > 0) {
- balance = ((right - left) * 127) / vol;
- }
-
- msp3400_dbg("setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n",
- muted ? "on" : "off", left, right, val >> 8, balance);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007,
- muted ? 0x1 : (val | 0x1));
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0001, balance << 8);
-}
-
-static void msp3400c_setbass(struct i2c_client *client, int bass)
-{
- int val = ((bass-32768) * 0x60 / 65535) << 8;
-
- msp3400_dbg("setbass: %d 0x%02x\n", bass, val >> 8);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */
-}
-
-static void msp3400c_settreble(struct i2c_client *client, int treble)
-{
- int val = ((treble-32768) * 0x60 / 65535) << 8;
-
- msp3400_dbg("settreble: %d 0x%02x\n",treble, val>>8);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */
-}
-
-static void msp3400c_setmode(struct i2c_client *client, int type)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
-
- msp3400_dbg("setmode: %d\n",type);
- msp->mode = type;
- msp->audmode = V4L2_TUNER_MODE_MONO;
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */
- msp_init_data[type].ad_cv);
-
- for (i = 5; i >= 0; i--) /* fir 1 */
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0001,
- msp_init_data[type].fir1[i]);
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0040);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0000);
- for (i = 5; i >= 0; i--)
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005,
- msp_init_data[type].fir2[i]);
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
- msp_init_data[type].mode_reg);
-
- msp3400c_setcarrier(client, msp_init_data[type].cdo1,
- msp_init_data[type].cdo2);
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
-
- if (dolby) {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,
- 0x0520); /* I2S1 */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,
- 0x0620); /* I2S2 */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,
- msp_init_data[type].dfp_src);
- } else {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,
- msp_init_data[type].dfp_src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,
- msp_init_data[type].dfp_src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,
- msp_init_data[type].dfp_src);
- }
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,
- msp_init_data[type].dfp_src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e,
- msp_init_data[type].dfp_matrix);
-
- if (HAVE_NICAM(msp)) {
- /* nicam prescale */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */
- }
-}
-
-/* given a bitmask of VIDEO_SOUND_XXX returns the "best" in the bitmask */
-static int best_video_sound(int rxsubchans)
-{
- if (rxsubchans & V4L2_TUNER_SUB_STEREO)
- return V4L2_TUNER_MODE_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG1)
- return V4L2_TUNER_MODE_LANG1;
- if (rxsubchans & V4L2_TUNER_SUB_LANG2)
- return V4L2_TUNER_MODE_LANG2;
- return V4L2_TUNER_MODE_MONO;
-}
-
-/* turn on/off nicam + stereo */
-static void msp3400c_setstereo(struct i2c_client *client, int mode)
-{
- static char *strmode[] = { "0", "mono", "stereo", "3",
- "lang1", "5", "6", "7", "lang2"
- };
- struct msp3400c *msp = i2c_get_clientdata(client);
- int nicam = 0; /* channel source: FM/AM or nicam */
- int src = 0;
-
- if (IS_MSP34XX_G(msp)) {
- /* this method would break everything, let's make sure
- * it's never called
- */
- msp3400_dbg
- ("DEBUG WARNING setstereo called with mode=%d instead of set_source (ignored)\n",
- mode);
- return;
- }
-
- /* switch demodulator */
- switch (msp->mode) {
- case MSP_MODE_FM_TERRA:
- msp3400_dbg("FM setstereo: %s\n", strmode[mode]);
- msp3400c_setcarrier(client,msp->second,msp->main);
- switch (mode) {
- case V4L2_TUNER_MODE_STEREO:
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001);
- break;
- case V4L2_TUNER_MODE_MONO:
- case V4L2_TUNER_MODE_LANG1:
- case V4L2_TUNER_MODE_LANG2:
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000);
- break;
- }
- break;
- case MSP_MODE_FM_SAT:
- msp3400_dbg("SAT setstereo: %s\n", strmode[mode]);
- switch (mode) {
- case V4L2_TUNER_MODE_MONO:
- msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
- break;
- case V4L2_TUNER_MODE_STEREO:
- msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
- break;
- case V4L2_TUNER_MODE_LANG1:
- msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
- break;
- case V4L2_TUNER_MODE_LANG2:
- msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
- break;
- }
- break;
- case MSP_MODE_FM_NICAM1:
- case MSP_MODE_FM_NICAM2:
- case MSP_MODE_AM_NICAM:
- msp3400_dbg("NICAM setstereo: %s\n",strmode[mode]);
- msp3400c_setcarrier(client,msp->second,msp->main);
- if (msp->nicam_on)
- nicam=0x0100;
- break;
- case MSP_MODE_BTSC:
- msp3400_dbg("BTSC setstereo: %s\n",strmode[mode]);
- nicam=0x0300;
- break;
- case MSP_MODE_EXTERN:
- msp3400_dbg("extern setstereo: %s\n",strmode[mode]);
- nicam = 0x0200;
- break;
- case MSP_MODE_FM_RADIO:
- msp3400_dbg("FM-Radio setstereo: %s\n",strmode[mode]);
- break;
- default:
- msp3400_dbg("mono setstereo\n");
- return;
- }
-
- /* switch audio */
- switch (best_video_sound(mode)) {
- case V4L2_TUNER_MODE_STEREO:
- src = 0x0020 | nicam;
- break;
- case V4L2_TUNER_MODE_MONO:
- if (msp->mode == MSP_MODE_AM_NICAM) {
- msp3400_dbg("switching to AM mono\n");
- /* AM mono decoding is handled by tuner, not MSP chip */
- /* SCART switching control register */
- msp3400c_set_scart(client,SCART_MONO,0);
- src = 0x0200;
- break;
- }
- case V4L2_TUNER_MODE_LANG1:
- src = 0x0000 | nicam;
- break;
- case V4L2_TUNER_MODE_LANG2:
- src = 0x0010 | nicam;
- break;
- }
- msp3400_dbg("setstereo final source/matrix = 0x%x\n", src);
-
- if (dolby) {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,0x0620);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src);
- } else {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src);
- }
-}
-
-static void
-msp3400c_print_mode(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- if (msp->main == msp->second) {
- msp3400_dbg("mono sound carrier: %d.%03d MHz\n",
- msp->main/910000,(msp->main/910)%1000);
- } else {
- msp3400_dbg("main sound carrier: %d.%03d MHz\n",
- msp->main/910000,(msp->main/910)%1000);
- }
- if (msp->mode == MSP_MODE_FM_NICAM1 || msp->mode == MSP_MODE_FM_NICAM2)
- msp3400_dbg("NICAM/FM carrier : %d.%03d MHz\n",
- msp->second/910000,(msp->second/910)%1000);
- if (msp->mode == MSP_MODE_AM_NICAM)
- msp3400_dbg("NICAM/AM carrier : %d.%03d MHz\n",
- msp->second/910000,(msp->second/910)%1000);
- if (msp->mode == MSP_MODE_FM_TERRA &&
- msp->main != msp->second) {
- msp3400_dbg("FM-stereo carrier : %d.%03d MHz\n",
- msp->second/910000,(msp->second/910)%1000);
- }
-}
-
-#define MSP3400_MAX 4
-static struct i2c_client *msps[MSP3400_MAX];
-static void msp3400c_restore_dfp(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
-
- for (i = 0; i < DFP_COUNT; i++) {
- if (-1 == msp->dfp_regs[i])
- continue;
- msp3400c_write(client, I2C_MSP3400C_DFP, i, msp->dfp_regs[i]);
- }
-}
-
-/* if the dfp_regs is set, set what's in there. Otherwise, set the default value */
-static int msp3400c_write_dfp_with_default(struct i2c_client *client,
- int addr, int default_value)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int value = default_value;
- if (addr < DFP_COUNT && -1 != msp->dfp_regs[addr])
- value = msp->dfp_regs[addr];
- return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value);
-}
-
-/* ----------------------------------------------------------------------- */
-
-struct REGISTER_DUMP {
- int addr;
- char *name;
-};
-
-struct REGISTER_DUMP d1[] = {
- {0x007e, "autodetect"},
- {0x0023, "C_AD_BITS "},
- {0x0038, "ADD_BITS "},
- {0x003e, "CIB_BITS "},
- {0x0057, "ERROR_RATE"},
-};
-
-static int autodetect_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int val;
- int rxsubchans = msp->rxsubchans;
- int newnicam = msp->nicam_on;
- int update = 0;
-
- switch (msp->mode) {
- case MSP_MODE_FM_TERRA:
- val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18);
- if (val > 32767)
- val -= 65536;
- msp3400_dbg("stereo detect register: %d\n",val);
- if (val > 4096) {
- rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
- } else if (val < -4096) {
- rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
- } else {
- rxsubchans = V4L2_TUNER_SUB_MONO;
- }
- newnicam = 0;
- break;
- case MSP_MODE_FM_NICAM1:
- case MSP_MODE_FM_NICAM2:
- case MSP_MODE_AM_NICAM:
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23);
- msp3400_dbg("nicam sync=%d, mode=%d\n",
- val & 1, (val & 0x1e) >> 1);
-
- if (val & 1) {
- /* nicam synced */
- switch ((val & 0x1e) >> 1) {
- case 0:
- case 8:
- rxsubchans = V4L2_TUNER_SUB_STEREO;
- break;
- case 1:
- case 9:
- rxsubchans = V4L2_TUNER_SUB_MONO
- | V4L2_TUNER_SUB_LANG1;
- break;
- case 2:
- case 10:
- rxsubchans = V4L2_TUNER_SUB_MONO
- | V4L2_TUNER_SUB_LANG1
- | V4L2_TUNER_SUB_LANG2;
- break;
- default:
- rxsubchans = V4L2_TUNER_SUB_MONO;
- break;
- }
- newnicam=1;
- } else {
- newnicam = 0;
- rxsubchans = V4L2_TUNER_SUB_MONO;
- }
- break;
- case MSP_MODE_BTSC:
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200);
- msp3400_dbg("status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
- val,
- (val & 0x0002) ? "no" : "yes",
- (val & 0x0004) ? "no" : "yes",
- (val & 0x0040) ? "stereo" : "mono",
- (val & 0x0080) ? ", nicam 2nd mono" : "",
- (val & 0x0100) ? ", bilingual/SAP" : "");
- rxsubchans = V4L2_TUNER_SUB_MONO;
- if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO;
- if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1;
- break;
- }
- if (rxsubchans != msp->rxsubchans) {
- update = 1;
- msp3400_dbg("watch: rxsubchans %d => %d\n",
- msp->rxsubchans,rxsubchans);
- msp->rxsubchans = rxsubchans;
- }
- if (newnicam != msp->nicam_on) {
- update = 1;
- msp3400_dbg("watch: nicam %d => %d\n",
- msp->nicam_on,newnicam);
- msp->nicam_on = newnicam;
- }
- return update;
-}
-
-/*
- * A kernel thread for msp3400 control -- we don't want to block the
- * in the ioctl while doing the sound carrier & stereo detect
- */
-
-static int msp34xx_sleep(struct msp3400c *msp, int timeout)
-{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(&msp->wq, &wait);
- if (!kthread_should_stop()) {
- if (timeout < 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- } else {
- schedule_timeout_interruptible
- (msecs_to_jiffies(timeout));
- }
- }
-
- remove_wait_queue(&msp->wq, &wait);
- try_to_freeze();
- return msp->restart;
-}
-
-/* stereo/multilang monitoring */
-static void watch_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- if (autodetect_stereo(client)) {
- if (msp->stereo & V4L2_TUNER_MODE_STEREO)
- msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO);
- else if (msp->stereo & VIDEO_SOUND_LANG1)
- msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1);
- else
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- }
-
- if (once)
- msp->watch_stereo = 0;
-}
-
-
-static int msp3400c_thread(void *data)
-{
- struct i2c_client *client = data;
- struct msp3400c *msp = i2c_get_clientdata(client);
- struct CARRIER_DETECT *cd;
- int count, max1,max2,val1,val2, val,this;
-
-
- msp3400_info("msp3400 daemon started\n");
- for (;;) {
- msp3400_dbg_mediumvol("msp3400 thread: sleep\n");
- msp34xx_sleep(msp,-1);
- msp3400_dbg_mediumvol("msp3400 thread: wakeup\n");
-
- restart:
- msp3400_dbg("thread: restart scan\n");
- msp->restart = 0;
- if (kthread_should_stop())
- break;
-
- if (VIDEO_MODE_RADIO == msp->norm ||
- MSP_MODE_EXTERN == msp->mode) {
- /* no carrier scan, just unmute */
- msp3400_info("thread: no carrier scan\n");
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- continue;
- }
-
- /* mute */
- msp3400c_setvolume(client, msp->muted, 0, 0);
- msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
- val1 = val2 = 0;
- max1 = max2 = -1;
- msp->watch_stereo = 0;
-
- /* some time for the tuner to sync */
- if (msp34xx_sleep(msp,200))
- goto restart;
-
- /* carrier detect pass #1 -- main carrier */
- cd = carrier_detect_main;
- count = CARRIER_COUNT(carrier_detect_main);
-
- if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
- /* autodetect doesn't work well with AM ... */
- max1 = 3;
- count = 0;
- msp3400_dbg("AM sound override\n");
- }
-
- for (this = 0; this < count; this++) {
- msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
- if (msp34xx_sleep(msp,100))
- goto restart;
- val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
- if (val > 32767)
- val -= 65536;
- if (val1 < val)
- val1 = val, max1 = this;
- msp3400_dbg("carrier1 val: %5d / %s\n", val,cd[this].name);
- }
-
- /* carrier detect pass #2 -- second (stereo) carrier */
- switch (max1) {
- case 1: /* 5.5 */
- cd = carrier_detect_55;
- count = CARRIER_COUNT(carrier_detect_55);
- break;
- case 3: /* 6.5 */
- cd = carrier_detect_65;
- count = CARRIER_COUNT(carrier_detect_65);
- break;
- case 0: /* 4.5 */
- case 2: /* 6.0 */
- default:
- cd = NULL;
- count = 0;
- break;
- }
-
- if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
- /* autodetect doesn't work well with AM ... */
- cd = NULL;
- count = 0;
- max2 = 0;
- }
- for (this = 0; this < count; this++) {
- msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
- if (msp34xx_sleep(msp,100))
- goto restart;
- val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
- if (val > 32767)
- val -= 65536;
- if (val2 < val)
- val2 = val, max2 = this;
- msp3400_dbg("carrier2 val: %5d / %s\n", val,cd[this].name);
- }
-
- /* programm the msp3400 according to the results */
- msp->main = carrier_detect_main[max1].cdo;
- switch (max1) {
- case 1: /* 5.5 */
- if (max2 == 0) {
- /* B/G FM-stereo */
- msp->second = carrier_detect_55[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_TERRA);
- msp->nicam_on = 0;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- msp->watch_stereo = 1;
- } else if (max2 == 1 && HAVE_NICAM(msp)) {
- /* B/G NICAM */
- msp->second = carrier_detect_55[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
- msp->nicam_on = 1;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->watch_stereo = 1;
- } else {
- goto no_second;
- }
- break;
- case 2: /* 6.0 */
- /* PAL I NICAM */
- msp->second = MSP_CARRIER(6.552);
- msp3400c_setmode(client, MSP_MODE_FM_NICAM2);
- msp->nicam_on = 1;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->watch_stereo = 1;
- break;
- case 3: /* 6.5 */
- if (max2 == 1 || max2 == 2) {
- /* D/K FM-stereo */
- msp->second = carrier_detect_65[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_TERRA);
- msp->nicam_on = 0;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- msp->watch_stereo = 1;
- } else if (max2 == 0 &&
- msp->norm == VIDEO_MODE_SECAM) {
- /* L NICAM or AM-mono */
- msp->second = carrier_detect_65[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_AM_NICAM);
- msp->nicam_on = 0;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- msp3400c_setcarrier(client, msp->second, msp->main);
- /* volume prescale for SCART (AM mono input) */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
- msp->watch_stereo = 1;
- } else if (max2 == 0 && HAVE_NICAM(msp)) {
- /* D/K NICAM */
- msp->second = carrier_detect_65[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
- msp->nicam_on = 1;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->watch_stereo = 1;
- } else {
- goto no_second;
- }
- break;
- case 0: /* 4.5 */
- default:
- no_second:
- msp->second = carrier_detect_main[max1].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_TERRA);
- msp->nicam_on = 0;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- break;
- }
-
- /* unmute */
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- msp3400c_restore_dfp(client);
-
- if (debug)
- msp3400c_print_mode(client);
-
- /* monitor tv audio mode */
- while (msp->watch_stereo) {
- if (msp34xx_sleep(msp,5000))
- goto restart;
- watch_stereo(client);
- }
- }
- msp3400_dbg("thread: exit\n");
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-/* this one uses the automatic sound standard detection of newer */
-/* msp34xx chip versions */
-
-static struct MODES {
- int retval;
- int main, second;
- char *name;
-} modelist[] = {
- { 0x0000, 0, 0, "ERROR" },
- { 0x0001, 0, 0, "autodetect start" },
- { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" },
- { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" },
- { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
- { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
- { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
- { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
- { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
- { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
- { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
- { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
- { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
- { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
- { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
- { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" },
- { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" },
- { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" },
- { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" },
- { -1, 0, 0, NULL }, /* EOF */
-};
-
-static inline const char *msp34xx_standard_mode_name(int mode)
-{
- int i;
- for (i = 0; modelist[i].name != NULL; i++)
- if (modelist[i].retval == mode)
- return modelist[i].name;
- return "unknown";
-}
-
-static int msp34xx_modus(struct i2c_client *client, int norm)
-{
- switch (norm) {
- case VIDEO_MODE_PAL:
- msp3400_dbg("video mode selected to PAL\n");
-
-#if 1
- /* experimental: not sure this works with all chip versions */
- return 0x7003;
-#else
- /* previous value, try this if it breaks ... */
- return 0x1003;
-#endif
- case VIDEO_MODE_NTSC: /* BTSC */
- msp3400_dbg("video mode selected to NTSC\n");
- return 0x2003;
- case VIDEO_MODE_SECAM:
- msp3400_dbg("video mode selected to SECAM\n");
- return 0x0003;
- case VIDEO_MODE_RADIO:
- msp3400_dbg("video mode selected to Radio\n");
- return 0x0003;
- case VIDEO_MODE_AUTO:
- msp3400_dbg("video mode selected to Auto\n");
- return 0x2003;
- default:
- return 0x0003;
- }
-}
-
-static int msp34xx_standard(int norm)
-{
- switch (norm) {
- case VIDEO_MODE_PAL:
- return 1;
- case VIDEO_MODE_NTSC: /* BTSC */
- return 0x0020;
- case VIDEO_MODE_SECAM:
- return 1;
- case VIDEO_MODE_RADIO:
- return 0x0040;
- default:
- return 1;
- }
-}
-
-static int msp3410d_thread(void *data)
-{
- struct i2c_client *client = data;
- struct msp3400c *msp = i2c_get_clientdata(client);
- int mode,val,i,std;
-
- msp3400_info("msp3410 daemon started\n");
-
- for (;;) {
- msp3400_dbg_mediumvol("msp3410 thread: sleep\n");
- msp34xx_sleep(msp,-1);
- msp3400_dbg_mediumvol("msp3410 thread: wakeup\n");
-
- restart:
- msp3400_dbg("thread: restart scan\n");
- msp->restart = 0;
- if (kthread_should_stop())
- break;
-
- if (msp->mode == MSP_MODE_EXTERN) {
- /* no carrier scan needed, just unmute */
- msp3400_dbg("thread: no carrier scan\n");
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- continue;
- }
-
- /* put into sane state (and mute) */
- msp3400c_reset(client);
-
- /* some time for the tuner to sync */
- if (msp34xx_sleep(msp,200))
- goto restart;
-
- /* start autodetect */
- mode = msp34xx_modus(client, msp->norm);
- std = msp34xx_standard(msp->norm);
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode);
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std);
- msp->watch_stereo = 0;
-
- if (debug)
- msp3400_dbg("setting mode: %s (0x%04x)\n",
- msp34xx_standard_mode_name(std) ,std);
-
- if (std != 1) {
- /* programmed some specific mode */
- val = std;
- } else {
- /* triggered autodetect */
- for (;;) {
- if (msp34xx_sleep(msp,100))
- goto restart;
-
- /* check results */
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
- if (val < 0x07ff)
- break;
- msp3400_dbg("detection still in progress\n");
- }
- }
- for (i = 0; modelist[i].name != NULL; i++)
- if (modelist[i].retval == val)
- break;
- msp3400_dbg("current mode: %s (0x%04x)\n",
- modelist[i].name ? modelist[i].name : "unknown",
- val);
- msp->main = modelist[i].main;
- msp->second = modelist[i].second;
-
- if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) {
- /* autodetection has failed, let backup */
- msp3400_dbg("autodetection failed,"
- " switching to backup mode: %s (0x%04x)\n",
- modelist[8].name ? modelist[8].name : "unknown",val);
- val = 0x0009;
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val);
- }
-
- /* set various prescales */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */
-
- /* set stereo */
- switch (val) {
- case 0x0008: /* B/G NICAM */
- case 0x000a: /* I NICAM */
- if (val == 0x0008)
- msp->mode = MSP_MODE_FM_NICAM1;
- else
- msp->mode = MSP_MODE_FM_NICAM2;
- /* just turn on stereo */
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->nicam_on = 1;
- msp->watch_stereo = 1;
- msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
- break;
- case 0x0009:
- msp->mode = MSP_MODE_AM_NICAM;
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp->nicam_on = 1;
- msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO);
- msp->watch_stereo = 1;
- break;
- case 0x0020: /* BTSC */
- /* just turn on stereo */
- msp->mode = MSP_MODE_BTSC;
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->nicam_on = 0;
- msp->watch_stereo = 1;
- msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
- break;
- case 0x0040: /* FM radio */
- msp->mode = MSP_MODE_FM_RADIO;
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- msp->nicam_on = 0;
- msp->watch_stereo = 0;
- /* not needed in theory if HAVE_RADIO(), but
- short programming enables carrier mute */
- msp3400c_setmode(client,MSP_MODE_FM_RADIO);
- msp3400c_setcarrier(client, MSP_CARRIER(10.7),
- MSP_CARRIER(10.7));
- /* scart routing */
- msp3400c_set_scart(client,SCART_IN2,0);
- /* msp34xx does radio decoding */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0020);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0020);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0020);
- break;
- case 0x0003:
- case 0x0004:
- case 0x0005:
- msp->mode = MSP_MODE_FM_TERRA;
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp->audmode = V4L2_TUNER_MODE_MONO;
- msp->nicam_on = 0;
- msp->watch_stereo = 1;
- break;
- }
-
- /* unmute, restore misc registers */
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x13, msp->acb);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
- msp3400c_restore_dfp(client);
-
- /* monitor tv audio mode */
- while (msp->watch_stereo) {
- if (msp34xx_sleep(msp,5000))
- goto restart;
- watch_stereo(client);
- }
- }
- msp3400_dbg("thread: exit\n");
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-/* msp34xxG + (simpler no-thread) */
-/* this one uses both automatic standard detection and automatic sound */
-/* select which are available in the newer G versions */
-/* struct msp: only norm, acb and source are really used in this mode */
-
-static void msp34xxg_set_source(struct i2c_client *client, int source);
-
-/* (re-)initialize the msp34xxg, according to the current norm in msp->norm
- * return 0 if it worked, -1 if it failed
- */
-static int msp34xxg_reset(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int modus,std;
-
- if (msp3400c_reset(client))
- return -1;
-
- /* make sure that input/output is muted (paranoid mode) */
- if (msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x13, /* ACB */
- 0x0f20 /* mute DSP input, mute SCART 1 */))
- return -1;
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
-
- /* step-by-step initialisation, as described in the manual */
- modus = msp34xx_modus(client, msp->norm);
- std = msp34xx_standard(msp->norm);
- modus &= ~0x03; /* STATUS_CHANGE=0 */
- modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION=1 */
- if (msp3400c_write(client,
- I2C_MSP3400C_DEM,
- 0x30/*MODUS*/,
- modus))
- return -1;
- if (msp3400c_write(client,
- I2C_MSP3400C_DEM,
- 0x20/*standard*/,
- std))
- return -1;
-
- /* write the dfps that may have an influence on
- standard/audio autodetection right now */
- msp34xxg_set_source(client, msp->source);
-
- if (msp3400c_write_dfp_with_default(client, 0x0e, /* AM/FM Prescale */
- 0x3000
- /* default: [15:8] 75khz deviation */
- ))
- return -1;
-
- if (msp3400c_write_dfp_with_default(client, 0x10, /* NICAM Prescale */
- 0x5a00
- /* default: 9db gain (as recommended) */
- ))
- return -1;
-
- return 0;
-}
-
-static int msp34xxg_thread(void *data)
-{
- struct i2c_client *client = data;
- struct msp3400c *msp = i2c_get_clientdata(client);
- int val, std, i;
-
- msp3400_info("msp34xxg daemon started\n");
-
- msp->source = 1; /* default */
- for (;;) {
- msp3400_dbg_mediumvol("msp34xxg thread: sleep\n");
- msp34xx_sleep(msp,-1);
- msp3400_dbg_mediumvol("msp34xxg thread: wakeup\n");
-
- restart:
- msp3400_dbg("thread: restart scan\n");
- msp->restart = 0;
- if (kthread_should_stop())
- break;
-
- /* setup the chip*/
- msp34xxg_reset(client);
- std = standard;
- if (std != 0x01)
- goto unmute;
-
- /* watch autodetect */
- msp3400_dbg("triggered autodetect, waiting for result\n");
- for (i = 0; i < 10; i++) {
- if (msp34xx_sleep(msp,100))
- goto restart;
-
- /* check results */
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
- if (val < 0x07ff) {
- std = val;
- break;
- }
- msp3400_dbg("detection still in progress\n");
- }
- if (0x01 == std) {
- msp3400_dbg("detection still in progress after 10 tries. giving up.\n");
- continue;
- }
-
- unmute:
- msp3400_dbg("current mode: %s (0x%04x)\n",
- msp34xx_standard_mode_name(std), std);
-
- /* unmute: dispatch sound to scart output, set scart volume */
- msp3400_dbg("unmute\n");
-
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
-
- /* restore ACB */
- if (msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x13, /* ACB */
- msp->acb))
- return -1;
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
- }
- msp3400_dbg("thread: exit\n");
- return 0;
-}
-
-/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
- * the value for source is the same as bit 15:8 of DFP registers 0x08,
- * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
- *
- * this function replaces msp3400c_setstereo
- */
-static void msp34xxg_set_source(struct i2c_client *client, int source)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- /* fix matrix mode to stereo and let the msp choose what
- * to output according to 'source', as recommended
- * for MONO (source==0) downmixing set bit[7:0] to 0x30
- */
- int value = (source&0x07)<<8|(source==0 ? 0x30:0x20);
- msp3400_dbg("set source to %d (0x%x)\n", source, value);
- msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x08, /* Loudspeaker Output */
- value);
- msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x0a, /* SCART1 DA Output */
- value);
- msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x0c, /* Quasi-peak detector */
- value);
- /*
- * set identification threshold. Personally, I
- * I set it to a higher value that the default
- * of 0x190 to ignore noisy stereo signals.
- * this needs tuning. (recommended range 0x00a0-0x03c0)
- * 0x7f0 = forced mono mode
- */
- msp3400c_write(client,
- I2C_MSP3400C_DEM,
- 0x22, /* a2 threshold for stereo/bilingual */
- stereo_threshold);
- msp->source=source;
-}
-
-static void msp34xxg_detect_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- int status = msp3400c_read(client,
- I2C_MSP3400C_DEM,
- 0x0200 /* STATUS */);
- int is_bilingual = status&0x100;
- int is_stereo = status&0x40;
-
- msp->rxsubchans = 0;
- if (is_stereo)
- msp->rxsubchans |= V4L2_TUNER_SUB_STEREO;
- else
- msp->rxsubchans |= V4L2_TUNER_SUB_MONO;
- if (is_bilingual) {
- msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2;
- /* I'm supposed to check whether it's SAP or not
- * and set only LANG2/SAP in this case. Yet, the MSP
- * does a lot of work to hide this and handle everything
- * the same way. I don't want to work around it so unless
- * this is a problem, I'll handle SAP just like lang1/lang2.
- */
- }
- msp3400_dbg("status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
- status, is_stereo, is_bilingual, msp->rxsubchans);
-}
-
-static void msp34xxg_set_audmode(struct i2c_client *client, int audmode)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int source;
-
- switch (audmode) {
- case V4L2_TUNER_MODE_MONO:
- source=0; /* mono only */
- break;
- case V4L2_TUNER_MODE_STEREO:
- source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
- /* problem: that could also mean 2 (scart input) */
- break;
- case V4L2_TUNER_MODE_LANG1:
- source=3; /* stereo or A */
- break;
- case V4L2_TUNER_MODE_LANG2:
- source=4; /* stereo or B */
- break;
- default:
- audmode = 0;
- source = 1;
- break;
- }
- msp->audmode = audmode;
- msp34xxg_set_source(client, source);
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-static int msp_attach(struct i2c_adapter *adap, int addr, int kind);
-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, pm_message_t state);
-static int msp_resume(struct device * dev);
-
-static void msp_wake_thread(struct i2c_client *client);
-
-static struct i2c_driver driver = {
- .id = I2C_DRIVERID_MSP3400,
- .attach_adapter = msp_probe,
- .detach_client = msp_detach,
- .command = msp_command,
- .driver = {
- .name = "i2c msp3400 driver",
- .suspend = msp_suspend,
- .resume = msp_resume,
- },
-};
-
-static struct i2c_client client_template =
-{
- .name = "(unset)",
- .driver = &driver,
-};
-
-static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- struct msp3400c *msp;
- struct i2c_client *client = &client_template;
- int (*thread_func)(void *data) = NULL;
- int i;
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- if (-1 == msp3400c_reset(&client_template)) {
- msp3400_dbg("no chip found\n");
- return -1;
- }
-
- if (NULL == (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
- return -ENOMEM;
- memcpy(client,&client_template,sizeof(struct i2c_client));
- if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) {
- kfree(client);
- return -ENOMEM;
- }
-
- memset(msp,0,sizeof(struct msp3400c));
- msp->norm = VIDEO_MODE_NTSC;
- msp->left = 58880; /* 0db gain */
- msp->right = 58880; /* 0db gain */
- msp->bass = 32768;
- msp->treble = 32768;
- msp->input = -1;
- msp->muted = 0;
- msp->i2s_mode = 0;
- for (i = 0; i < DFP_COUNT; i++)
- msp->dfp_regs[i] = -1;
-
- i2c_set_clientdata(client, msp);
- init_waitqueue_head(&msp->wq);
-
- if (-1 == msp3400c_reset(client)) {
- kfree(msp);
- kfree(client);
- msp3400_dbg("no chip found\n");
- return -1;
- }
-
- msp->rev1 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1e);
- if (-1 != msp->rev1)
- msp->rev2 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1f);
- if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) {
- kfree(msp);
- kfree(client);
- msp3400_dbg("error while reading chip version\n");
- return -1;
- }
- msp3400_dbg("rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2);
-
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
-
- snprintf(client->name, sizeof(client->name), "MSP%c4%02d%c-%c%d",
- ((msp->rev1>>4)&0x0f) + '3',
- (msp->rev2>>8)&0xff, (msp->rev1&0x0f)+'@',
- ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f);
-
- msp->opmode = opmode;
- if (OPMODE_AUTO == msp->opmode) {
- if (HAVE_SIMPLER(msp))
- msp->opmode = OPMODE_SIMPLER;
- else if (HAVE_SIMPLE(msp))
- msp->opmode = OPMODE_SIMPLE;
- else
- msp->opmode = OPMODE_MANUAL;
- }
-
- /* hello world :-) */
- msp3400_info("chip=%s", client->name);
- if (HAVE_NICAM(msp))
- printk(" +nicam");
- if (HAVE_SIMPLE(msp))
- printk(" +simple");
- if (HAVE_SIMPLER(msp))
- printk(" +simpler");
- if (HAVE_RADIO(msp))
- printk(" +radio");
-
- /* version-specific initialization */
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- printk(" mode=manual");
- thread_func = msp3400c_thread;
- break;
- case OPMODE_SIMPLE:
- printk(" mode=simple");
- thread_func = msp3410d_thread;
- break;
- case OPMODE_SIMPLER:
- printk(" mode=simpler");
- thread_func = msp34xxg_thread;
- break;
- }
- printk("\n");
-
- /* startup control thread if needed */
- if (thread_func) {
- msp->kthread = kthread_run(thread_func, client, "msp34xx");
-
- if (NULL == msp->kthread)
- msp3400_warn("kernel_thread() failed\n");
- msp_wake_thread(client);
- }
-
- /* done */
- i2c_attach_client(client);
-
- /* update our own array */
- for (i = 0; i < MSP3400_MAX; i++) {
- if (NULL == msps[i]) {
- msps[i] = client;
- break;
- }
- }
-
- return 0;
-}
-
-static int msp_detach(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
-
- /* shutdown control thread */
- if (msp->kthread) {
- msp->restart = 1;
- kthread_stop(msp->kthread);
- }
- msp3400c_reset(client);
-
- /* update our own array */
- for (i = 0; i < MSP3400_MAX; i++) {
- if (client == msps[i]) {
- msps[i] = NULL;
- break;
- }
- }
-
- i2c_detach_client(client);
-
- kfree(msp);
- kfree(client);
- return 0;
-}
-
-static int msp_probe(struct i2c_adapter *adap)
-{
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, msp_attach);
- return 0;
-}
-
-static void msp_wake_thread(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- if (NULL == msp->kthread)
- return;
- msp3400c_setvolume(client,msp->muted,0,0);
- msp->watch_stereo = 0;
- msp->restart = 1;
- wake_up_interruptible(&msp->wq);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int mode_v4l2_to_v4l1(int rxsubchans)
-{
- int mode = 0;
-
- if (rxsubchans & V4L2_TUNER_SUB_STEREO)
- mode |= VIDEO_SOUND_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG2)
- mode |= VIDEO_SOUND_LANG2;
- if (rxsubchans & V4L2_TUNER_SUB_LANG1)
- mode |= VIDEO_SOUND_LANG1;
- if (0 == mode)
- mode |= VIDEO_SOUND_MONO;
- return mode;
-}
-
-static int mode_v4l1_to_v4l2(int mode)
-{
- if (mode & VIDEO_SOUND_STEREO)
- return V4L2_TUNER_MODE_STEREO;
- if (mode & VIDEO_SOUND_LANG2)
- return V4L2_TUNER_MODE_LANG2;
- if (mode & VIDEO_SOUND_LANG1)
- return V4L2_TUNER_MODE_LANG1;
- return V4L2_TUNER_MODE_MONO;
-}
-
-static void msp_any_detect_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- case OPMODE_SIMPLE:
- autodetect_stereo(client);
- break;
- case OPMODE_SIMPLER:
- msp34xxg_detect_stereo(client);
- break;
- }
-}
-
-static void msp_any_set_audmode(struct i2c_client *client, int audmode)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- case OPMODE_SIMPLE:
- msp->watch_stereo = 0;
- msp3400c_setstereo(client, audmode);
- break;
- case OPMODE_SIMPLER:
- msp34xxg_set_audmode(client, audmode);
- break;
- }
-}
-
-
-static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- __u16 *sarg = arg;
- int scart = 0;
-
- switch (cmd) {
-
- case AUDC_SET_INPUT:
- msp3400_dbg("AUDC_SET_INPUT(%d)\n",*sarg);
-
- if (*sarg == msp->input)
- break;
- msp->input = *sarg;
- switch (*sarg) {
- case AUDIO_RADIO:
- /* Hauppauge uses IN2 for the radio */
- msp->mode = MSP_MODE_FM_RADIO;
- scart = SCART_IN2;
- break;
- case AUDIO_EXTERN_1:
- /* IN1 is often used for external input ... */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN1;
- break;
- case AUDIO_EXTERN_2:
- /* ... sometimes it is IN2 through ;) */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN2;
- break;
- case AUDIO_TUNER:
- msp->mode = -1;
- break;
- default:
- if (*sarg & AUDIO_MUTE)
- msp3400c_set_scart(client,SCART_MUTE,0);
- break;
- }
- if (scart) {
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- msp3400c_set_scart(client,scart,0);
- msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
- if (msp->opmode != OPMODE_SIMPLER)
- msp3400c_setstereo(client, msp->audmode);
- }
- msp_wake_thread(client);
- break;
-
- case AUDC_SET_RADIO:
- msp3400_dbg("AUDC_SET_RADIO\n");
- msp->norm = VIDEO_MODE_RADIO;
- msp3400_dbg("switching to radio mode\n");
- msp->watch_stereo = 0;
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- /* set msp3400 to FM radio mode */
- msp3400c_setmode(client,MSP_MODE_FM_RADIO);
- msp3400c_setcarrier(client, MSP_CARRIER(10.7),
- MSP_CARRIER(10.7));
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- break;
- case OPMODE_SIMPLE:
- case OPMODE_SIMPLER:
- /* the thread will do for us */
- msp_wake_thread(client);
- break;
- }
- break;
- /* work-in-progress: hook to control the DFP registers */
- case MSP_SET_DFPREG:
- {
- struct msp_dfpreg *r = arg;
- int i;
-
- if (r->reg < 0 || r->reg >= DFP_COUNT)
- return -EINVAL;
- for (i = 0; i < sizeof(bl_dfp) / sizeof(int); i++)
- if (r->reg == bl_dfp[i])
- return -EINVAL;
- msp->dfp_regs[r->reg] = r->value;
- msp3400c_write(client, I2C_MSP3400C_DFP, r->reg, r->value);
- return 0;
- }
- case MSP_GET_DFPREG:
- {
- struct msp_dfpreg *r = arg;
-
- if (r->reg < 0 || r->reg >= DFP_COUNT)
- return -EINVAL;
- r->value = msp3400c_read(client, I2C_MSP3400C_DFP, r->reg);
- return 0;
- }
-
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
- case VIDIOCGAUDIO:
- {
- struct video_audio *va = arg;
-
- msp3400_dbg("VIDIOCGAUDIO\n");
- va->flags |= VIDEO_AUDIO_VOLUME |
- VIDEO_AUDIO_BASS |
- VIDEO_AUDIO_TREBLE |
- VIDEO_AUDIO_MUTABLE;
- if (msp->muted)
- va->flags |= VIDEO_AUDIO_MUTE;
-
- if (msp->muted)
- va->flags |= VIDEO_AUDIO_MUTE;
- va->volume = MAX(msp->left, msp->right);
- va->balance = (32768 * MIN(msp->left, msp->right)) /
- (va->volume ? va->volume : 1);
- va->balance = (msp->left < msp->right) ?
- (65535 - va->balance) : va->balance;
- if (0 == va->volume)
- va->balance = 32768;
- va->bass = msp->bass;
- va->treble = msp->treble;
-
- msp_any_detect_stereo(client);
- va->mode = mode_v4l2_to_v4l1(msp->rxsubchans);
- break;
- }
- case VIDIOCSAUDIO:
- {
- struct video_audio *va = arg;
-
- msp3400_dbg("VIDIOCSAUDIO\n");
- msp->muted = (va->flags & VIDEO_AUDIO_MUTE);
- msp->left = (MIN(65536 - va->balance, 32768) *
- va->volume) / 32768;
- msp->right = (MIN(va->balance, 32768) * va->volume) / 32768;
- msp->bass = va->bass;
- msp->treble = va->treble;
- msp3400_dbg("VIDIOCSAUDIO setting va->volume to %d\n",
- va->volume);
- msp3400_dbg("VIDIOCSAUDIO setting va->balance to %d\n",
- va->balance);
- msp3400_dbg("VIDIOCSAUDIO setting va->flags to %d\n",
- va->flags);
- msp3400_dbg("VIDIOCSAUDIO setting msp->left to %d\n",
- msp->left);
- msp3400_dbg("VIDIOCSAUDIO setting msp->right to %d\n",
- msp->right);
- msp3400_dbg("VIDIOCSAUDIO setting msp->bass to %d\n",
- msp->bass);
- msp3400_dbg("VIDIOCSAUDIO setting msp->treble to %d\n",
- msp->treble);
- msp3400_dbg("VIDIOCSAUDIO setting msp->mode to %d\n",
- msp->mode);
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
-
- if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO)
- msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode));
- break;
- }
-
- case VIDIOCSCHAN:
- {
- struct video_channel *vc = arg;
-
- msp3400_dbg("VIDIOCSCHAN (norm=%d)\n",vc->norm);
- msp->norm = vc->norm;
- msp_wake_thread(client);
- break;
- }
-
- case VIDIOCSFREQ:
- case VIDIOC_S_FREQUENCY:
- {
- /* new channel -- kick audio carrier scan */
- msp3400_dbg("VIDIOCSFREQ\n");
- msp_wake_thread(client);
- break;
- }
-
- /* msp34xx specific */
- case MSP_SET_MATRIX:
- {
- struct msp_matrix *mspm = arg;
-
- msp3400_dbg("MSP_SET_MATRIX\n");
- msp3400c_set_scart(client, mspm->input, mspm->output);
- break;
- }
-
- /* --- v4l2 ioctls --- */
- case VIDIOC_S_STD:
- {
- v4l2_std_id *id = arg;
-
- /*FIXME: use V4L2 mode flags on msp3400 instead of V4L1*/
- if (*id & V4L2_STD_PAL) {
- msp->norm=VIDEO_MODE_PAL;
- } else if (*id & V4L2_STD_SECAM) {
- msp->norm=VIDEO_MODE_SECAM;
- } else {
- msp->norm=VIDEO_MODE_NTSC;
- }
-
- msp_wake_thread(client);
- return 0;
- }
-
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input *i = arg;
-
- if (i->index != 0)
- return -EINVAL;
-
- i->type = V4L2_INPUT_TYPE_TUNER;
- switch (i->index) {
- case AUDIO_RADIO:
- strcpy(i->name,"Radio");
- break;
- case AUDIO_EXTERN_1:
- strcpy(i->name,"Extern 1");
- break;
- case AUDIO_EXTERN_2:
- strcpy(i->name,"Extern 2");
- break;
- case AUDIO_TUNER:
- strcpy(i->name,"Television");
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
-
- case VIDIOC_G_AUDIO:
- {
- struct v4l2_audio *a = arg;
-
- memset(a,0,sizeof(*a));
-
- switch (a->index) {
- case AUDIO_RADIO:
- strcpy(a->name,"Radio");
- break;
- case AUDIO_EXTERN_1:
- strcpy(a->name,"Extern 1");
- break;
- case AUDIO_EXTERN_2:
- strcpy(a->name,"Extern 2");
- break;
- case AUDIO_TUNER:
- strcpy(a->name,"Television");
- break;
- default:
- return -EINVAL;
- }
-
- msp_any_detect_stereo(client);
- if (msp->audmode == V4L2_TUNER_MODE_STEREO) {
- a->capability=V4L2_AUDCAP_STEREO;
- }
-
- break;
- }
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *sarg = arg;
-
- switch (sarg->index) {
- case AUDIO_RADIO:
- /* Hauppauge uses IN2 for the radio */
- msp->mode = MSP_MODE_FM_RADIO;
- scart = SCART_IN2;
- break;
- case AUDIO_EXTERN_1:
- /* IN1 is often used for external input ... */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN1;
- break;
- case AUDIO_EXTERN_2:
- /* ... sometimes it is IN2 through ;) */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN2;
- break;
- case AUDIO_TUNER:
- msp->mode = -1;
- break;
- }
- if (scart) {
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- msp3400c_set_scart(client,scart,0);
- msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
- }
- if (sarg->capability==V4L2_AUDCAP_STEREO) {
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- } else {
- msp->audmode &= ~V4L2_TUNER_MODE_STEREO;
- }
- msp_any_set_audmode(client, msp->audmode);
- msp_wake_thread(client);
- break;
- }
- case VIDIOC_G_TUNER:
- {
- struct v4l2_tuner *vt = arg;
-
- msp_any_detect_stereo(client);
- vt->audmode = msp->audmode;
- vt->rxsubchans = msp->rxsubchans;
- vt->capability = V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_LANG1|
- V4L2_TUNER_CAP_LANG2;
- break;
- }
- case VIDIOC_S_TUNER:
- {
- struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
-
- /* only set audmode */
- if (vt->audmode != -1 && vt->audmode != 0)
- msp_any_set_audmode(client, vt->audmode);
- break;
- }
-
- case VIDIOC_G_AUDOUT:
- {
- struct v4l2_audioout *a=(struct v4l2_audioout *)arg;
- int idx=a->index;
-
- memset(a,0,sizeof(*a));
-
- switch (idx) {
- case 0:
- strcpy(a->name,"Scart1 Out");
- break;
- case 1:
- strcpy(a->name,"Scart2 Out");
- break;
- case 2:
- strcpy(a->name,"I2S Out");
- break;
- default:
- return -EINVAL;
- }
- break;
-
- }
- case VIDIOC_S_AUDOUT:
- {
- struct v4l2_audioout *a=(struct v4l2_audioout *)arg;
-
- if (a->index<0||a->index>2)
- return -EINVAL;
-
- if (a->index==2) {
- if (a->mode == V4L2_AUDMODE_32BITS)
- msp->i2s_mode=1;
- else
- msp->i2s_mode=0;
- }
- msp3400_dbg("Setting audio out on msp34xx to input %i, mode %i\n",
- a->index,msp->i2s_mode);
- msp3400c_set_scart(client,msp->in_scart,a->index+1);
-
- break;
- }
-
- default:
- /* nothing */
- break;
- }
- return 0;
-}
-
-static int msp_suspend(struct device * dev, pm_message_t state)
-{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-
- msp3400_dbg("msp34xx: suspend\n");
- msp3400c_reset(client);
- return 0;
-}
-
-static int msp_resume(struct device * dev)
-{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-
- msp3400_dbg("msp34xx: resume\n");
- msp_wake_thread(client);
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int __init msp3400_init_module(void)
-{
- return i2c_add_driver(&driver);
-}
-
-static void __exit msp3400_cleanup_module(void)
-{
- i2c_del_driver(&driver);
-}
-
-module_init(msp3400_init_module);
-module_exit(msp3400_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/msp3400.h b/drivers/media/video/msp3400.h
index 2d9ff40f0b09..a9ac57d0700b 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -6,21 +6,19 @@
/* ---------------------------------------------------------------------- */
-struct msp_dfpreg {
- int reg;
- int value;
-};
-
-struct msp_matrix {
- int input;
- int output;
-};
-
-#define MSP_SET_DFPREG _IOW('m',15,struct msp_dfpreg)
-#define MSP_GET_DFPREG _IOW('m',16,struct msp_dfpreg)
+/* This macro is allowed for *constants* only, gcc must calculate it
+ at compile time. Remember -- no floats in kernel mode */
+#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24)))
-/* ioctl for MSP_SET_MATRIX will have to be registered */
-#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
+#define MSP_MODE_AM_DETECT 0
+#define MSP_MODE_FM_RADIO 2
+#define MSP_MODE_FM_TERRA 3
+#define MSP_MODE_FM_SAT 4
+#define MSP_MODE_FM_NICAM1 5
+#define MSP_MODE_FM_NICAM2 6
+#define MSP_MODE_AM_NICAM 7
+#define MSP_MODE_BTSC 8
+#define MSP_MODE_EXTERN 9
#define SCART_MASK 0
#define SCART_IN1 1
@@ -36,4 +34,84 @@ struct msp_matrix {
#define SCART1_OUT 1
#define SCART2_OUT 2
+#define OPMODE_AUTO -1
+#define OPMODE_MANUAL 0
+#define OPMODE_AUTODETECT 1 /* use autodetect (>= msp3410 only) */
+#define OPMODE_AUTOSELECT 2 /* use autodetect & autoselect (>= msp34xxG) */
+
+/* module parameters */
+extern int msp_debug;
+extern int msp_once;
+extern int msp_amsound;
+extern int msp_standard;
+extern int msp_dolby;
+extern int msp_stereo_thresh;
+
+struct msp_state {
+ int rev1, rev2;
+ u8 has_nicam;
+ u8 has_radio;
+ u8 has_headphones;
+ u8 has_ntsc_jp_d_k3;
+ u8 has_scart4;
+ u8 has_scart23_in_scart2_out;
+ u8 has_scart2_out_volume;
+ u8 has_i2s_conf;
+ u8 has_subwoofer;
+ u8 has_sound_processing;
+ u8 has_virtual_dolby_surround;
+ u8 has_dolby_pro_logic;
+
+ int radio;
+ int opmode;
+ int std;
+ int mode;
+ v4l2_std_id v4l2_std;
+ int nicam_on;
+ int acb;
+ int in_scart;
+ int i2s_mode;
+ int main, second; /* sound carrier */
+ int input;
+ int source; /* see msp34xxg_set_source */
+
+ /* v4l2 */
+ int audmode;
+ int rxsubchans;
+
+ int volume, muted;
+ int balance, loudness;
+ int bass, treble;
+
+ /* thread */
+ struct task_struct *kthread;
+ wait_queue_head_t wq;
+ int restart:1;
+ int watch_stereo:1;
+};
+
+/* msp3400-driver.c */
+int msp_write_dem(struct i2c_client *client, int addr, int val);
+int msp_write_dsp(struct i2c_client *client, int addr, int val);
+int msp_read_dem(struct i2c_client *client, int addr);
+int msp_read_dsp(struct i2c_client *client, int addr);
+int msp_reset(struct i2c_client *client);
+void msp_set_scart(struct i2c_client *client, int in, int out);
+void msp_set_mute(struct i2c_client *client);
+void msp_set_audio(struct i2c_client *client);
+int msp_modus(struct i2c_client *client);
+int msp_sleep(struct msp_state *state, int timeout);
+
+/* msp3400-kthreads.c */
+const char *msp_standard_std_name(int std);
+void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2);
+void msp3400c_setmode(struct i2c_client *client, int type);
+void msp3400c_setstereo(struct i2c_client *client, int mode);
+int autodetect_stereo(struct i2c_client *client);
+int msp3400c_thread(void *data);
+int msp3410d_thread(void *data);
+int msp34xxg_thread(void *data);
+void msp34xxg_detect_stereo(struct i2c_client *client);
+void msp34xxg_set_audmode(struct i2c_client *client, int audmode);
+
#endif /* MSP3400_H */
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index 2180018f06de..c7c9f3f8715c 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -20,6 +20,9 @@ module_param(tv_antenna, int, 0644);
static unsigned int radio_antenna = 0;
module_param(radio_antenna, int, 0644);
+/* from tuner-core.c */
+extern int tuner_debug;
+
/* ---------------------------------------------------------------------- */
#define MT2032 0x04
@@ -350,8 +353,8 @@ static int mt2032_init(struct i2c_client *c)
} while (xok != 1 );
t->xogc=xogc;
- t->tv_freq = mt2032_set_tv_freq;
- t->radio_freq = mt2032_set_radio_freq;
+ t->set_tv_freq = mt2032_set_tv_freq;
+ t->set_radio_freq = mt2032_set_radio_freq;
return(1);
}
@@ -478,8 +481,8 @@ static int mt2050_init(struct i2c_client *c)
i2c_master_recv(c,buf,1);
tuner_dbg("mt2050: sro is %x\n",buf[0]);
- t->tv_freq = mt2050_set_tv_freq;
- t->radio_freq = mt2050_set_radio_freq;
+ t->set_tv_freq = mt2050_set_tv_freq;
+ t->set_radio_freq = mt2050_set_radio_freq;
return 0;
}
@@ -491,9 +494,16 @@ int microtune_init(struct i2c_client *c)
int company_code;
memset(buf,0,sizeof(buf));
- t->tv_freq = NULL;
- t->radio_freq = NULL;
+ t->set_tv_freq = NULL;
+ t->set_radio_freq = NULL;
t->standby = NULL;
+ if (t->std & V4L2_STD_525_60) {
+ tuner_dbg("pinnacle ntsc\n");
+ t->radio_if2 = 41300 * 1000;
+ } else {
+ tuner_dbg("pinnacle pal\n");
+ t->radio_if2 = 33300 * 1000;
+ }
name = "unknown";
i2c_master_send(c,buf,1);
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index d04793fb80fc..8416ceff524b 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -26,6 +26,7 @@
#include <media/saa7146_vv.h>
#include <media/tuner.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
#include "mxb.h"
#include "tea6415c.h"
@@ -176,12 +177,11 @@ static int mxb_probe(struct saa7146_dev* dev)
return -ENODEV;
}
- mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);
+ mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
if( NULL == mxb ) {
DEB_D(("not enough kernel memory.\n"));
return -ENOMEM;
}
- memset(mxb, 0x0, sizeof(struct mxb));
mxb->i2c_adapter = (struct i2c_adapter) {
.class = I2C_CLASS_TV_ANALOG,
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
index b3f4d266cede..c04130dab127 100644
--- a/drivers/media/video/ovcamchip/ov6x20.c
+++ b/drivers/media/video/ovcamchip/ov6x20.c
@@ -178,10 +178,9 @@ static int ov6x20_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
index 6eab458ab792..73b94f51a85a 100644
--- a/drivers/media/video/ovcamchip/ov6x30.c
+++ b/drivers/media/video/ovcamchip/ov6x30.c
@@ -141,10 +141,9 @@ static int ov6x30_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov76be.c b/drivers/media/video/ovcamchip/ov76be.c
index 29bbdc05e3b6..11f6be924d8b 100644
--- a/drivers/media/video/ovcamchip/ov76be.c
+++ b/drivers/media/video/ovcamchip/ov76be.c
@@ -105,10 +105,9 @@ static int ov76be_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov7x10.c b/drivers/media/video/ovcamchip/ov7x10.c
index 6c383d4b14fa..5206e7913924 100644
--- a/drivers/media/video/ovcamchip/ov7x10.c
+++ b/drivers/media/video/ovcamchip/ov7x10.c
@@ -115,10 +115,9 @@ static int ov7x10_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov7x20.c b/drivers/media/video/ovcamchip/ov7x20.c
index 3c8c48f338ba..8e26ae338f31 100644
--- a/drivers/media/video/ovcamchip/ov7x20.c
+++ b/drivers/media/video/ovcamchip/ov7x20.c
@@ -232,10 +232,9 @@ static int ov7x20_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = DFL_AUTO_EXP;
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 428f1bb75ec3..e76b53d5909c 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -316,12 +316,11 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
c->adapter = adap;
strcpy(c->name, "OV????");
- ov = kmalloc(sizeof *ov, GFP_KERNEL);
+ ov = kzalloc(sizeof *ov, GFP_KERNEL);
if (!ov) {
rc = -ENOMEM;
goto no_ov;
}
- memset(ov, 0, sizeof *ov);
i2c_set_clientdata(c, ov);
rc = ovcamchip_detect(c);
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index b19c33434eaf..f3fc361bec97 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -76,9 +76,9 @@ static volatile struct planb_registers *planb_regs;
static int def_norm = PLANB_DEF_NORM; /* default norm */
static int video_nr = -1;
-MODULE_PARM(def_norm, "i");
+module_param(def_norm, int, 0);
MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
-MODULE_PARM(video_nr,"i");
+module_param(video_nr, int, 0);
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 2504207b2e3d..9e6448639480 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -883,6 +883,7 @@ static struct file_operations pms_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = pms_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = pms_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 0aa9e72f632c..2ce010201308 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -83,13 +83,12 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client));
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t==NULL)
{
kfree(client);
return -ENOMEM;
}
- memset(t, 0, sizeof(*t));
strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
init_MUTEX(&t->lock);
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index a51c7bd96618..5694eb58c3a1 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -151,13 +151,12 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client));
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t==NULL)
{
kfree(client);
return -ENOMEM;
}
- memset(t, 0, sizeof(*t));
strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
init_MUTEX(&t->lock);
@@ -165,7 +164,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
* Now create a video4linux device
*/
- vd = (struct video_device *)kmalloc(sizeof(struct video_device), GFP_KERNEL);
+ vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
if(vd==NULL)
{
kfree(t);
@@ -702,6 +701,7 @@ static struct file_operations saa_fops = {
.open = saa5249_open,
.release = saa5249_release,
.ioctl = saa5249_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index d60a783e0473..d17395c4f55c 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -50,15 +50,15 @@ static unsigned int rbds = 0;
static unsigned int plvl = 0;
static unsigned int bufblocks = 100;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
-MODULE_PARM(xtal, "i");
+module_param(xtal, int, 0);
MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
-MODULE_PARM(rbds, "i");
+module_param(rbds, int, 0);
MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
-MODULE_PARM(plvl, "i");
+module_param(plvl, int, 0);
MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
-MODULE_PARM(bufblocks, "i");
+module_param(bufblocks, int, 0);
MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
@@ -427,18 +427,8 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
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_HW_B_BT848:
- case I2C_HW_B_RIVA:
- case I2C_HW_SAA7134:
- return i2c_probe(adap, &addr_data, saa6588_attach);
- break;
- }
-#endif
return 0;
}
@@ -496,7 +486,7 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd,
static struct i2c_driver driver = {
.driver = {
- .name = "i2c saa6588 driver",
+ .name = "saa6588",
},
.id = -1, /* FIXME */
.attach_adapter = saa6588_probe,
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 619ff0b7a1ff..7bb85a7b326e 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -494,21 +494,19 @@ saa7110_detect_client (struct i2c_adapter *adapter,
I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7110;
strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
if (decoder == 0) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa7110));
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index acaeee592b54..8c06592b37ff 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -511,21 +511,19 @@ saa7111_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7111;
strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa7111));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index b7ac0122f729..fd0a4b4ef014 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -852,21 +852,19 @@ saa7114_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7114;
strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa7114), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa7114));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = -1;
decoder->enable = 1;
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 29e28c742cd4..048d000941c7 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -39,31 +39,18 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/audiochip.h>
+#include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil");
MODULE_LICENSE("GPL");
static int debug = 0;
-module_param(debug, int, 0644);
+module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define saa7115_dbg(fmt,arg...) \
- do { \
- if (debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define saa7115_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define saa7115_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
@@ -73,12 +60,13 @@ struct saa7115_state {
v4l2_std_id std;
int input;
int enable;
+ int radio;
int bright;
int contrast;
int hue;
int sat;
enum v4l2_chip_ident ident;
- enum v4l2_audio_clock_freq audclk_freq;
+ u32 audclk_freq;
};
/* ----------------------------------------------------------------------- */
@@ -469,80 +457,6 @@ static const unsigned char saa7115_init_misc[] = {
0x00, 0x00
};
-/* ============== SAA7715 AUDIO settings ============= */
-
-/* 48.0 kHz */
-static const unsigned char saa7115_cfg_48_audio[] = {
- 0x34, 0xce,
- 0x35, 0xfb,
- 0x36, 0x30,
- 0x00, 0x00
-};
-
-/* 44.1 kHz */
-static const unsigned char saa7115_cfg_441_audio[] = {
- 0x34, 0xf2,
- 0x35, 0x00,
- 0x36, 0x2d,
- 0x00, 0x00
-};
-
-/* 32.0 kHz */
-static const unsigned char saa7115_cfg_32_audio[] = {
- 0x34, 0xdf,
- 0x35, 0xa7,
- 0x36, 0x20,
- 0x00, 0x00
-};
-
-/* 48.0 kHz 60hz */
-static const unsigned char saa7115_cfg_60hz_48_audio[] = {
- 0x30, 0xcd,
- 0x31, 0x20,
- 0x32, 0x03,
- 0x00, 0x00
-};
-
-/* 48.0 kHz 50hz */
-static const unsigned char saa7115_cfg_50hz_48_audio[] = {
- 0x30, 0x00,
- 0x31, 0xc0,
- 0x32, 0x03,
- 0x00, 0x00
-};
-
-/* 44.1 kHz 60hz */
-static const unsigned char saa7115_cfg_60hz_441_audio[] = {
- 0x30, 0xbc,
- 0x31, 0xdf,
- 0x32, 0x02,
- 0x00, 0x00
-};
-
-/* 44.1 kHz 50hz */
-static const unsigned char saa7115_cfg_50hz_441_audio[] = {
- 0x30, 0x00,
- 0x31, 0x72,
- 0x32, 0x03,
- 0x00, 0x00
-};
-
-/* 32.0 kHz 60hz */
-static const unsigned char saa7115_cfg_60hz_32_audio[] = {
- 0x30, 0xde,
- 0x31, 0x15,
- 0x32, 0x02,
- 0x00, 0x00
-};
-
-/* 32.0 kHz 50hz */
-static const unsigned char saa7115_cfg_50hz_32_audio[] = {
- 0x30, 0x00,
- 0x31, 0x80,
- 0x32, 0x02,
- 0x00, 0x00
-};
-
static int saa7115_odd_parity(u8 c)
{
c ^= (c >> 4);
@@ -627,40 +541,38 @@ static int saa7115_decode_wss(u8 * p)
}
-static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq)
+static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
{
struct saa7115_state *state = i2c_get_clientdata(client);
+ u32 acpf;
+ u32 acni;
+ u32 hz;
+ u64 f;
- saa7115_dbg("set audio clock freq: %d\n", freq);
- switch (freq) {
- case V4L2_AUDCLK_32_KHZ:
- saa7115_writeregs(client, saa7115_cfg_32_audio);
- if (state->std & V4L2_STD_525_60) {
- saa7115_writeregs(client, saa7115_cfg_60hz_32_audio);
- } else {
- saa7115_writeregs(client, saa7115_cfg_50hz_32_audio);
- }
- break;
- case V4L2_AUDCLK_441_KHZ:
- saa7115_writeregs(client, saa7115_cfg_441_audio);
- if (state->std & V4L2_STD_525_60) {
- saa7115_writeregs(client, saa7115_cfg_60hz_441_audio);
- } else {
- saa7115_writeregs(client, saa7115_cfg_50hz_441_audio);
- }
- break;
- case V4L2_AUDCLK_48_KHZ:
- saa7115_writeregs(client, saa7115_cfg_48_audio);
- if (state->std & V4L2_STD_525_60) {
- saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
- } else {
- saa7115_writeregs(client, saa7115_cfg_50hz_48_audio);
- }
- break;
- default:
- saa7115_dbg("invalid audio setting %d\n", freq);
- return -EINVAL;
- }
+ v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
+
+ /* sanity check */
+ if (freq < 32000 || freq > 48000)
+ return -EINVAL;
+
+ /* hz is the refresh rate times 100 */
+ hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
+ /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
+ acpf = (25600 * freq) / hz;
+ /* acni = (256 * freq * 2^23) / crystal_frequency =
+ (freq * 2^(8+23)) / crystal_frequency =
+ (freq << 31) / 32.11 MHz */
+ f = freq;
+ f = f << 31;
+ do_div(f, 32110000);
+ acni = f;
+
+ saa7115_write(client, 0x30, acpf & 0xff);
+ saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
+ saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
+ saa7115_write(client, 0x34, acni & 0xff);
+ saa7115_write(client, 0x35, (acni >> 8) & 0xff);
+ saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
state->audclk_freq = freq;
return 0;
}
@@ -672,7 +584,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if (ctrl->value < 0 || ctrl->value > 255) {
- saa7115_err("invalid brightness setting %d\n", ctrl->value);
+ v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -682,7 +594,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
case V4L2_CID_CONTRAST:
if (ctrl->value < 0 || ctrl->value > 127) {
- saa7115_err("invalid contrast setting %d\n", ctrl->value);
+ v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -692,7 +604,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
case V4L2_CID_SATURATION:
if (ctrl->value < 0 || ctrl->value > 127) {
- saa7115_err("invalid saturation setting %d\n", ctrl->value);
+ v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -702,13 +614,16 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
case V4L2_CID_HUE:
if (ctrl->value < -127 || ctrl->value > 127) {
- saa7115_err("invalid hue setting %d\n", ctrl->value);
+ v4l_err(client, "invalid hue setting %d\n", ctrl->value);
return -ERANGE;
}
state->hue = ctrl->value;
saa7115_write(client, 0x0d, state->hue);
break;
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -743,12 +658,22 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
struct saa7115_state *state = i2c_get_clientdata(client);
int taskb = saa7115_read(client, 0x80) & 0x10;
+ /* Prevent unnecessary standard changes. During a standard
+ change the I-Port is temporarily disabled. Any devices
+ reading from that port can get confused.
+ Note that VIDIOC_S_STD is also used to switch from
+ radio to TV mode, so if a VIDIOC_S_STD is broadcast to
+ all I2C devices then you do not want to have an unwanted
+ side-effect here. */
+ if (std == state->std)
+ return;
+
// This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
if (std & V4L2_STD_525_60) {
- saa7115_dbg("decoder set standard 60 Hz\n");
+ v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
saa7115_writeregs(client, saa7115_cfg_60hz_video);
} else {
- saa7115_dbg("decoder set standard 50 Hz\n");
+ v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
saa7115_writeregs(client, saa7115_cfg_50hz_video);
}
@@ -773,24 +698,17 @@ static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
static void saa7115_log_status(struct i2c_client *client)
{
struct saa7115_state *state = i2c_get_clientdata(client);
- char *audfreq = "undefined";
int reg1e, reg1f;
int signalOk;
int vcr;
- switch (state->audclk_freq) {
- case V4L2_AUDCLK_32_KHZ: audfreq = "32 kHz"; break;
- case V4L2_AUDCLK_441_KHZ: audfreq = "44.1 kHz"; break;
- case V4L2_AUDCLK_48_KHZ: audfreq = "48 kHz"; break;
- }
-
- saa7115_info("Audio frequency: %s\n", audfreq);
+ v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq);
if (client->name[6] == '4') {
/* status for the saa7114 */
reg1f = saa7115_read(client, 0x1f);
signalOk = (reg1f & 0xc1) == 0x81;
- saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad");
- saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz");
+ v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad");
+ v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
return;
}
@@ -801,21 +719,26 @@ static void saa7115_log_status(struct i2c_client *client)
signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
vcr = !(reg1f & 0x10);
- saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
- saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz");
+ if (state->input >= 6) {
+ v4l_info(client, "Input: S-Video %d\n", state->input - 6);
+ } else {
+ v4l_info(client, "Input: Composite %d\n", state->input);
+ }
+ v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
+ v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
switch (reg1e & 0x03) {
case 1:
- saa7115_info("Detected format: NTSC\n");
+ v4l_info(client, "Detected format: NTSC\n");
break;
case 2:
- saa7115_info("Detected format: PAL\n");
+ v4l_info(client, "Detected format: PAL\n");
break;
case 3:
- saa7115_info("Detected format: SECAM\n");
+ v4l_info(client, "Detected format: SECAM\n");
break;
default:
- saa7115_info("Detected format: BW/No color\n");
+ v4l_info(client, "Detected format: BW/No color\n");
break;
}
}
@@ -940,7 +863,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
pix = &(fmt->fmt.pix);
- saa7115_dbg("decoder set size\n");
+ v4l_dbg(1, debug, client, "decoder set size\n");
/* FIXME need better bounds checking here */
if ((pix->width < 1) || (pix->width > 1440))
@@ -966,7 +889,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
HPSC = HPSC ? HPSC : 1;
HFSC = (int)((1024 * 720) / (HPSC * pix->width));
- saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
+ v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
/* FIXME hardcodes to "Task B"
* write H prescaler integer */
saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
@@ -980,10 +903,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
} else {
if (is_50hz) {
- saa7115_dbg("Setting full 50hz width\n");
+ v4l_dbg(1, debug, client, "Setting full 50hz width\n");
saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
} else {
- saa7115_dbg("Setting full 60hz width\n");
+ v4l_dbg(1, debug, client, "Setting full 60hz width\n");
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
}
}
@@ -992,7 +915,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
if (pix->height != Vsrc) {
VSCY = (int)((1024 * Vsrc) / pix->height);
- saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
+ v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
/* Correct Contrast and Luminance */
saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
@@ -1006,10 +929,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
} else {
if (is_50hz) {
- saa7115_dbg("Setting full 50Hz height\n");
+ v4l_dbg(1, debug, client, "Setting full 50Hz height\n");
saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
} else {
- saa7115_dbg("Setting full 60hz height\n");
+ v4l_dbg(1, debug, client, "Setting full 60hz height\n");
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
}
}
@@ -1089,6 +1012,48 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
/* ============ SAA7115 AUDIO settings (end) ============= */
+static struct v4l2_queryctrl saa7115_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 128,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+};
+
+/* ----------------------------------------------------------------------- */
+
static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct saa7115_state *state = i2c_get_clientdata(client);
@@ -1103,16 +1068,18 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
- return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg);
+ return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *vt = arg;
int status;
+ if (state->radio)
+ break;
status = saa7115_read(client, 0x1f);
- saa7115_dbg("status: 0x%02x\n", status);
+ v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
break;
}
@@ -1127,20 +1094,38 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
case VIDIOC_S_CTRL:
return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg);
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++)
+ if (qc->id && qc->id == saa7115_qctrl[i].id) {
+ memcpy(qc, &saa7115_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
case VIDIOC_G_STD:
*(v4l2_std_id *)arg = saa7115_get_v4lstd(client);
break;
case VIDIOC_S_STD:
+ state->radio = 0;
saa7115_set_v4lstd(client, *(v4l2_std_id *)arg);
break;
+ case AUDC_SET_RADIO:
+ state->radio = 1;
+ break;
+
case VIDIOC_G_INPUT:
*(int *)arg = state->input;
break;
case VIDIOC_S_INPUT:
- saa7115_dbg("decoder set input %d\n", *iarg);
+ v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg);
/* inputs from 0-9 are available */
if (*iarg < 0 || *iarg > 9) {
return -EINVAL;
@@ -1148,7 +1133,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
if (state->input == *iarg)
break;
- saa7115_dbg("now setting %s input\n",
+ v4l_dbg(1, debug, client, "now setting %s input\n",
*iarg >= 6 ? "S-Video" : "Composite");
state->input = *iarg;
@@ -1165,7 +1150,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
- saa7115_dbg("%s output\n",
+ v4l_dbg(1, debug, client, "%s output\n",
(cmd == VIDIOC_STREAMON) ? "enable" : "disable");
if (state->enable != (cmd == VIDIOC_STREAMON)) {
@@ -1179,7 +1164,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
break;
case VIDIOC_INT_RESET:
- saa7115_dbg("decoder RESET\n");
+ v4l_dbg(1, debug, client, "decoder RESET\n");
saa7115_writeregs(client, saa7115_cfg_reset_scaler);
break;
@@ -1264,47 +1249,46 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7115;
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
- saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1);
saa7115_write(client, 0, 5);
chip_id = saa7115_read(client, 0) & 0x0f;
if (chip_id != 4 && chip_id != 5) {
- saa7115_dbg("saa7115 not found\n");
+ v4l_dbg(1, debug, client, "saa7115 not found\n");
kfree(client);
return 0;
}
if (chip_id == 4) {
snprintf(client->name, sizeof(client->name) - 1, "saa7114");
}
- saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
+ v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
- state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL);
i2c_set_clientdata(client, state);
if (state == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(state, 0, sizeof(struct saa7115_state));
state->std = V4L2_STD_NTSC;
state->input = -1;
state->enable = 1;
+ state->radio = 0;
state->bright = 128;
state->contrast = 64;
state->hue = 0;
state->sat = 64;
state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
- state->audclk_freq = V4L2_AUDCLK_48_KHZ;
+ state->audclk_freq = 48000;
- saa7115_dbg("writing init values\n");
+ v4l_dbg(1, debug, client, "writing init values\n");
/* init to 60hz/48khz */
saa7115_writeregs(client, saa7115_init_auto_input);
@@ -1312,13 +1296,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
saa7115_writeregs(client, saa7115_cfg_60hz_video);
- saa7115_writeregs(client, saa7115_cfg_48_audio);
- saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
+ saa7115_set_audio_clock_freq(client, state->audclk_freq);
saa7115_writeregs(client, saa7115_cfg_reset_scaler);
i2c_attach_client(client);
- saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n",
+ v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
saa7115_read(client, 0x1e), saa7115_read(client, 0x1f));
return 0;
@@ -1326,11 +1309,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
static int saa7115_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, &saa7115_attach);
return 0;
}
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 8008537391b5..6c161f2f5e2c 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
#include <linux/video_decoder.h>
static int debug = 0;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)");
@@ -487,20 +487,18 @@ saa711x_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa711x;
strlcpy(I2C_NAME(client), "saa711x", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa711x), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa711x), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa711x));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
@@ -567,9 +565,7 @@ static struct i2c_driver i2c_driver_saa711x = {
.driver = {
.name = "saa711x",
},
-
.id = I2C_DRIVERID_SAA711X,
-
.attach_adapter = saa711x_attach_adapter,
.detach_client = saa711x_detach_client,
.command = saa711x_command,
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index bca6ed0e2752..992c71774f30 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -66,30 +66,6 @@ module_param(test_image, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_PARM_DESC(test_image, "test_image (0-1)");
-#define saa7127_dbg(fmt, arg...) \
- do { \
- if (debug >= 1) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-/* High volume debug. Use with care. */
-#define saa7127_dbg_highvol(fmt, arg...) \
- do { \
- if (debug == 2) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, \
- client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define saa7127_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define saa7127_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
@@ -336,7 +312,7 @@ static int saa7127_write(struct i2c_client *client, u8 reg, u8 val)
if (i2c_smbus_write_byte_data(client, reg, val) == 0)
return 0;
}
- saa7127_err("I2C Write Problem\n");
+ v4l_err(client, "I2C Write Problem\n");
return -1;
}
@@ -362,7 +338,7 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (enable && (data->field != 0 || data->line != 16))
return -EINVAL;
if (state->vps_enable != enable) {
- saa7127_dbg("Turn VPS Signal %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn VPS Signal %s\n", enable ? "on" : "off");
saa7127_write(client, 0x54, enable << 7);
state->vps_enable = enable;
}
@@ -374,7 +350,7 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
state->vps_data[2] = data->data[11];
state->vps_data[3] = data->data[12];
state->vps_data[4] = data->data[13];
- saa7127_dbg("Set VPS data %02x %02x %02x %02x %02x\n",
+ v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n",
state->vps_data[0], state->vps_data[1],
state->vps_data[2], state->vps_data[3],
state->vps_data[4]);
@@ -397,7 +373,7 @@ static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data
if (enable && (data->field != 0 || data->line != 21))
return -EINVAL;
if (state->cc_enable != enable) {
- saa7127_dbg("Turn CC %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn CC %s\n", enable ? "on" : "off");
saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
(state->xds_enable << 7) | (enable << 6) | 0x11);
state->cc_enable = enable;
@@ -405,7 +381,7 @@ static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data
if (!enable)
return 0;
- saa7127_dbg_highvol("CC data: %04x\n", cc);
+ v4l_dbg(2, debug, client, "CC data: %04x\n", cc);
saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
state->cc_data = cc;
@@ -423,7 +399,7 @@ static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (enable && (data->field != 1 || data->line != 21))
return -EINVAL;
if (state->xds_enable != enable) {
- saa7127_dbg("Turn XDS %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn XDS %s\n", enable ? "on" : "off");
saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
(enable << 7) | (state->cc_enable << 6) | 0x11);
state->xds_enable = enable;
@@ -431,7 +407,7 @@ static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (!enable)
return 0;
- saa7127_dbg_highvol("XDS data: %04x\n", xds);
+ v4l_dbg(2, debug, client, "XDS data: %04x\n", xds);
saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
state->xds_data = xds;
@@ -448,7 +424,7 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (enable && (data->field != 0 || data->line != 23))
return -EINVAL;
if (state->wss_enable != enable) {
- saa7127_dbg("Turn WSS %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn WSS %s\n", enable ? "on" : "off");
saa7127_write(client, 0x27, enable << 7);
state->wss_enable = enable;
}
@@ -457,7 +433,7 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat
saa7127_write(client, 0x26, data->data[0]);
saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f));
- saa7127_dbg("WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
+ v4l_dbg(1, debug, client, "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
return 0;
}
@@ -469,11 +445,11 @@ static int saa7127_set_video_enable(struct i2c_client *client, int enable)
struct saa7127_state *state = i2c_get_clientdata(client);
if (enable) {
- saa7127_dbg("Enable Video Output\n");
+ v4l_dbg(1, debug, client, "Enable Video Output\n");
saa7127_write(client, 0x2d, state->reg_2d);
saa7127_write(client, 0x61, state->reg_61);
} else {
- saa7127_dbg("Disable Video Output\n");
+ v4l_dbg(1, debug, client, "Disable Video Output\n");
saa7127_write(client, 0x2d, (state->reg_2d & 0xf0));
saa7127_write(client, 0x61, (state->reg_61 | 0xc0));
}
@@ -489,11 +465,11 @@ static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std)
const struct i2c_reg_value *inittab;
if (std & V4L2_STD_525_60) {
- saa7127_dbg("Selecting 60 Hz video Standard\n");
+ v4l_dbg(1, debug, client, "Selecting 60 Hz video Standard\n");
inittab = saa7127_init_config_60hz;
state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
} else {
- saa7127_dbg("Selecting 50 Hz video Standard\n");
+ v4l_dbg(1, debug, client, "Selecting 50 Hz video Standard\n");
inittab = saa7127_init_config_50hz;
state->reg_61 = SAA7127_50HZ_DAC_CONTROL;
}
@@ -544,7 +520,7 @@ static int saa7127_set_output_type(struct i2c_client *client, int output)
default:
return -EINVAL;
}
- saa7127_dbg("Selecting %s output type\n", output_strs[output]);
+ v4l_dbg(1, debug, client, "Selecting %s output type\n", output_strs[output]);
/* Configure Encoder */
saa7127_write(client, 0x2d, state->reg_2d);
@@ -561,12 +537,12 @@ static int saa7127_set_input_type(struct i2c_client *client, int input)
switch (input) {
case SAA7127_INPUT_TYPE_NORMAL: /* avia */
- saa7127_dbg("Selecting Normal Encoder Input\n");
+ v4l_dbg(1, debug, client, "Selecting Normal Encoder Input\n");
state->reg_3a_cb = 0;
break;
case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */
- saa7127_dbg("Selecting Color Bar generator\n");
+ v4l_dbg(1, debug, client, "Selecting Color Bar generator\n");
state->reg_3a_cb = 0x80;
break;
@@ -633,14 +609,14 @@ static int saa7127_command(struct i2c_client *client,
break;
case VIDIOC_LOG_STATUS:
- saa7127_info("Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
- saa7127_info("Input: %s\n", state->input_type ? "color bars" : "normal");
- saa7127_info("Output: %s\n", state->video_enable ?
+ v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
+ v4l_info(client, "Input: %s\n", state->input_type ? "color bars" : "normal");
+ v4l_info(client, "Output: %s\n", state->video_enable ?
output_strs[state->output_type] : "disabled");
- saa7127_info("WSS: %s\n", state->wss_enable ?
+ v4l_info(client, "WSS: %s\n", state->wss_enable ?
wss_strs[state->wss_mode] : "disabled");
- saa7127_info("VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
- saa7127_info("CC: %s\n", state->cc_enable ? "enabled" : "disabled");
+ v4l_info(client, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
+ v4l_info(client, "CC: %s\n", state->cc_enable ? "enabled" : "disabled");
break;
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -713,17 +689,16 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7127;
snprintf(client->name, sizeof(client->name) - 1, "saa7127");
- saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", address << 1);
/* First test register 0: Bits 5-7 are a version ID (should be 0),
and bit 2 should also be 0.
@@ -732,11 +707,11 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
0x1d after a reset and not expected to ever change. */
if ((saa7127_read(client, 0) & 0xe4) != 0 ||
(saa7127_read(client, 0x29) & 0x3f) != 0x1d) {
- saa7127_dbg("saa7127 not found\n");
+ v4l_dbg(1, debug, client, "saa7127 not found\n");
kfree(client);
return 0;
}
- state = kmalloc(sizeof(struct saa7127_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
if (state == NULL) {
kfree(client);
@@ -744,11 +719,10 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
}
i2c_set_clientdata(client, state);
- memset(state, 0, sizeof(struct saa7127_state));
/* Configure Encoder */
- saa7127_dbg("Configuring encoder\n");
+ v4l_dbg(1, debug, client, "Configuring encoder\n");
saa7127_write_inittab(client, saa7127_init_config_common);
saa7127_set_std(client, V4L2_STD_NTSC);
saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH);
@@ -769,12 +743,12 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
- saa7127_info("saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name);
saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result);
saa7127_write_inittab(client, saa7129_init_config_extra);
state->ident = V4L2_IDENT_SAA7129;
} else {
- saa7127_info("saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name);
state->ident = V4L2_IDENT_SAA7127;
}
@@ -787,11 +761,7 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
static int saa7127_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, saa7127_attach);
return 0;
}
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 8a5c3e71b37d..86671a43e769 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -15,7 +15,7 @@ config VIDEO_SAA7134
config VIDEO_SAA7134_ALSA
tristate "Philips SAA7134 DMA audio support"
depends on VIDEO_SAA7134 && SND
- select SND_PCM_OSS
+ select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio in
Philips SAA713x based TV cards using ALSA
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 4615a982ac64..0e0ba50946e8 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -9,7 +9,8 @@
#include <linux/poll.h>
#include <linux/i2c.h>
#include <linux/types.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
#include <linux/init.h>
#include <linux/crc32.h>
@@ -509,11 +510,9 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct saa6752hs_state *h;
- printk("saa6752hs: chip found @ 0x%x\n", addr<<1);
- if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL)))
+ if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL)))
return -ENOMEM;
- memset(h,0,sizeof(*h));
h->client = client_template;
h->params = param_defaults;
h->client.adapter = adap;
@@ -525,6 +524,8 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(&h->client, h);
i2c_attach_client(&h->client);
+ v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
+
return 0;
}
@@ -598,7 +599,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
static struct i2c_driver driver = {
.driver = {
- .name = "i2c saa6752hs MPEG encoder",
+ .name = "saa6752hs",
},
.id = I2C_DRIVERID_SAA6752HS,
.attach_adapter = saa6752hs_probe,
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index ade05f75fdb0..a7a6ab9298a9 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -20,13 +20,13 @@
*
*/
-#include <sound/driver.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
+#include <sound/driver.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 672fb205959f..c64718aec9cb 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -25,6 +25,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
/* commly used strings */
static char name_mute[] = "mute";
@@ -1665,7 +1666,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
@@ -2514,6 +2515,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 1 << 21,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -2528,6 +2530,11 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 8,
.amux = LINE1,
}},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
},
[SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = {
.name = "MSI TV@Anywhere plus",
@@ -2555,6 +2562,69 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7134_BOARD_CINERGY250PCI] = {
+ /* remote-control does not work. The signal about a
+ key press comes in via gpio, but the key code
+ doesn't. Neither does it have an i2c remote control
+ interface. */
+ .name = "Terratec Cinergy 250 PCI TV",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x80200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_svideo, /* NOT tested */
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_FLYDVB_TRIO] = {
+ /* LifeView LR319 FlyDVB Trio */
+ /* Peter Missel <peter.missel@onlinehome.de> */
+ .name = "LifeView FlyDVB Trio",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x00200000,
+ .inputs = {{
+ .name = name_tv, /* Analog broadcast/cable TV */
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x200000, /* GPIO21=High for TV input */
+ .tv = 1,
+ },{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ },{
+ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -2895,6 +2965,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1421,
+ .subdevice = 0x0351, /* PCI version, new revision */
+ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1421,
.subdevice = 0x0370, /* cardbus version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
},{
@@ -3002,6 +3078,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x6231,
.driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x153b,
+ .subdevice = 0x1160,
+ .driver_data = SAA7134_BOARD_CINERGY250PCI,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA 7131E */
+ .subvendor = 0x5168,
+ .subdevice = 0x0319,
+ .driver_data = SAA7134_BOARD_FLYDVB_TRIO,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3090,6 +3178,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
/* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+ case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 23d8747338ed..028904bd94a2 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -31,6 +31,7 @@
#include <linux/sound.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -84,7 +85,7 @@ MODULE_PARM_DESC(radio_nr, "radio device number");
MODULE_PARM_DESC(tuner, "tuner type");
MODULE_PARM_DESC(card, "card type");
-static DECLARE_MUTEX(devlist_lock);
+static DEFINE_MUTEX(devlist_lock);
LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
static unsigned int saa7134_devcount;
@@ -95,77 +96,6 @@ int (*dmasound_exit)(struct saa7134_dev *dev);
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
-/* ------------------------------------------------------------------ */
-/* debug help functions */
-
-static const char *v4l1_ioctls[] = {
- "0", "GCAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
- "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
- "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
- "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
- "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
- "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
- "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
- "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
- "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
- "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
- "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-static const char *osspcm_ioctls[] = {
- "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
- "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
- "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
- "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
- "SETDUPLEX", "GETODELAY"
-};
-#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void saa7134_print_ioctl(char *name, unsigned int cmd)
-{
- char *dir;
-
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "??"; break;
- }
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'P':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
- osspcm_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'M':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- break;
- default:
- printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- }
-}
-
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
{
unsigned long mode,status;
@@ -610,11 +540,38 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
card_has_mpeg(dev))
saa7134_irq_ts_done(dev,status);
- if ((report & (SAA7134_IRQ_REPORT_GPIO16 |
- SAA7134_IRQ_REPORT_GPIO18)) &&
- dev->remote)
- saa7134_input_irq(dev);
+ if (report & SAA7134_IRQ_REPORT_GPIO16) {
+ switch (dev->has_remote) {
+ case SAA7134_REMOTE_GPIO:
+ if (dev->remote->mask_keydown & 0x10000) {
+ saa7134_input_irq(dev);
+ }
+ break;
+
+ case SAA7134_REMOTE_I2C:
+ break; /* FIXME: invoke I2C get_key() */
+ default: /* GPIO16 not used by IR remote */
+ break;
+ }
+ }
+
+ if (report & SAA7134_IRQ_REPORT_GPIO18) {
+ switch (dev->has_remote) {
+ case SAA7134_REMOTE_GPIO:
+ if ((dev->remote->mask_keydown & 0x40000) ||
+ (dev->remote->mask_keyup & 0x40000)) {
+ saa7134_input_irq(dev);
+ }
+ break;
+
+ case SAA7134_REMOTE_I2C:
+ break; /* FIXME: invoke I2C get_key() */
+
+ default: /* GPIO18 not used by IR remote */
+ break;
+ }
+ }
}
if (10 == loop) {
@@ -624,13 +581,16 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_WARNING "%s/irq: looping -- "
"clearing PE (parity error!) enable bit\n",dev->name);
saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
- } else if (report & (SAA7134_IRQ_REPORT_GPIO16 |
- SAA7134_IRQ_REPORT_GPIO18)) {
- /* disable gpio IRQs */
+ } else if (report & SAA7134_IRQ_REPORT_GPIO16) {
+ /* disable gpio16 IRQ */
printk(KERN_WARNING "%s/irq: looping -- "
- "clearing GPIO enable bits\n",dev->name);
- saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 |
- SAA7134_IRQ2_INTE_GPIO18));
+ "clearing GPIO16 enable bit\n",dev->name);
+ saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16);
+ } else if (report & SAA7134_IRQ_REPORT_GPIO18) {
+ /* disable gpio18 IRQs */
+ printk(KERN_WARNING "%s/irq: looping -- "
+ "clearing GPIO18 enable bit\n",dev->name);
+ saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
} else {
/* disable all irqs */
printk(KERN_WARNING "%s/irq: looping -- "
@@ -711,10 +671,14 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
SAA7134_IRQ2_INTE_PE |
SAA7134_IRQ2_INTE_AR;
- if (dev->has_remote == SAA7134_REMOTE_GPIO)
- irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 |
- SAA7134_IRQ2_INTE_GPIO18A |
- SAA7134_IRQ2_INTE_GPIO16 );
+ if (dev->has_remote == SAA7134_REMOTE_GPIO) {
+ if (dev->remote->mask_keydown & 0x10000)
+ irq2_mask |= SAA7134_IRQ2_INTE_GPIO16;
+ else if (dev->remote->mask_keydown & 0x40000)
+ irq2_mask |= SAA7134_IRQ2_INTE_GPIO18;
+ else if (dev->remote->mask_keyup & 0x40000)
+ irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A;
+ }
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, irq2_mask);
@@ -840,10 +804,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
struct saa7134_mpeg_ops *mops;
int err;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
return -ENOMEM;
- memset(dev,0,sizeof(*dev));
/* pci init */
dev->pci = pci_dev;
@@ -1007,13 +970,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
pci_set_drvdata(pci_dev,dev);
saa7134_devcount++;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_for_each(item,&mops_list) {
mops = list_entry(item, struct saa7134_mpeg_ops, next);
mpeg_ops_attach(mops, dev);
}
list_add_tail(&dev->devlist,&saa7134_devlist);
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
/* check for signal */
saa7134_irq_video_intl(dev);
@@ -1069,13 +1032,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa7134_hwfini(dev);
/* unregister */
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_del(&dev->devlist);
list_for_each(item,&mops_list) {
mops = list_entry(item, struct saa7134_mpeg_ops, next);
mpeg_ops_detach(mops, dev);
}
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
saa7134_devcount--;
saa7134_i2c_unregister(dev);
@@ -1109,13 +1072,13 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
struct list_head *item;
struct saa7134_dev *dev;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_for_each(item,&saa7134_devlist) {
dev = list_entry(item, struct saa7134_dev, devlist);
mpeg_ops_attach(ops, dev);
}
list_add_tail(&ops->next,&mops_list);
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
return 0;
}
@@ -1124,13 +1087,13 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
struct list_head *item;
struct saa7134_dev *dev;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_del(&ops->next);
list_for_each(item,&saa7134_devlist) {
dev = list_entry(item, struct saa7134_dev, devlist);
mpeg_ops_detach(ops, dev);
}
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
}
EXPORT_SYMBOL(saa7134_ts_register);
@@ -1156,7 +1119,7 @@ static int saa7134_init(void)
printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
- return pci_module_init(&saa7134_pci_driver);
+ return pci_register_driver(&saa7134_pci_driver);
}
static void saa7134_fini(void)
@@ -1173,7 +1136,6 @@ module_exit(saa7134_fini);
/* ----------------------------------------------------------- */
-EXPORT_SYMBOL(saa7134_print_ioctl);
EXPORT_SYMBOL(saa7134_i2c_call_clients);
EXPORT_SYMBOL(saa7134_devlist);
EXPORT_SYMBOL(saa7134_boards);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index e016480c3468..399f9952596c 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -31,6 +31,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
#ifdef HAVE_MT352
# include "mt352.h"
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 575f3e835f91..bd4c389d4c37 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -29,6 +29,7 @@
#include "saa7134.h"
#include <media/saa6752hs.h>
+#include <media/v4l2-common.h>
/* ------------------------------------------------------------------ */
@@ -163,7 +164,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
struct saa7134_dev *dev = file->private_data;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
{
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 1792d03d621d..6162550c4136 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -30,6 +30,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
/* ----------------------------------------------------------- */
@@ -390,9 +391,7 @@ static struct i2c_algorithm saa7134_algo = {
static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE,
-#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
-#endif
.name = "saa7134",
.id = I2C_HW_SAA7134,
.algo = &saa7134_algo,
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index ab75ca5ac356..82d28cbf289f 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -56,23 +56,23 @@ static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
[ 12 ] = KEY_KP8,
[ 13 ] = KEY_KP9,
- [ 14 ] = KEY_TUNER, // Air/Cable
+ [ 14 ] = KEY_MODE, // Air/Cable
[ 17 ] = KEY_VIDEO, // Video
[ 21 ] = KEY_AUDIO, // Audio
- [ 0 ] = KEY_POWER, // Pover
+ [ 0 ] = KEY_POWER, // Power
+ [ 24 ] = KEY_TUNER, // AV Source
[ 2 ] = KEY_ZOOM, // Fullscreen
+ [ 26 ] = KEY_LANGUAGE, // Stereo
[ 27 ] = KEY_MUTE, // Mute
- [ 20 ] = KEY_VOLUMEUP,
- [ 23 ] = KEY_VOLUMEDOWN,
+ [ 20 ] = KEY_VOLUMEUP, // Volume +
+ [ 23 ] = KEY_VOLUMEDOWN, // Volume -
[ 18 ] = KEY_CHANNELUP, // Channel +
[ 19 ] = KEY_CHANNELDOWN, // Channel -
- [ 6 ] = KEY_AGAIN, // Recal
- [ 16 ] = KEY_KPENTER, // Enter
-
- [ 26 ] = KEY_F22, // Stereo
- [ 24 ] = KEY_EDIT, // AV Source
+ [ 6 ] = KEY_AGAIN, // Recall
+ [ 16 ] = KEY_ENTER, // Enter
};
+
static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
[ 0 ] = KEY_KP0,
[ 1 ] = KEY_KP1,
@@ -543,12 +543,22 @@ static int build_key(struct saa7134_dev *dev)
dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
gpio, ir->mask_keycode, data);
- 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);
- } else {
- ir_input_nokey(ir->dev, &ir->ir);
+ if (ir->polling) {
+ 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);
+ } else {
+ ir_input_nokey(ir->dev, &ir->ir);
+ }
+ }
+ else { /* IRQ driven mode - handle key press and release in one go */
+ 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_nokey(ir->dev, &ir->ir);
+ }
}
+
return 0;
}
@@ -686,6 +696,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
polling = 50; // ms
break;
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+ case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
ir_codes = videomate_tv_pvr_codes;
mask_keycode = 0x00003F;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 8badd2a9cb2f..7448e386a804 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -373,6 +373,42 @@ static ssize_t dsp_write(struct file *file, const char __user *buffer,
return -EINVAL;
}
+static const char *osspcm_ioctls[] = {
+ "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
+ "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
+ "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
+ "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
+ "SETDUPLEX", "GETODELAY"
+};
+#define OSSPCM_IOCTLS ARRAY_SIZE(osspcm_ioctls)
+
+static void saa7134_oss_print_ioctl(char *name, unsigned int cmd)
+{
+ char *dir;
+
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE: dir = "--"; break;
+ case _IOC_READ: dir = "r-"; break;
+ case _IOC_WRITE: dir = "-w"; break;
+ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+ default: dir = "??"; break;
+ }
+ switch (_IOC_TYPE(cmd)) {
+ case 'P':
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
+ name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
+ osspcm_ioctls[_IOC_NR(cmd)] : "???");
+ break;
+ case 'M':
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
+ name, cmd, dir, _IOC_NR(cmd));
+ break;
+ default:
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
+ name, cmd, dir, _IOC_NR(cmd));
+ }
+}
+
static int dsp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -382,7 +418,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
int val = 0;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ saa7134_oss_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
@@ -678,7 +714,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
int __user *p = argp;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ saa7134_oss_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 93268427750d..afa4dcb3f96d 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -180,8 +180,8 @@ static void tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
- // frame locked audio was reported not to be reliable
- saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02);
+ /* frame locked audio is mandatory for NICAM */
+ saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01);
saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14);
saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
@@ -809,7 +809,12 @@ static int tvaudio_thread_ddep(void *data)
dprintk("ddep override: %s\n",stdres[audio_ddep]);
} else if (&card(dev).radio == dev->input) {
dprintk("FM Radio\n");
- norms = (0x0f << 2) | 0x01;
+ if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
+ norms = (0x11 << 2) | 0x01;
+ saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
+ } else {
+ norms = (0x0f << 2) | 0x01;
+ }
} else {
/* (let chip) scan for sound carrier */
norms = 0;
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 45c852df13ed..e97426bc85df 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -29,6 +29,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
/* Include V4L1 specific functions. Should be removed soon */
#include <linux/videodev.h>
@@ -1263,10 +1264,9 @@ static int video_open(struct inode *inode, struct file *file)
v4l2_type_names[type]);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -1689,7 +1689,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
int err;
if (video_debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_S_CTRL:
@@ -2142,7 +2142,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
struct saa7134_dev *dev = fh->dev;
if (video_debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
{
@@ -2262,6 +2262,7 @@ static struct file_operations video_fops =
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -2271,6 +2272,7 @@ static struct file_operations radio_fops =
.open = video_open,
.release = video_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index add49db1ad41..e70eae8d29bb 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -37,6 +37,9 @@
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
#include <media/video-buf.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
#include <media/video-buf-dvb.h>
#ifndef TRUE
@@ -47,10 +50,6 @@
#endif
#define UNSET (-1U)
-#include <sound/driver.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-
/* ----------------------------------------------------------- */
/* enums */
@@ -209,6 +208,8 @@ struct saa7134_format {
#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
#define SAA7134_BOARD_PHILIPS_TIGER 81
#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82
+#define SAA7134_BOARD_CINERGY250PCI 83
+#define SAA7134_BOARD_FLYDVB_TRIO 84
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -546,7 +547,6 @@ struct saa7134_dev {
extern struct list_head saa7134_devlist;
-void saa7134_print_ioctl(char *name, unsigned int cmd);
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
#define SAA7134_PGTABLE_SIZE 4096
diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h
index f305ec802ea6..756963f01bbd 100644
--- a/drivers/media/video/saa7146.h
+++ b/drivers/media/video/saa7146.h
@@ -73,7 +73,6 @@ struct saa7146
unsigned int nr;
unsigned long irq; /* IRQ used by SAA7146 card */
unsigned short id;
- struct pci_dev *dev;
unsigned char revision;
unsigned char boardcfg[64]; /* 64 bytes of config from eeprom */
unsigned long saa7146_adr; /* bus address of IO mem from PCI BIOS */
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index f72a9f796209..3ed0edb870a4 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -408,21 +408,19 @@ saa7185_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7185;
strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct saa7185));
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index 41f6f05a0436..746cadb8f1c4 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -571,18 +571,15 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
printk(KERN_INFO "Philips SAA7191 driver version %s\n",
SAA7191_MODULE_VERSION);
- client = kmalloc(sizeof(*client), GFP_KERNEL);
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
+ decoder = kzalloc(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;
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index d4497dbae05c..54fc33011ffb 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -49,9 +49,9 @@
#include "saa7121.h"
#include "cs8420.h"
-#define DEBUG(x) /* debug driver */
-#undef IDEBUG /* debug irq handler */
-#undef MDEBUG /* debug memory management */
+#define DEBUG(x) /* debug driver */
+#undef IDEBUG /* debug irq handler */
+#undef MDEBUG /* debug memory management */
#define SAA7146_MAX 6
@@ -63,7 +63,6 @@ static int video_nr = -1;
module_param(video_nr, int, 0);
MODULE_LICENSE("GPL");
-
#define nDebNormal 0x00480000
#define nDebNoInc 0x00480000
#define nDebVideo 0xd0480000
@@ -99,7 +98,12 @@ MODULE_LICENSE("GPL");
#ifdef USE_RESCUE_EEPROM_SDM275
static unsigned char rescue_eeprom[64] = {
-0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
+ 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l',
+ 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
+ 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a',
+ 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
};
#endif
@@ -140,17 +144,18 @@ static int I2CRead(struct saa7146 *saa, unsigned char addr,
if (saaread(SAA7146_I2C_STATUS) & 0x3c)
I2CWipe(saa);
- for (i = 0; i < 1000 &&
- (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
+ for (i = 0;
+ i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
+ i++)
schedule();
if (i == 1000)
I2CWipe(saa);
if (dosub)
saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
- ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
+ ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
else
saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
- 0xf1, SAA7146_I2C_TRANSFER);
+ 0xf1, SAA7146_I2C_TRANSFER);
saawrite((SAA7146_MC2_UPLD_I2C << 16) |
SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
/* wait for i2c registers to be programmed */
@@ -163,7 +168,7 @@ static int I2CRead(struct saa7146 *saa, unsigned char addr,
schedule();
if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
return -1;
- if (i == 1000)
+ if (i == 1000)
printk("i2c setup read timeout\n");
saawrite(0x41, SAA7146_I2C_TRANSFER);
saawrite((SAA7146_MC2_UPLD_I2C << 16) |
@@ -178,7 +183,7 @@ static int I2CRead(struct saa7146 *saa, unsigned char addr,
schedule();
if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
return -1;
- if (i == 1000)
+ if (i == 1000)
printk("i2c read timeout\n");
return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
}
@@ -213,20 +218,22 @@ static void attach_inform(struct saa7146 *saa, int id)
{
int i;
- DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id));
- if (id == 0xa0) { /* we have rev2 or later board, fill in info */
+ DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
+ id));
+ if (id == 0xa0) { /* we have rev2 or later board, fill in info */
for (i = 0; i < 64; i++)
saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
#ifdef USE_RESCUE_EEPROM_SDM275
if (saa->boardcfg[0] != 0) {
- printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr);
+ printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
+ "BEEN IGNORED\n", saa->nr);
for (i = 0; i < 64; i++)
saa->boardcfg[i] = rescue_eeprom[i];
}
#endif
printk("stradis%d: config =", saa->nr);
for (i = 0; i < 51; i++) {
- printk(" %02x",saa->boardcfg[i]);
+ printk(" %02x", saa->boardcfg[i]);
}
printk("\n");
}
@@ -254,17 +261,19 @@ static int wait_for_debi_done(struct saa7146 *saa)
for (i = 0; i < 500000 &&
(saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
saaread(SAA7146_MC2);
+
if (i > debiwait_maxwait)
printk("wait-for-debi-done maxwait: %d\n",
debiwait_maxwait = i);
-
+
if (i == 500000)
return -1;
+
return 0;
}
static int debiwrite(struct saa7146 *saa, u32 config, int addr,
- u32 val, int count)
+ u32 val, int count)
{
u32 cmd;
if (count <= 0 || count > 32764)
@@ -309,41 +318,6 @@ static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
return result;
}
-#if 0 /* unused */
-/* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */
-/* data copied into saa->dmadebi buffer, caller must re-enable interrupts */
-static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes)
-{
- int i, j;
- u32 *buf;
- buf = (u32 *) saa->dmadebi;
- if (bytes > 0x7000)
- bytes = 0x7000;
- saawrite(0, SAA7146_IER); /* disable interrupts */
- for (i=0; i < 10000 &&
- (debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2)
- & 0x8000); i++)
- saaread(SAA7146_MC2);
- if (i == 10000)
- printk(KERN_ERR "stradis%d: dram_busy never cleared\n",
- saa->nr);
- debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) |
- (address>>16), 4);
- debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2);
- debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2);
- for (j = 0; j < bytes/4; j++) {
- for (i = 0; i < 10000 &&
- (!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2)
- & 0x4000)); i++)
- saaread(SAA7146_MC2);
- if (i == 10000)
- printk(KERN_ERR "stradis%d: dram_ready never set\n",
- saa->nr);
- buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4);
- }
-}
-#endif /* unused */
-
static void do_irq_send_data(struct saa7146 *saa)
{
int split, audbytes, vidbytes;
@@ -365,16 +339,15 @@ static void do_irq_send_data(struct saa7146 *saa)
return;
}
/* if at least 1 block audio waiting and audio fifo isn't full */
- if (audbytes >= 2048 && (debiread(saa, debNormal,
- IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) {
+ if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
+ & 0xff) < 60) {
if (saa->audhead > saa->audtail)
split = 65536 - saa->audhead;
else
split = 0;
audbytes = 2048;
if (split > 0 && split < 2048) {
- memcpy(saa->dmadebi, saa->audbuf + saa->audhead,
- split);
+ memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
saa->audhead = 0;
audbytes -= split;
} else
@@ -383,20 +356,19 @@ static void do_irq_send_data(struct saa7146 *saa)
audbytes);
saa->audhead += audbytes;
saa->audhead &= 0xffff;
- debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO :
- IBM_MP2_AUD_FIFOW), 0, 2048);
+ debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
+ IBM_MP2_AUD_FIFOW), 0, 2048);
wake_up_interruptible(&saa->audq);
- /* if at least 1 block video waiting and video fifo isn't full */
+ /* if at least 1 block video waiting and video fifo isn't full */
} else if (vidbytes >= 30720 && (debiread(saa, debNormal,
- IBM_MP2_FIFO, 2)) < 16384) {
+ IBM_MP2_FIFO, 2)) < 16384) {
if (saa->vidhead > saa->vidtail)
split = 524288 - saa->vidhead;
else
split = 0;
vidbytes = 30720;
if (split > 0 && split < 30720) {
- memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead,
- split);
+ memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
saa->vidhead = 0;
vidbytes -= split;
} else
@@ -406,7 +378,7 @@ static void do_irq_send_data(struct saa7146 *saa)
saa->vidhead += vidbytes;
saa->vidhead &= 0x7ffff;
debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
- IBM_MP2_FIFOW), 0, 30720);
+ IBM_MP2_FIFOW), 0, 30720);
wake_up_interruptible(&saa->vidq);
}
saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
@@ -418,10 +390,10 @@ static void send_osd_data(struct saa7146 *saa)
if (size > 30720)
size = 30720;
/* ensure some multiple of 8 bytes is transferred */
- size = 8 * ((size + 8)>>3);
+ size = 8 * ((size + 8) >> 3);
if (size) {
debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
- (saa->osdhead>>3), 2);
+ (saa->osdhead >> 3), 2);
memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
saa->osdhead += size;
/* block transfer of next 8 bytes to ~32k bytes */
@@ -435,7 +407,7 @@ static void send_osd_data(struct saa7146 *saa)
static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct saa7146 *saa = (struct saa7146 *) dev_id;
+ struct saa7146 *saa = dev_id;
u32 stat, astat;
int count;
int handled = 0;
@@ -484,7 +456,7 @@ static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
saa->vidinfo.v_size = 480;
#if 0
if (saa->endmarkhead != saa->endmarktail) {
- saa->audhead =
+ saa->audhead =
saa->endmark[saa->endmarkhead];
saa->endmarkhead++;
if (saa->endmarkhead >= MAX_MARKS)
@@ -494,7 +466,7 @@ static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
}
if (istat & 0x4000) { /* Sequence Error Code */
if (saa->endmarkhead != saa->endmarktail) {
- saa->audhead =
+ saa->audhead =
saa->endmark[saa->endmarkhead];
saa->endmarkhead++;
if (saa->endmarkhead >= MAX_MARKS)
@@ -613,7 +585,7 @@ static int ibm_send_command(struct saa7146 *saa,
int i;
if (chain)
- debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1) | 1, 2);
+ debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
else
debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
@@ -663,11 +635,9 @@ static void initialize_cs8420(struct saa7146 *saa, int pro)
else
sequence = mode8420con;
for (i = 0; i < INIT8420LEN; i++)
- I2CWrite(saa, 0x20, init8420[i * 2],
- init8420[i * 2 + 1], 2);
+ I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
for (i = 0; i < MODE8420LEN; i++)
- I2CWrite(saa, 0x20, sequence[i * 2],
- sequence[i * 2 + 1], 2);
+ I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
printk("stradis%d: CS8420 initialized\n", saa->nr);
}
@@ -683,35 +653,36 @@ static void initialize_saa7121(struct saa7146 *saa, int dopal)
/* initialize PAL/NTSC video encoder */
for (i = 0; i < INIT7121LEN; i++) {
if (NewCard) { /* handle new card encoder differences */
- if (sequence[i*2] == 0x3a)
+ if (sequence[i * 2] == 0x3a)
I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
- else if (sequence[i*2] == 0x6b)
+ else if (sequence[i * 2] == 0x6b)
I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
- else if (sequence[i*2] == 0x6c)
+ else if (sequence[i * 2] == 0x6c)
I2CWrite(saa, 0x88, 0x6c,
dopal ? 0x09 : 0xf5, 2);
- else if (sequence[i*2] == 0x6d)
+ else if (sequence[i * 2] == 0x6d)
I2CWrite(saa, 0x88, 0x6d,
dopal ? 0x20 : 0x00, 2);
- else if (sequence[i*2] == 0x7a)
+ else if (sequence[i * 2] == 0x7a)
I2CWrite(saa, 0x88, 0x7a,
dopal ? (PALFirstActive - 1) :
(NTSCFirstActive - 4), 2);
- else if (sequence[i*2] == 0x7b)
+ else if (sequence[i * 2] == 0x7b)
I2CWrite(saa, 0x88, 0x7b,
dopal ? PALLastActive :
NTSCLastActive, 2);
- else I2CWrite(saa, 0x88, sequence[i * 2],
- sequence[i * 2 + 1], 2);
+ else
+ I2CWrite(saa, 0x88, sequence[i * 2],
+ sequence[i * 2 + 1], 2);
} else {
- if (sequence[i*2] == 0x6b && mod)
- I2CWrite(saa, 0x88, 0x6b,
- (sequence[i * 2 + 1] ^ 0x09), 2);
- else if (sequence[i*2] == 0x7a)
+ if (sequence[i * 2] == 0x6b && mod)
+ I2CWrite(saa, 0x88, 0x6b,
+ (sequence[i * 2 + 1] ^ 0x09), 2);
+ else if (sequence[i * 2] == 0x7a)
I2CWrite(saa, 0x88, 0x7a,
dopal ? (PALFirstActive - 1) :
(NTSCFirstActive - 4), 2);
- else if (sequence[i*2] == 0x7b)
+ else if (sequence[i * 2] == 0x7b)
I2CWrite(saa, 0x88, 0x7b,
dopal ? PALLastActive :
NTSCLastActive, 2);
@@ -735,7 +706,8 @@ static void set_genlock_offset(struct saa7146 *saa, int noffset)
nCode = noffset + 0x100;
if (nCode == 1)
nCode = 0x401;
- else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode;
+ else if (nCode < 1)
+ nCode = 0x400 + PixelsPerLine + nCode;
debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
}
@@ -745,33 +717,31 @@ static void set_out_format(struct saa7146 *saa, int mode)
saa->boardcfg[2] = mode;
/* do not adjust analog video parameters here, use saa7121 init */
/* you will affect the SDI output on the new card */
- if (mode == VIDEO_MODE_PAL) { /* PAL */
+ if (mode == VIDEO_MODE_PAL) { /* PAL */
debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
mdelay(50);
saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
if (NewCard) {
- debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- 0xe100, 2);
+ debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
mdelay(50);
}
debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- NewCard ? 0xe500: 0x6500, 2);
+ NewCard ? 0xe500 : 0x6500, 2);
debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
(1 << 8) |
- (NewCard ? PALFirstActive : PALFirstActive-6), 2);
+ (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
} else { /* NTSC */
debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
mdelay(50);
saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- NewCard ? 0xe100: 0x6100, 2);
+ NewCard ? 0xe100 : 0x6100, 2);
debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
(1 << 8) |
- (NewCard ? NTSCFirstActive : NTSCFirstActive-6), 2);
+ (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
}
}
-
/* Intialize bitmangler to map from a byte value to the mangled word that
* must be output to program the Xilinx part through the DEBI port.
* Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
@@ -799,43 +769,41 @@ static int initialize_fpga(struct video_code *bitdata)
for (num = 0; num < saa_num; num++) {
saa = &saa7146s[num];
if (saa->boardcfg[0] > 20)
- continue; /* card was programmed */
+ continue; /* card was programmed */
loadtwo = (saa->boardcfg[18] & 0x10);
if (!NewCard) /* we have an old board */
for (i = 0; i < 256; i++)
- bitmangler[i] = ((i & 0x01) << 15) |
- ((i & 0x02) << 6) | ((i & 0x04) << 4) |
- ((i & 0x08) << 9) | ((i & 0x10) << 7) |
- ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
- ((i & 0x80) >> 7);
- else /* else we have a new board */
+ bitmangler[i] = ((i & 0x01) << 15) |
+ ((i & 0x02) << 6) | ((i & 0x04) << 4) |
+ ((i & 0x08) << 9) | ((i & 0x10) << 7) |
+ ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
+ ((i & 0x80) >> 7);
+ else /* else we have a new board */
for (i = 0; i < 256; i++)
- bitmangler[i] = ((i & 0x01) << 7) |
- ((i & 0x02) << 5) | ((i & 0x04) << 3) |
- ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
- ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
- ((i & 0x80) >> 7);
+ bitmangler[i] = ((i & 0x01) << 7) |
+ ((i & 0x02) << 5) | ((i & 0x04) << 3) |
+ ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
+ ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
+ ((i & 0x80) >> 7);
dmabuf = (u16 *) saa->dmadebi;
newdma = (u8 *) saa->dmadebi;
if (NewCard) { /* SDM2xxx */
if (!strncmp(bitdata->loadwhat, "decoder2", 8))
continue; /* fpga not for this card */
- if (!strncmp(&saa->boardcfg[42],
- bitdata->loadwhat, 8)) {
+ if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
loadfile = 1;
- } else if (loadtwo && !strncmp(&saa->boardcfg[19],
- bitdata->loadwhat, 8)) {
+ else if (loadtwo && !strncmp(&saa->boardcfg[19],
+ bitdata->loadwhat, 8))
loadfile = 2;
- } else if (!saa->boardcfg[42] && /* special */
- !strncmp("decxl", bitdata->loadwhat, 8)) {
- loadfile = 1;
- } else
+ else if (!saa->boardcfg[42] && !strncmp("decxl",
+ bitdata->loadwhat, 8))
+ loadfile = 1; /* special */
+ else
continue; /* fpga not for this card */
- if (loadfile != 1 && loadfile != 2) {
+ if (loadfile != 1 && loadfile != 2)
continue; /* skip to next card */
- }
- if (saa->boardcfg[0] && loadfile == 1 )
+ if (saa->boardcfg[0] && loadfile == 1)
continue; /* skip to next card */
if (saa->boardcfg[0] != 1 && loadfile == 2)
continue; /* skip to next card */
@@ -870,8 +838,9 @@ static int initialize_fpga(struct video_code *bitdata)
/* Release Xilinx INIT signal (WS2) */
saawrite(0x00000000, SAA7146_GPIO_CTRL);
/* Wait for the INIT to go High */
- for (i = 0; i < 10000 &&
- !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++)
+ for (i = 0;
+ i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
+ i++)
schedule();
if (i == 1000) {
printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
@@ -881,17 +850,13 @@ send_fpga_stuff:
if (NewCard) {
for (i = startindex; i < bitdata->datasize; i++)
newdma[i - startindex] =
- bitmangler[bitdata->data[i]];
+ bitmangler[bitdata->data[i]];
debiwrite(saa, 0x01420000, 0, 0,
((bitdata->datasize - startindex) + 5));
- if (loadtwo) {
- if (loadfile == 1) {
- printk("stradis%d: "
- "awaiting 2nd FPGA bitfile\n",
- saa->nr);
- continue; /* skip to next card */
- }
-
+ if (loadtwo && loadfile == 1) {
+ printk("stradis%d: awaiting 2nd FPGA bitfile\n",
+ saa->nr);
+ continue; /* skip to next card */
}
} else {
for (i = startindex; i < bitdata->datasize; i++)
@@ -900,8 +865,9 @@ send_fpga_stuff:
debiwrite(saa, 0x014a0000, 0, 0,
((bitdata->datasize - startindex) + 5) * 2);
}
- for (i = 0; i < 1000 &&
- !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++)
+ for (i = 0;
+ i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
+ i++)
schedule();
if (i == 1000) {
printk(KERN_INFO "stradis%d: FPGA load failed\n",
@@ -925,14 +891,14 @@ send_fpga_stuff:
/* mute CS3310 */
if (HaveCS3310)
debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
- 0, 2);
+ 0, 2);
/* set VXCO to PWM mode, release reset, blank on */
debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
mdelay(10);
/* unmute CS3310 */
if (HaveCS3310)
debiwrite(saa, debNormal, XILINX_CTL0,
- 0x2020, 2);
+ 0x2020, 2);
}
/* set source Black */
debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
@@ -958,10 +924,10 @@ send_fpga_stuff:
/* we must init CS8420 first since rev b pulls i2s */
/* master clock low and CS4341 needs i2s master to */
/* run the i2c port. */
- if (HaveCS8420) {
+ if (HaveCS8420)
/* 0=consumer, 1=pro */
initialize_cs8420(saa, 0);
- }
+
mdelay(5);
if (HaveCS4341)
initialize_cs4341(saa);
@@ -981,6 +947,7 @@ send_fpga_stuff:
debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
#endif
}
+
return failure;
}
@@ -1021,10 +988,10 @@ static int do_ibm_reset(struct saa7146 *saa)
/* we must init CS8420 first since rev b pulls i2s */
/* master clock low and CS4341 needs i2s master to */
/* run the i2c port. */
- if (HaveCS8420) {
+ if (HaveCS8420)
/* 0=consumer, 1=pro */
initialize_cs8420(saa, 1);
- }
+
mdelay(5);
if (HaveCS4341)
initialize_cs4341(saa);
@@ -1039,12 +1006,12 @@ static int do_ibm_reset(struct saa7146 *saa)
debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
- (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
+ (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
}
if (HaveCS3310) {
int i = CS3310MaxLvl;
- debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i<<8)|i), 2);
+ debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
}
/* start video decoder */
debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
@@ -1057,6 +1024,7 @@ static int do_ibm_reset(struct saa7146 *saa)
/* clear pending interrupts */
debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
+
return 0;
}
@@ -1070,8 +1038,8 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
saa = &saa7146s[num];
/* check that FPGA is loaded */
debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
- if ((i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2)) !=
- 0xa55a) {
+ i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
+ if (i != 0xa55a) {
printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
saa->nr, i);
#if 0
@@ -1082,17 +1050,17 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
if (saa->boardcfg[0] > 27)
continue; /* skip to next card */
/* load video control store */
- saa->boardcfg[1] = 0x13; /* no-sync default */
+ saa->boardcfg[1] = 0x13; /* no-sync default */
debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
for (i = 0; i < microcode->datasize / 2; i++)
debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
(microcode->data[i * 2] << 8) |
- microcode->data[i * 2 + 1], 2);
+ microcode->data[i * 2 + 1], 2);
debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
+ ChipControl, 2);
saa->boardcfg[0] = 28;
}
if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
@@ -1109,34 +1077,32 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
- 0xe000, 1)) {
- printk(KERN_ERR
- "stradis%d: IBM config failed\n",
- saa->nr);
+ 0xe000, 1)) {
+ printk(KERN_ERR "stradis%d: IBM config "
+ "failed\n", saa->nr);
return -1;
}
/* set PWM to center value */
if (NewCard) {
debiwrite(saa, debNormal, XILINX_PWM,
- saa->boardcfg[14] +
- (saa->boardcfg[13]<<8), 2);
+ saa->boardcfg[14] +
+ (saa->boardcfg[13] << 8), 2);
} else
- debiwrite(saa, debNormal, XILINX_PWM,
- 0x46, 2);
+ debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
+
if (HaveCS3310) {
i = CS3310MaxLvl;
- debiwrite(saa, debNormal,
- XILINX_CS3310_CMPLT, ((i<<8)|i), 2);
+ debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
+ (i << 8) | i, 2);
}
- printk(KERN_INFO
- "stradis%d: IBM MPEGCD%d Initialized\n",
- saa->nr, 18 + (debiread(saa, debNormal,
- IBM_MP2_CHIP_CONTROL, 2) >> 12));
+ printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
+ saa->nr, 18 + (debiread(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, 2) >> 12));
/* start video decoder */
debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
ChipControl, 2);
- debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD,
- 0x4037, 2); /* 256k vid, 3520 bytes aud */
+ debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
+ 2); /* 256k vid, 3520 bytes aud */
debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
/* enable buffer threshold irq */
@@ -1149,52 +1115,48 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
saa->boardcfg[0] = 37;
}
}
+
return 0;
}
-static u32 palette2fmt[] =
-{ /* some of these YUV translations are wrong */
- 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
- 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
- 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
+static u32 palette2fmt[] = { /* some of these YUV translations are wrong */
+ 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
+ 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
+ 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
};
-static int bpp2fmt[4] =
-{
+static int bpp2fmt[4] = {
VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
VIDEO_PALETTE_RGB32
};
/* I wish I could find a formula to calculate these... */
-static u32 h_prescale[64] =
-{
- 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
- 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
- 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
- 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
- 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
- 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
- 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
- 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
- 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
- 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
- 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
+static u32 h_prescale[64] = {
+ 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
+ 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
+ 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
+ 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
+ 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
+ 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
+ 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
+ 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
+ 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
+ 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
+ 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
};
-static u32 v_gain[64] =
-{
- 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
- 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
- 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+static u32 v_gain[64] = {
+ 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
+ 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
+ 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
};
-
static void saa7146_set_winsize(struct saa7146 *saa)
{
u32 format;
@@ -1209,24 +1171,23 @@ static void saa7146_set_winsize(struct saa7146 *saa)
saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
SAA7146_PROT_ADDR1);
saawrite(0, SAA7146_PAGE1);
- saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL);
+ saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
offset = (704 / (saa->win.width - 1)) & 0x3f;
saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
offset = (720896 / saa->win.width) / (offset + 1);
- saawrite((offset<<12)|0x0c, SAA7146_HPS_H_SCALE);
+ saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
if (CurrentMode == VIDEO_MODE_NTSC) {
- yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0;
+ yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
ysci = 1024 - (saa->win.height * 1024 / 480);
} else {
- yacl = /*(576 / saa->win.height - 1) & 0x3f*/ 0;
+ yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
ysci = 1024 - (saa->win.height * 1024 / 576);
}
- saawrite((1<<31)|(ysci<<21)|(yacl<<15), SAA7146_HPS_V_SCALE);
+ saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
- SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
- SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H),
- SAA7146_MC2);
+ SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
+ SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
}
/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
@@ -1261,8 +1222,8 @@ static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
startword = (x >> 5);
endword = ((x + w) >> 5);
bitsleft = (0xffffffff >> (x & 31));
- bitsright = (0xffffffff << (~((x + w) - (endword<<5))));
- temp = &clipmap[(y<<5) + startword];
+ bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
+ temp = &clipmap[(y << 5) + startword];
w = endword - startword;
if (!w) {
bitsleft |= bitsright;
@@ -1287,13 +1248,13 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
u32 *clipmap;
clipmap = saa->dmavid2;
- if((width=saa->win.width)>1023)
- width = 1023; /* sanity check */
- if((height=saa->win.height)>640)
- height = 639; /* sanity check */
- if (ncr > 0) { /* rectangles pased */
+ if ((width = saa->win.width) > 1023)
+ width = 1023; /* sanity check */
+ if ((height = saa->win.height) > 640)
+ height = 639; /* sanity check */
+ if (ncr > 0) { /* rectangles pased */
/* convert rectangular clips to a bitmap */
- memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
+ memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
for (i = 0; i < ncr; i++)
clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
cr[i].width, cr[i].height);
@@ -1301,14 +1262,15 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
/* clip against viewing window AND screen
so we do not have to rely on the user program
*/
- clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ?
- (saa->win.swidth-saa->win.x) : width, 0, 1024, 768);
- clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ?
- (saa->win.sheight-saa->win.y) : height,1024,768);
- if (saa->win.x<0)
- clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768);
- if (saa->win.y<0)
- clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y));
+ clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
+ (saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
+ clip_draw_rectangle(clipmap, 0,
+ (saa->win.y + height > saa->win.sheight) ?
+ (saa->win.sheight - saa->win.y) : height, 1024, 768);
+ if (saa->win.x < 0)
+ clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
+ if (saa->win.y < 0)
+ clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
}
static int saa_ioctl(struct inode *inode, struct file *file,
@@ -1322,11 +1284,9 @@ static int saa_ioctl(struct inode *inode, struct file *file,
{
struct video_capability b;
strcpy(b.name, saa->video_dev.name);
- b.type = VID_TYPE_CAPTURE |
- VID_TYPE_OVERLAY |
- VID_TYPE_CLIPPING |
- VID_TYPE_FRAMERAM |
- VID_TYPE_SCALES;
+ b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
+ VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
+ VID_TYPE_SCALES;
b.channels = 1;
b.audios = 1;
b.maxwidth = 768;
@@ -1363,17 +1323,18 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (p.palette < sizeof(palette2fmt) / sizeof(u32)) {
format = palette2fmt[p.palette];
saa->win.color_fmt = format;
- saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL);
+ saawrite(format | 0x60,
+ SAA7146_CLIP_FORMAT_CTRL);
}
saawrite(((p.brightness & 0xff00) << 16) |
- ((p.contrast & 0xfe00) << 7) |
- ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
+ ((p.contrast & 0xfe00) << 7) |
+ ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
saa->picture = p;
/* upload changed registers */
saawrite(((SAA7146_MC2_UPLD_HPS_H |
- SAA7146_MC2_UPLD_HPS_V) << 16) |
- SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V,
- SAA7146_MC2);
+ SAA7146_MC2_UPLD_HPS_V) << 16) |
+ SAA7146_MC2_UPLD_HPS_H |
+ SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
return 0;
}
case VIDIOCSWIN:
@@ -1384,11 +1345,14 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (copy_from_user(&vw, arg, sizeof(vw)))
return -EFAULT;
- if (vw.flags || vw.width < 16 || vw.height < 16) { /* stop capture */
- saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
+ /* stop capture */
+ if (vw.flags || vw.width < 16 || vw.height < 16) {
+ saawrite((SAA7146_MC1_TR_E_1 << 16),
+ SAA7146_MC1);
return -EINVAL;
}
- if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */
+ /* 32-bit align start and adjust width */
+ if (saa->win.bpp < 4) {
int i = vw.x;
vw.x = (vw.x + 3) & ~3;
i = vw.x - i;
@@ -1417,23 +1381,24 @@ static int saa_ioctl(struct inode *inode, struct file *file,
*/
if (vw.clipcount < 0) {
if (copy_from_user(saa->dmavid2, vw.clips,
- VIDEO_CLIPMAP_SIZE))
+ VIDEO_CLIPMAP_SIZE))
return -EFAULT;
- }
- else if (vw.clipcount > 16384) {
+ } else if (vw.clipcount > 16384) {
return -EINVAL;
} else if (vw.clipcount > 0) {
- if ((vcp = vmalloc(sizeof(struct video_clip) *
- (vw.clipcount))) == NULL)
- return -ENOMEM;
+ vcp = vmalloc(sizeof(struct video_clip) *
+ vw.clipcount);
+ if (vcp == NULL)
+ return -ENOMEM;
if (copy_from_user(vcp, vw.clips,
- sizeof(struct video_clip) *
- vw.clipcount)) {
+ sizeof(struct video_clip) *
+ vw.clipcount)) {
vfree(vcp);
return -EFAULT;
}
} else /* nothing clipped */
memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
+
make_clip_tab(saa, vcp, vw.clipcount);
if (vw.clipcount > 0)
vfree(vcp);
@@ -1466,21 +1431,21 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (v == 0) {
saa->cap &= ~1;
saawrite((SAA7146_MC1_TR_E_1 << 16),
- SAA7146_MC1);
+ SAA7146_MC1);
} else {
if (saa->win.vidadr == 0 || saa->win.width == 0
- || saa->win.height == 0)
+ || saa->win.height == 0)
return -EINVAL;
saa->cap |= 1;
saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
- SAA7146_MC1);
+ SAA7146_MC1);
}
return 0;
}
case VIDIOCGFBUF:
{
struct video_buffer v;
- v.base = (void *) saa->win.vidadr;
+ v.base = (void *)saa->win.vidadr;
v.height = saa->win.sheight;
v.width = saa->win.swidth;
v.depth = saa->win.depth;
@@ -1498,19 +1463,20 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
- v.depth != 24 && v.depth != 32 && v.width > 16 &&
+ v.depth != 24 && v.depth != 32 && v.width > 16 &&
v.height > 16 && v.bytesperline > 16)
return -EINVAL;
if (v.base)
- saa->win.vidadr = (unsigned long) v.base;
+ saa->win.vidadr = (unsigned long)v.base;
saa->win.sheight = v.height;
saa->win.swidth = v.width;
saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
saa->win.depth = v.depth;
saa->win.bpl = v.bytesperline;
- DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
- v.base, v.width, v.height, saa->win.bpp, saa->win.bpl));
+ DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
+ "bpl %d\n", v.base, v.width, v.height,
+ saa->win.bpp, saa->win.bpl));
saa7146_set_winsize(saa);
return 0;
}
@@ -1538,21 +1504,18 @@ static int saa_ioctl(struct inode *inode, struct file *file,
int i;
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
- i = (~(v.volume>>8))&0xff;
+ i = (~(v.volume >> 8)) & 0xff;
if (!HaveCS4341) {
- if (v.flags & VIDEO_AUDIO_MUTE) {
+ if (v.flags & VIDEO_AUDIO_MUTE)
debiwrite(saa, debNormal,
- IBM_MP2_FRNT_ATTEN,
- 0xffff, 2);
- }
+ IBM_MP2_FRNT_ATTEN, 0xffff, 2);
if (!(v.flags & VIDEO_AUDIO_MUTE))
debiwrite(saa, debNormal,
- IBM_MP2_FRNT_ATTEN,
- 0x0000, 2);
+ IBM_MP2_FRNT_ATTEN, 0x0000, 2);
if (v.flags & VIDEO_AUDIO_VOLUME)
debiwrite(saa, debNormal,
IBM_MP2_FRNT_ATTEN,
- (i<<8)|i, 2);
+ (i << 8) | i, 2);
} else {
if (v.flags & VIDEO_AUDIO_MUTE)
cs4341_setlevel(saa, 0xff, 0xff);
@@ -1580,163 +1543,138 @@ static int saa_ioctl(struct inode *inode, struct file *file,
case VIDIOCSPLAYMODE:
{
struct video_play_mode pmode;
- if (copy_from_user((void *) &pmode, arg,
- sizeof(struct video_play_mode)))
+ if (copy_from_user((void *)&pmode, arg,
+ sizeof(struct video_play_mode)))
return -EFAULT;
switch (pmode.mode) {
- case VID_PLAY_VID_OUT_MODE:
- if (pmode.p1 != VIDEO_MODE_NTSC &&
+ case VID_PLAY_VID_OUT_MODE:
+ if (pmode.p1 != VIDEO_MODE_NTSC &&
pmode.p1 != VIDEO_MODE_PAL)
- return -EINVAL;
- set_out_format(saa, pmode.p1);
- return 0;
- case VID_PLAY_GENLOCK:
- debiwrite(saa, debNormal,
- XILINX_CTL0,
- (pmode.p1 ? 0x8000 : 0x8080),
- 2);
- if (NewCard)
- set_genlock_offset(saa,
- pmode.p2);
- return 0;
- case VID_PLAY_NORMAL:
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- ibm_send_command(saa,
- IBM_MP2_PLAY, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_PAUSE:
- /* IBM removed the PAUSE command */
- /* they say use SINGLE_FRAME now */
- case VID_PLAY_SINGLE_FRAME:
- ibm_send_command(saa,
- IBM_MP2_SINGLE_FRAME,
- 0, 0);
- if (saa->playmode == pmode.mode) {
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- }
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_FAST_FORWARD:
- ibm_send_command(saa,
- IBM_MP2_FAST_FORWARD, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_SLOW_MOTION:
- ibm_send_command(saa,
- IBM_MP2_SLOW_MOTION,
- pmode.p1, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_IMMEDIATE_NORMAL:
- /* ensure transfers resume */
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- ibm_send_command(saa,
- IBM_MP2_IMED_NORM_PLAY, 0, 0);
- saa->playmode = VID_PLAY_NORMAL;
- return 0;
- case VID_PLAY_SWITCH_CHANNELS:
- saa->audhead = saa->audtail = 0;
- saa->vidhead = saa->vidtail = 0;
- ibm_send_command(saa,
- IBM_MP2_FREEZE_FRAME, 0, 1);
- ibm_send_command(saa,
- IBM_MP2_RESET_AUD_RATE, 0, 1);
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL, 0, 2);
- ibm_send_command(saa,
- IBM_MP2_CHANNEL_SWITCH, 0, 1);
+ return -EINVAL;
+ set_out_format(saa, pmode.p1);
+ return 0;
+ case VID_PLAY_GENLOCK:
+ debiwrite(saa, debNormal, XILINX_CTL0,
+ pmode.p1 ? 0x8000 : 0x8080, 2);
+ if (NewCard)
+ set_genlock_offset(saa, pmode.p2);
+ return 0;
+ case VID_PLAY_NORMAL:
+ debiwrite(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+ ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_PAUSE:
+ /* IBM removed the PAUSE command */
+ /* they say use SINGLE_FRAME now */
+ case VID_PLAY_SINGLE_FRAME:
+ ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
+ if (saa->playmode == pmode.mode) {
debiwrite(saa, debNormal,
IBM_MP2_CHIP_CONTROL,
ChipControl, 2);
- ibm_send_command(saa,
- IBM_MP2_PLAY, 0, 0);
- saa->playmode = VID_PLAY_NORMAL;
- return 0;
- case VID_PLAY_FREEZE_FRAME:
- ibm_send_command(saa,
- IBM_MP2_FREEZE_FRAME, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_STILL_MODE:
- ibm_send_command(saa,
- IBM_MP2_SET_STILL_MODE, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_MASTER_MODE:
- if (pmode.p1 == VID_PLAY_MASTER_NONE)
- saa->boardcfg[1] = 0x13;
- else if (pmode.p1 ==
- VID_PLAY_MASTER_VIDEO)
- saa->boardcfg[1] = 0x23;
- else if (pmode.p1 ==
- VID_PLAY_MASTER_AUDIO)
- saa->boardcfg[1] = 0x43;
- else
+ }
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_FAST_FORWARD:
+ ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_SLOW_MOTION:
+ ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
+ pmode.p1, 0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_IMMEDIATE_NORMAL:
+ /* ensure transfers resume */
+ debiwrite(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+ ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
+ 0, 0);
+ saa->playmode = VID_PLAY_NORMAL;
+ return 0;
+ case VID_PLAY_SWITCH_CHANNELS:
+ saa->audhead = saa->audtail = 0;
+ saa->vidhead = saa->vidtail = 0;
+ ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
+ ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
+ 0, 1);
+ debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
+ 0, 2);
+ ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
+ 0, 1);
+ debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
+ ChipControl, 2);
+ ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
+ saa->playmode = VID_PLAY_NORMAL;
+ return 0;
+ case VID_PLAY_FREEZE_FRAME:
+ ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_STILL_MODE:
+ ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
+ 0, 0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_MASTER_MODE:
+ if (pmode.p1 == VID_PLAY_MASTER_NONE)
+ saa->boardcfg[1] = 0x13;
+ else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
+ saa->boardcfg[1] = 0x23;
+ else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
+ saa->boardcfg[1] = 0x43;
+ else
+ return -EINVAL;
+ debiwrite(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+ return 0;
+ case VID_PLAY_ACTIVE_SCANLINES:
+ if (CurrentMode == VIDEO_MODE_PAL) {
+ if (pmode.p1 < 1 || pmode.p2 > 625)
return -EINVAL;
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- return 0;
- case VID_PLAY_ACTIVE_SCANLINES:
- if (CurrentMode == VIDEO_MODE_PAL) {
- if (pmode.p1 < 1 ||
- pmode.p2 > 625)
- return -EINVAL;
- saa->boardcfg[5] = pmode.p1;
- saa->boardcfg[55] = (pmode.p1 +
- (pmode.p2/2) - 1) &
- 0xff;
- } else {
- if (pmode.p1 < 4 ||
- pmode.p2 > 525)
- return -EINVAL;
- saa->boardcfg[4] = pmode.p1;
- saa->boardcfg[54] = (pmode.p1 +
- (pmode.p2/2) - 4) &
- 0xff;
- }
- set_out_format(saa, CurrentMode);
- case VID_PLAY_RESET:
- return do_ibm_reset(saa);
- case VID_PLAY_END_MARK:
- if (saa->endmarktail <
- saa->endmarkhead) {
- if (saa->endmarkhead -
+ saa->boardcfg[5] = pmode.p1;
+ saa->boardcfg[55] = (pmode.p1 +
+ (pmode.p2 / 2) - 1) & 0xff;
+ } else {
+ if (pmode.p1 < 4 || pmode.p2 > 525)
+ return -EINVAL;
+ saa->boardcfg[4] = pmode.p1;
+ saa->boardcfg[54] = (pmode.p1 +
+ (pmode.p2 / 2) - 4) & 0xff;
+ }
+ set_out_format(saa, CurrentMode);
+ case VID_PLAY_RESET:
+ return do_ibm_reset(saa);
+ case VID_PLAY_END_MARK:
+ if (saa->endmarktail < saa->endmarkhead) {
+ if (saa->endmarkhead -
saa->endmarktail < 2)
- return -ENOSPC;
- } else if (saa->endmarkhead <=
- saa->endmarktail) {
- if (saa->endmarktail -
- saa->endmarkhead >
- (MAX_MARKS - 2))
- return -ENOSPC;
- } else
return -ENOSPC;
- saa->endmark[saa->endmarktail] =
- saa->audtail;
- saa->endmarktail++;
- if (saa->endmarktail >= MAX_MARKS)
- saa->endmarktail = 0;
+ } else if (saa->endmarkhead <=saa->endmarktail){
+ if (saa->endmarktail - saa->endmarkhead
+ > (MAX_MARKS - 2))
+ return -ENOSPC;
+ } else
+ return -ENOSPC;
+ saa->endmark[saa->endmarktail] = saa->audtail;
+ saa->endmarktail++;
+ if (saa->endmarktail >= MAX_MARKS)
+ saa->endmarktail = 0;
}
return -EINVAL;
}
case VIDIOCSWRITEMODE:
{
int mode;
- if (copy_from_user((void *) &mode, arg, sizeof(int)))
- return -EFAULT;
+ if (copy_from_user((void *)&mode, arg, sizeof(int)))
+ return -EFAULT;
if (mode == VID_WRITE_MPEG_AUD ||
- mode == VID_WRITE_MPEG_VID ||
- mode == VID_WRITE_CC ||
- mode == VID_WRITE_TTX ||
- mode == VID_WRITE_OSD) {
+ mode == VID_WRITE_MPEG_VID ||
+ mode == VID_WRITE_CC ||
+ mode == VID_WRITE_TTX ||
+ mode == VID_WRITE_OSD) {
saa->writemode = mode;
return 0;
}
@@ -1750,7 +1688,7 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (copy_from_user(&ucode, arg, sizeof(ucode)))
return -EFAULT;
if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
- strncmp(ucode.loadwhat, "dec", 3))
+ strncmp(ucode.loadwhat, "dec", 3))
return -EINVAL;
if ((udata = vmalloc(ucode.datasize)) == NULL)
return -ENOMEM;
@@ -1759,8 +1697,8 @@ static int saa_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
}
ucode.data = udata;
- if (!strncmp(ucode.loadwhat, "decoder.aud", 11)
- || !strncmp(ucode.loadwhat, "decoder.vid", 11))
+ if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
+ !strncmp(ucode.loadwhat, "decoder.vid", 11))
i = initialize_ibmmpeg2(&ucode);
else
i = initialize_fpga(&ucode);
@@ -1805,14 +1743,14 @@ static int saa_mmap(struct file *file, struct vm_area_struct *vma)
return -EINVAL;
}
-static ssize_t saa_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t saa_read(struct file *file, char __user * buf,
+ size_t count, loff_t * ppos)
{
return -EINVAL;
}
-static ssize_t saa_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t saa_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * ppos)
{
struct saa7146 *saa = file->private_data;
unsigned long todo = count;
@@ -1823,20 +1761,22 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
if (saa->writemode == VID_WRITE_MPEG_AUD) {
spin_lock_irqsave(&saa->lock, flags);
if (saa->audhead <= saa->audtail)
- blocksize = 65536-(saa->audtail - saa->audhead);
+ blocksize = 65536 -
+ (saa->audtail - saa->audhead);
else
blocksize = saa->audhead - saa->audtail;
spin_unlock_irqrestore(&saa->lock, flags);
if (blocksize < 16384) {
saawrite(SAA7146_PSR_DEBI_S |
- SAA7146_PSR_PIN1, SAA7146_IER);
+ SAA7146_PSR_PIN1, SAA7146_IER);
saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
/* wait for buffer space to open */
interruptible_sleep_on(&saa->audq);
}
spin_lock_irqsave(&saa->lock, flags);
if (saa->audhead <= saa->audtail) {
- blocksize = 65536-(saa->audtail - saa->audhead);
+ blocksize = 65536 -
+ (saa->audtail - saa->audhead);
split = 65536 - saa->audtail;
} else {
blocksize = saa->audhead - saa->audtail;
@@ -1851,7 +1791,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
return -ENOSPC;
if (split < blocksize) {
if (copy_from_user(saa->audbuf +
- saa->audtail, buf, split))
+ saa->audtail, buf, split))
return -EFAULT;
buf += split;
todo -= split;
@@ -1859,7 +1799,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
saa->audtail = 0;
}
if (copy_from_user(saa->audbuf + saa->audtail, buf,
- blocksize))
+ blocksize))
return -EFAULT;
saa->audtail += blocksize;
todo -= blocksize;
@@ -1868,20 +1808,22 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
} else if (saa->writemode == VID_WRITE_MPEG_VID) {
spin_lock_irqsave(&saa->lock, flags);
if (saa->vidhead <= saa->vidtail)
- blocksize=524288-(saa->vidtail - saa->vidhead);
+ blocksize = 524288 -
+ (saa->vidtail - saa->vidhead);
else
blocksize = saa->vidhead - saa->vidtail;
spin_unlock_irqrestore(&saa->lock, flags);
if (blocksize < 65536) {
saawrite(SAA7146_PSR_DEBI_S |
- SAA7146_PSR_PIN1, SAA7146_IER);
+ SAA7146_PSR_PIN1, SAA7146_IER);
saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
/* wait for buffer space to open */
interruptible_sleep_on(&saa->vidq);
}
spin_lock_irqsave(&saa->lock, flags);
if (saa->vidhead <= saa->vidtail) {
- blocksize=524288-(saa->vidtail - saa->vidhead);
+ blocksize = 524288 -
+ (saa->vidtail - saa->vidhead);
split = 524288 - saa->vidtail;
} else {
blocksize = saa->vidhead - saa->vidtail;
@@ -1896,7 +1838,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
return -ENOSPC;
if (split < blocksize) {
if (copy_from_user(saa->vidbuf +
- saa->vidtail, buf, split))
+ saa->vidtail, buf, split))
return -EFAULT;
buf += split;
todo -= split;
@@ -1904,7 +1846,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
saa->vidtail = 0;
}
if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
- blocksize))
+ blocksize))
return -EFAULT;
saa->vidtail += blocksize;
todo -= blocksize;
@@ -1922,8 +1864,8 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- debiread(saa, debNormal,
- IBM_MP2_DISP_MODE, 2) | 1, 2);
+ debiread(saa, debNormal,
+ IBM_MP2_DISP_MODE, 2) | 1, 2);
/* trigger osd data transfer */
saawrite(SAA7146_PSR_DEBI_S |
SAA7146_PSR_PIN1, SAA7146_IER);
@@ -1935,21 +1877,11 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
static int saa_open(struct inode *inode, struct file *file)
{
- struct saa7146 *saa = NULL;
- unsigned int minor = iminor(inode);
- int i;
+ struct video_device *vdev = video_devdata(file);
+ struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
- for (i = 0; i < SAA7146_MAX; i++) {
- if (saa7146s[i].video_dev.minor == minor) {
- saa = &saa7146s[i];
- }
- }
- if (saa == NULL) {
- return -ENODEV;
- }
file->private_data = saa;
- //saa->video_dev.busy = 0; /* old hack to support multiple open */
saa->user++;
if (saa->user > 1)
return 0; /* device open already, don't reset */
@@ -1961,42 +1893,39 @@ static int saa_release(struct inode *inode, struct file *file)
{
struct saa7146 *saa = file->private_data;
saa->user--;
- //saa->video_dev.busy = 0; /* old hack to support multiple open */
+
if (saa->user > 0) /* still someone using device */
return 0;
saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */
return 0;
}
-static struct file_operations saa_fops =
-{
- .owner = THIS_MODULE,
- .open = saa_open,
- .release = saa_release,
- .ioctl = saa_ioctl,
- .read = saa_read,
- .llseek = no_llseek,
- .write = saa_write,
- .mmap = saa_mmap,
+static struct file_operations saa_fops = {
+ .owner = THIS_MODULE,
+ .open = saa_open,
+ .release = saa_release,
+ .ioctl = saa_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .read = saa_read,
+ .llseek = no_llseek,
+ .write = saa_write,
+ .mmap = saa_mmap,
};
/* template for video_device-structure */
-static struct video_device saa_template =
-{
- .name = "SAA7146A",
- .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
- .hardware = VID_HARDWARE_SAA7146,
- .fops = &saa_fops,
- .minor = -1,
+static struct video_device saa_template = {
+ .name = "SAA7146A",
+ .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
+ .hardware = VID_HARDWARE_SAA7146,
+ .fops = &saa_fops,
+ .minor = -1,
};
-static int configure_saa7146(struct pci_dev *dev, int num)
+static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
{
- int result;
- struct saa7146 *saa;
+ int retval;
+ struct saa7146 *saa = pci_get_drvdata(pdev);
- saa = &saa7146s[num];
-
saa->endmarkhead = saa->endmarktail = 0;
saa->win.x = saa->win.y = 0;
saa->win.width = saa->win.cropwidth = 720;
@@ -2012,7 +1941,6 @@ static int configure_saa7146(struct pci_dev *dev, int num)
saa->picture.contrast = 38768;
saa->picture.colour = 32768;
saa->cap = 0;
- saa->dev = dev;
saa->nr = num;
saa->playmode = VID_PLAY_NORMAL;
memset(saa->boardcfg, 0, 64); /* clear board config area */
@@ -2032,45 +1960,59 @@ static int configure_saa7146(struct pci_dev *dev, int num)
init_waitqueue_head(&saa->vidq);
spin_lock_init(&saa->lock);
- if (pci_enable_device(dev))
- return -EIO;
-
- saa->id = dev->device;
- saa->irq = dev->irq;
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
+ goto err;
+ }
+
+ saa->id = pdev->device;
+ saa->irq = pdev->irq;
saa->video_dev.minor = -1;
- saa->saa7146_adr = pci_resource_start(dev, 0);
- pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision);
+ saa->saa7146_adr = pci_resource_start(pdev, 0);
+ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
- if (!saa->saa7146_mem)
- return -EIO;
+ if (saa->saa7146_mem == NULL) {
+ dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
+ retval = -EIO;
+ goto err;
+ }
memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
saawrite(0, SAA7146_IER); /* turn off all interrupts */
- result = request_irq(saa->irq, saa7146_irq,
- SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa);
- if (result == -EINVAL)
- printk(KERN_ERR "stradis%d: Bad irq number or handler\n",
- num);
- if (result == -EBUSY)
- printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP"
- " config in BIOS\n", num, saa->irq);
- if (result < 0) {
- iounmap(saa->saa7146_mem);
- return result;
- }
- pci_set_master(dev);
- if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) {
- iounmap(saa->saa7146_mem);
- return -1;
+
+ retval = request_irq(saa->irq, saa7146_irq, SA_SHIRQ | SA_INTERRUPT,
+ "stradis", saa);
+ if (retval == -EINVAL)
+ dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
+ else if (retval == -EBUSY)
+ dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
+ "in BIOS\n", num, saa->irq);
+ if (retval < 0)
+ goto errio;
+
+ pci_set_master(pdev);
+ retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
+ video_nr);
+ if (retval < 0) {
+ dev_err(&pdev->dev, "%d: error in registering video device!\n",
+ num);
+ goto errio;
}
+
return 0;
+errio:
+ iounmap(saa->saa7146_mem);
+err:
+ return retval;
}
-static int init_saa7146(int i)
+static int __devinit init_saa7146(struct pci_dev *pdev)
{
- struct saa7146 *saa = &saa7146s[i];
+ struct saa7146 *saa = pci_get_drvdata(pdev);
+ memset(saa, 0, sizeof(*saa));
saa->user = 0;
/* reset the saa7146 */
saawrite(0xffff0000, SAA7146_MC1);
@@ -2088,23 +2030,23 @@ static int init_saa7146(int i)
saawrite(0x00000000, SAA7146_DD1_STREAM_A);
saawrite(0x00000000, SAA7146_BRS_CTRL);
saawrite(0x80400040, SAA7146_BCS_CTRL);
- saawrite(0x0000e000 /*| (1<<29)*/, SAA7146_HPS_CTRL);
+ saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL);
saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
saawrite(0x00000000, SAA7146_ACON1);
saawrite(0x00000000, SAA7146_ACON2);
saawrite(0x00000600, SAA7146_I2C_STATUS);
saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
- SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
- SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
- SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
- SAA7146_MC2);
+ SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
+ SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
+ SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
+ SAA7146_MC2);
/* setup arbitration control registers */
saawrite(0x1412121a, SAA7146_PCI_BT_V1);
/* allocate 32k dma buffer + 4k for page table */
if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i);
- return -1;
+ dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr);
+ goto err;
}
#if 0
saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */
@@ -2114,133 +2056,162 @@ static int init_saa7146(int i)
#endif
saa->audhead = saa->vidhead = saa->osdhead = 0;
saa->audtail = saa->vidtail = saa->osdtail = 0;
- if (saa->vidbuf == NULL)
- if ((saa->vidbuf = vmalloc(524288)) == NULL) {
- printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
- return -ENOMEM;
- }
- if (saa->audbuf == NULL)
- if ((saa->audbuf = vmalloc(65536)) == NULL) {
- printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
- vfree(saa->vidbuf);
- saa->vidbuf = NULL;
- return -ENOMEM;
- }
- if (saa->osdbuf == NULL)
- if ((saa->osdbuf = vmalloc(131072)) == NULL) {
- printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
- vfree(saa->vidbuf);
- vfree(saa->audbuf);
- saa->vidbuf = saa->audbuf = NULL;
- return -ENOMEM;
- }
+ if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) {
+ dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
+ goto err;
+ }
+ if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
+ dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
+ goto errvid;
+ }
+ if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
+ dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
+ goto erraud;
+ }
/* allocate 81920 byte buffer for clipping */
- if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr);
- vfree(saa->vidbuf);
- vfree(saa->audbuf);
- vfree(saa->osdbuf);
- saa->vidbuf = saa->audbuf = saa->osdbuf = NULL;
- saa->dmavid2 = NULL;
- return -1;
+ if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
+ dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
+ goto errosd;
}
- memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE); /* clip everything */
/* setup clipping registers */
saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
- SAA7146_PROT_ADDR2);
+ SAA7146_PROT_ADDR2);
saawrite(256, SAA7146_PITCH2);
- saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
+ saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
SAA7146_MC2);
I2CBusScan(saa);
+
return 0;
+errosd:
+ vfree(saa->osdbuf);
+ saa->osdbuf = NULL;
+erraud:
+ vfree(saa->audbuf);
+ saa->audbuf = NULL;
+errvid:
+ vfree(saa->vidbuf);
+ saa->vidbuf = NULL;
+err:
+ return -ENOMEM;
}
-static void release_saa(void)
+static void stradis_release_saa(struct pci_dev *pdev)
{
u8 command;
- int i;
- struct saa7146 *saa;
+ struct saa7146 *saa = pci_get_drvdata(pdev);
- for (i = 0; i < saa_num; i++) {
- saa = &saa7146s[i];
+ /* turn off all capturing, DMA and IRQs */
+ saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
+ saawrite(0, SAA7146_MC2);
+ saawrite(0, SAA7146_IER);
+ saawrite(0xffffffffUL, SAA7146_ISR);
+
+ /* disable PCI bus-mastering */
+ pci_read_config_byte(pdev, PCI_COMMAND, &command);
+ command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_byte(pdev, PCI_COMMAND, command);
+
+ /* unmap and free memory */
+ saa->audhead = saa->audtail = saa->osdhead = 0;
+ saa->vidhead = saa->vidtail = saa->osdtail = 0;
+ vfree(saa->vidbuf);
+ vfree(saa->audbuf);
+ vfree(saa->osdbuf);
+ kfree(saa->dmavid2);
+ saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
+ saa->dmavid2 = NULL;
+ 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);
+ if (saa->video_dev.minor != -1)
+ video_unregister_device(&saa->video_dev);
+}
- /* turn off all capturing, DMA and IRQs */
- saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
- saawrite(0, SAA7146_MC2);
- saawrite(0, SAA7146_IER);
- saawrite(0xffffffffUL, SAA7146_ISR);
-
- /* disable PCI bus-mastering */
- pci_read_config_byte(saa->dev, PCI_COMMAND, &command);
- command &= ~PCI_COMMAND_MASTER;
- pci_write_config_byte(saa->dev, PCI_COMMAND, command);
-
- /* unmap and free memory */
- saa->audhead = saa->audtail = saa->osdhead = 0;
- saa->vidhead = saa->vidtail = saa->osdtail = 0;
- vfree(saa->vidbuf);
- vfree(saa->audbuf);
- vfree(saa->osdbuf);
- kfree(saa->dmavid2);
- saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
- saa->dmavid2 = NULL;
- 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);
- if (saa->video_dev.minor != -1)
- video_unregister_device(&saa->video_dev);
+static int __devinit stradis_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int retval = -EINVAL;
+
+ if (saa_num >= SAA7146_MAX)
+ goto err;
+
+ if (!pdev->subsystem_vendor)
+ dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
+ else
+ dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
+
+ pci_set_drvdata(pdev, &saa7146s[saa_num]);
+
+ retval = configure_saa7146(pdev, saa_num);
+ if (retval) {
+ dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
+ goto err;
+ }
+
+ if (init_saa7146(pdev) < 0) {
+ dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
+ retval = -EIO;
+ goto errrel;
}
+
+ saa_num++;
+
+ return 0;
+errrel:
+ stradis_release_saa(pdev);
+err:
+ return retval;
+}
+
+static void __devexit stradis_remove(struct pci_dev *pdev)
+{
+ stradis_release_saa(pdev);
}
+static struct pci_device_id stradis_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);
+
+static struct pci_driver stradis_driver = {
+ .name = "stradis",
+ .id_table = stradis_pci_tbl,
+ .probe = stradis_probe,
+ .remove = __devexit_p(stradis_remove)
+};
-static int __init stradis_init (void)
+int __init stradis_init(void)
{
- struct pci_dev *dev = NULL;
- int result = 0, i;
+ int retval;
saa_num = 0;
- while ((dev = pci_find_device(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, dev))) {
- if (!dev->subsystem_vendor)
- printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num);
- else
- printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num);
- result = configure_saa7146(dev, saa_num++);
- if (result)
- return result;
- }
- if (saa_num)
- printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num);
- else
- return -EINVAL;
- for (i = 0; i < saa_num; i++)
- if (init_saa7146(i) < 0) {
- release_saa();
- return -EIO;
- }
- return 0;
-}
+ retval = pci_register_driver(&stradis_driver);
+ if (retval)
+ printk(KERN_ERR "stradis: Unable to register pci driver.\n");
+ return retval;
+}
-static void __exit stradis_exit (void)
+void __exit stradis_exit(void)
{
- release_saa();
+ pci_unregister_driver(&stradis_driver);
printk(KERN_INFO "stradis: module cleanup complete\n");
}
-
module_init(stradis_init);
module_exit(stradis_exit);
-
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 549c9929f107..fc3d5824efff 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -50,6 +50,7 @@
#include "bttv.h"
#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#ifndef VIDEO_AUDIO_BALANCE
# define VIDEO_AUDIO_BALANCE 32
@@ -90,9 +91,6 @@ struct tda7432 {
static struct i2c_driver driver;
static struct i2c_client client_template;
-#define dprintk if (debug) printk
-#define d2printk if (debug > 1) printk
-
/* The TDA7432 is made by STS-Thompson
* http://www.st.com
* http://us.st.com/stonline/books/pdf/docs/4056.pdf
@@ -229,12 +227,12 @@ static struct i2c_client client_template;
static int tda7432_write(struct i2c_client *client, int subaddr, int val)
{
unsigned char buffer[2];
- d2printk("tda7432: In tda7432_write\n");
- dprintk("tda7432: Writing %d 0x%x\n", subaddr, val);
+ v4l_dbg(2, debug,client,"In tda7432_write\n");
+ v4l_dbg(1, debug,client,"Writing %d 0x%x\n", subaddr, val);
buffer[0] = subaddr;
buffer[1] = val;
if (2 != i2c_master_send(client,buffer,2)) {
- printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n",
+ v4l_err(client,"I/O error, trying (write %d 0x%x)\n",
subaddr, val);
return -1;
}
@@ -247,9 +245,9 @@ static int tda7432_set(struct i2c_client *client)
{
struct tda7432 *t = i2c_get_clientdata(client);
unsigned char buf[16];
- d2printk("tda7432: In tda7432_set\n");
+ v4l_dbg(2, debug,client,"In tda7432_set\n");
- dprintk(KERN_INFO
+ v4l_dbg(1, debug,client,
"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud);
buf[0] = TDA7432_IN;
@@ -263,7 +261,7 @@ static int tda7432_set(struct i2c_client *client)
buf[8] = t->rr;
buf[9] = t->loud;
if (10 != i2c_master_send(client,buf,10)) {
- printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n");
+ v4l_err(client,"I/O error, trying tda7432_set\n");
return -1;
}
@@ -273,7 +271,7 @@ static int tda7432_set(struct i2c_client *client)
static void do_tda7432_init(struct i2c_client *client)
{
struct tda7432 *t = i2c_get_clientdata(client);
- d2printk("tda7432: In tda7432_init\n");
+ v4l_dbg(2, debug,client,"In tda7432_init\n");
t->input = TDA7432_STEREO_IN | /* Main (stereo) input */
TDA7432_BASS_SYM | /* Symmetric bass cut */
@@ -301,12 +299,10 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct tda7432 *t;
struct i2c_client *client;
- d2printk("tda7432: In tda7432_attach\n");
- t = kmalloc(sizeof *t,GFP_KERNEL);
+ t = kzalloc(sizeof *t,GFP_KERNEL);
if (!t)
return -ENOMEM;
- memset(t,0,sizeof *t);
client = &t->c;
memcpy(client,&client_template,sizeof(struct i2c_client));
@@ -315,21 +311,16 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(client, t);
do_tda7432_init(client);
- printk(KERN_INFO "tda7432: init\n");
-
i2c_attach_client(client);
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", addr << 1, adap->name);
return 0;
}
static int tda7432_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda7432_attach);
-#else
- if (adap->id == I2C_HW_B_BT848)
- return i2c_probe(adap, &addr_data, tda7432_attach);
-#endif
return 0;
}
@@ -348,7 +339,9 @@ static int tda7432_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
struct tda7432 *t = i2c_get_clientdata(client);
- d2printk("tda7432: In tda7432_command\n");
+ v4l_dbg(2, debug,client,"In tda7432_command\n");
+ if (debug>1)
+ v4l_i2c_print_ioctl(client,cmd);
switch (cmd) {
/* --- v4l ioctls --- */
@@ -359,7 +352,6 @@ static int tda7432_command(struct i2c_client *client,
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
- dprintk("tda7432: VIDIOCGAUDIO\n");
va->flags |= VIDEO_AUDIO_VOLUME |
VIDEO_AUDIO_BASS |
@@ -414,7 +406,6 @@ static int tda7432_command(struct i2c_client *client,
case VIDIOCSAUDIO:
{
struct video_audio *va = arg;
- dprintk("tda7432: VIDEOCSAUDIO\n");
if(va->flags & VIDEO_AUDIO_VOLUME){
if(!maxvol){ /* max +20db */
@@ -490,11 +481,6 @@ static int tda7432_command(struct i2c_client *client,
} /* end of VIDEOCSAUDIO case */
- default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */
-
- /* nothing */
- d2printk("tda7432: Default\n");
-
} /* end of (cmd) switch */
return 0;
@@ -502,7 +488,7 @@ static int tda7432_command(struct i2c_client *client,
static struct i2c_driver driver = {
.driver = {
- .name = "i2c tda7432 driver",
+ .name = "tda7432",
},
.id = I2C_DRIVERID_TDA7432,
.attach_adapter = tda7432_probe,
@@ -519,7 +505,7 @@ static struct i2c_client client_template =
static int __init tda7432_init(void)
{
if ( (loudness < 0) || (loudness > 15) ) {
- printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n");
+ printk(KERN_ERR "loudness parameter must be between 0 and 15\n");
return -EINVAL;
}
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index 61d94ddaff41..7b4fb282ac82 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -398,14 +398,8 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
return 0;
}
-
/*---------------------------------------------------------------------*/
-#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
-#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
-#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
-#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
-
static void set_audio(struct tuner *t)
{
char* mode;
@@ -573,8 +567,8 @@ int tda8290_init(struct i2c_client *c)
}
tuner_info("tuner: type set to %s\n", c->name);
- t->tv_freq = set_tv_freq;
- t->radio_freq = set_radio_freq;
+ t->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = has_signal;
t->standby = standby;
t->tda827x_lpsel = 0;
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 9c3ecf7a0fed..ef98c4982250 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -232,10 +232,9 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *client;
dprintk("In tda9875_attach\n");
- t = kmalloc(sizeof *t,GFP_KERNEL);
+ t = kzalloc(sizeof *t,GFP_KERNEL);
if (!t)
return -ENOMEM;
- memset(t,0,sizeof *t);
client = &t->c;
memcpy(client,&client_template,sizeof(struct i2c_client));
@@ -257,13 +256,8 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind)
static int tda9875_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9875_attach);
-#else
- if (adap->id == I2C_HW_B_BT848)
- return i2c_probe(adap, &addr_data, tda9875_attach);
-#endif
return 0;
}
@@ -373,7 +367,7 @@ static int tda9875_command(struct i2c_client *client,
static struct i2c_driver driver = {
.driver = {
- .name = "i2c tda9875 driver",
+ .name = "tda9875",
},
.id = I2C_DRIVERID_TDA9875,
.attach_adapter = tda9875_probe,
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 7165a1b9625a..5815649bdc78 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -9,7 +9,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#include <media/tuner.h>
@@ -57,7 +57,6 @@ struct tda9887 {
v4l2_std_id std;
enum tuner_mode mode;
unsigned int config;
- unsigned int pinnacle_id;
unsigned int using_v4l2;
unsigned int radio_mode;
unsigned char data[4];
@@ -115,6 +114,9 @@ static struct i2c_client client_template;
#define cAudioGain0 0x00 // bit c7
#define cAudioGain6 0x80 // bit c7
+#define cTopMask 0x1f // bit c0:4
+#define cTopPalSecamDefault 0x14 // bit c0:4
+#define cTopNtscRadioDefault 0x10 // bit c0:4
//// third reg (e)
#define cAudioIF_4_5 0x00 // bit e0:1
@@ -146,13 +148,15 @@ static struct i2c_client client_template;
static struct tvnorm tvnorms[] = {
{
- .std = V4L2_STD_PAL_BG,
- .name = "PAL-BG",
+ .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
+ .name = "PAL-BGHN",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_5_5 |
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_5_5 |
cVideoIF_38_90 ),
},{
.std = V4L2_STD_PAL_I,
@@ -160,8 +164,10 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_6_0 |
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_0 |
cVideoIF_38_90 ),
},{
.std = V4L2_STD_PAL_DK,
@@ -169,52 +175,80 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_6_5 |
- cVideoIF_38_00 ),
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_5 |
+ cVideoIF_38_90 ),
},{
- .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N,
- .name = "PAL-M/N",
+ .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
+ .name = "PAL-M/Nc",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis75 ),
- .e = ( cAudioIF_4_5 |
+ cDeemphasis75 |
+ cTopNtscRadioDefault),
+ .e = ( cGating_36 |
+ cAudioIF_4_5 |
cVideoIF_45_75 ),
},{
+ .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
+ .name = "SECAM-BGH",
+ .b = ( cPositiveAmTV |
+ cQSS ),
+ .c = ( cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_5_5 |
+ cVideoIF_38_90 ),
+ },{
.std = V4L2_STD_SECAM_L,
.name = "SECAM-L",
.b = ( cPositiveAmTV |
cQSS ),
+ .c = ( cTopPalSecamDefault),
.e = ( cGating_36 |
cAudioIF_6_5 |
cVideoIF_38_90 ),
},{
+ .std = V4L2_STD_SECAM_LC,
+ .name = "SECAM-L'",
+ .b = ( cOutputPort2Inactive |
+ cPositiveAmTV |
+ cQSS ),
+ .c = ( cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_5 |
+ cVideoIF_33_90 ),
+ },{
.std = V4L2_STD_SECAM_DK,
.name = "SECAM-DK",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_6_5 |
- cVideoIF_38_00 ),
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_5 |
+ cVideoIF_38_90 ),
},{
.std = V4L2_STD_NTSC_M,
.name = "NTSC-M",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis75 ),
+ cDeemphasis75 |
+ cTopNtscRadioDefault),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_45_75 ),
},{
.std = V4L2_STD_NTSC_M_JP,
- .name = "NTSC-JP",
+ .name = "NTSC-M-JP",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
+ cDeemphasis50 |
+ cTopNtscRadioDefault),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_58_75 ),
@@ -226,8 +260,10 @@ static struct tvnorm radio_stereo = {
.b = ( cFmRadio |
cQSS ),
.c = ( cDeemphasisOFF |
- cAudioGain6 ),
- .e = ( cAudioIF_5_5 |
+ cAudioGain6 |
+ cTopNtscRadioDefault),
+ .e = ( cTunerGainLow |
+ cAudioIF_5_5 |
cRadioIF_38_90 ),
};
@@ -236,8 +272,10 @@ static struct tvnorm radio_mono = {
.b = ( cFmRadio |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50),
- .e = ( cAudioIF_5_5 |
+ cDeemphasis75 |
+ cTopNtscRadioDefault),
+ .e = ( cTunerGainLow |
+ cAudioIF_5_5 |
cRadioIF_38_90 ),
};
@@ -400,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
static unsigned int port1 = UNSET;
static unsigned int port2 = UNSET;
static unsigned int qss = UNSET;
-static unsigned int adjust = 0x10;
+static unsigned int adjust = UNSET;
+
module_param(port1, int, 0644);
module_param(port2, int, 0644);
module_param(qss, int, 0644);
@@ -428,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf)
buf[1] &= ~cQSS;
}
- if (adjust >= 0x00 && adjust < 0x20)
+ if (adjust >= 0x00 && adjust < 0x20) {
+ buf[2] &= ~cTopMask;
buf[2] |= adjust;
+ }
return 0;
}
@@ -465,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
break;
}
}
+ if (t->config & TDA9887_TOP_SET) {
+ buf[2] &= ~cTopMask;
+ buf[2] |= (t->config >> 8) & cTopMask;
+ }
if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
buf[1] &= ~cQSS;
return 0;
@@ -472,38 +517,13 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
/* ---------------------------------------------------------------------- */
-static int tda9887_set_pinnacle(struct tda9887 *t, char *buf)
-{
- unsigned int bCarrierMode = UNSET;
-
- if (t->std & V4L2_STD_625_50) {
- if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) {
- bCarrierMode = cIntercarrier;
- } else {
- bCarrierMode = cQSS;
- }
- }
- if (t->std & V4L2_STD_525_60) {
- if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
- bCarrierMode = cIntercarrier;
- } else {
- bCarrierMode = cQSS;
- }
- }
-
- if (bCarrierMode != UNSET) {
- buf[1] &= ~0x04;
- buf[1] |= bCarrierMode;
- }
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
-static char pal[] = "-";
module_param_string(pal, pal, sizeof(pal), 0644);
-static char secam[] = "-";
module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
static int tda9887_fixup_std(struct tda9887 *t)
{
@@ -514,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t)
case 'B':
case 'g':
case 'G':
- tda9887_dbg("insmod fixup: PAL => PAL-BG\n");
- t->std = V4L2_STD_PAL_BG;
+ case 'h':
+ case 'H':
+ case 'n':
+ case 'N':
+ if (pal[1] == 'c' || pal[1] == 'C') {
+ tda9887_dbg("insmod fixup: PAL => PAL-Nc\n");
+ t->std = V4L2_STD_PAL_Nc;
+ } else {
+ tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n");
+ t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N;
+ }
break;
case 'i':
case 'I':
@@ -529,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
tda9887_dbg("insmod fixup: PAL => PAL-DK\n");
t->std = V4L2_STD_PAL_DK;
break;
+ case 'm':
+ case 'M':
+ tda9887_dbg("insmod fixup: PAL => PAL-M\n");
+ t->std = V4L2_STD_PAL_M;
+ break;
case '-':
/* default parameter, do nothing */
break;
@@ -539,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t)
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
switch (secam[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ case 'h':
+ case 'H':
+ tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n");
+ t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ break;
case 'd':
case 'D':
case 'k':
@@ -548,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t)
break;
case 'l':
case 'L':
- tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
- t->std = V4L2_STD_SECAM_L;
+ if (secam[1] == 'c' || secam[1] == 'C') {
+ tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n");
+ t->std = V4L2_STD_SECAM_LC;
+ } else {
+ tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
+ t->std = V4L2_STD_SECAM_L;
+ }
break;
case '-':
/* default parameter, do nothing */
@@ -559,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t)
break;
}
}
+ if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+ switch (ntsc[0]) {
+ case 'm':
+ case 'M':
+ tda9887_dbg("insmod fixup: NTSC => NTSC-M\n");
+ t->std = V4L2_STD_NTSC_M;
+ break;
+ case 'j':
+ case 'J':
+ tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
+ t->std = V4L2_STD_NTSC_M_JP;
+ break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tda9887_info("ntsc= argument not recognised\n");
+ break;
+ }
+ }
return 0;
}
@@ -581,12 +649,22 @@ static int tda9887_configure(struct tda9887 *t)
memset(t->data,0,sizeof(t->data));
tda9887_set_tvnorm(t,t->data);
+ /* A note on the port settings:
+ These settings tend to depend on the specifics of the board.
+ By default they are set to inactive (bit value 1) by this driver,
+ overwriting any changes made by the tvnorm. This means that it
+ is the responsibility of the module using the tda9887 to set
+ these values in case of changes in the tvnorm.
+ In many cases port 2 should be made active (0) when selecting
+ SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
+
+ For the other standards the tda9887 application note says that
+ the ports should be set to active (0), but, again, that may
+ differ depending on the precise hardware configuration.
+ */
t->data[1] |= cOutputPort1Inactive;
t->data[1] |= cOutputPort2Inactive;
- if (UNSET != t->pinnacle_id) {
- tda9887_set_pinnacle(t,t->data);
- }
tda9887_set_config(t,t->data);
tda9887_set_insmod(t,t->data);
@@ -594,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t)
t->data[1] |= cForcedMuteAudioON;
}
-
tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
t->data[1],t->data[2],t->data[3]);
if (debug > 1)
@@ -619,13 +696,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
- if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
+ if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
- memset(t,0,sizeof(*t));
t->client = client_template;
t->std = 0;
- t->pinnacle_id = UNSET;
t->radio_mode = V4L2_TUNER_MODE_STEREO;
tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name);
@@ -638,18 +713,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
static int tda9887_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9887_attach);
-#else
- switch (adap->id) {
- case I2C_HW_B_BT848:
- case I2C_HW_B_RIVA:
- case I2C_HW_SAA7134:
- return i2c_probe(adap, &addr_data, tda9887_attach);
- break;
- }
-#endif
return 0;
}
@@ -689,14 +754,6 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
tda9887_configure(t);
break;
}
- case AUDC_CONFIG_PINNACLE:
- {
- int *i = arg;
-
- t->pinnacle_id = *i;
- tda9887_configure(t);
- break;
- }
case TDA9887_SET_CONFIG:
{
int *i = arg;
@@ -787,7 +844,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
case VIDIOC_LOG_STATUS:
{
- tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]);
+ tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]);
break;
}
default:
@@ -824,7 +881,7 @@ static struct i2c_driver driver = {
.detach_client = tda9887_detach,
.command = tda9887_command,
.driver = {
- .name = "i2c tda9887 driver",
+ .name = "tda9887",
.suspend = tda9887_suspend,
.resume = tda9887_resume,
},
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index a9375ef05de1..c2b98f81c192 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -17,6 +17,9 @@
#define PREFIX "TEA5767 "
+/* from tuner-core.c */
+extern int tuner_debug;
+
/*****************************************************************************/
/******************************
@@ -59,7 +62,7 @@
#define TEA5767_PORT1_HIGH 0x01
-/* Forth register */
+/* Fourth register */
#define TEA5767_PORT2_HIGH 0x80
/* Chips stops working. Only I2C bus remains on */
#define TEA5767_STDBY 0x40
@@ -82,7 +85,7 @@
/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
#define TEA5767_SRCH_IND 0x01
-/* Fiveth register */
+/* Fifth register */
/* By activating, it will use Xtal at 13 MHz as reference for divider */
#define TEA5767_PLLREF_ENABLE 0x80
@@ -106,13 +109,13 @@
#define TEA5767_STEREO_MASK 0x80
#define TEA5767_IF_CNTR_MASK 0x7f
-/* Four register */
+/* Fourth register */
#define TEA5767_ADC_LEVEL_MASK 0xf0
/* should be 0 */
#define TEA5767_CHIP_ID_MASK 0x0f
-/* Fiveth register */
+/* Fifth register */
/* Reserved for future extensions */
#define TEA5767_RESERVED_MASK 0xff
@@ -217,19 +220,19 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
buffer[2] |= TEA5767_HIGH_LO_INJECT;
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 + 700000 + 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_13MHz:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 - 700000 - 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_32768:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
buffer[3] |= TEA5767_XTAL_32768;
/* const 700=4000*175 Khz - to adjust freq to right value */
- div = ((frq * 4000 / 16 - 700000 - 225000) + 16384) >> 15;
+ div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
break;
case TEA5767_HIGH_LO_32768:
default:
@@ -264,7 +267,7 @@ static int tea5767_signal(struct i2c_client *c)
if (5 != (rc = i2c_master_recv(c, buffer, 5)))
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
- return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << (13 - 4));
+ return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
}
static int tea5767_stereo(struct i2c_client *c)
@@ -347,8 +350,8 @@ int tea5767_tuner_init(struct i2c_client *c)
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->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = tea5767_signal;
t->is_stereo = tea5767_stereo;
t->standby = tea5767_standby;
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index c4ba3742f5c7..4dcba5a4fff0 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -99,11 +99,10 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* allocate memory for client structure */
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (0 == client) {
return -ENOMEM;
}
- memset(client, 0x0, sizeof(struct i2c_client));
/* fill client structure */
memcpy(client, &client_template, sizeof(struct i2c_client));
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index d97f66804c37..c4a78e7a5a58 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -193,8 +193,7 @@ static struct i2c_client client_template =
static int __init
tuner3036_init(void)
{
- i2c_add_driver(&i2c_driver_tuner);
- return 0;
+ return i2c_add_driver(&i2c_driver_tuner);
}
static void __exit
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index c13c7b95ef35..2995b22acb43 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -20,10 +20,9 @@
#include <linux/init.h>
#include <media/tuner.h>
+#include <media/v4l2-common.h>
#include <media/audiochip.h>
-#include "msp3400.h"
-
#define UNSET (-1U)
/* standard i2c insmod options */
@@ -38,21 +37,30 @@ I2C_CLIENT_INSMOD;
/* insmod options used at init time => read/only */
static unsigned int addr = 0;
-module_param(addr, int, 0444);
-
static unsigned int no_autodetect = 0;
-module_param(no_autodetect, int, 0444);
-
static unsigned int show_i2c = 0;
-module_param(show_i2c, int, 0444);
/* insmod options used at runtime => read/write */
-unsigned int tuner_debug = 0;
-module_param(tuner_debug, int, 0644);
+static unsigned int tuner_debug_old = 0;
+int tuner_debug = 0;
static unsigned int tv_range[2] = { 44, 958 };
static unsigned int radio_range[2] = { 65, 108 };
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+
+module_param(addr, int, 0444);
+module_param(no_autodetect, int, 0444);
+module_param(show_i2c, int, 0444);
+/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */
+module_param_named(tuner_debug,tuner_debug_old, int, 0444);
+module_param_named(debug,tuner_debug, int, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
module_param_array(tv_range, int, NULL, 0644);
module_param_array(radio_range, int, NULL, 0644);
@@ -74,7 +82,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->tv_freq) {
+ if (NULL == t->set_tv_freq) {
tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
@@ -82,8 +90,14 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
freq / 16, freq % 16 * 100 / 16, tv_range[0],
tv_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < tv_range[0] * 16)
+ freq = tv_range[0] * 16;
+ else
+ freq = tv_range[1] * 16;
}
- t->tv_freq(c, freq);
+ t->set_tv_freq(c, freq);
}
static void set_radio_freq(struct i2c_client *c, unsigned int freq)
@@ -94,18 +108,23 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->radio_freq) {
+ if (NULL == t->set_radio_freq) {
tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
- if (freq <= radio_range[0] * 16000 || freq >= radio_range[1] * 16000) {
+ if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
freq / 16000, freq % 16000 * 100 / 16000,
radio_range[0], radio_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < radio_range[0] * 16000)
+ freq = radio_range[0] * 16000;
+ else
+ freq = radio_range[1] * 16000;
}
- t->radio_freq(c, freq);
- return;
+ t->set_radio_freq(c, freq);
}
static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -117,15 +136,16 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
tuner_dbg("radio freq set to %lu.%02lu\n",
freq / 16000, freq % 16000 * 100 / 16000);
set_radio_freq(c, freq);
+ t->radio_freq = freq;
break;
case V4L2_TUNER_ANALOG_TV:
case V4L2_TUNER_DIGITAL_TV:
tuner_dbg("tv freq set to %lu.%02lu\n",
freq / 16, freq % 16 * 100 / 16);
set_tv_freq(c, freq);
+ t->tv_freq = freq;
break;
}
- t->freq = freq;
}
static void set_type(struct i2c_client *c, unsigned int type,
@@ -204,7 +224,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
- set_freq(c, t->freq);
+ set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
c->adapter->name, c->driver->driver.name, c->addr << 1, type,
t->mode_mask);
@@ -249,11 +269,6 @@ static inline int check_mode(struct tuner *t, char *cmd)
return 0;
}
-static char pal[] = "-";
-module_param_string(pal, pal, sizeof(pal), 0644);
-static char secam[] = "--";
-module_param_string(secam, secam, sizeof(secam), 0644);
-
/* get more precise norm info from insmod option */
static int tuner_fixup_std(struct tuner *t)
{
@@ -285,8 +300,13 @@ static int tuner_fixup_std(struct tuner *t)
break;
case 'N':
case 'n':
- tuner_dbg ("insmod fixup: PAL => PAL-N\n");
- t->std = V4L2_STD_PAL_N;
+ if (pal[1] == 'c' || pal[1] == 'C') {
+ tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
+ t->std = V4L2_STD_PAL_Nc;
+ } else {
+ tuner_dbg ("insmod fixup: PAL => PAL-N\n");
+ t->std = V4L2_STD_PAL_N;
+ }
break;
case '-':
/* default parameter, do nothing */
@@ -298,6 +318,15 @@ static int tuner_fixup_std(struct tuner *t)
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
switch (secam[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ case 'h':
+ case 'H':
+ tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
+ t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ break;
case 'd':
case 'D':
case 'k':
@@ -324,9 +353,60 @@ static int tuner_fixup_std(struct tuner *t)
}
}
+ if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+ switch (ntsc[0]) {
+ case 'm':
+ case 'M':
+ tuner_dbg("insmod fixup: NTSC => NTSC-M\n");
+ t->std = V4L2_STD_NTSC_M;
+ break;
+ case 'j':
+ case 'J':
+ tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
+ t->std = V4L2_STD_NTSC_M_JP;
+ break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tuner_info("ntsc= argument not recognised\n");
+ break;
+ }
+ }
return 0;
}
+static void tuner_status(struct i2c_client *client)
+{
+ struct tuner *t = i2c_get_clientdata(client);
+ unsigned long freq, freq_fraction;
+ const char *p;
+
+ switch (t->mode) {
+ case V4L2_TUNER_RADIO: p = "radio"; break;
+ case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break;
+ case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break;
+ default: p = "undefined"; break;
+ }
+ if (t->mode == V4L2_TUNER_RADIO) {
+ freq = t->radio_freq / 16000;
+ freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
+ } else {
+ freq = t->tv_freq / 16;
+ freq_fraction = (t->tv_freq % 16) * 100 / 16;
+ }
+ tuner_info("Tuner mode: %s\n", p);
+ tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
+ tuner_info("Standard: 0x%08llx\n", t->std);
+ if (t->mode == V4L2_TUNER_RADIO) {
+ if (t->has_signal) {
+ tuner_info("Signal strength: %d\n", t->has_signal(client));
+ }
+ if (t->is_stereo) {
+ tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no");
+ }
+ }
+}
/* ---------------------------------------------------------------------- */
/* static var Used only in tuner_attach and tuner_probe */
@@ -342,16 +422,20 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
- t = kmalloc(sizeof(struct tuner), GFP_KERNEL);
+ t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
if (NULL == t)
return -ENOMEM;
- memset(t, 0, sizeof(struct tuner));
memcpy(&t->i2c, &client_template, sizeof(struct i2c_client));
i2c_set_clientdata(&t->i2c, t);
t->type = UNSET;
t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
t->audmode = V4L2_TUNER_MODE_STEREO;
t->mode_mask = T_UNINITIALIZED;
+ if (tuner_debug_old) {
+ tuner_debug = tuner_debug_old;
+ printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n");
+ printk(KERN_ERR "tuner: use the debug option instead.\n");
+ }
if (show_i2c) {
unsigned char buffer[16];
@@ -384,7 +468,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
t->type = TUNER_TEA5767;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
- t->freq = 87.5 * 16; /* Sets freq to FM range */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask &= ~T_RADIO;
goto register_client;
@@ -397,7 +481,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
if (default_mode_mask != T_UNINITIALIZED) {
tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask);
t->mode_mask = default_mode_mask;
- t->freq = 400 * 16; /* Sets freq to VHF High */
+ t->tv_freq = 400 * 16; /* Sets freq to VHF High */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask = T_UNINITIALIZED;
}
@@ -478,7 +563,9 @@ static inline int check_v4l2(struct tuner *t)
static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct tuner *t = i2c_get_clientdata(client);
- unsigned int *iarg = (int *)arg;
+
+ if (tuner_debug>1)
+ v4l_i2c_print_ioctl(&(t->i2c),cmd);
switch (cmd) {
/* --- configuration --- */
@@ -491,27 +578,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
set_addr(client, (struct tuner_setup *)arg);
break;
case AUDC_SET_RADIO:
- set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
+ if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
+ == EINVAL)
+ return 0;
+ if (t->radio_freq)
+ set_freq(client, t->radio_freq);
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:
- switch (*iarg) {
- case 2:
- tuner_dbg("pinnacle pal\n");
- t->radio_if2 = 33300 * 1000;
- break;
- case 3:
- tuner_dbg("pinnacle ntsc\n");
- t->radio_if2 = 41300 * 1000;
- break;
- }
+ if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ return 0;
+ if (t->standby)
+ t->standby (client);
break;
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
@@ -521,10 +598,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* Should be implemented, since bttv calls it */
tuner_dbg("VIDIOCSAUDIO not implemented.\n");
-
- break;
- case MSP_SET_MATRIX:
- case TDA9887_SET_CONFIG:
break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
@@ -550,8 +623,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tuner_fixup_std(t);
- if (t->freq)
- set_tv_freq(client, t->freq);
+ if (t->tv_freq)
+ set_tv_freq(client, t->tv_freq);
return 0;
}
case VIDIOCSFREQ:
@@ -625,15 +698,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->std = *id;
tuner_fixup_std(t);
- if (t->freq)
- set_freq(client, t->freq);
+ if (t->tv_freq)
+ set_freq(client, t->tv_freq);
break;
}
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *f = arg;
- t->freq = f->frequency;
switch_v4l2();
if (V4L2_TUNER_RADIO == f->type &&
V4L2_TUNER_RADIO != t->mode) {
@@ -641,7 +713,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
== EINVAL)
return 0;
}
- set_freq(client,t->freq);
+ set_freq(client,f->frequency);
break;
}
@@ -653,7 +725,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
switch_v4l2();
f->type = t->mode;
- f->frequency = t->freq;
+ f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+ t->radio_freq : t->tv_freq;
break;
}
case VIDIOC_G_TUNER:
@@ -704,14 +777,12 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (V4L2_TUNER_RADIO == t->mode) {
t->audmode = tuner->audmode;
- set_radio_freq(client, t->freq);
+ set_radio_freq(client, t->radio_freq);
}
break;
}
- default:
- tuner_dbg("Unimplemented IOCTL 0x%08x(dir=%d,tp='%c',nr=%d,sz=%d)\n",
- cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd),
- _IOC_NR(cmd), _IOC_SIZE(cmd));
+ case VIDIOC_LOG_STATUS:
+ tuner_status(client);
break;
}
@@ -734,8 +805,13 @@ static int tuner_resume(struct device *dev)
struct tuner *t = i2c_get_clientdata (c);
tuner_dbg ("resume\n");
- if (t->freq)
- set_freq(c, t->freq);
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (t->radio_freq)
+ set_freq(c, t->radio_freq);
+ } else {
+ if (t->tv_freq)
+ set_freq(c, t->tv_freq);
+ }
return 0;
}
@@ -747,10 +823,10 @@ static struct i2c_driver driver = {
.detach_client = tuner_detach,
.command = tuner_command,
.driver = {
- .name = "tuner",
- .suspend = tuner_suspend,
- .resume = tuner_resume,
- },
+ .name = "tuner",
+ .suspend = tuner_suspend,
+ .resume = tuner_resume,
+ },
};
static struct i2c_client client_template = {
.name = "(tuner unset)",
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index e0c9fdb9914a..37977ff49780 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -8,6 +8,10 @@
#include <linux/videodev.h>
#include <media/tuner.h>
+static int offset = 0;
+module_param(offset, int, 0666);
+MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+
/* ---------------------------------------------------------------------- */
/* tv standard selection for Temic 4046 FM5
@@ -75,188 +79,16 @@
#define TUNER_PLL_LOCKED 0x40
#define TUNER_STEREO_MK3 0x04
-/* ---------------------------------------------------------------------- */
-
-struct tunertype
-{
- char *name;
- unsigned char Vendor;
- unsigned char Type;
-
- unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */
- unsigned short thresh2; /* band switch VHF_HI <=> UHF */
- unsigned char VHF_L;
- unsigned char VHF_H;
- unsigned char UHF;
- unsigned char config;
- unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL,
- 732 =16*45.75 NTSCi,
- 940 =16*58.75 NTSC-Japan
- 704 =16*44 ATSC */
-};
-
-/*
- * The floats in the tuner struct are computed at compile time
- * by gcc and cast back to integers. Thus we don't violate the
- * "no float in kernel" rule.
+#define TUNER_PARAM_ANALOG 0 /* to be removed */
+/* FIXME:
+ * Right now, all tuners are using the first tuner_params[] array element
+ * for analog mode. In the future, we will be merging similar tuner
+ * definitions together, such that each tuner definition will have a
+ * tuner_params struct for each available video standard. At that point,
+ * TUNER_PARAM_ANALOG will be removed, and the tuner_params[] array
+ * element will be chosen based on the video standard in use.
+ *
*/
-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,
- 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
- { "Philips NTSC (FI1236,FM1236 and compatibles)", Philips, NTSC,
- 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,
- 16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
- { "Temic NTSC (4032 FY5)", TEMIC, NTSC,
- 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},
-
- /* 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,
- 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
- { "Temic PAL_DK (4016 FY5)", TEMIC, PAL,
- 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
- { "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,
- 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
- { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL,
- 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,
- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
- { "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I,
- 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 */
- 16*169,16*464,0xA0,0x90,0x30,0x8e,623},
- { "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,
- 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623},
- { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL,
- 16*158.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
- { "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,
- 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,
- 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,
- /* see tda8290.c for details */ },
- { "TCL 2002MB", TCL, 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,
- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
- { "Ymec TVision TVF-8531MF/8831MF/8731MF", Philips, NTSC,
- 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
- { "Ymec TVision TVF-5533MF", Philips, NTSC,
- 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
-
- /* 60-69 */
- { "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,
- 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623},
- { "Philips TEA5767HN FM Radio", Philips, RADIO,
- /* 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, 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 },
- { "Philips TD1316 Hybrid Tuner", Philips, PAL,
- 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 },
- { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC,
- 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 },
- { "Tena TNF 5335 MF", Philips, NTSC,
- 16*157.25,16*454.00,0x01,0x02,0x04,0x8e,732 },
-};
-
-unsigned const int tuner_count = ARRAY_SIZE(tuners);
/* ---------------------------------------------------------------------- */
@@ -304,21 +136,27 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
u8 config, tuneraddr;
u16 div;
struct tunertype *tun;
- unsigned char buffer[4];
- int rc;
+ u8 buffer[4];
+ int rc, IFPCoff, i, j;
tun = &tuners[t->type];
- if (freq < tun->thresh1) {
- config = tun->VHF_L;
- tuner_dbg("tv: VHF lowrange\n");
- } else if (freq < tun->thresh2) {
- config = tun->VHF_H;
- tuner_dbg("tv: VHF high range\n");
- } else {
- config = tun->UHF;
- tuner_dbg("tv: UHF range\n");
- }
+ j = TUNER_PARAM_ANALOG;
+ for (i = 0; i < tun->params[j].count; i++) {
+ if (freq > tun->params[j].ranges[i].limit)
+ continue;
+ break;
+ }
+ if (i == tun->params[j].count) {
+ tuner_dbg("TV frequency out of range (%d > %d)",
+ freq, tun->params[j].ranges[i - 1].limit);
+ freq = tun->params[j].ranges[--i].limit;
+ }
+ config = tun->params[j].ranges[i].cb;
+ /* i == 0 -> VHF_LO */
+ /* i == 1 -> VHF_HI */
+ /* i == 2 -> UHF */
+ tuner_dbg("tv: range %d\n",i);
/* tv norm specific stuff for multi-norm tuners */
switch (t->type) {
@@ -377,7 +215,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
case TUNER_MICROTUNE_4042FI5:
/* Set the charge pump for fast tuning */
- tun->config |= TUNER_CHARGE_PUMP;
+ tun->params[j].config |= TUNER_CHARGE_PUMP;
break;
case TUNER_PHILIPS_TUV1236D:
@@ -406,32 +244,49 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
break;
}
- /*
- * Philips FI1216MK2 remark from specification :
- * for channel selection involving band switching, and to ensure
- * smooth tuning to the desired channel without causing
- * unnecessary charge pump action, it is recommended to consider
- * the difference between wanted channel frequency and the
- * current channel frequency. Unnecessary charge pump action
- * will result in very low tuning voltage which may drive the
- * oscillator to extreme conditions.
- *
- * Progfou: specification says to send config data before
- * frequency in case (wanted frequency < current frequency).
- */
-
- div=freq + tun->IFPCoff;
- if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
- buffer[0] = tun->config;
+ /* IFPCoff = Video Intermediate Frequency - Vif:
+ 940 =16*58.75 NTSC/J (Japan)
+ 732 =16*45.75 M/N STD
+ 704 =16*44 ATSC (at DVB code)
+ 632 =16*39.50 I U.K.
+ 622.4=16*38.90 B/G D/K I, L STD
+ 592 =16*37.00 D China
+ 590 =16.36.875 B Australia
+ 543.2=16*33.95 L' STD
+ 171.2=16*10.70 FM Radio (at set_radio_freq)
+ */
+
+ if (t->std == V4L2_STD_NTSC_M_JP) {
+ IFPCoff = 940;
+ } else if ((t->std & V4L2_STD_MN) &&
+ !(t->std & ~V4L2_STD_MN)) {
+ IFPCoff = 732;
+ } else if (t->std == V4L2_STD_SECAM_LC) {
+ IFPCoff = 543;
+ } else {
+ IFPCoff = 623;
+ }
+
+ div=freq + IFPCoff + offset;
+
+ tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
+ freq / 16, freq % 16 * 100 / 16,
+ IFPCoff / 16, IFPCoff % 16 * 100 / 16,
+ offset / 16, offset % 16 * 100 / 16,
+ div);
+
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = tun->params[j].config;
buffer[1] = config;
buffer[2] = (div>>8) & 0x7f;
buffer[3] = div & 0xff;
} else {
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
- buffer[2] = tun->config;
+ buffer[2] = tun->params[j].config;
buffer[3] = config;
}
+ t->last_div = div;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -457,10 +312,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
}
/* Set the charge pump for optimized phase noise figure */
- tun->config &= ~TUNER_CHARGE_PUMP;
+ tun->params[j].config &= ~TUNER_CHARGE_PUMP;
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
- buffer[2] = tun->config;
+ buffer[2] = tun->params[j].config;
buffer[3] = config;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -474,13 +329,15 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
{
struct tunertype *tun;
struct tuner *t = i2c_get_clientdata(c);
- unsigned char buffer[4];
- unsigned div;
- int rc;
+ u8 buffer[4];
+ u16 div;
+ int rc, j;
tun = &tuners[t->type];
+ j = TUNER_PARAM_ANALOG;
+
div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */
- buffer[2] = (tun->config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
+ buffer[2] = (tun->params[j].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
switch (t->type) {
case TUNER_TENA_9533_DI:
@@ -509,9 +366,19 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
}
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = buffer[2];
+ buffer[1] = buffer[3];
+ buffer[2] = (div>>8) & 0x7f;
+ buffer[3] = div & 0xff;
+ } else {
+ buffer[0] = (div>>8) & 0x7f;
+ buffer[1] = div & 0xff;
+ }
tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
+ t->last_div = div;
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
@@ -525,10 +392,10 @@ int default_tuner_init(struct i2c_client *c)
t->type, tuners[t->type].name);
strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
- t->tv_freq = default_set_tv_freq;
- t->radio_freq = default_set_radio_freq;
+ t->set_tv_freq = default_set_tv_freq;
+ t->set_radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
- t->is_stereo = tuner_stereo;
+ t->is_stereo = tuner_stereo;
t->standby = NULL;
return 0;
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
new file mode 100644
index 000000000000..6fe781798d89
--- /dev/null
+++ b/drivers/media/video/tuner-types.c
@@ -0,0 +1,1406 @@
+/*
+ *
+ * i2c tv tuner chip device type database.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <media/tuner.h>
+#include <media/tuner-types.h>
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * The floats in the tuner struct are computed at compile time
+ * by gcc and cast back to integers. Thus we don't violate the
+ * "no float in kernel" rule.
+ *
+ * A tuner_range may be referenced by multiple tuner_params structs.
+ * There are many duplicates in here. Reusing tuner_range structs,
+ * rather than defining new ones for each tuner, will cut down on
+ * memory usage, and is preferred when possible.
+ *
+ * Each tuner_params array may contain one or more elements, one
+ * for each video standard.
+ *
+ * FIXME: Some tuner_range definitions are duplicated, and
+ * should be eliminated.
+ *
+ * FIXME: tunertype struct contains an element, has_tda988x.
+ * We must set this for all tunertypes that contain a tda988x
+ * chip, and then we can remove this setting from the various
+ * card structs.
+ */
+
+/* 0-9 */
+/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
+
+static struct tuner_range tuner_philips_pal_i_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_i_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_i_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 451.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
+
+static struct tuner_range tuner_philips_secam_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa7, },
+ { 16 * 447.25 /*MHz*/, 0x97, },
+ { 16 * 999.99 , 0x37, },
+};
+
+static struct tuner_params tuner_philips_secam_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_SECAM,
+ .ranges = tuner_philips_secam_ranges,
+ .count = ARRAY_SIZE(tuner_philips_secam_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_pal_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 447.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
+
+static struct tuner_range tuner_temic_pal_i_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x02, },
+ { 16 * 450.00 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_i_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_i_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4036fy5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_alps_tsb_1_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 385.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_alps_tsb_1_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 10-19 */
+/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_alps_tsb_1_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_1_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
+
+static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
+ { 16 * 133.25 /*MHz*/, 0x01, },
+ { 16 * 351.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_alps_tsbb5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
+
+static struct tuner_params tuner_alps_tsbe5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
+
+static struct tuner_params tuner_alps_tsbc5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4006fh5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4006fh5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
+
+static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x14, },
+ { 16 * 385.25 /*MHz*/, 0x12, },
+ { 16 * 999.99 , 0x11, },
+};
+
+static struct tuner_params tuner_alps_tshc6_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_alps_tshc6_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_pal_dk_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 456.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_pal_dk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_dk_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_ntsc_m_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_ntsc_m_ranges,
+ .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
+
+static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_40x6f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_40x6f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 20-29 */
+/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4009f_5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4039fr5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4039fr5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4046fm5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4046fm5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
+
+static struct tuner_range tuner_lg_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_dk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
+
+static struct tuner_params tuner_philips_fq1216me_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
+
+static struct tuner_params tuner_lg_pal_i_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
+
+static struct tuner_params tuner_lg_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
+ { 16 * 210.00 /*MHz*/, 0xa0, },
+ { 16 * 497.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_lg_ntsc_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_ntsc_fm_ranges,
+ .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
+
+static struct tuner_params tuner_lg_pal_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
+
+static struct tuner_params tuner_lg_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 30-39 */
+/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
+
+static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 317.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
+
+static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
+ { 16 * 169 /*MHz*/, 0xa0, },
+ { 16 * 464 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
+ .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4106fh5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_4012fy5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4012fy5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4136_fy5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4136_fy5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
+
+static struct tuner_range tuner_lg_new_tapc_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_fm1216me_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_fm1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
+
+static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 40-49 */
+/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
+
+static struct tuner_params tuner_hitachi_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x01, },
+ { 16 * 463.25 /*MHz*/, 0xc2, },
+ { 16 * 999.99 , 0xcf, },
+};
+
+static struct tuner_params tuner_philips_pal_mk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_mk_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */
+
+static struct tuner_range tuner_philips_atsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_atsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_atsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_atsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_fm1236_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_fm1236_mk3_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_4in1_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_4in1_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
+
+static struct tuner_params tuner_microtune_4049_fm5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
+
+static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_panasonic_vp27_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_panasonic_vp27_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_ntsc_tape_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_lg_ntsc_tape_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_ntsc_tape_ranges,
+ .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
+
+static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
+ { 16 * 161.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_tnf_8831bgff_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tnf_8831bgff_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
+
+static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
+ { 16 * 162.00 /*MHz*/, 0xa2, },
+ { 16 * 457.00 /*MHz*/, 0x94, },
+ { 16 * 999.99 , 0x31, },
+};
+
+static struct tuner_params tuner_microtune_4042fi5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_microtune_4042fi5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 50-59 */
+/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
+
+static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
+ { 16 * 172.00 /*MHz*/, 0x01, },
+ { 16 * 448.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_tcl_2002n_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tcl_2002n_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fm1256_ih3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
+
+static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x39, },
+ { 16 * 454.00 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+};
+
+static struct tuner_params tuner_thomson_dtt7610_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x41, },
+ { 16 * 454.00 /*MHz*/, 0x42, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fq1286_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_fq1286_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
+
+static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_tcl_2002mb_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tcl_2002mb_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fq12_6a___mk4_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
+
+static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_fq12_6a___mk4_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 60-69 */
+/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
+/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+
+static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
+ { 16 * 145.25 /*MHz*/, 0x39, },
+ { 16 * 415.25 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+};
+
+
+static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_thomson_dtt761x_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
+
+static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_tena_9533_di_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tuner_tena_9533_di_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x51, },
+ { 16 * 442.00 /*MHz*/, 0x52, },
+ { 16 * 999.99 , 0x54, },
+};
+
+
+static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
+ .config = 0x86,
+ },
+};
+
+
+/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
+
+static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01 },
+ { 16 * 455.00 /*MHz*/, 0x02 },
+ { 16 * 999.99 , 0x04 },
+};
+
+
+static struct tuner_params tuner_tua6034_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tua6034_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
+
+static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 373.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_lg_taln_mini_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_taln_mini_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa1, },
+ { 16 * 442.00 /*MHz*/, 0xa2, },
+ { 16 * 999.99 , 0xa4, },
+};
+
+static struct tuner_params tuner_philips_td1316_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_td1316_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
+ .config = 0xc8,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
+
+static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+
+static struct tuner_params tuner_tuner_tuv1236d_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tuv1236d_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_tnf_5335mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tnf_5335mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 70-79 */
+/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+
+static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
+ { 16 * 175.75 /*MHz*/, 0x01, },
+ { 16 * 410.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* --------------------------------------------------------------------- */
+
+struct tunertype tuners[] = {
+ /* 0-9 */
+ [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL (4002 FH5)",
+ .params = tuner_temic_pal_params,
+ },
+ [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
+ .name = "Philips PAL_I (FI1246 and compatibles)",
+ .params = tuner_philips_pal_i_params,
+ },
+ [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
+ .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
+ .params = tuner_philips_ntsc_params,
+ },
+ [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
+ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
+ .params = tuner_philips_secam_params,
+ },
+ [TUNER_ABSENT] = { /* Tuner Absent */
+ .name = "NoTuner",
+ },
+ [TUNER_PHILIPS_PAL] = { /* Philips PAL */
+ .name = "Philips PAL_BG (FI1216 and compatibles)",
+ .params = tuner_philips_pal_params,
+ },
+ [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4032 FY5)",
+ .params = tuner_temic_ntsc_params,
+ },
+ [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4062 FY5)",
+ .params = tuner_temic_pal_i_params,
+ },
+ [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4036 FY5)",
+ .params = tuner_temic_4036fy5_ntsc_params,
+ },
+ [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
+ .name = "Alps HSBH1",
+ .params = tuner_alps_tsbh1_ntsc_params,
+ },
+
+ /* 10-19 */
+ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
+ .name = "Alps TSBE1",
+ .params = tuner_alps_tsb_1_params,
+ },
+ [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
+ .name = "Alps TSBB5",
+ .params = tuner_alps_tsbb5_params,
+ },
+ [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBE5",
+ .params = tuner_alps_tsbe5_params,
+ },
+ [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBC5",
+ .params = tuner_alps_tsbc5_params,
+ },
+ [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4006FH5)",
+ .params = tuner_temic_4006fh5_params,
+ },
+ [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
+ .name = "Alps TSCH6",
+ .params = tuner_alps_tshc6_params,
+ },
+ [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK (4016 FY5)",
+ .params = tuner_temic_pal_dk_params,
+ },
+ [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
+ .name = "Philips NTSC_M (MK2)",
+ .params = tuner_philips_ntsc_m_params,
+ },
+ [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4066 FY5)",
+ .params = tuner_temic_4066fy5_pal_i_params,
+ },
+ [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto (4006 FN5)",
+ .params = tuner_temic_4006fn5_multi_params,
+ },
+
+ /* 20-29 */
+ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
+ .params = tuner_temic_4009f_5_params,
+ },
+ [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4039 FR5)",
+ .params = tuner_temic_4039fr5_params,
+ },
+ [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
+ .name = "Temic PAL/SECAM multi (4046 FM5)",
+ .params = tuner_temic_4046fm5_params,
+ },
+ [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
+ .name = "Philips PAL_DK (FI1256 and compatibles)",
+ .params = tuner_philips_pal_dk_params,
+ },
+ [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216ME)",
+ .params = tuner_philips_fq1216me_params,
+ },
+ [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I+FM (TAPC-I001D)",
+ .params = tuner_lg_pal_i_fm_params,
+ },
+ [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I (TAPC-I701D)",
+ .params = tuner_lg_pal_i_params,
+ },
+ [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC+FM (TPI8NSR01F)",
+ .params = tuner_lg_ntsc_fm_params,
+ },
+ [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG+FM (TPI8PSB01D)",
+ .params = tuner_lg_pal_fm_params,
+ },
+ [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG (TPI8PSB11D)",
+ .params = tuner_lg_pal_params,
+ },
+
+ /* 30-39 */
+ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto + FM (4009 FN5)",
+ .params = tuner_temic_4009_fn5_multi_pal_fm_params,
+ },
+ [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
+ .name = "SHARP NTSC_JP (2U5JF5540)",
+ .params = tuner_sharp_2u5jf5540_params,
+ },
+ [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
+ .name = "Samsung PAL TCPM9091PD27",
+ .params = tuner_samsung_pal_tcpm9091pd27_params,
+ },
+ [TUNER_MT2032] = { /* Microtune PAL|NTSC */
+ .name = "MT20xx universal",
+ /* see mt20xx.c for details */ },
+ [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4106 FH5)",
+ .params = tuner_temic_4106fh5_params,
+ },
+ [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
+ .params = tuner_temic_4012fy5_params,
+ },
+ [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4136 FY5)",
+ .params = tuner_temic_4136_fy5_params,
+ },
+ [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
+ .name = "LG PAL (newer TAPC series)",
+ .params = tuner_lg_pal_new_tapc_params,
+ },
+ [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
+ .params = tuner_fm1216me_mk3_params,
+ },
+ [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (newer TAPC series)",
+ .params = tuner_lg_ntsc_new_tapc_params,
+ },
+
+ /* 40-49 */
+ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
+ .name = "HITACHI V7-J180AT",
+ .params = tuner_hitachi_ntsc_params,
+ },
+ [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
+ .name = "Philips PAL_MK (FI1216 MK)",
+ .params = tuner_philips_pal_mk_params,
+ },
+ [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
+ .name = "Philips 1236D ATSC/NTSC dual in",
+ .params = tuner_philips_atsc_params,
+ },
+ [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+ .params = tuner_fm1236_mk3_params,
+ },
+ [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
+ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
+ .params = tuner_philips_4in1_params,
+ },
+ [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
+ .name = "Microtune 4049 FM5",
+ .params = tuner_microtune_4049_fm5_params,
+ },
+ [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
+ .name = "Panasonic VP27s/ENGE4324D",
+ .params = tuner_panasonic_vp27_params,
+ },
+ [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TAPE series)",
+ .params = tuner_lg_ntsc_tape_params,
+ },
+ [TUNER_TNF_8831BGFF] = { /* Philips PAL */
+ .name = "Tenna TNF 8831 BGFF)",
+ .params = tuner_tnf_8831bgff_params,
+ },
+ [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
+ .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
+ .params = tuner_microtune_4042fi5_params,
+ },
+
+ /* 50-59 */
+ [TUNER_TCL_2002N] = { /* TCL NTSC */
+ .name = "TCL 2002N",
+ .params = tuner_tcl_2002n_params,
+ },
+ [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
+ .params = tuner_philips_fm1256_ih3_params,
+ },
+ [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
+ .name = "Thomson DTT 7610 (ATSC/NTSC)",
+ .params = tuner_thomson_dtt7610_params,
+ },
+ [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+ .name = "Philips FQ1286",
+ .params = tuner_philips_fq1286_params,
+ },
+ [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
+ .name = "tda8290+75",
+ /* see tda8290.c for details */ },
+ [TUNER_TCL_2002MB] = { /* TCL PAL */
+ .name = "TCL 2002MB",
+ .params = tuner_tcl_2002mb_params,
+ },
+ [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
+ .params = tuner_philips_fq1216ame_mk4_params,
+ },
+ [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
+ .name = "Philips FQ1236A MK4",
+ .params = tuner_philips_fq1236a_mk4_params,
+ },
+ [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
+ .params = tuner_ymec_tvf_8531mf_params,
+ },
+ [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-5533MF",
+ .params = tuner_ymec_tvf_5533mf_params,
+ },
+
+ /* 60-69 */
+ [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson DTT 761X (ATSC/NTSC)",
+ .params = tuner_thomson_dtt761x_params,
+ },
+ [TUNER_TENA_9533_DI] = { /* Philips PAL */
+ .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
+ .params = tuner_tena_9533_di_params,
+ },
+ [TUNER_TEA5767] = { /* Philips RADIO */
+ .name = "Philips TEA5767HN FM Radio",
+ /* see tea5767.c for details */
+ },
+ [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips FMD1216ME MK3 Hybrid Tuner",
+ .params = tuner_tuner_philips_fmd1216me_mk3_params,
+ },
+ [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
+ .name = "LG TDVS-H062F/TUA6034",
+ .params = tuner_tua6034_params,
+ },
+ [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+ .name = "Ymec TVF66T5-B/DFF",
+ .params = tuner_ymec_tvf66t5_b_dff_params,
+ },
+ [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TALN mini series)",
+ .params = tuner_lg_taln_mini_params,
+ },
+ [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
+ .name = "Philips TD1316 Hybrid Tuner",
+ .params = tuner_philips_td1316_params,
+ },
+ [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+ .name = "Philips TUV1236D ATSC/NTSC dual in",
+ .params = tuner_tuner_tuv1236d_params,
+ },
+ [TUNER_TNF_5335MF] = { /* Philips NTSC */
+ .name = "Tena TNF 5335 MF",
+ .params = tuner_tnf_5335mf_params,
+ },
+
+ /* 70-79 */
+ [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
+ .name = "Samsung TCPN 2121P30A",
+ .params = tuner_samsung_tcpn_2121p30a_params,
+ },
+};
+
+unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 0292c5abf14a..6d03b9b05c6e 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -31,6 +31,7 @@
#include <linux/smp_lock.h>
#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#include "tvaudio.h"
@@ -46,17 +47,6 @@ MODULE_LICENSE("GPL");
#define UNSET (-1U)
-#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 */
@@ -131,7 +121,7 @@ struct CHIPSTATE {
/* current settings */
__u16 left,right,treble,bass,mode;
int prevmode;
- int norm;
+ int radio;
/* thread */
pid_t tpid;
@@ -142,8 +132,6 @@ struct CHIPSTATE {
int watch_stereo;
};
-#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
-
/* ---------------------------------------------------------------------- */
/* i2c addresses */
@@ -171,23 +159,23 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
unsigned char buffer[2];
if (-1 == subaddr) {
- tvaudio_dbg("%s: chip_write: 0x%x\n",
+ v4l_dbg(1, debug, &chip->c, "%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)) {
- tvaudio_warn("%s: I/O error (write 0x%x)\n",
+ v4l_warn(&chip->c, "%s: I/O error (write 0x%x)\n",
chip->c.name, val);
return -1;
}
} else {
- tvaudio_dbg("%s: chip_write: reg%d=0x%x\n",
+ v4l_dbg(1, debug, &chip->c, "%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)) {
- tvaudio_warn("%s: I/O error (write reg%d=0x%x)\n",
+ v4l_warn(&chip->c, "%s: I/O error (write reg%d=0x%x)\n",
chip->c.name, subaddr, val);
return -1;
}
@@ -212,11 +200,11 @@ static int chip_read(struct CHIPSTATE *chip)
unsigned char buffer;
if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
- tvaudio_warn("%s: I/O error (read)\n",
+ v4l_warn(&chip->c, "%s: I/O error (read)\n",
chip->c.name);
return -1;
}
- tvaudio_dbg("%s: chip_read: 0x%x\n",chip->c.name, buffer);
+ v4l_dbg(1, debug, &chip->c, "%s: chip_read: 0x%x\n",chip->c.name, buffer);
return buffer;
}
@@ -231,10 +219,10 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr)
write[0] = subaddr;
if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
- tvaudio_warn("%s: I/O error (read2)\n", chip->c.name);
+ v4l_warn(&chip->c, "%s: I/O error (read2)\n", chip->c.name);
return -1;
}
- tvaudio_dbg("%s: chip_read2: reg%d=0x%x\n",
+ v4l_dbg(1, debug, &chip->c, "%s: chip_read2: reg%d=0x%x\n",
chip->c.name, subaddr,read[0]);
return read[0];
}
@@ -247,7 +235,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
return 0;
/* update our shadow register set; print bytes if (debug > 0) */
- tvaudio_dbg("%s: chip_cmd(%s): reg=%d, data:",
+ v4l_dbg(1, debug, &chip->c, "%s: chip_cmd(%s): reg=%d, data:",
chip->c.name, name,cmd->bytes[0]);
for (i = 1; i < cmd->count; i++) {
if (debug)
@@ -259,7 +247,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
/* send data to the chip */
if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) {
- tvaudio_warn("%s: I/O error (%s)\n", chip->c.name, name);
+ v4l_warn(&chip->c, "%s: I/O error (%s)\n", chip->c.name, name);
return -1;
}
return 0;
@@ -286,7 +274,7 @@ static int chip_thread(void *data)
daemonize("%s", chip->c.name);
allow_signal(SIGTERM);
- tvaudio_dbg("%s: thread started\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
for (;;) {
add_wait_queue(&chip->wq, &wait);
@@ -298,10 +286,10 @@ static int chip_thread(void *data)
try_to_freeze();
if (chip->done || signal_pending(current))
break;
- tvaudio_dbg("%s: thread wakeup\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%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)
+ if (chip->radio || chip->mode != 0)
continue;
/* have a look what's going on */
@@ -311,7 +299,7 @@ static int chip_thread(void *data)
mod_timer(&chip->wt, jiffies+2*HZ);
}
- tvaudio_dbg("%s: thread exiting\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%s: thread exiting\n", chip->c.name);
complete_and_exit(&chip->texit, 0);
return 0;
}
@@ -324,7 +312,7 @@ static void generic_checkmode(struct CHIPSTATE *chip)
if (mode == chip->prevmode)
return;
- tvaudio_dbg("%s: thread checkmode\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%s: thread checkmode\n", chip->c.name);
chip->prevmode = mode;
if (mode & VIDEO_SOUND_STEREO)
@@ -371,7 +359,7 @@ static int tda9840_getmode(struct CHIPSTATE *chip)
if (val & TDA9840_ST_STEREO)
mode |= VIDEO_SOUND_STEREO;
- tvaudio_dbg ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+ v4l_dbg(1, debug, &chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n",
val, mode);
return mode;
}
@@ -667,7 +655,7 @@ static int tda9873_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_STEREO;
if (val & TDA9873_DUAL)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
- tvaudio_dbg ("tda9873_getmode(): raw chip read: %d, return: %d\n",
+ v4l_dbg(1, debug, &chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n",
val, mode);
return mode;
}
@@ -678,12 +666,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) {
- tvaudio_dbg("tda9873_setmode(): external input\n");
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): external input\n");
return;
}
- 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);
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data);
switch (mode) {
case VIDEO_SOUND_MONO:
@@ -704,7 +692,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
}
chip_write(chip, TDA9873_SW, sw_data);
- tvaudio_dbg("tda9873_setmode(): req. mode %d; chip_write: %d\n",
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): req. mode %d; chip_write: %d\n",
mode, sw_data);
}
@@ -843,7 +831,7 @@ static int tda9874a_setup(struct CHIPSTATE *chip)
chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
}
- tvaudio_dbg("tda9874a_setup(): %s [0x%02X].\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_setup(): %s [0x%02X].\n",
tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
return 1;
}
@@ -886,7 +874,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
- tvaudio_dbg("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
dsr, nsr, necr, mode);
return mode;
}
@@ -932,7 +920,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_AOSR, aosr);
chip_write(chip, TDA9874A_MDACOSR, mdacosr);
- tvaudio_dbg("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
mode, aosr, mdacosr);
} else { /* dic == 0x07 */
@@ -967,7 +955,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_FMMR, fmmr);
chip_write(chip, TDA9874A_AOSR, aosr);
- tvaudio_dbg("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
mode, fmmr, aosr);
}
}
@@ -981,10 +969,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
return 0;
- tvaudio_dbg("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+ v4l_dbg(1, debug, &chip->c, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
if((dic == 0x11)||(dic == 0x07)) {
- tvaudio_info("found tda9874%s.\n", (dic == 0x11) ? "a":"h");
+ v4l_info(&chip->c, "found tda9874%s.\n", (dic == 0x11) ? "a":"h");
tda9874a_dic = dic; /* remember device id. */
return 1;
}
@@ -1196,7 +1184,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip)
}else if (!(val & TA8874Z_B0)){
mode |= VIDEO_SOUND_STEREO;
}
- /* tvaudio_dbg ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
+ /* v4l_dbg(1, debug, &chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
return mode;
}
@@ -1209,7 +1197,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode)
{
int update = 1;
audiocmd *t = NULL;
- tvaudio_dbg("ta8874z_setmode(): mode: 0x%02x\n", mode);
+ v4l_dbg(1, debug, &chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode);
switch(mode){
case VIDEO_SOUND_MONO:
@@ -1480,17 +1468,16 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
struct CHIPSTATE *chip;
struct CHIPDESC *desc;
- chip = kmalloc(sizeof(*chip),GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip),GFP_KERNEL);
if (!chip)
return -ENOMEM;
- memset(chip,0,sizeof(*chip));
memcpy(&chip->c,&client_template,sizeof(struct i2c_client));
chip->c.adapter = adap;
chip->c.addr = addr;
i2c_set_clientdata(&chip->c, chip);
/* find description for the chip */
- tvaudio_dbg("chip found @ 0x%x\n", addr<<1);
+ v4l_dbg(1, debug, &chip->c, "chip found @ 0x%x\n", addr<<1);
for (desc = chiplist; desc->name != NULL; desc++) {
if (0 == *(desc->insmodopt))
continue;
@@ -1502,12 +1489,12 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
break;
}
if (desc->name == NULL) {
- tvaudio_dbg("no matching chip description found\n");
+ v4l_dbg(1, debug, &chip->c, "no matching chip description found\n");
return -EIO;
}
- tvaudio_info("%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
+ v4l_info(&chip->c, "%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
if (desc->flags) {
- tvaudio_dbg("matches:%s%s%s.\n",
+ v4l_dbg(1, debug, &chip->c, "matches:%s%s%s.\n",
(desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
(desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
@@ -1550,7 +1537,7 @@ 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)
- tvaudio_warn("%s: kernel_thread() failed\n",
+ v4l_warn(&chip->c, "%s: kernel_thread() failed\n",
chip->c.name);
wake_up_interruptible(&chip->wq);
}
@@ -1563,17 +1550,8 @@ static int chip_probe(struct i2c_adapter *adap)
because dedicated drivers are used */
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_HW_B_BT848:
- case I2C_HW_B_RIVA:
- case I2C_HW_SAA7134:
- return i2c_probe(adap, &addr_data, chip_attach);
- }
-#endif
return 0;
}
@@ -1604,7 +1582,7 @@ static int chip_command(struct i2c_client *client,
struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type;
- tvaudio_dbg("%s: chip_command 0x%x\n", chip->c.name, cmd);
+ v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd);
switch (cmd) {
case AUDC_SET_INPUT:
@@ -1617,7 +1595,7 @@ static int chip_command(struct i2c_client *client,
break;
case AUDC_SET_RADIO:
- chip->norm = VIDEO_MODE_RADIO;
+ chip->radio = 1;
chip->watch_stereo = 0;
/* del_timer(&chip->wt); */
break;
@@ -1643,7 +1621,7 @@ static int chip_command(struct i2c_client *client,
va->bass = chip->bass;
va->treble = chip->treble;
}
- if (chip->norm != VIDEO_MODE_RADIO) {
+ if (!chip->radio) {
if (desc->getmode)
va->mode = desc->getmode(chip);
else
@@ -1678,15 +1656,80 @@ static int chip_command(struct i2c_client *client,
}
break;
}
- case VIDIOCSCHAN:
+
+ case VIDIOC_S_TUNER:
{
- struct video_channel *vc = arg;
+ struct v4l2_tuner *vt = arg;
+ int mode = 0;
- chip->norm = vc->norm;
+ switch (vt->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ mode = VIDEO_SOUND_MONO;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ mode = VIDEO_SOUND_STEREO;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ mode = VIDEO_SOUND_LANG1;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ mode = VIDEO_SOUND_LANG2;
+ break;
+ default:
+ break;
+ }
+
+ if (desc->setmode && mode) {
+ chip->watch_stereo = 0;
+ /* del_timer(&chip->wt); */
+ chip->mode = mode;
+ desc->setmode(chip, mode);
+ }
break;
}
- case VIDIOCSFREQ:
+
+ case VIDIOC_G_TUNER:
{
+ struct v4l2_tuner *vt = arg;
+ int mode = VIDEO_SOUND_MONO;
+
+ if (chip->radio)
+ break;
+ vt->audmode = 0;
+ vt->rxsubchans = 0;
+ vt->capability = V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+
+ if (desc->getmode)
+ mode = desc->getmode(chip);
+
+ if (mode & VIDEO_SOUND_MONO)
+ vt->rxsubchans |= V4L2_TUNER_SUB_MONO;
+ if (mode & VIDEO_SOUND_STEREO)
+ vt->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ if (mode & VIDEO_SOUND_LANG1)
+ vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ mode = chip->mode;
+ if (mode & VIDEO_SOUND_MONO)
+ vt->audmode = V4L2_TUNER_MODE_MONO;
+ if (mode & VIDEO_SOUND_STEREO)
+ vt->audmode = V4L2_TUNER_MODE_STEREO;
+ if (mode & VIDEO_SOUND_LANG1)
+ vt->audmode = V4L2_TUNER_MODE_LANG1;
+ if (mode & VIDEO_SOUND_LANG2)
+ vt->audmode = V4L2_TUNER_MODE_LANG2;
+ break;
+ }
+
+ case VIDIOCSCHAN:
+ case VIDIOC_S_STD:
+ chip->radio = 0;
+ break;
+
+ case VIDIOCSFREQ:
+ case VIDIOC_S_FREQUENCY:
chip->mode = 0; /* automatic */
if (desc->checkmode) {
desc->setmode(chip,VIDEO_SOUND_MONO);
@@ -1695,15 +1738,14 @@ static int chip_command(struct i2c_client *client,
mod_timer(&chip->wt, jiffies+2*HZ);
/* the thread will call checkmode() later */
}
- }
+ break;
}
return 0;
}
-
static struct i2c_driver driver = {
.driver = {
- .name = "generic i2c audio driver",
+ .name = "tvaudio",
},
.id = I2C_DRIVERID_TVAUDIO,
.attach_adapter = chip_probe,
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 8ac4cb82a459..582551b0969b 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -40,6 +40,7 @@
#include <media/tuner.h>
#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
#include <media/audiochip.h>
MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
@@ -52,21 +53,19 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown")
-#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 {\
+#define tveeprom_info(fmt, arg...) \
+ v4l_printk(KERN_INFO, "tveeprom", c->adapter, c->addr, fmt , ## arg)
+#define tveeprom_warn(fmt, arg...) \
+ v4l_printk(KERN_WARNING, "tveeprom", c->adapter, c->addr, fmt , ## arg)
+#define tveeprom_dbg(fmt, arg...) do { \
if (debug) \
- printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
- c->adapter->nr, c->addr , ##arg); } while (0)
-
-
-/* ----------------------------------------------------------------------- */
-/* some hauppauge specific stuff */
+ v4l_printk(KERN_DEBUG, "tveeprom", c->adapter, c->addr, fmt , ## arg); \
+ } while (0)
+/*
+ * The Hauppauge eeprom uses an 8bit field to determine which
+ * tuner formats the tuner supports.
+ */
static struct HAUPPAUGE_TUNER_FMT
{
int id;
@@ -74,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/DVB Digital" },
+ { V4L2_STD_UNKNOWN," UNKNOWN" },
+ { V4L2_STD_UNKNOWN," FM" },
+ { V4L2_STD_PAL_BG, " PAL(B/G)" },
+ { V4L2_STD_NTSC_M, " NTSC(M)" },
+ { V4L2_STD_PAL_I, " PAL(I)" },
+ { V4L2_STD_SECAM_L," SECAM(L/L')" },
+ { V4L2_STD_PAL_DK, " PAL(D/D1/K)" },
+ { V4L2_STD_ATSC, " ATSC/DVB Digital" },
};
/* This is the full list of possible tuners. Many thanks to Hauppauge for
@@ -191,7 +190,7 @@ hauppauge_tuner[] =
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
{ TUNER_TCL_2002N, "TCL 2002N 6A"},
{ TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"},
- { TUNER_ABSENT, "Samsung TCPN 2121P30A"},
+ { TUNER_SAMSUNG_TCPN_2121P30A, "Samsung TCPN 2121P30A"},
{ TUNER_ABSENT, "Samsung TCPE 4121P30A"},
{ TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
/* 90-99 */
@@ -387,7 +386,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
if ((eeprom_data[0] == 0x1a) && (eeprom_data[1] == 0xeb) &&
(eeprom_data[2] == 0x67) && (eeprom_data[3] == 0x95))
start=0xa0; /* Generic em28xx offset */
- else if (((eeprom_data[0] & 0xf0) == 0x10) &&
+ else if (((eeprom_data[0] & 0xe1) == 0x01) &&
(eeprom_data[1] == 0x00) &&
(eeprom_data[2] == 0x00) &&
(eeprom_data[8] == 0x84))
@@ -720,8 +719,7 @@ tveeprom_command(struct i2c_client *client,
switch (cmd) {
case 0:
- buf = kmalloc(256,GFP_KERNEL);
- memset(buf,0,256);
+ buf = kzalloc(256,GFP_KERNEL);
tveeprom_read(client,buf,256);
tveeprom_hauppauge_analog(client, &eeprom,buf);
kfree(buf);
@@ -744,10 +742,9 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
{
struct i2c_client *client;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (NULL == client)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_tveeprom;
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index e837f9f7fed6..9e86caeb96a7 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -227,13 +227,9 @@ static int tvmixer_release(struct inode *inode, struct file *file)
}
static struct i2c_driver driver = {
-#ifdef I2C_PEC
.driver = {
- .name = "tv card mixer driver",
+ .name = "tvmixer",
},
-#else
- .name = "tv card mixer driver",
-#endif
.id = I2C_DRIVERID_TVMIXER,
.detach_adapter = tvmixer_adapters,
.attach_adapter = tvmixer_adapters,
@@ -267,22 +263,8 @@ static int tvmixer_clients(struct i2c_client *client)
struct video_audio va;
int i,minor;
-#ifdef I2C_CLASS_TV_ANALOG
if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
return -1;
-#else
- /* TV card ??? */
- switch (client->adapter->id) {
- case I2C_HW_SMBUS_VOODOO3:
- case I2C_HW_B_BT848:
- case I2C_HW_B_RIVA:
- /* ok, have a look ... */
- break;
- default:
- /* ignore that one */
- return -1;
- }
-#endif
/* unregister ?? */
for (i = 0; i < DEV_MAX; i++) {
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index a60442ea4f94..fad9ea0ae4f2 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -9,6 +9,7 @@
#include <linux/videodev.h>
#include <linux/delay.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
#include "tvp5150_reg.h"
@@ -28,33 +29,38 @@ static int debug = 0;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
+#define tvp5150_info(fmt, arg...) do { \
+ printk(KERN_INFO "%s %d-%04x: " fmt, c->driver->driver.name, \
+ i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0)
+#define tvp5150_dbg(num, fmt, arg...) \
do { \
if (debug >= num) \
- printk(format, ##args); \
- } while (0)
+ printk(KERN_DEBUG "%s debug %d-%04x: " fmt,\
+ c->driver->driver.name, \
+ i2c_adapter_id(c->adapter), \
+ c->addr , ## arg); } while (0)
/* supported controls */
static struct v4l2_queryctrl tvp5150_qctrl[] = {
{
- .id = V4L2_CID_BRIGHTNESS,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 255,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- }, {
- .id = V4L2_CID_CONTRAST,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 255,
- .step = 0x1,
- .default_value = 0x10,
- .flags = 0,
- }, {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 0x1,
+ .default_value = 0x10,
+ .flags = 0,
+ }, {
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Saturation",
@@ -63,16 +69,16 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.step = 0x1,
.default_value = 0x10,
.flags = 0,
- }, {
- .id = V4L2_CID_HUE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Hue",
- .minimum = -128,
- .maximum = 127,
- .step = 0x1,
- .default_value = 0x10,
- .flags = 0,
- }
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 0x1,
+ .default_value = 0x10,
+ .flags = 0,
+ }
};
struct tvp5150 {
@@ -87,19 +93,21 @@ struct tvp5150 {
int sat;
};
-static inline int tvp5150_read(struct i2c_client *c, unsigned char addr)
+static int tvp5150_read(struct i2c_client *c, unsigned char addr)
{
unsigned char buffer[1];
int rc;
buffer[0] = addr;
if (1 != (rc = i2c_master_send(c, buffer, 1)))
- dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
+ tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
msleep(10);
if (1 != (rc = i2c_master_recv(c, buffer, 1)))
- dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
+ tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
+
+ tvp5150_dbg(2, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
return (buffer[0]);
}
@@ -109,13 +117,12 @@ static inline void tvp5150_write(struct i2c_client *c, unsigned char addr,
{
unsigned char buffer[2];
int rc;
-/* struct tvp5150 *core = i2c_get_clientdata(c); */
buffer[0] = addr;
buffer[1] = value;
- dprintk(1, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+ tvp5150_dbg(2, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
if (2 != (rc = i2c_master_send(c, buffer, 2)))
- dprintk(0, "i2c i/o error: rc == %d (should be 2)\n", rc);
+ tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 2)\n", rc);
}
static void dump_reg(struct i2c_client *c)
@@ -437,48 +444,346 @@ enum tvp5150_input {
static inline void tvp5150_selmux(struct i2c_client *c,
enum tvp5150_input input)
{
+ int opmode=0;
+
struct tvp5150 *decoder = i2c_get_clientdata(c);
if (!decoder->enable)
input |= TVP5150_BLACK_SCREEN;
+ switch (input) {
+ case TVP5150_ANALOG_CH0:
+ case TVP5150_ANALOG_CH1:
+ opmode=0x30; /* TV Mode */
+ break;
+ default:
+ opmode=0; /* Auto Mode */
+ break;
+ }
+
+ tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode);
tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input);
};
-static inline void tvp5150_reset(struct i2c_client *c)
+struct i2c_reg_value {
+ unsigned char reg;
+ unsigned char value;
+};
+
+/* Default values as sugested at TVP5150AM1 datasheet */
+static const struct i2c_reg_value tvp5150_init_default[] = {
+ { /* 0x00 */
+ TVP5150_VD_IN_SRC_SEL_1,0x00
+ },
+ { /* 0x01 */
+ TVP5150_ANAL_CHL_CTL,0x15
+ },
+ { /* 0x02 */
+ TVP5150_OP_MODE_CTL,0x00
+ },
+ { /* 0x03 */
+ TVP5150_MISC_CTL,0x01
+ },
+ { /* 0x06 */
+ TVP5150_COLOR_KIL_THSH_CTL,0x10
+ },
+ { /* 0x07 */
+ TVP5150_LUMA_PROC_CTL_1,0x60
+ },
+ { /* 0x08 */
+ TVP5150_LUMA_PROC_CTL_2,0x00
+ },
+ { /* 0x09 */
+ TVP5150_BRIGHT_CTL,0x80
+ },
+ { /* 0x0a */
+ TVP5150_SATURATION_CTL,0x80
+ },
+ { /* 0x0b */
+ TVP5150_HUE_CTL,0x00
+ },
+ { /* 0x0c */
+ TVP5150_CONTRAST_CTL,0x80
+ },
+ { /* 0x0d */
+ TVP5150_DATA_RATE_SEL,0x47
+ },
+ { /* 0x0e */
+ TVP5150_LUMA_PROC_CTL_3,0x00
+ },
+ { /* 0x0f */
+ TVP5150_CONF_SHARED_PIN,0x08
+ },
+ { /* 0x11 */
+ TVP5150_ACT_VD_CROP_ST_MSB,0x00
+ },
+ { /* 0x12 */
+ TVP5150_ACT_VD_CROP_ST_LSB,0x00
+ },
+ { /* 0x13 */
+ TVP5150_ACT_VD_CROP_STP_MSB,0x00
+ },
+ { /* 0x14 */
+ TVP5150_ACT_VD_CROP_STP_LSB,0x00
+ },
+ { /* 0x15 */
+ TVP5150_GENLOCK,0x01
+ },
+ { /* 0x16 */
+ TVP5150_HORIZ_SYNC_START,0x80
+ },
+ { /* 0x18 */
+ TVP5150_VERT_BLANKING_START,0x00
+ },
+ { /* 0x19 */
+ TVP5150_VERT_BLANKING_STOP,0x00
+ },
+ { /* 0x1a */
+ TVP5150_CHROMA_PROC_CTL_1,0x0c
+ },
+ { /* 0x1b */
+ TVP5150_CHROMA_PROC_CTL_2,0x14
+ },
+ { /* 0x1c */
+ TVP5150_INT_RESET_REG_B,0x00
+ },
+ { /* 0x1d */
+ TVP5150_INT_ENABLE_REG_B,0x00
+ },
+ { /* 0x1e */
+ TVP5150_INTT_CONFIG_REG_B,0x00
+ },
+ { /* 0x28 */
+ TVP5150_VIDEO_STD,0x00
+ },
+ { /* 0x2e */
+ TVP5150_MACROVISION_ON_CTR,0x0f
+ },
+ { /* 0x2f */
+ TVP5150_MACROVISION_OFF_CTR,0x01
+ },
+ { /* 0xbb */
+ TVP5150_TELETEXT_FIL_ENA,0x00
+ },
+ { /* 0xc0 */
+ TVP5150_INT_STATUS_REG_A,0x00
+ },
+ { /* 0xc1 */
+ TVP5150_INT_ENABLE_REG_A,0x00
+ },
+ { /* 0xc2 */
+ TVP5150_INT_CONF,0x04
+ },
+ { /* 0xc8 */
+ TVP5150_FIFO_INT_THRESHOLD,0x80
+ },
+ { /* 0xc9 */
+ TVP5150_FIFO_RESET,0x00
+ },
+ { /* 0xca */
+ TVP5150_LINE_NUMBER_INT,0x00
+ },
+ { /* 0xcb */
+ TVP5150_PIX_ALIGN_REG_LOW,0x4e
+ },
+ { /* 0xcc */
+ TVP5150_PIX_ALIGN_REG_HIGH,0x00
+ },
+ { /* 0xcd */
+ TVP5150_FIFO_OUT_CTRL,0x01
+ },
+ { /* 0xcf */
+ TVP5150_FULL_FIELD_ENA_1,0x00
+ },
+ { /* 0xd0 */
+ TVP5150_FULL_FIELD_ENA_2,0x00
+ },
+ { /* 0xfc */
+ TVP5150_FULL_FIELD_MODE_REG,0x7f
+ },
+ { /* end of data */
+ 0xff,0xff
+ }
+};
+
+/* Default values as sugested at TVP5150AM1 datasheet */
+static const struct i2c_reg_value tvp5150_init_enable[] = {
+ {
+ TVP5150_CONF_SHARED_PIN, 2
+ },{ /* Automatic offset and AGC enabled */
+ TVP5150_ANAL_CHL_CTL, 0x15
+ },{ /* Activate YCrCb output 0x9 or 0xd ? */
+ TVP5150_MISC_CTL, 0x6f
+ },{ /* Activates video std autodetection for all standards */
+ TVP5150_AUTOSW_MSK, 0x0
+ },{ /* Default format: 0x47. For 4:2:2: 0x40 */
+ TVP5150_DATA_RATE_SEL, 0x47
+ },{
+ TVP5150_CHROMA_PROC_CTL_1, 0x0c
+ },{
+ TVP5150_CHROMA_PROC_CTL_2, 0x54
+ },{ /* Non documented, but initialized on WinTV USB2 */
+ 0x27, 0x20
+ },{
+ 0xff,0xff
+ }
+};
+
+struct i2c_vbi_ram_value {
+ u16 reg;
+ unsigned char values[26];
+};
+
+static struct i2c_vbi_ram_value vbi_ram_default[] =
{
- struct tvp5150 *decoder = i2c_get_clientdata(c);
+ {0x010, /* WST SECAM 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x030, /* WST PAL B 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x050, /* WST PAL C 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0xa6, 0x98, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x070, /* WST NTSC 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x090, /* NABTS, NTSC 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x15, 0x0 }
+ },
+ {0x0b0, /* NABTS, NTSC-J 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xa7, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x0d0, /* CC, PAL/SECAM 6 */
+ { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 }
+ },
+ {0x0f0, /* CC, NTSC 6 */
+ { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0x69, 0x8c, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 }
+ },
+ {0x110, /* WSS, PAL/SECAM 6 */
+ { 0x5b, 0x55, 0xc5, 0xff , 0x0, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x0, 0x0, 0x0, 0x3a, 0x0 }
+ },
+ {0x130, /* WSS, NTSC C */
+ { 0x38, 0x00, 0x3f, 0x00 , 0x0, 0x71, 0x6e, 0x43, 0x69, 0x7c, 0x08, 0x0, 0x0, 0x0, 0x39, 0x0 }
+ },
+ {0x150, /* VITC, PAL/SECAM 6 */
+ { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0xa6, 0x85, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 }
+ },
+ {0x170, /* VITC, NTSC 6 */
+ { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 }
+ },
+ { (u16)-1 }
+};
- tvp5150_write(c, TVP5150_CONF_SHARED_PIN, 2);
+static int tvp5150_write_inittab(struct i2c_client *c,
+ const struct i2c_reg_value *regs)
+{
+ while (regs->reg != 0xff) {
+ tvp5150_write(c, regs->reg, regs->value);
+ regs++;
+ }
+ return 0;
+}
- /* Automatic offset and AGC enabled */
- tvp5150_write(c, TVP5150_ANAL_CHL_CTL, 0x15);
+static int tvp5150_vdp_init(struct i2c_client *c,
+ const struct i2c_vbi_ram_value *regs)
+{
+ unsigned int i;
- /* Normal Operation */
-// tvp5150_write(c, TVP5150_OP_MODE_CTL, 0x00);
+ /* Disable Full Field */
+ tvp5150_write(c, TVP5150_FULL_FIELD_ENA_1, 0);
- /* Activate YCrCb output 0x9 or 0xd ? */
- tvp5150_write(c, TVP5150_MISC_CTL, 0x6f);
+ /* Before programming, Line mode should be at 0xff */
+ for (i=TVP5150_FULL_FIELD_ENA_2; i<=TVP5150_LINE_MODE_REG_44; i++)
+ tvp5150_write(c, i, 0xff);
- /* Activates video std autodetection for all standards */
- tvp5150_write(c, TVP5150_AUTOSW_MSK, 0x0);
+ /* Load Ram Table */
+ while (regs->reg != (u16)-1 ) {
+ tvp5150_write(c, TVP5150_CONF_RAM_ADDR_HIGH,regs->reg>>8);
+ tvp5150_write(c, TVP5150_CONF_RAM_ADDR_LOW,regs->reg);
- /* Default format: 0x47, 4:2:2: 0x40 */
- tvp5150_write(c, TVP5150_DATA_RATE_SEL, 0x47);
+ for (i=0;i<16;i++)
+ tvp5150_write(c, TVP5150_VDP_CONF_RAM_DATA,regs->values[i]);
- tvp5150_selmux(c, decoder->input);
+ regs++;
+ }
+ return 0;
+}
+
+static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std)
+{
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
+ int fmt=0;
+
+ decoder->norm=std;
+
+ /* First tests should be against specific std */
+
+ if (std == V4L2_STD_ALL) {
+ fmt=0; /* Autodetect mode */
+ } else if (std & V4L2_STD_NTSC_443) {
+ fmt=0xa;
+ } else if (std & V4L2_STD_PAL_M) {
+ fmt=0x6;
+ } else if (std & (V4L2_STD_PAL_N| V4L2_STD_PAL_Nc)) {
+ fmt=0x8;
+ } else {
+ /* Then, test against generic ones */
+ if (std & V4L2_STD_NTSC) {
+ fmt=0x2;
+ } else if (std & V4L2_STD_PAL) {
+ fmt=0x4;
+ } else if (std & V4L2_STD_SECAM) {
+ fmt=0xc;
+ }
+ }
+
+ tvp5150_dbg(1,"Set video std register to %d.\n",fmt);
+ tvp5150_write(c, TVP5150_VIDEO_STD, fmt);
- tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_1, 0x0c);
- tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_2, 0x54);
+ return 0;
+}
- tvp5150_write(c, 0x27, 0x20); /* ?????????? */
+static inline void tvp5150_reset(struct i2c_client *c)
+{
+ u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom;
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
- tvp5150_write(c, TVP5150_VIDEO_STD, 0x0); /* Auto switch */
+ type=tvp5150_read(c,TVP5150_AUTOSW_MSK);
+ msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID);
+ lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID);
+ msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER);
+ lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER);
+
+ if (type==0xdc) {
+ ver_656=tvp5150_read(c,TVP5150_REV_SELECT);
+ tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656);
+ } else if (type==0xfc) {
+ tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+ } else {
+ tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type);
+ }
+ tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom);
+ /* Initializes TVP5150 to its default values */
+ tvp5150_write_inittab(c, tvp5150_init_default);
+
+ /* Initializes VDP registers */
+ tvp5150_vdp_init(c, vbi_ram_default);
+
+ /* Selects decoder input */
+ tvp5150_selmux(c, decoder->input);
+
+ /* Initializes TVP5150 to stream enabled values */
+ tvp5150_write_inittab(c, tvp5150_init_enable);
+
+ /* Initialize image preferences */
tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8);
tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8);
tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8);
tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8);
+
+ tvp5150_set_std(c, decoder->norm);
};
static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
@@ -498,9 +803,8 @@ static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
case V4L2_CID_HUE:
ctrl->value = tvp5150_read(c, TVP5150_HUE_CTL);
return 0;
- default:
- return -EINVAL;
}
+ return -EINVAL;
}
static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
@@ -520,28 +824,59 @@ static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
case V4L2_CID_HUE:
tvp5150_write(c, TVP5150_HUE_CTL, ctrl->value);
return 0;
- default:
- return -EINVAL;
}
+ return -EINVAL;
}
/****************************************************************************
I2C Command
****************************************************************************/
-static int tvp5150_command(struct i2c_client *client,
+static int tvp5150_command(struct i2c_client *c,
unsigned int cmd, void *arg)
{
- struct tvp5150 *decoder = i2c_get_clientdata(client);
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
switch (cmd) {
case 0:
+ case VIDIOC_INT_RESET:
case DECODER_INIT:
- tvp5150_reset(client);
+ tvp5150_reset(c);
+ break;
+ case VIDIOC_S_STD:
+ if (decoder->norm == *(v4l2_std_id *)arg)
+ break;
+ return tvp5150_set_std(c, *(v4l2_std_id *)arg);
+ case VIDIOC_G_STD:
+ *(v4l2_std_id *)arg = decoder->norm;
+ break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_TVP5150)
+ return -EINVAL;
+ reg->val = tvp5150_read(c, reg->reg & 0xff);
+ break;
+ }
+
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_TVP5150)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
break;
+ }
+#endif
case DECODER_DUMP:
- dump_reg(client);
+ dump_reg(c);
break;
case DECODER_GET_CAPABILITIES:
@@ -600,7 +935,7 @@ static int tvp5150_command(struct i2c_client *client,
}
decoder->input = *iarg;
- tvp5150_selmux(client, decoder->input);
+ tvp5150_selmux(c, decoder->input);
break;
}
@@ -620,19 +955,18 @@ static int tvp5150_command(struct i2c_client *client,
decoder->enable = (*iarg != 0);
- tvp5150_selmux(client, decoder->input);
+ tvp5150_selmux(c, decoder->input);
break;
}
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
- u8 i, n;
+ int i;
- dprintk(1, KERN_DEBUG "VIDIOC_QUERYCTRL");
+ tvp5150_dbg(1, "VIDIOC_QUERYCTRL called\n");
- n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]);
- for (i = 0; i < n; i++)
+ for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++)
if (qc->id && qc->id == tvp5150_qctrl[i].id) {
memcpy(qc, &(tvp5150_qctrl[i]),
sizeof(*qc));
@@ -644,16 +978,14 @@ static int tvp5150_command(struct i2c_client *client,
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
- dprintk(1, KERN_DEBUG "VIDIOC_G_CTRL");
+ tvp5150_dbg(1, "VIDIOC_G_CTRL called\n");
- return tvp5150_get_ctrl(client, ctrl);
+ return tvp5150_get_ctrl(c, ctrl);
}
- case VIDIOC_S_CTRL_OLD: /* ??? */
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
u8 i, n;
- dprintk(1, KERN_DEBUG "VIDIOC_S_CTRL");
n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]);
for (i = 0; i < n; i++)
if (ctrl->id == tvp5150_qctrl[i].id) {
@@ -662,11 +994,10 @@ static int tvp5150_command(struct i2c_client *client,
|| ctrl->value >
tvp5150_qctrl[i].maximum)
return -ERANGE;
- dprintk(1,
- KERN_DEBUG
- "VIDIOC_S_CTRL: id=%d, value=%d",
+ tvp5150_dbg(1,
+ "VIDIOC_S_CTRL: id=%d, value=%d\n",
ctrl->id, ctrl->value);
- return tvp5150_set_ctrl(client, ctrl);
+ return tvp5150_set_ctrl(c, ctrl);
}
return -EINVAL;
}
@@ -677,25 +1008,25 @@ static int tvp5150_command(struct i2c_client *client,
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */
decoder->bright = pic->brightness;
- tvp5150_write(client, TVP5150_BRIGHT_CTL,
+ tvp5150_write(c, TVP5150_BRIGHT_CTL,
decoder->bright >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 255 we get 0-65535 */
decoder->contrast = pic->contrast;
- tvp5150_write(client, TVP5150_CONTRAST_CTL,
+ tvp5150_write(c, TVP5150_CONTRAST_CTL,
decoder->contrast >> 8);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 255 we get 0-65535 */
decoder->sat = pic->colour;
- tvp5150_write(client, TVP5150_SATURATION_CTL,
+ tvp5150_write(c, TVP5150_SATURATION_CTL,
decoder->contrast >> 8);
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
- tvp5150_write(client, TVP5150_HUE_CTL,
+ tvp5150_write(c, TVP5150_HUE_CTL,
(decoder->hue - 32768) >> 8);
}
break;
@@ -720,12 +1051,12 @@ static struct i2c_client client_template = {
static int tvp5150_detect_client(struct i2c_adapter *adapter,
int address, int kind)
{
- struct i2c_client *client;
+ struct i2c_client *c;
struct tvp5150 *core;
int rv;
- dprintk(1,
- KERN_INFO
+ if (debug)
+ printk( KERN_INFO
"tvp5150.c: detecting tvp5150 client on address 0x%x\n",
address << 1);
@@ -738,22 +1069,21 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ c = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (c == 0)
return -ENOMEM;
- memcpy(client, &client_template, sizeof(struct i2c_client));
+ memcpy(c, &client_template, sizeof(struct i2c_client));
- core = kmalloc(sizeof(struct tvp5150), GFP_KERNEL);
+ core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL);
if (core == 0) {
- kfree(client);
+ kfree(c);
return -ENOMEM;
}
- memset(core, 0, sizeof(struct tvp5150));
- i2c_set_clientdata(client, core);
+ i2c_set_clientdata(c, core);
- rv = i2c_attach_client(client);
+ rv = i2c_attach_client(c);
- core->norm = VIDEO_MODE_AUTO;
+ core->norm = V4L2_STD_ALL;
core->input = 2;
core->enable = 1;
core->bright = 32768;
@@ -762,37 +1092,41 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
core->sat = 32768;
if (rv) {
- kfree(client);
+ kfree(c);
kfree(core);
return rv;
}
if (debug > 1)
- dump_reg(client);
+ dump_reg(c);
return 0;
}
static int tvp5150_attach_adapter(struct i2c_adapter *adapter)
{
- dprintk(1,
- KERN_INFO
+ if (debug)
+ printk( KERN_INFO
"tvp5150.c: starting probe for adapter %s (0x%x)\n",
adapter->name, adapter->id);
return i2c_probe(adapter, &addr_data, &tvp5150_detect_client);
}
-static int tvp5150_detach_client(struct i2c_client *client)
+static int tvp5150_detach_client(struct i2c_client *c)
{
- struct tvp5150 *decoder = i2c_get_clientdata(client);
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
int err;
- err = i2c_detach_client(client);
+ tvp5150_dbg(1,
+ "tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
+ c->addr << 1);
+
+ err = i2c_detach_client(c);
if (err) {
return err;
}
kfree(decoder);
- kfree(client);
+ kfree(c);
return 0;
}
@@ -803,9 +1137,7 @@ static struct i2c_driver driver = {
.driver = {
.name = "tvp5150",
},
-
- /* FIXME */
- .id = I2C_DRIVERID_SAA7110,
+ .id = I2C_DRIVERID_TVP5150,
.attach_adapter = tvp5150_attach_adapter,
.detach_client = tvp5150_detach_client,
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 4134549d11a8..474a29bc1760 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -305,9 +305,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct video_capability *cap = arg;
- cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
+ cap2 = kzalloc(sizeof(*cap2),GFP_KERNEL);
memset(cap, 0, sizeof(*cap));
- memset(cap2, 0, sizeof(*cap2));
memset(&fbuf2, 0, sizeof(fbuf2));
err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
@@ -422,9 +421,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct video_window *win = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
memset(win,0,sizeof(*win));
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -461,8 +459,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
struct video_window *win = arg;
int err1,err2;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -595,8 +592,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
pict->whiteness = get_v4l_control(inode, file,
V4L2_CID_WHITENESS, drv);
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
@@ -622,8 +618,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
set_v4l_control(inode, file,
V4L2_CID_WHITENESS, pict->whiteness, drv);
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0)
@@ -846,9 +841,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct video_mmap *mm = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
memset(&buf2,0,sizeof(buf2));
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -942,8 +936,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct vbi_format *fmt = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2, 0, sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -951,6 +944,10 @@ v4l_compat_translate_ioctl(struct inode *inode,
dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
break;
}
+ if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+ err = -EINVAL;
+ break;
+ }
memset(fmt, 0, sizeof(*fmt));
fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
@@ -966,8 +963,12 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct vbi_format *fmt = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2, 0, sizeof(*fmt2));
+ if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+ err = -EINVAL;
+ break;
+ }
+
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
@@ -986,7 +987,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
- VIDEO_PALETTE_RAW != fmt->sample_format ||
+ fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
fmt2->fmt.vbi.start[0] != fmt->start[0] ||
fmt2->fmt.vbi.count[0] != fmt->count[0] ||
fmt2->fmt.vbi.start[1] != fmt->start[1] ||
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 597b8db35a13..cd2c4475525e 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -58,6 +58,8 @@
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/div64.h>
+#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
@@ -190,57 +192,175 @@ char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
};
-char *v4l2_ioctl_names[256] = {
-#if __GNUC__ >= 3
- [0 ... 255] = "UNKNOWN",
+/* ------------------------------------------------------------------ */
+/* debug help functions */
+
+#ifdef HAVE_V4L1
+static const char *v4l1_ioctls[] = {
+ [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
+ [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
+ [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN",
+ [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER",
+ [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER",
+ [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT",
+ [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT",
+ [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE",
+ [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN",
+ [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN",
+ [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF",
+ [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF",
+ [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY",
+ [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ",
+ [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ",
+ [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO",
+ [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO",
+ [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC",
+ [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE",
+ [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF",
+ [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT",
+ [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE",
+ [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE",
+ [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE",
+ [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
+ [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO",
+ [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
+ [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT",
+ [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT"
+};
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
+#endif
+
+static const char *v4l2_ioctls[] = {
+ [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
+ [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
+ [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
+ [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
+ [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
+ [_IOC_NR(VIDIOC_G_MPEGCOMP)] = "VIDIOC_G_MPEGCOMP",
+ [_IOC_NR(VIDIOC_S_MPEGCOMP)] = "VIDIOC_S_MPEGCOMP",
+ [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
+ [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
+ [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
+ [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
+ [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
+ [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
+ [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
+ [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
+ [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
+ [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
+ [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
+ [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
+ [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
+ [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
+ [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
+ [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
+ [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
+ [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
+ [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
+ [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
+ [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
+ [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
+ [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
+ [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
+ [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
+ [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
+ [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
+ [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
+ [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
+ [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
+ [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
+ [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
+ [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
+ [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
+ [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
+ [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
+ [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
+ [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
+ [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
+ [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
+ [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
+ [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
+ [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
+ [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
+ [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
+#if 1
+ [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
#endif
- [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
- [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
- [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
- [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
- [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
- [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
- [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
- [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
- [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
- [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
- [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
- [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
- [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
- [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
- [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
- [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
- [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
- [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
- [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
- [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
- [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
- [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
- [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
- [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
- [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
- [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
- [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
- [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
- [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
- [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
- [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
- [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
- [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
- [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
- [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
- [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
- [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
- [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
- [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
- [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
- [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
- [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
- [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
- [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
- [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
- [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
+ [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS"
};
+#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
+
+static const char *v4l2_int_ioctls[] = {
+#ifdef HAVE_VIDEO_DECODER
+ [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES",
+ [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS",
+ [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM",
+ [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT",
+ [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT",
+ [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT",
+ [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE",
+ [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO",
+ [_IOC_NR(DECODER_INIT)] = "DECODER_INIT",
+ [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS",
+ [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP",
+#endif
+ [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
+ [_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT",
+ [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX",
+
+ [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
+ [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
+ [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG",
+
+ [_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER",
+ [_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER",
+ [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
+ [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
+ [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE",
+ [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
+ [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
+ [_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT",
+ [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ"
+};
+#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
+
+/* Common ioctl debug function. This function can be used by
+ external ioctl messages as well as internal V4L ioctl */
+void v4l_printk_ioctl(unsigned int cmd)
+{
+ char *dir;
+
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE: dir = "--"; break;
+ case _IOC_READ: dir = "r-"; break;
+ case _IOC_WRITE: dir = "-w"; break;
+ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+ default: dir = "*ERR*"; break;
+ }
+ switch (_IOC_TYPE(cmd)) {
+ case 'd':
+ printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
+ (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
+ v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+ break;
+#ifdef HAVE_V4L1
+ case 'v':
+ printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
+ (_IOC_NR(cmd) < V4L1_IOCTLS) ?
+ v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+ break;
+#endif
+ case 'V':
+ printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
+ (_IOC_NR(cmd) < V4L2_IOCTLS) ?
+ v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+ break;
+
+ default:
+ printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
+ _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+ }
+}
/* ----------------------------------------------------------------- */
@@ -255,7 +375,7 @@ EXPORT_SYMBOL(v4l2_prio_check);
EXPORT_SYMBOL(v4l2_field_names);
EXPORT_SYMBOL(v4l2_type_names);
-EXPORT_SYMBOL(v4l2_ioctl_names);
+EXPORT_SYMBOL(v4l_printk_ioctl);
/*
* Local variables:
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 9a6bf287e26a..9ef477523d27 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -52,10 +52,9 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
struct page *pg;
int i;
- sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
+ sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
- memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
@@ -80,10 +79,9 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
if (NULL == pages[0])
return NULL;
- sglist = kmalloc(sizeof(*sglist) * nr_pages, GFP_KERNEL);
+ sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
- memset(sglist, 0, sizeof(*sglist) * nr_pages);
if (NULL == pages[0])
goto nopage;
@@ -284,9 +282,8 @@ void* videobuf_alloc(unsigned int size)
{
struct videobuf_buffer *vb;
- vb = kmalloc(size,GFP_KERNEL);
+ vb = kzalloc(size,GFP_KERNEL);
if (NULL != vb) {
- memset(vb,0,size);
videobuf_dma_init(&vb->dma);
init_waitqueue_head(&vb->done);
vb->magic = MAGIC_BUFFER;
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
index 839db622040d..8f271de57fd6 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/videocodec.c
@@ -124,17 +124,13 @@ videocodec_attach (struct videocodec_master *master)
if (res == 0) {
dprintk(3, "videocodec_attach '%s'\n",
codec->name);
- ptr = (struct attached_list *)
- kmalloc(sizeof(struct attached_list),
- GFP_KERNEL);
+ ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
if (!ptr) {
dprintk(1,
KERN_ERR
"videocodec_attach: no memory\n");
goto out_kfree;
}
- memset(ptr, 0,
- sizeof(struct attached_list));
ptr->codec = codec;
a = h->list;
@@ -249,14 +245,11 @@ videocodec_register (const struct videocodec *codec)
"videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
codec->name, codec->type, codec->flags, codec->magic);
- ptr =
- (struct codec_list *) kmalloc(sizeof(struct codec_list),
- GFP_KERNEL);
+ ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
if (!ptr) {
dprintk(1, KERN_ERR "videocodec_register: no memory\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct codec_list));
ptr->codec = codec;
if (!h) {
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 6de5b0094b82..078880e4c8c0 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -29,7 +29,6 @@
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/semaphore.h>
#include <linux/videodev.h>
@@ -52,10 +51,7 @@ struct video_device *video_device_alloc(void)
{
struct video_device *vfd;
- vfd = kmalloc(sizeof(*vfd),GFP_KERNEL);
- if (NULL == vfd)
- return NULL;
- memset(vfd,0,sizeof(*vfd));
+ vfd = kzalloc(sizeof(*vfd),GFP_KERNEL);
return vfd;
}
@@ -68,7 +64,8 @@ static void video_release(struct class_device *cd)
{
struct video_device *vfd = container_of(cd, struct video_device, class_dev);
-#if 1 /* needed until all drivers are fixed */
+#if 1
+ /* needed until all drivers are fixed */
if (!vfd->release)
return;
#endif
@@ -85,7 +82,7 @@ static struct class video_class = {
*/
static struct video_device *video_device[VIDEO_NUM_DEVICES];
-static DECLARE_MUTEX(videodev_lock);
+static DEFINE_MUTEX(videodev_lock);
struct video_device* video_devdata(struct file *file)
{
@@ -104,15 +101,15 @@ static int video_open(struct inode *inode, struct file *file)
if(minor>=VIDEO_NUM_DEVICES)
return -ENODEV;
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
vfl=video_device[minor];
if(vfl==NULL) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
vfl=video_device[minor];
if (vfl==NULL) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENODEV;
}
}
@@ -125,7 +122,7 @@ static int video_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return err;
}
@@ -306,12 +303,12 @@ int video_register_device(struct video_device *vfd, int type, int nr)
}
/* pick a minor number */
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
if (nr >= 0 && nr < end-base) {
/* use the one the driver asked for */
i = base+nr;
if (NULL != video_device[i]) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENFILE;
}
} else {
@@ -320,13 +317,13 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (NULL == video_device[i])
break;
if (i == end) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENFILE;
}
}
video_device[i]=vfd;
vfd->minor=i;
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base);
devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor),
@@ -338,13 +335,14 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (vfd->dev)
vfd->class_dev.dev = vfd->dev;
vfd->class_dev.class = &video_class;
- vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
+ vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE);
class_device_register(&vfd->class_dev);
class_device_create_file(&vfd->class_dev,
- &class_device_attr_name);
+ &class_device_attr_name);
-#if 1 /* needed until all drivers are fixed */
+#if 1
+ /* needed until all drivers are fixed */
if (!vfd->release)
printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
"Please fix your driver for proper sysfs support, see "
@@ -363,14 +361,14 @@ int video_register_device(struct video_device *vfd, int type, int nr)
void video_unregister_device(struct video_device *vfd)
{
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
if(video_device[vfd->minor]!=vfd)
panic("videodev: bad unregister");
devfs_remove(vfd->devfs_name);
video_device[vfd->minor]=NULL;
class_device_unregister(&vfd->class_dev);
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 71b28e9e0850..c8fd8238904d 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -4499,13 +4499,11 @@ 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);
+ vino_drvdata = kzalloc(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++;
/* create a dummy dma descriptor */
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 8dcee8b60e21..d0a1e72ea8c4 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -621,13 +621,11 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == NULL) {
return -ENOMEM;
}
- memset(client, 0, sizeof(struct i2c_client));
-
client->addr = address;
client->adapter = adapter;
client->driver = &vpx3220_i2c_driver;
@@ -675,12 +673,11 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
sizeof(I2C_NAME(client)));
}
- decoder = kmalloc(sizeof(struct vpx3220), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct vpx3220));
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index c318ba32fbaf..b7b0afffd214 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -187,6 +187,7 @@ static struct file_operations w9966_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = w9966_v4l_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = w9966_v4l_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index bbfd55cd9948..8cb64f8a8a91 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -25,7 +25,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioctl.h>
@@ -33,20 +32,12 @@
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("wm8775 driver");
MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
MODULE_LICENSE("GPL");
-#define wm8775_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define wm8775_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-
static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END };
@@ -70,7 +61,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val)
int i;
if (reg < 0 || reg >= TOT_REGS) {
- wm8775_err("Invalid register R%d\n", reg);
+ v4l_err(client, "Invalid register R%d\n", reg);
return -1;
}
@@ -80,7 +71,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val)
return 0;
}
}
- wm8775_err("I2C: cannot write %03x to register R%d\n", val, reg);
+ v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
return -1;
}
@@ -88,38 +79,53 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
struct wm8775_state *state = i2c_get_clientdata(client);
- int *input = arg;
+ struct v4l2_audio *input = arg;
+ struct v4l2_control *ctrl = arg;
switch (cmd) {
- case AUDC_SET_INPUT:
+ case VIDIOC_S_AUDIO:
+ /* There are 4 inputs and one output. Zero or more inputs
+ are multiplexed together to the output. Hence there are
+ 16 combinations.
+ If only one input is active (the normal case) then the
+ input values 1, 2, 4 or 8 should be used. */
+ if (input->index > 15) {
+ v4l_err(client, "Invalid input %d.\n", input->index);
+ return -EINVAL;
+ }
+ state->input = input->index;
+ if (state->muted)
+ break;
wm8775_write(client, R21, 0x0c0);
wm8775_write(client, R14, 0x1d4);
wm8775_write(client, R15, 0x1d4);
+ wm8775_write(client, R21, 0x100 + state->input);
+ break;
- if (*input == AUDIO_RADIO) {
- wm8775_write(client, R21, 0x108);
- state->input = 8;
- state->muted = 0;
- break;
- }
- if (*input == AUDIO_MUTE) {
- state->muted = 1;
- break;
- }
- if (*input == AUDIO_UNMUTE) {
+ case VIDIOC_G_AUDIO:
+ memset(input, 0, sizeof(*input));
+ input->index = state->input;
+ break;
+
+ case VIDIOC_G_CTRL:
+ if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+ return -EINVAL;
+ ctrl->value = state->muted;
+ break;
+
+ case VIDIOC_S_CTRL:
+ if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+ return -EINVAL;
+ state->muted = ctrl->value;
+ wm8775_write(client, R21, 0x0c0);
+ wm8775_write(client, R14, 0x1d4);
+ wm8775_write(client, R15, 0x1d4);
+ if (!state->muted)
wm8775_write(client, R21, 0x100 + state->input);
- state->muted = 0;
- break;
- }
- /* All other inputs... */
- wm8775_write(client, R21, 0x102);
- state->input = 2;
- state->muted = 0;
break;
case VIDIOC_LOG_STATUS:
- wm8775_info("Input: %s%s\n",
- state->input == 8 ? "radio" : "default",
+ v4l_info(client, "Input: %d%s\n", state->input,
state->muted ? " (muted)" : "");
break;
@@ -160,17 +166,16 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver;
snprintf(client->name, sizeof(client->name) - 1, "wm8775");
- wm8775_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL);
if (state == NULL) {
@@ -206,11 +211,7 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind)
static int wm8775_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, wm8775_attach);
return 0;
}
@@ -235,12 +236,10 @@ static struct i2c_driver i2c_driver = {
.driver = {
.name = "wm8775",
},
-
- .id = I2C_DRIVERID_WM8775,
-
+ .id = I2C_DRIVERID_WM8775,
.attach_adapter = wm8775_probe,
- .detach_client = wm8775_detach,
- .command = wm8775_command,
+ .detach_client = wm8775_detach,
+ .command = wm8775_command,
};
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 39a0d238900e..246e67cd8b51 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -995,7 +995,7 @@ test_interrupts (struct zoran *zr)
static int __devinit
zr36057_init (struct zoran *zr)
{
- unsigned long mem;
+ u32 *mem;
void *vdev;
unsigned mem_needed;
int j;
@@ -1050,7 +1050,7 @@ zr36057_init (struct zoran *zr)
/* allocate memory *before* doing anything to the hardware
* in case allocation fails */
mem_needed = BUZ_NUM_STAT_COM * 4;
- mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL);
+ mem = kzalloc(mem_needed, GFP_KERNEL);
vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL);
if (!mem || !vdev) {
dprintk(1,
@@ -1058,11 +1058,10 @@ zr36057_init (struct zoran *zr)
"%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
ZR_DEVNAME(zr));
kfree(vdev);
- kfree((void *)mem);
+ kfree(mem);
return -ENOMEM;
}
- memset((void *) mem, 0, mem_needed);
- zr->stat_com = (u32 *) mem;
+ zr->stat_com = mem;
for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */
}
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 4034f1b45366..485553be190b 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -1345,7 +1345,7 @@ zoran_open (struct inode *inode,
ZR_DEVNAME(zr), current->comm, current->pid, zr->user);
/* now, create the open()-specific file_ops struct */
- fh = kmalloc(sizeof(struct zoran_fh), GFP_KERNEL);
+ fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
if (!fh) {
dprintk(1,
KERN_ERR
@@ -1354,7 +1354,6 @@ zoran_open (struct inode *inode,
res = -ENOMEM;
goto open_unlock_and_return;
}
- memset(fh, 0, sizeof(struct zoran_fh));
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
* on norm-change! */
fh->overlay_mask =
@@ -4678,6 +4677,7 @@ static struct file_operations zoran_fops = {
.open = zoran_open,
.release = zoran_close,
.ioctl = zoran_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
.read = zoran_read,
.write = zoran_write,
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
index 4ed898585c70..10130ef67ea7 100644
--- a/drivers/media/video/zr36016.c
+++ b/drivers/media/video/zr36016.c
@@ -451,12 +451,11 @@ zr36016_setup (struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kmalloc(sizeof(struct zr36016), GFP_KERNEL);
+ codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
if (NULL == ptr) {
dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct zr36016));
snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
zr36016_codecs);
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index 0144576a6123..bd0cd28543ca 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -813,12 +813,11 @@ zr36050_setup (struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kmalloc(sizeof(struct zr36050), GFP_KERNEL);
+ codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
if (NULL == ptr) {
dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct zr36050));
snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
zr36050_codecs);
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
index 129744a07abd..28fa31a5f150 100644
--- a/drivers/media/video/zr36060.c
+++ b/drivers/media/video/zr36060.c
@@ -919,12 +919,11 @@ zr36060_setup (struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kmalloc(sizeof(struct zr36060), GFP_KERNEL);
+ codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
if (NULL == ptr) {
dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct zr36060));
snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
zr36060_codecs);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index 07286816d7df..d4c633b8a7f5 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -1490,6 +1490,7 @@ static struct video_device zr36120_template=
.write = zoran_write,
.poll = zoran_poll,
.ioctl = zoran_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.mmap = zoran_mmap,
.minor = -1,
};
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 1883d22cffeb..e67cf15e9c39 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -23,6 +23,7 @@ config FUSION_FC
tristate "Fusion MPT ScsiHost drivers for FC"
depends on PCI && SCSI
select FUSION
+ select SCSI_FC_ATTRS
---help---
SCSI HOST support for a Fiber Channel host adapters.
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index b61e3d175070..02cdc840a06b 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.08
+ * mpi.h Version: 01.05.10
*
* Version History
* ---------------
@@ -74,6 +74,8 @@
* 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Added EEDP IOCStatus codes.
+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* --------------------------------------------------------------------------
*/
@@ -104,7 +106,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x0A)
+#define MPI_HEADER_VERSION_UNIT (0x0C)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
+#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
+#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
/****************************************************************************/
/* Additional FCP target values (obsolete) */
@@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_LAN_CANCELED (0x0087)
/****************************************************************************/
-/* Serial Attached SCSI values */
+/* Serial Attached SCSI values */
/****************************************************************************/
#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index d8339896f734..b1becec27e1b 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.09
+ * mpi_cnfg.h Version: 01.05.11
*
* Version History
* ---------------
@@ -249,6 +249,23 @@
* 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.
+ * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
+ * Manufacturing Page 4.
+ * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ * define.
+ * Added EnclosureHandle field to SAS Expander page 0.
+ * Removed redundant NumTableEntriesProg field from SAS
+ * Expander Page 1.
+ * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
+ * SAS1078.
+ * Added more defines for Manufacturing Page 4 Flags field.
+ * Added more defines for IOCSettings and added
+ * ExpanderSpinup field to Bios Page 1.
+ * Added postpone SATA Init bit to SAS IO Unit Page 1
+ * ControlFlags.
+ * Changed LogEntry format for Log Page 0.
* --------------------------------------------------------------------------
*/
@@ -494,7 +511,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)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646)
/* SCSI */
#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A)
#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054)
#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058)
-#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062)
typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
U32 IMVolumeSettings; /* 50h */
U32 Reserved3; /* 54h */
U32 Reserved4; /* 58h */
- U8 ISDataScrubRate; /* 5Ch */
- U8 ISResyncRate; /* 5Dh */
- U16 Reserved5; /* 5Eh */
+ U32 Reserved5; /* 5Ch */
U8 IMEDataScrubRate; /* 60h */
U8 IMEResyncRate; /* 61h */
U16 Reserved6; /* 62h */
@@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
-#define MPI_MANUFACTURING4_PAGEVERSION (0x02)
+#define MPI_MANUFACTURING4_PAGEVERSION (0x03)
/* defines for the Flags field */
+#define MPI_MANPAGE4_IME_DISABLE (0x20)
+#define MPI_MANPAGE4_IM_DISABLE (0x10)
+#define MPI_MANPAGE4_IS_DISABLE (0x08)
+#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04)
+#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02)
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
@@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
-#define MPI_IOUNITPAGE1_PAGEVERSION (0x01)
+#define MPI_IOUNITPAGE1_PAGEVERSION (0x02)
/* IO Unit Page 1 Flags defines */
#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000)
@@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040)
#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080)
#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
-
+#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200)
typedef struct _MPI_ADAPTER_INFO
{
@@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
U32 Reserved1; /* 0Ch */
U32 DeviceSettings; /* 10h */
U16 NumberOfDevices; /* 14h */
- U16 Reserved2; /* 16h */
+ U8 ExpanderSpinup; /* 16h */
+ U8 Reserved2; /* 17h */
U16 IOTimeoutBlockDevicesNonRM; /* 18h */
U16 IOTimeoutSequential; /* 1Ah */
U16 IOTimeoutOther; /* 1Ch */
@@ -976,7 +997,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 (0x02)
+#define MPI_BIOSPAGE1_PAGEVERSION (0x03)
/* values for the BiosOptions field */
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000)
#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20)
+
+#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000)
+#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
@@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
+/* defines for the ExpanderSpinup field */
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0)
+#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4)
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F)
+
typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
{
U32 Reserved1; /* 00h */
@@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8)
#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \
- ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \
+ ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \
)
#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000)
#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16)
#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \
- ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
+ ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \
)
#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000)
@@ -2370,47 +2403,48 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
-#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05)
/* 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)
-#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
-
-#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
-#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 (0x02)
-
-#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)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
-#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
-#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
-#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
-#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
+#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)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
+
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
+#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 (0x02)
+
+#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (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)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
/* values for SAS IO Unit Page 1 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
/* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
/* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
@@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ U8 NumDevsPerEnclosure; /* 08h */
+ U8 Reserved1; /* 09h */
+ U16 Reserved2; /* 0Ah */
U16 MaxPersistentIDs; /* 0Ch */
U16 NumPersistentIDsUsed; /* 0Eh */
U8 Status; /* 10h */
U8 Flags; /* 11h */
- U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */
+ U16 MaxNumPhysicalMappedIDs;/* 12h */
} 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 (0x04)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05)
/* values for SAS IO Unit Page 2 Status field */
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00)
#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01)
#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
+#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07)
#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20)
@@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U8 PhysicalPort; /* 08h */
U8 Reserved1; /* 09h */
- U16 Reserved2; /* 0Ah */
+ U16 EnclosureHandle; /* 0Ah */
U64 SASAddress; /* 0Ch */
U32 DiscoveryStatus; /* 14h */
U16 DevHandle; /* 18h */
@@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
-#define MPI_SASEXPANDER0_PAGEVERSION (0x02)
+#define MPI_SASEXPANDER0_PAGEVERSION (0x03)
/* values for SAS Expander Page 0 DiscoveryStatus field */
#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
@@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
U8 NegotiatedLinkRate; /* 1Fh */
U8 PhyIdentifier; /* 20h */
U8 AttachedPhyIdentifier; /* 21h */
- U8 NumTableEntriesProg; /* 22h */
+ U8 Reserved3; /* 22h */
U8 DiscoveryInfo; /* 23h */
- U32 Reserved3; /* 24h */
+ U32 Reserved4; /* 24h */
} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
@@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
#define MPI_LOG_0_NUM_LOG_ENTRIES (1)
#endif
-#define MPI_LOG_0_LOG_DATA_LENGTH (20)
+#define MPI_LOG_0_LOG_DATA_LENGTH (0x1C)
typedef struct _MPI_LOG_0_ENTRY
{
- U64 WWID; /* 00h */
- U32 TimeStamp; /* 08h */
- U32 Reserved1; /* 0Ch */
- U16 LogSequence; /* 10h */
- U16 LogEntryQualifier; /* 12h */
- U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+ U32 TimeStamp; /* 00h */
+ U32 Reserved1; /* 04h */
+ U16 LogSequence; /* 08h */
+ U16 LogEntryQualifier; /* 0Ah */
+ U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */
} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
@@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0
} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
LogPage0_t, MPI_POINTER pLogPage0_t;
-#define MPI_LOG_0_PAGEVERSION (0x00)
+#define MPI_LOG_0_PAGEVERSION (0x01)
#endif
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 1a30ef16adb4..4a5f8dd1d766 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,25 +6,25 @@
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.10
- Header Set Release Date: 03-11-05
+ Header Set Release Version: 01.05.12
+ Header Set Release Date: 08-30-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- 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.h 01.05.10 01.05.09
+ mpi_ioc.h 01.05.10 01.05.09
+ mpi_cnfg.h 01.05.11 01.05.10
+ mpi_init.h 01.05.06 01.05.06
+ mpi_targ.h 01.05.05 01.05.05
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
- mpi_history.txt 01.05.09 01.05.09
+ mpi_sas.h 01.05.02 01.05.01
+ mpi_type.h 01.05.02 01.05.01
+ mpi_history.txt 01.05.12 01.05.11
* Date Version Description
@@ -91,6 +91,8 @@ mpi.h
* 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Added EEDP IOCStatus codes.
+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -164,6 +166,10 @@ mpi_ioc.h
* 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.
+ * 08-30-05 01.05.10 Added 4 new events and their event data structures.
+ * Added new ReasonCode value for SAS Device Status Change
+ * event.
+ * Added new family code for FC949E.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -402,6 +408,23 @@ mpi_cnfg.h
* 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.
+ * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
+ * Manufacturing Page 4.
+ * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ * define.
+ * Added EnclosureHandle field to SAS Expander page 0.
+ * Removed redundant NumTableEntriesProg field from SAS
+ * Expander Page 1.
+ * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
+ * SAS1078.
+ * Added more defines for Manufacturing Page 4 Flags field.
+ * Added more defines for IOCSettings and added
+ * ExpanderSpinup field to Bios Page 1.
+ * Added postpone SATA Init bit to SAS IO Unit Page 1
+ * ControlFlags.
+ * Changed LogEntry format for Log Page 0.
* --------------------------------------------------------------------------
mpi_init.h
@@ -442,6 +465,8 @@ mpi_init.h
* addressing.
* 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
* Added four new defines for SEP SlotStatus.
+ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ * unique in the first 32 characters.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -582,6 +607,9 @@ mpi_inb.h
mpi_sas.h
* 08-19-04 01.05.01 Original release.
+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
+ * Added PrimFlags and Primitive field to SAS IO Unit
+ * Control request, and added a new operation code.
* --------------------------------------------------------------------------
mpi_type.h
@@ -592,24 +620,25 @@ mpi_type.h
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 08-30-05 01.05.02 Added PowerPC option to #ifdef's.
* --------------------------------------------------------------------------
mpi_history.txt Parts list history
-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.12 01.05.11 01.05.10 01.05.09
+---------- -------- -------- -------- --------
+mpi.h 01.05.10 01.05.09 01.05.08 01.05.07
+mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08
+mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08
+mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04
+mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01
+mpi_type.h 01.05.02 01.05.01 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 d5af75afbd94..68941f459ca3 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.05
+ * mpi_init.h Version: 01.05.06
*
* Version History
* ---------------
@@ -50,6 +50,8 @@
* addressing.
* 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
* Added four new defines for SEP SlotStatus.
+ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ * unique in the first 32 characters.
* --------------------------------------------------------------------------
*/
@@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST
/* 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_32_SENSE_WIDTH (0x00)
+#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01)
#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02)
#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 93b70e2b4266..2c5f43fa7c73 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.09
+ * mpi_ioc.h Version: 01.05.10
*
* Version History
* ---------------
@@ -83,6 +83,10 @@
* 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.
+ * 08-30-05 01.05.10 Added 4 new events and their event data structures.
+ * Added new ReasonCode value for SAS Device Status Change
+ * event.
+ * Added new family code for FC949E.
* --------------------------------------------------------------------------
*/
@@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
+#define MPI_EVENT_IR2 (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
+#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
/* AckRequired field values */
@@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE
} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE,
EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t;
+/* LogEntryAdded Event data */
+
+/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */
+#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C)
+typedef struct _EVENT_DATA_LOG_ENTRY
+{
+ U32 TimeStamp; /* 00h */
+ U32 Reserved1; /* 04h */
+ U16 LogSequence; /* 08h */
+ U16 LogEntryQualifier; /* 0Ah */
+ U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */
+} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY,
+ MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t;
+
+typedef struct _EVENT_DATA_LOG_ENTRY_ADDED
+{
+ U16 LogSequence; /* 00h */
+ U16 Reserved1; /* 02h */
+ U32 Reserved2; /* 04h */
+ EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */
+} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED,
+ MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t;
+
/* SCSI Event data for Port, Bus and Device forms */
typedef struct _EVENT_DATA_SCSI
@@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
/* SCSI Event data for Queue Full event */
@@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID
#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
+
+/* MPI Integrated RAID Resync Update Event data */
+
+typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE
+{
+ U8 VolumeID; /* 00h */
+ U8 VolumeBus; /* 01h */
+ U8 ResyncComplete; /* 02h */
+ U8 Reserved1; /* 03h */
+ U32 Reserved2; /* 04h */
+} MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+ MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+ MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t;
+
+/* MPI IR2 Event data */
+
+/* MPI_LD_STATE or MPI_PD_STATE */
+typedef struct _IR2_STATE_CHANGED
+{
+ U16 PreviousState; /* 00h */
+ U16 NewState; /* 02h */
+} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED;
+
+typedef struct _IR2_PD_INFO
+{
+ U16 DeviceHandle; /* 00h */
+ U8 TruncEnclosureHandle; /* 02h */
+ U8 TruncatedSlot; /* 03h */
+} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO;
+
+typedef union _MPI_IR2_RC_EVENT_DATA
+{
+ IR2_STATE_CHANGED StateChanged;
+ U32 Lba;
+ IR2_PD_INFO PdInfo;
+} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA;
+
+typedef struct _MPI_EVENT_DATA_IR2
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 ReasonCode; /* 02h */
+ U8 PhysDiskNum; /* 03h */
+ MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */
+} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2,
+ MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t;
+
+/* MPI IR2 Event data ReasonCode values */
+#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01)
+#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02)
+#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03)
+#define MPI_EVENT_IR2_RC_PD_INSERTED (0x04)
+#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05)
+#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06)
+#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07)
+
+/* defines for logical disk states */
+#define MPI_LD_STATE_OPTIMAL (0x00)
+#define MPI_LD_STATE_DEGRADED (0x01)
+#define MPI_LD_STATE_FAILED (0x02)
+#define MPI_LD_STATE_MISSING (0x03)
+#define MPI_LD_STATE_OFFLINE (0x04)
+
+/* defines for physical disk states */
+#define MPI_PD_STATE_ONLINE (0x00)
+#define MPI_PD_STATE_MISSING (0x01)
+#define MPI_PD_STATE_NOT_COMPATIBLE (0x02)
+#define MPI_PD_STATE_FAILED (0x03)
+#define MPI_PD_STATE_INITIALIZING (0x04)
+#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05)
+#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06)
+#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF)
+
/* MPI Link Status Change Event data */
typedef struct _EVENT_DATA_LINK_STATUS
@@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
+/* SAS Discovery Event data */
+
+typedef struct _EVENT_DATA_SAS_DISCOVERY
+{
+ U32 DiscoveryStatus; /* 00h */
+ U32 Reserved1; /* 04h */
+} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY,
+ EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t;
+
+#define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000)
+#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16)
+
/* SAS Discovery Errror Event data */
typedef struct _EVENT_DATA_DISCOVERY_ERROR
@@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */
#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */
#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005)
+#define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006)
/* SAS */
#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001)
#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002)
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
new file mode 100644
index 000000000000..dc98d46f9071
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_fc.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *
+ * NAME: fc_log.h
+ * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips
+ * DESCRIPTION: Contains the enumerated list of values that may be returned
+ * in the IOCLogInfo field of a MPI Default Reply Message.
+ *
+ * CREATION DATE: 6/02/2000
+ * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
+ */
+
+
+/*
+ * MpiIocLogInfo_t enum
+ *
+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply
+ * messages.
+ * The value is 0xabcccccc where
+ * a = The type of log info as per the MPI spec. Since these codes are
+ * all for Fibre Channel this value will always be 2.
+ * b = Specifies a subclass of the firmware where
+ * 0 = FCP Initiator
+ * 1 = FCP Target
+ * 2 = LAN
+ * 3 = MPI Message Layer
+ * 4 = FC Link
+ * 5 = Context Manager
+ * 6 = Invalid Field Offset
+ * 7 = State Change Info
+ * all others are reserved for future use
+ * c = A specific value within the subclass.
+ *
+ * NOTE: Any new values should be added to the end of each subclass so that the
+ * codes remain consistent across firmware releases.
+ */
+typedef enum _MpiIocLogInfoFc
+{
+ MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000,
+ MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */
+
+ MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000,
+ MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
+ MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */
+ MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */
+ MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */
+ MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */
+ MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */
+ MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */
+ MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */
+
+ MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000,
+ MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */
+ MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */
+ MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */
+ MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */
+
+ MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000,
+
+ MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000,
+ MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */
+ MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */
+ MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
+ MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */
+
+ MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000,
+
+ MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
+ MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff,
+
+ MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */
+
+} MpiIocLogInfoFc_t;
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
new file mode 100644
index 000000000000..9259d1ad6e6e
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -0,0 +1,162 @@
+
+/***************************************************************************
+ * *
+ * Copyright 2003 LSI Logic Corporation. All rights reserved. *
+ * *
+ * This file is confidential and a trade secret of LSI Logic. The *
+ * receipt of or possession of this file does not convey any rights to *
+ * reproduce or disclose its contents or to manufacture, use, or sell *
+ * anything it may describe, in whole, or in part, without the specific *
+ * written consent of LSI Logic Corporation. *
+ * *
+ ***************************************************************************
+ *
+ * Name: iopiIocLogInfo.h
+ * Title: SAS Firmware IOP Interface IOC Log Info Definitions
+ * Programmer: Guy Kendall
+ * Creation Date: September 24, 2003
+ *
+ * Version History
+ * ---------------
+ *
+ * Last Updated
+ * -------------
+ * Version %version: 22 %
+ * Date Updated %date_modified: %
+ * Programmer %created_by: nperucca %
+ *
+ * Date Who Description
+ * -------- --- -------------------------------------------------------
+ * 09/24/03 GWK Initial version
+ *
+ *
+ * Description
+ * ------------
+ * This include file contains SAS firmware interface IOC Log Info codes
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef IOPI_IOCLOGINFO_H_INCLUDED
+#define IOPI_IOCLOGINFO_H_INCLUDED
+
+
+/****************************************************************************/
+/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */
+/* Format: */
+/* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */
+/* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */
+/* Bits 23-16: LOGINFO_CODE */
+/* Bits 15-0: LOGINFO_CODE Specific */
+/****************************************************************************/
+
+/****************************************************************************/
+/* IOC_LOGINFO_ORIGINATOR defines */
+/****************************************************************************/
+#define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000)
+#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)
+#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)
+
+/****************************************************************************/
+/* LOGINFO_CODE defines */
+/****************************************************************************/
+#define IOC_LOGINFO_CODE_MASK (0x00FF0000)
+#define IOC_LOGINFO_CODE_SHIFT (16)
+
+/****************************************************************************/
+/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */
+/****************************************************************************/
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
+#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)
+
+
+/****************************************************************************/
+/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
+/****************************************************************************/
+#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)
+#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
+#define PL_LOGINFO_CODE_RESET (0x00110000)
+#define PL_LOGINFO_CODE_ABORT (0x00120000)
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
+
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
+
+
+/****************************************************************************/
+/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */
+/****************************************************************************/
+#define IR_LOGINFO_CODE_UNUSED1 (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)
+
+/****************************************************************************/
+/* Defines for convienence */
+/****************************************************************************/
+#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
+#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
+#define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)
+
+#endif /* end of file */
+
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 230fa69b5353..70514867bddf 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -6,7 +6,7 @@
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.01
+ * mpi_sas.h Version: 01.05.02
*
* Version History
* ---------------
@@ -14,6 +14,9 @@
* Date Version Description
* -------- -------- ------------------------------------------------------
* 08-19-04 01.05.01 Original release.
+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
+ * Added PrimFlags and Primitive field to SAS IO Unit
+ * Control request, and added a new operation code.
* --------------------------------------------------------------------------
*/
@@ -51,6 +54,7 @@
* Values for the SAS DeviceInfo field used in SAS Device Status Change Event
* data and SAS IO Unit Configuration pages.
*/
+#define MPI_SAS_DEVICE_INFO_SEP (0x00004000)
#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
@@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
U8 TargetID; /* 0Ch */
U8 Bus; /* 0Dh */
U8 PhyNum; /* 0Eh */
- U8 Reserved4; /* 0Fh */
- U32 Reserved5; /* 10h */
+ U8 PrimFlags; /* 0Fh */
+ U32 Primitive; /* 10h */
U64 SASAddress; /* 14h */
- U32 Reserved6; /* 1Ch */
+ U32 Reserved4; /* 1Ch */
} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
/* values for the Operation field */
-#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
-#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
-#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
-#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
-#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
-#define MPI_SAS_OP_MAP_CURRENT (0x09)
+#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
+#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
+#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
+#define MPI_SAS_OP_MAP_CURRENT (0x09)
+#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)
+
+/* values for the PrimFlags field */
+#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
+#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02)
+#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01)
/* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 537836068c49..d890b2b8a93e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -148,7 +148,6 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
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);
@@ -1232,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((KERN_INFO MYNAM
": Not using 64 bit consistent mask\n"));
- ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+ ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
return -ENOMEM;
}
- memset(ioc, 0, sizeof(MPT_ADAPTER));
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@@ -1245,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pcidev = pdev;
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
+ spin_lock_init(&ioc->fc_rescan_work_lock);
+ spin_lock_init(&ioc->fc_rport_lock);
spin_lock_init(&ioc->initializing_hba_lock);
/* Initialize the event logging.
@@ -1268,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
*/
INIT_LIST_HEAD(&ioc->configQ);
+ /* Initialize the fc rport list head.
+ */
+ INIT_LIST_HEAD(&ioc->fc_rports);
+
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
ioc->id = mpt_ids++;
@@ -1374,6 +1378,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->bus_type = FC;
ioc->errata_flag_1064 = 1;
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+ ioc->prod_name = "LSIFC949E";
+ ioc->bus_type = FC;
+ }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
ioc->bus_type = SPI;
@@ -1622,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev)
pci_enable_device(pdev);
/* enable interrupts */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
/* F/W not running */
@@ -1715,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
@@ -1831,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (ret == 0) {
/* Enable! (reply interrupt) */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
}
@@ -1839,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* (re)Enable alt-IOC! (reply interrupt) */
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));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
@@ -1880,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
* (FCPortPage0_t stuff)
*/
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) GetFcPortPage0(ioc, ii);
+ (void) mptbase_GetFcPortPage0(ioc, ii);
}
if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -4199,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * GetFcPortPage0 - Fetch FCPort config Page0.
+ * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
* @ioc: Pointer to MPT_ADAPTER structure
* @portnum: IOC Port number
*
@@ -4209,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
* -EAGAIN if no msg frames currently available
* -EFAULT for non-successful reply or no reply (timeout)
*/
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
{
ConfigPageHeader_t hdr;
CONFIGPARMS cfg;
@@ -4220,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
int data_sz;
int copy_sz;
int rc;
+ int count = 400;
+
/* Get FCPort Page 0 header */
hdr.PageVersion = 0;
@@ -4243,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
rc = -ENOMEM;
ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
if (ppage0_alloc) {
+
+ try_again:
memset((u8 *)ppage0_alloc, 0, data_sz);
cfg.physAddr = page0_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4274,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
+ /*
+ * if still doing discovery,
+ * hang loose a while until finished
+ */
+ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+ if (count-- > 0) {
+ msleep_interruptible(100);
+ goto try_again;
+ }
+ printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+ " complete.\n",
+ ioc->name);
+ }
}
pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -6358,6 +6383,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
EXPORT_SYMBOL(mpt_alt_ioc_wait);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6c48d1f54ac9..47053ac65068 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.05"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05"
+#define MPT_LINUX_VERSION_COMMON "3.03.06"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -413,7 +413,7 @@ typedef struct _MPT_IOCTL {
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
u8 target; /* target for reset */
- struct semaphore sem_ioc;
+ struct mutex ioctl_mutex;
} MPT_IOCTL;
#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */
@@ -421,7 +421,7 @@ typedef struct _MPT_IOCTL {
#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */
typedef struct _MPT_SAS_MGMT {
- struct semaphore mutex;
+ struct mutex mutex;
struct completion done;
u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 status; /* current command status */
@@ -499,6 +499,22 @@ typedef struct _RaidCfgData {
int isRaid; /* bit field, 1 if RAID */
}RaidCfgData;
+#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
+#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
+#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */
+
+/*
+ * data allocated for each fc rport device
+ */
+struct mptfc_rport_info
+{
+ struct list_head list;
+ struct fc_rport *rport;
+ VirtDevice *vdev;
+ FCDevicePage0_t pg0;
+ u8 flags;
+};
+
/*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
*/
@@ -612,7 +628,16 @@ typedef struct _MPT_ADAPTER
struct list_head list;
struct net_device *netdev;
struct list_head sas_topology;
+ struct mutex sas_topology_mutex;
MPT_SAS_MGMT sas_mgmt;
+ int num_ports;
+
+ struct list_head fc_rports;
+ spinlock_t fc_rport_lock; /* list and ri flags */
+ spinlock_t fc_rescan_work_lock;
+ int fc_rescan_work_count;
+ struct work_struct fc_rescan_work;
+
} MPT_ADAPTER;
/*
@@ -999,6 +1024,7 @@ 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);
+extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
/*
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 959d2c5951b8..bdf709987982 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
if (nonblock) {
- if (down_trylock(&ioc->ioctl->sem_ioc))
+ if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
rc = -EAGAIN;
} else {
- if (down_interruptible(&ioc->ioctl->sem_ioc))
+ if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
rc = -ERESTARTSYS;
}
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
else
ret = -EINVAL;
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2585,8 +2585,6 @@ static struct miscdevice mptctl_miscdev = {
#ifdef CONFIG_COMPAT
-#include <linux/ioctl32.h>
-
static int
compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
@@ -2621,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2675,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
*/
ret = mptctl_do_mpt_command (karg, &uarg->MF);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2745,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
memset(mem, 0, sz);
ioc->ioctl = (MPT_IOCTL *) mem;
ioc->ioctl->ioc = ioc;
- sema_init(&ioc->ioctl->sem_ioc, 1);
+ mutex_init(&ioc->ioctl->ioctl_mutex);
return 0;
out_fail:
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ba61e1828858..b102c7666d0e 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -55,12 +55,14 @@
#include <linux/reboot.h> /* notifier code */
#include <linux/sched.h>
#include <linux/workqueue.h>
+#include <linux/sort.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
#include "mptbase.h"
#include "mptscsih.h"
@@ -79,19 +81,34 @@ static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+#define MPTFC_DEV_LOSS_TMO (60)
+static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
+module_param(mptfc_dev_loss_tmo, int, 0);
+MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
+ " transport to wait for an rport to "
+ " return following a device loss event."
+ " Default=60.");
+
static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
+int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *));
+
+static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
+static void __devexit mptfc_remove(struct pci_dev *pdev);
+
static struct scsi_host_template mptfc_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptfc",
.proc_info = mptscsih_proc_info,
.name = "MPT FC Host",
.info = mptscsih_info,
- .queuecommand = mptscsih_qcmd,
+ .queuecommand = mptfc_qcmd,
.target_alloc = mptscsih_target_alloc,
- .slave_alloc = mptscsih_slave_alloc,
+ .slave_alloc = mptfc_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
@@ -128,19 +145,478 @@ static struct pci_device_id mptfc_pci_table[] = {
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+ PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static struct scsi_transport_template *mptfc_transport_template = NULL;
+
+struct fc_function_template mptfc_transport_functions = {
+ .dd_fcrport_size = 8,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_port_id = 1,
+ .show_rport_supported_classes = 1,
+ .show_starget_node_name = 1,
+ .show_starget_port_name = 1,
+ .show_starget_port_id = 1,
+ .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
+ .show_rport_dev_loss_tmo = 1,
+
+};
+
+/* FIXME! values controlling firmware RESCAN event
+ * need to be set low to allow dev_loss_tmo to
+ * work as expected. Currently, firmware doesn't
+ * notify driver of RESCAN event until some number
+ * of seconds elapse. This value can be set via
+ * lsiutil.
+ */
+static void
+mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+ if (timeout > 0)
+ rport->dev_loss_tmo = timeout;
+ else
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+}
+
+static int
+mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
+{
+ FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
+ FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
+
+ if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
+ if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
+ return 0;
+ if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
+ return -1;
+ return 1;
+ }
+ if ((*aa)->CurrentBus < (*bb)->CurrentBus)
+ return -1;
+ return 1;
+}
+
+static int
+mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
+ void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
+{
+ ConfigPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ FCDevicePage0_t *ppage0_alloc, *fc;
+ dma_addr_t page0_dma;
+ int data_sz;
+ int ii;
+
+ FCDevicePage0_t *p0_array=NULL, *p_p0;
+ FCDevicePage0_t **pp0_array=NULL, **p_pp0;
+
+ int rc = -ENOMEM;
+ U32 port_id = 0xffffff;
+ int num_targ = 0;
+ int max_bus = ioc->facts.MaxBuses;
+ int max_targ = ioc->facts.MaxDevices;
+
+ if (max_bus == 0 || max_targ == 0)
+ goto out;
+
+ data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
+ p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
+ if (!p0_array)
+ goto out;
+
+ data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
+ p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
+ if (!pp0_array)
+ goto out;
+
+ do {
+ /* Get FC Device Page 0 header */
+ hdr.PageVersion = 0;
+ hdr.PageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
+ cfg.cfghdr.hdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0;
+ cfg.pageAddr = port_id;
+ cfg.timeout = 0;
+
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
+ break;
+
+ if (hdr.PageLength <= 0)
+ break;
+
+ data_sz = hdr.PageLength * 4;
+ ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
+ &page0_dma);
+ rc = -ENOMEM;
+ if (!ppage0_alloc)
+ break;
+
+ cfg.physAddr = page0_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ if ((rc = mpt_config(ioc, &cfg)) == 0) {
+ ppage0_alloc->PortIdentifier =
+ le32_to_cpu(ppage0_alloc->PortIdentifier);
+
+ ppage0_alloc->WWNN.Low =
+ le32_to_cpu(ppage0_alloc->WWNN.Low);
+
+ ppage0_alloc->WWNN.High =
+ le32_to_cpu(ppage0_alloc->WWNN.High);
+
+ ppage0_alloc->WWPN.Low =
+ le32_to_cpu(ppage0_alloc->WWPN.Low);
+
+ ppage0_alloc->WWPN.High =
+ le32_to_cpu(ppage0_alloc->WWPN.High);
+
+ ppage0_alloc->BBCredit =
+ le16_to_cpu(ppage0_alloc->BBCredit);
+
+ ppage0_alloc->MaxRxFrameSize =
+ le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
+
+ port_id = ppage0_alloc->PortIdentifier;
+ num_targ++;
+ *p_p0 = *ppage0_alloc; /* save data */
+ *p_pp0++ = p_p0++; /* save addr */
+ }
+ pci_free_consistent(ioc->pcidev, data_sz,
+ (u8 *) ppage0_alloc, page0_dma);
+ if (rc != 0)
+ break;
+
+ } while (port_id <= 0xff0000);
+
+ if (num_targ) {
+ /* sort array */
+ if (num_targ > 1)
+ sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
+ mptfc_FcDevPage0_cmp_func, NULL);
+ /* call caller's func for each targ */
+ for (ii = 0; ii < num_targ; ii++) {
+ fc = *(pp0_array+ii);
+ func(ioc, ioc_port, fc);
+ }
+ }
+
+ out:
+ if (pp0_array)
+ kfree(pp0_array);
+ if (p0_array)
+ kfree(p0_array);
+ return rc;
+}
+
+static int
+mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
+{
+ /* not currently usable */
+ if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
+ MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
+ return -1;
+
+ if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
+ return -1;
+
+ if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
+ return -1;
+
+ /*
+ * board data structure already normalized to platform endianness
+ * shifted to avoid unaligned access on 64 bit architecture
+ */
+ rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
+ rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
+ rid->port_id = pg0->PortIdentifier;
+ rid->roles = FC_RPORT_ROLE_UNKNOWN;
+ rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+ rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+ return 0;
+}
+
+static void
+mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
+{
+ struct fc_rport_identifiers rport_ids;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ int match = 0;
+ u64 port_name;
+ unsigned long flags;
+
+ if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
+ return;
+
+ /* scan list looking for a match */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+ if (port_name == rport_ids.port_name) { /* match */
+ list_move_tail(&ri->list, &ioc->fc_rports);
+ match = 1;
+ break;
+ }
+ }
+ if (!match) { /* allocate one */
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+ ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
+ if (!ri)
+ return;
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_add_tail(&ri->list, &ioc->fc_rports);
+ }
+
+ ri->pg0 = *pg0; /* add/update pg0 data */
+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
+
+ if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+ rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ if (rport) {
+ if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+ ri->vdev = NULL;
+ ri->rport = rport;
+ *((struct mptfc_rport_info **)rport->dd_data) = ri;
+ }
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+ /*
+ * if already mapped, remap here. If not mapped,
+ * slave_alloc will allocate vdev and map
+ */
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
+ ri->vdev->target_id = ri->pg0.CurrentTargetID;
+ ri->vdev->bus_id = ri->pg0.CurrentBus;
+ ri->vdev->vtarget->target_id = ri->vdev->target_id;
+ ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+ }
+ #ifdef MPT_DEBUG
+ printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+ "rport tid %d, tmo %d\n",
+ ioc->sh->host_no,
+ pg0->PortIdentifier,
+ pg0->WWNN,
+ pg0->WWPN,
+ pg0->CurrentTargetID,
+ ri->rport->scsi_target_id,
+ ri->rport->dev_loss_tmo);
+ #endif
+ } else {
+ list_del(&ri->list);
+ kfree(ri);
+ ri = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+}
+
/*
- * mptfc_probe - Installs scsi devices per bus.
- * @pdev: Pointer to pci_dev structure
- *
- * Returns 0 for success, non-zero for failure.
- *
+ * OS entry point to allow host driver to alloc memory
+ * for each scsi device. Called once per device the bus scan.
+ * Return non-zero if allocation fails.
+ * Init memory once per LUN.
*/
+int
+mptfc_slave_alloc(struct scsi_device *sdev)
+{
+ MPT_SCSI_HOST *hd;
+ VirtTarget *vtarget;
+ VirtDevice *vdev;
+ struct scsi_target *starget;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ unsigned long flags;
+
+
+ rport = starget_to_rport(scsi_target(sdev));
+
+ if (!rport || fc_remote_port_chkready(rport))
+ return -ENXIO;
+
+ hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+
+ 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));
+
+ spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
+
+ if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+ kfree(vdev);
+ return -ENODEV;
+ }
+
+ sdev->hostdata = vdev;
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ if (vtarget->num_luns == 0) {
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
+ MPT_TARGET_FLAGS_VALID_INQUIRY;
+ hd->Targets[sdev->id] = vtarget;
+ }
+
+ vtarget->target_id = vdev->target_id;
+ vtarget->bus_id = vdev->bus_id;
+
+ vdev->vtarget = vtarget;
+ vdev->ioc_id = hd->ioc->id;
+ vdev->lun = sdev->lun;
+ vdev->target_id = ri->pg0.CurrentTargetID;
+ vdev->bus_id = ri->pg0.CurrentBus;
+
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+ ri->vdev = vdev;
+
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+
+ vtarget->num_luns++;
+
+#ifdef MPT_DEBUG
+ printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+ "CurrentTargetID %d, %x %llx %llx\n",
+ sdev->host->host_no,
+ vtarget->num_luns,
+ sdev->id, ri->pg0.CurrentTargetID,
+ ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
+#endif
+
+ return 0;
+}
+
+static int
+mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ int err;
+
+ err = fc_remote_port_chkready(rport);
+ if (unlikely(err)) {
+ SCpnt->result = err;
+ done(SCpnt);
+ return 0;
+ }
+ return mptscsih_qcmd(SCpnt,done);
+}
+
+static void
+mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
+{
+ unsigned class = 0, cos = 0;
+
+ /* don't know what to do as only one scsi (fc) host was allocated */
+ if (portnum != 0)
+ return;
+
+ class = ioc->fc_port_page0[portnum].SupportedServiceClass;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
+ cos |= FC_COS_CLASS1;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
+ cos |= FC_COS_CLASS2;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
+ cos |= FC_COS_CLASS3;
+
+ fc_host_node_name(ioc->sh) =
+ (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
+ | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
+
+ fc_host_port_name(ioc->sh) =
+ (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
+ | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
+
+ fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
+
+ fc_host_supported_classes(ioc->sh) = cos;
+
+ fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
+}
+
+static void
+mptfc_rescan_devices(void *arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+ int ii;
+ int work_to_do;
+ unsigned long flags;
+ struct mptfc_rport_info *ri;
+
+ do {
+ /* start by tagging all ports as missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock,flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * now rescan devices known to adapter,
+ * will reregister existing rports
+ */
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ (void) mptbase_GetFcPortPage0(ioc, ii);
+ mptfc_init_host_attr(ioc,ii); /* refresh */
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+ }
+
+ /* delete devices still missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ /* if newly missing, delete it */
+ if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING))
+ == (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING)) {
+
+ ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+ MPT_RPORT_INFO_FLAGS_MISSING);
+ fc_remote_port_delete(ri->rport);
+ /*
+ * remote port not really deleted 'cause
+ * binding is by WWPN and driver only
+ * registers FCP_TARGETs
+ */
+ #ifdef MPT_DEBUG
+ printk ("mptfc_rescan.%d: %llx deleted\n",
+ ioc->sh->host_no, ri->pg0.WWPN);
+ #endif
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * allow multiple passes as target state
+ * might have changed during scan
+ */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ if (ioc->fc_rescan_work_count > 2) /* only need one more */
+ ioc->fc_rescan_work_count = 2;
+ work_to_do = --ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ } while (work_to_do);
+}
+
static int
mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -148,17 +624,16 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
-
+
if ((r = mpt_attach(pdev,id)) != 0)
return r;
-
+
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptfcDoneCtx;
ioc->TaskCtx = mptfcTaskCtx;
@@ -194,7 +669,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 0;
+ return -ENODEV;
}
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -207,6 +682,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_mptfc_probe;
}
+ INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
+
spin_lock_irqsave(&ioc->FreeQlock, flags);
/* Attach the SCSI Host to the IOC structure
@@ -268,36 +745,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* 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) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
goto out_mptfc_probe;
}
- 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));
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+ ioc->name, hd->ScsiLookup));
/* 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) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
goto out_mptfc_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtTarget **) mem;
-
- dprintk((KERN_INFO
- " vdev @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -332,6 +800,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
+ sh->transportt = mptfc_transport_template;
error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) {
dprintk((KERN_ERR MYNAM
@@ -339,7 +808,11 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_mptfc_probe;
}
- scsi_scan_host(sh);
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ mptfc_init_host_attr(ioc,ii);
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+ }
+
return 0;
out_mptfc_probe:
@@ -352,7 +825,7 @@ static struct pci_driver mptfc_driver = {
.name = "mptfc",
.id_table = mptfc_pci_table,
.probe = mptfc_probe,
- .remove = __devexit_p(mptscsih_remove),
+ .remove = __devexit_p(mptfc_remove),
.shutdown = mptscsih_shutdown,
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
@@ -370,9 +843,20 @@ static struct pci_driver mptfc_driver = {
static int __init
mptfc_init(void)
{
+ int error;
show_mptmod_ver(my_NAME, my_VERSION);
+ /* sanity check module parameter */
+ if (mptfc_dev_loss_tmo == 0)
+ mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
+
+ mptfc_transport_template =
+ fc_attach_transport(&mptfc_transport_functions);
+
+ if (!mptfc_transport_template)
+ return -ENODEV;
+
mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
@@ -387,7 +871,33 @@ mptfc_init(void)
": Registered for IOC reset notifications\n"));
}
- return pci_register_driver(&mptfc_driver);
+ error = pci_register_driver(&mptfc_driver);
+ if (error) {
+ fc_release_transport(mptfc_transport_template);
+ }
+
+ return error;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptfc_remove - Removed fc infrastructure for devices
+ * @pdev: Pointer to pci_dev structure
+ *
+ */
+static void __devexit mptfc_remove(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct mptfc_rport_info *p, *n;
+
+ fc_remove_host(ioc->sh);
+
+ list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
+ list_del(&p->list);
+ kfree(p);
+ }
+
+ mptscsih_remove(pdev);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -400,7 +910,8 @@ static void __exit
mptfc_exit(void)
{
pci_unregister_driver(&mptfc_driver);
-
+ fc_release_transport(mptfc_transport_template);
+
mpt_reset_deregister(mptfcDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 014085d8ec85..73f59528212a 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev)
goto out;
priv->mpt_txfidx_tail = -1;
- priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),
+ priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),
GFP_KERNEL);
if (priv->SendCtl == NULL)
goto out_mpt_txfidx;
- for (i = 0; i < priv->tx_max_out; i++) {
- memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
+ for (i = 0; i < priv->tx_max_out; i++)
priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
- }
dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
@@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev)
goto out_SendCtl;
priv->mpt_rxfidx_tail = -1;
- priv->RcvCtl = kmalloc(priv->max_buckets_out *
- sizeof(struct BufferControl),
+ priv->RcvCtl = kcalloc(priv->max_buckets_out,
+ sizeof(struct BufferControl),
GFP_KERNEL);
if (priv->RcvCtl == NULL)
goto out_mpt_rxfidx;
- for (i = 0; i < priv->max_buckets_out; i++) {
- memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
+ for (i = 0; i < priv->max_buckets_out; i++)
priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
- }
/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
/**/ for (i = 0; i < priv->tx_max_out; i++)
@@ -848,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static inline void
+static void
mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
/*
* @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue
@@ -870,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static inline int
+static int
mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb)
{
struct mpt_lan_priv *priv = dev->priv;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 17e9757e728b..5a06d8d8694e 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
- * Copyright (c) 2005 Dell
+ * Copyright (c) 2005-2006 Dell
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */
static int mptsasMgmtCtx = -1;
+enum mptsas_hotplug_action {
+ MPTSAS_ADD_DEVICE,
+ MPTSAS_DEL_DEVICE,
+};
+
+struct mptsas_hotplug_event {
+ struct work_struct work;
+ MPT_ADAPTER *ioc;
+ enum mptsas_hotplug_action event_type;
+ u64 sas_address;
+ u32 channel;
+ u32 id;
+ u32 device_info;
+ u16 handle;
+ u16 parent_handle;
+ u8 phy_id;
+};
+
/*
* SAS topology structures
*
@@ -99,8 +117,8 @@ struct mptsas_devinfo {
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 */
+ u8 id; /* logical target id of this device */
+ u8 channel; /* 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 */
@@ -114,6 +132,7 @@ struct mptsas_phyinfo {
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_phy *phy;
struct sas_rphy *rphy;
};
@@ -239,13 +258,12 @@ mptsas_slave_alloc(struct scsi_device *sdev)
struct scsi_target *starget;
int i;
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ vdev = kzalloc(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->ioc_id = hd->ioc->id;
sdev->hostdata = vdev;
starget = scsi_target(sdev);
@@ -256,19 +274,32 @@ mptsas_slave_alloc(struct scsi_device *sdev)
hd->Targets[sdev->id] = vtarget;
}
+ /*
+ RAID volumes placed beyond the last expected port.
+ */
+ if (sdev->channel == hd->ioc->num_ports) {
+ vdev->target_id = sdev->id;
+ vdev->bus_id = 0;
+ vdev->lun = 0;
+ goto out;
+ }
+
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+ mutex_lock(&hd->ioc->sas_topology_mutex);
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;
+ p->phy_info[i].attached.id;
+ vdev->bus_id = p->phy_info[i].attached.channel;
vdev->lun = sdev->lun;
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
goto out;
}
}
}
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
printk("No matching SAS device found!!\n");
kfree(vdev);
@@ -282,6 +313,42 @@ mptsas_slave_alloc(struct scsi_device *sdev)
return 0;
}
+static void
+mptsas_slave_destroy(struct scsi_device *sdev)
+{
+ struct Scsi_Host *host = sdev->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ struct sas_rphy *rphy;
+ struct mptsas_portinfo *p;
+ int i;
+
+ /*
+ * Handle hotplug removal case.
+ * We need to clear out attached data structure.
+ */
+ rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+
+ mutex_lock(&hd->ioc->sas_topology_mutex);
+ 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) {
+ memset(&p->phy_info[i].attached, 0,
+ sizeof(struct mptsas_devinfo));
+ p->phy_info[i].rphy = NULL;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
+ /*
+ * TODO: Issue target reset to flush firmware outstanding commands.
+ */
+ mptscsih_slave_destroy(sdev);
+}
+
static struct scsi_host_template mptsas_driver_template = {
.module = THIS_MODULE,
.proc_name = "mptsas",
@@ -293,7 +360,7 @@ static struct scsi_host_template mptsas_driver_template = {
.slave_alloc = mptsas_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.target_destroy = mptscsih_target_destroy,
- .slave_destroy = mptscsih_slave_destroy,
+ .slave_destroy = mptsas_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
@@ -399,7 +466,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
return -ENXIO;
- if (down_interruptible(&ioc->sas_mgmt.mutex))
+ if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
goto out;
mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
@@ -450,7 +517,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
error = 0;
out_unlock:
- up(&ioc->sas_mgmt.mutex);
+ mutex_unlock(&ioc->sas_mgmt.mutex);
out:
return error;
}
@@ -649,8 +716,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
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;
+ device_info->id = buffer->TargetID;
+ device_info->channel = buffer->Bus;
memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
device_info->sas_address = le64_to_cpu(sas_address);
device_info->device_info =
@@ -858,36 +925,36 @@ mptsas_parse_device_info(struct sas_identify *identify,
static int mptsas_probe_one_phy(struct device *dev,
struct mptsas_phyinfo *phy_info, int index, int local)
{
- struct sas_phy *port;
+ struct sas_phy *phy;
int error;
- port = sas_phy_alloc(dev, index);
- if (!port)
+ phy = sas_phy_alloc(dev, index);
+ if (!phy)
return -ENOMEM;
- port->port_identifier = phy_info->port_id;
- mptsas_parse_device_info(&port->identify, &phy_info->identify);
+ phy->port_identifier = phy_info->port_id;
+ mptsas_parse_device_info(&phy->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;
+ phy->negotiated_linkrate = SAS_PHY_DISABLED;
break;
case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
- port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+ phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
break;
case MPI_SAS_IOUNIT0_RATE_1_5:
- port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->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;
+ phy->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;
+ phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
break;
}
@@ -896,10 +963,10 @@ static int mptsas_probe_one_phy(struct device *dev,
*/
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;
+ phy->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;
+ phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -911,10 +978,10 @@ static int mptsas_probe_one_phy(struct device *dev,
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;
+ phy->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;
+ phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -925,10 +992,10 @@ static int mptsas_probe_one_phy(struct device *dev,
*/
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;
+ phy->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;
+ phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -940,28 +1007,29 @@ static int mptsas_probe_one_phy(struct device *dev,
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;
+ phy->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;
+ phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
}
if (local)
- port->local_attached = 1;
+ phy->local_attached = 1;
- error = sas_phy_add(port);
+ error = sas_phy_add(phy);
if (error) {
- sas_phy_free(port);
+ sas_phy_free(phy);
return error;
}
+ phy_info->phy = phy;
if (phy_info->attached.handle) {
struct sas_rphy *rphy;
- rphy = sas_rphy_alloc(port);
+ rphy = sas_rphy_alloc(phy);
if (!rphy)
return 0; /* non-fatal: an rphy can be added later */
@@ -985,16 +1053,19 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
u32 handle = 0xFFFF;
int error = -ENOMEM, i;
- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ port_info = kzalloc(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;
+ ioc->num_ports = port_info->num_phys;
+ mutex_lock(&ioc->sas_topology_mutex);
list_add_tail(&port_info->list, &ioc->sas_topology);
+ mutex_unlock(&ioc->sas_topology_mutex);
+
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 <<
@@ -1034,10 +1105,9 @@ 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);
+ port_info = kzalloc(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 <<
@@ -1047,7 +1117,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
*handle = port_info->handle;
+ mutex_lock(&ioc->sas_topology_mutex);
list_add_tail(&port_info->list, &ioc->sas_topology);
+ mutex_unlock(&ioc->sas_topology_mutex);
+
for (i = 0; i < port_info->num_phys; i++) {
struct device *parent;
@@ -1079,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
* HBA phys.
*/
parent = &ioc->sh->shost_gendev;
+ mutex_lock(&ioc->sas_topology_mutex);
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 ==
@@ -1086,6 +1160,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
parent = &p->phy_info[j].rphy->dev;
}
}
+ mutex_unlock(&ioc->sas_topology_mutex);
mptsas_probe_one_phy(parent, &port_info->phy_info[i],
*index, 0);
@@ -1111,6 +1186,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
;
}
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_devinfo device_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i, error;
+
+ /*
+ * Retrieve the parent sas_address
+ */
+ error = mptsas_sas_device_pg0(ioc, &device_info,
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ parent_handle);
+ if (error) {
+ printk("mptsas: failed to retrieve device page\n");
+ return NULL;
+ }
+
+ /*
+ * The phy_info structures are never deallocated during lifetime of
+ * a host, so the code below is safe without additional refcounting.
+ */
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].identify.sas_address ==
+ device_info.sas_address &&
+ port_info->phy_info[i].phy_id == phy_id) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i;
+
+ /*
+ * The phy_info structures are never deallocated during lifetime of
+ * a host, so the code below is safe without additional refcounting.
+ */
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].attached.handle == handle) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ return phy_info;
+}
+
+static void
+mptsas_hotplug_work(void *arg)
+{
+ struct mptsas_hotplug_event *ev = arg;
+ MPT_ADAPTER *ioc = ev->ioc;
+ struct mptsas_phyinfo *phy_info;
+ struct sas_rphy *rphy;
+ char *ds = NULL;
+
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ ds = "ssp";
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "stp";
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "sata";
+
+ switch (ev->event_type) {
+ case MPTSAS_DEL_DEVICE:
+ printk(MYIOC_s_INFO_FMT
+ "removing %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+ if (!phy_info) {
+ printk("mptsas: remove event for non-existant PHY.\n");
+ break;
+ }
+
+ if (phy_info->rphy) {
+ sas_rphy_delete(phy_info->rphy);
+ phy_info->rphy = NULL;
+ }
+ break;
+ case MPTSAS_ADD_DEVICE:
+ printk(MYIOC_s_INFO_FMT
+ "attaching %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ phy_info = mptsas_find_phyinfo_by_parent(ioc,
+ ev->parent_handle, ev->phy_id);
+ if (!phy_info) {
+ printk("mptsas: add event for non-existant PHY.\n");
+ break;
+ }
+
+ if (phy_info->rphy) {
+ printk("mptsas: trying to add existing device.\n");
+ break;
+ }
+
+ /* fill attached info */
+ phy_info->attached.handle = ev->handle;
+ phy_info->attached.phy_id = ev->phy_id;
+ phy_info->attached.port_id = phy_info->identify.port_id;
+ phy_info->attached.id = ev->id;
+ phy_info->attached.channel = ev->channel;
+ phy_info->attached.sas_address = ev->sas_address;
+ phy_info->attached.device_info = ev->device_info;
+
+ rphy = sas_rphy_alloc(phy_info->phy);
+ if (!rphy)
+ break; /* non-fatal: an rphy can be added later */
+
+ mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+ if (sas_rphy_add(rphy)) {
+ sas_rphy_free(rphy);
+ break;
+ }
+
+ phy_info->rphy = rphy;
+ break;
+ }
+
+ kfree(ev);
+}
+
+static void
+mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+{
+ struct mptsas_hotplug_event *ev;
+ u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+ __le64 sas_address;
+
+ if ((device_info &
+ (MPI_SAS_DEVICE_INFO_SSP_TARGET |
+ MPI_SAS_DEVICE_INFO_STP_TARGET |
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
+ return;
+
+ if ((sas_event_data->ReasonCode &
+ (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
+ MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
+ return;
+
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ printk(KERN_WARNING "mptsas: lost hotplug event\n");
+ return;
+ }
+
+
+ INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+ ev->ioc = ioc;
+ ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+ ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+ ev->channel = sas_event_data->Bus;
+ ev->id = sas_event_data->TargetID;
+ ev->phy_id = sas_event_data->PhyNum;
+ memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
+ ev->sas_address = le64_to_cpu(sas_address);
+ ev->device_info = device_info;
+
+ if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
+ ev->event_type = MPTSAS_ADD_DEVICE;
+ else
+ ev->event_type = MPTSAS_DEL_DEVICE;
+
+ schedule_work(&ev->work);
+}
+
+static int
+mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+{
+ u8 event = le32_to_cpu(reply->Event) & 0xFF;
+
+ if (!ioc->sh)
+ return 1;
+
+ switch (event) {
+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ mptscsih_send_sas_event(ioc,
+ (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+ return 1; /* currently means nothing really */
+
+ default:
+ return mptscsih_event_process(ioc, reply);
+ }
+}
+
static int
mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -1118,11 +1398,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
@@ -1203,7 +1482,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->unique_id = ioc->id;
INIT_LIST_HEAD(&ioc->sas_topology);
- init_MUTEX(&ioc->sas_mgmt.mutex);
+ mutex_init(&ioc->sas_topology_mutex);
+
+ mutex_init(&ioc->sas_mgmt.mutex);
init_completion(&ioc->sas_mgmt.done);
/* Verify that we won't exceed the maximum
@@ -1244,36 +1525,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* 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) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
goto out_mptsas_probe;
}
- 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));
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+ ioc->name, hd->ScsiLookup));
/* 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) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
goto out_mptsas_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtTarget **) mem;
-
- dprintk((KERN_INFO
- " vtarget @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -1324,6 +1596,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mptsas_scan_sas_topology(ioc);
+ /*
+ Reporting RAID volumes.
+ */
+ if (!ioc->raid_data.pIocPg2)
+ return 0;
+ if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+ return 0;
+ for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
+ scsi_add_device(sh,
+ ioc->num_ports,
+ ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
+ 0);
+ }
+
return 0;
out_mptsas_probe:
@@ -1339,10 +1625,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
sas_remove_host(ioc->sh);
+ mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
list_del(&p->list);
kfree(p);
}
+ mutex_unlock(&ioc->sas_topology_mutex);
mptscsih_remove(pdev);
}
@@ -1393,7 +1681,7 @@ mptsas_init(void)
mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
- if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+ if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 93a16fa3c4ba..cdac5578fdf2 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -893,6 +893,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
* when a lun is disable by mid-layer.
* Do NOT access the referenced scsi_cmnd structure or
* members. Will cause either a paging or NULL ptr error.
+ * (BUT, BUT, BUT, the code does reference it! - mdr)
* @hd: Pointer to a SCSI HOST structure
* @vdevice: per device private data
*
@@ -2162,10 +2163,9 @@ mptscsih_target_alloc(struct scsi_target *starget)
{
VirtTarget *vtarget;
- vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL);
+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
if (!vtarget)
return -ENOMEM;
- memset(vtarget, 0, sizeof(VirtTarget));
starget->hostdata = vtarget;
return 0;
}
@@ -2185,14 +2185,13 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
VirtDevice *vdev;
struct scsi_target *starget;
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ vdev = kzalloc(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->ioc_id = hd->ioc->id;
vdev->target_id = sdev->id;
vdev->bus_id = sdev->channel;
@@ -2559,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
hd->cmdPtr = NULL;
}
- /* 7. Set flag to force DV and re-read IOC Page 3
+ /* 7. SPI: Set flag to force DV and re-read IOC Page 3
*/
if (ioc->bus_type == SPI) {
ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
ddvtprintk(("Set reload IOC Pg3 Flag\n"));
}
+ /* 7. FC: Rescan for blocked rports which might have returned.
+ */
+ else if (ioc->bus_type == FC) {
+ int work_count;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ work_count = ++ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ if (work_count == 1)
+ schedule_work(&ioc->fc_rescan_work);
+ }
dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
}
@@ -2589,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
MPT_SCSI_HOST *hd;
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+ int work_count;
+ unsigned long flags;
devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
ioc->name, event));
@@ -2610,11 +2623,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
/* FIXME! */
break;
+ case MPI_EVENT_RESCAN: /* 06 */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ work_count = ++ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ if (work_count == 1)
+ schedule_work(&ioc->fc_rescan_work);
+ break;
+
/*
* CHECKME! Don't think we need to do
* anything for these, but...
*/
- case MPI_EVENT_RESCAN: /* 06 */
case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
/*
@@ -3954,8 +3974,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
/* Search IOC page 3 to determine if this is hidden physical disk
*/
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
static int
mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
{
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index ce332a6085e5..7dce29277cb7 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -158,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
@@ -288,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* 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) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
goto out_mptspi_probe;
}
- 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));
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+ ioc->name, hd->ScsiLookup));
/* 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) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
goto out_mptspi_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtTarget **) mem;
-
- dprintk((KERN_INFO
- " vdev @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags
*/
diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl
index 73dd084c0e98..65c0c47aeb79 100644
--- a/drivers/message/i2o/README.ioctl
+++ b/drivers/message/i2o/README.ioctl
@@ -185,7 +185,7 @@ VII. Getting Parameters
ENOMEM Kernel memory allocation error
A return value of 0 does not mean that the value was actually
- properly retreived. The user should check the result list
+ properly retrieved. The user should check the result list
to determine the specific status of the transaction.
VIII. Downloading Software
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 5b1febed3133..b09fb6307153 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -662,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file)
return 0;
}
+static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ i2o_block_biosparam(get_capacity(bdev->bd_disk),
+ &geo->cylinders, &geo->heads, &geo->sectors);
+ return 0;
+}
+
/**
* i2o_block_ioctl - Issue device specific ioctl calls.
* @cmd: ioctl command
@@ -676,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2o_block_device *dev = disk->private_data;
- void __user *argp = (void __user *)arg;
/* Anyone capable of this syscall can do *real bad* things */
@@ -684,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
return -EPERM;
switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry g;
- i2o_block_biosparam(get_capacity(disk),
- &g.cylinders, &g.heads, &g.sectors);
- g.start = get_start_sect(inode->i_bdev);
- return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
- }
-
case BLKI2OGRSTRAT:
return put_user(dev->rcache, (int __user *)arg);
case BLKI2OGWSTRAT:
@@ -962,6 +959,7 @@ static struct block_device_operations i2o_block_fops = {
.open = i2o_block_open,
.release = i2o_block_release,
.ioctl = i2o_block_ioctl,
+ .getgeo = i2o_block_getgeo,
.media_changed = i2o_block_media_changed
};
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index c5b656cdea7c..d698d7709c31 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -88,11 +88,6 @@ 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)) {
@@ -319,6 +314,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
return rc;
}
+ if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+ printk(KERN_ERR "i2o: device already claimed\n");
+ return -ENODEV;
+ }
+
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
pci_name(pdev));
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 55ba23075c90..75f401d52fda 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device *dev)
static struct bus_type mcp_bus_type = {
.name = "mcp",
.match = mcp_bus_match,
+ .probe = mcp_bus_probe,
+ .remove = mcp_bus_remove,
.suspend = mcp_bus_suspend,
.resume = mcp_bus_resume,
};
@@ -227,8 +229,6 @@ 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);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index e335d54c4659..aff83f966803 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -24,14 +24,14 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include <asm/dma.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
#include "ucb1x00.h"
-static DECLARE_MUTEX(ucb1x00_sem);
+static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
@@ -507,14 +507,14 @@ static int ucb1x00_probe(struct mcp *mcp)
goto err_free;
}
- ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb);
+ ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING,
+ "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);
@@ -522,12 +522,12 @@ static int ucb1x00_probe(struct mcp *mcp)
goto err_irq;
INIT_LIST_HEAD(&ucb->devs);
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
list_add(&ucb->node, &ucb1x00_devices);
list_for_each_entry(drv, &ucb1x00_drivers, node) {
ucb1x00_add_dev(ucb, drv);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
goto out;
err_irq:
@@ -545,13 +545,13 @@ static void ucb1x00_remove(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct list_head *l, *n;
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
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);
+ mutex_unlock(&ucb1x00_mutex);
free_irq(ucb->irq, ucb);
class_device_unregister(&ucb->cdev);
@@ -562,12 +562,12 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv)
struct ucb1x00 *ucb;
INIT_LIST_HEAD(&drv->devs);
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
list_add(&drv->node, &ucb1x00_drivers);
list_for_each_entry(ucb, &ucb1x00_devices, node) {
ucb1x00_add_dev(ucb, drv);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
return 0;
}
@@ -575,13 +575,13 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
{
struct list_head *n, *l;
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
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);
+ mutex_unlock(&ucb1x00_mutex);
}
static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
@@ -589,12 +589,12 @@ 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);
+ mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->suspend)
dev->drv->suspend(dev, state);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
return 0;
}
@@ -603,12 +603,12 @@ static int ucb1x00_resume(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev;
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->resume)
dev->drv->resume(dev);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
return 0;
}
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 551061c2eadf..79fd062ccb34 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -32,7 +32,6 @@
#include <linux/suspend.h>
#include <linux/slab.h>
#include <linux/kthread.h>
-#include <linux/delay.h>
#include <asm/dma.h>
#include <asm/semaphore.h>
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index d7e20a34f88d..1cef2387fa65 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -141,8 +141,8 @@ struct reverse_heartbeat {
};
struct ibmasm_remote {
- struct input_dev keybd_dev;
- struct input_dev mouse_dev;
+ struct input_dev *keybd_dev;
+ struct input_dev *mouse_dev;
};
struct service_processor {
@@ -157,7 +157,7 @@ struct service_processor {
char dirname[IBMASM_NAME_SIZE];
char devname[IBMASM_NAME_SIZE];
unsigned int number;
- struct ibmasm_remote *remote;
+ struct ibmasm_remote remote;
int serial_line;
struct device *dev;
};
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index d3c48d23ee51..0f9e3aa34d07 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -203,9 +203,9 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
print_input(&input);
if (input.type == INPUT_TYPE_MOUSE) {
- send_mouse_event(&sp->remote->mouse_dev, regs, &input);
+ send_mouse_event(sp->remote.mouse_dev, regs, &input);
} else if (input.type == INPUT_TYPE_KEYBOARD) {
- send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
+ send_keyboard_event(sp->remote.keybd_dev, regs, &input);
} else
break;
@@ -217,56 +217,71 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
int ibmasm_init_remote_input_dev(struct service_processor *sp)
{
/* set up the mouse input device */
- struct ibmasm_remote *remote;
+ struct input_dev *mouse_dev, *keybd_dev;
struct pci_dev *pdev = to_pci_dev(sp->dev);
+ int error = -ENOMEM;
int i;
- sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
- if (!remote)
- return -ENOMEM;
+ sp->remote.mouse_dev = mouse_dev = input_allocate_device();
+ sp->remote.keybd_dev = keybd_dev = input_allocate_device();
- memset(remote, 0, sizeof(*remote));
+ if (!mouse_dev || !keybd_dev)
+ goto err_free_devices;
- remote->mouse_dev.private = remote;
- init_input_dev(&remote->mouse_dev);
- remote->mouse_dev.id.vendor = pdev->vendor;
- remote->mouse_dev.id.product = pdev->device;
- remote->mouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
+ mouse_dev->id.bustype = BUS_PCI;
+ mouse_dev->id.vendor = pdev->vendor;
+ mouse_dev->id.product = pdev->device;
+ mouse_dev->id.version = 1;
+ mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
- remote->mouse_dev.name = remote_mouse_name;
- input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
- input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
+ set_bit(BTN_TOUCH, mouse_dev->keybit);
+ mouse_dev->name = remote_mouse_name;
+ input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
+ input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
- remote->keybd_dev.private = remote;
- init_input_dev(&remote->keybd_dev);
- remote->keybd_dev.id.vendor = pdev->vendor;
- remote->keybd_dev.id.product = pdev->device;
- remote->keybd_dev.evbit[0] = BIT(EV_KEY);
- remote->keybd_dev.name = remote_keybd_name;
+ mouse_dev->id.bustype = BUS_PCI;
+ keybd_dev->id.vendor = pdev->vendor;
+ keybd_dev->id.product = pdev->device;
+ mouse_dev->id.version = 2;
+ keybd_dev->evbit[0] = BIT(EV_KEY);
+ keybd_dev->name = remote_keybd_name;
- for (i=0; i<XLATE_SIZE; i++) {
+ for (i = 0; i < XLATE_SIZE; i++) {
if (xlate_high[i])
- set_bit(xlate_high[i], remote->keybd_dev.keybit);
+ set_bit(xlate_high[i], keybd_dev->keybit);
if (xlate[i])
- set_bit(xlate[i], remote->keybd_dev.keybit);
+ set_bit(xlate[i], keybd_dev->keybit);
}
- input_register_device(&remote->mouse_dev);
- input_register_device(&remote->keybd_dev);
+ error = input_register_device(mouse_dev);
+ if (error)
+ goto err_free_devices;
+
+ error = input_register_device(keybd_dev);
+ if (error)
+ goto err_unregister_mouse_dev;
+
enable_mouse_interrupts(sp);
printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
return 0;
+
+ err_unregister_mouse_dev:
+ input_unregister_device(mouse_dev);
+ mouse_dev = NULL; /* so we don't try to free it again below */
+ err_free_devices:
+ input_free_device(mouse_dev);
+ input_free_device(keybd_dev);
+
+ return error;
}
void ibmasm_free_remote_input_dev(struct service_processor *sp)
{
disable_mouse_interrupts(sp);
- input_unregister_device(&sp->remote->keybd_dev);
- input_unregister_device(&sp->remote->mouse_dev);
- kfree(sp->remote);
+ input_unregister_device(sp->remote.mouse_dev);
+ input_unregister_device(sp->remote.keybd_dev);
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index eb41391e06e9..bfca5c176e88 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -495,6 +495,7 @@ static void mmc_decode_cid(struct mmc_card *card)
case 2: /* MMC v2.0 - v2.2 */
case 3: /* MMC v3.1 - v3.3 */
+ case 4: /* MMC v4 */
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);
@@ -550,6 +551,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
} else {
/*
* We only understand CSD structure v1.1 and v1.2.
@@ -579,6 +585,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
}
}
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 8e380c14bf65..5b014c370e80 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -28,6 +28,7 @@
#include <linux/kdev_t.h>
#include <linux/blkdev.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/mutex.h>
#include <linux/mmc/card.h>
#include <linux/mmc/protocol.h>
@@ -54,41 +55,36 @@ struct mmc_blk_data {
unsigned int usage;
unsigned int block_bits;
+ unsigned int read_only;
};
-static DECLARE_MUTEX(open_lock);
+static DEFINE_MUTEX(open_lock);
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
struct mmc_blk_data *md;
- down(&open_lock);
+ mutex_lock(&open_lock);
md = disk->private_data;
if (md && md->usage == 0)
md = NULL;
if (md)
md->usage++;
- up(&open_lock);
+ mutex_unlock(&open_lock);
return md;
}
static void mmc_blk_put(struct mmc_blk_data *md)
{
- down(&open_lock);
+ mutex_lock(&open_lock);
md->usage--;
if (md->usage == 0) {
put_disk(md->disk);
mmc_cleanup_queue(&md->queue);
kfree(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);
+ mutex_unlock(&open_lock);
}
static int mmc_blk_open(struct inode *inode, struct file *filp)
@@ -102,8 +98,7 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
check_disk_change(inode->i_bdev);
ret = 0;
- if ((filp->f_mode & FMODE_WRITE) &&
- mmc_blk_readonly(md->queue.card))
+ if ((filp->f_mode & FMODE_WRITE) && md->read_only)
ret = -EROFS;
}
@@ -119,31 +114,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp)
}
static int
-mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct block_device *bdev = inode->i_bdev;
-
- if (cmd == HDIO_GETGEO) {
- struct hd_geometry geo;
-
- memset(&geo, 0, sizeof(struct hd_geometry));
-
- geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
- geo.heads = 4;
- geo.sectors = 16;
- geo.start = get_start_sect(bdev);
-
- return copy_to_user((void __user *)arg, &geo, sizeof(geo))
- ? -EFAULT : 0;
- }
-
- return -ENOTTY;
+ geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
+ geo->heads = 4;
+ geo->sectors = 16;
+ return 0;
}
static struct block_device_operations mmc_bdops = {
.open = mmc_blk_open,
.release = mmc_blk_release,
- .ioctl = mmc_blk_ioctl,
+ .getgeo = mmc_blk_getgeo,
.owner = THIS_MODULE,
};
@@ -206,7 +188,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.data.flags |= MMC_DATA_WRITE;
brq.data.blocks = 1;
}
- brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
+
+ if (brq.data.blocks > 1) {
+ brq.data.flags |= MMC_DATA_MULTI;
+ brq.mrq.stop = &brq.stop;
+ } else {
+ brq.mrq.stop = NULL;
+ }
brq.data.sg = mq->sg;
brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
@@ -299,6 +287,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
+static inline int mmc_blk_readonly(struct mmc_card *card)
+{
+ return mmc_card_readonly(card) ||
+ !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+}
+
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
{
struct mmc_blk_data *md;
@@ -310,64 +304,121 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
__set_bit(devidx, dev_use);
md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
- if (md) {
- memset(md, 0, sizeof(struct mmc_blk_data));
+ if (!md) {
+ ret = -ENOMEM;
+ goto out;
+ }
- md->disk = alloc_disk(1 << MMC_SHIFT);
- if (md->disk == NULL) {
- kfree(md);
- md = ERR_PTR(-ENOMEM);
- goto out;
- }
+ memset(md, 0, sizeof(struct mmc_blk_data));
- spin_lock_init(&md->lock);
- md->usage = 1;
+ /*
+ * Set the read-only status based on the supported commands
+ * and the write protect switch.
+ */
+ md->read_only = mmc_blk_readonly(card);
- ret = mmc_init_queue(&md->queue, card, &md->lock);
- if (ret) {
- put_disk(md->disk);
- kfree(md);
- md = ERR_PTR(ret);
- goto out;
+ /*
+ * Figure out a workable block size. MMC cards have:
+ * - two block sizes, one for read and one for write.
+ * - may support partial reads and/or writes
+ * (allows block sizes smaller than specified)
+ */
+ md->block_bits = card->csd.read_blkbits;
+ if (card->csd.write_blkbits != card->csd.read_blkbits) {
+ if (card->csd.write_blkbits < card->csd.read_blkbits &&
+ card->csd.read_partial) {
+ /*
+ * write block size is smaller than read block
+ * size, but we support partial reads, so choose
+ * the smaller write block size.
+ */
+ md->block_bits = card->csd.write_blkbits;
+ } else if (card->csd.write_blkbits > card->csd.read_blkbits &&
+ card->csd.write_partial) {
+ /*
+ * read block size is smaller than write block
+ * size, but we support partial writes. Use read
+ * block size.
+ */
+ } else {
+ /*
+ * We don't support this configuration for writes.
+ */
+ printk(KERN_ERR "%s: unable to select block size for "
+ "writing (rb%u wb%u rp%u wp%u)\n",
+ md->disk->disk_name,
+ 1 << card->csd.read_blkbits,
+ 1 << card->csd.write_blkbits,
+ card->csd.read_partial,
+ card->csd.write_partial);
+ md->read_only = 1;
}
- md->queue.prep_fn = mmc_blk_prep_rq;
- md->queue.issue_fn = mmc_blk_issue_rq;
- md->queue.data = md;
+ }
- md->disk->major = major;
- md->disk->first_minor = devidx << MMC_SHIFT;
- md->disk->fops = &mmc_bdops;
- md->disk->private_data = md;
- md->disk->queue = md->queue.queue;
- md->disk->driverfs_dev = &card->dev;
+ /*
+ * Refuse to allow block sizes smaller than 512 bytes.
+ */
+ if (md->block_bits < 9) {
+ printk(KERN_ERR "%s: unable to support block size %u\n",
+ mmc_card_id(card), 1 << md->block_bits);
+ ret = -EINVAL;
+ goto err_kfree;
+ }
- /*
- * As discussed on lkml, GENHD_FL_REMOVABLE should:
- *
- * - be set for removable media with permanent block devices
- * - be unset for removable block devices with permanent media
- *
- * Since MMC block devices clearly fall under the second
- * case, we do not set GENHD_FL_REMOVABLE. Userspace
- * should use the block device creation/destruction hotplug
- * messages to tell when the card is present.
- */
+ md->disk = alloc_disk(1 << MMC_SHIFT);
+ if (md->disk == NULL) {
+ ret = -ENOMEM;
+ goto err_kfree;
+ }
- sprintf(md->disk->disk_name, "mmcblk%d", devidx);
- sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
+ spin_lock_init(&md->lock);
+ md->usage = 1;
- md->block_bits = card->csd.read_blkbits;
+ ret = mmc_init_queue(&md->queue, card, &md->lock);
+ if (ret)
+ goto err_putdisk;
- blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+ md->queue.prep_fn = mmc_blk_prep_rq;
+ md->queue.issue_fn = mmc_blk_issue_rq;
+ md->queue.data = md;
- /*
- * The CSD capacity field is in units of read_blkbits.
- * set_capacity takes units of 512 bytes.
- */
- set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
- }
- out:
+ md->disk->major = major;
+ md->disk->first_minor = devidx << MMC_SHIFT;
+ md->disk->fops = &mmc_bdops;
+ md->disk->private_data = md;
+ md->disk->queue = md->queue.queue;
+ md->disk->driverfs_dev = &card->dev;
+
+ /*
+ * As discussed on lkml, GENHD_FL_REMOVABLE should:
+ *
+ * - be set for removable media with permanent block devices
+ * - be unset for removable block devices with permanent media
+ *
+ * Since MMC block devices clearly fall under the second
+ * case, we do not set GENHD_FL_REMOVABLE. Userspace
+ * should use the block device creation/destruction hotplug
+ * messages to tell when the card is present.
+ */
+
+ sprintf(md->disk->disk_name, "mmcblk%d", devidx);
+ sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
+
+ blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+
+ /*
+ * The CSD capacity field is in units of read_blkbits.
+ * set_capacity takes units of 512 bytes.
+ */
+ set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
return md;
+
+ err_putdisk:
+ put_disk(md->disk);
+ err_kfree:
+ kfree(md);
+ out:
+ return ERR_PTR(ret);
}
static int
@@ -403,12 +454,6 @@ static int mmc_blk_probe(struct mmc_card *card)
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
return -ENODEV;
- if (card->csd.read_blkbits < 9) {
- printk(KERN_WARNING "%s: read blocksize too small (%u)\n",
- mmc_card_id(card), 1 << card->csd.read_blkbits);
- return -ENODEV;
- }
-
md = mmc_blk_alloc(card);
if (IS_ERR(md))
return PTR_ERR(md);
@@ -417,9 +462,10 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
- printk(KERN_INFO "%s: %s %s %luKiB %s\n",
+ printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- get_capacity(md->disk) >> 1, mmc_blk_readonly(card)?"(ro)":"");
+ (unsigned long long)(get_capacity(md->disk) >> 1),
+ md->read_only ? "(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 ec701667abfc..a2a35fd946ee 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device *dev)
return ret;
}
-static struct bus_type mmc_bus_type = {
- .name = "mmc",
- .dev_attrs = mmc_dev_attrs,
- .match = mmc_bus_match,
- .uevent = mmc_bus_uevent,
- .suspend = mmc_bus_suspend,
- .resume = mmc_bus_resume,
-};
-
-
-static int mmc_drv_probe(struct device *dev)
+static int mmc_bus_probe(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device *dev)
return drv->probe(card);
}
-static int mmc_drv_remove(struct device *dev)
+static int mmc_bus_remove(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device *dev)
return 0;
}
+static struct bus_type mmc_bus_type = {
+ .name = "mmc",
+ .dev_attrs = mmc_dev_attrs,
+ .match = mmc_bus_match,
+ .uevent = mmc_bus_uevent,
+ .probe = mmc_bus_probe,
+ .remove = mmc_bus_remove,
+ .suspend = mmc_bus_suspend,
+ .resume = mmc_bus_resume,
+};
/**
* mmc_register_driver - register a media driver
@@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device *dev)
int mmc_register_driver(struct mmc_driver *drv)
{
drv->drv.bus = &mmc_bus_type;
- drv->drv.probe = mmc_drv_probe;
- drv->drv.remove = mmc_drv_remove;
return driver_register(&drv->drv);
}
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 166c9b0ad04e..634ef53e85a5 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -19,13 +19,14 @@
#include <linux/highmem.h>
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
+#include <linux/amba/bus.h>
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
#include <asm/mach/mmc.h>
#include "mmci.h"
@@ -157,6 +158,13 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
data->error = MMC_ERR_FIFO;
status |= MCI_DATAEND;
+
+ /*
+ * We hit an error condition. Ensure that any data
+ * partially written to a page is properly coherent.
+ */
+ if (host->sg_len && data->flags & MMC_DATA_READ)
+ flush_dcache_page(host->sg_ptr->page);
}
if (status & MCI_DATAEND) {
mmci_stop_data(host);
@@ -292,7 +300,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
/*
* Unmap the buffer.
*/
- mmci_kunmap_atomic(host, &flags);
+ mmci_kunmap_atomic(host, buffer, &flags);
host->sg_off += len;
host->size -= len;
@@ -301,6 +309,13 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
if (remain)
break;
+ /*
+ * If we were reading, and we have completed this
+ * page, ensure that the data cache is coherent.
+ */
+ if (status & MCI_RXACTIVE)
+ flush_dcache_page(host->sg_ptr->page);
+
if (!mmci_next_sg(host))
break;
@@ -479,13 +494,9 @@ static int mmci_probe(struct amba_device *dev, void *id)
goto host_free;
}
- ret = clk_use(host->clk);
- if (ret)
- goto clk_free;
-
ret = clk_enable(host->clk);
if (ret)
- goto clk_unuse;
+ goto clk_free;
host->plat = plat;
host->mclk = clk_get_rate(host->clk);
@@ -558,8 +569,6 @@ static int mmci_probe(struct amba_device *dev, void *id)
iounmap(host->base);
clk_disable:
clk_disable(host->clk);
- clk_unuse:
- clk_unuse(host->clk);
clk_free:
clk_put(host->clk);
host_free:
@@ -594,7 +603,6 @@ static int mmci_remove(struct amba_device *dev)
iounmap(host->base);
clk_disable(host->clk);
- clk_unuse(host->clk);
clk_put(host->clk);
mmc_free_host(mmc);
diff --git a/drivers/mmc/mmci.h b/drivers/mmc/mmci.h
index 4589bbd68192..6d7eadc9a678 100644
--- a/drivers/mmc/mmci.h
+++ b/drivers/mmc/mmci.h
@@ -172,8 +172,8 @@ static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flag
return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
}
-static inline void mmci_kunmap_atomic(struct mmci_host *host, unsigned long *flags)
+static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
{
- kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ);
+ kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
local_irq_restore(*flags);
}
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index c7eb7c269081..f25757625361 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -90,7 +90,7 @@ static int dma = 2;
* Basic functions
*/
-static inline void wbsd_unlock_config(struct wbsd_host* host)
+static inline void wbsd_unlock_config(struct wbsd_host *host)
{
BUG_ON(host->config == 0);
@@ -98,14 +98,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
outb(host->unlock_code, host->config);
}
-static inline void wbsd_lock_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)
+static inline void wbsd_write_config(struct wbsd_host *host, u8 reg, u8 value)
{
BUG_ON(host->config == 0);
@@ -113,7 +113,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
outb(value, host->config + 1);
}
-static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
+static inline u8 wbsd_read_config(struct wbsd_host *host, u8 reg)
{
BUG_ON(host->config == 0);
@@ -121,13 +121,13 @@ static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
return inb(host->config + 1);
}
-static inline void wbsd_write_index(struct wbsd_host* host, u8 index, u8 value)
+static inline void wbsd_write_index(struct wbsd_host *host, u8 index, u8 value)
{
outb(index, host->base + WBSD_IDXR);
outb(value, host->base + WBSD_DATAR);
}
-static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
+static inline u8 wbsd_read_index(struct wbsd_host *host, u8 index)
{
outb(index, host->base + WBSD_IDXR);
return inb(host->base + WBSD_DATAR);
@@ -137,7 +137,7 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
* Common routines
*/
-static void wbsd_init_device(struct wbsd_host* host)
+static void wbsd_init_device(struct wbsd_host *host)
{
u8 setup, ier;
@@ -197,7 +197,7 @@ static void wbsd_init_device(struct wbsd_host* host)
inb(host->base + WBSD_ISR);
}
-static void wbsd_reset(struct wbsd_host* host)
+static void wbsd_reset(struct wbsd_host *host)
{
u8 setup;
@@ -211,14 +211,13 @@ static void wbsd_reset(struct wbsd_host* host)
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
}
-static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
+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)
- {
+ if (host->dma >= 0) {
/*
* Release ISA DMA controller.
*/
@@ -247,7 +246,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
* Scatter/gather functions
*/
-static inline void wbsd_init_sg(struct wbsd_host* host, struct mmc_data* data)
+static inline void wbsd_init_sg(struct wbsd_host *host, struct mmc_data *data)
{
/*
* Get info. about SG list from data structure.
@@ -259,7 +258,7 @@ static inline void wbsd_init_sg(struct wbsd_host* host, struct mmc_data* data)
host->remain = host->cur_sg->length;
}
-static inline int wbsd_next_sg(struct wbsd_host* host)
+static inline int wbsd_next_sg(struct wbsd_host *host)
{
/*
* Skip to next SG entry.
@@ -270,33 +269,32 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
/*
* Any entries left?
*/
- if (host->num_sg > 0)
- {
- host->offset = 0;
- host->remain = host->cur_sg->length;
- }
+ if (host->num_sg > 0) {
+ host->offset = 0;
+ host->remain = host->cur_sg->length;
+ }
return host->num_sg;
}
-static inline char* wbsd_kmap_sg(struct wbsd_host* host)
+static inline char *wbsd_kmap_sg(struct wbsd_host *host)
{
host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) +
host->cur_sg->offset;
return host->mapped_sg;
}
-static inline void wbsd_kunmap_sg(struct wbsd_host* host)
+static inline void wbsd_kunmap_sg(struct wbsd_host *host)
{
kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
}
-static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
+static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
{
unsigned int len, i, size;
- struct scatterlist* sg;
- char* dmabuf = host->dma_buffer;
- char* sgbuf;
+ struct scatterlist *sg;
+ char *dmabuf = host->dma_buffer;
+ char *sgbuf;
size = host->size;
@@ -308,8 +306,7 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
* be the entire list though so make sure that
* we do not transfer too much.
*/
- for (i = 0;i < len;i++)
- {
+ for (i = 0; i < len; i++) {
sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
if (size < sg[i].length)
memcpy(dmabuf, sgbuf, size);
@@ -337,12 +334,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
host->size -= size;
}
-static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
+static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
{
unsigned int len, i, size;
- struct scatterlist* sg;
- char* dmabuf = host->dma_buffer;
- char* sgbuf;
+ struct scatterlist *sg;
+ char *dmabuf = host->dma_buffer;
+ char *sgbuf;
size = host->size;
@@ -354,8 +351,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
* be the entire list though so make sure that
* we do not transfer too much.
*/
- for (i = 0;i < len;i++)
- {
+ for (i = 0; i < len; i++) {
sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
if (size < sg[i].length)
memcpy(sgbuf, dmabuf, size);
@@ -387,46 +383,38 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
* Command handling
*/
-static inline void wbsd_get_short_reply(struct wbsd_host* host,
- struct mmc_command* cmd)
+static inline void wbsd_get_short_reply(struct wbsd_host *host,
+ struct mmc_command *cmd)
{
/*
* Correct response type?
*/
- if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT)
- {
+ if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) {
cmd->error = MMC_ERR_INVALID;
return;
}
- cmd->resp[0] =
- wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
- cmd->resp[0] |=
- wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
- cmd->resp[0] |=
- wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
- cmd->resp[0] |=
- wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
- cmd->resp[1] =
- wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
+ cmd->resp[0] = wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
+ cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
+ cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
+ cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
+ cmd->resp[1] = wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
}
-static inline void wbsd_get_long_reply(struct wbsd_host* host,
- struct mmc_command* cmd)
+static inline void wbsd_get_long_reply(struct wbsd_host *host,
+ struct mmc_command *cmd)
{
int i;
/*
* Correct response type?
*/
- if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG)
- {
+ if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) {
cmd->error = MMC_ERR_INVALID;
return;
}
- for (i = 0;i < 4;i++)
- {
+ for (i = 0; i < 4; i++) {
cmd->resp[i] =
wbsd_read_index(host, WBSD_IDX_RESP1 + i * 4) << 24;
cmd->resp[i] |=
@@ -438,7 +426,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
}
}
-static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
+static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
{
int i;
u8 status, isr;
@@ -456,7 +444,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Send the command (CRC calculated by host).
*/
outb(cmd->opcode, host->base + WBSD_CMDR);
- for (i = 3;i >= 0;i--)
+ for (i = 3; i >= 0; i--)
outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
cmd->error = MMC_ERR_NONE;
@@ -471,8 +459,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
/*
* Do we expect a reply?
*/
- if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE)
- {
+ if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
/*
* Read back status.
*/
@@ -488,8 +475,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC))
cmd->error = MMC_ERR_BADCRC;
/* All ok */
- else
- {
+ else {
if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT)
wbsd_get_short_reply(host, cmd);
else
@@ -504,10 +490,10 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Data functions
*/
-static void wbsd_empty_fifo(struct wbsd_host* host)
+static void wbsd_empty_fifo(struct wbsd_host *host)
{
- struct mmc_data* data = host->mrq->cmd->data;
- char* buffer;
+ struct mmc_data *data = host->mrq->cmd->data;
+ char *buffer;
int i, fsr, fifo;
/*
@@ -522,8 +508,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
* Drain the fifo. This has a tendency to loop longer
* than the FIFO length (usually one block).
*/
- while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY))
- {
+ while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) {
/*
* The size field in the FSR is broken so we have to
* do some guessing.
@@ -535,8 +520,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
else
fifo = 1;
- for (i = 0;i < fifo;i++)
- {
+ for (i = 0; i < fifo; i++) {
*buffer = inb(host->base + WBSD_DFR);
buffer++;
host->offset++;
@@ -547,8 +531,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* Transfer done?
*/
- if (data->bytes_xfered == host->size)
- {
+ if (data->bytes_xfered == host->size) {
wbsd_kunmap_sg(host);
return;
}
@@ -556,15 +539,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* End of scatter list entry?
*/
- if (host->remain == 0)
- {
+ if (host->remain == 0) {
wbsd_kunmap_sg(host);
/*
* Get next entry. Check if last.
*/
- if (!wbsd_next_sg(host))
- {
+ if (!wbsd_next_sg(host)) {
/*
* We should never reach this point.
* It means that we're trying to
@@ -594,10 +575,10 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
tasklet_schedule(&host->fifo_tasklet);
}
-static void wbsd_fill_fifo(struct wbsd_host* host)
+static void wbsd_fill_fifo(struct wbsd_host *host)
{
- struct mmc_data* data = host->mrq->cmd->data;
- char* buffer;
+ struct mmc_data *data = host->mrq->cmd->data;
+ char *buffer;
int i, fsr, fifo;
/*
@@ -613,8 +594,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
* Fill the fifo. This has a tendency to loop longer
* than the FIFO length (usually one block).
*/
- while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL))
- {
+ while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) {
/*
* The size field in the FSR is broken so we have to
* do some guessing.
@@ -626,8 +606,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
else
fifo = 15;
- for (i = 16;i > fifo;i--)
- {
+ for (i = 16; i > fifo; i--) {
outb(*buffer, host->base + WBSD_DFR);
buffer++;
host->offset++;
@@ -638,8 +617,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* Transfer done?
*/
- if (data->bytes_xfered == host->size)
- {
+ if (data->bytes_xfered == host->size) {
wbsd_kunmap_sg(host);
return;
}
@@ -647,15 +625,13 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* End of scatter list entry?
*/
- if (host->remain == 0)
- {
+ if (host->remain == 0) {
wbsd_kunmap_sg(host);
/*
* Get next entry. Check if last.
*/
- if (!wbsd_next_sg(host))
- {
+ if (!wbsd_next_sg(host)) {
/*
* We should never reach this point.
* It means that we're trying to
@@ -684,7 +660,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
tasklet_schedule(&host->fifo_tasklet);
}
-static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
+static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
{
u16 blksize;
u8 setup;
@@ -706,8 +682,10 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
*/
if (data->timeout_ns > 127000000)
wbsd_write_index(host, WBSD_IDX_TAAC, 127);
- else
- wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
+ 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);
@@ -722,23 +700,18 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* Space for CRC must be included in the size.
* Two bytes are needed for each data line.
*/
- if (host->bus_width == MMC_BUS_WIDTH_1)
- {
+ 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)
- {
+ } 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_PBSMSB,
+ ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
- }
- else
- {
+ } else {
data->error = MMC_ERR_INVALID;
return;
}
@@ -755,14 +728,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
/*
* DMA transfer?
*/
- if (host->dma >= 0)
- {
+ if (host->dma >= 0) {
/*
* The buffer for DMA is only 64 kB.
*/
BUG_ON(host->size > 0x10000);
- if (host->size > 0x10000)
- {
+ if (host->size > 0x10000) {
data->error = MMC_ERR_INVALID;
return;
}
@@ -794,9 +765,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* Enable DMA on the host.
*/
wbsd_write_index(host, WBSD_IDX_DMA, WBSD_DMA_ENABLE);
- }
- else
- {
+ } else {
/*
* This flag is used to keep printk
* output to a minimum.
@@ -817,13 +786,10 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* Set up FIFO threshold levels (and fill
* buffer if doing a write).
*/
- if (data->flags & MMC_DATA_READ)
- {
+ if (data->flags & MMC_DATA_READ) {
wbsd_write_index(host, WBSD_IDX_FIFOEN,
WBSD_FIFOEN_FULL | 8);
- }
- else
- {
+ } else {
wbsd_write_index(host, WBSD_IDX_FIFOEN,
WBSD_FIFOEN_EMPTY | 8);
wbsd_fill_fifo(host);
@@ -833,7 +799,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
data->error = MMC_ERR_NONE;
}
-static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
+static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
{
unsigned long dmaflags;
int count;
@@ -851,16 +817,14 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* Wait for the controller to leave data
* transfer state.
*/
- do
- {
+ do {
status = wbsd_read_index(host, WBSD_IDX_STATUS);
} while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
/*
* DMA transfer?
*/
- if (host->dma >= 0)
- {
+ if (host->dma >= 0) {
/*
* Disable DMA on the host.
*/
@@ -878,16 +842,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
/*
* Any leftover data?
*/
- if (count)
- {
+ if (count) {
printk(KERN_ERR "%s: Incomplete DMA transfer. "
"%d bytes left.\n",
mmc_hostname(host->mmc), count);
data->error = MMC_ERR_FAILED;
- }
- else
- {
+ } else {
/*
* Transfer data from DMA buffer to
* SG list.
@@ -910,10 +871,10 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* *
\*****************************************************************************/
-static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
+static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
- struct wbsd_host* host = mmc_priv(mmc);
- struct mmc_command* cmd;
+ struct wbsd_host *host = mmc_priv(mmc);
+ struct mmc_command *cmd;
/*
* Disable tasklets to avoid a deadlock.
@@ -930,8 +891,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
* If there is no card in the slot then
* timeout immediatly.
*/
- if (!(host->flags & WBSD_FCARD_PRESENT))
- {
+ if (!(host->flags & WBSD_FCARD_PRESENT)) {
cmd->error = MMC_ERR_TIMEOUT;
goto done;
}
@@ -939,8 +899,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
/*
* Does the request include data?
*/
- if (cmd->data)
- {
+ if (cmd->data) {
wbsd_prepare_data(host, cmd->data);
if (cmd->data->error != MMC_ERR_NONE)
@@ -954,8 +913,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
* will be finished after the data has
* transfered.
*/
- if (cmd->data && (cmd->error == MMC_ERR_NONE))
- {
+ if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
/*
* Dirty fix for hardware bug.
*/
@@ -973,14 +931,14 @@ done:
spin_unlock_bh(&host->lock);
}
-static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
+static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
- struct wbsd_host* host = mmc_priv(mmc);
+ struct wbsd_host *host = mmc_priv(mmc);
u8 clk, setup, pwr;
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);
+ ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
+ ios->vdd, ios->bus_width);
spin_lock_bh(&host->lock);
@@ -1004,8 +962,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
* Only write to the clock register when
* there is an actual change.
*/
- if (clk != host->clk)
- {
+ if (clk != host->clk) {
wbsd_write_index(host, WBSD_IDX_CLK, clk);
host->clk = clk;
}
@@ -1013,8 +970,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
/*
* Power up card.
*/
- if (ios->power_mode != MMC_POWER_OFF)
- {
+ if (ios->power_mode != MMC_POWER_OFF) {
pwr = inb(host->base + WBSD_CSR);
pwr &= ~WBSD_POWER_N;
outb(pwr, host->base + WBSD_CSR);
@@ -1026,23 +982,19 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
* that needs to be disabled.
*/
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
- if (ios->chip_select == MMC_CS_HIGH)
- {
+ 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
- {
- if (setup & WBSD_DAT3_H)
- {
+ } else {
+ 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);
+ mod_timer(&host->ignore_timer, jiffies + HZ / 100);
}
}
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
@@ -1056,9 +1008,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
spin_unlock_bh(&host->lock);
}
-static int wbsd_get_ro(struct mmc_host* mmc)
+static int wbsd_get_ro(struct mmc_host *mmc)
{
- struct wbsd_host* host = mmc_priv(mmc);
+ struct wbsd_host *host = mmc_priv(mmc);
u8 csr;
spin_lock_bh(&host->lock);
@@ -1096,7 +1048,7 @@ static struct mmc_host_ops wbsd_ops = {
static void wbsd_reset_ignore(unsigned long data)
{
- struct wbsd_host *host = (struct wbsd_host*)data;
+ struct wbsd_host *host = (struct wbsd_host *)data;
BUG_ON(host == NULL);
@@ -1119,7 +1071,7 @@ static void wbsd_reset_ignore(unsigned long data)
* Tasklets
*/
-static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
+static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
{
WARN_ON(!host->mrq);
if (!host->mrq)
@@ -1138,14 +1090,13 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
static void wbsd_tasklet_card(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
+ struct wbsd_host *host = (struct wbsd_host *)param;
u8 csr;
int delay = -1;
spin_lock(&host->lock);
- if (host->flags & WBSD_FIGNORE_DETECT)
- {
+ if (host->flags & WBSD_FIGNORE_DETECT) {
spin_unlock(&host->lock);
return;
}
@@ -1153,23 +1104,18 @@ static void wbsd_tasklet_card(unsigned long param)
csr = inb(host->base + WBSD_CSR);
WARN_ON(csr == 0xff);
- if (csr & WBSD_CARDPRESENT)
- {
- if (!(host->flags & WBSD_FCARD_PRESENT))
- {
+ if (csr & WBSD_CARDPRESENT) {
+ if (!(host->flags & WBSD_FCARD_PRESENT)) {
DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT;
delay = 500;
}
- }
- else if (host->flags & WBSD_FCARD_PRESENT)
- {
+ } else if (host->flags & WBSD_FCARD_PRESENT) {
DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT;
- if (host->mrq)
- {
+ if (host->mrq) {
printk(KERN_ERR "%s: Card removed during transfer!\n",
mmc_hostname(host->mmc));
wbsd_reset(host);
@@ -1193,8 +1139,8 @@ static void wbsd_tasklet_card(unsigned long param)
static void wbsd_tasklet_fifo(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1213,8 +1159,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
/*
* Done?
*/
- if (host->size == data->bytes_xfered)
- {
+ if (host->size == data->bytes_xfered) {
wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
tasklet_schedule(&host->finish_tasklet);
}
@@ -1225,8 +1170,8 @@ end:
static void wbsd_tasklet_crc(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1249,8 +1194,8 @@ end:
static void wbsd_tasklet_timeout(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1273,8 +1218,8 @@ end:
static void wbsd_tasklet_finish(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1294,14 +1239,13 @@ end:
static void wbsd_tasklet_block(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ 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) !=
- WBSD_CRC_OK)
- {
+ WBSD_CRC_OK) {
data = wbsd_get_data(host);
if (!data)
goto end;
@@ -1323,7 +1267,7 @@ end:
static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct wbsd_host* host = dev_id;
+ struct wbsd_host *host = dev_id;
int isr;
isr = inb(host->base + WBSD_ISR);
@@ -1365,10 +1309,10 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
* Allocate/free MMC structure.
*/
-static int __devinit wbsd_alloc_mmc(struct device* dev)
+static int __devinit wbsd_alloc_mmc(struct device *dev)
{
- struct mmc_host* mmc;
- struct wbsd_host* host;
+ struct mmc_host *mmc;
+ struct wbsd_host *host;
/*
* Allocate MMC structure.
@@ -1388,7 +1332,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
mmc->ops = &wbsd_ops;
mmc->f_min = 375000;
mmc->f_max = 24000000;
- mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = MMC_CAP_4_BIT_DATA;
spin_lock_init(&host->lock);
@@ -1424,10 +1368,10 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
return 0;
}
-static void __devexit wbsd_free_mmc(struct device* dev)
+static void __devexit wbsd_free_mmc(struct device *dev)
{
- struct mmc_host* mmc;
- struct wbsd_host* host;
+ struct mmc_host *mmc;
+ struct wbsd_host *host;
mmc = dev_get_drvdata(dev);
if (!mmc)
@@ -1447,7 +1391,7 @@ static void __devexit wbsd_free_mmc(struct device* dev)
* Scan for known chip id:s
*/
-static int __devinit wbsd_scan(struct wbsd_host* host)
+static int __devinit wbsd_scan(struct wbsd_host *host)
{
int i, j, k;
int id;
@@ -1456,13 +1400,11 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
* Iterate through all ports, all codes to
* find hardware that is in our known list.
*/
- for (i = 0;i < sizeof(config_ports)/sizeof(int);i++)
- {
+ for (i = 0; i < ARRAY_SIZE(config_ports); i++) {
if (!request_region(config_ports[i], 2, DRIVER_NAME))
continue;
- for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
- {
+ for (j = 0; j < ARRAY_SIZE(unlock_codes); j++) {
id = 0xFFFF;
host->config = config_ports[i];
@@ -1478,18 +1420,15 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
wbsd_lock_config(host);
- for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
- {
- if (id == valid_ids[k])
- {
+ for (k = 0; k < ARRAY_SIZE(valid_ids); k++) {
+ if (id == valid_ids[k]) {
host->chip_id = id;
return 0;
}
}
- if (id != 0xFFFF)
- {
+ if (id != 0xFFFF) {
DBG("Unknown hardware (id %x) found at %x\n",
id, config_ports[i]);
}
@@ -1508,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
* Allocate/free io port ranges
*/
-static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
+static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
{
if (io & 0x7)
return -EINVAL;
@@ -1521,7 +1460,7 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
return 0;
}
-static void __devexit wbsd_release_regions(struct wbsd_host* host)
+static void __devexit wbsd_release_regions(struct wbsd_host *host)
{
if (host->base)
release_region(host->base, 8);
@@ -1538,7 +1477,7 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
* Allocate/free DMA port and buffer
*/
-static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
+static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
{
if (dma < 0)
return;
@@ -1582,8 +1521,8 @@ kfree:
*/
BUG_ON(1);
- dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
- DMA_BIDIRECTIONAL);
+ 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);
@@ -1597,11 +1536,12 @@ err:
"Falling back on FIFO.\n", dma);
}
-static void __devexit wbsd_release_dma(struct wbsd_host* host)
+static void __devexit wbsd_release_dma(struct wbsd_host *host)
{
- if (host->dma_addr)
- dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
- DMA_BIDIRECTIONAL);
+ if (host->dma_addr) {
+ dma_unmap_single(host->mmc->dev, host->dma_addr,
+ WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+ }
kfree(host->dma_buffer);
if (host->dma >= 0)
free_dma(host->dma);
@@ -1615,7 +1555,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
* Allocate/free IRQ.
*/
-static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
+static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
{
int ret;
@@ -1632,17 +1572,23 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
/*
* Set up tasklets.
*/
- tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host);
- tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host);
- tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host);
- 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);
+ tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
+ (unsigned long)host);
+ tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo,
+ (unsigned long)host);
+ tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc,
+ (unsigned long)host);
+ 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;
}
-static void __devexit wbsd_release_irq(struct wbsd_host* host)
+static void __devexit wbsd_release_irq(struct wbsd_host *host)
{
if (!host->irq)
return;
@@ -1663,7 +1609,7 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
* Allocate all resources for the host.
*/
-static int __devinit wbsd_request_resources(struct wbsd_host* host,
+static int __devinit wbsd_request_resources(struct wbsd_host *host,
int base, int irq, int dma)
{
int ret;
@@ -1694,7 +1640,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
* Release all resources for the host.
*/
-static void __devexit wbsd_release_resources(struct wbsd_host* host)
+static void __devexit wbsd_release_resources(struct wbsd_host *host)
{
wbsd_release_dma(host);
wbsd_release_irq(host);
@@ -1705,7 +1651,7 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host)
* Configure the resources the chip should use.
*/
-static void wbsd_chip_config(struct wbsd_host* host)
+static void wbsd_chip_config(struct wbsd_host *host)
{
wbsd_unlock_config(host);
@@ -1749,7 +1695,7 @@ static void wbsd_chip_config(struct wbsd_host* host)
* Check that configured resources are correct.
*/
-static int wbsd_chip_validate(struct wbsd_host* host)
+static int wbsd_chip_validate(struct wbsd_host *host)
{
int base, irq, dma;
@@ -1789,7 +1735,7 @@ static int wbsd_chip_validate(struct wbsd_host* host)
* Powers down the SD function
*/
-static void wbsd_chip_poweroff(struct wbsd_host* host)
+static void wbsd_chip_poweroff(struct wbsd_host *host)
{
wbsd_unlock_config(host);
@@ -1805,11 +1751,11 @@ static void wbsd_chip_poweroff(struct wbsd_host* host)
* *
\*****************************************************************************/
-static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
+static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
int pnp)
{
- struct wbsd_host* host = NULL;
- struct mmc_host* mmc = NULL;
+ struct wbsd_host *host = NULL;
+ struct mmc_host *mmc = NULL;
int ret;
ret = wbsd_alloc_mmc(dev);
@@ -1823,16 +1769,12 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Scan for hardware.
*/
ret = wbsd_scan(host);
- if (ret)
- {
- if (pnp && (ret == -ENODEV))
- {
+ if (ret) {
+ if (pnp && (ret == -ENODEV)) {
printk(KERN_WARNING DRIVER_NAME
": Unable to confirm device presence. You may "
"experience lock-ups.\n");
- }
- else
- {
+ } else {
wbsd_free_mmc(dev);
return ret;
}
@@ -1842,8 +1784,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Request resources.
*/
ret = wbsd_request_resources(host, io, irq, dma);
- if (ret)
- {
+ if (ret) {
wbsd_release_resources(host);
wbsd_free_mmc(dev);
return ret;
@@ -1852,18 +1793,15 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
/*
* See if chip needs to be configured.
*/
- if (pnp)
- {
- if ((host->config != 0) && !wbsd_chip_validate(host))
- {
+ if (pnp) {
+ if ((host->config != 0) && !wbsd_chip_validate(host)) {
printk(KERN_WARNING DRIVER_NAME
": PnP active but chip not configured! "
"You probably have a buggy BIOS. "
"Configuring chip manually.\n");
wbsd_chip_config(host);
}
- }
- else
+ } else
wbsd_chip_config(host);
/*
@@ -1871,8 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Not tested.
*/
#ifdef CONFIG_PM
- if (host->config)
- {
+ if (host->config) {
wbsd_unlock_config(host);
wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
wbsd_lock_config(host);
@@ -1905,10 +1842,10 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
return 0;
}
-static void __devexit wbsd_shutdown(struct device* dev, int pnp)
+static void __devexit wbsd_shutdown(struct device *dev, int pnp)
{
- struct mmc_host* mmc = dev_get_drvdata(dev);
- struct wbsd_host* host;
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct wbsd_host *host;
if (!mmc)
return;
@@ -1932,12 +1869,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
* Non-PnP
*/
-static int __devinit wbsd_probe(struct platform_device* dev)
+static int __devinit wbsd_probe(struct platform_device *dev)
{
return wbsd_init(&dev->dev, io, irq, dma, 0);
}
-static int __devexit wbsd_remove(struct platform_device* dev)
+static int __devexit wbsd_remove(struct platform_device *dev)
{
wbsd_shutdown(&dev->dev, 0);
@@ -1951,7 +1888,7 @@ static int __devexit wbsd_remove(struct platform_device* dev)
#ifdef CONFIG_PNP
static int __devinit
-wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
+wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
{
int io, irq, dma;
@@ -1970,7 +1907,7 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
}
-static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
+static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
{
wbsd_shutdown(&dev->dev, 1);
}
@@ -1983,37 +1920,54 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
#ifdef CONFIG_PM
-static int wbsd_suspend(struct platform_device *dev, pm_message_t state)
+static int wbsd_suspend(struct wbsd_host *host, pm_message_t state)
+{
+ BUG_ON(host == NULL);
+
+ return mmc_suspend_host(host->mmc, state);
+}
+
+static int wbsd_resume(struct wbsd_host *host)
+{
+ BUG_ON(host == NULL);
+
+ wbsd_init_device(host);
+
+ return mmc_resume_host(host->mmc);
+}
+
+static int wbsd_platform_suspend(struct platform_device *dev,
+ pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
struct wbsd_host *host;
int ret;
- if (!mmc)
+ if (mmc == NULL)
return 0;
- DBG("Suspending...\n");
-
- ret = mmc_suspend_host(mmc, state);
- if (!ret)
- return ret;
+ DBGF("Suspending...\n");
host = mmc_priv(mmc);
+ ret = wbsd_suspend(host, state);
+ if (ret)
+ return ret;
+
wbsd_chip_poweroff(host);
return 0;
}
-static int wbsd_resume(struct platform_device *dev)
+static int wbsd_platform_resume(struct platform_device *dev)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
struct wbsd_host *host;
- if (!mmc)
+ if (mmc == NULL)
return 0;
- DBG("Resuming...\n");
+ DBGF("Resuming...\n");
host = mmc_priv(mmc);
@@ -2024,15 +1978,68 @@ static int wbsd_resume(struct platform_device *dev)
*/
mdelay(5);
- wbsd_init_device(host);
+ return wbsd_resume(host);
+}
+
+#ifdef CONFIG_PNP
+
+static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
+{
+ struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
+ struct wbsd_host *host;
+
+ if (mmc == NULL)
+ return 0;
+
+ DBGF("Suspending...\n");
+
+ host = mmc_priv(mmc);
+
+ return wbsd_suspend(host, state);
+}
+
+static int wbsd_pnp_resume(struct pnp_dev *pnp_dev)
+{
+ struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
+ struct wbsd_host *host;
+
+ if (mmc == NULL)
+ return 0;
+
+ DBGF("Resuming...\n");
+
+ host = mmc_priv(mmc);
+
+ /*
+ * See if chip needs to be configured.
+ */
+ if (host->config != 0) {
+ if (!wbsd_chip_validate(host)) {
+ printk(KERN_WARNING DRIVER_NAME
+ ": PnP active but chip not configured! "
+ "You probably have a buggy BIOS. "
+ "Configuring chip manually.\n");
+ wbsd_chip_config(host);
+ }
+ }
- return mmc_resume_host(mmc);
+ /*
+ * Allow device to initialise itself properly.
+ */
+ mdelay(5);
+
+ return wbsd_resume(host);
}
+#endif /* CONFIG_PNP */
+
#else /* CONFIG_PM */
-#define wbsd_suspend NULL
-#define wbsd_resume NULL
+#define wbsd_platform_suspend NULL
+#define wbsd_platform_resume NULL
+
+#define wbsd_pnp_suspend NULL
+#define wbsd_pnp_resume NULL
#endif /* CONFIG_PM */
@@ -2042,8 +2049,8 @@ static struct platform_driver wbsd_driver = {
.probe = wbsd_probe,
.remove = __devexit_p(wbsd_remove),
- .suspend = wbsd_suspend,
- .resume = wbsd_resume,
+ .suspend = wbsd_platform_suspend,
+ .resume = wbsd_platform_resume,
.driver = {
.name = DRIVER_NAME,
},
@@ -2056,6 +2063,9 @@ static struct pnp_driver wbsd_pnp_driver = {
.id_table = pnp_dev_table,
.probe = wbsd_pnp_probe,
.remove = __devexit_p(wbsd_pnp_remove),
+
+ .suspend = wbsd_pnp_suspend,
+ .resume = wbsd_pnp_resume,
};
#endif /* CONFIG_PNP */
@@ -2075,25 +2085,30 @@ static int __init wbsd_drv_init(void)
#ifdef CONFIG_PNP
- if (!nopnp)
- {
+ if (!nopnp) {
result = pnp_register_driver(&wbsd_pnp_driver);
if (result < 0)
return result;
}
-
#endif /* CONFIG_PNP */
- if (nopnp)
- {
+ if (nopnp) {
result = platform_driver_register(&wbsd_driver);
if (result < 0)
return result;
- wbsd_device = platform_device_register_simple(DRIVER_NAME, -1,
- NULL, 0);
- if (IS_ERR(wbsd_device))
- return PTR_ERR(wbsd_device);
+ wbsd_device = platform_device_alloc(DRIVER_NAME, -1);
+ if (!wbsd_device) {
+ platform_driver_unregister(&wbsd_driver);
+ return -ENOMEM;
+ }
+
+ result = platform_device_add(wbsd_device);
+ if (result) {
+ platform_device_put(wbsd_device);
+ platform_driver_unregister(&wbsd_driver);
+ return result;
+ }
}
return 0;
@@ -2108,8 +2123,7 @@ static void __exit wbsd_drv_exit(void)
#endif /* CONFIG_PNP */
- if (nopnp)
- {
+ if (nopnp) {
platform_device_unregister(wbsd_device);
platform_driver_unregister(&wbsd_driver);
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index eafa23f5cbd6..effa0d7a73ac 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -31,6 +31,7 @@ config MTD_JEDECPROBE
config MTD_GEN_PROBE
tristate
+ select OBSOLETE_INTERMODULE
config MTD_CFI_ADV_OPTIONS
bool "Flash chip driver advanced configuration options"
@@ -259,7 +260,7 @@ config MTD_ABSENT
with this driver will return -ENODEV upon access.
config MTD_OBSOLETE_CHIPS
- depends on MTD && BROKEN
+ depends on MTD
bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
help
This option does not enable any code directly, but will allow you to
@@ -272,7 +273,7 @@ config MTD_OBSOLETE_CHIPS
config MTD_AMDSTD
tristate "AMD compatible flash chip support (non-CFI)"
- depends on MTD && MTD_OBSOLETE_CHIPS
+ depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN
help
This option enables support for flash chips using AMD-compatible
commands, including some which are not CFI-compatible and hence
@@ -290,7 +291,7 @@ config MTD_SHARP
config MTD_JEDEC
tristate "JEDEC device support"
- depends on MTD && MTD_OBSOLETE_CHIPS
+ depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN
help
Enable older older JEDEC flash interface devices for self
programming flash. It is commonly used in older AMD chips. It is
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 9a2aa4033c6a..dd628cb51e31 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -47,6 +47,22 @@ config MTD_MS02NV
accelerator. Say Y here if you have a DECstation 5000/2x0 or a
DECsystem 5900 equipped with such a module.
+config MTD_DATAFLASH
+ tristate "Support for AT45xxx DataFlash"
+ depends on MTD && SPI_MASTER && EXPERIMENTAL
+ help
+ This enables access to AT45xxx DataFlash chips, using SPI.
+ Sometimes DataFlash chips are packaged inside MMC-format
+ cards; at this writing, the MMC stack won't handle those.
+
+config MTD_M25P80
+ tristate "Support for M25 SPI Flash"
+ depends on MTD && SPI_MASTER && EXPERIMENTAL
+ help
+ This enables access to ST M25P80 and similar SPI flash chips,
+ used for program and data storage. Set up your spi devices
+ with the right board-specific platform data.
+
config MTD_SLRAM
tristate "Uncached system RAM"
depends on MTD
@@ -202,6 +218,7 @@ config MTD_DOC2001PLUS
config MTD_DOCPROBE
tristate
select MTD_DOCECC
+ select OBSOLETE_INTERMODULE
config MTD_DOCECC
tristate
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index e38db348057d..7c5ed2178380 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -23,3 +23,5 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
+obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
+obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index be5e88b3888d..e4345cf744a2 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -138,7 +138,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc)
bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
+static int DoC_Command(struct DiskOnChip *doc, unsigned char command,
unsigned char xtraflags)
{
void __iomem *docptr = doc->virtadr;
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index fcb28a6fd89f..681a9c73a2a3 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -103,7 +103,7 @@ static inline int DoC_WaitReady(void __iomem * docptr)
with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline void DoC_Command(void __iomem * docptr, unsigned char command,
+static void DoC_Command(void __iomem * docptr, unsigned char command,
unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 0595cc7324b2..5f57f29efee4 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(void __iomem * docptr)
/* DoC_Command: Send a flash command to the flash chip through the Flash
* command register. Need 2 Write Pipeline Terminates to complete send.
*/
-static inline void DoC_Command(void __iomem * docptr, unsigned char command,
+static void DoC_Command(void __iomem * docptr, unsigned char command,
unsigned char xtraflags)
{
WriteDOC(command, docptr, Mplus_FlashCmd);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
new file mode 100644
index 000000000000..d5f24089be71
--- /dev/null
+++ b/drivers/mtd/devices/m25p80.c
@@ -0,0 +1,582 @@
+/*
+ * MTD SPI driver for ST M25Pxx flash chips
+ *
+ * Author: Mike Lavender, mike@steroidmicros.com
+ *
+ * Copyright (c) 2005, Intec Automation Inc.
+ *
+ * Some parts are based on lart.c by Abraham Van Der Merwe
+ *
+ * Cleaned up and generalized based on mtd_dataflash.c
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <asm/semaphore.h>
+
+
+/* NOTE: AT 25F and SST 25LF series are very similar,
+ * but commands for sector erase and chip id differ...
+ */
+
+#define FLASH_PAGESIZE 256
+
+/* Flash opcodes. */
+#define OPCODE_WREN 6 /* Write enable */
+#define OPCODE_RDSR 5 /* Read status register */
+#define OPCODE_READ 3 /* Read data bytes */
+#define OPCODE_PP 2 /* Page program */
+#define OPCODE_SE 0xd8 /* Sector erase */
+#define OPCODE_RES 0xab /* Read Electronic Signature */
+#define OPCODE_RDID 0x9f /* Read JEDEC ID */
+
+/* Status Register bits. */
+#define SR_WIP 1 /* Write in progress */
+#define SR_WEL 2 /* Write enable latch */
+#define SR_BP0 4 /* Block protect 0 */
+#define SR_BP1 8 /* Block protect 1 */
+#define SR_BP2 0x10 /* Block protect 2 */
+#define SR_SRWD 0x80 /* SR write protect */
+
+/* Define max times to check status register before we give up. */
+#define MAX_READY_WAIT_COUNT 100000
+
+
+#ifdef CONFIG_MTD_PARTITIONS
+#define mtd_has_partitions() (1)
+#else
+#define mtd_has_partitions() (0)
+#endif
+
+/****************************************************************************/
+
+struct m25p {
+ struct spi_device *spi;
+ struct semaphore lock;
+ struct mtd_info mtd;
+ unsigned partitioned;
+ u8 command[4];
+};
+
+static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct m25p, mtd);
+}
+
+/****************************************************************************/
+
+/*
+ * Internal helper functions
+ */
+
+/*
+ * Read the status register, returning its value in the location
+ * Return the status register value.
+ * Returns negative if error occurred.
+ */
+static int read_sr(struct m25p *flash)
+{
+ ssize_t retval;
+ u8 code = OPCODE_RDSR;
+ u8 val;
+
+ retval = spi_write_then_read(flash->spi, &code, 1, &val, 1);
+
+ if (retval < 0) {
+ dev_err(&flash->spi->dev, "error %d reading SR\n",
+ (int) retval);
+ return retval;
+ }
+
+ return val;
+}
+
+
+/*
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
+ */
+static inline int write_enable(struct m25p *flash)
+{
+ u8 code = OPCODE_WREN;
+
+ return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+}
+
+
+/*
+ * Service routine to read status register until ready, or timeout occurs.
+ * Returns non-zero if error.
+ */
+static int wait_till_ready(struct m25p *flash)
+{
+ int count;
+ int sr;
+
+ /* one chip guarantees max 5 msec wait here after page writes,
+ * but potentially three seconds (!) after page erase.
+ */
+ for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
+ if ((sr = read_sr(flash)) < 0)
+ break;
+ else if (!(sr & SR_WIP))
+ return 0;
+
+ /* REVISIT sometimes sleeping would be best */
+ }
+
+ return 1;
+}
+
+
+/*
+ * Erase one sector of flash memory at offset ``offset'' which is any
+ * address within the sector which should be erased.
+ *
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int erase_sector(struct m25p *flash, u32 offset)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
+ __FUNCTION__, offset);
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash))
+ return 1;
+
+ /* Send write enable, then erase commands. */
+ write_enable(flash);
+
+ /* Set up command buffer. */
+ flash->command[0] = OPCODE_SE;
+ flash->command[1] = offset >> 16;
+ flash->command[2] = offset >> 8;
+ flash->command[3] = offset;
+
+ spi_write(flash->spi, flash->command, sizeof(flash->command));
+
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+ * MTD implementation
+ */
+
+/*
+ * Erase an address range on the flash chip. The address range may extend
+ * one or more erase sectors. Return an error is there is a problem erasing.
+ */
+static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ u32 addr,len;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ flash->spi->dev.bus_id, __FUNCTION__, "at",
+ (u32)instr->addr, instr->len);
+
+ /* sanity checks */
+ if (instr->addr + instr->len > flash->mtd.size)
+ return -EINVAL;
+ if ((instr->addr % mtd->erasesize) != 0
+ || (instr->len % mtd->erasesize) != 0) {
+ return -EINVAL;
+ }
+
+ addr = instr->addr;
+ len = instr->len;
+
+ down(&flash->lock);
+
+ /* now erase those sectors */
+ while (len) {
+ if (erase_sector(flash, addr)) {
+ instr->state = MTD_ERASE_FAILED;
+ up(&flash->lock);
+ return -EIO;
+ }
+
+ addr += mtd->erasesize;
+ len -= mtd->erasesize;
+ }
+
+ up(&flash->lock);
+
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return 0;
+}
+
+/*
+ * Read an address range from the flash chip. The address range
+ * may be any size provided it is within the physical boundaries.
+ */
+static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t[2];
+ struct spi_message m;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ flash->spi->dev.bus_id, __FUNCTION__, "from",
+ (u32)from, len);
+
+ /* sanity checks */
+ if (!len)
+ return 0;
+
+ if (from + len > flash->mtd.size)
+ return -EINVAL;
+
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+ t[0].len = sizeof(flash->command);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+ t[1].len = len;
+ spi_message_add_tail(&t[1], &m);
+
+ /* Byte count starts at zero. */
+ if (retlen)
+ *retlen = 0;
+
+ down(&flash->lock);
+
+ /* Wait till previous write/erase is done. */
+ if (wait_till_ready(flash)) {
+ /* REVISIT status return?? */
+ up(&flash->lock);
+ return 1;
+ }
+
+ /* NOTE: OPCODE_FAST_READ (if available) is faster... */
+
+ /* Set up the write data buffer. */
+ flash->command[0] = OPCODE_READ;
+ flash->command[1] = from >> 16;
+ flash->command[2] = from >> 8;
+ flash->command[3] = from;
+
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - sizeof(flash->command);
+
+ up(&flash->lock);
+
+ return 0;
+}
+
+/*
+ * Write an address range to the flash chip. Data must be written in
+ * FLASH_PAGESIZE chunks. The address range may be any size provided
+ * it is within the physical boundaries.
+ */
+static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ u32 page_offset, page_size;
+ struct spi_transfer t[2];
+ struct spi_message m;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ flash->spi->dev.bus_id, __FUNCTION__, "to",
+ (u32)to, len);
+
+ if (retlen)
+ *retlen = 0;
+
+ /* sanity checks */
+ if (!len)
+ return(0);
+
+ if (to + len > flash->mtd.size)
+ return -EINVAL;
+
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+ t[0].len = sizeof(flash->command);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+ spi_message_add_tail(&t[1], &m);
+
+ down(&flash->lock);
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash))
+ return 1;
+
+ write_enable(flash);
+
+ /* Set up the opcode in the write buffer. */
+ flash->command[0] = OPCODE_PP;
+ flash->command[1] = to >> 16;
+ flash->command[2] = to >> 8;
+ flash->command[3] = to;
+
+ /* what page do we start with? */
+ page_offset = to % FLASH_PAGESIZE;
+
+ /* do all the bytes fit onto one page? */
+ if (page_offset + len <= FLASH_PAGESIZE) {
+ t[1].len = len;
+
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - sizeof(flash->command);
+ } else {
+ u32 i;
+
+ /* the size of data remaining on the first page */
+ page_size = FLASH_PAGESIZE - page_offset;
+
+ t[1].len = page_size;
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - sizeof(flash->command);
+
+ /* write everything in PAGESIZE chunks */
+ for (i = page_size; i < len; i += page_size) {
+ page_size = len - i;
+ if (page_size > FLASH_PAGESIZE)
+ page_size = FLASH_PAGESIZE;
+
+ /* write the next page to flash */
+ flash->command[1] = (to + i) >> 16;
+ flash->command[2] = (to + i) >> 8;
+ flash->command[3] = (to + i);
+
+ t[1].tx_buf = buf + i;
+ t[1].len = page_size;
+
+ wait_till_ready(flash);
+
+ write_enable(flash);
+
+ spi_sync(flash->spi, &m);
+
+ if (retlen)
+ *retlen += m.actual_length
+ - sizeof(flash->command);
+ }
+ }
+
+ up(&flash->lock);
+
+ return 0;
+}
+
+
+/****************************************************************************/
+
+/*
+ * SPI device driver setup and teardown
+ */
+
+struct flash_info {
+ char *name;
+ u8 id;
+ u16 jedec_id;
+ unsigned sector_size;
+ unsigned n_sectors;
+};
+
+static struct flash_info __devinitdata m25p_data [] = {
+ /* REVISIT: fill in JEDEC ids, for parts that have them */
+ { "m25p05", 0x05, 0x0000, 32 * 1024, 2 },
+ { "m25p10", 0x10, 0x0000, 32 * 1024, 4 },
+ { "m25p20", 0x11, 0x0000, 64 * 1024, 4 },
+ { "m25p40", 0x12, 0x0000, 64 * 1024, 8 },
+ { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
+ { "m25p16", 0x14, 0x0000, 64 * 1024, 32 },
+ { "m25p32", 0x15, 0x0000, 64 * 1024, 64 },
+ { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
+};
+
+/*
+ * board specific setup should have ensured the SPI clock used here
+ * matches what the READ command supports, at least until this driver
+ * understands FAST_READ (for clocks over 25 MHz).
+ */
+static int __devinit m25p_probe(struct spi_device *spi)
+{
+ struct flash_platform_data *data;
+ struct m25p *flash;
+ struct flash_info *info;
+ unsigned i;
+
+ /* Platform data helps sort out which chip type we have, as
+ * well as how this board partitions it.
+ */
+ data = spi->dev.platform_data;
+ if (!data || !data->type) {
+ /* FIXME some chips can identify themselves with RES
+ * or JEDEC get-id commands. Try them ...
+ */
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
+ flash->spi->dev.bus_id);
+ return -ENODEV;
+ }
+
+ for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
+ if (strcmp(data->type, info->name) == 0)
+ break;
+ }
+ if (i == ARRAY_SIZE(m25p_data)) {
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
+ flash->spi->dev.bus_id, data->type);
+ return -ENODEV;
+ }
+
+ flash = kzalloc(sizeof *flash, SLAB_KERNEL);
+ if (!flash)
+ return -ENOMEM;
+
+ flash->spi = spi;
+ init_MUTEX(&flash->lock);
+ dev_set_drvdata(&spi->dev, flash);
+
+ if (data->name)
+ flash->mtd.name = data->name;
+ else
+ flash->mtd.name = spi->dev.bus_id;
+
+ flash->mtd.type = MTD_NORFLASH;
+ flash->mtd.flags = MTD_CAP_NORFLASH;
+ flash->mtd.size = info->sector_size * info->n_sectors;
+ flash->mtd.erasesize = info->sector_size;
+ flash->mtd.erase = m25p80_erase;
+ flash->mtd.read = m25p80_read;
+ flash->mtd.write = m25p80_write;
+
+ dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
+ flash->mtd.size / 1024);
+
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "mtd .name = %s, .size = 0x%.8x (%uM) "
+ ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
+ flash->mtd.name,
+ flash->mtd.size, flash->mtd.size / (1024*1024),
+ flash->mtd.erasesize, flash->mtd.erasesize / 1024,
+ flash->mtd.numeraseregions);
+
+ if (flash->mtd.numeraseregions)
+ for (i = 0; i < flash->mtd.numeraseregions; i++)
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
+ ".erasesize = 0x%.8x (%uK), "
+ ".numblocks = %d }\n",
+ i, flash->mtd.eraseregions[i].offset,
+ flash->mtd.eraseregions[i].erasesize,
+ flash->mtd.eraseregions[i].erasesize / 1024,
+ flash->mtd.eraseregions[i].numblocks);
+
+
+ /* partitions should match sector boundaries; and it may be good to
+ * use readonly partitions for writeprotected sectors (BP2..BP0).
+ */
+ if (mtd_has_partitions()) {
+ struct mtd_partition *parts = NULL;
+ int nr_parts = 0;
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_probes[] = { "cmdlinepart", NULL, };
+
+ nr_parts = parse_mtd_partitions(&flash->mtd,
+ part_probes, &parts, 0);
+#endif
+
+ if (nr_parts <= 0 && data && data->parts) {
+ parts = data->parts;
+ nr_parts = data->nr_parts;
+ }
+
+ if (nr_parts > 0) {
+ for (i = 0; i < data->nr_parts; i++) {
+ DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+ "{.name = %s, .offset = 0x%.8x, "
+ ".size = 0x%.8x (%uK) }\n",
+ i, data->parts[i].name,
+ data->parts[i].offset,
+ data->parts[i].size,
+ data->parts[i].size / 1024);
+ }
+ flash->partitioned = 1;
+ return add_mtd_partitions(&flash->mtd, parts, nr_parts);
+ }
+ } else if (data->nr_parts)
+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
+ data->nr_parts, data->name);
+
+ return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
+}
+
+
+static int __devexit m25p_remove(struct spi_device *spi)
+{
+ struct m25p *flash = dev_get_drvdata(&spi->dev);
+ int status;
+
+ /* Clean up MTD stuff. */
+ if (mtd_has_partitions() && flash->partitioned)
+ status = del_mtd_partitions(&flash->mtd);
+ else
+ status = del_mtd_device(&flash->mtd);
+ if (status == 0)
+ kfree(flash);
+ return 0;
+}
+
+
+static struct spi_driver m25p80_driver = {
+ .driver = {
+ .name = "m25p80",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = m25p_probe,
+ .remove = __devexit_p(m25p_remove),
+};
+
+
+static int m25p80_init(void)
+{
+ return spi_register_driver(&m25p80_driver);
+}
+
+
+static void m25p80_exit(void)
+{
+ spi_unregister_driver(&m25p80_driver);
+}
+
+
+module_init(m25p80_init);
+module_exit(m25p80_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike Lavender");
+MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
new file mode 100644
index 000000000000..155737e7483f
--- /dev/null
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -0,0 +1,629 @@
+/*
+ * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework
+ *
+ * Largely derived from at91_dataflash.c:
+ * Copyright (C) 2003-2005 SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+*/
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+
+/*
+ * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in
+ * each chip, which may be used for double buffered I/O; but this driver
+ * doesn't (yet) use these for any kind of i/o overlap or prefetching.
+ *
+ * Sometimes DataFlash is packaged in MMC-format cards, although the
+ * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash
+ * protocols during enumeration.
+ */
+
+#define CONFIG_DATAFLASH_WRITE_VERIFY
+
+/* reads can bypass the buffers */
+#define OP_READ_CONTINUOUS 0xE8
+#define OP_READ_PAGE 0xD2
+
+/* group B requests can run even while status reports "busy" */
+#define OP_READ_STATUS 0xD7 /* group B */
+
+/* move data between host and buffer */
+#define OP_READ_BUFFER1 0xD4 /* group B */
+#define OP_READ_BUFFER2 0xD6 /* group B */
+#define OP_WRITE_BUFFER1 0x84 /* group B */
+#define OP_WRITE_BUFFER2 0x87 /* group B */
+
+/* erasing flash */
+#define OP_ERASE_PAGE 0x81
+#define OP_ERASE_BLOCK 0x50
+
+/* move data between buffer and flash */
+#define OP_TRANSFER_BUF1 0x53
+#define OP_TRANSFER_BUF2 0x55
+#define OP_MREAD_BUFFER1 0xD4
+#define OP_MREAD_BUFFER2 0xD6
+#define OP_MWERASE_BUFFER1 0x83
+#define OP_MWERASE_BUFFER2 0x86
+#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */
+#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */
+
+/* write to buffer, then write-erase to flash */
+#define OP_PROGRAM_VIA_BUF1 0x82
+#define OP_PROGRAM_VIA_BUF2 0x85
+
+/* compare buffer to flash */
+#define OP_COMPARE_BUF1 0x60
+#define OP_COMPARE_BUF2 0x61
+
+/* read flash to buffer, then write-erase to flash */
+#define OP_REWRITE_VIA_BUF1 0x58
+#define OP_REWRITE_VIA_BUF2 0x59
+
+/* newer chips report JEDEC manufacturer and device IDs; chip
+ * serial number and OTP bits; and per-sector writeprotect.
+ */
+#define OP_READ_ID 0x9F
+#define OP_READ_SECURITY 0x77
+#define OP_WRITE_SECURITY 0x9A /* OTP bits */
+
+
+struct dataflash {
+ u8 command[4];
+ char name[24];
+
+ unsigned partitioned:1;
+
+ unsigned short page_offset; /* offset in flash address */
+ unsigned int page_size; /* of bytes per page */
+
+ struct semaphore lock;
+ struct spi_device *spi;
+
+ struct mtd_info mtd;
+};
+
+#ifdef CONFIG_MTD_PARTITIONS
+#define mtd_has_partitions() (1)
+#else
+#define mtd_has_partitions() (0)
+#endif
+
+/* ......................................................................... */
+
+/*
+ * Return the status of the DataFlash device.
+ */
+static inline int dataflash_status(struct spi_device *spi)
+{
+ /* NOTE: at45db321c over 25 MHz wants to write
+ * a dummy byte after the opcode...
+ */
+ return spi_w8r8(spi, OP_READ_STATUS);
+}
+
+/*
+ * Poll the DataFlash device until it is READY.
+ * This usually takes 5-20 msec or so; more for sector erase.
+ */
+static int dataflash_waitready(struct spi_device *spi)
+{
+ int status;
+
+ for (;;) {
+ status = dataflash_status(spi);
+ if (status < 0) {
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
+ spi->dev.bus_id, status);
+ status = 0;
+ }
+
+ if (status & (1 << 7)) /* RDY/nBSY */
+ return status;
+
+ msleep(3);
+ }
+}
+
+/* ......................................................................... */
+
+/*
+ * Erase pages of flash.
+ */
+static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ struct spi_device *spi = priv->spi;
+ struct spi_transfer x = { .tx_dma = 0, };
+ struct spi_message msg;
+ unsigned blocksize = priv->page_size << 3;
+ u8 *command;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n",
+ spi->dev.bus_id,
+ instr->addr, instr->len);
+
+ /* Sanity checks */
+ if ((instr->addr + instr->len) > mtd->size
+ || (instr->len % priv->page_size) != 0
+ || (instr->addr % priv->page_size) != 0)
+ return -EINVAL;
+
+ spi_message_init(&msg);
+
+ x.tx_buf = command = priv->command;
+ x.len = 4;
+ spi_message_add_tail(&x, &msg);
+
+ down(&priv->lock);
+ while (instr->len > 0) {
+ unsigned int pageaddr;
+ int status;
+ int do_block;
+
+ /* Calculate flash page address; use block erase (for speed) if
+ * we're at a block boundary and need to erase the whole block.
+ */
+ pageaddr = instr->addr / priv->page_size;
+ do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize;
+ pageaddr = pageaddr << priv->page_offset;
+
+ command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE;
+ command[1] = (u8)(pageaddr >> 16);
+ command[2] = (u8)(pageaddr >> 8);
+ command[3] = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
+ do_block ? "block" : "page",
+ command[0], command[1], command[2], command[3],
+ pageaddr);
+
+ status = spi_sync(spi, &msg);
+ (void) dataflash_waitready(spi);
+
+ if (status < 0) {
+ printk(KERN_ERR "%s: erase %x, err %d\n",
+ spi->dev.bus_id, pageaddr, status);
+ /* REVISIT: can retry instr->retries times; or
+ * giveup and instr->fail_addr = instr->addr;
+ */
+ continue;
+ }
+
+ if (do_block) {
+ instr->addr += blocksize;
+ instr->len -= blocksize;
+ } else {
+ instr->addr += priv->page_size;
+ instr->len -= priv->page_size;
+ }
+ }
+ up(&priv->lock);
+
+ /* Inform MTD subsystem that erase is complete */
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return 0;
+}
+
+/*
+ * Read from the DataFlash device.
+ * from : Start offset in flash device
+ * len : Amount to read
+ * retlen : About of data actually read
+ * buf : Buffer containing the data
+ */
+static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ struct spi_transfer x[2] = { { .tx_dma = 0, }, };
+ struct spi_message msg;
+ unsigned int addr;
+ u8 *command;
+ int status;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
+ priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len));
+
+ *retlen = 0;
+
+ /* Sanity checks */
+ if (!len)
+ return 0;
+ if (from + len > mtd->size)
+ return -EINVAL;
+
+ /* Calculate flash page/byte address */
+ addr = (((unsigned)from / priv->page_size) << priv->page_offset)
+ + ((unsigned)from % priv->page_size);
+
+ command = priv->command;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ spi_message_init(&msg);
+
+ x[0].tx_buf = command;
+ x[0].len = 8;
+ spi_message_add_tail(&x[0], &msg);
+
+ x[1].rx_buf = buf;
+ x[1].len = len;
+ spi_message_add_tail(&x[1], &msg);
+
+ down(&priv->lock);
+
+ /* Continuous read, max clock = f(car) which may be less than
+ * the peak rate available. Some chips support commands with
+ * fewer "don't care" bytes. Both buffers stay unchanged.
+ */
+ command[0] = OP_READ_CONTINUOUS;
+ command[1] = (u8)(addr >> 16);
+ command[2] = (u8)(addr >> 8);
+ command[3] = (u8)(addr >> 0);
+ /* plus 4 "don't care" bytes */
+
+ status = spi_sync(priv->spi, &msg);
+ up(&priv->lock);
+
+ if (status >= 0) {
+ *retlen = msg.actual_length - 8;
+ status = 0;
+ } else
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
+ priv->spi->dev.bus_id,
+ (unsigned)from, (unsigned)(from + len),
+ status);
+ return status;
+}
+
+/*
+ * Write to the DataFlash device.
+ * to : Start offset in flash device
+ * len : Amount to write
+ * retlen : Amount of data actually written
+ * buf : Buffer containing the data
+ */
+static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ struct spi_device *spi = priv->spi;
+ struct spi_transfer x[2] = { { .tx_dma = 0, }, };
+ struct spi_message msg;
+ unsigned int pageaddr, addr, offset, writelen;
+ size_t remaining = len;
+ u_char *writebuf = (u_char *) buf;
+ int status = -EINVAL;
+ u8 *command;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
+ spi->dev.bus_id, (unsigned)to, (unsigned)(to + len));
+
+ *retlen = 0;
+
+ /* Sanity checks */
+ if (!len)
+ return 0;
+ if ((to + len) > mtd->size)
+ return -EINVAL;
+
+ spi_message_init(&msg);
+
+ x[0].tx_buf = command = priv->command;
+ x[0].len = 4;
+ spi_message_add_tail(&x[0], &msg);
+
+ pageaddr = ((unsigned)to / priv->page_size);
+ offset = ((unsigned)to % priv->page_size);
+ if (offset + len > priv->page_size)
+ writelen = priv->page_size - offset;
+ else
+ writelen = len;
+
+ down(&priv->lock);
+ while (remaining > 0) {
+ DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
+ pageaddr, offset, writelen);
+
+ /* REVISIT:
+ * (a) each page in a sector must be rewritten at least
+ * once every 10K sibling erase/program operations.
+ * (b) for pages that are already erased, we could
+ * use WRITE+MWRITE not PROGRAM for ~30% speedup.
+ * (c) WRITE to buffer could be done while waiting for
+ * a previous MWRITE/MWERASE to complete ...
+ * (d) error handling here seems to be mostly missing.
+ *
+ * Two persistent bits per page, plus a per-sector counter,
+ * could support (a) and (b) ... we might consider using
+ * the second half of sector zero, which is just one block,
+ * to track that state. (On AT91, that sector should also
+ * support boot-from-DataFlash.)
+ */
+
+ addr = pageaddr << priv->page_offset;
+
+ /* (1) Maybe transfer partial page to Buffer1 */
+ if (writelen != priv->page_size) {
+ command[0] = OP_TRANSFER_BUF1;
+ command[1] = (addr & 0x00FF0000) >> 16;
+ command[2] = (addr & 0x0000FF00) >> 8;
+ command[3] = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ status = spi_sync(spi, &msg);
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
+ spi->dev.bus_id, addr, status);
+
+ (void) dataflash_waitready(priv->spi);
+ }
+
+ /* (2) Program full page via Buffer1 */
+ addr += offset;
+ command[0] = OP_PROGRAM_VIA_BUF1;
+ command[1] = (addr & 0x00FF0000) >> 16;
+ command[2] = (addr & 0x0000FF00) >> 8;
+ command[3] = (addr & 0x000000FF);
+
+ DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ x[1].tx_buf = writebuf;
+ x[1].len = writelen;
+ spi_message_add_tail(x + 1, &msg);
+ status = spi_sync(spi, &msg);
+ spi_transfer_del(x + 1);
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
+ spi->dev.bus_id, addr, writelen, status);
+
+ (void) dataflash_waitready(priv->spi);
+
+
+#ifdef CONFIG_DATAFLASH_WRITE_VERIFY
+
+ /* (3) Compare to Buffer1 */
+ addr = pageaddr << priv->page_offset;
+ command[0] = OP_COMPARE_BUF1;
+ command[1] = (addr & 0x00FF0000) >> 16;
+ command[2] = (addr & 0x0000FF00) >> 8;
+ command[3] = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ status = spi_sync(spi, &msg);
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
+ spi->dev.bus_id, addr, status);
+
+ status = dataflash_waitready(priv->spi);
+
+ /* Check result of the compare operation */
+ if ((status & (1 << 6)) == 1) {
+ printk(KERN_ERR "%s: compare page %u, err %d\n",
+ spi->dev.bus_id, pageaddr, status);
+ remaining = 0;
+ status = -EIO;
+ break;
+ } else
+ status = 0;
+
+#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */
+
+ remaining = remaining - writelen;
+ pageaddr++;
+ offset = 0;
+ writebuf += writelen;
+ *retlen += writelen;
+
+ if (remaining > priv->page_size)
+ writelen = priv->page_size;
+ else
+ writelen = remaining;
+ }
+ up(&priv->lock);
+
+ return status;
+}
+
+/* ......................................................................... */
+
+/*
+ * Register DataFlash device with MTD subsystem.
+ */
+static int __devinit
+add_dataflash(struct spi_device *spi, char *name,
+ int nr_pages, int pagesize, int pageoffset)
+{
+ struct dataflash *priv;
+ struct mtd_info *device;
+ struct flash_platform_data *pdata = spi->dev.platform_data;
+
+ priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ init_MUTEX(&priv->lock);
+ priv->spi = spi;
+ priv->page_size = pagesize;
+ priv->page_offset = pageoffset;
+
+ /* name must be usable with cmdlinepart */
+ sprintf(priv->name, "spi%d.%d-%s",
+ spi->master->bus_num, spi->chip_select,
+ name);
+
+ device = &priv->mtd;
+ device->name = (pdata && pdata->name) ? pdata->name : priv->name;
+ device->size = nr_pages * pagesize;
+ device->erasesize = pagesize;
+ device->owner = THIS_MODULE;
+ device->type = MTD_DATAFLASH;
+ device->flags = MTD_CAP_NORFLASH;
+ device->erase = dataflash_erase;
+ device->read = dataflash_read;
+ device->write = dataflash_write;
+ device->priv = priv;
+
+ dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024);
+ dev_set_drvdata(&spi->dev, priv);
+
+ if (mtd_has_partitions()) {
+ struct mtd_partition *parts;
+ int nr_parts = 0;
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_probes[] = { "cmdlinepart", NULL, };
+
+ nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0);
+#endif
+
+ if (nr_parts <= 0 && pdata && pdata->parts) {
+ parts = pdata->parts;
+ nr_parts = pdata->nr_parts;
+ }
+
+ if (nr_parts > 0) {
+ priv->partitioned = 1;
+ return add_mtd_partitions(device, parts, nr_parts);
+ }
+ } else if (pdata && pdata->nr_parts)
+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
+ pdata->nr_parts, device->name);
+
+ return add_mtd_device(device) == 1 ? -ENODEV : 0;
+}
+
+/*
+ * Detect and initialize DataFlash device:
+ *
+ * Device Density ID code #Pages PageSize Offset
+ * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9
+ * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9
+ * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9
+ * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9
+ * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10
+ * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10
+ * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11
+ * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11
+ */
+static int __devinit dataflash_probe(struct spi_device *spi)
+{
+ int status;
+
+ status = dataflash_status(spi);
+ if (status <= 0 || status == 0xff) {
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
+ spi->dev.bus_id, status);
+ if (status == 0xff)
+ status = -ENODEV;
+ return status;
+ }
+
+ /* if there's a device there, assume it's dataflash.
+ * board setup should have set spi->max_speed_max to
+ * match f(car) for continuous reads, mode 0 or 3.
+ */
+ switch (status & 0x3c) {
+ case 0x0c: /* 0 0 1 1 x x */
+ status = add_dataflash(spi, "AT45DB011B", 512, 264, 9);
+ break;
+ case 0x14: /* 0 1 0 1 x x */
+ status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9);
+ break;
+ case 0x1c: /* 0 1 1 1 x x */
+ status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9);
+ break;
+ case 0x24: /* 1 0 0 1 x x */
+ status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9);
+ break;
+ case 0x2c: /* 1 0 1 1 x x */
+ status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10);
+ break;
+ case 0x34: /* 1 1 0 1 x x */
+ status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10);
+ break;
+ case 0x38: /* 1 1 1 x x x */
+ case 0x3c:
+ status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11);
+ break;
+ /* obsolete AT45DB1282 not (yet?) supported */
+ default:
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
+ spi->dev.bus_id, status & 0x3c);
+ status = -ENODEV;
+ }
+
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
+ spi->dev.bus_id, status);
+
+ return status;
+}
+
+static int __devexit dataflash_remove(struct spi_device *spi)
+{
+ struct dataflash *flash = dev_get_drvdata(&spi->dev);
+ int status;
+
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
+
+ if (mtd_has_partitions() && flash->partitioned)
+ status = del_mtd_partitions(&flash->mtd);
+ else
+ status = del_mtd_device(&flash->mtd);
+ if (status == 0)
+ kfree(flash);
+ return status;
+}
+
+static struct spi_driver dataflash_driver = {
+ .driver = {
+ .name = "mtd_dataflash",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = dataflash_probe,
+ .remove = __devexit_p(dataflash_remove),
+
+ /* FIXME: investigate suspend and resume... */
+};
+
+static int __init dataflash_init(void)
+{
+ return spi_register_driver(&dataflash_driver);
+}
+module_init(dataflash_init);
+
+static void __exit dataflash_exit(void)
+{
+ spi_unregister_driver(&dataflash_driver);
+}
+module_exit(dataflash_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrew Victor, David Brownell");
+MODULE_DESCRIPTION("MTD DataFlash driver");
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b9b77cf39a18..7abd7fee0dda 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -473,14 +473,6 @@ config MTD_IXP2000
IXDP425 and Coyote. If you have an IXP2000 based board and
would like to use the flash chips on it, say 'Y'.
-config MTD_EPXA10DB
- tristate "CFI Flash device mapped on Epxa10db"
- depends on MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
- help
- This enables support for the flash devices on the Altera
- Excalibur XA10 Development Board. If you are building a kernel
- for on of these boards then you should say 'Y' otherwise say 'N'.
-
config MTD_FORTUNET
tristate "CFI Flash device mapped on the FortuNet board"
depends on MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 2f7e254912f0..ab71f172eb77 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
obj-$(CONFIG_MTD_DC21285) += dc21285.o
obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
-obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
obj-$(CONFIG_MTD_IQ80310) += iq80310.o
obj-$(CONFIG_MTD_L440GX) += l440gx.o
obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c
deleted file mode 100644
index 265b079fe934..000000000000
--- a/drivers/mtd/maps/epxa10db-flash.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Flash memory access on EPXA based devices
- *
- * (C) 2000 Nicolas Pitre <nico@cam.org>
- * Copyright (C) 2001 Altera Corporation
- * Copyright (C) 2001 Red Hat, Inc.
- *
- * $Id: epxa10db-flash.c,v 1.15 2005/11/07 11:14:27 gleixner Exp $
- *
- * This program is free software; you can redistribute 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/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.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
-#define BOARD_NAME "EPXA1DB"
-#endif
-
-static int nr_parts = 0;
-static struct mtd_partition *parts;
-
-static struct mtd_info *mymtd;
-
-static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-
-
-static struct map_info epxa_map = {
- .name = "EPXA flash",
- .size = FLASH_SIZE,
- .bankwidth = 2,
- .phys = FLASH_START,
-};
-
-static const char *probes[] = { "RedBoot", "afs", NULL };
-
-static int __init epxa_mtd_init(void)
-{
- int i;
-
- printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
-
- epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE);
- if (!epxa_map.virt) {
- printk("Failed to ioremap %s flash\n",BOARD_NAME);
- return -EIO;
- }
- simple_map_init(&epxa_map);
-
- mymtd = do_map_probe("cfi_probe", &epxa_map);
- if (!mymtd) {
- iounmap((void *)epxa_map.virt);
- return -ENXIO;
- }
-
- mymtd->owner = THIS_MODULE;
-
- /* Unlock the flash device. */
- if(mymtd->unlock){
- for (i=0; i<mymtd->numeraseregions;i++){
- int j;
- for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
- mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
- }
- }
- }
-
-#ifdef CONFIG_MTD_PARTITIONS
- nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0);
-
- if (nr_parts > 0) {
- add_mtd_partitions(mymtd, parts, nr_parts);
- return 0;
- }
-#endif
- /* No recognised partitioning schemes found - use defaults */
- nr_parts = epxa_default_partitions(mymtd, &parts);
- if (nr_parts > 0) {
- add_mtd_partitions(mymtd, parts, nr_parts);
- return 0;
- }
-
- /* If all else fails... */
- add_mtd_device(mymtd);
- return 0;
-}
-
-static void __exit epxa_mtd_cleanup(void)
-{
- if (mymtd) {
- if (nr_parts)
- del_mtd_partitions(mymtd);
- else
- del_mtd_device(mymtd);
- map_destroy(mymtd);
- }
- if (epxa_map.virt) {
- iounmap((void *)epxa_map.virt);
- epxa_map.virt = 0;
- }
-}
-
-
-/*
- * This will do for now, once we decide which bootldr we're finally
- * going to use then we'll remove this function and do it properly
- *
- * Partions are currently (as offsets from base of flash):
- * 0x00000000 - 0x003FFFFF - bootloader (!)
- * 0x00400000 - 0x00FFFFFF - Flashdisk
- */
-
-static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
-{
- struct mtd_partition *parts;
- int ret, i;
- int npartitions = 0;
- char *names;
- const char *name = "jffs";
-
- printk("Using default partitions for %s\n",BOARD_NAME);
- npartitions=1;
- parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
- memzero(parts,npartitions*sizeof(*parts)+strlen(name));
- if (!parts) {
- ret = -ENOMEM;
- goto out;
- }
- i=0;
- names = (char *)&parts[npartitions];
- parts[i].name = names;
- names += strlen(name) + 1;
- strcpy(parts[i].name, name);
-
-#ifdef CONFIG_EPXA10DB
- parts[i].size = FLASH_SIZE-0x00400000;
- parts[i].offset = 0x00400000;
-#else
- parts[i].size = FLASH_SIZE-0x00180000;
- parts[i].offset = 0x00180000;
-#endif
-
- out:
- *pparts = parts;
- return npartitions;
-}
-
-
-module_init(epxa_mtd_init);
-module_exit(epxa_mtd_cleanup);
-
-MODULE_AUTHOR("Clive Davies");
-MODULE_DESCRIPTION("Altera epxa mtd flash map");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 339cb1218eaa..7f3ff500b68e 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f)
return ret;
}
+static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+
+ if (dev->tr->getgeo)
+ return dev->tr->getgeo(dev, geo);
+ return -ENOTTY;
+}
static int blktrans_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
return tr->flush(dev);
/* The core code did the work, we had nothing to do. */
return 0;
-
- case HDIO_GETGEO:
- if (tr->getgeo) {
- struct hd_geometry g;
- int ret;
-
- memset(&g, 0, sizeof(g));
- ret = tr->getgeo(dev, &g);
- if (ret)
- return ret;
-
- g.start = get_start_sect(inode->i_bdev);
- if (copy_to_user((void __user *)arg, &g, sizeof(g)))
- return -EFAULT;
- return 0;
- } /* else */
default:
return -ENOTTY;
}
@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = {
.open = blktrans_open,
.release = blktrans_release,
.ioctl = blktrans_ioctl,
+ .getgeo = blktrans_getgeo,
};
int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 9c5945d6df88..201e1362da14 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -43,7 +43,7 @@ static int nand_width = 1; /* default x8*/
/*
* Define partitions for flash device
*/
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
{
.name = "NAND FS 0",
.offset = 0,
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 21d4e8f4b7af..ec5e45e4e4ef 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1506,7 +1506,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
return 1;
}
-static inline int __init doc_probe(unsigned long physadr)
+static int __init doc_probe(unsigned long physadr)
{
unsigned char ChipID;
struct mtd_info *mtd;
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 3a5841c9d950..4129c03dfd90 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -96,7 +96,7 @@ static struct mtd_info *rtc_from4_mtd = NULL;
*/
static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
{
.name = "Renesas flash partition 1",
.offset = 0,
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d209214b1318..5b55599739f3 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -53,6 +53,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/clk.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -60,7 +61,6 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-nand.h>
#include <asm/arch/nand.h>
@@ -460,7 +460,6 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
if (info->clk != NULL && !IS_ERR(info->clk)) {
clk_disable(info->clk);
- clk_unuse(info->clk);
clk_put(info->clk);
}
@@ -598,7 +597,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
goto exit_error;
}
- clk_use(info->clk);
clk_enable(info->clk);
/* allocate and map the resource */
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 32541cbb0103..9cf1ce718ec1 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -67,7 +67,7 @@ module_param(spia_peddr, int, 0);
/*
* Define partitions for flash device
*/
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
{
.name = "SPIA flash partition 1",
.offset = 0,
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 45c077d0f063..af06a80f44de 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 20ce212638fc..a3e00a4635a5 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -18,6 +18,7 @@
#include <linux/mtd/blktrans.h>
#include <linux/mtd/mtd.h>
#include <linux/vmalloc.h>
+#include <linux/slab.h>
#include <linux/jiffies.h>
#include <asm/types.h>
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 5c5eebdb6914..dcc98afa65d7 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -148,14 +148,6 @@ el2_pio_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: el2_close() handles free_irq */
- release_region(dev->base_addr, EL2_IO_EXTENT);
- if (ei_status.mem)
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init el2_probe(int unit)
{
@@ -726,6 +718,14 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: el2_close() handles free_irq */
+ release_region(dev->base_addr, EL2_IO_EXTENT);
+ if (ei_status.mem)
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/3c527.h b/drivers/net/3c527.h
index c10f009ce9b6..53b5b071df08 100644
--- a/drivers/net/3c527.h
+++ b/drivers/net/3c527.h
@@ -32,43 +32,43 @@
struct mc32_mailbox
{
- u16 mbox __attribute((packed));
- u16 data[1] __attribute((packed));
-};
+ u16 mbox;
+ u16 data[1];
+} __attribute((packed));
struct skb_header
{
- u8 status __attribute((packed));
- u8 control __attribute((packed));
- u16 next __attribute((packed)); /* Do not change! */
- u16 length __attribute((packed));
- u32 data __attribute((packed));
-};
+ u8 status;
+ u8 control;
+ u16 next; /* Do not change! */
+ u16 length;
+ u32 data;
+} __attribute((packed));
struct mc32_stats
{
/* RX Errors */
- u32 rx_crc_errors __attribute((packed));
- u32 rx_alignment_errors __attribute((packed));
- u32 rx_overrun_errors __attribute((packed));
- u32 rx_tooshort_errors __attribute((packed));
- u32 rx_toolong_errors __attribute((packed));
- u32 rx_outofresource_errors __attribute((packed));
+ u32 rx_crc_errors;
+ u32 rx_alignment_errors;
+ u32 rx_overrun_errors;
+ u32 rx_tooshort_errors;
+ u32 rx_toolong_errors;
+ u32 rx_outofresource_errors;
- u32 rx_discarded __attribute((packed)); /* via card pattern match filter */
+ u32 rx_discarded; /* via card pattern match filter */
/* TX Errors */
- u32 tx_max_collisions __attribute((packed));
- u32 tx_carrier_errors __attribute((packed));
- u32 tx_underrun_errors __attribute((packed));
- u32 tx_cts_errors __attribute((packed));
- u32 tx_timeout_errors __attribute((packed)) ;
+ u32 tx_max_collisions;
+ u32 tx_carrier_errors;
+ u32 tx_underrun_errors;
+ u32 tx_cts_errors;
+ u32 tx_timeout_errors;
/* various cruft */
- u32 dataA[6] __attribute((packed));
- u16 dataB[5] __attribute((packed));
- u32 dataC[14] __attribute((packed));
-};
+ u32 dataA[6];
+ u16 dataB[5];
+ u32 dataC[14];
+} __attribute((packed));
#define STATUS_MASK 0x0F
#define COMPLETED (1<<7)
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index d2102a27d307..adfba44dac5a 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -505,7 +505,7 @@ enum chip_flags {
#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)
/* directly indexed by chip_t, above */
-const static struct {
+static const struct {
const char *name;
u32 version; /* from RTL8139C/RTL8139D docs */
u32 flags;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e2fa29b612cd..626508afe1b1 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,6 +7,7 @@ menu "Network device support"
config NETDEVICES
depends on NET
+ default y if UML
bool "Network device support"
---help---
You can say N here if you don't intend to connect your Linux box to
@@ -27,6 +28,19 @@ config NETDEVICES
# that for each of the symbols.
if NETDEVICES
+config IFB
+ tristate "Intermediate Functional Block support"
+ depends on NET_CLS_ACT
+ ---help---
+ This is an intermidiate driver that allows sharing of
+ resources.
+ To compile this driver as a module, choose M here: the module
+ will be called ifb. If you want to use more than one ifb
+ device at a time, you need to compile this driver as a module.
+ Instead of 'ifb', the devices will then be called 'ifb0',
+ 'ifb1' etc.
+ Look at the iproute2 documentation directory for usage etc
+
config DUMMY
tristate "Dummy net driver support"
---help---
@@ -129,7 +143,7 @@ config NET_SB1000
If you don't have this card, of course say N.
- source "drivers/net/arcnet/Kconfig"
+source "drivers/net/arcnet/Kconfig"
source "drivers/net/phy/Kconfig"
@@ -844,7 +858,7 @@ config SMC9194
config DM9000
tristate "DM9000 support"
- depends on ARM && NET_ETHERNET
+ depends on (ARM || MIPS) && NET_ETHERNET
select CRC32
select MII
---help---
@@ -1374,7 +1388,7 @@ config FORCEDETH
config CS89x0
tristate "CS89x0 support"
- depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105
+ depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
@@ -1384,7 +1398,7 @@ config CS89x0
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module will be
- called cs89x.
+ called cs89x0.
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
@@ -1791,7 +1805,7 @@ config 68360_ENET
config FEC
bool "FEC ethernet controller (of ColdFire CPUs)"
- depends on M523x || M527x || M5272 || M528x
+ depends on M523x || M527x || M5272 || M528x || M520x
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire processors.
@@ -1901,6 +1915,15 @@ config E1000_NAPI
If in doubt, say N.
+config E1000_DISABLE_PACKET_SPLIT
+ bool "Disable Packet Split for PCI express adapters"
+ depends on E1000
+ help
+ Say Y here if you want to use the legacy receive path for PCI express
+ hadware.
+
+ If in doubt, say N.
+
source "drivers/net/ixp2000/Kconfig"
config MYRI_SBUS
@@ -2663,10 +2686,6 @@ config SHAPER
Class-Based Queueing (CBQ) scheduling support which you get if you
say Y to "QoS and/or fair queueing" above.
- To set up and configure shaper devices, you need the shapecfg
- program, available from <ftp://shadow.cabi.net/pub/Linux/> in the
- shaper package.
-
To compile this driver as a module, choose M here: the module
will be called shaper. If unsure, say N.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b74a7cb5bae6..00e72b12fb92 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -125,6 +125,7 @@ ifeq ($(CONFIG_SLIP_COMPRESSED),y)
endif
obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_IFB) += ifb.o
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
obj-$(CONFIG_LANCE) += lance.o
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 8a0af5453e21..7952dc6d77e3 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -123,14 +123,6 @@ static int __init do_ac3200_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* Someday free_irq may be in ac_close_card() */
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, AC_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init ac3200_probe(int unit)
{
@@ -406,6 +398,14 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* Someday free_irq may be in ac_close_card() */
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, AC_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 470364deded0..625184b65e38 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -31,16 +31,3 @@ config ARM_ETHERH
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHER00
- tristate "Altera Ether00 support"
- depends on NET_ETHERNET && ARM && ARCH_CAMELOT
- help
- This is the driver for Altera's ether00 ethernet mac IP core. Say
- Y here if you want to build support for this into the kernel. It
- is also available as a module (say M here) that can be inserted/
- removed from the kernel at the same time as the PLD is configured.
- If this driver is running on an epxa10 development board then it
- will generate a suitable hw address based on the board serial
- number (MTD support is required for this). Otherwise you will
- need to set a suitable hw address using ifconfig.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
index b0d706834d89..bc263edf06a7 100644
--- a/drivers/net/arm/Makefile
+++ b/drivers/net/arm/Makefile
@@ -4,7 +4,6 @@
#
obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
-obj-$(CONFIG_ARM_ETHER00) += ether00.o
obj-$(CONFIG_ARM_ETHERH) += etherh.o
obj-$(CONFIG_ARM_ETHER3) += ether3.o
obj-$(CONFIG_ARM_ETHER1) += ether1.o
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 877891a29aaa..53e3afc1b7b7 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -668,9 +668,8 @@ static void __init am79c961_banner(void)
printk(KERN_INFO "%s", version);
}
-static int __init am79c961_probe(struct device *_dev)
+static int __init am79c961_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(_dev);
struct resource *res;
struct net_device *dev;
struct dev_priv *priv;
@@ -758,15 +757,16 @@ out:
return ret;
}
-static struct device_driver am79c961_driver = {
- .name = "am79c961",
- .bus = &platform_bus_type,
+static struct platform_driver am79c961_driver = {
.probe = am79c961_probe,
+ .driver = {
+ .name = "am79c961",
+ },
};
static int __init am79c961_init(void)
{
- return driver_register(&am79c961_driver);
+ return platform_driver_register(&am79c961_driver);
}
__initcall(am79c961_init);
diff --git a/drivers/net/arm/ether00.c b/drivers/net/arm/ether00.c
deleted file mode 100644
index 4f1f4e31bda5..000000000000
--- a/drivers/net/arm/ether00.c
+++ /dev/null
@@ -1,1017 +0,0 @@
-/*
- * drivers/net/ether00.c
- *
- * Copyright (C) 2001 Altera 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.
- *
- * 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
- */
-
-/* includes */
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/tqueue.h>
-#include <linux/mtd/mtd.h>
-#include <linux/pld/pld_hotswap.h>
-#include <asm/arch/excalibur.h>
-#include <asm/arch/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-#include <asm/arch/ether00.h>
-#include <asm/arch/tdkphy.h>
-
-
-MODULE_AUTHOR("Clive Davies");
-MODULE_DESCRIPTION("Altera Ether00 IP core driver");
-MODULE_LICENSE("GPL");
-
-#define PKT_BUF_SZ 1540 /* Size of each rx buffer */
-#define ETH_NR 4 /* Number of MACs this driver supports */
-
-#define DEBUG(x)
-
-#define __dma_va(x) (unsigned int)((unsigned int)priv->dma_data+(((unsigned int)(x))&(EXC_SPSRAM_BLOCK0_SIZE-1)))
-#define __dma_pa(x) (unsigned int)(EXC_SPSRAM_BLOCK0_BASE+(((unsigned int)(x))-(unsigned int)priv->dma_data))
-
-#define ETHER00_BASE 0
-#define ETHER00_TYPE
-#define ETHER00_NAME "ether00"
-#define MAC_REG_SIZE 0x400 /* size of MAC register area */
-
-
-
-/* typedefs */
-
-/* The definition of the driver control structure */
-
-#define RX_NUM_BUFF 10
-#define RX_NUM_FDESC 10
-#define TX_NUM_FDESC 10
-
-struct tx_fda_ent{
- FDA_DESC fd;
- BUF_DESC bd;
- BUF_DESC pad;
-};
-struct rx_fda_ent{
- FDA_DESC fd;
- BUF_DESC bd;
- BUF_DESC pad;
-};
-struct rx_blist_ent{
- FDA_DESC fd;
- BUF_DESC bd;
- BUF_DESC pad;
-};
-struct net_priv
-{
- struct net_device_stats stats;
- struct sk_buff* skb;
- void* dma_data;
- struct rx_blist_ent* rx_blist_vp;
- struct rx_fda_ent* rx_fda_ptr;
- struct tx_fda_ent* tx_fdalist_vp;
- struct tq_struct tq_memupdate;
- unsigned char memupdate_scheduled;
- unsigned char rx_disabled;
- unsigned char queue_stopped;
- spinlock_t rx_lock;
-};
-
-static const char vendor_id[2]={0x07,0xed};
-
-#ifdef ETHER00_DEBUG
-
-/* Dump (most) registers for debugging puposes */
-
-static void dump_regs(struct net_device *dev){
- struct net_priv* priv=dev->priv;
- unsigned int* i;
-
- printk("\n RX free descriptor area:\n");
-
- for(i=(unsigned int*)priv->rx_fda_ptr;
- i<((unsigned int*)(priv->rx_fda_ptr+RX_NUM_FDESC));){
- printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3));
- i+=4;
- }
-
- printk("\n RX buffer list:\n");
-
- for(i=(unsigned int*)priv->rx_blist_vp;
- i<((unsigned int*)(priv->rx_blist_vp+RX_NUM_BUFF));){
- printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3));
- i+=4;
- }
-
- printk("\n TX frame descriptor list:\n");
-
- for(i=(unsigned int*)priv->tx_fdalist_vp;
- i<((unsigned int*)(priv->tx_fdalist_vp+TX_NUM_FDESC));){
- printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3));
- i+=4;
- }
-
- printk("\ndma ctl=%#x\n",readw(ETHER_DMA_CTL(dev->base_addr)));
- printk("txfrmptr=%#x\n",readw(ETHER_TXFRMPTR(dev->base_addr)));
- printk("txthrsh=%#x\n",readw(ETHER_TXTHRSH(dev->base_addr)));
- printk("txpollctr=%#x\n",readw(ETHER_TXPOLLCTR(dev->base_addr)));
- printk("blfrmptr=%#x\n",readw(ETHER_BLFRMPTR(dev->base_addr)));
- printk("rxfragsize=%#x\n",readw(ETHER_RXFRAGSIZE(dev->base_addr)));
- printk("tx_int_en=%#x\n",readw(ETHER_INT_EN(dev->base_addr)));
- printk("fda_bas=%#x\n",readw(ETHER_FDA_BAS(dev->base_addr)));
- printk("fda_lim=%#x\n",readw(ETHER_FDA_LIM(dev->base_addr)));
- printk("int_src=%#x\n",readw(ETHER_INT_SRC(dev->base_addr)));
- printk("pausecnt=%#x\n",readw(ETHER_PAUSECNT(dev->base_addr)));
- printk("rempaucnt=%#x\n",readw(ETHER_REMPAUCNT(dev->base_addr)));
- printk("txconfrmstat=%#x\n",readw(ETHER_TXCONFRMSTAT(dev->base_addr)));
- printk("mac_ctl=%#x\n",readw(ETHER_MAC_CTL(dev->base_addr)));
- printk("arc_ctl=%#x\n",readw(ETHER_ARC_CTL(dev->base_addr)));
- printk("tx_ctl=%#x\n",readw(ETHER_TX_CTL(dev->base_addr)));
-}
-#endif /* ETHER00_DEBUG */
-
-
-static int ether00_write_phy(struct net_device *dev, short address, short value)
-{
- volatile int count = 1024;
- writew(value,ETHER_MD_DATA(dev->base_addr));
- writew( ETHER_MD_CA_BUSY_MSK |
- ETHER_MD_CA_WR_MSK |
- (address & ETHER_MD_CA_ADDR_MSK),
- ETHER_MD_CA(dev->base_addr));
-
- /* Wait for the command to complete */
- while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){
- count--;
- }
- if (!count){
- printk("Write to phy failed, addr=%#x, data=%#x\n",address, value);
- return -EIO;
- }
- return 0;
-}
-
-static int ether00_read_phy(struct net_device *dev, short address)
-{
- volatile int count = 1024;
- writew( ETHER_MD_CA_BUSY_MSK |
- (address & ETHER_MD_CA_ADDR_MSK),
- ETHER_MD_CA(dev->base_addr));
-
- /* Wait for the command to complete */
- while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){
- count--;
- }
- if (!count){
- printk(KERN_WARNING "Read from phy timed out\n");
- return -EIO;
- }
- return readw(ETHER_MD_DATA(dev->base_addr));
-}
-
-static void ether00_phy_int(int irq_num, void* dev_id, struct pt_regs* regs)
-{
- struct net_device* dev=dev_id;
- int irq_status;
-
- irq_status=ether00_read_phy(dev, PHY_IRQ_CONTROL);
-
- if(irq_status & PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK){
- /*
- * Autonegotiation complete on epxa10db. The mac doesn't
- * twig if we're in full duplex so we need to check the
- * phy status register and configure the mac accordingly
- */
- if(ether00_read_phy(dev, PHY_STATUS)&(PHY_STATUS_10T_F_MSK|PHY_STATUS_100_X_F_MSK)){
- int tmp;
- tmp=readl(ETHER_MAC_CTL(dev->base_addr));
- writel(tmp|ETHER_MAC_CTL_FULLDUP_MSK,ETHER_MAC_CTL(dev->base_addr));
- }
- }
-
- if(irq_status&PHY_IRQ_CONTROL_LS_CHG_INT_MSK){
-
- if(ether00_read_phy(dev, PHY_STATUS)& PHY_STATUS_LINK_MSK){
- /* Link is up */
- netif_carrier_on(dev);
- //printk("Carrier on\n");
- }else{
- netif_carrier_off(dev);
- //printk("Carrier off\n");
-
- }
- }
-
-}
-
-static void setup_blist_entry(struct sk_buff* skb,struct rx_blist_ent* blist_ent_ptr){
- /* Make the buffer consistent with the cache as the mac is going to write
- * directly into it*/
- blist_ent_ptr->fd.FDSystem=(unsigned int)skb;
- blist_ent_ptr->bd.BuffData=(char*)__pa(skb->data);
- consistent_sync(skb->data,PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
- /* align IP on 16 Byte (DMA_CTL set to skip 2 bytes) */
- skb_reserve(skb,2);
- blist_ent_ptr->bd.BuffLength=PKT_BUF_SZ-2;
- blist_ent_ptr->fd.FDLength=1;
- blist_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK;
- blist_ent_ptr->bd.BDCtl=BDCTL_COWNSBD_MSK;
-}
-
-
-static int ether00_mem_init(struct net_device* dev)
-{
- struct net_priv* priv=dev->priv;
- struct tx_fda_ent *tx_fd_ptr,*tx_end_ptr;
- struct rx_blist_ent* blist_ent_ptr;
- int i;
-
- /*
- * Grab a block of on chip SRAM to contain the control stuctures for
- * the ethernet MAC. This uncached becuase it needs to be accesses by both
- * bus masters (cpu + mac). However, it shouldn't matter too much in terms
- * of speed as its on chip memory
- */
- priv->dma_data=ioremap_nocache(EXC_SPSRAM_BLOCK0_BASE,EXC_SPSRAM_BLOCK0_SIZE );
- if (!priv->dma_data)
- return -ENOMEM;
-
- priv->rx_fda_ptr=(struct rx_fda_ent*)priv->dma_data;
- /*
- * Now share it out amongst the Frame descriptors and the buffer list
- */
- priv->rx_blist_vp=(struct rx_blist_ent*)((unsigned int)priv->dma_data+RX_NUM_FDESC*sizeof(struct rx_fda_ent));
-
- /*
- *Initalise the FDA list
- */
- /* set ownership to the controller */
- memset(priv->rx_fda_ptr,0x80,RX_NUM_FDESC*sizeof(struct rx_fda_ent));
-
- /*
- *Initialise the buffer list
- */
- blist_ent_ptr=priv->rx_blist_vp;
- i=0;
- while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){
- struct sk_buff *skb;
- blist_ent_ptr->fd.FDLength=1;
- skb=dev_alloc_skb(PKT_BUF_SZ);
- if(skb){
- setup_blist_entry(skb,blist_ent_ptr);
- blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(blist_ent_ptr+1);
- blist_ent_ptr->bd.BDStat=i++;
- blist_ent_ptr++;
- }
- else
- {
- printk("Failed to initalise buffer list\n");
- }
-
- }
- blist_ent_ptr--;
- blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->rx_blist_vp);
-
- priv->tx_fdalist_vp=(struct tx_fda_ent*)(priv->rx_blist_vp+RX_NUM_BUFF);
-
- /* Initialise the buffers to be a circular list. The mac will then go poll
- * the list until it finds a frame ready to transmit */
- tx_end_ptr=priv->tx_fdalist_vp+TX_NUM_FDESC;
- for(tx_fd_ptr=priv->tx_fdalist_vp;tx_fd_ptr<tx_end_ptr;tx_fd_ptr++){
- tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa((tx_fd_ptr+1));
- tx_fd_ptr->fd.FDCtl=1;
- tx_fd_ptr->fd.FDStat=0;
- tx_fd_ptr->fd.FDLength=1;
-
- }
- /* Change the last FDNext pointer to make a circular list */
- tx_fd_ptr--;
- tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->tx_fdalist_vp);
-
- /* Point the device at the chain of Rx and Tx Buffers */
- writel((unsigned int)__dma_pa(priv->rx_fda_ptr),ETHER_FDA_BAS(dev->base_addr));
- writel((RX_NUM_FDESC-1)*sizeof(struct rx_fda_ent),ETHER_FDA_LIM(dev->base_addr));
- writel((unsigned int)__dma_pa(priv->rx_blist_vp),ETHER_BLFRMPTR(dev->base_addr));
-
- writel((unsigned int)__dma_pa(priv->tx_fdalist_vp),ETHER_TXFRMPTR(dev->base_addr));
-
- return 0;
-}
-
-
-void ether00_mem_update(void* dev_id)
-{
- struct net_device* dev=dev_id;
- struct net_priv* priv=dev->priv;
- struct sk_buff* skb;
- struct tx_fda_ent *fda_ptr=priv->tx_fdalist_vp;
- struct rx_blist_ent* blist_ent_ptr;
- unsigned long flags;
-
- priv->tq_memupdate.sync=0;
- //priv->tq_memupdate.list=
- priv->memupdate_scheduled=0;
-
- /* Transmit interrupt */
- while(fda_ptr<(priv->tx_fdalist_vp+TX_NUM_FDESC)){
- if(!(FDCTL_COWNSFD_MSK&fda_ptr->fd.FDCtl) && (ETHER_TX_STAT_COMP_MSK&fda_ptr->fd.FDStat)){
- priv->stats.tx_packets++;
- priv->stats.tx_bytes+=fda_ptr->bd.BuffLength;
- skb=(struct sk_buff*)fda_ptr->fd.FDSystem;
- //printk("%d:txcln:fda=%#x skb=%#x\n",jiffies,fda_ptr,skb);
- dev_kfree_skb(skb);
- fda_ptr->fd.FDSystem=0;
- fda_ptr->fd.FDStat=0;
- fda_ptr->fd.FDCtl=0;
- }
- fda_ptr++;
- }
- /* Fill in any missing buffers from the received queue */
- spin_lock_irqsave(&priv->rx_lock,flags);
- blist_ent_ptr=priv->rx_blist_vp;
- while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){
- /* fd.FDSystem of 0 indicates we failed to allocate the buffer in the ISR */
- if(!blist_ent_ptr->fd.FDSystem){
- struct sk_buff *skb;
- skb=dev_alloc_skb(PKT_BUF_SZ);
- blist_ent_ptr->fd.FDSystem=(unsigned int)skb;
- if(skb){
- setup_blist_entry(skb,blist_ent_ptr);
- }
- else
- {
- break;
- }
- }
- blist_ent_ptr++;
- }
- spin_unlock_irqrestore(&priv->rx_lock,flags);
- if(priv->queue_stopped){
- //printk("%d:cln:start q\n",jiffies);
- netif_start_queue(dev);
- }
- if(priv->rx_disabled){
- //printk("%d:enable_irq\n",jiffies);
- priv->rx_disabled=0;
- writel(ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr));
-
- }
-}
-
-
-static void ether00_int( int irq_num, void* dev_id, struct pt_regs* regs)
-{
- struct net_device* dev=dev_id;
- struct net_priv* priv=dev->priv;
-
- unsigned int interruptValue;
-
- interruptValue=readl(ETHER_INT_SRC(dev->base_addr));
-
- //printk("INT_SRC=%x\n",interruptValue);
-
- if(!(readl(ETHER_INT_SRC(dev->base_addr)) & ETHER_INT_SRC_IRQ_MSK))
- {
- return; /* Interrupt wasn't caused by us!! */
- }
-
- if(readl(ETHER_INT_SRC(dev->base_addr))&
- (ETHER_INT_SRC_INTMACRX_MSK |
- ETHER_INT_SRC_FDAEX_MSK |
- ETHER_INT_SRC_BLEX_MSK)) {
- struct rx_blist_ent* blist_ent_ptr;
- struct rx_fda_ent* fda_ent_ptr;
- struct sk_buff* skb;
-
- fda_ent_ptr=priv->rx_fda_ptr;
- spin_lock(&priv->rx_lock);
- while(fda_ent_ptr<(priv->rx_fda_ptr+RX_NUM_FDESC)){
- int result;
-
- if(!(fda_ent_ptr->fd.FDCtl&FDCTL_COWNSFD_MSK))
- {
- /* This frame is ready for processing */
- /*find the corresponding buffer in the bufferlist */
- blist_ent_ptr=priv->rx_blist_vp+fda_ent_ptr->bd.BDStat;
- skb=(struct sk_buff*)blist_ent_ptr->fd.FDSystem;
-
- /* Pass this skb up the stack */
- skb->dev=dev;
- skb_put(skb,fda_ent_ptr->fd.FDLength);
- skb->protocol=eth_type_trans(skb,dev);
- skb->ip_summed=CHECKSUM_UNNECESSARY;
- result=netif_rx(skb);
- /* Update statistics */
- priv->stats.rx_packets++;
- priv->stats.rx_bytes+=fda_ent_ptr->fd.FDLength;
-
- /* Free the FDA entry */
- fda_ent_ptr->bd.BDStat=0xff;
- fda_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK;
-
- /* Allocate a new skb and point the bd entry to it */
- blist_ent_ptr->fd.FDSystem=0;
- skb=dev_alloc_skb(PKT_BUF_SZ);
- //printk("allocskb=%#x\n",skb);
- if(skb){
- setup_blist_entry(skb,blist_ent_ptr);
-
- }
- else if(!priv->memupdate_scheduled){
- int tmp;
- /* There are no buffers at the moment, so schedule */
- /* the background task to sort this out */
- schedule_task(&priv->tq_memupdate);
- priv->memupdate_scheduled=1;
- printk(KERN_DEBUG "%s:No buffers",dev->name);
- /* If this interrupt was due to a lack of buffers then
- * we'd better stop the receiver too */
- if(interruptValue&ETHER_INT_SRC_BLEX_MSK){
- priv->rx_disabled=1;
- tmp=readl(ETHER_INT_SRC(dev->base_addr));
- writel(tmp&~ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr));
- printk(KERN_DEBUG "%s:Halting rx",dev->name);
- }
-
- }
-
- }
- fda_ent_ptr++;
- }
- spin_unlock(&priv->rx_lock);
-
- /* Clear the interrupts */
- writel(ETHER_INT_SRC_INTMACRX_MSK | ETHER_INT_SRC_FDAEX_MSK
- | ETHER_INT_SRC_BLEX_MSK,ETHER_INT_SRC(dev->base_addr));
-
- }
-
- if(readl(ETHER_INT_SRC(dev->base_addr))&ETHER_INT_SRC_INTMACTX_MSK){
-
- if(!priv->memupdate_scheduled){
- schedule_task(&priv->tq_memupdate);
- priv->memupdate_scheduled=1;
- }
- /* Clear the interrupt */
- writel(ETHER_INT_SRC_INTMACTX_MSK,ETHER_INT_SRC(dev->base_addr));
- }
-
- if (readl(ETHER_INT_SRC(dev->base_addr)) & (ETHER_INT_SRC_SWINT_MSK|
- ETHER_INT_SRC_INTEARNOT_MSK|
- ETHER_INT_SRC_INTLINK_MSK|
- ETHER_INT_SRC_INTEXBD_MSK|
- ETHER_INT_SRC_INTTXCTLCMP_MSK))
- {
- /*
- * Not using any of these so they shouldn't happen
- *
- * In the cased of INTEXBD - if you allocate more
- * than 28 decsriptors you may need to think about this
- */
- printk("Not using this interrupt\n");
- }
-
- if (readl(ETHER_INT_SRC(dev->base_addr)) &
- (ETHER_INT_SRC_INTSBUS_MSK |
- ETHER_INT_SRC_INTNRABT_MSK
- |ETHER_INT_SRC_DMPARERR_MSK))
- {
- /*
- * Hardware errors, we can either ignore them and hope they go away
- *or reset the device, I'll try the first for now to see if they happen
- */
- printk("Hardware error\n");
- }
-}
-
-static void ether00_setup_ethernet_address(struct net_device* dev)
-{
- int tmp;
-
- dev->addr_len=6;
- writew(0,ETHER_ARC_ADR(dev->base_addr));
- writel((dev->dev_addr[0]<<24) |
- (dev->dev_addr[1]<<16) |
- (dev->dev_addr[2]<<8) |
- dev->dev_addr[3],
- ETHER_ARC_DATA(dev->base_addr));
-
- writew(4,ETHER_ARC_ADR(dev->base_addr));
- tmp=readl(ETHER_ARC_DATA(dev->base_addr));
- tmp&=0xffff;
- tmp|=(dev->dev_addr[4]<<24) | (dev->dev_addr[5]<<16);
- writel(tmp, ETHER_ARC_DATA(dev->base_addr));
- /* Enable this entry in the ARC */
-
- writel(1,ETHER_ARC_ENA(dev->base_addr));
-
- return;
-}
-
-
-static void ether00_reset(struct net_device *dev)
-{
- /* reset the controller */
- writew(ETHER_MAC_CTL_RESET_MSK,ETHER_MAC_CTL(dev->base_addr));
-
- /*
- * Make sure we're not going to send anything
- */
-
- writew(ETHER_TX_CTL_TXHALT_MSK,ETHER_TX_CTL(dev->base_addr));
-
- /*
- * Make sure we're not going to receive anything
- */
- writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr));
-
- /*
- * Disable Interrupts for now, and set the burst size to 8 bytes
- */
-
- writel(ETHER_DMA_CTL_INTMASK_MSK |
- ((8 << ETHER_DMA_CTL_DMBURST_OFST) & ETHER_DMA_CTL_DMBURST_MSK)
- |(2<<ETHER_DMA_CTL_RXALIGN_OFST),
- ETHER_DMA_CTL(dev->base_addr));
-
-
- /*
- * Set TxThrsh - start transmitting a packet after 1514
- * bytes or when a packet is complete, whichever comes first
- */
- writew(1514,ETHER_TXTHRSH(dev->base_addr));
-
- /*
- * Set TxPollCtr. Each cycle is
- * 61.44 microseconds with a 33 MHz bus
- */
- writew(1,ETHER_TXPOLLCTR(dev->base_addr));
-
- /*
- * Set Rx_Ctl - Turn off reception and let RxData turn it
- * on later
- */
- writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr));
-
-}
-
-
-static void ether00_set_multicast(struct net_device* dev)
-{
- int count=dev->mc_count;
-
- /* Set promiscuous mode if it's asked for. */
-
- if (dev->flags&IFF_PROMISC){
-
- writew( ETHER_ARC_CTL_COMPEN_MSK |
- ETHER_ARC_CTL_BROADACC_MSK |
- ETHER_ARC_CTL_GROUPACC_MSK |
- ETHER_ARC_CTL_STATIONACC_MSK,
- ETHER_ARC_CTL(dev->base_addr));
- return;
- }
-
- /*
- * Get all multicast packets if required, or if there are too
- * many addresses to fit in hardware
- */
- if (dev->flags & IFF_ALLMULTI){
- writew( ETHER_ARC_CTL_COMPEN_MSK |
- ETHER_ARC_CTL_GROUPACC_MSK |
- ETHER_ARC_CTL_BROADACC_MSK,
- ETHER_ARC_CTL(dev->base_addr));
- return;
- }
- if (dev->mc_count > (ETHER_ARC_SIZE - 1)){
-
- printk(KERN_WARNING "Too many multicast addresses for hardware to filter - receiving all multicast packets\n");
- writew( ETHER_ARC_CTL_COMPEN_MSK |
- ETHER_ARC_CTL_GROUPACC_MSK |
- ETHER_ARC_CTL_BROADACC_MSK,
- ETHER_ARC_CTL(dev->base_addr));
- return;
- }
-
- if(dev->mc_count){
- struct dev_mc_list *mc_list_ent=dev->mc_list;
- unsigned int temp,i;
- DEBUG(printk("mc_count=%d mc_list=%#x\n",dev-> mc_count, dev->mc_list));
- DEBUG(printk("mc addr=%02#x%02x%02x%02x%02x%02x\n",
- mc_list_ent->dmi_addr[5],
- mc_list_ent->dmi_addr[4],
- mc_list_ent->dmi_addr[3],
- mc_list_ent->dmi_addr[2],
- mc_list_ent->dmi_addr[1],
- mc_list_ent->dmi_addr[0]);)
-
- /*
- * The first 6 bytes are the MAC address, so
- * don't change them!
- */
- writew(4,ETHER_ARC_ADR(dev->base_addr));
- temp=readl(ETHER_ARC_DATA(dev->base_addr));
- temp&=0xffff0000;
-
- /* Disable the current multicast stuff */
- writel(1,ETHER_ARC_ENA(dev->base_addr));
-
- for(;;){
- temp|=mc_list_ent->dmi_addr[1] |
- mc_list_ent->dmi_addr[0]<<8;
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- i=readl(ETHER_ARC_ADR(dev->base_addr));
- writew(i+4,ETHER_ARC_ADR(dev->base_addr));
-
- temp=mc_list_ent->dmi_addr[5]|
- mc_list_ent->dmi_addr[4]<<8 |
- mc_list_ent->dmi_addr[3]<<16 |
- mc_list_ent->dmi_addr[2]<<24;
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- count--;
- if(!mc_list_ent->next || !count){
- break;
- }
- DEBUG(printk("mc_list_next=%#x\n",mc_list_ent->next);)
- mc_list_ent=mc_list_ent->next;
-
-
- i=readl(ETHER_ARC_ADR(dev->base_addr));
- writel(i+4,ETHER_ARC_ADR(dev->base_addr));
-
- temp=mc_list_ent->dmi_addr[3]|
- mc_list_ent->dmi_addr[2]<<8 |
- mc_list_ent->dmi_addr[1]<<16 |
- mc_list_ent->dmi_addr[0]<<24;
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- i=readl(ETHER_ARC_ADR(dev->base_addr));
- writel(i+4,ETHER_ARC_ADR(dev->base_addr));
-
- temp=mc_list_ent->dmi_addr[4]<<16 |
- mc_list_ent->dmi_addr[5]<<24;
-
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- count--;
- if(!mc_list_ent->next || !count){
- break;
- }
- mc_list_ent=mc_list_ent->next;
- }
-
-
- if(count)
- printk(KERN_WARNING "Multicast list size error\n");
-
-
- writew( ETHER_ARC_CTL_BROADACC_MSK|
- ETHER_ARC_CTL_COMPEN_MSK,
- ETHER_ARC_CTL(dev->base_addr));
-
- }
-
- /* enable the active ARC enties */
- writew((1<<(count+2))-1,ETHER_ARC_ENA(dev->base_addr));
-}
-
-
-static int ether00_open(struct net_device* dev)
-{
- int result,tmp;
- struct net_priv* priv;
-
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EINVAL;
-
- /* Install interrupt handlers */
- result=request_irq(dev->irq,ether00_int,0,"ether00",dev);
- if(result)
- goto open_err1;
-
- result=request_irq(2,ether00_phy_int,0,"ether00_phy",dev);
- if(result)
- goto open_err2;
-
- ether00_reset(dev);
- result=ether00_mem_init(dev);
- if(result)
- goto open_err3;
-
-
- ether00_setup_ethernet_address(dev);
-
- ether00_set_multicast(dev);
-
- result=ether00_write_phy(dev,PHY_CONTROL, PHY_CONTROL_ANEGEN_MSK | PHY_CONTROL_RANEG_MSK);
- if(result)
- goto open_err4;
- result=ether00_write_phy(dev,PHY_IRQ_CONTROL, PHY_IRQ_CONTROL_LS_CHG_IE_MSK |
- PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK);
- if(result)
- goto open_err4;
-
- /* Start the device enable interrupts */
- writew(ETHER_RX_CTL_RXEN_MSK
-// | ETHER_RX_CTL_STRIPCRC_MSK
- | ETHER_RX_CTL_ENGOOD_MSK
- | ETHER_RX_CTL_ENRXPAR_MSK| ETHER_RX_CTL_ENLONGERR_MSK
- | ETHER_RX_CTL_ENOVER_MSK| ETHER_RX_CTL_ENCRCERR_MSK,
- ETHER_RX_CTL(dev->base_addr));
-
- writew(ETHER_TX_CTL_TXEN_MSK|
- ETHER_TX_CTL_ENEXDEFER_MSK|
- ETHER_TX_CTL_ENLCARR_MSK|
- ETHER_TX_CTL_ENEXCOLL_MSK|
- ETHER_TX_CTL_ENLATECOLL_MSK|
- ETHER_TX_CTL_ENTXPAR_MSK|
- ETHER_TX_CTL_ENCOMP_MSK,
- ETHER_TX_CTL(dev->base_addr));
-
- tmp=readl(ETHER_DMA_CTL(dev->base_addr));
- writel(tmp&~ETHER_DMA_CTL_INTMASK_MSK,ETHER_DMA_CTL(dev->base_addr));
-
- return 0;
-
- open_err4:
- ether00_reset(dev);
- open_err3:
- free_irq(2,dev);
- open_err2:
- free_irq(dev->irq,dev);
- open_err1:
- return result;
-
-}
-
-
-static int ether00_tx(struct sk_buff* skb, struct net_device* dev)
-{
- struct net_priv *priv=dev->priv;
- struct tx_fda_ent *fda_ptr;
- int i;
-
-
- /*
- * Find an empty slot in which to stick the frame
- */
- fda_ptr=(struct tx_fda_ent*)__dma_va(readl(ETHER_TXFRMPTR(dev->base_addr)));
- i=0;
- while(i<TX_NUM_FDESC){
- if (fda_ptr->fd.FDStat||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){
- fda_ptr =(struct tx_fda_ent*) __dma_va((struct tx_fda_ent*)fda_ptr->fd.FDNext);
- }
- else {
- break;
- }
- i++;
- }
-
- /* Write the skb data from the cache*/
- consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE);
- fda_ptr->bd.BuffData=(char*)__pa(skb->data);
- fda_ptr->bd.BuffLength=(unsigned short)skb->len;
- /* Save the pointer to the skb for freeing later */
- fda_ptr->fd.FDSystem=(unsigned int)skb;
- fda_ptr->fd.FDStat=0;
- /* Pass ownership of the buffers to the controller */
- fda_ptr->fd.FDCtl=1;
- fda_ptr->fd.FDCtl|=FDCTL_COWNSFD_MSK;
-
- /* If the next buffer in the list is full, stop the queue */
- fda_ptr=(struct tx_fda_ent*)__dma_va(fda_ptr->fd.FDNext);
- if ((fda_ptr->fd.FDStat)||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){
- netif_stop_queue(dev);
- priv->queue_stopped=1;
- }
-
- return 0;
-}
-
-static struct net_device_stats *ether00_stats(struct net_device* dev)
-{
- struct net_priv *priv=dev->priv;
- return &priv->stats;
-}
-
-
-static int ether00_stop(struct net_device* dev)
-{
- struct net_priv *priv=dev->priv;
- int tmp;
-
- /* Stop/disable the device. */
- tmp=readw(ETHER_RX_CTL(dev->base_addr));
- tmp&=~(ETHER_RX_CTL_RXEN_MSK | ETHER_RX_CTL_ENGOOD_MSK);
- tmp|=ETHER_RX_CTL_RXHALT_MSK;
- writew(tmp,ETHER_RX_CTL(dev->base_addr));
-
- tmp=readl(ETHER_TX_CTL(dev->base_addr));
- tmp&=~ETHER_TX_CTL_TXEN_MSK;
- tmp|=ETHER_TX_CTL_TXHALT_MSK;
- writel(tmp,ETHER_TX_CTL(dev->base_addr));
-
- /* Free up system resources */
- free_irq(dev->irq,dev);
- free_irq(2,dev);
- iounmap(priv->dma_data);
-
- return 0;
-}
-
-
-static void ether00_get_ethernet_address(struct net_device* dev)
-{
- struct mtd_info *mymtd=NULL;
- int i;
- size_t retlen;
-
- /*
- * For the Epxa10 dev board (camelot), the ethernet MAC
- * address is of the form 00:aa:aa:00:xx:xx where
- * 00:aa:aa is the Altera vendor ID and xx:xx is the
- * last 2 bytes of the board serial number, as programmed
- * into the OTP area of the flash device on EBI1. If this
- * isn't an expa10 dev board, or there's no mtd support to
- * read the serial number from flash then we'll force the
- * use to set their own mac address using ifconfig.
- */
-
-#ifdef CONFIG_ARCH_CAMELOT
-#ifdef CONFIG_MTD
- /* get the mtd_info structure for the first mtd device*/
- for(i=0;i<MAX_MTD_DEVICES;i++){
- mymtd=get_mtd_device(NULL,i);
- if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))
- break;
- }
-
- if(!mymtd || !mymtd->read_user_prot_reg){
- printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);
- }else{
- mymtd->read_user_prot_reg(mymtd,2,1,&retlen,&dev->dev_addr[5]);
- mymtd->read_user_prot_reg(mymtd,3,1,&retlen,&dev->dev_addr[4]);
- dev->dev_addr[3]=0;
- dev->dev_addr[2]=vendor_id[1];
- dev->dev_addr[1]=vendor_id[0];
- dev->dev_addr[0]=0;
- }
-#else
- printk(KERN_WARNING "%s: MTD support required to read MAC address from EPXA10 dev board\n", dev->name);
-#endif
-#endif
-
- if (!is_valid_ether_addr(dev->dev_addr))
- printk("%s: Invalid ethernet MAC address. Please set using "
- "ifconfig\n", dev->name);
-
-}
-
-/*
- * Keep a mapping of dev_info addresses -> port lines to use when
- * removing ports dev==NULL indicates unused entry
- */
-
-
-static struct net_device* dev_list[ETH_NR];
-
-static int ether00_add_device(struct pldhs_dev_info* dev_info,void* dev_ps_data)
-{
- struct net_device *dev;
- struct net_priv *priv;
- void *map_addr;
- int result;
- int i;
-
- i=0;
- while(dev_list[i] && i < ETH_NR)
- i++;
-
- if(i==ETH_NR){
- printk(KERN_WARNING "ether00: Maximum number of ports reached\n");
- return 0;
- }
-
-
- if (!request_mem_region(dev_info->base_addr, MAC_REG_SIZE, "ether00"))
- return -EBUSY;
-
- dev = alloc_etherdev(sizeof(struct net_priv));
- if(!dev) {
- result = -ENOMEM;
- goto out_release;
- }
- priv = dev->priv;
-
- priv->tq_memupdate.routine=ether00_mem_update;
- priv->tq_memupdate.data=(void*) dev;
-
- spin_lock_init(&priv->rx_lock);
-
- map_addr=ioremap_nocache(dev_info->base_addr,SZ_4K);
- if(!map_addr){
- result = -ENOMEM;
- out_kfree;
- }
-
- dev->open=ether00_open;
- dev->stop=ether00_stop;
- dev->set_multicast_list=ether00_set_multicast;
- dev->hard_start_xmit=ether00_tx;
- dev->get_stats=ether00_stats;
-
- ether00_get_ethernet_address(dev);
-
- SET_MODULE_OWNER(dev);
-
- dev->base_addr=(unsigned int)map_addr;
- dev->irq=dev_info->irq;
- dev->features=NETIF_F_DYNALLOC | NETIF_F_HW_CSUM;
-
- result=register_netdev(dev);
- if(result){
- printk("Ether00: Error %i registering driver\n",result);
- goto out_unmap;
- }
- printk("registered ether00 device at %#x\n",dev_info->base_addr);
-
- dev_list[i]=dev;
-
- return result;
-
- out_unmap:
- iounmap(map_addr);
- out_kfree:
- free_netdev(dev);
- out_release:
- release_mem_region(dev_info->base_addr, MAC_REG_SIZE);
- return result;
-}
-
-
-static int ether00_remove_devices(void)
-{
- int i;
-
- for(i=0;i<ETH_NR;i++){
- if(dev_list[i]){
- netif_device_detach(dev_list[i]);
- unregister_netdev(dev_list[i]);
- iounmap((void*)dev_list[i]->base_addr);
- release_mem_region(dev_list[i]->base_addr, MAC_REG_SIZE);
- free_netdev(dev_list[i]);
- dev_list[i]=0;
- }
- }
- return 0;
-}
-
-static struct pld_hotswap_ops ether00_pldhs_ops={
- .name = ETHER00_NAME,
- .add_device = ether00_add_device,
- .remove_devices = ether00_remove_devices,
-};
-
-
-static void __exit ether00_cleanup_module(void)
-{
- int result;
- result=ether00_remove_devices();
- if(result)
- printk(KERN_WARNING "ether00: failed to remove all devices\n");
-
- pldhs_unregister_driver(ETHER00_NAME);
-}
-module_exit(ether00_cleanup_module);
-
-
-static int __init ether00_mod_init(void)
-{
- printk("mod init\n");
- return pldhs_register_driver(&ether00_pldhs_ops);
-
-}
-
-module_init(ether00_mod_init);
-
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 1cc53abc3a39..f1d5b1027ff7 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -69,7 +69,6 @@
#include <asm/system.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 942a2819576c..6a93b666eb72 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -50,7 +50,6 @@
#include <asm/system.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include "../8390.h"
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 7aa49b974dc5..df9d6e80c4f2 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2136,7 +2136,7 @@ static int __init b44_init(void)
/* 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));
+ dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
return pci_module_init(&b44_driver);
}
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 854ddfb90da1..f2a63186ae05 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -169,9 +169,9 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
index = next_index;
}
- _unlock_tx_hashtbl(bond);
-
tlb_init_slave(slave);
+
+ _unlock_tx_hashtbl(bond);
}
/* Must be called before starting the monitor timer */
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 015c7f1d1bc0..3dd78d048c3e 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "3.0.0"
-#define DRV_RELDATE "November 8, 2005"
+#define DRV_VERSION "3.0.1"
+#define DRV_RELDATE "January 9, 2006"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@@ -205,7 +205,7 @@ struct bonding {
*
* Caller must hold bond lock for read
*/
-extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
{
struct slave *slave = NULL;
int i;
@@ -219,7 +219,7 @@ extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n
return slave;
}
-extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
+static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
{
if (!slave || !slave->dev->master) {
return NULL;
@@ -228,13 +228,13 @@ extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
return (struct bonding *)slave->dev->master->priv;
}
-extern inline void bond_set_slave_inactive_flags(struct slave *slave)
+static inline void bond_set_slave_inactive_flags(struct slave *slave)
{
slave->state = BOND_STATE_BACKUP;
slave->dev->flags |= IFF_NOARP;
}
-extern inline void bond_set_slave_active_flags(struct slave *slave)
+static inline void bond_set_slave_active_flags(struct slave *slave)
{
slave->state = BOND_STATE_ACTIVE;
slave->dev->flags &= ~IFF_NOARP;
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 1f7ca453bb4a..6e295fce5c6f 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -335,6 +335,30 @@ static inline void cas_mask_intr(struct cas *cp)
cas_disable_irq(cp, i);
}
+static inline void cas_buffer_init(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_set((atomic_t *)&page->lru.next, 1);
+}
+
+static inline int cas_buffer_count(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ return atomic_read((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_inc(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_inc((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_dec(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_dec((atomic_t *)&page->lru.next);
+}
+
static void cas_enable_irq(struct cas *cp, const int ring)
{
if (ring == 0) { /* all but TX_DONE */
@@ -472,6 +496,7 @@ 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);
+ cas_buffer_dec(page);
__free_pages(page->buffer, cp->page_order);
kfree(page);
return 0;
@@ -501,6 +526,7 @@ static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
page->buffer = alloc_pages(flags, cp->page_order);
if (!page->buffer)
goto page_err;
+ cas_buffer_init(page);
page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
cp->page_size, PCI_DMA_FROMDEVICE);
return page;
@@ -579,7 +605,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
list_for_each_safe(elem, tmp, &list) {
cas_page_t *page = list_entry(elem, cas_page_t, list);
- if (page_count(page->buffer) > 1)
+ if (cas_buffer_count(page) > 1)
continue;
list_del(elem);
@@ -1347,7 +1373,7 @@ 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)
+ if (cas_buffer_count(page) == 1)
return page;
new = cas_page_dequeue(cp);
@@ -1367,7 +1393,7 @@ static cas_page_t *cas_page_swap(struct cas *cp, const int ring,
cas_page_t **page1 = cp->rx_pages[1];
/* swap if buffer is in use */
- if (page_count(page0[index]->buffer) > 1) {
+ if (cas_buffer_count(page0[index]) > 1) {
cas_page_t *new = cas_page_spare(cp, index);
if (new) {
page1[index] = page0[index];
@@ -1925,8 +1951,8 @@ static void cas_tx(struct net_device *dev, struct cas *cp,
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);
+ printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %llx\n",
+ cp->dev->name, status, (unsigned long long)compwb);
/* process all the rings */
for (ring = 0; ring < N_TX_RINGS; ring++) {
#ifdef USE_TX_COMPWB
@@ -2039,6 +2065,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->len += hlen - swivel;
get_page(page->buffer);
+ cas_buffer_inc(page);
frag->page = page->buffer;
frag->page_offset = off;
frag->size = hlen - swivel;
@@ -2063,6 +2090,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
frag++;
get_page(page->buffer);
+ cas_buffer_inc(page);
frag->page = page->buffer;
frag->page_offset = 0;
frag->size = hlen;
@@ -2225,7 +2253,7 @@ static int cas_post_rxds_ringN(struct cas *cp, int ring, int num)
released = 0;
while (entry != last) {
/* make a new buffer if it's still in use */
- if (page_count(page[entry]->buffer) > 1) {
+ if (cas_buffer_count(page[entry]) > 1) {
cas_page_t *new = cas_page_dequeue(cp);
if (!new) {
/* let the timer know that we need to
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index a6078ad9b654..ef54ebeb29b8 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -87,6 +87,15 @@
Deepak Saxena : dsaxena@plexity.net
: Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
+ Dmitry Pervushin : dpervushin@ru.mvista.com
+ : PNX010X platform support
+
+ Deepak Saxena : dsaxena@plexity.net
+ : Intel IXDP2351 platform support
+
+ Dmitry Pervushin : dpervushin@ru.mvista.com
+ : PNX010X platform support
+
*/
/* Always include 'config.h' first in case the user wants to turn on
@@ -100,7 +109,7 @@
* Note that even if DMA is turned off we still support the 'dma' and 'use_dma'
* module options so we don't break any startup scripts.
*/
-#ifndef CONFIG_ARCH_IXDP2X01
+#ifndef CONFIG_ISA_DMA_API
#define ALLOW_DMA 0
#else
#define ALLOW_DMA 1
@@ -171,11 +180,15 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0};
static unsigned int netcard_portlist[] __initdata =
{ 0x0300, 0};
static unsigned int cs8900_irq_map[] = {1,0,0,0};
+#elif defined(CONFIG_MACH_IXDP2351)
+static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
+#include <asm/irq.h>
#elif defined(CONFIG_ARCH_IXDP2X01)
#include <asm/irq.h>
static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
-#elif defined(CONFIG_ARCH_PNX0105)
+#elif defined(CONFIG_ARCH_PNX010X)
#include <asm/irq.h>
#include <asm/arch/gpio.h>
#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */
@@ -338,30 +351,96 @@ out:
}
#endif
-static int
-readreg(struct net_device *dev, int portno)
+#if defined(CONFIG_MACH_IXDP2351)
+static u16
+readword(unsigned long base_addr, int portno)
{
- outw(portno, dev->base_addr + ADD_PORT);
- return inw(dev->base_addr + DATA_PORT);
+ return __raw_readw(base_addr + (portno << 1));
}
static void
-writereg(struct net_device *dev, int portno, int value)
+writeword(unsigned long base_addr, int portno, u16 value)
{
- outw(portno, dev->base_addr + ADD_PORT);
- outw(value, dev->base_addr + DATA_PORT);
+ __raw_writew(value, base_addr + (portno << 1));
+}
+#elif defined(CONFIG_ARCH_IXDP2X01)
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return __raw_readl(base_addr + (portno << 1));
}
-static int
-readword(struct net_device *dev, int portno)
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+ __raw_writel(value, base_addr + (portno << 1));
+}
+#elif defined(CONFIG_ARCH_PNX010X)
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return inw(base_addr + (portno << 1));
+}
+
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+ outw(value, base_addr + (portno << 1));
+}
+#else
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return inw(base_addr + portno);
+}
+
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+ outw(value, base_addr + portno);
+}
+#endif
+
+static void
+readwords(unsigned long base_addr, int portno, void *buf, int length)
+{
+ u8 *buf8 = (u8 *)buf;
+
+ do {
+ u16 tmp16;
+
+ tmp16 = readword(base_addr, portno);
+ *buf8++ = (u8)tmp16;
+ *buf8++ = (u8)(tmp16 >> 8);
+ } while (--length);
+}
+
+static void
+writewords(unsigned long base_addr, int portno, void *buf, int length)
+{
+ u8 *buf8 = (u8 *)buf;
+
+ do {
+ u16 tmp16;
+
+ tmp16 = *buf8++;
+ tmp16 |= (*buf8++) << 8;
+ writeword(base_addr, portno, tmp16);
+ } while (--length);
+}
+
+static u16
+readreg(struct net_device *dev, u16 regno)
{
- return inw(dev->base_addr + portno);
+ writeword(dev->base_addr, ADD_PORT, regno);
+ return readword(dev->base_addr, DATA_PORT);
}
static void
-writeword(struct net_device *dev, int portno, int value)
+writereg(struct net_device *dev, u16 regno, u16 value)
{
- outw(value, dev->base_addr + portno);
+ writeword(dev->base_addr, ADD_PORT, regno);
+ writeword(dev->base_addr, DATA_PORT, value);
}
static int __init
@@ -456,7 +535,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
#endif
}
-#ifdef CONFIG_ARCH_PNX0105
+#ifdef CONFIG_ARCH_PNX010X
initialize_ebi();
/* Map GPIO registers for the pins connected to the CS8900a. */
@@ -491,8 +570,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
#ifdef CONFIG_SH_HICOSH4
/* truely reset the chip */
- outw(0x0114, ioaddr + ADD_PORT);
- outw(0x0040, ioaddr + DATA_PORT);
+ writeword(ioaddr, ADD_PORT, 0x0114);
+ writeword(ioaddr, DATA_PORT, 0x0040);
#endif
/* if they give us an odd I/O address, then do ONE write to
@@ -503,24 +582,24 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
if (net_debug > 1)
printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
if ((ioaddr & 2) != 2)
- if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
+ if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
printk(KERN_ERR "%s: bad signature 0x%x\n",
- dev->name, inw((ioaddr & ~3)+ ADD_PORT));
+ dev->name, readword(ioaddr & ~3, ADD_PORT));
retval = -ENODEV;
goto out2;
}
}
- printk(KERN_DEBUG "PP_addr at %x: 0x%x\n",
- ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT));
+ printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
+ ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
ioaddr &= ~3;
- outw(PP_ChipID, ioaddr + ADD_PORT);
+ writeword(ioaddr, ADD_PORT, PP_ChipID);
- tmp = inw(ioaddr + DATA_PORT);
+ tmp = readword(ioaddr, DATA_PORT);
if (tmp != CHIP_EISA_ID_SIG) {
- printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!="
+ printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!="
CHIP_EISA_ID_SIG_STR "\n",
- dev->name, ioaddr + DATA_PORT, tmp);
+ dev->name, ioaddr, DATA_PORT, tmp);
retval = -ENODEV;
goto out2;
}
@@ -724,7 +803,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
} else {
i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) {
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
+#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X)
i = cs8900_irq_map[0];
#else
/* Translate the IRQ using the IRQ mapping table. */
@@ -790,7 +869,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
goto out3;
return 0;
out3:
- outw(PP_ChipID, dev->base_addr + ADD_PORT);
+ writeword(dev->base_addr, ADD_PORT, PP_ChipID);
out2:
release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
out1:
@@ -956,7 +1035,7 @@ skip_this_frame:
void __init reset_chip(struct net_device *dev)
{
-#ifndef CONFIG_ARCH_IXDP2X01
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
struct net_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
#endif
@@ -967,14 +1046,14 @@ void __init reset_chip(struct net_device *dev)
/* wait 30 ms */
msleep(30);
-#ifndef CONFIG_ARCH_IXDP2X01
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
if (lp->chip_type != CS8900) {
/* Hardware problem requires PNP registers to be reconfigured after a reset */
- outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT);
+ writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
outb(dev->irq, ioaddr + DATA_PORT);
outb(0, ioaddr + DATA_PORT + 1);
- outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT);
+ writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1);
}
@@ -1104,8 +1183,8 @@ send_test_pkt(struct net_device *dev)
memcpy(test_packet, dev->dev_addr, ETH_ALEN);
memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
- writeword(dev, TX_CMD_PORT, TX_AFTER_ALL);
- writeword(dev, TX_LEN_PORT, ETH_ZLEN);
+ writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
+ writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
/* Test to see if the chip has allocated memory for the packet */
while (jiffies - timenow < 5)
@@ -1115,7 +1194,7 @@ send_test_pkt(struct net_device *dev)
return 0; /* this shouldn't happen */
/* Write the contents of the packet */
- outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
+ writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
if (net_debug > 1) printk("Sending test packet ");
/* wait a couple of jiffies for packet to be received */
@@ -1200,7 +1279,7 @@ net_open(struct net_device *dev)
int i;
int ret;
-#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */
+#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */
if (dev->irq < 2) {
/* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
@@ -1231,7 +1310,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105)
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
@@ -1316,7 +1395,7 @@ net_open(struct net_device *dev)
case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
}
-#ifdef CONFIG_ARCH_PNX0105
+#ifdef CONFIG_ARCH_PNX010X
result = A_CNF_10B_T;
#endif
if (!result) {
@@ -1457,8 +1536,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
/* initiate a transmit sequence */
- writeword(dev, TX_CMD_PORT, lp->send_cmd);
- writeword(dev, TX_LEN_PORT, skb->len);
+ writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
+ writeword(dev->base_addr, TX_LEN_PORT, skb->len);
/* Test to see if the chip has allocated memory for the packet */
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
@@ -1472,7 +1551,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
return 1;
}
/* Write the contents of the packet */
- outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+ writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
spin_unlock_irq(&lp->lock);
lp->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
@@ -1512,7 +1591,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
course, if you're on a slow machine, and packets are arriving
faster than you can read them off, you're screwed. Hasta la
vista, baby! */
- while ((status = readword(dev, ISQ_PORT))) {
+ while ((status = readword(dev->base_addr, ISQ_PORT))) {
if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
handled = 1;
switch(status & ISQ_EVENT_MASK) {
@@ -1606,8 +1685,8 @@ net_rx(struct net_device *dev)
int status, length;
int ioaddr = dev->base_addr;
- status = inw(ioaddr + RX_FRAME_PORT);
- length = inw(ioaddr + RX_FRAME_PORT);
+ status = readword(ioaddr, RX_FRAME_PORT);
+ length = readword(ioaddr, RX_FRAME_PORT);
if ((status & RX_OK) == 0) {
count_rx_errors(status, lp);
@@ -1626,9 +1705,9 @@ net_rx(struct net_device *dev)
skb_reserve(skb, 2); /* longword align L3 header */
skb->dev = dev;
- insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);
+ readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
if (length & 1)
- skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
+ skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
if (net_debug > 3) {
printk( "%s: received %d byte packet of type %x\n",
@@ -1901,7 +1980,7 @@ void
cleanup_module(void)
{
unregister_netdev(dev_cs89x0);
- outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT);
+ writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
free_netdev(dev_cs89x0);
}
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index decea264f121..bd954aaa636f 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -16,13 +16,6 @@
#include <linux/config.h>
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
-/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
-#define CS89x0_PORT(reg) ((reg) * 2)
-#else
-#define CS89x0_PORT(reg) (reg)
-#endif
-
#define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */
/* offset 2h -> Model/Product Number */
/* offset 3h -> Chip Revision Number */
@@ -332,16 +325,16 @@
#define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */
#define PKT_START PP_TxFrame /* Start of packet RAM */
-#define RX_FRAME_PORT CS89x0_PORT(0x0000)
+#define RX_FRAME_PORT 0x0000
#define TX_FRAME_PORT RX_FRAME_PORT
-#define TX_CMD_PORT CS89x0_PORT(0x0004)
+#define TX_CMD_PORT 0x0004
#define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */
#define TX_AFTER_381 0x0040 /* Tx packet after 381 bytes copied */
#define TX_AFTER_ALL 0x00c0 /* Tx packet after all bytes copied */
-#define TX_LEN_PORT CS89x0_PORT(0x0006)
-#define ISQ_PORT CS89x0_PORT(0x0008)
-#define ADD_PORT CS89x0_PORT(0x000A)
-#define DATA_PORT CS89x0_PORT(0x000C)
+#define TX_LEN_PORT 0x0006
+#define ISQ_PORT 0x0008
+#define ADD_PORT 0x000A
+#define DATA_PORT 0x000C
#define EEPROM_WRITE_EN 0x00F0
#define EEPROM_WRITE_DIS 0x0000
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 22cd04556707..bf1fd2b98bf8 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,25 +1,25 @@
/*******************************************************************************
-
+
Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your option)
+
+ This program is free software; you can redistribute 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
+
+ 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
+ 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:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -132,6 +132,10 @@
* TODO:
* o several entry points race with dev->close
* o check for tx-no-resources/stop Q races with tx clean/wake Q
+ *
+ * FIXES:
+ * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
+ * - Stratus87247: protect MDI control register manipulations
*/
#include <linux/config.h>
@@ -156,7 +160,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.4.14-k4"DRV_EXT
+#define DRV_VERSION "3.5.10-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 ": "
@@ -316,7 +320,7 @@ enum cuc_dump {
cuc_dump_complete = 0x0000A005,
cuc_dump_reset_complete = 0x0000A007,
};
-
+
enum port {
software_reset = 0x0000,
selftest = 0x0001,
@@ -578,6 +582,7 @@ struct nic {
u16 leds;
u16 eeprom_wc;
u16 eeprom[256];
+ spinlock_t mdio_lock;
};
static inline void e100_write_flush(struct nic *nic)
@@ -587,7 +592,7 @@ static inline void e100_write_flush(struct nic *nic)
(void)readb(&nic->csr->scb.status);
}
-static inline void e100_enable_irq(struct nic *nic)
+static void e100_enable_irq(struct nic *nic)
{
unsigned long flags;
@@ -597,7 +602,7 @@ static inline void e100_enable_irq(struct nic *nic)
e100_write_flush(nic);
}
-static inline void e100_disable_irq(struct nic *nic)
+static void e100_disable_irq(struct nic *nic)
{
unsigned long flags;
@@ -710,10 +715,10 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
-
+
writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
-
+
/* Eeprom drives a dummy zero to EEDO after receiving
* complete address. Use this to adjust addr_len. */
ctrl = readb(&nic->csr->eeprom_ctrl_lo);
@@ -721,7 +726,7 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
*addr_len -= (i - 16);
i = 17;
}
-
+
data = (data << 1) | (ctrl & eedo ? 1 : 0);
}
@@ -786,7 +791,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)
+static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
unsigned long flags;
unsigned int i;
@@ -817,7 +822,7 @@ err_unlock:
return err;
}
-static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
+static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
{
struct cb *cb;
@@ -876,15 +881,35 @@ static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
{
u32 data_out = 0;
unsigned int i;
+ unsigned long flags;
+
+ /*
+ * Stratus87247: we shouldn't be writing the MDI control
+ * register until the Ready bit shows True. Also, since
+ * manipulation of the MDI control registers is a multi-step
+ * procedure it should be done under lock.
+ */
+ spin_lock_irqsave(&nic->mdio_lock, flags);
+ for (i = 100; i; --i) {
+ if (readl(&nic->csr->mdi_ctrl) & mdi_ready)
+ break;
+ udelay(20);
+ }
+ if (unlikely(!i)) {
+ printk("e100.mdio_ctrl(%s) won't go Ready\n",
+ nic->netdev->name );
+ spin_unlock_irqrestore(&nic->mdio_lock, flags);
+ return 0; /* No way to indicate timeout error */
+ }
writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
- for(i = 0; i < 100; i++) {
+ for (i = 0; i < 100; i++) {
udelay(20);
- if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready)
+ if ((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready)
break;
}
-
+ spin_unlock_irqrestore(&nic->mdio_lock, flags);
DPRINTK(HW, DEBUG,
"%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out);
@@ -1145,7 +1170,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
}
-static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
/* *INDENT-OFF* */
static struct {
@@ -1188,13 +1213,13 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* driver can change the algorithm.
*
* INTDELAY - This loads the dead-man timer with its inital value.
-* When this timer expires the interrupt is asserted, and the
+* When this timer expires the interrupt is asserted, and the
* timer is reset each time a new packet is received. (see
* BUNDLEMAX below to set the limit on number of chained packets)
* The current default is 0x600 or 1536. Experiments show that
* the value should probably stay within the 0x200 - 0x1000.
*
-* BUNDLEMAX -
+* BUNDLEMAX -
* This sets the maximum number of frames that will be bundled. In
* some situations, such as the TCP windowing algorithm, it may be
* better to limit the growth of the bundle size than let it go as
@@ -1204,7 +1229,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* an interrupt for every frame received. If you do not want to put
* a limit on the bundle size, set this value to xFFFF.
*
-* BUNDLESMALL -
+* BUNDLESMALL -
* This contains a bit-mask describing the minimum size frame that
* will be bundled. The default masks the lower 7 bits, which means
* that any frame less than 128 bytes in length will not be bundled,
@@ -1219,7 +1244,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
*
* The current default is 0xFF80, which masks out the lower 7 bits.
* This means that any frame which is x7F (127) bytes or smaller
-* will cause an immediate interrupt. Because this value must be a
+* will cause an immediate interrupt. Because this value must be a
* bit mask, there are only a few valid values that can be used. To
* turn this feature off, the driver can write the value xFFFF to the
* lower word of this instruction (in the same way that the other
@@ -1228,7 +1253,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* standard Ethernet frames are <= 2047 bytes in length.
*************************************************************************/
-/* if you wish to disable the ucode functionality, while maintaining the
+/* if you wish to disable the ucode functionality, while maintaining the
* workarounds it provides, set the following defines to:
* BUNDLESMALL 0
* BUNDLEMAX 1
@@ -1259,12 +1284,46 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
for (i = 0; i < UCODE_SIZE; i++)
cb->u.ucode[i] = cpu_to_le32(ucode[i]);
- cb->command = cpu_to_le16(cb_ucode);
+ cb->command = cpu_to_le16(cb_ucode | cb_el);
return;
}
noloaducode:
- cb->command = cpu_to_le16(cb_nop);
+ cb->command = cpu_to_le16(cb_nop | cb_el);
+}
+
+static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
+ void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+{
+ int err = 0, counter = 50;
+ struct cb *cb = nic->cb_to_clean;
+
+ if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode)))
+ DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
+
+ /* must restart cuc */
+ nic->cuc_cmd = cuc_start;
+
+ /* wait for completion */
+ e100_write_flush(nic);
+ udelay(10);
+
+ /* wait for possibly (ouch) 500ms */
+ while (!(cb->status & cpu_to_le16(cb_complete))) {
+ msleep(10);
+ if (!--counter) break;
+ }
+
+ /* ack any interupts, something could have been set */
+ writeb(~0, &nic->csr->scb.stat_ack);
+
+ /* if the command failed, or is not OK, notify and return */
+ if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
+ DPRINTK(PROBE,ERR, "ucode load failed\n");
+ err = -EPERM;
+ }
+
+ return err;
}
static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
@@ -1332,13 +1391,13 @@ static int e100_phy_init(struct nic *nic)
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
}
- if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
+ if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) {
/* enable/disable MDI/MDI-X auto-switching.
MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */
if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) ||
- (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
- !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
+ (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
+ !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0);
else
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH);
@@ -1363,7 +1422,7 @@ static int e100_hw_init(struct nic *nic)
return err;
if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
return err;
- if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+ if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
return err;
if((err = e100_exec_cb(nic, NULL, e100_configure)))
return err;
@@ -1468,7 +1527,7 @@ static void e100_update_stats(struct nic *nic)
}
}
-
+
if(e100_exec_cmd(nic, cuc_dump_reset, 0))
DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}
@@ -1517,10 +1576,10 @@ static void e100_watchdog(unsigned long data)
mii_check_link(&nic->mii);
/* Software generated interrupt to recover from (rare) Rx
- * allocation failure.
- * Unfortunately have to use a spinlock to not re-enable interrupts
- * accidentally, due to hardware that shares a register between the
- * interrupt mask bit and the SW Interrupt generation bit */
+ * allocation failure.
+ * Unfortunately have to use a spinlock to not re-enable interrupts
+ * accidentally, due to hardware that shares a register between the
+ * interrupt mask bit and the SW Interrupt generation bit */
spin_lock_irq(&nic->cmd_lock);
writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
spin_unlock_irq(&nic->cmd_lock);
@@ -1542,7 +1601,7 @@ static void e100_watchdog(unsigned long data)
mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD);
}
-static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
+static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
cb->command = nic->tx_command;
@@ -1592,7 +1651,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return 0;
}
-static inline int e100_tx_clean(struct nic *nic)
+static int e100_tx_clean(struct nic *nic)
{
struct cb *cb;
int tx_cleaned = 0;
@@ -1703,7 +1762,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
}
#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
-static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
+static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
{
if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))
return -ENOMEM;
@@ -1737,7 +1796,7 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
return 0;
}
-static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
+static int e100_rx_indicate(struct nic *nic, struct rx *rx,
unsigned int *work_done, unsigned int work_to_do)
{
struct sk_buff *skb = rx->skb;
@@ -1797,7 +1856,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
return 0;
}
-static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
+static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
unsigned int work_to_do)
{
struct rx *rx;
@@ -1805,7 +1864,7 @@ static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
struct rx *rx_to_start = NULL;
/* are we already rnr? then pay attention!!! this ensures that
- * the state machine progression never allows a start with a
+ * the state machine progression never allows a start with a
* partially cleaned list, avoiding a race between hardware
* and rx_to_clean when in NAPI mode */
if(RU_SUSPENDED == nic->ru_running)
@@ -2041,7 +2100,7 @@ static void e100_tx_timeout(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
- /* Reset outside of interrupt context, to avoid request_irq
+ /* Reset outside of interrupt context, to avoid request_irq
* in interrupt context */
schedule_work(&nic->tx_timeout_task);
}
@@ -2288,7 +2347,7 @@ static int e100_set_ringparam(struct net_device *netdev,
struct param_range *rfds = &nic->params.rfds;
struct param_range *cbs = &nic->params.cbs;
- if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
if(netif_running(netdev))
@@ -2562,6 +2621,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
/* locks must be initialized before calling hw_reset */
spin_lock_init(&nic->cb_lock);
spin_lock_init(&nic->cmd_lock);
+ spin_lock_init(&nic->mdio_lock);
/* Reset the device before pci_set_master() in case device is in some
* funky state and has an interrupt pending - hint: we don't have the
@@ -2605,7 +2665,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->flags |= wol_magic;
/* ack any pending wake events, disable PME */
- pci_enable_wake(pdev, 0, 0);
+ err = pci_enable_wake(pdev, 0, 0);
+ if (err)
+ DPRINTK(PROBE, ERR, "Error clearing wake event\n");
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
@@ -2656,6 +2718,7 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
if(netif_running(netdev))
e100_down(nic);
@@ -2663,9 +2726,14 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
netif_device_detach(netdev);
pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), nic->flags & (wol_magic | e100_asf(nic)));
+ retval = pci_enable_wake(pdev, pci_choose_state(pdev, state),
+ nic->flags & (wol_magic | e100_asf(nic)));
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error enabling wake\n");
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error %d setting power state\n", retval);
return 0;
}
@@ -2674,11 +2742,16 @@ static int e100_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
- pci_set_power_state(pdev, PCI_D0);
+ retval = pci_set_power_state(pdev, PCI_D0);
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error waking adapter\n");
pci_restore_state(pdev);
/* ack any pending wake events, disable PME */
- pci_enable_wake(pdev, 0, 0);
+ retval = pci_enable_wake(pdev, 0, 0);
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error clearing wake events\n");
if(e100_hw_init(nic))
DPRINTK(HW, ERR, "e100_hw_init failed\n");
@@ -2695,12 +2768,15 @@ static void e100_shutdown(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
#ifdef CONFIG_PM
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+ retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
#else
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
+ retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
#endif
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error enabling wake\n");
}
@@ -2713,7 +2789,7 @@ static struct pci_driver e100_driver = {
.suspend = e100_suspend,
.resume = e100_resume,
#endif
- .shutdown = e100_shutdown,
+ .shutdown = e100_shutdown,
};
static int __init e100_init_module(void)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index e02e9ba2e18b..27c77306193b 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,10 +72,6 @@
#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
@@ -87,6 +83,10 @@
struct e1000_adapter;
#include "e1000_hw.h"
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
#ifdef DBG
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
@@ -169,6 +169,13 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
+#ifdef CONFIG_E1000_MQ
+struct e1000_queue_stats {
+ uint64_t packets;
+ uint64_t bytes;
+};
+#endif
+
struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
@@ -191,10 +198,12 @@ struct e1000_tx_ring {
spinlock_t tx_lock;
uint16_t tdh;
uint16_t tdt;
- uint64_t pkt;
boolean_t last_tx_tso;
+#ifdef CONFIG_E1000_MQ
+ struct e1000_queue_stats tx_stats;
+#endif
};
struct e1000_rx_ring {
@@ -216,9 +225,17 @@ struct e1000_rx_ring {
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *rx_skb_top;
+ struct sk_buff *rx_skb_prev;
+
+ /* cpu for rx queue */
+ int cpu;
+
uint16_t rdh;
uint16_t rdt;
- uint64_t pkt;
+#ifdef CONFIG_E1000_MQ
+ struct e1000_queue_stats rx_stats;
+#endif
};
#define E1000_DESC_UNUSED(R) \
@@ -251,6 +268,9 @@ struct e1000_adapter {
uint16_t link_speed;
uint16_t link_duplex;
spinlock_t stats_lock;
+#ifdef CONFIG_E1000_NAPI
+ spinlock_t tx_queue_lock;
+#endif
atomic_t irq_sem;
struct work_struct tx_timeout_task;
struct work_struct watchdog_task;
@@ -264,6 +284,7 @@ struct e1000_adapter {
#ifdef CONFIG_E1000_MQ
struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
#endif
+ unsigned long tx_queue_len;
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
@@ -271,9 +292,11 @@ struct e1000_adapter {
uint64_t gotcl_old;
uint64_t tpt_old;
uint64_t colc_old;
+ uint32_t tx_timeout_count;
uint32_t tx_fifo_head;
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
+ uint8_t tx_timeout_factor;
atomic_t tx_fifo_stall;
boolean_t pcix_82544;
boolean_t detect_tx_hung;
@@ -281,14 +304,15 @@ struct e1000_adapter {
/* RX */
#ifdef CONFIG_E1000_NAPI
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
#else
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring);
#endif
void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */
#ifdef CONFIG_E1000_NAPI
struct net_device *polling_netdev; /* One per active queue */
@@ -296,13 +320,15 @@ struct e1000_adapter {
#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];
+ cpumask_t cpumask;
#endif
- int num_queues;
+ int num_tx_queues;
+ int num_rx_queues;
uint64_t hw_csum_err;
uint64_t hw_csum_good;
uint64_t rx_hdr_split;
+ uint32_t alloc_rx_buff_failed;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
@@ -330,6 +356,7 @@ struct e1000_adapter {
struct e1000_rx_ring test_rx_ring;
+ u32 *config_space;
int msg_enable;
#ifdef CONFIG_PCI_MSI
boolean_t have_msi;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index c88f1a3c1b1d..5cedc81786e3 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -80,6 +80,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_deferred_ok", E1000_STAT(stats.dc) },
{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
+ { "tx_timeout_count", E1000_STAT(tx_timeout_count) },
{ "rx_long_length_errors", E1000_STAT(stats.roc) },
{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
@@ -93,9 +94,20 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
{ "rx_header_split", E1000_STAT(rx_hdr_split) },
+ { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
};
-#define E1000_STATS_LEN \
+
+#ifdef CONFIG_E1000_MQ
+#define E1000_QUEUE_STATS_LEN \
+ (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \
+ ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \
+ * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t))
+#else
+#define E1000_QUEUE_STATS_LEN 0
+#endif
+#define E1000_GLOBAL_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
+#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
"Register test (offline)", "Eeprom test (offline)",
"Interrupt test (offline)", "Loopback test (offline)",
@@ -109,7 +121,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- if(hw->media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
@@ -121,7 +133,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_TP;
- if(hw->autoneg == 1) {
+ if (hw->autoneg == 1) {
ecmd->advertising |= ADVERTISED_Autoneg;
/* the e1000 autoneg seems to match ethtool nicely */
@@ -132,7 +144,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
- if(hw->mac_type == e1000_82543)
+ if (hw->mac_type == e1000_82543)
ecmd->transceiver = XCVR_EXTERNAL;
else
ecmd->transceiver = XCVR_INTERNAL;
@@ -148,13 +160,13 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
- if(hw->mac_type >= e1000_82545)
+ if (hw->mac_type >= e1000_82545)
ecmd->transceiver = XCVR_INTERNAL;
else
ecmd->transceiver = XCVR_EXTERNAL;
}
- if(netif_carrier_ok(adapter->netdev)) {
+ if (netif_carrier_ok(adapter->netdev)) {
e1000_get_speed_and_duplex(hw, &adapter->link_speed,
&adapter->link_duplex);
@@ -163,7 +175,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
* and HALF_DUPLEX != DUPLEX_HALF */
- if(adapter->link_duplex == FULL_DUPLEX)
+ if (adapter->link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
@@ -183,13 +195,21 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- if(ecmd->autoneg == AUTONEG_ENABLE) {
+ /* When SoL/IDER sessions are active, autoneg/speed/duplex
+ * cannot be changed */
+ if (e1000_check_phy_reset_block(hw)) {
+ DPRINTK(DRV, ERR, "Cannot change link characteristics "
+ "when SoL/IDER is active.\n");
+ return -EINVAL;
+ }
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
hw->autoneg = 1;
- if(hw->media_type == e1000_media_type_fiber)
+ if (hw->media_type == e1000_media_type_fiber)
hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg;
- else
+ else
hw->autoneg_advertised = ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
@@ -199,12 +219,12 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ADVERTISED_TP;
ecmd->advertising = hw->autoneg_advertised;
} else
- if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
+ if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
return -EINVAL;
/* reset the link */
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_reset(adapter);
e1000_up(adapter);
@@ -221,14 +241,14 @@ e1000_get_pauseparam(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- pause->autoneg =
+ pause->autoneg =
(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-
- if(hw->fc == e1000_fc_rx_pause)
+
+ if (hw->fc == e1000_fc_rx_pause)
pause->rx_pause = 1;
- else if(hw->fc == e1000_fc_tx_pause)
+ else if (hw->fc == e1000_fc_tx_pause)
pause->tx_pause = 1;
- else if(hw->fc == e1000_fc_full) {
+ else if (hw->fc == e1000_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
}
@@ -240,31 +260,30 @@ e1000_set_pauseparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
-
+
adapter->fc_autoneg = pause->autoneg;
- if(pause->rx_pause && pause->tx_pause)
+ if (pause->rx_pause && pause->tx_pause)
hw->fc = e1000_fc_full;
- else if(pause->rx_pause && !pause->tx_pause)
+ else if (pause->rx_pause && !pause->tx_pause)
hw->fc = e1000_fc_rx_pause;
- else if(!pause->rx_pause && pause->tx_pause)
+ else if (!pause->rx_pause && pause->tx_pause)
hw->fc = e1000_fc_tx_pause;
- else if(!pause->rx_pause && !pause->tx_pause)
+ else if (!pause->rx_pause && !pause->tx_pause)
hw->fc = e1000_fc_none;
hw->original_fc = hw->fc;
- if(adapter->fc_autoneg == AUTONEG_ENABLE) {
- if(netif_running(adapter->netdev)) {
+ if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
- }
- else
+ } else
return ((hw->media_type == e1000_media_type_fiber) ?
e1000_setup_link(hw) : e1000_force_mac_fc(hw));
-
+
return 0;
}
@@ -281,14 +300,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data;
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
return 0;
}
-
+
static uint32_t
e1000_get_tx_csum(struct net_device *netdev)
{
@@ -300,7 +319,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(adapter->hw.mac_type < e1000_82543) {
+ if (adapter->hw.mac_type < e1000_82543) {
if (!data)
return -EINVAL;
return 0;
@@ -319,8 +338,8 @@ static int
e1000_set_tso(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if((adapter->hw.mac_type < e1000_82544) ||
- (adapter->hw.mac_type == e1000_82547))
+ if ((adapter->hw.mac_type < e1000_82544) ||
+ (adapter->hw.mac_type == e1000_82547))
return data ? -EINVAL : 0;
if (data)
@@ -328,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
else
netdev->features &= ~NETIF_F_TSO;
return 0;
-}
+}
#endif /* NETIF_F_TSO */
static uint32_t
@@ -345,7 +364,7 @@ e1000_set_msglevel(struct net_device *netdev, uint32_t data)
adapter->msg_enable = data;
}
-static int
+static int
e1000_get_regs_len(struct net_device *netdev)
{
#define E1000_REGS_LEN 32
@@ -381,7 +400,7 @@ e1000_get_regs(struct net_device *netdev,
regs_buff[11] = E1000_READ_REG(hw, TIDV);
regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */
- if(hw->phy_type == e1000_phy_igp) {
+ if (hw->phy_type == e1000_phy_igp) {
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_A);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
@@ -435,7 +454,7 @@ e1000_get_regs(struct net_device *netdev,
e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
- if(hw->mac_type >= e1000_82540 &&
+ if (hw->mac_type >= e1000_82540 &&
hw->media_type == e1000_media_type_copper) {
regs_buff[26] = E1000_READ_REG(hw, MANC);
}
@@ -459,7 +478,7 @@ e1000_get_eeprom(struct net_device *netdev,
int ret_val = 0;
uint16_t i;
- if(eeprom->len == 0)
+ if (eeprom->len == 0)
return -EINVAL;
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -469,16 +488,16 @@ e1000_get_eeprom(struct net_device *netdev,
eeprom_buff = kmalloc(sizeof(uint16_t) *
(last_word - first_word + 1), GFP_KERNEL);
- if(!eeprom_buff)
+ if (!eeprom_buff)
return -ENOMEM;
- if(hw->eeprom.type == e1000_eeprom_spi)
+ if (hw->eeprom.type == e1000_eeprom_spi)
ret_val = e1000_read_eeprom(hw, first_word,
last_word - first_word + 1,
eeprom_buff);
else {
for (i = 0; i < last_word - first_word + 1; i++)
- if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+ if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
&eeprom_buff[i])))
break;
}
@@ -505,10 +524,10 @@ e1000_set_eeprom(struct net_device *netdev,
int max_len, first_word, last_word, ret_val = 0;
uint16_t i;
- if(eeprom->len == 0)
+ if (eeprom->len == 0)
return -EOPNOTSUPP;
- if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
max_len = hw->eeprom.word_size * 2;
@@ -516,19 +535,19 @@ e1000_set_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
eeprom_buff = kmalloc(max_len, GFP_KERNEL);
- if(!eeprom_buff)
+ if (!eeprom_buff)
return -ENOMEM;
ptr = (void *)eeprom_buff;
- if(eeprom->offset & 1) {
+ if (eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
ptr++;
}
- if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
+ if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
ret_val = e1000_read_eeprom(hw, last_word, 1,
@@ -547,9 +566,9 @@ 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
+ /* 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) ||
+ if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
(hw->mac_type == e1000_82573)))
e1000_update_eeprom_checksum(hw);
@@ -567,21 +586,21 @@ e1000_get_drvinfo(struct net_device *netdev,
strncpy(drvinfo->driver, e1000_driver_name, 32);
strncpy(drvinfo->version, e1000_driver_version, 32);
-
- /* EEPROM image version # is reported as firware version # for
+
+ /* EEPROM image version # is reported as firmware version # for
* 8257{1|2|3} controllers */
e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
switch (adapter->hw.mac_type) {
case e1000_82571:
case e1000_82572:
case e1000_82573:
- sprintf(firmware_version, "%d.%d-%d",
+ sprintf(firmware_version, "%d.%d-%d",
(eeprom_data & 0xF000) >> 12,
(eeprom_data & 0x0FF0) >> 4,
eeprom_data & 0x000F);
break;
default:
- sprintf(firmware_version, "n/a");
+ sprintf(firmware_version, "N/A");
}
strncpy(drvinfo->fw_version, firmware_version, 32);
@@ -613,7 +632,7 @@ e1000_get_ringparam(struct net_device *netdev,
ring->rx_jumbo_pending = 0;
}
-static int
+static int
e1000_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
@@ -623,8 +642,8 @@ e1000_set_ringparam(struct net_device *netdev,
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;
+ tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
+ rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
if (netif_running(adapter->netdev))
e1000_down(adapter);
@@ -650,25 +669,25 @@ e1000_set_ringparam(struct net_device *netdev,
txdr = adapter->tx_ring;
rxdr = adapter->rx_ring;
- if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
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));
- E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+ E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD));
- E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
txdr[i].count = txdr->count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
rxdr[i].count = rxdr->count;
- }
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
@@ -688,7 +707,7 @@ e1000_set_ringparam(struct net_device *netdev,
kfree(rx_old);
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
- if((err = e1000_up(adapter)))
+ if ((err = e1000_up(adapter)))
return err;
}
@@ -707,10 +726,10 @@ err_setup_rx:
uint32_t pat, value; \
uint32_t test[] = \
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
- for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
+ for (pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
value = E1000_READ_REG(&adapter->hw, R); \
- if(value != (test[pat] & W & M)) { \
+ if (value != (test[pat] & W & M)) { \
DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
"0x%08X expected 0x%08X\n", \
E1000_##R, value, (test[pat] & W & M)); \
@@ -726,7 +745,7 @@ err_setup_rx:
uint32_t value; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
value = E1000_READ_REG(&adapter->hw, R); \
- if((W & M) != (value & M)) { \
+ if ((W & M) != (value & M)) { \
DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
"expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \
*data = (adapter->hw.mac_type < e1000_82543) ? \
@@ -762,7 +781,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
- if(value != after) {
+ if (value != after) {
DPRINTK(DRV, ERR, "failed STATUS register test got: "
"0x%08X expected: 0x%08X\n", after, value);
*data = 1;
@@ -790,7 +809,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
- if(adapter->hw.mac_type >= e1000_82543) {
+ if (adapter->hw.mac_type >= e1000_82543) {
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
@@ -798,7 +817,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
- for(i = 0; i < E1000_RAR_ENTRIES; i++) {
+ for (i = 0; i < E1000_RAR_ENTRIES; i++) {
REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
0xFFFFFFFF);
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -814,7 +833,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
}
- for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+ for (i = 0; i < E1000_MC_TBL_SIZE; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0;
@@ -830,8 +849,8 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Read and add up the contents of the EEPROM */
- for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+ for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
*data = 1;
break;
}
@@ -839,7 +858,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
}
/* If Checksum is not Correct return error else test passed */
- if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
+ if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
*data = 2;
return *data;
@@ -868,9 +887,9 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Hook up test interrupt handler just for this test */
- if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
shared_int = FALSE;
- } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+ } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
netdev->name, netdev)){
*data = 1;
return -1;
@@ -881,12 +900,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
msec_delay(10);
/* Test each interrupt */
- for(; i < 10; i++) {
+ for (; i < 10; i++) {
/* Interrupt to test */
mask = 1 << i;
- if(!shared_int) {
+ if (!shared_int) {
/* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
@@ -897,8 +916,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, IMC, mask);
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
-
- if(adapter->test_icr & mask) {
+
+ if (adapter->test_icr & mask) {
*data = 3;
break;
}
@@ -915,12 +934,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
- if(!(adapter->test_icr & mask)) {
+ if (!(adapter->test_icr & mask)) {
*data = 4;
break;
}
- if(!shared_int) {
+ if (!shared_int) {
/* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted. If
@@ -932,7 +951,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
msec_delay(10);
- if(adapter->test_icr) {
+ if (adapter->test_icr) {
*data = 5;
break;
}
@@ -957,40 +976,39 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
int i;
- if(txdr->desc && txdr->buffer_info) {
- for(i = 0; i < txdr->count; i++) {
- if(txdr->buffer_info[i].dma)
+ if (txdr->desc && txdr->buffer_info) {
+ for (i = 0; i < txdr->count; i++) {
+ if (txdr->buffer_info[i].dma)
pci_unmap_single(pdev, txdr->buffer_info[i].dma,
txdr->buffer_info[i].length,
PCI_DMA_TODEVICE);
- if(txdr->buffer_info[i].skb)
+ if (txdr->buffer_info[i].skb)
dev_kfree_skb(txdr->buffer_info[i].skb);
}
}
- if(rxdr->desc && rxdr->buffer_info) {
- for(i = 0; i < rxdr->count; i++) {
- if(rxdr->buffer_info[i].dma)
+ if (rxdr->desc && rxdr->buffer_info) {
+ for (i = 0; i < rxdr->count; i++) {
+ if (rxdr->buffer_info[i].dma)
pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
rxdr->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
- if(rxdr->buffer_info[i].skb)
+ if (rxdr->buffer_info[i].skb)
dev_kfree_skb(rxdr->buffer_info[i].skb);
}
}
- if(txdr->desc) {
+ if (txdr->desc) {
pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
txdr->desc = NULL;
}
- if(rxdr->desc) {
+ if (rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
rxdr->desc = NULL;
}
kfree(txdr->buffer_info);
txdr->buffer_info = NULL;
-
kfree(rxdr->buffer_info);
rxdr->buffer_info = NULL;
@@ -1008,11 +1026,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Tx descriptor ring and Tx buffers */
- if(!txdr->count)
- txdr->count = E1000_DEFAULT_TXD;
+ if (!txdr->count)
+ txdr->count = E1000_DEFAULT_TXD;
size = txdr->count * sizeof(struct e1000_buffer);
- if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ if (!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 1;
goto err_nomem;
}
@@ -1020,7 +1038,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
E1000_ROUNDUP(txdr->size, 4096);
- if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
+ if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
ret_val = 2;
goto err_nomem;
}
@@ -1039,12 +1057,12 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
- for(i = 0; i < txdr->count; i++) {
+ for (i = 0; i < txdr->count; i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
struct sk_buff *skb;
unsigned int size = 1024;
- if(!(skb = alloc_skb(size, GFP_KERNEL))) {
+ if (!(skb = alloc_skb(size, GFP_KERNEL))) {
ret_val = 3;
goto err_nomem;
}
@@ -1064,18 +1082,18 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Rx descriptor ring and Rx buffers */
- if(!rxdr->count)
- rxdr->count = E1000_DEFAULT_RXD;
+ if (!rxdr->count)
+ rxdr->count = E1000_DEFAULT_RXD;
size = rxdr->count * sizeof(struct e1000_buffer);
- if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ if (!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 4;
goto err_nomem;
}
memset(rxdr->buffer_info, 0, size);
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
- if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+ if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
ret_val = 5;
goto err_nomem;
}
@@ -1095,11 +1113,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- for(i = 0; i < rxdr->count; i++) {
+ for (i = 0; i < rxdr->count; i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
- if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
+ if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
GFP_KERNEL))) {
ret_val = 6;
goto err_nomem;
@@ -1208,15 +1226,15 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
/* Check Phy Configuration */
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
- if(phy_reg != 0x4100)
+ if (phy_reg != 0x4100)
return 9;
e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
- if(phy_reg != 0x0070)
+ if (phy_reg != 0x0070)
return 10;
e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
- if(phy_reg != 0x001A)
+ if (phy_reg != 0x001A)
return 11;
return 0;
@@ -1230,7 +1248,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
adapter->hw.autoneg = FALSE;
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
e1000_write_phy_reg(&adapter->hw,
M88E1000_PHY_SPEC_CTRL, 0x0808);
@@ -1250,14 +1268,14 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
- if(adapter->hw.media_type == e1000_media_type_copper &&
+ if (adapter->hw.media_type == e1000_media_type_copper &&
adapter->hw.phy_type == e1000_phy_m88) {
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
} else {
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
- if((stat_reg & E1000_STATUS_FD) == 0)
+ if ((stat_reg & E1000_STATUS_FD) == 0)
ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
}
@@ -1266,7 +1284,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if(adapter->hw.phy_type == e1000_phy_m88)
+ if (adapter->hw.phy_type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
udelay(500);
@@ -1282,14 +1300,14 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
switch (adapter->hw.mac_type) {
case e1000_82543:
- if(adapter->hw.media_type == e1000_media_type_copper) {
+ if (adapter->hw.media_type == e1000_media_type_copper) {
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
*/
- while(e1000_nonintegrated_phy_loopback(adapter) &&
+ while (e1000_nonintegrated_phy_loopback(adapter) &&
count++ < 10);
- if(count < 11)
+ if (count < 11)
return 0;
}
break;
@@ -1327,11 +1345,11 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
static int
e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
- uint32_t rctl;
struct e1000_hw *hw = &adapter->hw;
+ uint32_t rctl;
if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes) {
+ hw->media_type == e1000_media_type_internal_serdes) {
switch (hw->mac_type) {
case e1000_82545:
case e1000_82546:
@@ -1362,25 +1380,25 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
static void
e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
uint32_t rctl;
uint16_t phy_reg;
- struct e1000_hw *hw = &adapter->hw;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = E1000_READ_REG(hw, RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes){
+ hw->media_type == e1000_media_type_internal_serdes) {
#define E1000_SERDES_LB_OFF 0x400
E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
msec_delay(10);
break;
}
- /* fall thru for Cu adapters */
+ /* Fall Through */
case e1000_82545:
case e1000_82546:
case e1000_82545_rev_3:
@@ -1401,7 +1419,7 @@ static void
e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
memset(skb->data, 0xFF, frame_size);
- frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+ frame_size &= ~1;
memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
@@ -1410,9 +1428,9 @@ e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int
e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
- frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
- if(*(skb->data + 3) == 0xFF) {
- if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+ frame_size &= ~1;
+ if (*(skb->data + 3) == 0xFF) {
+ if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
(*(skb->data + frame_size / 2 + 12) == 0xAF)) {
return 0;
}
@@ -1431,53 +1449,53 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
- /* Calculate the loop count based on the largest descriptor ring
+ /* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
* send/receive pairs during each loop
*/
- if(rxdr->count <= txdr->count)
+ if (rxdr->count <= txdr->count)
lc = ((txdr->count / 64) * 2) + 1;
else
lc = ((rxdr->count / 64) * 2) + 1;
k = l = 0;
- for(j = 0; j <= lc; j++) { /* loop count loop */
- for(i = 0; i < 64; i++) { /* send the packets */
- e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
+ for (j = 0; j <= lc; j++) { /* loop count loop */
+ for (i = 0; i < 64; i++) { /* send the packets */
+ e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
1024);
- pci_dma_sync_single_for_device(pdev,
+ pci_dma_sync_single_for_device(pdev,
txdr->buffer_info[k].dma,
txdr->buffer_info[k].length,
PCI_DMA_TODEVICE);
- if(unlikely(++k == txdr->count)) k = 0;
+ if (unlikely(++k == txdr->count)) k = 0;
}
E1000_WRITE_REG(&adapter->hw, TDT, k);
msec_delay(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0;
do { /* receive the sent packets */
- pci_dma_sync_single_for_cpu(pdev,
+ pci_dma_sync_single_for_cpu(pdev,
rxdr->buffer_info[l].dma,
rxdr->buffer_info[l].length,
PCI_DMA_FROMDEVICE);
-
+
ret_val = e1000_check_lbtest_frame(
rxdr->buffer_info[l].skb,
1024);
- if(!ret_val)
+ if (!ret_val)
good_cnt++;
- if(unlikely(++l == rxdr->count)) l = 0;
- /* time + 20 msecs (200 msecs on 2.4) is more than
- * enough time to complete the receives, if it's
+ if (unlikely(++l == rxdr->count)) l = 0;
+ /* time + 20 msecs (200 msecs on 2.4) is more than
+ * enough time to complete the receives, if it's
* exceeded, break and error off
*/
} while (good_cnt < 64 && jiffies < (time + 20));
- if(good_cnt != 64) {
+ if (good_cnt != 64) {
ret_val = 13; /* ret_val is the same as mis-compare */
- break;
+ break;
}
- if(jiffies >= (time + 2)) {
+ if (jiffies >= (time + 2)) {
ret_val = 14; /* error code for time out error */
break;
}
@@ -1488,14 +1506,25 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
static int
e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
{
- if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
- if((*data = e1000_setup_loopback_test(adapter)))
- goto err_loopback_setup;
+ /* PHY loopback cannot be performed if SoL/IDER
+ * sessions are active */
+ if (e1000_check_phy_reset_block(&adapter->hw)) {
+ DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
+ "when SoL/IDER is active.\n");
+ *data = 0;
+ goto out;
+ }
+
+ if ((*data = e1000_setup_desc_rings(adapter)))
+ goto out;
+ if ((*data = e1000_setup_loopback_test(adapter)))
+ goto err_loopback;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
-err_loopback_setup:
- e1000_free_desc_rings(adapter);
+
err_loopback:
+ e1000_free_desc_rings(adapter);
+out:
return *data;
}
@@ -1519,17 +1548,17 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 1;
} else {
e1000_check_for_link(&adapter->hw);
- if(adapter->hw.autoneg) /* if auto_neg is set wait for it */
+ if (adapter->hw.autoneg) /* if auto_neg is set wait for it */
msec_delay(4000);
- if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
*data = 1;
}
}
return *data;
}
-static int
+static int
e1000_diag_test_count(struct net_device *netdev)
{
return E1000_TEST_LEN;
@@ -1542,7 +1571,7 @@ e1000_diag_test(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
boolean_t if_running = netif_running(netdev);
- if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
/* Offline tests */
/* save speed, duplex, autoneg settings */
@@ -1552,27 +1581,27 @@ e1000_diag_test(struct net_device *netdev,
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
- if(e1000_link_test(adapter, &data[4]))
+ if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
- if(if_running)
+ if (if_running)
e1000_down(adapter);
else
e1000_reset(adapter);
- if(e1000_reg_test(adapter, &data[0]))
+ if (e1000_reg_test(adapter, &data[0]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_eeprom_test(adapter, &data[1]))
+ if (e1000_eeprom_test(adapter, &data[1]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_intr_test(adapter, &data[2]))
+ if (e1000_intr_test(adapter, &data[2]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_loopback_test(adapter, &data[3]))
+ if (e1000_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* restore speed, duplex, autoneg settings */
@@ -1581,11 +1610,11 @@ e1000_diag_test(struct net_device *netdev,
adapter->hw.autoneg = autoneg;
e1000_reset(adapter);
- if(if_running)
+ if (if_running)
e1000_up(adapter);
} else {
/* Online tests */
- if(e1000_link_test(adapter, &data[4]))
+ if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* Offline tests aren't run; pass by default */
@@ -1603,7 +1632,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- switch(adapter->hw.device_id) {
+ switch (adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
@@ -1617,8 +1646,9 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
wol->wolopts = 0;
return;
@@ -1630,13 +1660,13 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
WAKE_BCAST | WAKE_MAGIC;
wol->wolopts = 0;
- if(adapter->wol & E1000_WUFC_EX)
+ if (adapter->wol & E1000_WUFC_EX)
wol->wolopts |= WAKE_UCAST;
- if(adapter->wol & E1000_WUFC_MC)
+ if (adapter->wol & E1000_WUFC_MC)
wol->wolopts |= WAKE_MCAST;
- if(adapter->wol & E1000_WUFC_BC)
+ if (adapter->wol & E1000_WUFC_BC)
wol->wolopts |= WAKE_BCAST;
- if(adapter->wol & E1000_WUFC_MAG)
+ if (adapter->wol & E1000_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
}
@@ -1648,7 +1678,7 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- switch(adapter->hw.device_id) {
+ switch (adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
@@ -1660,24 +1690,25 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
return wol->wolopts ? -EOPNOTSUPP : 0;
/* Fall Through */
default:
- if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
adapter->wol = 0;
- if(wol->wolopts & WAKE_UCAST)
+ if (wol->wolopts & WAKE_UCAST)
adapter->wol |= E1000_WUFC_EX;
- if(wol->wolopts & WAKE_MCAST)
+ if (wol->wolopts & WAKE_MCAST)
adapter->wol |= E1000_WUFC_MC;
- if(wol->wolopts & WAKE_BCAST)
+ if (wol->wolopts & WAKE_BCAST)
adapter->wol |= E1000_WUFC_BC;
- if(wol->wolopts & WAKE_MAGIC)
+ if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
}
@@ -1695,7 +1726,7 @@ e1000_led_blink_callback(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
+ if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
e1000_led_off(&adapter->hw);
else
e1000_led_on(&adapter->hw);
@@ -1708,11 +1739,11 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+ if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82571) {
- if(!adapter->blink_timer.function) {
+ 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;
adapter->blink_timer.data = (unsigned long) adapter;
@@ -1721,21 +1752,21 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- }
- else if(adapter->hw.mac_type < e1000_82573) {
- E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+ } else if (adapter->hw.mac_type < e1000_82573) {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL,
+ (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
msleep_interruptible(data * 1000);
- }
- else {
- E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+ } else {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL,
+ (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
msleep_interruptible(data * 1000);
}
@@ -1750,50 +1781,89 @@ static int
e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
return 0;
}
-static int
+static int
e1000_get_stats_count(struct net_device *netdev)
{
return E1000_STATS_LEN;
}
-static void
-e1000_get_ethtool_stats(struct net_device *netdev,
+static void
+e1000_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+#ifdef CONFIG_E1000_MQ
+ uint64_t *queue_stat;
+ int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t);
+ int j, k;
+#endif
int i;
e1000_update_stats(adapter);
- for(i = 0; i < E1000_STATS_LEN; i++) {
- char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
- data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+ data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
}
+#ifdef CONFIG_E1000_MQ
+ for (j = 0; j < adapter->num_tx_queues; j++) {
+ queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats;
+ for (k = 0; k < stat_count; k++)
+ data[i + k] = queue_stat[k];
+ i += k;
+ }
+ for (j = 0; j < adapter->num_rx_queues; j++) {
+ queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats;
+ for (k = 0; k < stat_count; k++)
+ data[i + k] = queue_stat[k];
+ i += k;
+ }
+#endif
+/* BUG_ON(i != E1000_STATS_LEN); */
}
-static void
+static void
e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
{
+#ifdef CONFIG_E1000_MQ
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+#endif
+ uint8_t *p = data;
int i;
- switch(stringset) {
+ switch (stringset) {
case ETH_SS_TEST:
- memcpy(data, *e1000_gstrings_test,
+ memcpy(data, *e1000_gstrings_test,
E1000_TEST_LEN*ETH_GSTRING_LEN);
break;
case ETH_SS_STATS:
- for (i=0; i < E1000_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- e1000_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ memcpy(p, e1000_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
}
+#ifdef CONFIG_E1000_MQ
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ sprintf(p, "tx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ sprintf(p, "rx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+#endif
+/* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
break;
}
}
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 136fc031e4ad..beeec0fbbeac 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -318,6 +318,8 @@ 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:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -639,6 +641,7 @@ e1000_init_hw(struct e1000_hw *hw)
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
uint32_t mta_size;
+ uint32_t ctrl_ext;
DEBUGFUNC("e1000_init_hw");
@@ -735,7 +738,6 @@ e1000_init_hw(struct e1000_hw *hw)
break;
case e1000_82571:
case e1000_82572:
- ctrl |= (1 << 22);
case e1000_82573:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -775,6 +777,15 @@ e1000_init_hw(struct e1000_hw *hw)
*/
e1000_clear_hw_cntrs(hw);
+ if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
+ hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ /* Relaxed ordering must be disabled to avoid a parity
+ * error crash in a PCI slot. */
+ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ }
+
return ret_val;
}
@@ -838,6 +849,11 @@ e1000_setup_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_link");
+ /* In the case of the phy reset being blocked, we already have a link.
+ * We do not have to set it up again. */
+ if (e1000_check_phy_reset_block(hw))
+ return E1000_SUCCESS;
+
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -1584,10 +1600,10 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if(ret_val)
+ return ret_val;
/* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
@@ -1929,14 +1945,19 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
void
e1000_config_collision_dist(struct e1000_hw *hw)
{
- uint32_t tctl;
+ uint32_t tctl, coll_dist;
DEBUGFUNC("e1000_config_collision_dist");
+ if (hw->mac_type < e1000_82543)
+ coll_dist = E1000_COLLISION_DISTANCE_82542;
+ else
+ coll_dist = E1000_COLLISION_DISTANCE;
+
tctl = E1000_READ_REG(hw, TCTL);
tctl &= ~E1000_TCTL_COLD;
- tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+ tctl |= coll_dist << E1000_COLD_SHIFT;
E1000_WRITE_REG(hw, TCTL, tctl);
E1000_WRITE_FLUSH(hw);
@@ -2982,6 +3003,8 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
if (hw->mac_type < e1000_82571)
msec_delay(10);
+ else
+ udelay(100);
E1000_WRITE_REG(hw, CTRL, ctrl);
E1000_WRITE_FLUSH(hw);
@@ -3881,17 +3904,19 @@ e1000_read_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* FLASH reads without acquiring the semaphore are safe in 82573-based
- * controllers.
- */
- if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
- (hw->mac_type != e1000_82573)) {
- /* Prepare the EEPROM for reading */
- if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
+ /* FLASH reads without acquiring the semaphore are safe */
+ if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+ hw->eeprom.use_eerd == FALSE) {
+ switch (hw->mac_type) {
+ default:
+ /* Prepare the EEPROM for reading */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ break;
+ }
}
- if(eeprom->use_eerd == TRUE) {
+ if (eeprom->use_eerd == TRUE) {
ret_val = e1000_read_eeprom_eerd(hw, offset, words, data);
if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
(hw->mac_type != e1000_82573))
@@ -4398,7 +4423,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
return -E1000_ERR_EEPROM;
}
- /* If STM opcode located in bits 15:8 of flop, reset firmware */
+ /* If STM opcode located in bits 15:8 of flop, reset firmware */
if ((flop & 0xFF00) == E1000_STM_OPCODE) {
E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
}
@@ -4406,7 +4431,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* Perform the flash update */
E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
- for (i=0; i < attempts; i++) {
+ for (i=0; i < attempts; i++) {
eecd = E1000_READ_REG(hw, EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
@@ -4479,6 +4504,7 @@ 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);
}
+
switch (hw->mac_type) {
default:
break;
@@ -6720,6 +6746,12 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
break;
}
+ /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+ * Need to wait for PHY configuration completion before accessing NVM
+ * and PHY. */
+ if (hw->mac_type == e1000_82573)
+ msec_delay(25);
+
return E1000_SUCCESS;
}
@@ -6809,7 +6841,8 @@ int32_t
e1000_check_phy_reset_block(struct e1000_hw *hw)
{
uint32_t manc = 0;
- if(hw->mac_type > e1000_82547_rev_2)
+
+ if (hw->mac_type > e1000_82547_rev_2)
manc = E1000_READ_REG(hw, MANC);
return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
E1000_BLK_PHY_RESET : E1000_SUCCESS;
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 7caa35748cea..f1219dd9dbac 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -377,6 +377,7 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
/* Filters (multicast, vlan, receive) */
+void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -401,7 +402,9 @@ void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
/* Port I/O is only supported on 82544 and newer */
uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
+uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+void e1000_enable_pciex_master(struct e1000_hw *hw);
int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
void e1000_release_software_semaphore(struct e1000_hw *hw);
@@ -439,6 +442,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_FIBER 0x107A
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define E1000_DEV_ID_82547EI 0x1019
#define E1000_DEV_ID_82571EB_COPPER 0x105E
#define E1000_DEV_ID_82571EB_FIBER 0x105F
@@ -449,6 +453,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#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_KSP3 0x10B5
#define NODE_ADDRESS_SIZE 6
@@ -897,14 +902,14 @@ struct e1000_ffvt_entry {
#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
-#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
-#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
-#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
+#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
+#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
+#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
+#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
@@ -1497,6 +1502,7 @@ struct e1000_hw {
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
@@ -1758,7 +1764,6 @@ struct e1000_hw {
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
still to be processed. */
-
/* Transmit Configuration Word */
#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
@@ -1954,6 +1959,23 @@ struct e1000_host_command_info {
#define E1000_MDALIGN 4096
+/* PCI-Ex registers */
+
+/* PCI-Ex Control Register */
+#define E1000_GCR_RXD_NO_SNOOP 0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
+#define E1000_GCR_TXD_NO_SNOOP 0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
+
+#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
+ E1000_GCR_RXDSCW_NO_SNOOP | \
+ E1000_GCR_RXDSCR_NO_SNOOP | \
+ E1000_GCR TXD_NO_SNOOP | \
+ E1000_GCR_TXDSCW_NO_SNOOP | \
+ E1000_GCR_TXDSCR_NO_SNOOP)
+
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
@@ -2077,7 +2099,10 @@ struct e1000_host_command_info {
/* Collision related configuration parameters */
#define E1000_COLLISION_THRESHOLD 15
#define E1000_CT_SHIFT 4
-#define E1000_COLLISION_DISTANCE 64
+/* Collision distance is a 0-based value that applies to
+ * half-duplex-capable hardware only. */
+#define E1000_COLLISION_DISTANCE 63
+#define E1000_COLLISION_DISTANCE_82542 64
#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_COLD_SHIFT 12
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 438a931fd55d..31e332935e5a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -29,11 +29,71 @@
#include "e1000.h"
/* Change Log
- * 6.0.58 4/20/05
- * o Accepted ethtool cleanup patch from Stephen Hemminger
- * 6.0.44+ 2/15/05
- * o applied Anton's patch to resolve tx hang in hardware
- * o Applied Andrew Mortons patch - e1000 stops working after resume
+ * 6.3.9 12/16/2005
+ * o incorporate fix for recycled skbs from IBM LTC
+ * 6.3.7 11/18/2005
+ * o Honor eeprom setting for enabling/disabling Wake On Lan
+ * 6.3.5 11/17/2005
+ * o Fix memory leak in rx ring handling for PCI Express adapters
+ * 6.3.4 11/8/05
+ * o Patch from Jesper Juhl to remove redundant NULL checks for kfree
+ * 6.3.2 9/20/05
+ * o Render logic that sets/resets DRV_LOAD as inline functions to
+ * avoid code replication. If f/w is AMT then set DRV_LOAD only when
+ * network interface is open.
+ * o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
+ * o Adjust PBA partioning for Jumbo frames using MTU size and not
+ * rx_buffer_len
+ * 6.3.1 9/19/05
+ * o Use adapter->tx_timeout_factor in Tx Hung Detect logic
+ (e1000_clean_tx_irq)
+ * o Support for 8086:10B5 device (Quad Port)
+ * 6.2.14 9/15/05
+ * o In AMT enabled configurations, set/reset DRV_LOAD bit on interface
+ * open/close
+ * 6.2.13 9/14/05
+ * o Invoke e1000_check_mng_mode only for 8257x controllers since it
+ * accesses the FWSM that is not supported in other controllers
+ * 6.2.12 9/9/05
+ * o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER
+ * o set RCTL:SECRC only for controllers newer than 82543.
+ * o When the n/w interface comes down reset DRV_LOAD bit to notify f/w.
+ * This code was moved from e1000_remove to e1000_close
+ * 6.2.10 9/6/05
+ * o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off.
+ * o Enable fc by default on 82573 controllers (do not read eeprom)
+ * o Fix rx_errors statistic not to include missed_packet_count
+ * o Fix rx_dropped statistic not to include missed_packet_count
+ (Padraig Brady)
+ * 6.2.9 8/30/05
+ * o Remove call to update statistics from the controller ib e1000_get_stats
+ * 6.2.8 8/30/05
+ * o Improved algorithm for rx buffer allocation/rdt update
+ * o Flow control watermarks relative to rx PBA size
+ * o Simplified 'Tx Hung' detect logic
+ * 6.2.7 8/17/05
+ * o Report rx buffer allocation failures and tx timeout counts in stats
+ * 6.2.6 8/16/05
+ * o Implement workaround for controller erratum -- linear non-tso packet
+ * following a TSO gets written back prematurely
+ * 6.2.5 8/15/05
+ * o Set netdev->tx_queue_len based on link speed/duplex settings.
+ * o Fix net_stats.rx_fifo_errors <p@draigBrady.com>
+ * o Do not power off PHY if SoL/IDER session is active
+ * 6.2.4 8/10/05
+ * o Fix loopback test setup/cleanup for 82571/3 controllers
+ * o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat
+ * all packets as raw
+ * o Prevent operations that will cause the PHY to be reset if SoL/IDER
+ * sessions are active and log a message
+ * 6.2.2 7/21/05
+ * o used fixed size descriptors for all MTU sizes, reduces memory load
+ * 6.1.2 4/13/05
+ * o Fixed ethtool diagnostics
+ * o Enabled flow control to take default eeprom settings
+ * o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent
+ * calls, one from mii_ioctl and other from within update_stats while
+ * processing MIIREG ioctl.
*/
char e1000_driver_name[] = "e1000";
@@ -43,7 +103,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -97,7 +157,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
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),
+ INTEL_E1000_ETHERNET_DEVICE(0x10B5),
/* required last entry */
{0,}
};
@@ -171,9 +233,11 @@ 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,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -291,7 +355,7 @@ e1000_irq_disable(struct e1000_adapter *adapter)
static inline void
e1000_irq_enable(struct e1000_adapter *adapter)
{
- if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
E1000_WRITE_FLUSH(&adapter->hw);
}
@@ -303,23 +367,91 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
uint16_t vid = adapter->hw.mng_cookie.vlan_id;
uint16_t old_vid = adapter->mng_vlan_id;
- if(adapter->vlgrp) {
- if(!adapter->vlgrp->vlan_devices[vid]) {
- if(adapter->hw.mng_cookie.status &
+ if (adapter->vlgrp) {
+ if (!adapter->vlgrp->vlan_devices[vid]) {
+ if (adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
e1000_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
} else
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-
- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
- (vid != old_vid) &&
+
+ if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
!adapter->vlgrp->vlan_devices[old_vid])
e1000_vlan_rx_kill_vid(netdev, old_vid);
}
}
}
-
+
+/**
+ * e1000_release_hw_control - release control of the h/w to f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that the
+ * driver is no longer loaded. For AMT version (only with 82573) i
+ * of the f/w this means that the netowrk i/f is closed.
+ *
+ **/
+
+static inline void
+e1000_release_hw_control(struct e1000_adapter *adapter)
+{
+ uint32_t ctrl_ext;
+ uint32_t swsm;
+
+ /* Let firmware taken over control of h/w */
+ 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,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ default:
+ break;
+ }
+}
+
+/**
+ * e1000_get_hw_control - get control of the h/w from f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded. For AMT version (only with 82573)
+ * of the f/w this means that the netowrk i/f is open.
+ *
+ **/
+
+static inline void
+e1000_get_hw_control(struct e1000_adapter *adapter)
+{
+ uint32_t ctrl_ext;
+ uint32_t swsm;
+ /* 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,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+}
+
int
e1000_up(struct e1000_adapter *adapter)
{
@@ -329,10 +461,10 @@ e1000_up(struct e1000_adapter *adapter)
/* hardware has been reset, we need to reload some things */
/* Reset the PHY if it was previously powered down */
- if(adapter->hw.media_type == e1000_media_type_copper) {
+ if (adapter->hw.media_type == e1000_media_type_copper) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
e1000_phy_reset(&adapter->hw);
}
@@ -343,20 +475,26 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- for (i = 0; i < adapter->num_queues; i++)
- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
+ /* call E1000_DESC_UNUSED which always leaves
+ * at least 1 descriptor unused to make sure
+ * next_to_use != next_to_clean */
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct e1000_rx_ring *ring = &adapter->rx_ring[i];
+ adapter->alloc_rx_buf(adapter, ring,
+ E1000_DESC_UNUSED(ring));
+ }
#ifdef CONFIG_PCI_MSI
- if(adapter->hw.mac_type > e1000_82547_rev_2) {
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
adapter->have_msi = TRUE;
- if((err = pci_enable_msi(adapter->pdev))) {
+ if ((err = pci_enable_msi(adapter->pdev))) {
DPRINTK(PROBE, ERR,
"Unable to allocate MSI interrupt Error: %d\n", err);
adapter->have_msi = FALSE;
}
}
#endif
- if((err = request_irq(adapter->pdev->irq, &e1000_intr,
+ if ((err = request_irq(adapter->pdev->irq, &e1000_intr,
SA_SHIRQ | SA_SAMPLE_RANDOM,
netdev->name, netdev))) {
DPRINTK(PROBE, ERR,
@@ -364,6 +502,12 @@ e1000_up(struct e1000_adapter *adapter)
return err;
}
+#ifdef CONFIG_E1000_MQ
+ e1000_setup_queue_mapping(adapter);
+#endif
+
+ adapter->tx_queue_len = netdev->tx_queue_len;
+
mod_timer(&adapter->watchdog_timer, jiffies);
#ifdef CONFIG_E1000_NAPI
@@ -378,6 +522,8 @@ void
e1000_down(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
+ e1000_check_mng_mode(&adapter->hw);
e1000_irq_disable(adapter);
#ifdef CONFIG_E1000_MQ
@@ -385,7 +531,7 @@ e1000_down(struct e1000_adapter *adapter)
#endif
free_irq(adapter->pdev->irq, netdev);
#ifdef CONFIG_PCI_MSI
- if(adapter->hw.mac_type > e1000_82547_rev_2 &&
+ if (adapter->hw.mac_type > e1000_82547_rev_2 &&
adapter->have_msi == TRUE)
pci_disable_msi(adapter->pdev);
#endif
@@ -396,6 +542,7 @@ e1000_down(struct e1000_adapter *adapter)
#ifdef CONFIG_E1000_NAPI
netif_poll_disable(netdev);
#endif
+ netdev->tx_queue_len = adapter->tx_queue_len;
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
@@ -405,12 +552,16 @@ e1000_down(struct e1000_adapter *adapter)
e1000_clean_all_tx_rings(adapter);
e1000_clean_all_rx_rings(adapter);
- /* 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 &&
+ /* Power down the PHY so no link is implied when interface is down *
+ * The PHY cannot be powered down if any of the following is TRUE *
+ * (a) WoL is enabled
+ * (b) AMT is active
+ * (c) SoL/IDER session is active */
+ if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper &&
- !e1000_check_mng_mode(&adapter->hw) &&
- !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) {
+ !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
+ !mng_mode_enabled &&
+ !e1000_check_phy_reset_block(&adapter->hw)) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
@@ -422,10 +573,8 @@ e1000_down(struct e1000_adapter *adapter)
void
e1000_reset(struct e1000_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
uint32_t pba, manc;
uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
@@ -448,19 +597,12 @@ e1000_reset(struct e1000_adapter *adapter)
break;
}
- if((adapter->hw.mac_type != e1000_82573) &&
- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+ if ((adapter->hw.mac_type != e1000_82573) &&
+ (adapter->netdev->mtu > E1000_RXBUFFER_8192))
pba -= 8; /* allocate more FIFO for Tx */
- /* send an XOFF when there is enough space in the
- * Rx FIFO to hold one extra full size Rx packet
- */
- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE +
- ETHERNET_FCS_SIZE + 1;
- fc_low_water_mark = fc_high_water_mark + 8;
- }
- if(adapter->hw.mac_type == e1000_82547) {
+ if (adapter->hw.mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
@@ -471,19 +613,21 @@ e1000_reset(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* flow control settings */
- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
- fc_high_water_mark;
- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
- fc_low_water_mark;
+ /* Set the FC high water mark to 90% of the FIFO size.
+ * Required to clear last 3 LSB */
+ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
+
+ adapter->hw.fc_high_water = fc_high_water_mark;
+ adapter->hw.fc_low_water = fc_high_water_mark - 8;
adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
adapter->hw.fc_send_xon = 1;
adapter->hw.fc = adapter->hw.original_fc;
/* Allow time for pending master requests to run */
e1000_reset_hw(&adapter->hw);
- if(adapter->hw.mac_type >= e1000_82544)
+ if (adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
- if(e1000_init_hw(&adapter->hw))
+ if (e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
@@ -517,33 +661,31 @@ 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;
int i, err, pci_using_dac;
uint16_t eeprom_data;
uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
- if((err = pci_enable_device(pdev)))
+ if ((err = pci_enable_device(pdev)))
return err;
- if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
E1000_ERR("No usable DMA configuration, aborting\n");
return err;
}
pci_using_dac = 0;
}
- if((err = pci_request_regions(pdev, e1000_driver_name)))
+ if ((err = pci_request_regions(pdev, e1000_driver_name)))
return err;
pci_set_master(pdev);
netdev = alloc_etherdev(sizeof(struct e1000_adapter));
- if(!netdev) {
+ if (!netdev) {
err = -ENOMEM;
goto err_alloc_etherdev;
}
@@ -562,15 +704,15 @@ e1000_probe(struct pci_dev *pdev,
mmio_len = pci_resource_len(pdev, BAR_0);
adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
- if(!adapter->hw.hw_addr) {
+ if (!adapter->hw.hw_addr) {
err = -EIO;
goto err_ioremap;
}
- for(i = BAR_1; i <= BAR_5; i++) {
- if(pci_resource_len(pdev, i) == 0)
+ for (i = BAR_1; i <= BAR_5; i++) {
+ if (pci_resource_len(pdev, i) == 0)
continue;
- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
adapter->hw.io_base = pci_resource_start(pdev, i);
break;
}
@@ -607,13 +749,13 @@ e1000_probe(struct pci_dev *pdev,
/* setup the private structure */
- if((err = e1000_sw_init(adapter)))
+ if ((err = e1000_sw_init(adapter)))
goto err_sw_init;
- if((err = e1000_check_phy_reset_block(&adapter->hw)))
+ if ((err = e1000_check_phy_reset_block(&adapter->hw)))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
- if(adapter->hw.mac_type >= e1000_82543) {
+ if (adapter->hw.mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
@@ -622,16 +764,16 @@ e1000_probe(struct pci_dev *pdev,
}
#ifdef NETIF_F_TSO
- if((adapter->hw.mac_type >= e1000_82544) &&
+ if ((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
#ifdef NETIF_F_TSO_IPV6
- if(adapter->hw.mac_type > e1000_82547_rev_2)
+ if (adapter->hw.mac_type > e1000_82547_rev_2)
netdev->features |= NETIF_F_TSO_IPV6;
#endif
#endif
- if(pci_using_dac)
+ if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* hard_start_xmit is safe against parallel locking */
@@ -639,14 +781,14 @@ e1000_probe(struct pci_dev *pdev,
adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
- /* before reading the EEPROM, reset the controller to
+ /* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
-
+
e1000_reset_hw(&adapter->hw);
/* make sure the EEPROM is good */
- if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
@@ -654,12 +796,12 @@ e1000_probe(struct pci_dev *pdev,
/* copy the MAC address out of the EEPROM */
- if(e1000_read_mac_addr(&adapter->hw))
+ 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->perm_addr)) {
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
@@ -699,7 +841,7 @@ e1000_probe(struct pci_dev *pdev,
* enable the ACPI Magic Packet filter
*/
- switch(adapter->hw.mac_type) {
+ switch (adapter->hw.mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -712,8 +854,7 @@ e1000_probe(struct pci_dev *pdev,
case e1000_82546:
case e1000_82546_rev_3:
case e1000_82571:
- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
- && (adapter->hw.media_type == e1000_media_type_copper)) {
+ if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
e1000_read_eeprom(&adapter->hw,
EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
break;
@@ -724,31 +865,42 @@ e1000_probe(struct pci_dev *pdev,
EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
- if(eeprom_data & eeprom_apme_mask)
+ if (eeprom_data & eeprom_apme_mask)
adapter->wol |= E1000_WUFC_MAG;
+ /* print bus type/speed/width info */
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
+ (hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
+ ((hw->bus_speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
+ (hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
+ (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
+ (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
+ (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
+ ((hw->bus_width == e1000_bus_width_64) ? "64-bit" :
+ (hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
+ (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
+ "32-bit"));
+ }
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':');
+
/* reset the hardware with the new settings */
e1000_reset(adapter);
- /* 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,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
strcpy(netdev->name, "eth%d");
- if((err = register_netdev(netdev)))
+ if ((err = register_netdev(netdev)))
goto err_register;
DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -782,47 +934,33 @@ 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;
+ uint32_t manc;
#ifdef CONFIG_E1000_NAPI
int i;
#endif
flush_scheduled_work();
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
- if(manc & E1000_MANC_SMBUS_EN) {
+ if (manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
}
- 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,
- swsm & ~E1000_SWSM_DRV_LOAD);
- break;
-
- default:
- break;
- }
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+ * would have already happened in close and is redundant. */
+ e1000_release_hw_control(adapter);
unregister_netdev(netdev);
#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
__dev_put(&adapter->polling_netdev[i]);
#endif
- if(!e1000_check_phy_reset_block(&adapter->hw))
+ if (!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
kfree(adapter->tx_ring);
@@ -881,19 +1019,19 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* identify the MAC */
- if(e1000_set_mac_type(hw)) {
+ if (e1000_set_mac_type(hw)) {
DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
return -EIO;
}
/* initialize eeprom parameters */
- if(e1000_init_eeprom_params(hw)) {
+ if (e1000_init_eeprom_params(hw)) {
E1000_ERR("EEPROM initialization failed\n");
return -EIO;
}
- switch(hw->mac_type) {
+ switch (hw->mac_type) {
default:
break;
case e1000_82541:
@@ -912,7 +1050,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* Copper options */
- if(hw->media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
hw->mdix = AUTO_ALL_MODES;
hw->disable_polarity_correction = FALSE;
hw->master_slave = E1000_MASTER_SLAVE;
@@ -923,15 +1061,34 @@ e1000_sw_init(struct e1000_adapter *adapter)
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
- adapter->num_queues = 2;
+ /* These controllers support 2 tx queues, but with a single
+ * qdisc implementation, multiple tx queues aren't quite as
+ * interesting. If we can find a logical way of mapping
+ * flows to a queue, then perhaps we can up the num_tx_queue
+ * count back to its default. Until then, we run the risk of
+ * terrible performance due to SACK overload. */
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 2;
break;
default:
- adapter->num_queues = 1;
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
break;
}
- adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+ adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus());
+ adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus());
+ DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n",
+ adapter->num_rx_queues,
+ ((adapter->num_rx_queues == 1)
+ ? ((num_online_cpus() > 1)
+ ? "(due to unsupported feature in current adapter)"
+ : "(due to unsupported system configuration)")
+ : ""));
+ DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n",
+ adapter->num_tx_queues);
#else
- adapter->num_queues = 1;
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
#endif
if (e1000_alloc_queues(adapter)) {
@@ -940,17 +1097,14 @@ e1000_sw_init(struct e1000_adapter *adapter)
}
#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_rx_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);
+ spin_lock_init(&adapter->tx_queue_lock);
#endif
atomic_set(&adapter->irq_sem, 1);
@@ -973,13 +1127,13 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
{
int size;
- size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ size = sizeof(struct e1000_tx_ring) * adapter->num_tx_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;
+ size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
adapter->rx_ring = kmalloc(size, GFP_KERNEL);
if (!adapter->rx_ring) {
kfree(adapter->tx_ring);
@@ -988,7 +1142,7 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
memset(adapter->rx_ring, 0, size);
#ifdef CONFIG_E1000_NAPI
- size = sizeof(struct net_device) * adapter->num_queues;
+ size = sizeof(struct net_device) * adapter->num_rx_queues;
adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
if (!adapter->polling_netdev) {
kfree(adapter->tx_ring);
@@ -998,6 +1152,14 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
memset(adapter->polling_netdev, 0, size);
#endif
+#ifdef CONFIG_E1000_MQ
+ adapter->rx_sched_call_data.func = e1000_rx_schedule;
+ adapter->rx_sched_call_data.info = adapter->netdev;
+
+ adapter->cpu_netdev = alloc_percpu(struct net_device *);
+ adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+#endif
+
return E1000_SUCCESS;
}
@@ -1017,14 +1179,15 @@ e1000_setup_queue_mapping(struct e1000_adapter *adapter)
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];
+ *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_tx_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) {
+ if (i < adapter->num_rx_queues) {
*per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
- adapter->cpu_for_queue[i] = cpu;
+ adapter->rx_ring[i].cpu = cpu;
+ cpu_set(cpu, adapter->cpumask);
} else
*per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
@@ -1063,14 +1226,20 @@ e1000_open(struct net_device *netdev)
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
- if((err = e1000_up(adapter)))
+ if ((err = e1000_up(adapter)))
goto err_up;
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- if((adapter->hw.mng_cookie.status &
+ if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_update_mng_vlan(adapter);
}
+ /* If AMT is enabled, let the firmware know that the network
+ * interface is now open */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+
return E1000_SUCCESS;
err_up:
@@ -1105,10 +1274,17 @@ e1000_close(struct net_device *netdev)
e1000_free_all_tx_resources(adapter);
e1000_free_all_rx_resources(adapter);
- if((adapter->hw.mng_cookie.status &
+ if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
}
+
+ /* If AMT is enabled, let the firmware know that the network
+ * interface is now closed */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ e1000_check_mng_mode(&adapter->hw))
+ e1000_release_hw_control(adapter);
+
return 0;
}
@@ -1153,7 +1329,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_buffer) * txdr->count;
txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
- if(!txdr->buffer_info) {
+ if (!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
@@ -1166,7 +1342,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
E1000_ROUNDUP(txdr->size, 4096);
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if(!txdr->desc) {
+ if (!txdr->desc) {
setup_tx_desc_die:
vfree(txdr->buffer_info);
DPRINTK(PROBE, ERR,
@@ -1182,8 +1358,8 @@ setup_tx_desc_die:
"at %p\n", txdr->size, txdr->desc);
/* Try again, without freeing the previous */
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if(!txdr->desc) {
/* Failed allocation, critical failure */
+ if (!txdr->desc) {
pci_free_consistent(pdev, txdr->size, olddesc, olddma);
goto setup_tx_desc_die;
}
@@ -1229,7 +1405,7 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_tx_queues; i++) {
err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
if (err) {
DPRINTK(PROBE, ERR,
@@ -1254,10 +1430,11 @@ e1000_configure_tx(struct e1000_adapter *adapter)
uint64_t tdba;
struct e1000_hw *hw = &adapter->hw;
uint32_t tdlen, tctl, tipg, tarc;
+ uint32_t ipgr1, ipgr2;
/* Setup the HW Tx Head and Tail descriptor pointers */
- switch (adapter->num_queues) {
+ switch (adapter->num_tx_queues) {
case 2:
tdba = adapter->tx_ring[1].dma;
tdlen = adapter->tx_ring[1].count *
@@ -1287,22 +1464,26 @@ e1000_configure_tx(struct e1000_adapter *adapter)
/* Set the default values for the Tx Inter Packet Gap timer */
+ 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;
+
switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
tipg = DEFAULT_82542_TIPG_IPGT;
- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+ ipgr1 = DEFAULT_82542_TIPG_IPGR1;
+ ipgr2 = DEFAULT_82542_TIPG_IPGR2;
break;
default:
- 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;
+ ipgr1 = DEFAULT_82543_TIPG_IPGR1;
+ ipgr2 = DEFAULT_82543_TIPG_IPGR2;
+ break;
}
+ tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
+ tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
E1000_WRITE_REG(hw, TIPG, tipg);
/* Set the Tx Interrupt Delay register */
@@ -1378,7 +1559,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_ps_page) * rxdr->count;
rxdr->ps_page = kmalloc(size, GFP_KERNEL);
- if(!rxdr->ps_page) {
+ if (!rxdr->ps_page) {
vfree(rxdr->buffer_info);
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
@@ -1388,7 +1569,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
- if(!rxdr->ps_page_dma) {
+ if (!rxdr->ps_page_dma) {
vfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
DPRINTK(PROBE, ERR,
@@ -1397,7 +1578,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
}
memset(rxdr->ps_page_dma, 0, size);
- if(adapter->hw.mac_type <= e1000_82547_rev_2)
+ if (adapter->hw.mac_type <= e1000_82547_rev_2)
desc_len = sizeof(struct e1000_rx_desc);
else
desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1454,6 +1635,8 @@ setup_rx_desc_die:
rxdr->next_to_clean = 0;
rxdr->next_to_use = 0;
+ rxdr->rx_skb_top = NULL;
+ rxdr->rx_skb_prev = NULL;
return 0;
}
@@ -1475,7 +1658,7 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_rx_queues; i++) {
err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
if (err) {
DPRINTK(PROBE, ERR,
@@ -1498,7 +1681,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
{
uint32_t rctl, rfctl;
uint32_t psrctl = 0;
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
uint32_t pages = 0;
#endif
@@ -1510,7 +1693,10 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
- if(adapter->hw.tbi_compatibility_on == 1)
+ if (adapter->hw.mac_type > e1000_82543)
+ rctl |= E1000_RCTL_SECRC;
+
+ if (adapter->hw.tbi_compatibility_on == 1)
rctl |= E1000_RCTL_SBP;
else
rctl &= ~E1000_RCTL_SBP;
@@ -1521,32 +1707,17 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- if(adapter->hw.mac_type >= e1000_82571) {
+ 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;
} else {
rctl &= ~E1000_RCTL_SZ_4096;
- rctl |= E1000_RCTL_BSEX;
- switch (adapter->rx_buffer_len) {
- case E1000_RXBUFFER_2048:
- default:
- rctl |= E1000_RCTL_SZ_2048;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- case E1000_RXBUFFER_4096:
- rctl |= E1000_RCTL_SZ_4096;
- break;
- case E1000_RXBUFFER_8192:
- rctl |= E1000_RCTL_SZ_8192;
- break;
- case E1000_RXBUFFER_16384:
- rctl |= E1000_RCTL_SZ_16384;
- break;
- }
+ rctl &= ~E1000_RCTL_BSEX;
+ rctl |= E1000_RCTL_SZ_2048;
}
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
/* 82571 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
* placed in pages hanging off of skb_shinfo(skb)->nr_frags.
@@ -1570,7 +1741,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
-
+
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
@@ -1632,22 +1803,27 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if (hw->mac_type >= e1000_82540) {
E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
- if(adapter->itr > 1)
+ if (adapter->itr > 1)
E1000_WRITE_REG(hw, ITR,
1000000000 / (adapter->itr * 256));
}
if (hw->mac_type >= e1000_82571) {
- /* Reset delay timers after every interrupt */
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ /* Reset delay timers after every interrupt */
ctrl_ext |= E1000_CTRL_EXT_CANC;
+#ifdef CONFIG_E1000_NAPI
+ /* Auto-Mask interrupts upon ICR read. */
+ ctrl_ext |= E1000_CTRL_EXT_IAME;
+#endif
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_REG(hw, IAM, ~0);
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) {
+ switch (adapter->num_rx_queues) {
#ifdef CONFIG_E1000_MQ
case 2:
rdba = adapter->rx_ring[1].dma;
@@ -1674,7 +1850,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
}
#ifdef CONFIG_E1000_MQ
- if (adapter->num_queues > 1) {
+ if (adapter->num_rx_queues > 1) {
uint32_t random[10];
get_random_bytes(&random[0], 40);
@@ -1684,7 +1860,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
E1000_WRITE_REG(hw, RSSIM, 0);
}
- switch (adapter->num_queues) {
+ switch (adapter->num_rx_queues) {
case 2:
default:
reta = 0x00800080;
@@ -1716,13 +1892,13 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
if (hw->mac_type >= e1000_82543) {
rxcsum = E1000_READ_REG(hw, RXCSUM);
- if(adapter->rx_csum == TRUE) {
+ if (adapter->rx_csum == TRUE) {
rxcsum |= E1000_RXCSUM_TUOFL;
/* Enable 82571 IPv4 payload checksum for UDP fragments
* Must be used in conjunction with packet-split. */
- if ((hw->mac_type >= e1000_82571) &&
- (adapter->rx_ps_pages)) {
+ if ((hw->mac_type >= e1000_82571) &&
+ (adapter->rx_ps_pages)) {
rxcsum |= E1000_RXCSUM_IPPCSE;
}
} else {
@@ -1776,7 +1952,7 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
@@ -1784,17 +1960,15 @@ static inline void
e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
- if(buffer_info->dma) {
+ if (buffer_info->dma) {
pci_unmap_page(adapter->pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
}
- if(buffer_info->skb) {
+ if (buffer_info->skb)
dev_kfree_skb_any(buffer_info->skb);
- buffer_info->skb = NULL;
- }
+ memset(buffer_info, 0, sizeof(struct e1000_buffer));
}
/**
@@ -1813,7 +1987,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
/* Free all the Tx ring sk_buffs */
- for(i = 0; i < tx_ring->count; i++) {
+ for (i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
}
@@ -1843,7 +2017,7 @@ e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
}
@@ -1887,7 +2061,7 @@ e1000_free_all_rx_resources(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
}
@@ -1909,12 +2083,9 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
unsigned int i, j;
/* Free all the Rx ring sk_buffs */
-
- for(i = 0; i < rx_ring->count; i++) {
+ for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if(buffer_info->skb) {
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
+ if (buffer_info->skb) {
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
@@ -1922,19 +2093,30 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
-
- 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],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
- ps_page_dma->ps_page_dma[j] = 0;
- put_page(ps_page->ps_page[j]);
- ps_page->ps_page[j] = NULL;
- }
}
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+ for (j = 0; j < adapter->rx_ps_pages; j++) {
+ if (!ps_page->ps_page[j]) break;
+ pci_unmap_page(pdev,
+ ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ put_page(ps_page->ps_page[j]);
+ ps_page->ps_page[j] = NULL;
+ }
+ }
+
+ /* there also may be some cached data in our adapter */
+ if (rx_ring->rx_skb_top) {
+ dev_kfree_skb(rx_ring->rx_skb_top);
+
+ /* rx_skb_prev will be wiped out by rx_skb_top */
+ rx_ring->rx_skb_top = NULL;
+ rx_ring->rx_skb_prev = NULL;
}
+
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
size = sizeof(struct e1000_ps_page) * rx_ring->count;
@@ -1963,7 +2145,7 @@ e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
}
@@ -1984,7 +2166,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
mdelay(5);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_clean_all_rx_rings(adapter);
}
@@ -2000,12 +2182,14 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
mdelay(5);
- if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
e1000_pci_set_mwi(&adapter->hw);
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
+ /* No need to loop, because 82542 supports only 1 queue */
+ struct e1000_rx_ring *ring = &adapter->rx_ring[0];
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
+ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
}
}
@@ -2023,12 +2207,12 @@ e1000_set_mac(struct net_device *netdev, void *p)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
- if(!is_valid_ether_addr(addr->sa_data))
+ if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
/* 82542 2.0 needs to be in reset to write receive address registers */
- if(adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -2042,17 +2226,17 @@ e1000_set_mac(struct net_device *netdev, void *p)
/* 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
+ /* 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
+ * are dropped. Eventaully the LAA will be in RAR[0] and
* RAR[14] */
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
E1000_RAR_ENTRIES - 1);
}
- if(adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
return 0;
@@ -2086,9 +2270,9 @@ e1000_set_multi(struct net_device *netdev)
rctl = E1000_READ_REG(hw, RCTL);
- if(netdev->flags & IFF_PROMISC) {
+ if (netdev->flags & IFF_PROMISC) {
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
- } else if(netdev->flags & IFF_ALLMULTI) {
+ } else if (netdev->flags & IFF_ALLMULTI) {
rctl |= E1000_RCTL_MPE;
rctl &= ~E1000_RCTL_UPE;
} else {
@@ -2099,7 +2283,7 @@ e1000_set_multi(struct net_device *netdev)
/* 82542 2.0 needs to be in reset to write receive address registers */
- if(hw->mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
/* load the first 14 multicast address into the exact filters 1-14
@@ -2109,7 +2293,7 @@ e1000_set_multi(struct net_device *netdev)
*/
mc_ptr = netdev->mc_list;
- for(i = 1; i < rar_entries; i++) {
+ for (i = 1; i < rar_entries; i++) {
if (mc_ptr) {
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
mc_ptr = mc_ptr->next;
@@ -2121,17 +2305,17 @@ e1000_set_multi(struct net_device *netdev)
/* clear the old settings from the multicast hash table */
- for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+ for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* load any remaining addresses into the hash table */
- for(; mc_ptr; mc_ptr = mc_ptr->next) {
+ for (; mc_ptr; mc_ptr = mc_ptr->next) {
hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr);
e1000_mta_set(hw, hash_value);
}
- if(hw->mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
}
@@ -2157,8 +2341,8 @@ e1000_82547_tx_fifo_stall(unsigned long data)
struct net_device *netdev = adapter->netdev;
uint32_t tctl;
- if(atomic_read(&adapter->tx_fifo_stall)) {
- if((E1000_READ_REG(&adapter->hw, TDT) ==
+ if (atomic_read(&adapter->tx_fifo_stall)) {
+ if ((E1000_READ_REG(&adapter->hw, TDT) ==
E1000_READ_REG(&adapter->hw, TDH)) &&
(E1000_READ_REG(&adapter->hw, TDFT) ==
E1000_READ_REG(&adapter->hw, TDFH)) &&
@@ -2204,24 +2388,24 @@ static void
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
uint32_t link;
e1000_check_for_link(&adapter->hw);
if (adapter->hw.mac_type == e1000_82573) {
e1000_enable_tx_pkt_filtering(&adapter->hw);
- if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
e1000_update_mng_vlan(adapter);
- }
+ }
- if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+ if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
!(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
link = !adapter->hw.serdes_link_down;
else
link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
- if(link) {
- if(!netif_carrier_ok(netdev)) {
+ if (link) {
+ if (!netif_carrier_ok(netdev)) {
e1000_get_speed_and_duplex(&adapter->hw,
&adapter->link_speed,
&adapter->link_duplex);
@@ -2231,13 +2415,28 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
adapter->link_duplex == FULL_DUPLEX ?
"Full Duplex" : "Half Duplex");
+ /* tweak tx_queue_len according to speed/duplex */
+ netdev->tx_queue_len = adapter->tx_queue_len;
+ adapter->tx_timeout_factor = 1;
+ if (adapter->link_duplex == HALF_DUPLEX) {
+ switch (adapter->link_speed) {
+ case SPEED_10:
+ netdev->tx_queue_len = 10;
+ adapter->tx_timeout_factor = 8;
+ break;
+ case SPEED_100:
+ netdev->tx_queue_len = 100;
+ break;
+ }
+ }
+
netif_carrier_on(netdev);
netif_wake_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
adapter->smartspeed = 0;
}
} else {
- if(netif_carrier_ok(netdev)) {
+ if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
DPRINTK(LINK, INFO, "NIC Link is Down\n");
@@ -2263,7 +2462,10 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
e1000_update_adaptive(&adapter->hw);
- if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+#ifdef CONFIG_E1000_MQ
+ txdr = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#endif
+ if (!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
@@ -2274,12 +2476,12 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
}
/* Dynamic mode for Interrupt Throttle Rate (ITR) */
- if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
+ if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
* asymmetrical Tx or Rx gets ITR=8000; everyone
* else is between 2000-8000. */
uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
- uint32_t dif = (adapter->gotcl > adapter->gorcl ?
+ uint32_t dif = (adapter->gotcl > adapter->gorcl ?
adapter->gotcl - adapter->gorcl :
adapter->gorcl - adapter->gotcl) / 10000;
uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
@@ -2292,7 +2494,7 @@ 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
+ /* 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);
@@ -2314,13 +2516,14 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint32_t cmd_length = 0;
uint16_t ipcse = 0, tucse, mss;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
- if(skb_shinfo(skb)->tso_size) {
+ if (skb_shinfo(skb)->tso_size) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
@@ -2329,7 +2532,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
- if(skb->protocol == ntohs(ETH_P_IP)) {
+ if (skb->protocol == ntohs(ETH_P_IP)) {
skb->nh.iph->tot_len = 0;
skb->nh.iph->check = 0;
skb->h.th->check =
@@ -2341,7 +2544,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
cmd_length = E1000_TXD_CMD_IP;
ipcse = skb->h.raw - skb->data - 1;
#ifdef NETIF_F_TSO_IPV6
- } else if(skb->protocol == ntohs(ETH_P_IPV6)) {
+ } else if (skb->protocol == ntohs(ETH_P_IPV6)) {
skb->nh.ipv6h->payload_len = 0;
skb->h.th->check =
~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -2363,6 +2566,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
i = tx_ring->next_to_use;
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
@@ -2374,14 +2578,16 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
+ buffer_info->time_stamp = jiffies;
+
if (++i == tx_ring->count) i = 0;
tx_ring->next_to_use = i;
- return 1;
+ return TRUE;
}
#endif
- return 0;
+ return FALSE;
}
static inline boolean_t
@@ -2389,13 +2595,15 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint8_t css;
- if(likely(skb->ip_summed == CHECKSUM_HW)) {
+ if (likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
i = tx_ring->next_to_use;
+ buffer_info = &tx_ring->buffer_info[i];
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
@@ -2404,6 +2612,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+ buffer_info->time_stamp = jiffies;
+
if (unlikely(++i == tx_ring->count)) i = 0;
tx_ring->next_to_use = i;
@@ -2429,7 +2639,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
i = tx_ring->next_to_use;
- while(len) {
+ while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
@@ -2445,7 +2655,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if(unlikely(mss && !nr_frags && size == len && size > 8))
+ if (unlikely(mss && !nr_frags && size == len && size > 8))
size -= 4;
#endif
/* work-around for errata 10 and it applies
@@ -2453,13 +2663,13 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
* The fix is to make sure that the first descriptor of a
* packet is smaller than 2048 - 16 - 16 (or 2016) bytes
*/
- if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
(size > 2015) && count == 0))
size = 2015;
-
+
/* Workaround for potential 82544 hang in PCI-X. Avoid
* terminating buffers within evenly-aligned dwords. */
- if(unlikely(adapter->pcix_82544 &&
+ if (unlikely(adapter->pcix_82544 &&
!((unsigned long)(skb->data + offset + size - 1) & 4) &&
size > 4))
size -= 4;
@@ -2475,29 +2685,29 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
len -= size;
offset += size;
count++;
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
- for(f = 0; f < nr_frags; f++) {
+ for (f = 0; f < nr_frags; f++) {
struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = frag->page_offset;
- while(len) {
+ while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
+ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
size -= 4;
#endif
/* Workaround for potential 82544 hang in PCI-X.
* Avoid terminating buffers within evenly-aligned
* dwords. */
- if(unlikely(adapter->pcix_82544 &&
+ if (unlikely(adapter->pcix_82544 &&
!((unsigned long)(frag->page+offset+size-1) & 4) &&
size > 4))
size -= 4;
@@ -2514,7 +2724,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
len -= size;
offset += size;
count++;
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
}
@@ -2534,35 +2744,35 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
unsigned int i;
- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
E1000_TXD_CMD_TSE;
txd_upper |= E1000_TXD_POPTS_TXSM << 8;
- if(likely(tx_flags & E1000_TX_FLAGS_IPV4))
+ if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
txd_upper |= E1000_TXD_POPTS_IXSM << 8;
}
- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
+ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
txd_upper |= E1000_TXD_POPTS_TXSM << 8;
}
- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
+ if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
txd_lower |= E1000_TXD_CMD_VLE;
txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
}
i = tx_ring->next_to_use;
- while(count--) {
+ while (count--) {
buffer_info = &tx_ring->buffer_info[i];
tx_desc = E1000_TX_DESC(*tx_ring, i);
tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
tx_desc->lower.data =
cpu_to_le32(txd_lower | buffer_info->length);
tx_desc->upper.data = cpu_to_le32(txd_upper);
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
@@ -2597,20 +2807,20 @@ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR);
- if(adapter->link_duplex != HALF_DUPLEX)
+ if (adapter->link_duplex != HALF_DUPLEX)
goto no_fifo_stall_required;
- if(atomic_read(&adapter->tx_fifo_stall))
+ if (atomic_read(&adapter->tx_fifo_stall))
return 1;
- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
+ if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
atomic_set(&adapter->tx_fifo_stall, 1);
return 1;
}
no_fifo_stall_required:
adapter->tx_fifo_head += skb_fifo_len;
- if(adapter->tx_fifo_head >= adapter->tx_fifo_size)
+ if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
adapter->tx_fifo_head -= adapter->tx_fifo_size;
return 0;
}
@@ -2621,27 +2831,27 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
{
struct e1000_hw *hw = &adapter->hw;
uint16_t length, offset;
- if(vlan_tx_tag_present(skb)) {
- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ if (vlan_tx_tag_present(skb)) {
+ if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
( adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
return 0;
}
- if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+ if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
struct ethhdr *eth = (struct ethhdr *) skb->data;
- if((htons(ETH_P_IP) == eth->h_proto)) {
- const struct iphdr *ip =
+ if ((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
(struct iphdr *)((uint8_t *)skb->data+14);
- if(IPPROTO_UDP == ip->protocol) {
- struct udphdr *udp =
- (struct udphdr *)((uint8_t *)ip +
+ if (IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+ (struct udphdr *)((uint8_t *)ip +
(ip->ihl << 2));
- if(ntohs(udp->dest) == 67) {
+ if (ntohs(udp->dest) == 67) {
offset = (uint8_t *)udp + 8 - skb->data;
length = skb->len - offset;
return e1000_mng_write_dhcp_info(hw,
- (uint8_t *)udp + 8,
+ (uint8_t *)udp + 8,
length);
}
}
@@ -2664,7 +2874,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int nr_frags = 0;
unsigned int mss = 0;
int count = 0;
- int tso;
+ int tso;
unsigned int f;
len -= skb->data_len;
@@ -2687,16 +2897,35 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* 4 = ceil(buffer len/mss). To make sure we don't
* overrun the FIFO, adjust the max buffer len if mss
* drops. */
- if(mss) {
+ if (mss) {
+ uint8_t hdr_len;
max_per_txd = min(mss << 2, max_per_txd);
max_txd_pwr = fls(max_per_txd) - 1;
+
+ /* TSO Workaround for 82571/2 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
+ 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;
+ }
+ len = skb->len - skb->data_len;
+ }
}
- if((mss) || (skb->ip_summed == CHECKSUM_HW))
+ /* reserve a descriptor for the offload context */
+ if ((mss) || (skb->ip_summed == CHECKSUM_HW))
count++;
count++;
#else
- if(skb->ip_summed == CHECKSUM_HW)
+ if (skb->ip_summed == CHECKSUM_HW)
count++;
#endif
@@ -2709,45 +2938,24 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
count += TXD_USE_COUNT(len, max_txd_pwr);
- if(adapter->pcix_82544)
+ if (adapter->pcix_82544)
count++;
- /* work-around for errata 10 and it applies to all controllers
+ /* work-around for errata 10 and it applies to all controllers
* in PCI-X mode, so add one more descriptor to the count
*/
- if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
(len > 2015)))
count++;
nr_frags = skb_shinfo(skb)->nr_frags;
- for(f = 0; f < nr_frags; f++)
+ for (f = 0; f < nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
max_txd_pwr);
- if(adapter->pcix_82544)
+ if (adapter->pcix_82544)
count += nr_frags;
-#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) )
+ if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
local_irq_save(flags);
@@ -2765,8 +2973,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
- if(unlikely(adapter->hw.mac_type == e1000_82547)) {
- if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
+ if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+ if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
@@ -2774,13 +2982,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
}
- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
tx_flags |= E1000_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
first = tx_ring->next_to_use;
-
+
tso = e1000_tso(adapter, tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
@@ -2833,6 +3041,7 @@ e1000_tx_timeout_task(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->tx_timeout_count++;
e1000_down(adapter);
e1000_up(adapter);
}
@@ -2850,7 +3059,7 @@ e1000_get_stats(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_update_stats(adapter);
+ /* only return the current stats */
return &adapter->net_stats;
}
@@ -2868,56 +3077,57 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
struct e1000_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
- return -EINVAL;
- }
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
- /* might want this to be bigger enum check... */
- /* 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");
+ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
return -EINVAL;
}
- if(adapter->hw.mac_type > e1000_82547_rev_2) {
- adapter->rx_buffer_len = max_frame;
- E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
- } else {
- if(unlikely((adapter->hw.mac_type < e1000_82543) &&
- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
- DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
- "on 82542\n");
+ /* Adapter-specific max frame size limits. */
+ switch (adapter->hw.mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82573:
+ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
+ return -EINVAL;
+ }
+ break;
+ case e1000_82571:
+ case e1000_82572:
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
+ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
return -EINVAL;
-
- } else {
- if(max_frame <= E1000_RXBUFFER_2048) {
- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
- } else if(max_frame <= E1000_RXBUFFER_4096) {
- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
- } else if(max_frame <= E1000_RXBUFFER_8192) {
- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
- } else if(max_frame <= E1000_RXBUFFER_16384) {
- adapter->rx_buffer_len = E1000_RXBUFFER_16384;
- }
}
+ break;
+ default:
+ /* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
+ break;
}
+ /* since the driver code now supports splitting a packet across
+ * multiple descriptors, most of the fifo related limitations on
+ * jumbo frame traffic have gone away.
+ * simply use 2k descriptors for everything.
+ *
+ * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ * means we reserve 2 more, this pushes us to allocate from the next
+ * larger slab size
+ * i.e. RXBUFFER_2048 --> size-4096 slab */
+
+ /* recent hardware supports 1KB granularity */
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->rx_buffer_len =
+ ((max_frame < E1000_RXBUFFER_2048) ?
+ max_frame : E1000_RXBUFFER_2048);
+ E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
+ } else
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+
netdev->mtu = new_mtu;
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
@@ -3004,7 +3214,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
hw->collision_delta = E1000_READ_REG(hw, COLC);
adapter->stats.colc += hw->collision_delta;
- if(hw->mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
@@ -3012,7 +3222,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
}
- if(hw->mac_type > e1000_82547_rev_2) {
+ if (hw->mac_type > e1000_82547_rev_2) {
adapter->stats.iac += E1000_READ_REG(hw, IAC);
adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
@@ -3037,12 +3247,11 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc +
- adapter->stats.rlec + adapter->stats.mpc +
- adapter->stats.cexterr;
+ adapter->stats.rlec + adapter->stats.cexterr;
+ adapter->net_stats.rx_dropped = 0;
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;
- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
/* Tx Errors */
@@ -3057,14 +3266,14 @@ e1000_update_stats(struct e1000_adapter *adapter)
/* Phy Stats */
- if(hw->media_type == e1000_media_type_copper) {
- if((adapter->link_speed == SPEED_1000) &&
+ if (hw->media_type == e1000_media_type_copper) {
+ if ((adapter->link_speed == SPEED_1000) &&
(!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
adapter->phy_stats.idle_errors += phy_tmp;
}
- if((hw->mac_type <= e1000_82546) &&
+ if ((hw->mac_type <= e1000_82546) &&
(hw->phy_type == e1000_phy_m88) &&
!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
adapter->phy_stats.receive_errors += phy_tmp;
@@ -3110,32 +3319,44 @@ 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);
-#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+#ifndef CONFIG_E1000_NAPI
int i;
+#else
+ /* Interrupt Auto-Mask...upon reading ICR,
+ * interrupts are masked. No need for the
+ * IMC write, but it does mean we should
+ * account for it ASAP. */
+ if (likely(hw->mac_type >= e1000_82571))
+ atomic_inc(&adapter->irq_sem);
#endif
- if(unlikely(!icr))
+ if (unlikely(!icr)) {
+#ifdef CONFIG_E1000_NAPI
+ if (hw->mac_type >= e1000_82571)
+ e1000_irq_enable(adapter);
+#endif
return IRQ_NONE; /* Not our interrupt */
+ }
- if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
+ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
mod_timer(&adapter->watchdog_timer, jiffies);
}
#ifdef CONFIG_E1000_NAPI
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(hw, IMC, ~0);
- E1000_WRITE_FLUSH(hw);
+ if (unlikely(hw->mac_type < e1000_82571)) {
+ 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);
+ /* We must setup the cpumask once count == 0 since
+ * each cpu bit is cleared when the work is done. */
+ adapter->rx_sched_call_data.cpumask = adapter->cpumask;
+ atomic_add(adapter->num_rx_queues - 1, &adapter->irq_sem);
+ atomic_set(&adapter->rx_sched_call_data.count,
+ adapter->num_rx_queues);
smp_call_async_mask(&adapter->rx_sched_call_data);
} else {
printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
@@ -3149,26 +3370,26 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
#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.
- When an interrupt assertion message is generated later,
- two messages are re-ordered and sent out.
- That causes APIC to think 82547 is in de-assertion
- state, while 82547 is in assertion state, resulting
- in dead lock. Writing IMC forces 82547 into
- de-assertion state.
- */
- if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){
+ * Due to Hub Link bus being occupied, an interrupt
+ * de-assertion message is not able to be sent.
+ * When an interrupt assertion message is generated later,
+ * two messages are re-ordered and sent out.
+ * That causes APIC to think 82547 is in de-assertion
+ * state, while 82547 is in assertion state, resulting
+ * in dead lock. Writing IMC forces 82547 into
+ * de-assertion state.
+ */
+ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) {
atomic_inc(&adapter->irq_sem);
E1000_WRITE_REG(hw, IMC, ~0);
}
- for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+ for (i = 0; i < E1000_MAX_INTR; i++)
+ 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)
+ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
#endif /* CONFIG_E1000_NAPI */
@@ -3187,7 +3408,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
{
struct e1000_adapter *adapter;
int work_to_do = min(*budget, poll_dev->quota);
- int tx_cleaned, i = 0, work_done = 0;
+ int tx_cleaned = 0, i = 0, work_done = 0;
/* Must NOT use netdev_priv macro here. */
adapter = poll_dev->priv;
@@ -3198,19 +3419,31 @@ e1000_clean(struct net_device *poll_dev, int *budget)
while (poll_dev != &adapter->polling_netdev[i]) {
i++;
- if (unlikely(i == adapter->num_queues))
+ if (unlikely(i == adapter->num_rx_queues))
BUG();
}
- tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+ if (likely(adapter->num_tx_queues == 1)) {
+ /* e1000_clean is called per-cpu. This lock protects
+ * tx_ring[0] from being cleaned by multiple cpus
+ * simultaneously. A failure obtaining the lock means
+ * tx_ring[0] is currently being cleaned anyway. */
+ if (spin_trylock(&adapter->tx_queue_lock)) {
+ tx_cleaned = e1000_clean_tx_irq(adapter,
+ &adapter->tx_ring[0]);
+ spin_unlock(&adapter->tx_queue_lock);
+ }
+ } else
+ 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;
poll_dev->quota -= work_done;
-
+
/* If no Tx and not enough Rx work done, exit the polling mode */
- if((!tx_cleaned && (work_done == 0)) ||
+ if ((!tx_cleaned && (work_done == 0)) ||
!netif_running(adapter->netdev)) {
quit_polling:
netif_rx_complete(poll_dev);
@@ -3242,22 +3475,24 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop_desc = E1000_TX_DESC(*tx_ring, eop);
while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
- for(cleaned = FALSE; !cleaned; ) {
+ for (cleaned = FALSE; !cleaned; ) {
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
cleaned = (i == eop);
+#ifdef CONFIG_E1000_MQ
+ tx_ring->tx_stats.bytes += buffer_info->length;
+#endif
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
+ memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
- tx_desc->buffer_addr = 0;
- tx_desc->lower.data = 0;
- tx_desc->upper.data = 0;
-
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
- tx_ring->pkt++;
-
+#ifdef CONFIG_E1000_MQ
+ tx_ring->tx_stats.packets++;
+#endif
+
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
}
@@ -3266,7 +3501,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
spin_lock(&tx_ring->tx_lock);
- if(unlikely(cleaned && netif_queue_stopped(netdev) &&
+ if (unlikely(cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev)))
netif_wake_queue(netdev);
@@ -3276,32 +3511,31 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
/* 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;
- if (tx_ring->buffer_info[i].dma &&
- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+ if (tx_ring->buffer_info[eop].dma &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+ adapter->tx_timeout_factor * HZ)
&& !(E1000_READ_REG(&adapter->hw, STATUS) &
- E1000_STATUS_TXOFF)) {
+ E1000_STATUS_TXOFF)) {
/* detected Tx unit hang */
- i = tx_ring->next_to_clean;
- eop = tx_ring->buffer_info[i].next_to_watch;
- eop_desc = E1000_TX_DESC(*tx_ring, eop);
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+ " Tx Queue <%lu>\n"
" TDH <%x>\n"
" TDT <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%llx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
+ (unsigned long)((tx_ring - adapter->tx_ring) /
+ sizeof(struct e1000_tx_ring)),
readl(adapter->hw.hw_addr + tx_ring->tdh),
readl(adapter->hw.hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
- i,
- (unsigned long long)tx_ring->buffer_info[i].dma,
- tx_ring->buffer_info[i].time_stamp,
+ tx_ring->next_to_clean,
+ tx_ring->buffer_info[eop].time_stamp,
eop,
jiffies,
eop_desc->upper.fields.status);
@@ -3329,21 +3563,21 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
skb->ip_summed = CHECKSUM_NONE;
/* 82543 or newer only */
- if(unlikely(adapter->hw.mac_type < e1000_82543)) return;
+ if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
- if(unlikely(status & E1000_RXD_STAT_IXSM)) return;
+ if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
/* TCP/UDP checksum error bit is set */
- if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
+ if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
/* let the stack verify checksum errors */
adapter->hw_csum_err++;
return;
}
/* TCP/UDP Checksum has not been calculated */
- if(adapter->hw.mac_type <= e1000_82547_rev_2) {
- if(!(status & E1000_RXD_STAT_TCPCS))
+ if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if (!(status & E1000_RXD_STAT_TCPCS))
return;
} else {
- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
+ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
return;
}
/* It must be a TCP or UDP packet with a valid checksum */
@@ -3379,46 +3613,87 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_rx_desc *rx_desc;
- struct e1000_buffer *buffer_info;
- struct sk_buff *skb;
+ struct e1000_rx_desc *rx_desc, *next_rxd;
+ struct e1000_buffer *buffer_info, *next_buffer;
unsigned long flags;
uint32_t length;
uint8_t last_byte;
unsigned int i;
- boolean_t cleaned = FALSE;
+ int cleaned_count = 0;
+ boolean_t cleaned = FALSE, multi_descriptor = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
+ buffer_info = &rx_ring->buffer_info[i];
- while(rx_desc->status & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
+ while (rx_desc->status & E1000_RXD_STAT_DD) {
+ struct sk_buff *skb, *next_skb;
+ u8 status;
#ifdef CONFIG_E1000_NAPI
- if(*work_done >= work_to_do)
+ if (*work_done >= work_to_do)
break;
(*work_done)++;
#endif
- cleaned = TRUE;
+ status = rx_desc->status;
+ skb = buffer_info->skb;
+ buffer_info->skb = NULL;
+
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC(*rx_ring, i);
+ next_buffer = &rx_ring->buffer_info[i];
+ next_skb = next_buffer->skb;
+ cleaned = TRUE;
+ cleaned_count++;
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
length = le16_to_cpu(rx_desc->length);
- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
- /* All receives must fit into a single buffer */
- E1000_DBG("%s: Receive packet consumed multiple"
- " buffers\n", netdev->name);
- dev_kfree_skb_irq(skb);
+ skb_put(skb, length);
+
+ if (!(status & E1000_RXD_STAT_EOP)) {
+ if (!rx_ring->rx_skb_top) {
+ rx_ring->rx_skb_top = skb;
+ rx_ring->rx_skb_top->len = length;
+ rx_ring->rx_skb_prev = skb;
+ } else {
+ if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) {
+ rx_ring->rx_skb_prev->next = skb;
+ skb->prev = rx_ring->rx_skb_prev;
+ } else {
+ skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb;
+ }
+ rx_ring->rx_skb_prev = skb;
+ rx_ring->rx_skb_top->data_len += length;
+ }
goto next_desc;
+ } else {
+ if (rx_ring->rx_skb_top) {
+ if (skb_shinfo(rx_ring->rx_skb_top)
+ ->frag_list) {
+ rx_ring->rx_skb_prev->next = skb;
+ skb->prev = rx_ring->rx_skb_prev;
+ } else
+ skb_shinfo(rx_ring->rx_skb_top)
+ ->frag_list = skb;
+
+ rx_ring->rx_skb_top->data_len += length;
+ rx_ring->rx_skb_top->len +=
+ rx_ring->rx_skb_top->data_len;
+
+ skb = rx_ring->rx_skb_top;
+ multi_descriptor = TRUE;
+ rx_ring->rx_skb_top = NULL;
+ rx_ring->rx_skb_prev = NULL;
+ }
}
- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
last_byte = *(skb->data + length - 1);
- if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
+ if (TBI_ACCEPT(&adapter->hw, status,
rx_desc->errors, length, last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
e1000_tbi_adjust_stats(&adapter->hw,
@@ -3433,18 +3708,41 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
}
- /* Good Receive */
- skb_put(skb, length - ETHERNET_FCS_SIZE);
+ /* code added for copybreak, this should improve
+ * performance for small packets with large amounts
+ * of reassembly being done in the stack */
+#define E1000_CB_LENGTH 256
+ if ((length < E1000_CB_LENGTH) &&
+ !rx_ring->rx_skb_top &&
+ /* or maybe (status & E1000_RXD_STAT_EOP) && */
+ !multi_descriptor) {
+ struct sk_buff *new_skb =
+ dev_alloc_skb(length + NET_IP_ALIGN);
+ if (new_skb) {
+ skb_reserve(new_skb, NET_IP_ALIGN);
+ new_skb->dev = netdev;
+ memcpy(new_skb->data - NET_IP_ALIGN,
+ skb->data - NET_IP_ALIGN,
+ length + NET_IP_ALIGN);
+ /* save the skb in buffer_info as good */
+ buffer_info->skb = skb;
+ skb = new_skb;
+ skb_put(skb, length);
+ }
+ }
+
+ /* end copybreak code */
/* Receive Checksum Offload */
e1000_rx_checksum(adapter,
- (uint32_t)(rx_desc->status) |
+ (uint32_t)(status) |
((uint32_t)(rx_desc->errors) << 24),
rx_desc->csum, skb);
+
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
- if(unlikely(adapter->vlgrp &&
- (rx_desc->status & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp &&
+ (status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3452,8 +3750,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
- if(unlikely(adapter->vlgrp &&
- (rx_desc->status & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp &&
+ (status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3462,17 +3760,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+ rx_ring->rx_stats.packets++;
+ rx_ring->rx_stats.bytes += length;
+#endif
next_desc:
rx_desc->status = 0;
- buffer_info->skb = NULL;
- if(unlikely(++i == rx_ring->count)) i = 0;
- rx_desc = E1000_RX_DESC(*rx_ring, i);
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
return cleaned;
}
@@ -3492,52 +3801,59 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring)
#endif
{
- union e1000_rx_desc_packet_split *rx_desc;
+ union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_buffer *buffer_info;
+ struct e1000_buffer *buffer_info, *next_buffer;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *skb;
+ struct sk_buff *skb, *next_skb;
unsigned int i, j;
uint32_t length, staterr;
+ int cleaned_count = 0;
boolean_t cleaned = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+ buffer_info = &rx_ring->buffer_info[i];
- while(staterr & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
+ while (staterr & E1000_RXD_STAT_DD) {
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
#ifdef CONFIG_E1000_NAPI
- if(unlikely(*work_done >= work_to_do))
+ if (unlikely(*work_done >= work_to_do))
break;
(*work_done)++;
#endif
+ skb = buffer_info->skb;
+
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
+ next_buffer = &rx_ring->buffer_info[i];
+ next_skb = next_buffer->skb;
+
cleaned = TRUE;
+ cleaned_count++;
pci_unmap_single(pdev, buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
-
- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+ if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
E1000_DBG("%s: Packet Split buffers didn't pick up"
" the full packet\n", netdev->name);
dev_kfree_skb_irq(skb);
goto next_desc;
}
- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
dev_kfree_skb_irq(skb);
goto next_desc;
}
length = le16_to_cpu(rx_desc->wb.middle.length0);
- if(unlikely(!length)) {
+ if (unlikely(!length)) {
E1000_DBG("%s: Last part of the packet spanning"
" multiple descriptors\n", netdev->name);
dev_kfree_skb_irq(skb);
@@ -3547,8 +3863,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
/* Good Receive */
skb_put(skb, length);
- for(j = 0; j < adapter->rx_ps_pages; j++) {
- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+ for (j = 0; j < adapter->rx_ps_pages; j++) {
+ if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
@@ -3568,15 +3884,11 @@ 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);
- if(likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP)) {
+ if (likely(rx_desc->wb.upper.header_status &
+ 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))) {
+ if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3584,7 +3896,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3593,18 +3905,31 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+ rx_ring->rx_stats.packets++;
+ rx_ring->rx_stats.bytes += length;
+#endif
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;
buffer_info->skb = NULL;
- if(unlikely(++i == rx_ring->count)) i = 0;
- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
+
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
return cleaned;
}
@@ -3616,7 +3941,8 @@ next_desc:
static void
e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3629,11 +3955,18 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
- while(!buffer_info->skb) {
- skb = dev_alloc_skb(bufsz);
+ while (cleaned_count--) {
+ if (!(skb = buffer_info->skb))
+ skb = dev_alloc_skb(bufsz);
+ else {
+ skb_trim(skb, 0);
+ goto map_skb;
+ }
+
- if(unlikely(!skb)) {
+ if (unlikely(!skb)) {
/* Better luck next round */
+ adapter->alloc_rx_buff_failed++;
break;
}
@@ -3670,6 +4003,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
+map_skb:
buffer_info->dma = pci_map_single(pdev,
skb->data,
adapter->rx_buffer_len,
@@ -3695,20 +4029,23 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
rx_desc = E1000_RX_DESC(*rx_ring, i);
rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
- }
-
- if(unlikely(++i == rx_ring->count)) i = 0;
+ if (unlikely(++i == rx_ring->count))
+ i = 0;
buffer_info = &rx_ring->buffer_info[i];
}
- rx_ring->next_to_use = i;
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0))
+ i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ }
}
/**
@@ -3718,7 +4055,8 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
static void
e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3734,16 +4072,18 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
- while(!buffer_info->skb) {
+ while (cleaned_count--) {
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for (j = 0; j < PS_PAGE_BUFFERS; j++) {
if (j < adapter->rx_ps_pages) {
if (likely(!ps_page->ps_page[j])) {
ps_page->ps_page[j] =
alloc_page(GFP_ATOMIC);
- if (unlikely(!ps_page->ps_page[j]))
+ if (unlikely(!ps_page->ps_page[j])) {
+ adapter->alloc_rx_buff_failed++;
goto no_buffers;
+ }
ps_page_dma->ps_page_dma[j] =
pci_map_page(pdev,
ps_page->ps_page[j],
@@ -3751,7 +4091,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
PCI_DMA_FROMDEVICE);
}
/* Refresh the desc even if buffer_addrs didn't
- * change because each write-back erases
+ * change because each write-back erases
* this info.
*/
rx_desc->read.buffer_addr[j+1] =
@@ -3762,8 +4102,10 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
- if(unlikely(!skb))
+ if (unlikely(!skb)) {
+ adapter->alloc_rx_buff_failed++;
break;
+ }
/* Make buffer alignment 2 beyond a 16 byte boundary
* this will result in a 16 byte aligned IP header after
@@ -3781,27 +4123,28 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- /* Hardware increments by 16 bytes, but packet split
- * descriptors are 32 bytes...so we increment tail
- * twice as much.
- */
- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
- }
-
- if(unlikely(++i == rx_ring->count)) i = 0;
+ if (unlikely(++i == rx_ring->count)) i = 0;
buffer_info = &rx_ring->buffer_info[i];
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
}
no_buffers:
- rx_ring->next_to_use = i;
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0)) i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ /* Hardware increments by 16 bytes, but packet split
+ * descriptors are 32 bytes...so we increment tail
+ * twice as much.
+ */
+ writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+ }
}
/**
@@ -3815,24 +4158,24 @@ e1000_smartspeed(struct e1000_adapter *adapter)
uint16_t phy_status;
uint16_t phy_ctrl;
- if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
+ if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
!(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
return;
- if(adapter->smartspeed == 0) {
+ if (adapter->smartspeed == 0) {
/* If Master/Slave config fault is asserted twice,
* we assume back-to-back */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
- if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
- if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
- if(phy_ctrl & CR_1000T_MS_ENABLE) {
+ if (phy_ctrl & CR_1000T_MS_ENABLE) {
phy_ctrl &= ~CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
phy_ctrl);
adapter->smartspeed++;
- if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+ if (!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
&phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
@@ -3842,12 +4185,12 @@ e1000_smartspeed(struct e1000_adapter *adapter)
}
}
return;
- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
+ } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
/* If still no link, perhaps using 2/3 pair cable */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
phy_ctrl |= CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
- if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+ if (!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
@@ -3855,7 +4198,7 @@ e1000_smartspeed(struct e1000_adapter *adapter)
}
}
/* Restart process after E1000_SMARTSPEED_MAX iterations */
- if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
+ if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
adapter->smartspeed = 0;
}
@@ -3896,7 +4239,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
uint16_t spddplx;
unsigned long flags;
- if(adapter->hw.media_type != e1000_media_type_copper)
+ if (adapter->hw.media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
switch (cmd) {
@@ -3904,10 +4247,10 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
data->phy_id = adapter->hw.phy_addr;
break;
case SIOCGMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
&data->val_out)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
@@ -3915,23 +4258,23 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
case SIOCSMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if(data->reg_num & ~(0x1F))
+ if (data->reg_num & ~(0x1F))
return -EFAULT;
mii_reg = data->val_in;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
mii_reg)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
switch (data->reg_num) {
case PHY_CTRL:
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
break;
- if(mii_reg & MII_CR_AUTO_NEG_EN) {
+ if (mii_reg & MII_CR_AUTO_NEG_EN) {
adapter->hw.autoneg = 1;
adapter->hw.autoneg_advertised = 0x2F;
} else {
@@ -3946,14 +4289,14 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
HALF_DUPLEX;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if(retval) {
+ if (retval) {
spin_unlock_irqrestore(
- &adapter->stats_lock,
+ &adapter->stats_lock,
flags);
return retval;
}
}
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
@@ -3961,7 +4304,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if(e1000_phy_reset(&adapter->hw)) {
+ if (e1000_phy_reset(&adapter->hw)) {
spin_unlock_irqrestore(
&adapter->stats_lock, flags);
return -EIO;
@@ -3971,9 +4314,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
} else {
switch (data->reg_num) {
case PHY_CTRL:
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
break;
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
@@ -3995,7 +4338,7 @@ e1000_pci_set_mwi(struct e1000_hw *hw)
struct e1000_adapter *adapter = hw->back;
int ret_val = pci_set_mwi(adapter->pdev);
- if(ret_val)
+ if (ret_val)
DPRINTK(PROBE, ERR, "Error in setting MWI\n");
}
@@ -4044,7 +4387,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
e1000_irq_disable(adapter);
adapter->vlgrp = grp;
- if(grp) {
+ if (grp) {
/* enable VLAN tag insert/strip */
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
ctrl |= E1000_CTRL_VME;
@@ -4066,7 +4409,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~E1000_RCTL_VFE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+ if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
}
@@ -4080,9 +4423,10 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
- if((adapter->hw.mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id))
+
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
@@ -4099,15 +4443,19 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
e1000_irq_disable(adapter);
- if(adapter->vlgrp)
+ if (adapter->vlgrp)
adapter->vlgrp->vlan_devices[vid] = NULL;
e1000_irq_enable(adapter);
- if((adapter->hw.mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id))
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id)) {
+ /* release control to f/w */
+ e1000_release_hw_control(adapter);
return;
+ }
+
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -4120,10 +4468,10 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
{
e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
- if(adapter->vlgrp) {
+ if (adapter->vlgrp) {
uint16_t vid;
- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if(!adapter->vlgrp->vlan_devices[vid])
+ for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if (!adapter->vlgrp->vlan_devices[vid])
continue;
e1000_vlan_rx_add_vid(adapter->netdev, vid);
}
@@ -4136,13 +4484,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
adapter->hw.autoneg = 0;
/* Fiber NICs only allow 1000 gbps Full duplex */
- if((adapter->hw.media_type == e1000_media_type_fiber) &&
+ if ((adapter->hw.media_type == e1000_media_type_fiber) &&
spddplx != (SPEED_1000 + DUPLEX_FULL)) {
DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
return -EINVAL;
}
- switch(spddplx) {
+ switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_10_half;
break;
@@ -4168,35 +4516,92 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
}
#ifdef CONFIG_PM
+/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config
+ * space versus the 64 bytes that pci_[save|restore]_state handle
+ */
+#define PCIE_CONFIG_SPACE_LEN 256
+#define PCI_CONFIG_SPACE_LEN 64
+static int
+e1000_pci_save_state(struct e1000_adapter *adapter)
+{
+ struct pci_dev *dev = adapter->pdev;
+ int size;
+ int i;
+ if (adapter->hw.mac_type >= e1000_82571)
+ size = PCIE_CONFIG_SPACE_LEN;
+ else
+ size = PCI_CONFIG_SPACE_LEN;
+
+ WARN_ON(adapter->config_space != NULL);
+
+ adapter->config_space = kmalloc(size, GFP_KERNEL);
+ if (!adapter->config_space) {
+ DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
+ return -ENOMEM;
+ }
+ for (i = 0; i < (size / 4); i++)
+ pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
+ return 0;
+}
+
+static void
+e1000_pci_restore_state(struct e1000_adapter *adapter)
+{
+ struct pci_dev *dev = adapter->pdev;
+ int size;
+ int i;
+ if (adapter->config_space == NULL)
+ return;
+ if (adapter->hw.mac_type >= e1000_82571)
+ size = PCIE_CONFIG_SPACE_LEN;
+ else
+ size = PCI_CONFIG_SPACE_LEN;
+ for (i = 0; i < (size / 4); i++)
+ pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
+ kfree(adapter->config_space);
+ adapter->config_space = NULL;
+ return;
+}
+#endif /* CONFIG_PM */
+
static int
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);
- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
+ uint32_t ctrl, ctrl_ext, rctl, manc, status;
uint32_t wufc = adapter->wol;
+ int retval = 0;
netif_device_detach(netdev);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_down(adapter);
+#ifdef CONFIG_PM
+ /* implement our own version of pci_save_state(pdev) because pci
+ * express adapters have larger 256 byte config spaces */
+ retval = e1000_pci_save_state(adapter);
+ if (retval)
+ return retval;
+#endif
+
status = E1000_READ_REG(&adapter->hw, STATUS);
- if(status & E1000_STATUS_LU)
+ if (status & E1000_STATUS_LU)
wufc &= ~E1000_WUFC_LNKC;
- if(wufc) {
+ if (wufc) {
e1000_setup_rctl(adapter);
e1000_set_multi(netdev);
/* turn on all-multi mode if wake on multicast is enabled */
- if(adapter->wol & E1000_WUFC_MC) {
+ if (adapter->wol & E1000_WUFC_MC) {
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
- if(adapter->hw.mac_type >= e1000_82540) {
+ if (adapter->hw.mac_type >= e1000_82540) {
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
/* advertise wake from D3Cold */
#define E1000_CTRL_ADVD3WUC 0x00100000
@@ -4207,7 +4612,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
}
- if(adapter->hw.media_type == e1000_media_type_fiber ||
+ if (adapter->hw.media_type == e1000_media_type_fiber ||
adapter->hw.media_type == e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
@@ -4220,96 +4625,96 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
- pci_enable_wake(pdev, 3, 1);
- pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
} else {
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, 0);
- pci_enable_wake(pdev, 3, 0);
- pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
}
- pci_save_state(pdev);
-
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
- if(manc & E1000_MANC_SMBUS_EN) {
+ if (manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc);
- pci_enable_wake(pdev, 3, 1);
- pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
}
}
- 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,
- swsm & ~E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+ * would have already happened in close and is redundant. */
+ e1000_release_hw_control(adapter);
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error in setting power state\n");
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;
+ int retval;
+ uint32_t manc, ret_val;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
+ retval = pci_set_power_state(pdev, PCI_D0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error in setting power state\n");
+ e1000_pci_restore_state(adapter);
ret_val = pci_enable_device(pdev);
pci_set_master(pdev);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+ retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_up(adapter);
netif_device_attach(netdev);
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
- 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,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
return 0;
}
@@ -4327,6 +4732,9 @@ e1000_netpoll(struct net_device *netdev)
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
e1000_clean_tx_irq(adapter, adapter->tx_ring);
+#ifndef CONFIG_E1000_NAPI
+ adapter->clean_rx(adapter, adapter->rx_ring);
+#endif
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index aac64de61437..9790db974dc1 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -47,7 +47,7 @@
BUG(); \
} else { \
msleep(x); \
- } } while(0)
+ } } while (0)
/* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 38695d5b4637..3768d83cd577 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -177,7 +177,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
*
* Valid Range: 100-100000 (0=off, 1=dynamic)
*
- * Default Value: 1
+ * Default Value: 8000
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
@@ -227,7 +227,7 @@ static int __devinit
e1000_validate_option(int *value, struct e1000_option *opt,
struct e1000_adapter *adapter)
{
- if(*value == OPTION_UNSET) {
+ if (*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
@@ -244,7 +244,7 @@ e1000_validate_option(int *value, struct e1000_option *opt,
}
break;
case range_option:
- if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
DPRINTK(PROBE, INFO,
"%s set to %i\n", opt->name, *value);
return 0;
@@ -254,10 +254,10 @@ e1000_validate_option(int *value, struct e1000_option *opt,
int i;
struct e1000_opt_list *ent;
- for(i = 0; i < opt->arg.l.nr; i++) {
+ for (i = 0; i < opt->arg.l.nr; i++) {
ent = &opt->arg.l.p[i];
- if(*value == ent->i) {
- if(ent->str[0] != '\0')
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
DPRINTK(PROBE, INFO, "%s\n", ent->str);
return 0;
}
@@ -291,7 +291,7 @@ void __devinit
e1000_check_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if(bd >= E1000_MAX_NIC) {
+ if (bd >= E1000_MAX_NIC) {
DPRINTK(PROBE, NOTICE,
"Warning: no configuration for board #%i\n", bd);
DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
@@ -315,12 +315,12 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxDescriptors > bd) {
tx_ring->count = TxDescriptors[bd];
e1000_validate_option(&tx_ring->count, &opt, adapter);
- E1000_ROUNDUP(tx_ring->count,
+ E1000_ROUNDUP(tx_ring->count,
REQ_TX_DESCRIPTOR_MULTIPLE);
} else {
tx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
tx_ring[i].count = tx_ring->count;
}
{ /* Receive Descriptor Count */
@@ -341,12 +341,12 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxDescriptors > bd) {
rx_ring->count = RxDescriptors[bd];
e1000_validate_option(&rx_ring->count, &opt, adapter);
- E1000_ROUNDUP(rx_ring->count,
+ E1000_ROUNDUP(rx_ring->count,
REQ_RX_DESCRIPTOR_MULTIPLE);
} else {
rx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
rx_ring[i].count = rx_ring->count;
}
{ /* Checksum Offload Enable/Disable */
@@ -388,7 +388,7 @@ e1000_check_options(struct e1000_adapter *adapter)
e1000_validate_option(&fc, &opt, adapter);
adapter->hw.fc = adapter->hw.original_fc = fc;
} else {
- adapter->hw.fc = opt.def;
+ adapter->hw.fc = adapter->hw.original_fc = opt.def;
}
}
{ /* Transmit Interrupt Delay */
@@ -403,7 +403,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxIntDelay > bd) {
adapter->tx_int_delay = TxIntDelay[bd];
- e1000_validate_option(&adapter->tx_int_delay, &opt,
+ e1000_validate_option(&adapter->tx_int_delay, &opt,
adapter);
} else {
adapter->tx_int_delay = opt.def;
@@ -421,7 +421,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxAbsIntDelay > bd) {
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
- e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
+ e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
adapter);
} else {
adapter->tx_abs_int_delay = opt.def;
@@ -439,7 +439,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxIntDelay > bd) {
adapter->rx_int_delay = RxIntDelay[bd];
- e1000_validate_option(&adapter->rx_int_delay, &opt,
+ e1000_validate_option(&adapter->rx_int_delay, &opt,
adapter);
} else {
adapter->rx_int_delay = opt.def;
@@ -457,7 +457,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxAbsIntDelay > bd) {
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
- e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
+ e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
adapter);
} else {
adapter->rx_abs_int_delay = opt.def;
@@ -475,17 +475,17 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
- switch(adapter->itr) {
+ switch (adapter->itr) {
case 0:
- DPRINTK(PROBE, INFO, "%s turned off\n",
+ DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
break;
case 1:
- DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
+ DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
opt.name);
break;
default:
- e1000_validate_option(&adapter->itr, &opt,
+ e1000_validate_option(&adapter->itr, &opt,
adapter);
break;
}
@@ -494,7 +494,7 @@ e1000_check_options(struct e1000_adapter *adapter)
}
}
- switch(adapter->hw.media_type) {
+ switch (adapter->hw.media_type) {
case e1000_media_type_fiber:
case e1000_media_type_internal_serdes:
e1000_check_fiber_options(adapter);
@@ -518,17 +518,17 @@ static void __devinit
e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if(num_Speed > bd) {
+ if (num_Speed > bd) {
DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
"parameter ignored\n");
}
- if(num_Duplex > bd) {
+ if (num_Duplex > bd) {
DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
"parameter ignored\n");
}
- if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
+ if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
"not valid for fiber adapters, "
"parameter ignored\n");
@@ -545,7 +545,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter)
static void __devinit
e1000_check_copper_options(struct e1000_adapter *adapter)
{
- int speed, dplx;
+ int speed, dplx, an;
int bd = adapter->bd_number;
{ /* Speed */
@@ -584,6 +584,12 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = dplx_list }}
};
+ if (e1000_check_phy_reset_block(&adapter->hw)) {
+ DPRINTK(PROBE, INFO,
+ "Link active due to SoL/IDER Session. "
+ "Speed/Duplex/AutoNeg parameter ignored.\n");
+ return;
+ }
if (num_Duplex > bd) {
dplx = Duplex[bd];
e1000_validate_option(&dplx, &opt, adapter);
@@ -592,7 +598,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
}
}
- if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
+ if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
DPRINTK(PROBE, INFO,
"AutoNeg specified along with Speed or Duplex, "
"parameter ignored\n");
@@ -641,15 +647,19 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = an_list }}
};
- int an = AutoNeg[bd];
- e1000_validate_option(&an, &opt, adapter);
+ if (num_AutoNeg > bd) {
+ an = AutoNeg[bd];
+ e1000_validate_option(&an, &opt, adapter);
+ } else {
+ an = opt.def;
+ }
adapter->hw.autoneg_advertised = an;
}
switch (speed + dplx) {
case 0:
adapter->hw.autoneg = adapter->fc_autoneg = 1;
- if((num_Speed > bd) && (speed != 0 || dplx != 0))
+ if ((num_Speed > bd) && (speed != 0 || dplx != 0))
DPRINTK(PROBE, INFO,
"Speed and duplex autonegotiation enabled\n");
break;
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index f5a4dd7d8564..e5c5cd2a2712 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -140,13 +140,6 @@ static int __init do_e2100_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: e21_close() handles free_irq */
- iounmap(ei_status.mem);
- release_region(dev->base_addr, E21_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init e2100_probe(int unit)
{
@@ -463,6 +456,13 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: e21_close() handles free_irq */
+ iounmap(ei_status.mem);
+ release_region(dev->base_addr, E21_IO_EXTENT);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 50f8e23bb9e5..6b0ab1eac3fb 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -155,13 +155,6 @@ static int __init do_es_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, ES_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init es_probe(int unit)
{
@@ -456,6 +449,13 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, ES_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index c39344adecce..3682ec61e8a8 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -101,6 +101,7 @@
* 0.46: 20 Oct 2005: Add irq optimization modes.
* 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
* 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single
+ * 0.49: 10 Dec 2005: Fix tso for large buffers.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -112,7 +113,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.48"
+#define FORCEDETH_VERSION "0.49"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -349,6 +350,8 @@ typedef union _ring_type {
#define NV_TX2_VALID (1<<31)
#define NV_TX2_TSO (1<<28)
#define NV_TX2_TSO_SHIFT 14
+#define NV_TX2_TSO_MAX_SHIFT 14
+#define NV_TX2_TSO_MAX_SIZE (1<<NV_TX2_TSO_MAX_SHIFT)
#define NV_TX2_CHECKSUM_L3 (1<<27)
#define NV_TX2_CHECKSUM_L4 (1<<26)
@@ -408,15 +411,15 @@ typedef union _ring_type {
#define NV_WATCHDOG_TIMEO (5*HZ)
#define RX_RING 128
-#define TX_RING 64
+#define TX_RING 256
/*
* If your nic mysteriously hangs then try to reduce the limits
* to 1/0: It might be required to set NV_TX_LASTPACKET in the
* last valid ring entry. But this would be impossible to
* implement - probably a disassembly error.
*/
-#define TX_LIMIT_STOP 63
-#define TX_LIMIT_START 62
+#define TX_LIMIT_STOP 255
+#define TX_LIMIT_START 254
/* rx/tx mac addr + type + vlan + align + slack*/
#define NV_RX_HEADERS (64)
@@ -535,6 +538,7 @@ struct fe_priv {
unsigned int next_tx, nic_tx;
struct sk_buff *tx_skbuff[TX_RING];
dma_addr_t tx_dma[TX_RING];
+ unsigned int tx_dma_len[TX_RING];
u32 tx_flags;
};
@@ -935,6 +939,7 @@ static void nv_init_tx(struct net_device *dev)
else
np->tx_ring.ex[i].FlagLen = 0;
np->tx_skbuff[i] = NULL;
+ np->tx_dma[i] = 0;
}
}
@@ -945,30 +950,27 @@ static int nv_init_ring(struct net_device *dev)
return nv_alloc_rx(dev);
}
-static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
+static int 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;
- }
+
+ dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d\n",
+ dev->name, skbnr);
+
+ if (np->tx_dma[skbnr]) {
+ pci_unmap_page(np->pci_dev, np->tx_dma[skbnr],
+ np->tx_dma_len[skbnr],
+ PCI_DMA_TODEVICE);
+ np->tx_dma[skbnr] = 0;
+ }
+
+ if (np->tx_skbuff[skbnr]) {
+ dev_kfree_skb_irq(np->tx_skbuff[skbnr]);
+ np->tx_skbuff[skbnr] = NULL;
+ return 1;
+ } else {
+ return 0;
}
- 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)
@@ -981,10 +983,8 @@ static void nv_drain_tx(struct net_device *dev)
np->tx_ring.orig[i].FlagLen = 0;
else
np->tx_ring.ex[i].FlagLen = 0;
- if (np->tx_skbuff[i]) {
- nv_release_txskb(dev, i);
+ if (nv_release_txskb(dev, i))
np->stats.tx_dropped++;
- }
}
}
@@ -1021,68 +1021,105 @@ 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 = netdev_priv(dev);
+ u32 tx_flags = 0;
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 nr = (np->next_tx - 1) % TX_RING;
+ unsigned int start_nr = np->next_tx % TX_RING;
unsigned int i;
+ u32 offset = 0;
+ u32 bcnt;
+ u32 size = skb->len-skb->data_len;
+ u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+
+ /* add fragments to entries count */
+ for (i = 0; i < fragments; i++) {
+ entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) +
+ ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+ }
spin_lock_irq(&np->lock);
- if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
+ if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) {
spin_unlock_irq(&np->lock);
netif_stop_queue(dev);
return NETDEV_TX_BUSY;
}
- np->tx_skbuff[nr] = skb;
-
- 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);
+ /* setup the header buffer */
+ do {
+ bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
+ nr = (nr + 1) % TX_RING;
+
+ np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
+ PCI_DMA_TODEVICE);
+ np->tx_dma_len[nr] = bcnt;
+
+ 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((bcnt-1) | tx_flags);
+ } 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((bcnt-1) | tx_flags);
+ }
+ tx_flags = np->tx_flags;
+ offset += bcnt;
+ size -= bcnt;
+ } while(size);
+
+ /* setup the fragments */
+ for (i = 0; i < fragments; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ u32 size = frag->size;
+ offset = 0;
+
+ do {
+ bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
+ nr = (nr + 1) % TX_RING;
+
+ np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
+ PCI_DMA_TODEVICE);
+ np->tx_dma_len[nr] = bcnt;
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);
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
} 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);
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
}
-
- nr = (nr - 1) % TX_RING;
+ offset += bcnt;
+ size -= bcnt;
+ } while (size);
+ }
- if (np->desc_ver == DESC_VER_1)
- tx_flags_extra &= ~NV_TX_LASTPACKET;
- else
- tx_flags_extra &= ~NV_TX2_LASTPACKET;
- }
+ /* set last fragment flag */
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->tx_ring.orig[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
+ } else {
+ np->tx_ring.ex[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
}
+ np->tx_skbuff[nr] = skb;
+
#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);
+ 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);
+ 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);
-
+ /* set tx flags */
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);
+ np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(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);
+ np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(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);
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
+ dev->name, np->next_tx, entries, tx_flags_extra);
{
int j;
for (j=0; j<64; j++) {
@@ -1093,7 +1130,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
dprintk("\n");
}
- np->next_tx += 1 + fragments;
+ np->next_tx += entries;
dev->trans_start = jiffies;
spin_unlock_irq(&np->lock);
@@ -1140,7 +1177,6 @@ static void nv_tx_done(struct net_device *dev)
np->stats.tx_packets++;
np->stats.tx_bytes += skb->len;
}
- nv_release_txskb(dev, i);
}
} else {
if (Flags & NV_TX2_LASTPACKET) {
@@ -1156,9 +1192,9 @@ static void nv_tx_done(struct net_device *dev)
np->stats.tx_packets++;
np->stats.tx_bytes += skb->len;
}
- nv_release_txskb(dev, i);
}
}
+ nv_release_txskb(dev, i);
np->nic_tx++;
}
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
@@ -2456,7 +2492,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
#ifdef NETIF_F_TSO
- /* disabled dev->features |= NETIF_F_TSO; */
+ dev->features |= NETIF_F_TSO;
#endif
}
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 146f9513aea5..0c18dbd67d3b 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -84,6 +84,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/in.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -398,12 +399,15 @@ static int init_phy(struct net_device *dev)
priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
SUPPORTED_1000baseT_Full : 0;
struct phy_device *phydev;
+ char phy_id[BUS_ID_SIZE];
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
+
+ phydev = phy_connect(dev, phy_id, &adjust_link, 0);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 94a91da84fbb..cb9d66ac3ab9 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -718,14 +718,14 @@ struct gfar_private {
uint32_t msg_enable;
};
-extern inline u32 gfar_read(volatile unsigned *addr)
+static inline u32 gfar_read(volatile unsigned *addr)
{
u32 val;
val = in_be32(addr);
return val;
}
-extern inline void gfar_write(volatile unsigned *addr, u32 val)
+static inline void gfar_write(volatile unsigned *addr, u32 val)
{
out_be32(addr, val);
}
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 04a462c2a5b7..74e52fcbf806 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -128,6 +128,7 @@ int gfar_mdio_probe(struct device *dev)
struct gianfar_mdio_data *pdata;
struct gfar_mii *regs;
struct mii_bus *new_bus;
+ struct resource *r;
int err = 0;
if (NULL == dev)
@@ -151,8 +152,10 @@ int gfar_mdio_probe(struct device *dev)
return -ENODEV;
}
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
/* Set the PHY base address */
- regs = (struct gfar_mii *) ioremap(pdata->paddr,
+ regs = (struct gfar_mii *) ioremap(r->start,
sizeof (struct gfar_mii));
if (NULL == regs) {
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 10d34cb19192..51ef181b1368 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -7,7 +7,7 @@
* Based on 8260_io/fcc_enet.c
*
* Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ * Maintainer: Kumar Gala (galak@kernel.crashing.org)
*
* Copyright (c) 2002-2005 Freescale Semiconductor, Inc.
*
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 90999867a32c..102c1f0b90da 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -456,11 +456,6 @@ out:
/* ----------------------------------------------------------------------- */
-static int sixpack_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
@@ -671,6 +666,7 @@ static int sixpack_open(struct tty_struct *tty)
/* Done. We have linked the TTY line to a channel. */
tty->disc_data = sp;
+ tty->receive_room = 65536;
/* Now we're ready to register. */
if (register_netdev(dev))
@@ -802,7 +798,6 @@ static struct tty_ldisc sp_ldisc = {
.close = sixpack_close,
.ioctl = sixpack_ioctl,
.receive_buf = sixpack_receive_buf,
- .receive_room = sixpack_receive_room,
.write_wakeup = sixpack_write_wakeup,
};
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 3e9accf137e7..dc5e9d59deed 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -515,6 +515,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
}
}
+ spin_unlock_bh(&ax->buflock);
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
@@ -752,6 +753,7 @@ static int mkiss_open(struct tty_struct *tty)
ax->tty = tty;
tty->disc_data = ax;
+ tty->receive_room = 65535;
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
@@ -939,11 +941,6 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
tty->driver->unthrottle(tty);
}
-static int mkiss_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
@@ -982,7 +979,6 @@ static struct tty_ldisc ax_ldisc = {
.close = mkiss_close,
.ioctl = mkiss_ioctl,
.receive_buf = mkiss_receive_buf,
- .receive_room = mkiss_receive_room,
.write_wakeup = mkiss_write_wakeup
};
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 0abf5dd08b4c..74e167e7dea7 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -138,12 +138,6 @@ static int __init do_hpp_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: hpp_close() handles free_irq */
- release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init hp_plus_probe(int unit)
{
@@ -473,6 +467,12 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: hpp_close() handles free_irq */
+ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 59cf841b14ab..cf9fb3698a6b 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -102,12 +102,6 @@ static int __init do_hp_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init hp_probe(int unit)
{
@@ -444,6 +438,12 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index e92c17f6931c..55c7ed608391 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -276,7 +276,7 @@ static void hp100_RegisterDump(struct net_device *dev);
* Convert an address in a kernel buffer to a bus/phys/dma address.
* This work *only* for memory fragments part of lp->page_vaddr,
* because it was properly DMA allocated via pci_alloc_consistent(),
- * so we just need to "retreive" the original mapping to bus/phys/dma
+ * so we just need to "retrieve" the original mapping to bus/phys/dma
* address - Jean II */
static inline dma_addr_t virt_to_whatever(struct net_device *dev, u32 * ptr)
{
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c
index 08703d6f934c..d8410634bcaf 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/hplance.c
@@ -150,7 +150,7 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
lp->lance.name = (char*)d->name; /* discards const, shut up gcc */
lp->lance.base = va;
lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
- lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */
+ lp->lance.lance_init_block = NULL; /* LANCE addr of same RAM */
lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */
lp->lance.irq = d->ipl;
lp->lance.writerap = hplance_writerap;
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 644edbff4f94..c2dae6092c4c 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -110,6 +110,7 @@ struct emac_regs {
#define EMAC_MR1_TFS_2K 0x00080000
#define EMAC_MR1_TR0_MULT 0x00008000
#define EMAC_MR1_JPSM 0x00000000
+#define EMAC_MR1_MWSW_001 0x00000000
#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT)
#else
#define EMAC_MR1_RFS_4K 0x00180000
@@ -130,7 +131,7 @@ struct emac_regs {
(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))
+ EMAC_MR1_OBCI(opb))
#endif
/* EMACx_TMR0 */
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 1da8a66f91e1..591c5864ffb1 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -408,7 +408,7 @@ static int emac_configure(struct ocp_enet_private *dev)
/* 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;
+ r |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001;
dev->stop_timeout = STOP_TIMEOUT_10;
switch (dev->phy.speed) {
case SPEED_1000:
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
new file mode 100644
index 000000000000..1b699259b4ec
--- /dev/null
+++ b/drivers/net/ifb.c
@@ -0,0 +1,294 @@
+/* drivers/net/ifb.c:
+
+ The purpose of this driver is to provide a device that allows
+ for sharing of resources:
+
+ 1) qdiscs/policies that are per device as opposed to system wide.
+ ifb allows for a device which can be redirected to thus providing
+ an impression of sharing.
+
+ 2) Allows for queueing incoming traffic for shaping instead of
+ dropping.
+
+ The original concept is based on what is known as the IMQ
+ driver initially written by Martin Devera, later rewritten
+ by Patrick McHardy and then maintained by Andre Correa.
+
+ You need the tc action mirror or redirect to feed this device
+ packets.
+
+ This program is free software; you can redistribute 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.
+
+ Authors: Jamal Hadi Salim (2005)
+
+*/
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <net/pkt_sched.h>
+
+#define TX_TIMEOUT (2*HZ)
+
+#define TX_Q_LIMIT 32
+struct ifb_private {
+ struct net_device_stats stats;
+ struct tasklet_struct ifb_tasklet;
+ int tasklet_pending;
+ /* mostly debug stats leave in for now */
+ unsigned long st_task_enter; /* tasklet entered */
+ unsigned long st_txq_refl_try; /* transmit queue refill attempt */
+ unsigned long st_rxq_enter; /* receive queue entered */
+ unsigned long st_rx2tx_tran; /* receive to trasmit transfers */
+ unsigned long st_rxq_notenter; /*receiveQ not entered, resched */
+ unsigned long st_rx_frm_egr; /* received from egress path */
+ unsigned long st_rx_frm_ing; /* received from ingress path */
+ unsigned long st_rxq_check;
+ unsigned long st_rxq_rsch;
+ struct sk_buff_head rq;
+ struct sk_buff_head tq;
+};
+
+static int numifbs = 1;
+
+static void ri_tasklet(unsigned long dev);
+static int ifb_xmit(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *ifb_get_stats(struct net_device *dev);
+static int ifb_open(struct net_device *dev);
+static int ifb_close(struct net_device *dev);
+
+static void ri_tasklet(unsigned long dev)
+{
+
+ struct net_device *_dev = (struct net_device *)dev;
+ struct ifb_private *dp = netdev_priv(_dev);
+ struct net_device_stats *stats = &dp->stats;
+ struct sk_buff *skb;
+
+ dp->st_task_enter++;
+ if ((skb = skb_peek(&dp->tq)) == NULL) {
+ dp->st_txq_refl_try++;
+ if (spin_trylock(&_dev->xmit_lock)) {
+ dp->st_rxq_enter++;
+ while ((skb = skb_dequeue(&dp->rq)) != NULL) {
+ skb_queue_tail(&dp->tq, skb);
+ dp->st_rx2tx_tran++;
+ }
+ spin_unlock(&_dev->xmit_lock);
+ } else {
+ /* reschedule */
+ dp->st_rxq_notenter++;
+ goto resched;
+ }
+ }
+
+ while ((skb = skb_dequeue(&dp->tq)) != NULL) {
+ u32 from = G_TC_FROM(skb->tc_verd);
+
+ skb->tc_verd = 0;
+ skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
+ stats->tx_packets++;
+ stats->tx_bytes +=skb->len;
+ if (from & AT_EGRESS) {
+ dp->st_rx_frm_egr++;
+ dev_queue_xmit(skb);
+ } else if (from & AT_INGRESS) {
+
+ dp->st_rx_frm_ing++;
+ netif_rx(skb);
+ } else {
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+ }
+ }
+
+ if (spin_trylock(&_dev->xmit_lock)) {
+ dp->st_rxq_check++;
+ if ((skb = skb_peek(&dp->rq)) == NULL) {
+ dp->tasklet_pending = 0;
+ if (netif_queue_stopped(_dev))
+ netif_wake_queue(_dev);
+ } else {
+ dp->st_rxq_rsch++;
+ spin_unlock(&_dev->xmit_lock);
+ goto resched;
+ }
+ spin_unlock(&_dev->xmit_lock);
+ } else {
+resched:
+ dp->tasklet_pending = 1;
+ tasklet_schedule(&dp->ifb_tasklet);
+ }
+
+}
+
+static void __init ifb_setup(struct net_device *dev)
+{
+ /* Initialize the device structure. */
+ dev->get_stats = ifb_get_stats;
+ dev->hard_start_xmit = ifb_xmit;
+ dev->open = &ifb_open;
+ dev->stop = &ifb_close;
+
+ /* Fill in device structure with ethernet-generic values. */
+ ether_setup(dev);
+ dev->tx_queue_len = TX_Q_LIMIT;
+ dev->change_mtu = NULL;
+ dev->flags |= IFF_NOARP;
+ dev->flags &= ~IFF_MULTICAST;
+ SET_MODULE_OWNER(dev);
+ random_ether_addr(dev->dev_addr);
+}
+
+static int ifb_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+ struct net_device_stats *stats = &dp->stats;
+ int ret = 0;
+ u32 from = G_TC_FROM(skb->tc_verd);
+
+ stats->tx_packets++;
+ stats->tx_bytes+=skb->len;
+
+ if (!from || !skb->input_dev) {
+dropped:
+ dev_kfree_skb(skb);
+ stats->rx_dropped++;
+ return ret;
+ } else {
+ /*
+ * note we could be going
+ * ingress -> egress or
+ * egress -> ingress
+ */
+ skb->dev = skb->input_dev;
+ skb->input_dev = dev;
+ if (from & AT_INGRESS) {
+ skb_pull(skb, skb->dev->hard_header_len);
+ } else {
+ if (!(from & AT_EGRESS)) {
+ goto dropped;
+ }
+ }
+ }
+
+ if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) {
+ netif_stop_queue(dev);
+ }
+
+ dev->trans_start = jiffies;
+ skb_queue_tail(&dp->rq, skb);
+ if (!dp->tasklet_pending) {
+ dp->tasklet_pending = 1;
+ tasklet_schedule(&dp->ifb_tasklet);
+ }
+
+ return ret;
+}
+
+static struct net_device_stats *ifb_get_stats(struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+ struct net_device_stats *stats = &dp->stats;
+
+ pr_debug("tasklets stats %ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld \n",
+ dp->st_task_enter, dp->st_txq_refl_try, dp->st_rxq_enter,
+ dp->st_rx2tx_tran dp->st_rxq_notenter, dp->st_rx_frm_egr,
+ dp->st_rx_frm_ing, dp->st_rxq_check, dp->st_rxq_rsch );
+
+ return stats;
+}
+
+static struct net_device **ifbs;
+
+/* Number of ifb devices to be set up by this module. */
+module_param(numifbs, int, 0);
+MODULE_PARM_DESC(numifbs, "Number of ifb devices");
+
+static int ifb_close(struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+
+ tasklet_kill(&dp->ifb_tasklet);
+ netif_stop_queue(dev);
+ skb_queue_purge(&dp->rq);
+ skb_queue_purge(&dp->tq);
+ return 0;
+}
+
+static int ifb_open(struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+
+ tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev);
+ skb_queue_head_init(&dp->rq);
+ skb_queue_head_init(&dp->tq);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int __init ifb_init_one(int index)
+{
+ struct net_device *dev_ifb;
+ int err;
+
+ dev_ifb = alloc_netdev(sizeof(struct ifb_private),
+ "ifb%d", ifb_setup);
+
+ if (!dev_ifb)
+ return -ENOMEM;
+
+ if ((err = register_netdev(dev_ifb))) {
+ free_netdev(dev_ifb);
+ dev_ifb = NULL;
+ } else {
+ ifbs[index] = dev_ifb;
+ }
+
+ return err;
+}
+
+static void ifb_free_one(int index)
+{
+ unregister_netdev(ifbs[index]);
+ free_netdev(ifbs[index]);
+}
+
+static int __init ifb_init_module(void)
+{
+ int i, err = 0;
+ ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
+ if (!ifbs)
+ return -ENOMEM;
+ for (i = 0; i < numifbs && !err; i++)
+ err = ifb_init_one(i);
+ if (err) {
+ while (--i >= 0)
+ ifb_free_one(i);
+ }
+
+ return err;
+}
+
+static void __exit ifb_cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < numifbs; i++)
+ ifb_free_one(i);
+ kfree(ifbs);
+}
+
+module_init(ifb_init_module);
+module_exit(ifb_cleanup_module);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamal Hadi Salim");
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index d54156f11e61..7a081346f079 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -1,4 +1,3 @@
-
menu "Infrared-port device drivers"
depends on IRDA!=n
@@ -156,7 +155,7 @@ comment "Old Serial dongle support"
config DONGLE_OLD
bool "Old Serial dongle support"
- depends on (IRTTY_OLD || IRPORT_SIR) && BROKEN_ON_SMP
+ depends on IRPORT_SIR && BROKEN_ON_SMP
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index e7a8b7f7f5dd..72cbfdc9cfcc 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -45,4 +45,4 @@ obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
# The SIR helper module
-sir-dev-objs := sir_core.o sir_dev.o sir_dongle.o sir_kthread.o
+sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 3d016a498e1d..6070195b87bd 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -285,19 +285,6 @@ static void irport_start(struct irport_cb *self)
}
/*
- * Function irport_probe (void)
- *
- * Start IO port
- *
- */
-int irport_probe(int iobase)
-{
- IRDA_DEBUG(4, "%s(), iobase=%#x\n", __FUNCTION__, iobase);
-
- return 0;
-}
-
-/*
* Function irport_get_fcr (speed)
*
* Compute value of fcr
@@ -382,7 +369,7 @@ static void irport_change_speed(void *priv, __u32 speed)
* we cannot use schedule_timeout() when we are in interrupt context
*
*/
-int __irport_change_speed(struct irda_task *task)
+static int __irport_change_speed(struct irda_task *task)
{
struct irport_cb *self;
__u32 speed = (__u32) task->param;
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index b8d112348ba4..101750bf210f 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -289,22 +289,6 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
/*
- * Function irtty_receive_room (tty)
- *
- * Used by the TTY to find out how much data we can receive at a time
- *
-*/
-static int irtty_receive_room(struct tty_struct *tty)
-{
- struct sirtty_cb *priv = tty->disc_data;
-
- IRDA_ASSERT(priv != NULL, return 0;);
- IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
-
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
-/*
* Function irtty_write_wakeup (tty)
*
* Called by the driver when there's room for more data. If we have
@@ -534,6 +518,7 @@ static int irtty_open(struct tty_struct *tty)
dev->priv = priv;
tty->disc_data = priv;
+ tty->receive_room = 65536;
up(&irtty_sem);
@@ -605,7 +590,6 @@ static struct tty_ldisc irda_ldisc = {
.ioctl = irtty_ioctl,
.poll = NULL,
.receive_buf = irtty_receive_buf,
- .receive_room = irtty_receive_room,
.write_wakeup = irtty_write_wakeup,
.owner = THIS_MODULE,
};
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index f0b8bc3637e5..f69fb4cec76f 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -133,8 +133,6 @@ extern int sirdev_put_dongle(struct sir_dev *self);
extern void sirdev_enable_rx(struct sir_dev *dev);
extern int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param);
-extern int __init irda_thread_create(void);
-extern void __exit irda_thread_join(void);
/* inline helpers */
diff --git a/drivers/net/irda/sir_core.c b/drivers/net/irda/sir_core.c
deleted file mode 100644
index a49f910c835b..000000000000
--- a/drivers/net/irda/sir_core.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*********************************************************************
- *
- * sir_core.c: module core for irda-sir abstraction layer
- *
- * Copyright (c) 2002 Martin Diehl
- *
- * This program is free software; you can redistribute 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/init.h>
-
-#include <net/irda/irda.h>
-
-#include "sir-dev.h"
-
-/***************************************************************************/
-
-MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
-MODULE_DESCRIPTION("IrDA SIR core");
-MODULE_LICENSE("GPL");
-
-/***************************************************************************/
-
-EXPORT_SYMBOL(irda_register_dongle);
-EXPORT_SYMBOL(irda_unregister_dongle);
-
-EXPORT_SYMBOL(sirdev_get_instance);
-EXPORT_SYMBOL(sirdev_put_instance);
-
-EXPORT_SYMBOL(sirdev_set_dongle);
-EXPORT_SYMBOL(sirdev_write_complete);
-EXPORT_SYMBOL(sirdev_receive);
-
-EXPORT_SYMBOL(sirdev_raw_write);
-EXPORT_SYMBOL(sirdev_raw_read);
-EXPORT_SYMBOL(sirdev_set_dtr_rts);
-
-static int __init sir_core_init(void)
-{
- return irda_thread_create();
-}
-
-static void __exit sir_core_exit(void)
-{
- irda_thread_join();
-}
-
-module_init(sir_core_init);
-module_exit(sir_core_exit);
-
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index df22b8b532e7..ea7c9464d46a 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -60,6 +60,7 @@ int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type)
up(&dev->fsm.sem);
return err;
}
+EXPORT_SYMBOL(sirdev_set_dongle);
/* used by dongle drivers for dongle programming */
@@ -94,6 +95,7 @@ int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len)
spin_unlock_irqrestore(&dev->tx_lock, flags);
return ret;
}
+EXPORT_SYMBOL(sirdev_raw_write);
/* seems some dongle drivers may need this */
@@ -116,6 +118,7 @@ int sirdev_raw_read(struct sir_dev *dev, char *buf, int len)
return count;
}
+EXPORT_SYMBOL(sirdev_raw_read);
int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
{
@@ -124,7 +127,8 @@ int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
ret = dev->drv->set_dtr_rts(dev, dtr, rts);
return ret;
}
-
+EXPORT_SYMBOL(sirdev_set_dtr_rts);
+
/**********************************************************************/
/* called from client driver - likely with bh-context - to indicate
@@ -227,6 +231,7 @@ void sirdev_write_complete(struct sir_dev *dev)
done:
spin_unlock_irqrestore(&dev->tx_lock, flags);
}
+EXPORT_SYMBOL(sirdev_write_complete);
/* called from client driver - likely with bh-context - to give us
* some more received bytes. We put them into the rx-buffer,
@@ -279,6 +284,7 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
return 0;
}
+EXPORT_SYMBOL(sirdev_receive);
/**********************************************************************/
@@ -641,6 +647,7 @@ out_freenetdev:
out:
return NULL;
}
+EXPORT_SYMBOL(sirdev_get_instance);
int sirdev_put_instance(struct sir_dev *dev)
{
@@ -673,4 +680,5 @@ int sirdev_put_instance(struct sir_dev *dev)
return 0;
}
+EXPORT_SYMBOL(sirdev_put_instance);
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c
index c5b76746e72b..8d225921ae7b 100644
--- a/drivers/net/irda/sir_dongle.c
+++ b/drivers/net/irda/sir_dongle.c
@@ -50,6 +50,7 @@ int irda_register_dongle(struct dongle_driver *new)
up(&dongle_list_lock);
return 0;
}
+EXPORT_SYMBOL(irda_register_dongle);
int irda_unregister_dongle(struct dongle_driver *drv)
{
@@ -58,6 +59,7 @@ int irda_unregister_dongle(struct dongle_driver *drv)
up(&dongle_list_lock);
return 0;
}
+EXPORT_SYMBOL(irda_unregister_dongle);
int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
{
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index c65054364bca..e3904d6bfecd 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -466,7 +466,7 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
return 0;
}
-int __init irda_thread_create(void)
+static int __init irda_thread_create(void)
{
struct completion startup;
int pid;
@@ -488,7 +488,7 @@ int __init irda_thread_create(void)
return 0;
}
-void __exit irda_thread_join(void)
+static void __exit irda_thread_join(void)
{
if (irda_rq_queue.thread) {
flush_irda_queue();
@@ -499,3 +499,10 @@ void __exit irda_thread_join(void)
}
}
+module_init(irda_thread_create);
+module_exit(irda_thread_join);
+
+MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
+MODULE_DESCRIPTION("IrDA SIR core");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 741aecc655df..a82a4ba8de4f 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -577,8 +577,8 @@ struct ring_descr_hw {
struct {
u8 addr_res[3];
volatile u8 status; /* descriptor status */
- } rd_s __attribute__((packed));
- } rd_u __attribute((packed));
+ } __attribute__((packed)) rd_s;
+ } __attribute((packed)) rd_u;
} __attribute__ ((packed));
#define rd_addr rd_u.addr
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 77eadf84cb2c..f0f04be989d6 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -590,9 +590,9 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
{
struct veth_lpevent *veth_event = (struct veth_lpevent *)event;
- if (event->xFlags.xFunction == HvLpEvent_Function_Ack)
+ if (hvlpevent_is_ack(event))
veth_handle_ack(veth_event);
- else if (event->xFlags.xFunction == HvLpEvent_Function_Int)
+ else
veth_handle_int(veth_event);
}
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 1d75ca0bb939..d1d714faa6ce 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -309,17 +309,6 @@ static void lance_tx_timeout (struct net_device *dev);
-static void cleanup_card(struct net_device *dev)
-{
- struct lance_private *lp = dev->priv;
- if (dev->dma != 4)
- free_dma(dev->dma);
- release_region(dev->base_addr, LANCE_TOTAL_SIZE);
- kfree(lp->tx_bounce_buffs);
- kfree((void*)lp->rx_buffs);
- kfree(lp);
-}
-
#ifdef MODULE
#define MAX_CARDS 8 /* Max number of interfaces (cards) per module */
@@ -367,6 +356,17 @@ int init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ struct lance_private *lp = dev->priv;
+ if (dev->dma != 4)
+ free_dma(dev->dma);
+ release_region(dev->base_addr, LANCE_TOTAL_SIZE);
+ kfree(lp->tx_bounce_buffs);
+ kfree((void*)lp->rx_buffs);
+ kfree(lp);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 309d254842cf..646e89fc3562 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -145,13 +145,6 @@ static int __init do_lne390_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, LNE390_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init lne390_probe(int unit)
{
@@ -440,6 +433,13 @@ int init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, LNE390_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index d8c99f038fa0..06cb460361a8 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -559,55 +559,52 @@ static void mac8390_no_reset(struct net_device *dev)
/* directly from daynaport.c by Alan Cox */
static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
{
- volatile unsigned short *ptr;
- unsigned short *target=to;
+ volatile unsigned char *ptr;
+ unsigned char *target=to;
from<<=1; /* word, skip overhead */
- ptr=(unsigned short *)(dev->mem_start+from);
+ ptr=(unsigned char *)(dev->mem_start+from);
/* Leading byte? */
if (from&2) {
- *((char *)target)++ = *(((char *)ptr++)-1);
+ *target++ = ptr[-1];
+ ptr += 2;
count--;
}
while(count>=2)
{
- *target++=*ptr++; /* Copy and */
- ptr++; /* skip cruft */
+ *(unsigned short *)target = *(unsigned short volatile *)ptr;
+ ptr += 4; /* skip cruft */
+ target += 2;
count-=2;
}
/* Trailing byte? */
if(count)
- {
- /* Big endian */
- unsigned short v=*ptr;
- *((char *)target)=v>>8;
- }
+ *target = *ptr;
}
static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
{
volatile unsigned short *ptr;
- const unsigned short *src=from;
+ const unsigned char *src=from;
to<<=1; /* word, skip overhead */
ptr=(unsigned short *)(dev->mem_start+to);
/* Leading byte? */
if (to&2) { /* avoid a byte write (stomps on other data) */
- ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
+ ptr[-1] = (ptr[-1]&0xFF00)|*src++;
ptr++;
count--;
}
while(count>=2)
{
- *ptr++=*src++; /* Copy and */
+ *ptr++=*(unsigned short *)src; /* Copy and */
ptr++; /* skip cruft */
+ src += 2;
count-=2;
}
/* Trailing byte? */
if(count)
{
- /* Big endian */
- unsigned short v=*src;
/* card doesn't like byte writes */
- *ptr=(*ptr&0x00FF)|(v&0xFF00);
+ *ptr=(*ptr&0x00FF)|(*src << 8);
}
}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 3cb9b3fe0cf1..40ae36b20c9d 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -6,7 +6,7 @@
* Copyright (C) 2002 rabeeh@galileo.co.il
*
* Copyright (C) 2003 PMC-Sierra, Inc.,
- * written by Manish Lachwani (lachwani@pmc-sierra.com)
+ * written by Manish Lachwani
*
* Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
*
@@ -35,6 +35,8 @@
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -55,13 +57,15 @@
/* Constants */
#define VLAN_HLEN 4
#define FCS_LEN 4
-#define WRAP NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
+#define DMA_ALIGN 8 /* hw requires 8-byte alignment */
+#define HW_IP_ALIGN 2 /* hw aligns IP header */
+#define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
#define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7)
-#define INT_CAUSE_UNMASK_ALL 0x0007ffff
-#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff
-#define INT_CAUSE_MASK_ALL 0x00000000
-#define INT_CAUSE_MASK_ALL_EXT 0x00000000
+#define INT_UNMASK_ALL 0x0007ffff
+#define INT_UNMASK_ALL_EXT 0x0011ffff
+#define INT_MASK_ALL 0x00000000
+#define INT_MASK_ALL_EXT 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
@@ -78,8 +82,9 @@
static int eth_port_link_is_up(unsigned int eth_port_num);
static void eth_port_uc_addr_get(struct net_device *dev,
unsigned char *MacAddr);
-static int mv643xx_eth_real_open(struct net_device *);
-static int mv643xx_eth_real_stop(struct net_device *);
+static void eth_port_set_multicast_list(struct net_device *);
+static int mv643xx_eth_open(struct net_device *);
+static int mv643xx_eth_stop(struct net_device *);
static int mv643xx_eth_change_mtu(struct net_device *, int);
static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *);
static void eth_port_init_mac_tables(unsigned int eth_port_num);
@@ -124,15 +129,8 @@ static inline void mv_write(int offset, u32 data)
*/
static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
{
- struct mv643xx_private *mp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
-
- if ((new_mtu > 9500) || (new_mtu < 64)) {
- spin_unlock_irqrestore(&mp->lock, flags);
+ if ((new_mtu > 9500) || (new_mtu < 64))
return -EINVAL;
- }
dev->mtu = new_mtu;
/*
@@ -142,17 +140,13 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
* to memory is full, which might fail the open function.
*/
if (netif_running(dev)) {
- if (mv643xx_eth_real_stop(dev))
- printk(KERN_ERR
- "%s: Fatal error on stopping device\n",
- dev->name);
- if (mv643xx_eth_real_open(dev))
+ mv643xx_eth_stop(dev);
+ if (mv643xx_eth_open(dev))
printk(KERN_ERR
"%s: Fatal error on opening device\n",
dev->name);
}
- spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
@@ -170,15 +164,19 @@ static void mv643xx_eth_rx_task(void *data)
struct mv643xx_private *mp = netdev_priv(dev);
struct pkt_info pkt_info;
struct sk_buff *skb;
+ int unaligned;
if (test_and_set_bit(0, &mp->rx_task_busy))
panic("%s: Error in test_set_bit / clear_bit", dev->name);
while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
- skb = dev_alloc_skb(RX_SKB_SIZE);
+ skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN);
if (!skb)
break;
mp->rx_ring_skbs++;
+ unaligned = (u32)skb->data & (DMA_ALIGN - 1);
+ if (unaligned)
+ skb_reserve(skb, DMA_ALIGN - unaligned);
pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
pkt_info.byte_cnt = RX_SKB_SIZE;
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
@@ -189,7 +187,7 @@ static void mv643xx_eth_rx_task(void *data)
"%s: Error allocating RX Ring\n", dev->name);
break;
}
- skb_reserve(skb, 2);
+ skb_reserve(skb, HW_IP_ALIGN);
}
clear_bit(0, &mp->rx_task_busy);
/*
@@ -207,7 +205,7 @@ static void mv643xx_eth_rx_task(void *data)
else {
/* Return interrupts */
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
- INT_CAUSE_UNMASK_ALL);
+ INT_UNMASK_ALL);
}
#endif
}
@@ -267,6 +265,8 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
+
+ eth_port_set_multicast_list(dev);
}
/*
@@ -342,8 +342,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
if (!(eth_int_cause_ext & (BIT0 | BIT8)))
return released;
- spin_lock(&mp->lock);
-
/* Check only queue 0 */
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
if (pkt_info.cmd_sts & BIT0) {
@@ -351,31 +349,21 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
stats->tx_errors++;
}
- /*
- * If return_info is different than 0, release the skb.
- * The case where return_info is not 0 is only in case
- * when transmitted a scatter/gather packet, where only
- * last skb releases the whole chain.
- */
- if (pkt_info.return_info) {
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
+ if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+ dma_unmap_single(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ if (pkt_info.return_info) {
dev_kfree_skb_irq(pkt_info.return_info);
released = 0;
- } else
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, DMA_TO_DEVICE);
+ }
}
- spin_unlock(&mp->lock);
-
return released;
}
@@ -482,12 +470,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
/* Read interrupt cause registers */
eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL;
+ INT_UNMASK_ALL;
if (eth_int_cause & BIT1)
eth_int_cause_ext = mv_read(
MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL_EXT;
+ INT_UNMASK_ALL_EXT;
#ifdef MV643XX_NAPI
if (!(eth_int_cause & 0x0007fffd)) {
@@ -512,9 +500,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
} else {
if (netif_rx_schedule_prep(dev)) {
/* Mask all the interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG
- (port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
__netif_rx_schedule(dev);
}
#else
@@ -527,9 +516,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
* with skb's.
*/
#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
- /* Unmask all interrupts on ethernet port */
+ /* Mask all interrupts on ethernet port */
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_MASK_ALL);
+ INT_MASK_ALL);
+ /* wait for previous write to take effect */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
queue_task(&mp->rx_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -636,56 +628,6 @@ static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
}
/*
- * mv643xx_eth_open
- *
- * This function is called when openning the network device. The function
- * should initialize all the hardware, initialize cyclic Rx/Tx
- * descriptors chain and buffers and allocate an IRQ to the network
- * device.
- *
- * Input : a pointer to the network device structure
- *
- * Output : zero of success , nonzero if fails.
- */
-
-static int mv643xx_eth_open(struct net_device *dev)
-{
- struct mv643xx_private *mp = netdev_priv(dev);
- unsigned int port_num = mp->port_num;
- int err;
-
- spin_lock_irq(&mp->lock);
-
- err = request_irq(dev->irq, mv643xx_eth_int_handler,
- SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-
- if (err) {
- printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
- port_num);
- err = -EAGAIN;
- goto out;
- }
-
- if (mv643xx_eth_real_open(dev)) {
- printk("%s: Error opening interface\n", dev->name);
- err = -EBUSY;
- goto out_free;
- }
-
- spin_unlock_irq(&mp->lock);
-
- return 0;
-
-out_free:
- free_irq(dev->irq, dev);
-
-out:
- spin_unlock_irq(&mp->lock);
-
- return err;
-}
-
-/*
* ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
*
* DESCRIPTION:
@@ -777,28 +719,37 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp)
mp->port_tx_queue_command |= 1;
}
-/* Helper function for mv643xx_eth_open */
-static int mv643xx_eth_real_open(struct net_device *dev)
+/*
+ * mv643xx_eth_open
+ *
+ * This function is called when openning the network device. The function
+ * should initialize all the hardware, initialize cyclic Rx/Tx
+ * descriptors chain and buffers and allocate an IRQ to the network
+ * device.
+ *
+ * Input : a pointer to the network device structure
+ *
+ * Output : zero of success , nonzero if fails.
+ */
+
+static int mv643xx_eth_open(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int size;
+ int err;
+
+ err = request_irq(dev->irq, mv643xx_eth_int_handler,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ if (err) {
+ printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+ port_num);
+ return -EAGAIN;
+ }
/* Stop RX Queues */
mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
- /* Clear the ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
- /* Unmask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL);
-
- /* Unmask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
-
/* Set the MAC Address */
memcpy(mp->port_mac_addr, dev->dev_addr, 6);
@@ -818,14 +769,15 @@ static int mv643xx_eth_real_open(struct net_device *dev)
GFP_KERNEL);
if (!mp->rx_skb) {
printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_irq;
}
mp->tx_skb = kmalloc(sizeof(*mp->tx_skb) * mp->tx_ring_size,
GFP_KERNEL);
if (!mp->tx_skb) {
printk(KERN_ERR "%s: Cannot allocate Tx skb ring\n", dev->name);
- kfree(mp->rx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_rx_skb;
}
/* Allocate TX ring */
@@ -845,9 +797,8 @@ static int mv643xx_eth_real_open(struct net_device *dev)
if (!mp->p_tx_desc_area) {
printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
dev->name, size);
- kfree(mp->rx_skb);
- kfree(mp->tx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_tx_skb;
}
BUG_ON((u32) mp->p_tx_desc_area & 0xf); /* check 16-byte alignment */
memset((void *)mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
@@ -874,13 +825,12 @@ static int mv643xx_eth_real_open(struct net_device *dev)
printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
dev->name);
if (mp->rx_sram_size)
- iounmap(mp->p_rx_desc_area);
+ iounmap(mp->p_tx_desc_area);
else
dma_free_coherent(NULL, mp->tx_desc_area_size,
mp->p_tx_desc_area, mp->tx_desc_dma);
- kfree(mp->rx_skb);
- kfree(mp->tx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_tx_skb;
}
memset((void *)mp->p_rx_desc_area, 0, size);
@@ -900,9 +850,26 @@ static int mv643xx_eth_real_open(struct net_device *dev)
mp->tx_int_coal =
eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
- netif_start_queue(dev);
+ /* Clear any pending ethernet port interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+ /* Unmask phy and link status changes interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_UNMASK_ALL_EXT);
+ /* Unmask RX buffer and TX end interrupt */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
return 0;
+
+out_free_tx_skb:
+ kfree(mp->tx_skb);
+out_free_rx_skb:
+ kfree(mp->rx_skb);
+out_free_irq:
+ free_irq(dev->irq, dev);
+
+ return err;
}
static void mv643xx_eth_free_tx_rings(struct net_device *dev)
@@ -910,14 +877,17 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int curr;
+ struct sk_buff *skb;
/* Stop Tx Queues */
mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
/* Free outstanding skb's on TX rings */
for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) {
- if (mp->tx_skb[curr]) {
- dev_kfree_skb(mp->tx_skb[curr]);
+ skb = mp->tx_skb[curr];
+ if (skb) {
+ mp->tx_ring_skbs -= skb_shinfo(skb)->nr_frags;
+ dev_kfree_skb(skb);
mp->tx_ring_skbs--;
}
}
@@ -973,44 +943,32 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev)
* Output : zero if success , nonzero if fails
*/
-/* Helper function for mv643xx_eth_stop */
-
-static int mv643xx_eth_real_stop(struct net_device *dev)
+static int mv643xx_eth_stop(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
+ /* Mask all interrupts on ethernet port */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+#ifdef MV643XX_NAPI
+ netif_poll_disable(dev);
+#endif
netif_carrier_off(dev);
netif_stop_queue(dev);
- mv643xx_eth_free_tx_rings(dev);
- mv643xx_eth_free_rx_rings(dev);
-
eth_port_reset(mp->port_num);
- /* Disable ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
- /* Mask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
-
- /* Mask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
-
- return 0;
-}
-
-static int mv643xx_eth_stop(struct net_device *dev)
-{
- struct mv643xx_private *mp = netdev_priv(dev);
-
- spin_lock_irq(&mp->lock);
+ mv643xx_eth_free_tx_rings(dev);
+ mv643xx_eth_free_rx_rings(dev);
- mv643xx_eth_real_stop(dev);
+#ifdef MV643XX_NAPI
+ netif_poll_enable(dev);
+#endif
free_irq(dev->irq, dev);
- spin_unlock_irq(&mp->lock);
return 0;
}
@@ -1022,20 +980,17 @@ static void mv643xx_tx(struct net_device *dev)
struct pkt_info pkt_info;
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
- if (pkt_info.return_info) {
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
+ if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+ dma_unmap_single(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ if (pkt_info.return_info)
dev_kfree_skb_irq(pkt_info.return_info);
- } else
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, DMA_TO_DEVICE);
}
if (netif_queue_stopped(dev) &&
@@ -1053,14 +1008,11 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
struct mv643xx_private *mp = netdev_priv(dev);
int done = 1, orig_budget, work_done;
unsigned int port_num = mp->port_num;
- unsigned long flags;
#ifdef MV643XX_TX_FAST_REFILL
if (++mp->tx_clean_threshold > 5) {
- spin_lock_irqsave(&mp->lock, flags);
mv643xx_tx(dev);
mp->tx_clean_threshold = 0;
- spin_unlock_irqrestore(&mp->lock, flags);
}
#endif
@@ -1078,21 +1030,36 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
}
if (done) {
- spin_lock_irqsave(&mp->lock, flags);
- __netif_rx_complete(dev);
+ netif_rx_complete(dev);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
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);
+ INT_UNMASK_ALL);
}
return done ? 0 : 1;
}
#endif
+/* Hardware can't handle unaligned fragments smaller than 9 bytes.
+ * This helper function detects that case.
+ */
+
+static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
+{
+ unsigned int frag;
+ skb_frag_t *fragp;
+
+ for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+ fragp = &skb_shinfo(skb)->frags[frag];
+ if (fragp->size <= 8 && fragp->page_offset & 0x7)
+ return 1;
+
+ }
+ return 0;
+}
+
+
/*
* mv643xx_eth_start_xmit
*
@@ -1136,12 +1103,19 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ if (has_tiny_unaligned_frags(skb)) {
+ if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+ stats->tx_dropped++;
+ printk(KERN_DEBUG "%s: failed to linearize tiny "
+ "unaligned fragment\n", dev->name);
+ return 1;
+ }
+ }
+
spin_lock_irqsave(&mp->lock, flags);
- /* Update packet info data structure -- DMA owned, first last */
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
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 |
@@ -1150,7 +1124,6 @@ linear:
5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0;
} else {
-
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC |
@@ -1158,14 +1131,16 @@ linear:
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) {
+ if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_UDP) ) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
pkt_info.l4i_chk = skb->h.uh->check;
- } else if (skb->nh.iph->protocol == IPPROTO_TCP)
+ } else if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_TCP))
pkt_info.l4i_chk = skb->h.th->check;
else {
printk(KERN_ERR
- "%s: chksum proto != TCP or UDP\n",
+ "%s: chksum proto != IPv4 TCP or UDP\n",
dev->name);
spin_unlock_irqrestore(&mp->lock, flags);
return 1;
@@ -1183,26 +1158,6 @@ linear:
} else {
unsigned int frag;
- /* Since hardware can't handle unaligned fragments smaller
- * than 9 bytes, if we find any, we linearize the skb
- * and start again. When I've seen it, it's always been
- * the first frag (probably near the end of the page),
- * but we check all frags to be safe.
- */
- for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *fragp;
-
- fragp = &skb_shinfo(skb)->frags[frag];
- if (fragp->size <= 8 && fragp->page_offset & 0x7) {
- skb_linearize(skb, GFP_ATOMIC);
- printk(KERN_DEBUG "%s: unaligned tiny fragment"
- "%d of %d, fixed\n",
- dev->name, frag,
- skb_shinfo(skb)->nr_frags);
- goto linear;
- }
- }
-
/* first frag which is skb header */
pkt_info.byte_cnt = skb_headlen(skb);
pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
@@ -1221,14 +1176,16 @@ linear:
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) {
+ if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_UDP)) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
pkt_info.l4i_chk = skb->h.uh->check;
- } else if (skb->nh.iph->protocol == IPPROTO_TCP)
+ } else if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_TCP))
pkt_info.l4i_chk = skb->h.th->check;
else {
printk(KERN_ERR
- "%s: chksum proto != TCP or UDP\n",
+ "%s: chksum proto != IPv4 TCP or UDP\n",
dev->name);
spin_unlock_irqrestore(&mp->lock, flags);
return 1;
@@ -1288,6 +1245,8 @@ linear:
}
}
#else
+ spin_lock_irqsave(&mp->lock, flags);
+
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC;
pkt_info.l4i_chk = 0;
@@ -1340,39 +1299,18 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
}
#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);
+ int port_num = mp->port_num;
+
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
- mv643xx_disable_irq(mp);
mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
- mv643xx_enable_irq(mp);
+
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
}
#endif
@@ -1441,7 +1379,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
* Zero copy can only work if we use Discovery II memory. Else, we will
* have to map the buffers to ISA memory which is only 16 MB
*/
- dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
+ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
#endif
@@ -2054,6 +1992,196 @@ static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
}
/*
+ * The entries in each table are indexed by a hash of a packet's MAC
+ * address. One bit in each entry determines whether the packet is
+ * accepted. There are 4 entries (each 8 bits wide) in each register
+ * of the table. The bits in each entry are defined as follows:
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue (ETH_Q0=0)
+ * 7-4 Reserved = 0;
+ */
+static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+{
+ unsigned int table_reg;
+ unsigned int tbl_offset;
+ unsigned int reg_offset;
+
+ tbl_offset = (entry / 4) * 4; /* Register offset of DA table entry */
+ reg_offset = entry % 4; /* Entry offset within the register */
+
+ /* Set "accepts frame bit" at specified table entry */
+ table_reg = mv_read(table + tbl_offset);
+ table_reg |= 0x01 << (8 * reg_offset);
+ mv_write(table + tbl_offset, table_reg);
+}
+
+/*
+ * eth_port_mc_addr - Multicast address settings.
+ *
+ * The MV device supports multicast using two tables:
+ * 1) Special Multicast Table for MAC addresses of the form
+ * 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_FF).
+ * The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+ * Table entries in the DA-Filter table.
+ * 2) Other Multicast Table for multicast of another type. A CRC-8bit
+ * is used as an index to the Other Multicast Table entries in the
+ * DA-Filter table. This function calculates the CRC-8bit value.
+ * In either case, eth_port_set_filter_table_entry() is then called
+ * to set to set the actual table entry.
+ */
+static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+{
+ unsigned int mac_h;
+ unsigned int mac_l;
+ unsigned char crc_result = 0;
+ int table;
+ int mac_array[48];
+ int crc[8];
+ int i;
+
+ if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
+ (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
+ table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num);
+ eth_port_set_filter_table_entry(table, p_addr[5]);
+ return;
+ }
+
+ /* Calculate CRC-8 out of the given address */
+ mac_h = (p_addr[0] << 8) | (p_addr[1]);
+ mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) |
+ (p_addr[4] << 8) | (p_addr[5] << 0);
+
+ for (i = 0; i < 32; i++)
+ mac_array[i] = (mac_l >> i) & 0x1;
+ for (i = 32; i < 48; i++)
+ mac_array[i] = (mac_h >> (i - 32)) & 0x1;
+
+ crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ mac_array[39] ^
+ mac_array[35] ^ mac_array[34] ^ mac_array[31] ^ mac_array[30] ^
+ mac_array[28] ^ mac_array[23] ^ mac_array[21] ^ mac_array[19] ^
+ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ mac_array[12] ^
+ mac_array[8] ^ mac_array[7] ^ mac_array[6] ^ mac_array[0];
+
+ crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ mac_array[34] ^
+ mac_array[32] ^ mac_array[30] ^ mac_array[29] ^ mac_array[28] ^
+ mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ mac_array[21] ^
+ mac_array[20] ^ mac_array[18] ^ mac_array[17] ^ mac_array[16] ^
+ mac_array[15] ^ mac_array[14] ^ mac_array[13] ^ mac_array[12] ^
+ mac_array[9] ^ mac_array[6] ^ mac_array[1] ^ mac_array[0];
+
+ crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[42] ^ mac_array[39] ^ mac_array[37] ^ mac_array[34] ^
+ mac_array[33] ^ mac_array[29] ^ mac_array[28] ^ mac_array[25] ^
+ mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ mac_array[15] ^
+ mac_array[13] ^ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^
+ mac_array[6] ^ mac_array[2] ^ mac_array[1] ^ mac_array[0];
+
+ crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[40] ^ mac_array[38] ^ mac_array[35] ^ mac_array[34] ^
+ mac_array[30] ^ mac_array[29] ^ mac_array[26] ^ mac_array[25] ^
+ mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^
+ mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[7] ^
+ mac_array[3] ^ mac_array[2] ^ mac_array[1];
+
+ crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[41] ^
+ mac_array[39] ^ mac_array[36] ^ mac_array[35] ^ mac_array[31] ^
+ mac_array[30] ^ mac_array[27] ^ mac_array[26] ^ mac_array[24] ^
+ mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ mac_array[14] ^
+ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^ mac_array[4] ^
+ mac_array[3] ^ mac_array[2];
+
+ crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ mac_array[42] ^
+ mac_array[40] ^ mac_array[37] ^ mac_array[36] ^ mac_array[32] ^
+ mac_array[31] ^ mac_array[28] ^ mac_array[27] ^ mac_array[25] ^
+ mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ mac_array[15] ^
+ mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[5] ^
+ mac_array[4] ^ mac_array[3];
+
+ crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ mac_array[41] ^
+ mac_array[38] ^ mac_array[37] ^ mac_array[33] ^ mac_array[32] ^
+ mac_array[29] ^ mac_array[28] ^ mac_array[26] ^ mac_array[21] ^
+ mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ mac_array[14] ^
+ mac_array[12] ^ mac_array[10] ^ mac_array[6] ^ mac_array[5] ^
+ mac_array[4];
+
+ crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ mac_array[39] ^
+ mac_array[38] ^ mac_array[34] ^ mac_array[33] ^ mac_array[30] ^
+ mac_array[29] ^ mac_array[27] ^ mac_array[22] ^ mac_array[20] ^
+ mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ mac_array[13] ^
+ mac_array[11] ^ mac_array[7] ^ mac_array[6] ^ mac_array[5];
+
+ for (i = 0; i < 8; i++)
+ crc_result = crc_result | (crc[i] << i);
+
+ table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+ eth_port_set_filter_table_entry(table, crc_result);
+}
+
+/*
+ * Set the entire multicast list based on dev->mc_list.
+ */
+static void eth_port_set_multicast_list(struct net_device *dev)
+{
+
+ struct dev_mc_list *mc_list;
+ int i;
+ int table_index;
+ struct mv643xx_private *mp = netdev_priv(dev);
+ unsigned int eth_port_num = mp->port_num;
+
+ /* If the device is in promiscuous mode or in all multicast mode,
+ * we will fully populate both multicast tables with accept.
+ * This is guaranteed to yield a match on all multicast addresses...
+ */
+ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Set all entries in DA filter special multicast
+ * table (Ex_dFSMT)
+ * Set for ETH_Q0 for now
+ * Bits
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+
+ /* Set all entries in DA filter other multicast
+ * table (Ex_dFOMT)
+ * Set for ETH_Q0 for now
+ * Bits
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ }
+ return;
+ }
+
+ /* We will clear out multicast tables every time we get the list.
+ * Then add the entire new list...
+ */
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Clear DA filter special multicast table (Ex_dFSMT) */
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+
+ /* Clear DA filter other multicast table (Ex_dFOMT) */
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+ }
+
+ /* Get pointer to net_device multicast list and add each one... */
+ for (i = 0, mc_list = dev->mc_list;
+ (i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+ i++, mc_list = mc_list->next)
+ if (mc_list->dmi_addrlen == 6)
+ eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
+}
+
+/*
* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
*
* DESCRIPTION:
@@ -2080,11 +2208,11 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write((MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write((MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
}
}
@@ -2489,6 +2617,7 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
struct eth_tx_desc *current_descriptor;
struct eth_tx_desc *first_descriptor;
u32 command;
+ unsigned long flags;
/* Do not process Tx ring in case of Tx ring resource error */
if (mp->tx_resource_err)
@@ -2505,6 +2634,8 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
return ETH_ERROR;
}
+ spin_lock_irqsave(&mp->lock, flags);
+
mp->tx_ring_skbs++;
BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
@@ -2554,11 +2685,15 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
mp->tx_resource_err = 1;
mp->tx_curr_desc_q = tx_first_desc;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_QUEUE_LAST_RESOURCE;
}
mp->tx_curr_desc_q = tx_next_desc;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
#else
@@ -2569,11 +2704,14 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
int tx_desc_used;
struct eth_tx_desc *current_descriptor;
unsigned int command_status;
+ unsigned long flags;
/* Do not process Tx ring in case of Tx ring resource error */
if (mp->tx_resource_err)
return ETH_QUEUE_FULL;
+ spin_lock_irqsave(&mp->lock, flags);
+
mp->tx_ring_skbs++;
BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
@@ -2604,9 +2742,12 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
/* Check for ring index overlap in the Tx desc ring */
if (tx_desc_curr == tx_desc_used) {
mp->tx_resource_err = 1;
+
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_QUEUE_LAST_RESOURCE;
}
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_OK;
}
#endif
@@ -2629,23 +2770,27 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
* Tx ring 'first' and 'used' indexes are updated.
*
* RETURN:
- * ETH_ERROR in case the routine can not access Tx desc ring.
- * ETH_RETRY in case there is transmission in process.
- * ETH_END_OF_JOB if the routine has nothing to release.
- * ETH_OK otherwise.
+ * ETH_OK on success
+ * ETH_ERROR otherwise.
*
*/
static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
struct pkt_info *p_pkt_info)
{
int tx_desc_used;
+ int tx_busy_desc;
+ struct eth_tx_desc *p_tx_desc_used;
+ unsigned int command_status;
+ unsigned long flags;
+ int err = ETH_OK;
+
+ spin_lock_irqsave(&mp->lock, flags);
+
#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
- int tx_busy_desc = mp->tx_first_desc_q;
+ tx_busy_desc = mp->tx_first_desc_q;
#else
- int tx_busy_desc = mp->tx_curr_desc_q;
+ tx_busy_desc = mp->tx_curr_desc_q;
#endif
- struct eth_tx_desc *p_tx_desc_used;
- unsigned int command_status;
/* Get the Tx Desc ring indexes */
tx_desc_used = mp->tx_used_desc_q;
@@ -2653,22 +2798,30 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
/* Sanity check */
- if (p_tx_desc_used == NULL)
- return ETH_ERROR;
+ if (p_tx_desc_used == NULL) {
+ err = ETH_ERROR;
+ goto out;
+ }
/* Stop release. About to overlap the current available Tx descriptor */
- if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err)
- return ETH_END_OF_JOB;
+ if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err) {
+ err = ETH_ERROR;
+ goto out;
+ }
command_status = p_tx_desc_used->cmd_sts;
/* Still transmitting... */
- if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
- return ETH_RETRY;
+ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+ err = ETH_ERROR;
+ goto out;
+ }
/* Pass the packet information to the caller */
p_pkt_info->cmd_sts = command_status;
p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
+ p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr;
+ p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt;
mp->tx_skb[tx_desc_used] = NULL;
/* Update the next descriptor to release. */
@@ -2680,7 +2833,10 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
BUG_ON(mp->tx_ring_skbs == 0);
mp->tx_ring_skbs--;
- return ETH_OK;
+out:
+ spin_unlock_irqrestore(&mp->lock, flags);
+
+ return err;
}
/*
@@ -2712,11 +2868,14 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
volatile struct eth_rx_desc *p_rx_desc;
unsigned int command_status;
+ unsigned long flags;
/* Do not process Rx ring in case of Rx ring resource error */
if (mp->rx_resource_err)
return ETH_QUEUE_FULL;
+ spin_lock_irqsave(&mp->lock, flags);
+
/* Get the Rx Desc ring 'curr and 'used' indexes */
rx_curr_desc = mp->rx_curr_desc_q;
rx_used_desc = mp->rx_used_desc_q;
@@ -2728,8 +2887,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
rmb();
/* Nothing to receive... */
- if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_END_OF_JOB;
+ }
p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
p_pkt_info->cmd_sts = command_status;
@@ -2749,6 +2910,8 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
if (rx_next_curr_desc == rx_used_desc)
mp->rx_resource_err = 1;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
@@ -2777,6 +2940,9 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
{
int used_rx_desc; /* Where to return Rx resource */
volatile struct eth_rx_desc *p_used_rx_desc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
/* Get 'used' Rx descriptor */
used_rx_desc = mp->rx_used_desc_q;
@@ -2800,6 +2966,8 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
/* Any Rx return cancels the Rx resource error status */
mp->rx_resource_err = 0;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 0de8fdd2aa86..94f782d51f0f 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -212,15 +212,6 @@ static int __init do_ne_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init ne_probe(int unit)
{
@@ -859,6 +850,15 @@ int init_module(void)
return -ENODEV;
}
+static void cleanup_card(struct net_device *dev)
+{
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+ if (idev)
+ pnp_device_detach(idev);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 6d62ada85de6..e6df375a1d4b 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -278,14 +278,6 @@ static int __init do_ne2_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- mca_mark_as_unused(ei_status.priv);
- mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init ne2_probe(int unit)
{
@@ -812,6 +804,14 @@ int init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ mca_mark_as_unused(ei_status.priv);
+ mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index a1ac4bd1696e..a7bb54df75a8 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -415,7 +415,7 @@ typedef enum {
/* directly indexed by chip_t, above */
-const static struct {
+static const struct {
const char *name;
u8 version; /* from RTL8139C docs */
u32 RxConfigMask; /* should clear the bits supported by this chip */
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 049c34b37067..593d8adee891 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1598,7 +1598,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
switch(cmd) {
case SIOCGMIIPHY: /* Get the address of the PHY in use. */
data[0] = 0; /* we have only this address */
- /* fall trough */
+ /* fall through */
case SIOCGMIIREG: /* Read the specified MII register. */
data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
break;
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 02940c0fef68..459443b572ce 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -81,7 +81,7 @@ int mdiobus_register(struct mii_bus *bus)
phydev->dev.parent = bus->dev;
phydev->dev.bus = &mdio_bus_type;
- sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i);
phydev->bus = bus;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index b8686e47f899..1474b7c5ac0b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -42,7 +42,7 @@
*/
void phy_print_status(struct phy_device *phydev)
{
- pr_info("%s: Link is %s", phydev->dev.bus_id,
+ pr_info("PHY: %s - Link is %s", phydev->dev.bus_id,
phydev->link ? "Up" : "Down");
if (phydev->link)
printk(" - %d/%s", phydev->speed,
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 400f652282d7..aa6540b39466 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -189,7 +189,7 @@ ppp_asynctty_open(struct tty_struct *tty)
goto out_free;
tty->disc_data = ap;
-
+ tty->receive_room = 65536;
return 0;
out_free:
@@ -343,12 +343,6 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
return 0;
}
-static int
-ppp_asynctty_room(struct tty_struct *tty)
-{
- return 65535;
-}
-
/*
* This can now be called from hard interrupt level as well
* as soft interrupt level or mainline.
@@ -398,7 +392,6 @@ static struct tty_ldisc ppp_ldisc = {
.write = ppp_asynctty_write,
.ioctl = ppp_asynctty_ioctl,
.poll = ppp_asynctty_poll,
- .receive_room = ppp_asynctty_room,
.receive_buf = ppp_asynctty_receive,
.write_wakeup = ppp_asynctty_wakeup,
};
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 4d51c0c8023d..33cb8254e79d 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -237,7 +237,7 @@ ppp_sync_open(struct tty_struct *tty)
goto out_free;
tty->disc_data = ap;
-
+ tty->receive_room = 65536;
return 0;
out_free:
@@ -384,12 +384,6 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
return 0;
}
-static int
-ppp_sync_room(struct tty_struct *tty)
-{
- return 65535;
-}
-
/*
* This can now be called from hard interrupt level as well
* as soft interrupt level or mainline.
@@ -439,7 +433,6 @@ static struct tty_ldisc ppp_sync_ldisc = {
.write = ppp_sync_write,
.ioctl = ppp_synctty_ioctl,
.poll = ppp_sync_poll,
- .receive_room = ppp_sync_room,
.receive_buf = ppp_sync_receive,
.write_wakeup = ppp_sync_wakeup,
};
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 14a76f7cf900..2e1bed153c39 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -170,7 +170,7 @@ enum phy_version {
#define _R(NAME,MAC,MASK) \
{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
-const static struct {
+static const struct {
const char *name;
u8 mac_version;
u32 RxConfigMask; /* Clears the bits supported by this chip */
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index d6388e1533f0..76139478c3df 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -94,7 +94,7 @@ static inline int card_wait_for_busy_clear(const int ioaddr[],
const char* name);
static inline int card_wait_for_ready(const int ioaddr[], const char* name,
unsigned char in[]);
-static inline int card_send_command(const int ioaddr[], const char* name,
+static int card_send_command(const int ioaddr[], const char* name,
const unsigned char out[], unsigned char in[]);
/* SB1000 hardware routines to be used during frame rx interrupt */
@@ -309,7 +309,7 @@ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
}
/* Card Send Command (cannot be used during an interrupt) */
-static inline int
+static int
card_send_command(const int ioaddr[], const char* name,
const unsigned char out[], unsigned char in[])
{
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 478791e09bf7..b420182eec4b 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -329,7 +329,7 @@ static struct mii_chip_info {
{ NULL, }
};
-const static struct {
+static const struct {
const char *name;
} sis_chip_info[] = {
{ "SiS 190 PCI Fast Ethernet adapter" },
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
index 0fddf61047b4..07c1b4c8699d 100644
--- a/drivers/net/sk98lin/skdim.c
+++ b/drivers/net/sk98lin/skdim.c
@@ -180,7 +180,7 @@ SkDimModerate(SK_AC *pAC) {
/*
** The number of interrupts per sec is the same as expected.
** Evalulate the descriptor-ratio. If it has changed, a resize
- ** in the moderation timer might be usefull
+ ** in the moderation timer might be useful
*/
if (M_DIMINFO.AutoSizing) {
ResizeDimTimerDuration(pAC);
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 9a76ac180b11..a5f2b1ee0752 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -282,26 +282,22 @@ SK_U32 Val) /* pointer to store the read value */
* Description:
* This function initialize the PCI resources and IO
*
- * Returns: N/A
- *
+ * Returns:
+ * 0 - indicate everything worked ok.
+ * != 0 - error indication
*/
-int SkGeInitPCI(SK_AC *pAC)
+static __devinit int SkGeInitPCI(SK_AC *pAC)
{
struct SK_NET_DEVICE *dev = pAC->dev[0];
struct pci_dev *pdev = pAC->PciDev;
int retval;
- if (pci_enable_device(pdev) != 0) {
- return 1;
- }
-
dev->mem_start = pci_resource_start (pdev, 0);
pci_set_master(pdev);
- if (pci_request_regions(pdev, "sk98lin") != 0) {
- retval = 2;
- goto out_disable;
- }
+ retval = pci_request_regions(pdev, "sk98lin");
+ if (retval)
+ goto out;
#ifdef SK_BIG_ENDIAN
/*
@@ -320,9 +316,8 @@ int SkGeInitPCI(SK_AC *pAC)
* Remap the regs into kernel space.
*/
pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
-
- if (!pAC->IoBase){
- retval = 3;
+ if (!pAC->IoBase) {
+ retval = -EIO;
goto out_release;
}
@@ -330,8 +325,7 @@ int SkGeInitPCI(SK_AC *pAC)
out_release:
pci_release_regions(pdev);
- out_disable:
- pci_disable_device(pdev);
+ out:
return retval;
}
@@ -492,7 +486,7 @@ module_param_array(AutoSizing, charp, NULL, 0);
* 0, if everything is ok
* !=0, on error
*/
-static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
+static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
{
short i;
unsigned long Flags;
@@ -529,7 +523,7 @@ SK_BOOL DualNet;
if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
printk("HWInit (0) failed.\n");
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return(-EAGAIN);
+ return -EIO;
}
SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA);
SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
@@ -551,7 +545,7 @@ SK_BOOL DualNet;
if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
printk("sk98lin: HWInit (1) failed.\n");
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return(-EAGAIN);
+ return -EIO;
}
SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
@@ -583,20 +577,20 @@ SK_BOOL DualNet;
} else {
printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
pAC->GIni.GIMacsFound);
- return -EAGAIN;
+ return -EIO;
}
if (Ret) {
printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
dev->irq);
- return -EAGAIN;
+ return Ret;
}
pAC->AllocFlag |= SK_ALLOC_IRQ;
/* Alloc memory for this board (Mem for RxD/TxD) : */
if(!BoardAllocMem(pAC)) {
printk("No memory for descriptor rings.\n");
- return(-EAGAIN);
+ return -ENOMEM;
}
BoardInitMem(pAC);
@@ -612,7 +606,7 @@ SK_BOOL DualNet;
DualNet)) {
BoardFreeMem(pAC);
printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
- return(-EAGAIN);
+ return -EIO;
}
return (0);
@@ -633,8 +627,7 @@ SK_BOOL DualNet;
* SK_TRUE, if all memory could be allocated
* SK_FALSE, if not
*/
-static SK_BOOL BoardAllocMem(
-SK_AC *pAC)
+static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC)
{
caddr_t pDescrMem; /* pointer to descriptor memory area */
size_t AllocLength; /* length of complete descriptor area */
@@ -727,8 +720,7 @@ size_t AllocLength; /* length of complete descriptor area */
*
* Returns: N/A
*/
-static void BoardInitMem(
-SK_AC *pAC) /* pointer to adapter context */
+static __devinit void BoardInitMem(SK_AC *pAC)
{
int i; /* loop counter */
int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/
@@ -2859,7 +2851,7 @@ unsigned long Flags; /* for spin lock */
* Description:
* This function is called if an ioctl is issued on the device.
* There are three subfunction for reading, writing and test-writing
- * the private MIB data structure (usefull for SysKonnect-internal tools).
+ * the private MIB data structure (useful for SysKonnect-internal tools).
*
* Returns:
* 0, if everything is ok
@@ -4776,32 +4768,47 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
struct net_device *dev = NULL;
static int boards_found = 0;
int error = -ENODEV;
+ int using_dac = 0;
char DeviceStr[80];
if (pci_enable_device(pdev))
goto out;
/* Configure DMA attributes. */
- if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
- pci_set_dma_mask(pdev, DMA_32BIT_MASK))
- goto out_disable_device;
-
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ using_dac = 1;
+ error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (error < 0) {
+ printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto out_disable_device;
+ }
+ } else {
+ error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (error) {
+ printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto out_disable_device;
+ }
+ }
- if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
- printk(KERN_ERR "Unable to allocate etherdev "
+ error = -ENOMEM;
+ dev = alloc_etherdev(sizeof(DEV_NET));
+ if (!dev) {
+ printk(KERN_ERR "sk98lin: unable to allocate etherdev "
"structure!\n");
goto out_disable_device;
}
pNet = netdev_priv(dev);
- pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+ pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
if (!pNet->pAC) {
- printk(KERN_ERR "Unable to allocate adapter "
+ printk(KERN_ERR "sk98lin: unable to allocate adapter "
"structure!\n");
goto out_free_netdev;
}
- memset(pNet->pAC, 0, sizeof(SK_AC));
pAC = pNet->pAC;
pAC->PciDev = pdev;
@@ -4810,6 +4817,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
pAC->CheckQueue = SK_FALSE;
dev->irq = pdev->irq;
+
error = SkGeInitPCI(pAC);
if (error) {
printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
@@ -4844,19 +4852,25 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
#endif
}
+ if (using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
+
pAC->Index = boards_found++;
- if (SkGeBoardInit(dev, pAC))
+ error = SkGeBoardInit(dev, pAC);
+ if (error)
goto out_free_netdev;
/* Read Adapter name from VPD */
if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
+ error = -EIO;
printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
goto out_free_resources;
}
/* Register net device */
- if (register_netdev(dev)) {
+ error = register_netdev(dev);
+ if (error) {
printk(KERN_ERR "sk98lin: Could not register device.\n");
goto out_free_resources;
}
@@ -4883,15 +4897,17 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
boards_found++;
+ pci_set_drvdata(pdev, dev);
+
/* More then one port found */
if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
- printk(KERN_ERR "Unable to allocate etherdev "
+ dev = alloc_etherdev(sizeof(DEV_NET));
+ if (!dev) {
+ printk(KERN_ERR "sk98lin: unable to allocate etherdev "
"structure!\n");
- goto out;
+ goto single_port;
}
- pAC->dev[1] = dev;
pNet = netdev_priv(dev);
pNet->PortNr = 1;
pNet->NetNr = 1;
@@ -4920,20 +4936,28 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
#endif
}
- if (register_netdev(dev)) {
- printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n");
+ if (using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
+
+ error = register_netdev(dev);
+ if (error) {
+ printk(KERN_ERR "sk98lin: Could not register device"
+ " for second port. (%d)\n", error);
free_netdev(dev);
- pAC->dev[1] = pAC->dev[0];
- } else {
- memcpy(&dev->dev_addr,
- &pAC->Addr.Net[1].CurrentMacAddress, 6);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
- printk("%s: %s\n", dev->name, DeviceStr);
- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+ goto single_port;
}
+
+ pAC->dev[1] = dev;
+ memcpy(&dev->dev_addr,
+ &pAC->Addr.Net[1].CurrentMacAddress, 6);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ printk("%s: %s\n", dev->name, DeviceStr);
+ printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
}
+single_port:
+
/* Save the hardware revision */
pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
(pAC->GIni.GIPciHwRev & 0x0F);
@@ -4945,7 +4969,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
- pci_set_drvdata(pdev, dev);
return 0;
out_free_resources:
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
index 58e1a5be913f..a386172107e8 100644
--- a/drivers/net/sk98lin/skgepnmi.c
+++ b/drivers/net/sk98lin/skgepnmi.c
@@ -611,7 +611,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
* Description:
* Calls a general sub-function for all this stuff. The preset does
* the same as a set, but returns just before finally setting the
- * new value. This is usefull to check if a set might be successfull.
+ * new value. This is useful to check if a set might be successfull.
* If the instance -1 is passed, an array of values is supposed and
* all instances of the OID will be set.
*
@@ -654,7 +654,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
* Description:
* Calls a general sub-function for all this stuff. The preset does
* the same as a set, but returns just before finally setting the
- * new value. This is usefull to check if a set might be successfull.
+ * new value. This is useful to check if a set might be successfull.
* If the instance -1 is passed, an array of values is supposed and
* all instances of the OID will be set.
*
@@ -870,7 +870,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
* Description:
* Calls a general sub-function for all this set stuff. The preset does
* the same as a set, but returns just before finally setting the
- * new value. This is usefull to check if a set might be successfull.
+ * new value. This is useful to check if a set might be successfull.
* The sub-function runs through the IdTable, checks which OIDs are able
* to set, and calls the handler function of the OID to perform the
* preset. The return value of the function will also be stored in
@@ -6473,7 +6473,7 @@ unsigned int PhysPortIndex) /* Physical port index */
*
* Description:
* The COMMON module only tells us if the mode is half or full duplex.
- * But in the decade of auto sensing it is usefull for the user to
+ * But in the decade of auto sensing it is useful for the user to
* know if the mode was negotiated or forced. Therefore we have a
* look to the mode, which was last used by the negotiation process.
*
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index b538e3038058..bf55a4cfb3d2 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -3243,12 +3243,22 @@ static int __devinit skge_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)))
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
using_dac = 1;
- else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
- printk(KERN_ERR PFX "%s no usable DMA configuration\n",
- pci_name(pdev));
- goto err_out_free_regions;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto err_out_free_regions;
+ }
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
}
#ifdef __BIG_ENDIAN
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f5d697c0c031..f8b973a04b65 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -57,7 +57,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "0.11"
+#define DRV_VERSION "0.13"
#define PFX DRV_NAME " "
/*
@@ -75,6 +75,7 @@
#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
#define RX_DEF_PENDING RX_MAX_PENDING
+#define RX_SKB_ALIGN 8
#define TX_RING_SIZE 512
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -91,7 +92,7 @@
static const u32 default_msg =
NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
| NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
- | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_INTR;
+ | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
static int debug = -1; /* defaults above */
module_param(debug, int, 0);
@@ -624,13 +625,16 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
}
-static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len)
+/* Assign Ram Buffer allocation.
+ * start and end are in units of 4k bytes
+ * ram registers are in units of 64bit words
+ */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
{
- u32 end;
+ u32 start, end;
- start /= 8;
- len /= 8;
- end = start + len - 1;
+ start = startk * 4096/8;
+ end = (endk * 4096/8) - 1;
sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -639,14 +643,19 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len)
sky2_write32(hw, RB_ADDR(q, RB_RP), start);
if (q == Q_R1 || q == Q_R2) {
- u32 rxup, rxlo;
+ u32 space = (endk - startk) * 4096/8;
+ u32 tp = space - space/4;
- rxlo = len/2;
- rxup = rxlo + len/4;
+ /* On receive queue's set the thresholds
+ * give receiver priority when > 3/4 full
+ * send pause when down to 2K
+ */
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
- /* Set thresholds on receive queue's */
- sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), rxup);
- sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), rxlo);
+ tp = space - 2048/8;
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
} else {
/* Enable store & forward on Tx queue's because
* Tx FIFO is only 1K on Yukon
@@ -695,9 +704,10 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
* This is a workaround code taken from SysKonnect sk98lin driver
* to deal with chip bug on Yukon EC rev 0 in the wraparound case.
*/
-static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q,
+static void sky2_put_idx(struct sky2_hw *hw, unsigned q,
u16 idx, u16 *last, u16 size)
{
+ wmb();
if (is_ec_a1(hw) && idx < *last) {
u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
@@ -721,6 +731,7 @@ setnew:
sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
}
*last = idx;
+ mmiowb();
}
@@ -734,11 +745,11 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
/* Return high part of DMA address (could be 32 or 64 bit) */
static inline u32 high32(dma_addr_t a)
{
- return (a >> 16) >> 16;
+ return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
}
/* Build description to hardware about buffer */
-static inline void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
+static void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
{
struct sky2_rx_le *le;
u32 hi = high32(map);
@@ -878,13 +889,13 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
struct sky2_hw *hw = sky2->hw;
u16 port = sky2->port;
- spin_lock(&sky2->tx_lock);
+ spin_lock_bh(&sky2->tx_lock);
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
sky2->vlgrp = grp;
- spin_unlock(&sky2->tx_lock);
+ spin_unlock_bh(&sky2->tx_lock);
}
static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
@@ -893,27 +904,42 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
struct sky2_hw *hw = sky2->hw;
u16 port = sky2->port;
- spin_lock(&sky2->tx_lock);
+ spin_lock_bh(&sky2->tx_lock);
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
if (sky2->vlgrp)
sky2->vlgrp->vlan_devices[vid] = NULL;
- spin_unlock(&sky2->tx_lock);
+ spin_unlock_bh(&sky2->tx_lock);
}
#endif
/*
+ * It appears the hardware has a bug in the FIFO logic that
+ * cause it to hang if the FIFO gets overrun and the receive buffer
+ * is not aligned. ALso alloc_skb() won't align properly if slab
+ * debugging is enabled.
+ */
+static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+ if (likely(skb)) {
+ unsigned long p = (unsigned long) skb->data;
+ skb_reserve(skb,
+ ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+ }
+
+ return skb;
+}
+
+/*
* Allocate and setup receiver buffer pool.
* In case of 64 bit dma, there are 2X as many list elements
* available as ring entries
* and need to reserve one list element so we don't wrap around.
- *
- * It appears the hardware has a bug in the FIFO logic that
- * cause it to hang if the FIFO gets overrun and the receive buffer
- * is not aligned. This means we can't use skb_reserve to align
- * the IP header.
*/
static int sky2_rx_start(struct sky2_port *sky2)
{
@@ -929,7 +955,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
for (i = 0; i < sky2->rx_pending; i++) {
struct ring_info *re = sky2->rx_ring + i;
- re->skb = dev_alloc_skb(sky2->rx_bufsize);
+ re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL);
if (!re->skb)
goto nomem;
@@ -986,19 +1012,19 @@ static int sky2_up(struct net_device *dev)
sky2_mac_init(hw, port);
- /* Configure RAM buffers */
- if (hw->chip_id == CHIP_ID_YUKON_FE ||
- (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == 2))
- ramsize = 4096;
- else {
- u8 e0 = sky2_read8(hw, B2_E_0);
- ramsize = (e0 == 0) ? (128 * 1024) : (e0 * 4096);
- }
+ /* Determine available ram buffer space (in 4K blocks).
+ * Note: not sure about the FE setting below yet
+ */
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ ramsize = 4;
+ else
+ ramsize = sky2_read8(hw, B2_E_0);
+
+ /* Give transmitter one third (rounded up) */
+ rxspace = ramsize - (ramsize + 2) / 3;
- /* 2/3 for Rx */
- rxspace = (2 * ramsize) / 3;
sky2_ramset(hw, rxqaddr[port], 0, rxspace);
- sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace);
+ sky2_ramset(hw, txqaddr[port], rxspace, ramsize);
/* Make sure SyncQ is disabled */
sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
@@ -1054,7 +1080,7 @@ static inline int tx_avail(const struct sky2_port *sky2)
}
/* Estimate of number of transmit list elements required */
-static inline unsigned tx_le_req(const struct sk_buff *skb)
+static unsigned tx_le_req(const struct sk_buff *skb)
{
unsigned count;
@@ -1090,6 +1116,10 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
u16 mss;
u8 ctrl;
+ /* No BH disabling for tx_lock here. We are running in BH disabled
+ * context and TX reclaim runs via poll inside of a software
+ * interrupt, and no related locks in IRQ processing.
+ */
if (!spin_trylock(&sky2->tx_lock))
return NETDEV_TX_LOCKED;
@@ -1099,8 +1129,9 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
*/
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
- printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
- dev->name);
+ if (net_ratelimit())
+ printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+ dev->name);
}
spin_unlock(&sky2->tx_lock);
@@ -1199,7 +1230,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
- addr64 = (mapping >> 16) >> 16;
+ addr64 = high32(mapping);
if (addr64 != sky2->tx_addr64) {
le = get_tx_le(sky2);
le->tx.addr = cpu_to_le32(addr64);
@@ -1229,7 +1260,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
out_unlock:
- mmiowb();
spin_unlock(&sky2->tx_lock);
dev->trans_start = jiffies;
@@ -1282,17 +1312,17 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
dev_kfree_skb_any(skb);
}
- spin_lock(&sky2->tx_lock);
sky2->tx_cons = put;
if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE)
netif_wake_queue(dev);
- spin_unlock(&sky2->tx_lock);
}
/* Cleanup all untransmitted buffers, assume transmitter not running */
static void sky2_tx_clean(struct sky2_port *sky2)
{
+ spin_lock_bh(&sky2->tx_lock);
sky2_tx_complete(sky2, sky2->tx_prod);
+ spin_unlock_bh(&sky2->tx_lock);
}
/* Network shutdown */
@@ -1582,28 +1612,40 @@ out:
local_irq_enable();
}
+
+/* Transmit timeout is only called if we are running, carries is up
+ * and tx queue is full (stopped).
+ */
static void sky2_tx_timeout(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
unsigned txq = txqaddr[sky2->port];
+ u16 ridx;
+
+ /* Maybe we just missed an status interrupt */
+ spin_lock(&sky2->tx_lock);
+ ridx = sky2_read16(hw,
+ sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
+ sky2_tx_complete(sky2, ridx);
+ spin_unlock(&sky2->tx_lock);
+
+ if (!netif_queue_stopped(dev)) {
+ if (net_ratelimit())
+ pr_info(PFX "transmit interrupt missed? recovered\n");
+ return;
+ }
if (netif_msg_timer(sky2))
printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
- netif_stop_queue(dev);
-
sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
- sky2_read32(hw, Q_ADDR(txq, Q_CSR));
-
sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
sky2_tx_clean(sky2);
sky2_qset(hw, txq);
sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
-
- netif_wake_queue(dev);
}
@@ -1713,7 +1755,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
} else {
struct sk_buff *nskb;
- nskb = dev_alloc_skb(sky2->rx_bufsize);
+ nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
if (!nskb)
goto resubmit;
@@ -1745,7 +1787,7 @@ oversize:
error:
++sky2->net_stats.rx_errors;
- if (netif_msg_rx_err(sky2))
+ if (netif_msg_rx_err(sky2) && net_ratelimit())
printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
sky2->netdev->name, status, length);
@@ -1766,13 +1808,16 @@ error:
*/
#define TX_NO_STATUS 0xffff
-static inline void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
+static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
{
if (last != TX_NO_STATUS) {
struct net_device *dev = hw->dev[port];
if (dev && netif_running(dev)) {
struct sky2_port *sky2 = netdev_priv(dev);
+
+ spin_lock(&sky2->tx_lock);
sky2_tx_complete(sky2, last);
+ spin_unlock(&sky2->tx_lock);
}
}
}
@@ -1800,7 +1845,6 @@ static int sky2_poll(struct net_device *dev0, int *budget)
struct sk_buff *skb;
u32 status;
u16 length;
- u8 op;
le = hw->st_le + hw->st_idx;
hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
@@ -1814,10 +1858,8 @@ static int sky2_poll(struct net_device *dev0, int *budget)
sky2 = netdev_priv(dev);
status = le32_to_cpu(le->status);
length = le16_to_cpu(le->length);
- op = le->opcode & ~HW_OWNER;
- le->opcode = 0;
- switch (op) {
+ switch (le->opcode & ~HW_OWNER) {
case OP_RXSTAT:
skb = sky2_receive(sky2, length, status);
if (!skb)
@@ -1865,14 +1907,13 @@ static int sky2_poll(struct net_device *dev0, int *budget)
default:
if (net_ratelimit())
printk(KERN_WARNING PFX
- "unknown status opcode 0x%x\n", op);
+ "unknown status opcode 0x%x\n", le->opcode);
break;
}
}
exit_loop:
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
- mmiowb();
sky2_tx_check(hw, 0, tx_done[0]);
sky2_tx_check(hw, 1, tx_done[1]);
@@ -1887,7 +1928,6 @@ exit_loop:
netif_rx_complete(dev0);
hw->intr_mask |= Y2_IS_STAT_BMU;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
- mmiowb();
return 0;
} else {
*budget -= work_done;
@@ -1900,35 +1940,42 @@ static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
{
struct net_device *dev = hw->dev[port];
- printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
- dev->name, status);
+ if (net_ratelimit())
+ printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
+ dev->name, status);
if (status & Y2_IS_PAR_RD1) {
- printk(KERN_ERR PFX "%s: ram data read parity error\n",
- dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: ram data read parity error\n",
+ dev->name);
/* Clear IRQ */
sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
}
if (status & Y2_IS_PAR_WR1) {
- printk(KERN_ERR PFX "%s: ram data write parity error\n",
- dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: ram data write parity error\n",
+ dev->name);
sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
}
if (status & Y2_IS_PAR_MAC1) {
- printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
}
if (status & Y2_IS_PAR_RX1) {
- printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
}
if (status & Y2_IS_TCP_TXA1) {
- printk(KERN_ERR PFX "%s: TCP segmentation error\n", dev->name);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: TCP segmentation error\n",
+ dev->name);
sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
}
}
@@ -1944,8 +1991,9 @@ static void sky2_hw_intr(struct sky2_hw *hw)
u16 pci_err;
pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
- printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
- pci_name(hw->pdev), pci_err);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
+ pci_name(hw->pdev), pci_err);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
pci_write_config_word(hw->pdev, PCI_STATUS,
@@ -1959,8 +2007,9 @@ static void sky2_hw_intr(struct sky2_hw *hw)
pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
- printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
- pci_name(hw->pdev), pex_err);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
+ pci_name(hw->pdev), pex_err);
/* clear the interrupt */
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
@@ -2250,7 +2299,7 @@ static int sky2_reset(struct sky2_hw *hw)
return 0;
}
-static inline u32 sky2_supported_modes(const struct sky2_hw *hw)
+static u32 sky2_supported_modes(const struct sky2_hw *hw)
{
u32 modes;
if (hw->copper) {
@@ -2995,7 +3044,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
return dev;
}
-static inline void sky2_show_addr(struct net_device *dev)
+static void __devinit sky2_show_addr(struct net_device *dev)
{
const struct sky2_port *sky2 = netdev_priv(dev);
@@ -3038,13 +3087,17 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_regions;
}
- if (sizeof(dma_addr_t) > sizeof(u32)) {
- err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
- if (!err)
- using_dac = 1;
- }
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto err_out_free_regions;
+ }
- if (!using_dac) {
+ } else {
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
printk(KERN_ERR PFX "%s no usable DMA configuration\n",
@@ -3052,6 +3105,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_regions;
}
}
+
#ifdef __BIG_ENDIAN
/* byte swap descriptors in hardware */
{
@@ -3064,14 +3118,13 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
#endif
err = -ENOMEM;
- hw = kmalloc(sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw) {
printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
pci_name(pdev));
goto err_out_free_regions;
}
- memset(hw, 0, sizeof(*hw));
hw->pdev = pdev;
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 404ea4297e32..b2e18d28850d 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -651,11 +651,6 @@ static void sl_setup(struct net_device *dev)
******************************************/
-static int slip_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
@@ -869,10 +864,6 @@ static int slip_open(struct tty_struct *tty)
sl->line = tty_devnum(tty);
sl->pid = current->pid;
- /* FIXME: already done before we were called - seems this can go */
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
-
if (!test_bit(SLF_INUSE, &sl->flags)) {
/* Perform the low-level SLIP initialization. */
if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -897,6 +888,7 @@ static int slip_open(struct tty_struct *tty)
/* Done. We have linked the TTY line to a channel. */
rtnl_unlock();
+ tty->receive_room = 65536; /* We don't flow control */
return sl->dev->base_addr;
err_free_bufs:
@@ -1329,7 +1321,6 @@ static struct tty_ldisc sl_ldisc = {
.close = slip_close,
.ioctl = slip_ioctl,
.receive_buf = slip_receive_buf,
- .receive_room = slip_receive_room,
.write_wakeup = slip_write_wakeup,
};
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index ba8593ac3f8a..3db30cd0625e 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -168,18 +168,6 @@ static int __init do_ultra_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: ultra_close_card() does free_irq */
-#ifdef __ISAPNP__
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
-#endif
- release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init ultra_probe(int unit)
{
@@ -594,6 +582,18 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: ultra_close_card() does free_irq */
+#ifdef __ISAPNP__
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+ if (idev)
+ pnp_device_detach(idev);
+#endif
+ release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 28bf2e69eb5e..7ec08127c9d6 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -88,7 +88,6 @@ static const char version[] =
#include <linux/skbuff.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include "smc91x.h"
@@ -2007,12 +2006,10 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
}
/* Grab the IRQ */
- retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
+ retval = request_irq(dev->irq, &smc_interrupt, SMC_IRQ_FLAGS, dev->name, dev);
if (retval)
goto err_out;
- set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE);
-
#ifdef SMC_USE_PXA_DMA
{
int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 5c2824be4ee6..e0efd1964e72 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -90,7 +90,7 @@
__l--; \
} \
} while (0)
-#define set_irq_type(irq, type)
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_SA1100_PLEB)
/* We can only do 16-bit reads and writes in the static memory space. */
@@ -109,7 +109,7 @@
#define SMC_outw(v, a, r) writew(v, (a) + (r))
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
-#define set_irq_type(irq, type) do {} while (0)
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_SA1100_ASSABET)
@@ -185,11 +185,11 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#include <asm/mach-types.h>
#include <asm/arch/cpu.h>
-#define SMC_IRQ_TRIGGER_TYPE (( \
+#define SMC_IRQ_FLAGS (( \
machine_is_omap_h2() \
|| machine_is_omap_h3() \
|| (machine_is_omap_innovator() && !cpu_is_omap1510()) \
- ) ? IRQT_FALLING : IRQT_RISING)
+ ) ? SA_TRIGGER_FALLING : SA_TRIGGER_RISING)
#elif defined(CONFIG_SH_SH4202_MICRODEV)
@@ -209,7 +209,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#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 set_irq_type(irq, type) do {} while(0)
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_ISA)
@@ -237,7 +237,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#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)
+#define SMC_IRQ_FLAGS (0)
#define RPC_LSA_DEFAULT RPC_LED_TX_RX
#define RPC_LSB_DEFAULT RPC_LED_100_10
@@ -319,7 +319,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
au_writew(*_p++ , _a); \
} while(0)
-#define set_irq_type(irq, type) do {} while (0)
+#define SMC_IRQ_FLAGS (0)
#else
@@ -342,8 +342,8 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
#endif
-#ifndef SMC_IRQ_TRIGGER_TYPE
-#define SMC_IRQ_TRIGGER_TYPE IRQT_RISING
+#ifndef SMC_IRQ_FLAGS
+#define SMC_IRQ_FLAGS SA_TRIGGER_RISING
#endif
#ifdef SMC_USE_PXA_DMA
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 0d765f1733b5..1f5975a61e1f 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -22,7 +22,6 @@
*/
#include <linux/config.h>
-
#include <linux/compiler.h>
#include <linux/crc32.h>
#include <linux/delay.h>
@@ -30,6 +29,7 @@
#include <linux/ethtool.h>
#include <linux/firmware.h>
#include <linux/if_vlan.h>
+#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/ip.h>
@@ -43,6 +43,7 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
+#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <asm/bitops.h>
@@ -108,42 +109,6 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 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
@@ -199,60 +164,33 @@ spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
}
/**
- * 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
+ * spider_net_rx_irq_off - switch off rx irq on this spider card
* @card: device structure
*
- * switches off tx irq by masking them out in the GHIINTnMSK register
+ * switches off rx irq by masking them out in the GHIINTnMSK register
*/
static void
-spider_net_tx_irq_off(struct spider_net_card *card)
+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_TXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
+ regvalue = SPIDER_NET_INT0_MASK_VALUE & (~SPIDER_NET_RXINT);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}
/**
- * spider_net_tx_irq_on - switch on tx irq on this spider card
+ * spider_net_rx_irq_on - switch on rx irq on this spider card
* @card: device structure
*
- * switches on tx irq by enabling them in the GHIINTnMSK register
+ * switches on rx irq by enabling them in the GHIINTnMSK register
*/
static void
-spider_net_tx_irq_on(struct spider_net_card *card)
+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_TXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
+ regvalue = SPIDER_NET_INT0_MASK_VALUE | SPIDER_NET_RXINT;
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}
/**
@@ -326,9 +264,8 @@ 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) */
@@ -349,7 +286,6 @@ spider_net_set_descr_status(struct spider_net_descr *descr,
{
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;
@@ -357,7 +293,6 @@ spider_net_set_descr_status(struct spider_net_descr *descr,
cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
/* and write it back */
descr->dmac_cmd_status = cmd_status;
- wmb();
}
/**
@@ -398,8 +333,9 @@ spider_net_init_chain(struct spider_net_card *card,
{
int i;
struct spider_net_descr *descr;
+ dma_addr_t buf;
- spin_lock_init(&card->chain_lock);
+ atomic_set(&card->rx_chain_refill,0);
descr = start_descr;
memset(descr, 0, sizeof(*descr) * no);
@@ -408,14 +344,14 @@ spider_net_init_chain(struct spider_net_card *card,
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);
+ buf = pci_map_single(card->pdev, descr,
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
- if (descr->bus_addr == DMA_ERROR_CODE)
+ if (buf == DMA_ERROR_CODE)
goto iommu_error;
+ descr->bus_addr = buf;
descr->next = descr + 1;
descr->prev = descr - 1;
@@ -439,7 +375,8 @@ iommu_error:
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);
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
return -ENOMEM;
}
@@ -459,7 +396,7 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card)
if (descr->skb) {
dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->buf_addr,
- SPIDER_NET_MAX_MTU,
+ SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
}
descr = descr->next;
@@ -480,12 +417,13 @@ static int
spider_net_prepare_rx_descr(struct spider_net_card *card,
struct spider_net_descr *descr)
{
+ dma_addr_t buf;
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) &
+ bufsize = (SPIDER_NET_MAX_FRAME + SPIDER_NET_RXBUF_ALIGN - 1) &
(~(SPIDER_NET_RXBUF_ALIGN - 1));
/* and we need to have it 128 byte aligned, therefore we allocate a
@@ -493,10 +431,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
/* 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");
+ if (netif_msg_rx_err(card) && net_ratelimit())
+ pr_err("Not enough memory to allocate rx buffer\n");
return -ENOMEM;
}
descr->buf_size = bufsize;
@@ -510,12 +446,12 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
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) {
+ buf = pci_map_single(card->pdev, descr->skb->data,
+ SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ descr->buf_addr = buf;
+ if (buf == DMA_ERROR_CODE) {
dev_kfree_skb_any(descr->skb);
- if (netif_msg_rx_err(card))
+ if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
} else {
@@ -526,10 +462,10 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
}
/**
- * spider_net_enable_rxctails - sets RX dmac chain tail addresses
+ * spider_net_enable_rxchtails - sets RX dmac chain tail addresses
* @card: card structure
*
- * spider_net_enable_rxctails sets the RX DMAC chain tail adresses in the
+ * spider_net_enable_rxchtails sets the RX DMAC chain tail adresses in the
* chip by writing to the appropriate register. DMA is enabled in
* spider_net_enable_rxdmac.
*/
@@ -551,6 +487,7 @@ spider_net_enable_rxchtails(struct spider_net_card *card)
static void
spider_net_enable_rxdmac(struct spider_net_card *card)
{
+ wmb();
spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
SPIDER_NET_DMA_RX_VALUE);
}
@@ -559,32 +496,28 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
* 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.
+ * refills descriptors in the rx chain: 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);
+ /* one context doing the refill (and a second context seeing that
+ * and omitting it) is ok. If called by NAPI, we'll be called again
+ * as spider_net_decode_one_descr is called several times. If some
+ * interrupt calls us, the NAPI is about to clean up anyway. */
+ if (atomic_inc_return(&card->rx_chain_refill) == 1)
+ while (spider_net_get_descr_status(chain->head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE) {
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ break;
+ chain->head = chain->head->next;
+ }
- /* could be optimized, only do that, if we know the DMA processing
- * has terminated */
- if (count)
- spider_net_enable_rxdmac(card);
+ atomic_dec(&card->rx_chain_refill);
}
/**
@@ -613,6 +546,7 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card)
/* this will allocate the rest of the rx buffers; if not, it's
* business as usual later on */
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
return 0;
error:
@@ -649,24 +583,30 @@ spider_net_release_tx_descr(struct spider_net_card *card,
* @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)
+ * returns 0 if the tx ring is empty, otherwise 1.
+ *
+ * spider_net_release_tx_chain releases the tx descriptors that spider has
+ * finished with (if non-brutal) or simply release tx descriptors (if brutal).
+ * If some other context is calling this function, we return 1 so that we're
+ * scheduled again (if we were scheduled) and will not loose initiative.
*/
-static void
+static int
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);
+ if (atomic_inc_return(&card->tx_chain_release) != 1) {
+ atomic_dec(&card->tx_chain_release);
+ return 1;
+ }
- /* 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;
+ if (!brutal)
+ goto out;
/* fallthrough, if we release the descriptors
* brutally (then we don't care about
* SPIDER_NET_DESCR_CARDOWNED) */
@@ -693,25 +633,30 @@ again:
tx_chain->tail = tx_chain->tail->next;
}
out:
+ atomic_dec(&card->tx_chain_release);
+
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;
- }
- }
+ if (status == SPIDER_NET_DESCR_CARDOWNED)
+ return 1;
+ return 0;
+}
+/**
+ * spider_net_cleanup_tx_ring - cleans up the TX ring
+ * @card: card structure
+ *
+ * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
+ * interrupts to cleanup our TX ring) and returns sent packets to the stack
+ * by freeing them
+ */
+static void
+spider_net_cleanup_tx_ring(struct spider_net_card *card)
+{
+ if ( (spider_net_release_tx_chain(card, 0)) &&
+ (card->netdev->flags & IFF_UP) ) {
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
+ }
}
/**
@@ -726,16 +671,22 @@ out:
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;
+ char addr_for_crc[ETH_ALEN] = { 0, };
+ int i, bit;
- crc = crc32_be(~0, addr, netdev->addr_len);
+ for (i = 0; i < ETH_ALEN * 8; i++) {
+ bit = (addr[i / 8] >> (i % 8)) & 1;
+ addr_for_crc[ETH_ALEN - 1 - i / 8] += bit << (7 - (i % 8));
+ }
+
+ crc = crc32_be(~0, addr_for_crc, netdev->addr_len);
hash = (crc >> 27);
hash <<= 3;
hash |= crc & 7;
+ hash &= 0xff;
return hash;
}
@@ -821,9 +772,11 @@ spider_net_stop(struct net_device *netdev)
{
struct spider_net_card *card = netdev_priv(netdev);
+ tasklet_kill(&card->rxram_full_tl);
netif_poll_disable(netdev);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+ del_timer_sync(&card->tx_timer);
/* disable/mask all interrupts */
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
@@ -872,13 +825,15 @@ spider_net_get_next_tx_descr(struct spider_net_card *card)
* @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.
+ * depending on hardware checksum settings.
*/
static void
spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
struct sk_buff *skb)
{
+ /* make sure the other fields in the descriptor are written */
+ wmb();
+
if (skb->ip_summed != CHECKSUM_HW) {
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
return;
@@ -887,14 +842,13 @@ spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
/* is packet ip?
* if yes: tcp? udp? */
if (skb->protocol == htons(ETH_P_IP)) {
- if (skb->nh.iph->protocol == IPPROTO_TCP) {
+ if (skb->nh.iph->protocol == IPPROTO_TCP)
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
- } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ 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 */
+ 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;
- }
}
}
@@ -914,23 +868,22 @@ 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))
+ dma_addr_t buf;
+
+ buf = pci_map_single(card->pdev, skb->data,
+ skb->len, PCI_DMA_BIDIRECTIONAL);
+ if (buf == DMA_ERROR_CODE) {
+ if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
return -ENOMEM;
}
+ descr->buf_addr = buf;
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;
@@ -972,17 +925,12 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
struct spider_net_descr *descr;
int result;
- descr = spider_net_get_next_tx_descr(card);
+ spider_net_release_tx_chain(card, 0);
- if (!descr) {
- netif_stop_queue(netdev);
+ descr = spider_net_get_next_tx_descr(card);
- descr = spider_net_get_next_tx_descr(card);
- if (!descr)
- goto error;
- else
- netif_start_queue(netdev);
- }
+ if (!descr)
+ goto error;
result = spider_net_prepare_tx_descr(card, descr, skb);
if (result)
@@ -990,19 +938,25 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
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);
+ SPIDER_NET_DESCR_CARDOWNED) {
+ /* make sure the current descriptor is in memory. Then
+ * kicking it on again makes sense, if the previous is not
+ * card-owned anymore. Check the previous descriptor twice
+ * to omit an mb() in heavy traffic cases */
+ mb();
+ if (spider_net_get_descr_status(descr->prev) !=
+ SPIDER_NET_DESCR_CARDOWNED)
+ spider_net_kick_tx_dma(card, descr);
+ }
+
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
return NETDEV_TX_OK;
error:
card->netdev_stats.tx_dropped++;
- return NETDEV_TX_LOCKED;
+ return NETDEV_TX_BUSY;
}
/**
@@ -1027,6 +981,7 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
* spider_net_pass_skb_up - takes an skb from a descriptor and passes it on
* @descr: descriptor to process
* @card: card structure
+ * @napi: whether caller is in NAPI context
*
* returns 1 on success, 0 if no packet was passed to the stack
*
@@ -1035,7 +990,7 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
*/
static int
spider_net_pass_skb_up(struct spider_net_descr *descr,
- struct spider_net_card *card)
+ struct spider_net_card *card, int napi)
{
struct sk_buff *skb;
struct net_device *netdev;
@@ -1046,22 +1001,20 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
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,
+ /* unmap descriptor */
+ pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
/* the cases we'll throw away the packet immediately */
- if (data_error & SPIDER_NET_DESTROY_RX_FLAGS)
+ if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
+ if (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);
return 0;
+ }
+ skb = descr->skb;
skb->dev = netdev;
skb_put(skb, descr->valid_size);
@@ -1073,14 +1026,14 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
/* checksum offload */
if (card->options.rx_csum) {
- if ( (data_status & SPIDER_NET_DATA_STATUS_CHK_MASK) &&
- (!(data_error & SPIDER_NET_DATA_ERROR_CHK_MASK)) )
+ if ( ( (data_status & SPIDER_NET_DATA_STATUS_CKSUM_MASK) ==
+ SPIDER_NET_DATA_STATUS_CKSUM_MASK) &&
+ !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
- } else {
+ } else
skb->ip_summed = CHECKSUM_NONE;
- }
if (data_status & SPIDER_NET_VLAN_PACKET) {
/* further enhancements: HW-accel VLAN
@@ -1089,7 +1042,10 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
/* pass skb up to stack */
- netif_receive_skb(skb);
+ if (napi)
+ netif_receive_skb(skb);
+ else
+ netif_rx_ni(skb);
/* update netdevice statistics */
card->netdev_stats.rx_packets++;
@@ -1099,16 +1055,18 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
/**
- * spider_net_decode_descr - processes an rx descriptor
+ * spider_net_decode_one_descr - processes an rx descriptor
* @card: card structure
+ * @napi: whether caller is in NAPI context
*
* 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
+ * the packet up to the stack. This function is called in softirq
+ * context, e.g. either bottom half from interrupt or NAPI polling context
*/
static int
-spider_net_decode_one_descr(struct spider_net_card *card)
+spider_net_decode_one_descr(struct spider_net_card *card, int napi)
{
enum spider_net_descr_status status;
struct spider_net_descr *descr;
@@ -1122,17 +1080,19 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if (status == SPIDER_NET_DESCR_CARDOWNED) {
/* nothing in the descriptor yet */
- return 0;
+ result=0;
+ goto out;
}
if (status == SPIDER_NET_DESCR_NOT_IN_USE) {
- /* not initialized yet, I bet chain->tail == chain->head
- * and the ring is empty */
+ /* not initialized yet, the ring must be empty */
spider_net_refill_rx_chain(card);
- return 0;
+ spider_net_enable_rxdmac(card);
+ result=0;
+ goto out;
}
- /* descriptor definitively used -- move on head */
+ /* descriptor definitively used -- move on tail */
chain->tail = descr->next;
result = 0;
@@ -1143,6 +1103,9 @@ spider_net_decode_one_descr(struct spider_net_card *card)
pr_err("%s: dropping RX descriptor with state %d\n",
card->netdev->name, status);
card->netdev_stats.rx_dropped++;
+ pci_unmap_single(card->pdev, descr->buf_addr,
+ SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ dev_kfree_skb_irq(descr->skb);
goto refill;
}
@@ -1155,12 +1118,13 @@ spider_net_decode_one_descr(struct spider_net_card *card)
}
/* ok, we've got a packet in descr */
- result = spider_net_pass_skb_up(descr, card);
+ result = spider_net_pass_skb_up(descr, card, napi);
refill:
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
/* change the descriptor state: */
- spider_net_refill_rx_chain(card);
-
+ if (!napi)
+ spider_net_refill_rx_chain(card);
+out:
return result;
}
@@ -1186,7 +1150,7 @@ spider_net_poll(struct net_device *netdev, int *budget)
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
- if (spider_net_decode_one_descr(card)) {
+ if (spider_net_decode_one_descr(card, 1)) {
packets_done++;
packets_to_do--;
} else {
@@ -1198,6 +1162,7 @@ spider_net_poll(struct net_device *netdev, int *budget)
netdev->quota -= packets_done;
*budget -= packets_done;
+ spider_net_refill_rx_chain(card);
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
@@ -1342,6 +1307,24 @@ spider_net_enable_txdmac(struct spider_net_card *card)
}
/**
+ * spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
+ * @card: card structure
+ *
+ * spider_net_handle_rxram_full empties the RX ring so that spider can put
+ * more packets in it and empty its RX RAM. This is called in bottom half
+ * context
+ */
+static void
+spider_net_handle_rxram_full(struct spider_net_card *card)
+{
+ while (spider_net_decode_one_descr(card, 0))
+ ;
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+ netif_rx_schedule(card->netdev);
+}
+
+/**
* spider_net_handle_error_irq - handles errors raised by an interrupt
* @card: card structure
* @status_reg: interrupt status register 0 (GHIINT0STS)
@@ -1449,17 +1432,21 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
switch (i)
{
case SPIDER_NET_GTMFLLINT:
- if (netif_msg_intr(card))
+ if (netif_msg_intr(card) && net_ratelimit())
pr_err("Spider TX RAM full\n");
show_error = 0;
break;
+ case SPIDER_NET_GRFDFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFCFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFBFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFAFLLINT: /* fallthrough */
case SPIDER_NET_GRMFLLINT:
- if (netif_msg_intr(card))
+ if (netif_msg_intr(card) && net_ratelimit())
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);
+ "might be discarded!\n");
+ spider_net_rx_irq_off(card);
+ tasklet_schedule(&card->rxram_full_tl);
+ show_error = 0;
break;
/* case SPIDER_NET_GTMSHTINT: problem, print a message */
@@ -1467,10 +1454,6 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
/* 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 */
@@ -1482,6 +1465,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
"restarting DMAC %c.\n",
'D'+i-SPIDER_NET_GDDDCEINT);
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
show_error = 0;
break;
@@ -1492,6 +1476,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDAINVDINT:
/* could happen when rx chain is full */
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
show_error = 0;
break;
@@ -1580,17 +1565,13 @@ spider_net_interrupt(int irq, void *ptr, struct pt_regs *regs)
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);
+ if (status_reg & SPIDER_NET_ERRINT )
+ spider_net_handle_error_irq(card, status_reg);
/* clear interrupt sources */
spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
@@ -1831,34 +1812,40 @@ spider_net_setup_phy(struct spider_net_card *card)
/**
* spider_net_download_firmware - loads firmware into the adapter
* @card: card structure
- * @firmware: firmware pointer
+ * @firmware_ptr: pointer to firmware data
*
- * spider_net_download_firmware loads the firmware opened by
- * spider_net_init_firmware into the adapter.
+ * spider_net_download_firmware loads the firmware data into the
+ * adapter. It assumes the length etc. to be allright.
*/
-static void
+static int
spider_net_download_firmware(struct spider_net_card *card,
- const struct firmware *firmware)
+ u8 *firmware_ptr)
{
int sequencer, i;
- u32 *fw_ptr = (u32 *)firmware->data;
+ u32 *fw_ptr = (u32 *)firmware_ptr;
/* stop sequencers */
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_STOP_SEQ_VALUE);
- for (sequencer = 0; sequencer < 6; sequencer++) {
+ for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+ sequencer++) {
spider_net_write_reg(card,
SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
- for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, *fw_ptr);
fw_ptr++;
}
}
+ if (spider_net_read_reg(card, SPIDER_NET_GSINIT))
+ return -EIO;
+
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_RUN_SEQ_VALUE);
+
+ return 0;
}
/**
@@ -1890,31 +1877,53 @@ spider_net_download_firmware(struct spider_net_card *card,
static int
spider_net_init_firmware(struct spider_net_card *card)
{
- const struct firmware *firmware;
- int err = -EIO;
+ struct firmware *firmware = NULL;
+ struct device_node *dn;
+ u8 *fw_prop = NULL;
+ int err = -ENOENT;
+ int fw_size;
+
+ if (request_firmware((const struct firmware **)&firmware,
+ SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
+ if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
+ netif_msg_probe(card) ) {
+ pr_err("Incorrect size of spidernet firmware in " \
+ "filesystem. Looking in host firmware...\n");
+ goto try_host_fw;
+ }
+ err = spider_net_download_firmware(card, firmware->data);
- 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;
- }
+ release_firmware(firmware);
+ if (err)
+ goto try_host_fw;
- 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;
+ goto done;
}
- spider_net_download_firmware(card, firmware);
+try_host_fw:
+ dn = pci_device_to_OF_node(card->pdev);
+ if (!dn)
+ goto out_err;
- err = 0;
-out:
- release_firmware(firmware);
+ fw_prop = (u8 *)get_property(dn, "firmware", &fw_size);
+ if (!fw_prop)
+ goto out_err;
+
+ if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
+ netif_msg_probe(card) ) {
+ pr_err("Incorrect size of spidernet firmware in " \
+ "host firmware\n");
+ goto done;
+ }
+ err = spider_net_download_firmware(card, fw_prop);
+
+done:
+ return err;
+out_err:
+ if (netif_msg_probe(card))
+ pr_err("Couldn't find spidernet firmware in filesystem " \
+ "or host firmware\n");
return err;
}
@@ -1934,10 +1943,11 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
SPIDER_NET_CKRCTRL_RUN_VALUE);
/* empty sequencer data */
- for (sequencer = 0; sequencer < 6; sequencer++) {
+ for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+ sequencer++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, 0x0);
- for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, 0x0);
}
@@ -2061,7 +2071,15 @@ spider_net_setup_netdev(struct spider_net_card *card)
SET_NETDEV_DEV(netdev, &card->pdev->dev);
pci_set_drvdata(card->pdev, netdev);
- spin_lock_init(&card->intmask_lock);
+
+ atomic_set(&card->tx_chain_release,0);
+ card->rxram_full_tl.data = (unsigned long) card;
+ card->rxram_full_tl.func =
+ (void (*)(unsigned long)) spider_net_handle_rxram_full;
+ init_timer(&card->tx_timer);
+ card->tx_timer.function =
+ (void (*)(unsigned long)) spider_net_cleanup_tx_ring;
+ card->tx_timer.data = (unsigned long) card;
netdev->irq = card->pdev->irq;
card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 22b2f2347351..5922b529a048 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -33,25 +33,32 @@ extern struct ethtool_ops spider_net_ethtool_ops;
extern char spider_net_driver_name[];
-#define SPIDER_NET_MAX_MTU 2308
+#define SPIDER_NET_MAX_FRAME 2312
+#define SPIDER_NET_MAX_MTU 2294
#define SPIDER_NET_MIN_MTU 64
#define SPIDER_NET_RXBUF_ALIGN 128
-#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 256
#define SPIDER_NET_RX_DESCRIPTORS_MIN 16
-#define SPIDER_NET_RX_DESCRIPTORS_MAX 256
+#define SPIDER_NET_RX_DESCRIPTORS_MAX 512
-#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 256
#define SPIDER_NET_TX_DESCRIPTORS_MIN 16
-#define SPIDER_NET_TX_DESCRIPTORS_MAX 256
+#define SPIDER_NET_TX_DESCRIPTORS_MAX 512
+
+#define SPIDER_NET_TX_TIMER 20
#define SPIDER_NET_RX_CSUM_DEFAULT 1
-#define SPIDER_NET_WATCHDOG_TIMEOUT 5*HZ
-#define SPIDER_NET_NAPI_WEIGHT 64
+#define SPIDER_NET_WATCHDOG_TIMEOUT 50*HZ
+#define SPIDER_NET_NAPI_WEIGHT 64
-#define SPIDER_NET_FIRMWARE_LEN 1024
+#define SPIDER_NET_FIRMWARE_SEQS 6
+#define SPIDER_NET_FIRMWARE_SEQWORDS 1024
+#define SPIDER_NET_FIRMWARE_LEN (SPIDER_NET_FIRMWARE_SEQS * \
+ SPIDER_NET_FIRMWARE_SEQWORDS * \
+ sizeof(u32))
#define SPIDER_NET_FIRMWARE_NAME "spider_fw.bin"
/** spider_net SMMIO registers */
@@ -142,14 +149,12 @@ extern char spider_net_driver_name[];
/** 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
+/** interrupt mask registers */
+#define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe2c7
+#define SPIDER_NET_INT1_MASK_VALUE 0xffff7ff7
/* no MAC aborts -> auto retransmission */
-#define SPIDER_NET_INT2_MASK_VALUE 0xfffffff1
+#define SPIDER_NET_INT2_MASK_VALUE 0xffef7ff1
-/* 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 */
@@ -168,7 +173,7 @@ extern char spider_net_driver_name[];
#if 0
#define SPIDER_NET_WOL_VALUE 0x00000000
#endif
-#define SPIDER_NET_IPSECINIT_VALUE 0x00f000f8
+#define SPIDER_NET_IPSECINIT_VALUE 0x6f716f71
/* pause frames: automatic, no upper retransmission count */
/* outside loopback mode: ETOMOD signal dont matter, not connected */
@@ -318,6 +323,10 @@ enum spider_net_int2_status {
#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) | \
(1 << SPIDER_NET_GRMFLLINT) )
+#define SPIDER_NET_ERRINT ( 0xffffffff & \
+ (~SPIDER_NET_TXINT) & \
+ (~SPIDER_NET_RXINT) )
+
#define SPIDER_NET_GPREXEC 0x80000000
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
@@ -358,9 +367,6 @@ enum spider_net_int2_status {
/* 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 */
@@ -373,9 +379,9 @@ enum spider_net_descr_status {
struct spider_net_descr {
/* as defined by the hardware */
- dma_addr_t buf_addr;
+ u32 buf_addr;
u32 buf_size;
- dma_addr_t next_descr_addr;
+ u32 next_descr_addr;
u32 dmac_cmd_status;
u32 result_size;
u32 valid_size; /* all zeroes for tx */
@@ -384,7 +390,7 @@ struct spider_net_descr {
/* used in the driver */
struct sk_buff *skb;
- dma_addr_t bus_addr;
+ u32 bus_addr;
struct spider_net_descr *next;
struct spider_net_descr *prev;
} __attribute__((aligned(32)));
@@ -396,21 +402,21 @@ struct spider_net_descr_chain {
};
/* 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_RX_IPCHK 29
+#define SPIDER_NET_RX_TCPCHK 28
#define SPIDER_NET_VLAN_PACKET 21
+#define SPIDER_NET_DATA_STATUS_CKSUM_MASK ( (1 << SPIDER_NET_RX_IPCHK) | \
+ (1 << SPIDER_NET_RX_TCPCHK) )
/* 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)
+#define SPIDER_NET_RX_IPCHKERR 27
+#define SPIDER_NET_RX_RXTCPCHKERR 28
+
+#define SPIDER_NET_DATA_ERR_CKSUM_MASK (1 << SPIDER_NET_RX_IPCHKERR)
-/* the cases we don't pass the packet to the stack */
-#define SPIDER_NET_DESTROY_RX_FLAGS 0x70138000
+/* the cases we don't pass the packet to the stack.
+ * 701b8000 would be correct, but every packets gets that flag */
+#define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000
#define SPIDER_NET_DESCR_SIZE 32
@@ -445,13 +451,16 @@ struct spider_net_card {
struct spider_net_descr_chain tx_chain;
struct spider_net_descr_chain rx_chain;
- spinlock_t chain_lock;
+ atomic_t rx_chain_refill;
+ atomic_t tx_chain_release;
struct net_device_stats netdev_stats;
struct spider_net_options options;
spinlock_t intmask_lock;
+ struct tasklet_struct rxram_full_tl;
+ struct timer_list tx_timer;
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index d42e60ba74ce..a5bb0b7633af 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -113,6 +113,23 @@ spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
return 0;
}
+static uint32_t
+spider_net_ethtool_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
+
struct ethtool_ops spider_net_ethtool_ops = {
.get_settings = spider_net_ethtool_get_settings,
.get_drvinfo = spider_net_ethtool_get_drvinfo,
@@ -122,5 +139,7 @@ struct ethtool_ops spider_net_ethtool_ops = {
.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,
+ .get_tx_csum = spider_net_ethtool_get_tx_csum,
+ .set_tx_csum = spider_net_ethtool_set_tx_csum,
};
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 5c8fcd40ef4d..01bdb2334058 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -389,7 +389,7 @@ static int __init lance_probe( struct net_device *dev)
dev->stop = &lance_close;
dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &set_multicast_list;
- dev->set_mac_address = 0;
+ dev->set_mac_address = NULL;
// KLUDGE -- REMOVE ME
set_bit(__LINK_STATE_PRESENT, &dev->state);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index eb86b059809b..f2d1dafde087 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.47"
-#define DRV_MODULE_RELDATE "Dec 28, 2005"
+#define DRV_MODULE_VERSION "3.48"
+#define DRV_MODULE_RELDATE "Jan 16, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -1325,10 +1325,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
tw32(0x7d00, val);
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
- tg3_nvram_lock(tp);
+ int err;
+
+ err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
- tw32_f(NVRAM_SWARB, SWARB_REQ_CLR0);
- tg3_nvram_unlock(tp);
+ if (!err)
+ tg3_nvram_unlock(tp);
}
}
@@ -4193,14 +4195,19 @@ static int tg3_nvram_lock(struct tg3 *tp)
if (tp->tg3_flags & TG3_FLAG_NVRAM) {
int i;
- tw32(NVRAM_SWARB, SWARB_REQ_SET1);
- for (i = 0; i < 8000; i++) {
- if (tr32(NVRAM_SWARB) & SWARB_GNT1)
- break;
- udelay(20);
+ if (tp->nvram_lock_cnt == 0) {
+ tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+ for (i = 0; i < 8000; i++) {
+ if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+ break;
+ udelay(20);
+ }
+ if (i == 8000) {
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
+ return -ENODEV;
+ }
}
- if (i == 8000)
- return -ENODEV;
+ tp->nvram_lock_cnt++;
}
return 0;
}
@@ -4208,8 +4215,12 @@ static int tg3_nvram_lock(struct tg3 *tp)
/* tp->lock is held. */
static void tg3_nvram_unlock(struct tg3 *tp)
{
- if (tp->tg3_flags & TG3_FLAG_NVRAM)
- tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ if (tp->tg3_flags & TG3_FLAG_NVRAM) {
+ if (tp->nvram_lock_cnt > 0)
+ tp->nvram_lock_cnt--;
+ if (tp->nvram_lock_cnt == 0)
+ tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ }
}
/* tp->lock is held. */
@@ -4320,8 +4331,13 @@ static int tg3_chip_reset(struct tg3 *tp)
void (*write_op)(struct tg3 *, u32, u32);
int i;
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
tg3_nvram_lock(tp);
+ /* No matching tg3_nvram_unlock() after this because
+ * chip reset below will undo the nvram lock.
+ */
+ tp->nvram_lock_cnt = 0;
+ }
/*
* We must avoid the readl() that normally takes place.
@@ -4717,6 +4733,10 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
(offset == RX_CPU_BASE ? "RX" : "TX"));
return -ENODEV;
}
+
+ /* Clear firmware's nvram arbitration. */
+ if (tp->tg3_flags & TG3_FLAG_NVRAM)
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
return 0;
}
@@ -4736,7 +4756,7 @@ struct fw_info {
static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base,
int cpu_scratch_size, struct fw_info *info)
{
- int err, i;
+ int err, lock_err, i;
void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE &&
@@ -4755,9 +4775,10 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
/* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu.
*/
- tg3_nvram_lock(tp);
+ lock_err = tg3_nvram_lock(tp);
err = tg3_halt_cpu(tp, cpu_base);
- tg3_nvram_unlock(tp);
+ if (!lock_err)
+ tg3_nvram_unlock(tp);
if (err)
goto out;
@@ -8182,7 +8203,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
data[1] = 1;
}
if (etest->flags & ETH_TEST_FL_OFFLINE) {
- int irq_sync = 0;
+ int err, irq_sync = 0;
if (netif_running(dev)) {
tg3_netif_stop(tp);
@@ -8192,11 +8213,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
tg3_full_lock(tp, irq_sync);
tg3_halt(tp, RESET_KIND_SUSPEND, 1);
- tg3_nvram_lock(tp);
+ err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tg3_halt_cpu(tp, TX_CPU_BASE);
- tg3_nvram_unlock(tp);
+ if (!err)
+ tg3_nvram_unlock(tp);
if (tg3_test_registers(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
@@ -8588,7 +8610,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
tp->tg3_flags |= TG3_FLAG_NVRAM;
- tg3_nvram_lock(tp);
+ if (tg3_nvram_lock(tp)) {
+ printk(KERN_WARNING PFX "%s: Cannot get nvarm lock, "
+ "tg3_nvram_init failed.\n", tp->dev->name);
+ return;
+ }
tg3_enable_nvram_access(tp);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
@@ -8686,7 +8712,9 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
if (offset > NVRAM_ADDR_MSK)
return -EINVAL;
- tg3_nvram_lock(tp);
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
tg3_enable_nvram_access(tp);
@@ -8785,10 +8813,6 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
offset = offset + (pagesize - page_off);
- /* Nvram lock released by tg3_nvram_read() above,
- * so need to get it again.
- */
- tg3_nvram_lock(tp);
tg3_enable_nvram_access(tp);
/*
@@ -8925,7 +8949,9 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
else {
u32 grc_mode;
- tg3_nvram_lock(tp);
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
tg3_enable_nvram_access(tp);
if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 890e1635996b..e8243305f0e8 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2275,6 +2275,7 @@ struct tg3 {
dma_addr_t stats_mapping;
struct work_struct reset_task;
+ int nvram_lock_cnt;
u32 nvram_size;
u32 nvram_pagesize;
u32 nvram_jedecnum;
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 125ed00e95a5..c67c91251d04 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1564,7 +1564,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
dev->dev_addr, 6);
}
#endif
-#if defined(__i386__) /* Patch up x86 BIOS bug. */
+#if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */
if (last_irq)
irq = last_irq;
#endif
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 1a4316336256..983981666800 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -1689,9 +1689,9 @@ 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_param(debug, int, 0644);
+module_param(mode, int, 0);
+module_param(cr6set, int, 0);
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");
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 82c6b757d306..c2d5907dc8e0 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -791,7 +791,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
#endif
if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) {
- dev->features |= NETIF_F_HW_CSUM;
+ dev->features |= NETIF_F_IP_CSUM;
}
ret = register_netdev(dev);
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 2b948ea397d5..40926d779161 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -641,7 +641,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/
spin_lock_irqsave(&sc->lmc_lock, flags);
if(sc->check != 0xBEAFCAFE){
- printk("LMC: Corrupt net_device stuct, breaking out\n");
+ printk("LMC: Corrupt net_device struct, breaking out\n");
spin_unlock_irqrestore(&sc->lmc_lock, flags);
return;
}
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 52f26b9c69d2..931cbdf6d791 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -689,7 +689,7 @@ static void cpc_tty_rx_work(void * data)
}
}
cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
- kfree(buf);
+ kfree((void *)buf);
buf = cpc_tty->buf_rx.first;
flg_rx = 1;
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 036adc4f8ba7..22e794071cf4 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -329,9 +329,9 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
struct _dlci_stat
{
- short dlci __attribute__((packed));
- char flags __attribute__((packed));
-};
+ short dlci;
+ char flags;
+} __attribute__((packed));
struct _frad_stat
{
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index bdf672c48182..9c3ccc669143 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -515,11 +515,6 @@ static int x25_asy_close(struct net_device *dev)
return 0;
}
-static int x25_asy_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
@@ -573,6 +568,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
sl->tty = tty;
tty->disc_data = sl;
+ tty->receive_room = 65536;
if (tty->driver->flush_buffer) {
tty->driver->flush_buffer(tty);
}
@@ -779,7 +775,6 @@ static struct tty_ldisc x25_ldisc = {
.close = x25_asy_close_tty,
.ioctl = x25_asy_ioctl,
.receive_buf = x25_asy_receive_buf,
- .receive_room = x25_asy_receive_room,
.write_wakeup = x25_asy_write_wakeup,
};
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index b03feae459fc..7caa8dc88a58 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -127,13 +127,6 @@ static int __init do_wd_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init wd_probe(int unit)
{
@@ -538,6 +531,13 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 24f7967aab67..233a4f608084 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -24,10 +24,6 @@ config NET_RADIO
the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
- Some user-level drivers for scarab devices which don't require
- special kernel support are available from
- <ftp://shadow.cabi.net/pub/Linux/>.
-
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)"
@@ -160,7 +156,7 @@ config IPW2100
<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),
+ inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called ipw2100.ko.
@@ -213,7 +209,7 @@ config IPW2200
<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),
+ inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called ipw2200.ko.
@@ -243,7 +239,7 @@ config IPW2200_DEBUG
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
- depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
+ depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN)
---help---
This is the standard Linux driver to support Cisco/Aironet ISA and
PCI 802.11 wireless cards.
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index ee866fd6957d..a4c7ae94614d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5668,13 +5668,13 @@ static int airo_set_freq(struct net_device *dev,
int channel = fwrq->m;
/* We should do a better check than that,
* based on the card capability !!! */
- if((channel < 1) || (channel > 16)) {
+ if((channel < 1) || (channel > 14)) {
printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
rc = -EINVAL;
} else {
readConfigRid(local, 1);
/* Yes ! We can set it !!! */
- local->config.channelSet = (u16)(channel - 1);
+ local->config.channelSet = (u16) channel;
set_bit (FLAG_COMMIT, &local->flags);
}
}
@@ -5692,6 +5692,7 @@ static int airo_get_freq(struct net_device *dev,
{
struct airo_info *local = dev->priv;
StatusRid status_rid; /* Card status info */
+ int ch;
readConfigRid(local, 1);
if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
@@ -5699,16 +5700,14 @@ static int airo_get_freq(struct net_device *dev,
else
readStatusRid(local, &status_rid, 1);
-#ifdef WEXT_USECHANNELS
- fwrq->m = ((int)status_rid.channel) + 1;
- fwrq->e = 0;
-#else
- {
- int f = (int)status_rid.channel;
- fwrq->m = frequency_list[f] * 100000;
+ ch = (int)status_rid.channel;
+ if((ch > 0) && (ch < 15)) {
+ fwrq->m = frequency_list[ch - 1] * 100000;
fwrq->e = 1;
+ } else {
+ fwrq->m = ch;
+ fwrq->e = 0;
}
-#endif
return 0;
}
@@ -5783,7 +5782,7 @@ static int airo_get_essid(struct net_device *dev,
/* If none, we may want to get the one that was set */
/* Push it out ! */
- dwrq->length = status_rid.SSIDlen + 1;
+ dwrq->length = status_rid.SSIDlen;
dwrq->flags = 1; /* active */
return 0;
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index e4729ddf29fd..98a76f10a0f7 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1407,6 +1407,17 @@ static int atmel_close(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
+ /* Send event to userspace that we are disassociating */
+ if (priv->station_state == STATION_STATE_READY) {
+ union iwreq_data wrqu;
+
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+ }
+
atmel_enter_state(priv, STATION_STATE_DOWN);
if (priv->bus_type == BUS_TYPE_PCCARD)
@@ -1707,11 +1718,11 @@ static int atmel_get_essid(struct net_device *dev,
if (priv->new_SSID_size != 0) {
memcpy(extra, priv->new_SSID, priv->new_SSID_size);
extra[priv->new_SSID_size] = '\0';
- dwrq->length = priv->new_SSID_size + 1;
+ dwrq->length = priv->new_SSID_size;
} else {
memcpy(extra, priv->SSID, priv->SSID_size);
extra[priv->SSID_size] = '\0';
- dwrq->length = priv->SSID_size + 1;
+ dwrq->length = priv->SSID_size;
}
dwrq->flags = !priv->connect_to_any_BSS; /* active */
@@ -1780,10 +1791,10 @@ static int atmel_set_encode(struct net_device *dev,
priv->wep_is_on = 1;
priv->exclude_unencrypted = 1;
if (priv->wep_key_len[index] > 5) {
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
priv->encryption_level = 2;
} else {
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
priv->encryption_level = 1;
}
}
@@ -1853,6 +1864,181 @@ static int atmel_get_encode(struct net_device *dev,
return 0;
}
+static int atmel_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int idx, key_len;
+
+ /* Determine and validate the key index */
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else
+ idx = priv->default_key;
+
+ if ((encoding->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ priv->wep_is_on = 0;
+ priv->encryption_level = 0;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
+ }
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ priv->default_key = idx;
+
+ /* Set the requested key */
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_NONE:
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > 5) {
+ priv->wep_key_len[idx] = 13;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
+ priv->encryption_level = 2;
+ } else if (ext->key_len > 0) {
+ priv->wep_key_len[idx] = 5;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
+ priv->encryption_level = 1;
+ } else {
+ return -EINVAL;
+ }
+ priv->wep_is_on = 1;
+ memset(priv->wep_keys[idx], 0, 13);
+ key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
+ memcpy(priv->wep_keys[idx], ext->key, key_len);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return -EINPROGRESS;
+}
+
+static int atmel_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int idx, max_key_len;
+
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else
+ idx = priv->default_key;
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ if (!priv->wep_is_on) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ encoding->flags |= IW_ENCODE_DISABLED;
+ } else {
+ if (priv->encryption_level > 0)
+ ext->alg = IW_ENCODE_ALG_WEP;
+ else
+ return -EINVAL;
+
+ ext->key_len = priv->wep_key_len[idx];
+ memcpy(ext->key, priv->wep_keys[idx], ext->key_len);
+ encoding->flags |= IW_ENCODE_ENABLED;
+ }
+
+ return 0;
+}
+
+static int atmel_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_param *param = &wrqu->param;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ /*
+ * atmel does not use these parameters
+ */
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ priv->exclude_unencrypted = param->value ? 1 : 0;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG: {
+ if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+ priv->exclude_unencrypted = 1;
+ } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ priv->exclude_unencrypted = 0;
+ } else
+ return -EINVAL;
+ break;
+ }
+
+ case IW_AUTH_WPA_ENABLED:
+ /* Silently accept disable of WPA */
+ if (param->value > 0)
+ return -EOPNOTSUPP;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return -EINPROGRESS;
+}
+
+static int atmel_get_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_param *param = &wrqu->param;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_DROP_UNENCRYPTED:
+ param->value = priv->exclude_unencrypted;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if (priv->exclude_unencrypted == 1)
+ param->value = IW_AUTH_ALG_SHARED_KEY;
+ else
+ param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ param->value = 0;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
static int atmel_get_name(struct net_device *dev,
struct iw_request_info *info,
char *cwrq,
@@ -2289,13 +2475,15 @@ static int atmel_set_wap(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
int i;
- static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 };
+ static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned long flags;
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
- if (memcmp(bcast, awrq->sa_data, 6) == 0) {
+ if (!memcmp(any, awrq->sa_data, 6) ||
+ !memcmp(off, awrq->sa_data, 6)) {
del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
atmel_scan(priv, 1);
@@ -2378,6 +2566,15 @@ static const iw_handler atmel_handler[] =
(iw_handler) atmel_get_encode, /* SIOCGIWENCODE */
(iw_handler) atmel_set_power, /* SIOCSIWPOWER */
(iw_handler) atmel_get_power, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWGENIE */
+ (iw_handler) NULL, /* SIOCGIWGENIE */
+ (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
};
static const iw_handler atmel_private_handler[] =
@@ -2924,6 +3121,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
u16 ass_id = le16_to_cpu(ass_resp->ass_id);
u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
+ union iwreq_data wrqu;
+
if (frame_len < 8 + rates_len)
return;
@@ -2954,6 +3153,14 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
priv->station_is_associated = 1;
priv->station_was_associated = 1;
atmel_enter_state(priv, STATION_STATE_READY);
+
+ /* Send association event to userspace */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+
return;
}
@@ -3632,6 +3839,7 @@ static int reset_atmel_card(struct net_device *dev)
struct atmel_private *priv = netdev_priv(dev);
u8 configuration;
+ int old_state = priv->station_state;
/* data to add to the firmware names, in priority order
this implemenents firmware versioning */
@@ -3792,6 +4000,17 @@ static int reset_atmel_card(struct net_device *dev)
else
build_wep_mib(priv);
+ if (old_state == STATION_STATE_READY)
+ {
+ union iwreq_data wrqu;
+
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+ }
+
return 1;
}
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 56f41c714d38..c8f6286dd35f 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -26,11 +26,25 @@ config HOSTAP_FIRMWARE
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.
+ download. This option by itself only enables downloading to the
+ volatile memory, i.e. the card RAM. This option is required to
+ support cards that don't have firmware in flash, such as D-Link
+ DWL-520 rev E and D-Link DWL-650 rev P.
- Firmware image downloading needs user space tool, prism2_srec. It is
- available from http://hostap.epitest.fi/.
+ Firmware image downloading needs a user space tool, prism2_srec.
+ It is available from http://hostap.epitest.fi/.
+
+config HOSTAP_FIRMWARE_NVRAM
+ bool "Support for non-volatile firmware download"
+ depends on HOSTAP_FIRMWARE
+ ---help---
+ Allow Host AP driver to write firmware images to the non-volatile
+ card memory, i.e. flash memory that survives power cycling.
+ Enable this option if you want to be able to change card firmware
+ permanently.
+
+ Firmware image downloading needs a 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"
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
index 353ccb93134b..b8e41a702c00 100644
--- a/drivers/net/wireless/hostap/Makefile
+++ b/drivers/net/wireless/hostap/Makefile
@@ -1,4 +1,5 @@
-hostap-y := hostap_main.o
+hostap-y := hostap_80211_rx.o hostap_80211_tx.o hostap_ap.o hostap_info.o \
+ hostap_ioctl.o hostap_main.o hostap_proc.o
obj-$(CONFIG_HOSTAP) += hostap.o
obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index 5fac89b8ce3a..5e63765219fe 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -1,6 +1,15 @@
#ifndef HOSTAP_H
#define HOSTAP_H
+#include <linux/ethtool.h>
+
+#include "hostap_wlan.h"
+#include "hostap_ap.h"
+
+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]))
+
/* hostap.c */
extern struct proc_dir_entry *hostap_proc;
@@ -40,6 +49,26 @@ 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);
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked);
+int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove);
+
+
+/* hostap_ap.c */
+
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
+void ap_control_kickall(struct ap_data *ap);
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt);
+int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist);
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param);
/* hostap_proc.c */
@@ -54,4 +83,12 @@ void hostap_info_init(local_info_t *local);
void hostap_info_process(local_info_t *local, struct sk_buff *skb);
+/* hostap_ioctl.c */
+
+extern const struct iw_handler_def hostap_iw_handler_def;
+extern struct ethtool_ops prism2_ethtool_ops;
+
+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+
#endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index bf506f50d722..1fc72fe511e9 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -1,6 +1,9 @@
#ifndef HOSTAP_80211_H
#define HOSTAP_80211_H
+#include <linux/types.h>
+#include <net/ieee80211_crypt.h>
+
struct hostap_ieee80211_mgmt {
u16 frame_control;
u16 duration;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index ffac50899454..7e04dc94b3bc 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1,7 +1,18 @@
#include <linux/etherdevice.h>
+#include <net/ieee80211_crypt.h>
#include "hostap_80211.h"
#include "hostap.h"
+#include "hostap_ap.h"
+
+/* 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) */
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
@@ -435,7 +446,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
}
-static inline int
+static int
hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, u16 type,
u16 stype)
@@ -499,7 +510,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
/* Called only as a tasklet (software IRQ) */
-static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
+static struct net_device *prism2_rx_get_wds(local_info_t *local,
u8 *addr)
{
struct hostap_interface *iface = NULL;
@@ -519,7 +530,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
}
-static inline int
+static int
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
u16 fc, struct net_device **wds)
{
@@ -615,7 +626,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
/* Called only as a tasklet (software IRQ) */
-static inline int
+static int
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
struct ieee80211_crypt_data *crypt)
{
@@ -654,7 +665,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
/* Called only as a tasklet (software IRQ) */
-static inline int
+static int
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
int keyidx, struct ieee80211_crypt_data *crypt)
{
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 9d24f8a38ac5..4a85e63906f1 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,3 +1,18 @@
+#include "hostap_80211.h"
+#include "hostap_common.h"
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
+/* 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) */
+
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
struct ieee80211_hdr_4addr *hdr;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 9da94ab7f05f..753a1de6664b 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -16,6 +16,14 @@
* (8802.11: 5.5)
*/
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL,
DEF_INTS };
module_param_array(other_ap_policy, int, NULL, 0444);
@@ -360,8 +368,7 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
}
-static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac)
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
{
struct mac_entry *entry;
@@ -380,8 +387,7 @@ static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
}
-static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac)
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
{
struct list_head *ptr;
struct mac_entry *entry;
@@ -433,7 +439,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
}
-static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
{
struct list_head *ptr, *n;
struct mac_entry *entry;
@@ -454,8 +460,7 @@ 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)
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac)
{
struct sta_info *sta;
u16 resp;
@@ -486,7 +491,7 @@ static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
-static void ap_control_kickall(struct ap_data *ap)
+void ap_control_kickall(struct ap_data *ap)
{
struct list_head *ptr, *n;
struct sta_info *sta;
@@ -2321,9 +2326,9 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
}
-static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
- struct iw_quality qual[], int buf_size,
- int aplist)
+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;
@@ -2363,7 +2368,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
/* 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)
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
{
struct hostap_interface *iface;
local_info_t *local;
@@ -2608,8 +2613,7 @@ static int prism2_hostapd_sta_clear_stats(struct ap_data *ap,
}
-static int prism2_hostapd(struct ap_data *ap,
- struct prism2_hostapd_param *param)
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param)
{
switch (param->cmd) {
case PRISM2_HOSTAPD_FLUSH:
@@ -3207,8 +3211,8 @@ void hostap_update_rates(local_info_t *local)
}
-static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
- struct ieee80211_crypt_data ***crypt)
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt)
{
struct sta_info *sta;
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 6d00df69c2e3..2fa2452b6b07 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -1,6 +1,8 @@
#ifndef HOSTAP_AP_H
#define HOSTAP_AP_H
+#include "hostap_80211.h"
+
/* AP data structures for STAs */
/* maximum number of frames to buffer per STA */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index 6f4fa9dc308f..01624005d808 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -1,6 +1,9 @@
#ifndef HOSTAP_COMMON_H
#define HOSTAP_COMMON_H
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
#define BIT(x) (1 << (x))
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index 7ed3425d08c1..c090a5aebb58 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -21,15 +21,10 @@
#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 */
+/* Allow kernel configuration to enable non-volatile download support. */
+#ifdef CONFIG_HOSTAP_FIRMWARE_NVRAM
+#define PRISM2_NON_VOLATILE_DOWNLOAD
+#endif
/* Save low-level I/O for debugging. This should not be enabled in normal use.
*/
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index abfae7fedebc..b1f142d9e232 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -253,7 +253,7 @@ static void prism2_clear_cmd_queue(local_info_t *local)
* @dev: pointer to net_device
* @entry: Prism2 command queue entry to be issued
*/
-static inline int hfa384x_cmd_issue(struct net_device *dev,
+static int hfa384x_cmd_issue(struct net_device *dev,
struct hostap_cmd_queue *entry)
{
struct hostap_interface *iface;
@@ -743,7 +743,7 @@ static void prism2_cmd_ev(struct net_device *dev)
}
-static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off)
+static 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;
@@ -1904,7 +1904,7 @@ fail:
* 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)
+static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg)
{
#ifdef EXTRA_FID_READ_TESTS
u16 val, val2, val3;
@@ -2581,7 +2581,7 @@ static void prism2_ev_tick(struct net_device *dev)
/* Called only from hardware IRQ */
-static inline void prism2_check_magic(local_info_t *local)
+static 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
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 5aa998fdf1c4..50f72d831cf4 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -1,5 +1,8 @@
/* Host AP driver Info Frame processing (part of hostap.o module) */
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
/* Called only as a tasklet (software IRQ) */
static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 2617d70bcda9..f3e0ce1ee037 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1,11 +1,13 @@
/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
-#ifdef in_atomic
-/* Get kernel_locked() for in_atomic() */
+#include <linux/types.h>
#include <linux/smp_lock.h>
-#endif
#include <linux/ethtool.h>
+#include <net/ieee80211_crypt.h>
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
{
@@ -3910,7 +3912,7 @@ static void prism2_get_drvinfo(struct net_device *dev,
local->sta_fw_ver & 0xff);
}
-static struct ethtool_ops prism2_ethtool_ops = {
+struct ethtool_ops prism2_ethtool_ops = {
.get_drvinfo = prism2_get_drvinfo
};
@@ -3985,7 +3987,7 @@ static const iw_handler prism2_private_handler[] =
(iw_handler) prism2_ioctl_priv_readmif, /* 3 */
};
-static const struct iw_handler_def hostap_iw_handler_def =
+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),
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 3d2ea61033be..8dd4c4446a64 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -24,6 +24,7 @@
#include <linux/kmod.h>
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
+#include <linux/etherdevice.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <net/ieee80211_crypt.h>
@@ -47,57 +48,6 @@ MODULE_VERSION(PRISM2_VERSION);
#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,
@@ -196,8 +146,8 @@ static inline int prism2_wds_special_addr(u8 *addr)
}
-static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
- int rtnl_locked)
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked)
{
struct net_device *dev;
struct list_head *ptr;
@@ -258,8 +208,8 @@ static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
}
-static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
- int rtnl_locked, int do_not_remove)
+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;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index a0a4cbd4937a..d1d8ce022e63 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -1,5 +1,12 @@
/* /proc routines for Host AP driver */
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <net/ieee80211_crypt.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+
#define PROC_LIMIT (PAGE_SIZE - 80)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index cfd801559492..87a54aa6f4dd 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,10 @@
#ifndef HOSTAP_WLAN_H
#define HOSTAP_WLAN_H
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <net/iw_handler.h>
+
#include "hostap_config.h"
#include "hostap_common.h"
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 44cd3fcd1572..8bf02763b5c7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -411,7 +411,7 @@ 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,
+static void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
const u8 * buf)
{
u32 aligned_addr;
@@ -449,7 +449,7 @@ static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
*buf);
}
-static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
+static void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
u8 * buf)
{
u32 aligned_addr;
@@ -657,7 +657,7 @@ static void printk_buf(int level, const u8 * data, u32 len)
#define MAX_RESET_BACKOFF 10
-static inline void schedule_reset(struct ipw2100_priv *priv)
+static void schedule_reset(struct ipw2100_priv *priv)
{
unsigned long now = get_seconds();
@@ -1130,7 +1130,7 @@ static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv)
write_register(priv->net_dev, IPW_REG_GPIO, reg);
}
-static inline int rf_kill_active(struct ipw2100_priv *priv)
+static int rf_kill_active(struct ipw2100_priv *priv)
{
#define MAX_RF_KILL_CHECKS 5
#define RF_KILL_CHECK_DELAY 40
@@ -2177,7 +2177,7 @@ static const char *frame_types[] = {
};
#endif
-static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv,
+static int ipw2100_alloc_skb(struct ipw2100_priv *priv,
struct ipw2100_rx_packet *packet)
{
packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx));
@@ -2201,7 +2201,7 @@ static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv,
#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)
+static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
{
int i;
if (priv->snapshot[0])
@@ -2221,7 +2221,7 @@ static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
return 1;
}
-static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
+static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
{
int i;
if (!priv->snapshot[0])
@@ -2231,7 +2231,7 @@ static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
priv->snapshot[0] = NULL;
}
-static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
+static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
size_t len, int mode)
{
u32 i, j;
@@ -2288,7 +2288,7 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
#endif
-static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
+static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
{
#ifdef CONFIG_IPW2100_DEBUG_C3
struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2346,7 +2346,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
schedule_reset(priv);
}
-static inline void isr_rx(struct ipw2100_priv *priv, int i,
+static void isr_rx(struct ipw2100_priv *priv, int i,
struct ieee80211_rx_stats *stats)
{
struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2425,7 +2425,7 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i,
priv->rx_queue.drv[i].host_addr = packet->dma_addr;
}
-static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
+static 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;
@@ -2481,7 +2481,7 @@ static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
* The WRITE index is cached in the variable 'priv->rx_queue.next'.
*
*/
-static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
+static void __ipw2100_rx_process(struct ipw2100_priv *priv)
{
struct ipw2100_bd_queue *rxq = &priv->rx_queue;
struct ipw2100_status_queue *sq = &priv->status_queue;
@@ -2634,7 +2634,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
* for use by future command and data packets.
*
*/
-static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
+static int __ipw2100_tx_process(struct ipw2100_priv *priv)
{
struct ipw2100_bd_queue *txq = &priv->tx_queue;
struct ipw2100_bd *tbd;
@@ -5735,70 +5735,6 @@ static struct net_device_stats *ipw2100_stats(struct net_device *dev)
return &priv->ieee->stats;
}
-#if WIRELESS_EXT < 18
-/* Support for wpa_supplicant before WE-18, deprecated. */
-
-/* following definitions must match definitions in driver_ipw.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 reserved[32];
- u8 data[0];
- } wpa_ie;
- struct {
- u32 command;
- u32 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_ipw.c code */
-#endif /* WIRELESS_EXT < 18 */
-
static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
{
/* This is called when wpa_supplicant loads and closes the driver
@@ -5807,11 +5743,6 @@ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
return 0;
}
-#if WIRELESS_EXT < 18
-#define IW_AUTH_ALG_OPEN_SYSTEM 0x1
-#define IW_AUTH_ALG_SHARED_KEY 0x2
-#endif
-
static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
{
@@ -5855,360 +5786,6 @@ void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
ipw2100_set_wpa_ie(priv, &frame, 0);
}
-#if WIRELESS_EXT < 18
-static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- struct ipw2100_priv *priv = ieee80211_priv(dev);
- struct ieee80211_crypt_data *crypt;
- unsigned long flags;
- int ret = 0;
-
- switch (name) {
- case IPW2100_PARAM_WPA_ENABLED:
- ret = ipw2100_wpa_enable(priv, value);
- break;
-
- case IPW2100_PARAM_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
- if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
- break;
-
- flags = crypt->ops->get_flags(crypt->priv);
-
- if (value)
- flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
- else
- flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
-
- crypt->ops->set_flags(flags, crypt->priv);
-
- break;
-
- case IPW2100_PARAM_DROP_UNENCRYPTED:{
- /* See IW_AUTH_DROP_UNENCRYPTED handling for details */
- struct ieee80211_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- priv->ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- } else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (priv->ieee->set_security)
- priv->ieee->set_security(priv->ieee->dev, &sec);
- 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;
-}
-
-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;
- }
-
- sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
- if (strcmp(param->u.crypt.alg, "none") == 0) {
- if (crypt) {
- sec.enabled = 0;
- sec.encrypt = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_LEVEL;
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- }
- goto done;
- }
- sec.enabled = 1;
- sec.encrypt = 1;
-
- 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 = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- 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;
-}
-
-static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- 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;
- }
-
- return -EOPNOTSUPP;
-}
-#endif /* WIRELESS_EXT < 18 */
-
static void ipw_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -6337,9 +5914,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
dev->open = ipw2100_open;
dev->stop = ipw2100_close;
dev->init = ipw2100_net_init;
-#if WIRELESS_EXT < 18
- dev->do_ioctl = ipw2100_ioctl;
-#endif
dev->get_stats = ipw2100_stats;
dev->ethtool_ops = &ipw2100_ethtool_ops;
dev->tx_timeout = ipw2100_tx_timeout;
@@ -7153,7 +6727,7 @@ static int ipw2100_wx_get_range(struct net_device *dev,
/* Set the Wireless Extension versions */
range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
+ range->we_version_source = 18;
// range->retry_capa; /* What retry options are supported */
// range->retry_flags; /* How to decode max/min retry limit */
@@ -7184,6 +6758,9 @@ static int ipw2100_wx_get_range(struct net_device *dev,
IW_EVENT_CAPA_MASK(SIOCGIWAP));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
IPW_DEBUG_WX("GET Range\n");
return 0;
@@ -7852,7 +7429,6 @@ static int ipw2100_wx_get_power(struct net_device *dev,
return 0;
}
-#if WIRELESS_EXT > 17
/*
* WE-18 WPA support
*/
@@ -8114,7 +7690,6 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
}
return 0;
}
-#endif /* WIRELESS_EXT > 17 */
/*
*
@@ -8347,11 +7922,7 @@ static iw_handler ipw2100_wx_handlers[] = {
NULL, /* SIOCWIWTHRSPY */
ipw2100_wx_set_wap, /* SIOCSIWAP */
ipw2100_wx_get_wap, /* SIOCGIWAP */
-#if WIRELESS_EXT > 17
ipw2100_wx_set_mlme, /* SIOCSIWMLME */
-#else
- NULL, /* -- hole -- */
-#endif
NULL, /* SIOCGIWAPLIST -- deprecated */
ipw2100_wx_set_scan, /* SIOCSIWSCAN */
ipw2100_wx_get_scan, /* SIOCGIWSCAN */
@@ -8375,7 +7946,6 @@ static iw_handler ipw2100_wx_handlers[] = {
ipw2100_wx_get_encode, /* SIOCGIWENCODE */
ipw2100_wx_set_power, /* SIOCSIWPOWER */
ipw2100_wx_get_power, /* SIOCGIWPOWER */
-#if WIRELESS_EXT > 17
NULL, /* -- hole -- */
NULL, /* -- hole -- */
ipw2100_wx_set_genie, /* SIOCSIWGENIE */
@@ -8385,7 +7955,6 @@ static iw_handler ipw2100_wx_handlers[] = {
ipw2100_wx_set_encodeext, /* SIOCSIWENCODEEXT */
ipw2100_wx_get_encodeext, /* SIOCGIWENCODEEXT */
NULL, /* SIOCSIWPMKSA */
-#endif
};
#define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index cdfe50207757..4c28e332ecc3 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -813,7 +813,7 @@ static void ipw_bg_led_link_off(void *data)
up(&priv->sem);
}
-static inline void __ipw_led_activity_on(struct ipw_priv *priv)
+static void __ipw_led_activity_on(struct ipw_priv *priv)
{
u32 led;
@@ -1508,7 +1508,7 @@ static ssize_t store_direct_dword(struct device *d,
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)
+static int rf_kill_active(struct ipw_priv *priv)
{
if (0 == (ipw_read32(priv, 0x30) & 0x10000))
priv->status |= STATUS_RF_KILL_HW;
@@ -2359,7 +2359,7 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data)
}
/* perform a chip select operation */
-static inline void eeprom_cs(struct ipw_priv *priv)
+static void eeprom_cs(struct ipw_priv *priv)
{
eeprom_write_reg(priv, 0);
eeprom_write_reg(priv, EEPROM_BIT_CS);
@@ -2368,7 +2368,7 @@ static inline void eeprom_cs(struct ipw_priv *priv)
}
/* perform a chip select operation */
-static inline void eeprom_disable_cs(struct ipw_priv *priv)
+static void eeprom_disable_cs(struct ipw_priv *priv)
{
eeprom_write_reg(priv, EEPROM_BIT_CS);
eeprom_write_reg(priv, 0);
@@ -2475,7 +2475,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
IPW_DEBUG_TRACE("<<\n");
}
-static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
+static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
{
count >>= 2;
if (!count)
@@ -2772,7 +2772,7 @@ 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,
+static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
int timeout)
{
int i = 0;
@@ -3150,7 +3150,7 @@ static int ipw_get_fw(struct ipw_priv *priv,
#define IPW_RX_BUF_SIZE (3000)
-static inline void ipw_rx_queue_reset(struct ipw_priv *priv,
+static void ipw_rx_queue_reset(struct ipw_priv *priv,
struct ipw_rx_queue *rxq)
{
unsigned long flags;
@@ -3608,7 +3608,7 @@ static void ipw_tx_queue_free(struct ipw_priv *priv)
ipw_queue_tx_free(priv, &priv->txq[3]);
}
-static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
+static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
{
/* First 3 bytes are manufacturer */
bssid[0] = priv->mac_addr[0];
@@ -3622,7 +3622,7 @@ static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */
}
-static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
+static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
{
struct ipw_station_entry entry;
int i;
@@ -3655,7 +3655,7 @@ static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
return i;
}
-static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
+static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
{
int i;
@@ -3794,7 +3794,7 @@ static void inline average_init(struct average *avg)
memset(avg, 0, sizeof(*avg));
}
-static void inline average_add(struct average *avg, s16 val)
+static void average_add(struct average *avg, s16 val)
{
avg->sum -= avg->entries[avg->pos];
avg->sum += val;
@@ -3805,7 +3805,7 @@ static void inline average_add(struct average *avg, s16 val)
}
}
-static s16 inline average_value(struct average *avg)
+static s16 average_value(struct average *avg)
{
if (!unlikely(avg->init)) {
if (avg->pos)
@@ -3847,7 +3847,7 @@ static void ipw_reset_stats(struct ipw_priv *priv)
}
-static inline u32 ipw_get_max_rate(struct ipw_priv *priv)
+static u32 ipw_get_max_rate(struct ipw_priv *priv)
{
u32 i = 0x80000000;
u32 mask = priv->rates_mask;
@@ -4087,7 +4087,7 @@ static void ipw_bg_gather_stats(void *data)
* roaming_threshold -> disassociate_threshold, scan and roam for better signal.
* Above disassociate threshold, give up and stop scanning.
* Roaming is disabled if disassociate_threshold <= roaming_threshold */
-static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
+static void ipw_handle_missed_beacon(struct ipw_priv *priv,
int missed_count)
{
priv->notif_missed_beacons = missed_count;
@@ -4157,7 +4157,7 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
* Handle host notification packet.
* Called from interrupt routine
*/
-static inline void ipw_rx_notification(struct ipw_priv *priv,
+static void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
notif->size = le16_to_cpu(notif->size);
@@ -5095,7 +5095,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv,
return 1;
}
-static inline void ipw_copy_rates(struct ipw_supported_rates *dest,
+static void ipw_copy_rates(struct ipw_supported_rates *dest,
const struct ipw_supported_rates *src)
{
u8 i;
@@ -5856,7 +5856,7 @@ static void ipw_debug_config(struct ipw_priv *priv)
#define ipw_debug_config(x) do {} while (0)
#endif
-static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
+static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
{
/* TODO: Verify that this works... */
struct ipw_fixed_rate fr = {
@@ -7634,7 +7634,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
}
#endif
-static inline int is_network_packet(struct ipw_priv *priv,
+static int is_network_packet(struct ipw_priv *priv,
struct ieee80211_hdr_4addr *header)
{
/* Filter incoming packets to determine if they are targetted toward
@@ -7672,7 +7672,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
#define IPW_PACKET_RETRY_TIME HZ
-static inline int is_duplicate_packet(struct ipw_priv *priv,
+static int is_duplicate_packet(struct ipw_priv *priv,
struct ieee80211_hdr_4addr *header)
{
u16 sc = le16_to_cpu(header->seq_ctl);
@@ -8936,14 +8936,12 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
IPW_DEBUG_HC("starting request direct scan!\n");
if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
- err = wait_event_interruptible(priv->wait_state,
- !(priv->
- status & (STATUS_SCANNING |
- STATUS_SCAN_ABORTING)));
- if (err) {
- IPW_DEBUG_HC("aborting direct scan");
- goto done;
- }
+ /* We should not sleep here; otherwise we will block most
+ * of the system (for instance, we hold rtnl_lock when we
+ * get here).
+ */
+ err = -EAGAIN;
+ goto done;
}
memset(&scan, 0, sizeof(scan));
@@ -9581,7 +9579,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
/* net device stuff */
-static inline void init_sys_config(struct ipw_sys_config *sys_config)
+static 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 */
@@ -9627,7 +9625,7 @@ modify to send one tfd per fragment instead of using chunking. otherwise
we need to heavily modify the ieee80211_skb_to_txb.
*/
-static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
+static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
int pri)
{
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 135a156db25d..c5cd61c7f927 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -748,7 +748,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
if (essid->length) {
dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */
/* if it is to big, trunk it */
- dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length + 1);
+ dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length);
} else {
dwrq->flags = 0;
dwrq->length = 0;
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 33d64d2ee53f..a8261d8454dd 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -177,7 +177,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
#endif
newskb->dev = skb->dev;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
skb = newskb;
}
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 319180ca7e71..7880d8c31aad 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1256,7 +1256,7 @@ static int ray_get_essid(struct net_device *dev,
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Push it out ! */
- dwrq->length = strlen(extra) + 1;
+ dwrq->length = strlen(extra);
dwrq->flags = 1; /* active */
return 0;
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index d25264ba0c0e..18baacfc5a2c 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1675,11 +1675,6 @@ static int strip_rebuild_header(struct sk_buff *skb)
/************************************************************************/
/* Receiving routines */
-static int strip_receive_room(struct tty_struct *tty)
-{
- return 0x10000; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* This function parses the response to the ATS300? command,
* extracting the radio version and serial number.
@@ -2424,7 +2419,7 @@ static struct net_device_stats *strip_get_stats(struct net_device *dev)
/*
* Here's the order things happen:
* When the user runs "slattach -p strip ..."
- * 1. The TTY module calls strip_open
+ * 1. The TTY module calls strip_open;;
* 2. strip_open calls strip_alloc
* 3. strip_alloc calls register_netdev
* 4. register_netdev calls strip_dev_init
@@ -2652,6 +2647,8 @@ static int strip_open(struct tty_struct *tty)
strip_info->tty = tty;
tty->disc_data = strip_info;
+ tty->receive_room = 65536;
+
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
@@ -2762,7 +2759,6 @@ static struct tty_ldisc strip_ldisc = {
.close = strip_close,
.ioctl = strip_ioctl,
.receive_buf = strip_receive_buf,
- .receive_room = strip_receive_room,
.write_wakeup = strip_write_some_more,
};
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index b0d8b5b03152..ff192e96268a 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -102,7 +102,7 @@ static inline void hacr_write(unsigned long ioaddr, u16 hacr)
* Write to card's Host Adapter Command Register. Include a delay for
* those times when it is needed.
*/
-static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr)
+static void hacr_write_slow(unsigned long ioaddr, u16 hacr)
{
hacr_write(ioaddr, hacr);
/* delay might only be needed sometimes */
@@ -242,7 +242,7 @@ static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */
* The Windows drivers don't use the CRC, but the AP and the PtP tool
* depend on it.
*/
-static inline u16 psa_crc(u8 * psa, /* The PSA */
+static u16 psa_crc(u8 * psa, /* The PSA */
int size)
{ /* Number of short for CRC */
int byte_cnt; /* Loop on the PSA */
@@ -310,7 +310,7 @@ static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u
/*
* Write 1 byte to the MMC.
*/
-static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
+static void mmc_out(unsigned long ioaddr, u16 o, u8 d)
{
int count = 0;
@@ -326,7 +326,7 @@ static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
* Routine to write bytes to the Modem Management Controller.
* We start at the end because it is the way it should be!
*/
-static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
+static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
{
o += n;
b += n;
@@ -340,7 +340,7 @@ static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
* Read a byte from the MMC.
* Optimised version for 1 byte, avoid using memory.
*/
-static inline u8 mmc_in(unsigned long ioaddr, u16 o)
+static u8 mmc_in(unsigned long ioaddr, u16 o)
{
int count = 0;
@@ -587,7 +587,7 @@ static void wv_ack(struct net_device * dev)
* Set channel attention bit and busy wait until command has
* completed, then acknowledge completion of the command.
*/
-static inline int wv_synchronous_cmd(struct net_device * dev, const char *str)
+static int wv_synchronous_cmd(struct net_device * dev, const char *str)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -633,7 +633,7 @@ static inline int wv_synchronous_cmd(struct net_device * dev, const char *str)
* Configuration commands completion interrupt.
* Check if done, and if OK.
*/
-static inline int
+static int
wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp)
{
unsigned short mcs_addr;
@@ -843,7 +843,7 @@ if (lp->tx_n_in_use > 0)
* wavelan_interrupt is not an option), so you may experience
* delays sometimes.
*/
-static inline void wv_82586_reconfig(struct net_device * dev)
+static void wv_82586_reconfig(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long flags;
@@ -1281,7 +1281,7 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */
* This is the information which is displayed by the driver at startup.
* There are lots of flags for configuring it to your liking.
*/
-static inline void wv_init_info(struct net_device * dev)
+static void wv_init_info(struct net_device * dev)
{
short ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv;
@@ -1502,7 +1502,7 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr)
* It's a bit complicated and you don't really want to look into it.
* (called in wavelan_ioctl)
*/
-static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */
+static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */
iw_freq * frequency)
{
const int BAND_NUM = 10; /* Number of bands */
@@ -1677,7 +1677,7 @@ static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card
/*
* Give the list of available frequencies.
*/
-static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
+static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
iw_freq * list, /* List of frequencies to fill */
int max)
{ /* Maximum number of frequencies */
@@ -2489,7 +2489,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
* Note: if any errors occur, the packet is "dropped on the floor".
* (called by wv_packet_rcv())
*/
-static inline void
+static void
wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
{
net_local *lp = (net_local *) dev->priv;
@@ -2585,7 +2585,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
* (called in wavelan_interrupt()).
* Note : the spinlock is already grabbed for us.
*/
-static inline void wv_receive(struct net_device * dev)
+static void wv_receive(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv;
@@ -2768,7 +2768,7 @@ static inline void wv_receive(struct net_device * dev)
*
* (called in wavelan_packet_xmit())
*/
-static inline int wv_packet_write(struct net_device * dev, void *buf, short length)
+static int wv_packet_write(struct net_device * dev, void *buf, short length)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -2964,7 +2964,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
* Routine to initialize the Modem Management Controller.
* (called by wv_hw_reset())
*/
-static inline int wv_mmc_init(struct net_device * dev)
+static int wv_mmc_init(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv;
@@ -3136,7 +3136,7 @@ static inline int wv_mmc_init(struct net_device * dev)
* Start the receive unit.
* (called by wv_hw_reset())
*/
-static inline int wv_ru_start(struct net_device * dev)
+static int wv_ru_start(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -3228,7 +3228,7 @@ static inline int wv_ru_start(struct net_device * dev)
*
* (called by wv_hw_reset())
*/
-static inline int wv_cu_start(struct net_device * dev)
+static int wv_cu_start(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -3329,7 +3329,7 @@ static inline int wv_cu_start(struct net_device * dev)
*
* (called by wv_hw_reset())
*/
-static inline int wv_82586_start(struct net_device * dev)
+static int wv_82586_start(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -3641,7 +3641,7 @@ static void wv_82586_config(struct net_device * dev)
* WaveLAN controller (i82586).
* (called by wavelan_close())
*/
-static inline void wv_82586_stop(struct net_device * dev)
+static void wv_82586_stop(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 7e2039f52c49..cf373625fc70 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -2280,7 +2280,7 @@ static int wavelan_get_essid(struct net_device *dev,
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Set the length */
- wrqu->data.length = strlen(extra) + 1;
+ wrqu->data.length = strlen(extra);
return 0;
}
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 531b07313141..b2e8e49c8659 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -43,13 +43,16 @@ static void process_task_mortuary(void);
* list for processing. Only after two full buffer syncs
* does the task eventually get freed, because by then
* we are sure we will not reference it again.
+ * Can be invoked from softirq via RCU callback due to
+ * call_rcu() of the task struct, hence the _irqsave.
*/
static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
{
+ unsigned long flags;
struct task_struct * task = data;
- spin_lock(&task_mortuary);
+ spin_lock_irqsave(&task_mortuary, flags);
list_add(&task->tasks, &dying_tasks);
- spin_unlock(&task_mortuary);
+ spin_unlock_irqrestore(&task_mortuary, flags);
return NOTIFY_OK;
}
@@ -431,25 +434,22 @@ static void increment_tail(struct oprofile_cpu_buffer * b)
*/
static void process_task_mortuary(void)
{
- struct list_head * pos;
- struct list_head * pos2;
+ unsigned long flags;
+ LIST_HEAD(local_dead_tasks);
struct task_struct * task;
+ struct task_struct * ttask;
- spin_lock(&task_mortuary);
+ spin_lock_irqsave(&task_mortuary, flags);
- list_for_each_safe(pos, pos2, &dead_tasks) {
- task = list_entry(pos, struct task_struct, tasks);
- list_del(&task->tasks);
- free_task(task);
- }
+ list_splice_init(&dead_tasks, &local_dead_tasks);
+ list_splice_init(&dying_tasks, &dead_tasks);
- list_for_each_safe(pos, pos2, &dying_tasks) {
- task = list_entry(pos, struct task_struct, tasks);
+ spin_unlock_irqrestore(&task_mortuary, flags);
+
+ list_for_each_entry_safe(task, ttask, &local_dead_tasks, tasks) {
list_del(&task->tasks);
- list_add_tail(&task->tasks, &dead_tasks);
+ free_task(task);
}
-
- spin_unlock(&task_mortuary);
}
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 026f671ea558..78193e4bbdb5 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -52,7 +52,8 @@ int alloc_cpu_buffers(void)
for_each_online_cpu(i) {
struct oprofile_cpu_buffer * b = &cpu_buffer[i];
- b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size);
+ b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size,
+ cpu_to_node(i));
if (!b->buffer)
goto fail;
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 166bca790133..b80318f03420 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -15,6 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/oprofile.h>
#include <linux/sched.h>
+#include <linux/capability.h>
#include <linux/dcookies.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 5ab75334c579..216d1d859326 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -83,7 +83,8 @@
** bus number for each dino.
*/
-#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_cujo(id) ((id)->hversion == 0x682)
#define DINO_IAR0 0x004
#define DINO_IODC_ADDR 0x008
@@ -124,6 +125,7 @@
#define DINO_IRQS 11 /* bits 0-10 are architected */
#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */
+#define DINO_LOCAL_IRQS (DINO_IRQS+1)
#define DINO_MASK_IRQ(x) (1<<(x))
@@ -146,7 +148,7 @@ struct dino_device
unsigned long txn_addr; /* EIR addr to generate interrupt */
u32 txn_data; /* EIR data assign to each dino */
u32 imr; /* IRQ's which are enabled */
- int global_irq[12]; /* map IMR bit to global irq */
+ int global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
#ifdef DINO_DEBUG
unsigned int dino_irr0; /* save most recent IRQ line stat */
#endif
@@ -297,7 +299,7 @@ struct pci_port_ops dino_port_ops = {
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);
+ int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
@@ -309,7 +311,7 @@ static void dino_disable_irq(unsigned int irq)
static void dino_enable_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);
+ int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
u32 tmp;
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
@@ -435,6 +437,21 @@ static void dino_choose_irq(struct parisc_device *dev, void *ctrl)
dino_assign_irq(dino, irq, &dev->irq);
}
+
+/*
+ * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de)
+ * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...)
+ */
+static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev)
+{
+ u8 new_irq = dev->irq - 1;
+ printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n",
+ pci_name(dev), dev->irq, new_irq);
+ dev->irq = new_irq;
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
+
+
static void __init
dino_bios_init(void)
{
@@ -666,7 +683,6 @@ dino_fixup_bus(struct pci_bus *bus)
printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
#endif
} else {
-
/* Adjust INT_LINE for that busses region */
dino_assign_irq(dino_dev, dev->irq, &dev->irq);
}
@@ -872,7 +888,7 @@ static int __init dino_common_init(struct parisc_device *dev,
/* allocate I/O Port resource region */
res = &dino_dev->hba.io_space;
- if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) {
+ if (!is_cujo(&dev->id)) {
res->name = "Dino I/O Port";
} else {
res->name = "Cujo I/O Port";
@@ -927,7 +943,7 @@ static int __init dino_probe(struct parisc_device *dev)
if (is_card_dino(&dev->id)) {
version = "3.x (card mode)";
} else {
- if(dev->id.hversion == 0x680) {
+ if (!is_cujo(&dev->id)) {
if (dev->id.hversion_rev < 4) {
version = dino_vers[dev->id.hversion_rev];
}
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 6362bf99eff6..3d94d86c1c9f 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -57,7 +57,7 @@
static DEFINE_SPINLOCK(eisa_irq_lock);
-void __iomem *eisa_eeprom_addr;
+void __iomem *eisa_eeprom_addr __read_mostly;
/* We can only have one EISA adapter in the system because neither
* implementation can be flexed.
@@ -141,7 +141,7 @@ static int slave_mask;
* in the furure.
*/
/* irq 13,8,2,1,0 must be edge */
-static unsigned int eisa_irq_level; /* default to edge triggered */
+static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered */
/* called by free irq */
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index 3a1b4826e5c1..e13aafa70bf5 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -48,7 +48,7 @@ static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
}
static ssize_t eisa_eeprom_read(struct file * file,
- char *buf, size_t count, loff_t *ppos )
+ char __user *buf, size_t count, loff_t *ppos )
{
unsigned char *tmp;
ssize_t ret;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index a8c20396ffbe..2b3ba1dcf332 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -150,7 +150,7 @@ void __init lasi_led_init(unsigned long lasi_hpa)
*
*/
-static unsigned long lasi_power_off_hpa;
+static unsigned long lasi_power_off_hpa __read_mostly;
static void lasi_power_off(void)
{
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 5e495dcbc58a..cbae8c8963fa 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -167,7 +167,7 @@
/* non-postable I/O port space, densely packed */
#define LBA_PORT_BASE (PCI_F_EXTEND | 0xfee00000UL)
-static void __iomem *astro_iop_base;
+static void __iomem *astro_iop_base __read_mostly;
#define ELROY_HVERS 0x782
#define MERCURY_HVERS 0x783
@@ -695,11 +695,71 @@ lba_claim_dev_resources(struct pci_dev *dev)
}
}
}
+
+
+/*
+ * truncate_pat_collision: Deal with overlaps or outright collisions
+ * between PAT PDC reported ranges.
+ *
+ * Broken PA8800 firmware will report lmmio range that
+ * overlaps with CPU HPA. Just truncate the lmmio range.
+ *
+ * BEWARE: conflicts with this lmmio range may be an
+ * elmmio range which is pointing down another rope.
+ *
+ * FIXME: only deals with one collision per range...theoretically we
+ * could have several. Supporting more than one collision will get messy.
+ */
+static unsigned long
+truncate_pat_collision(struct resource *root, struct resource *new)
+{
+ unsigned long start = new->start;
+ unsigned long end = new->end;
+ struct resource *tmp = root->child;
+
+ if (end <= start || start < root->start || !tmp)
+ return 0;
+
+ /* find first overlap */
+ while (tmp && tmp->end < start)
+ tmp = tmp->sibling;
+
+ /* no entries overlap */
+ if (!tmp) return 0;
+
+ /* found one that starts behind the new one
+ ** Don't need to do anything.
+ */
+ if (tmp->start >= end) return 0;
+
+ if (tmp->start <= start) {
+ /* "front" of new one overlaps */
+ new->start = tmp->end + 1;
+
+ if (tmp->end >= end) {
+ /* AACCKK! totally overlaps! drop this range. */
+ return 1;
+ }
+ }
+
+ if (tmp->end < end ) {
+ /* "end" of new one overlaps */
+ new->end = tmp->start - 1;
+ }
+
+ printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] "
+ "to [%lx,%lx]\n",
+ start, end,
+ new->start, new->end );
+
+ return 0; /* truncation successful */
+}
+
#else
-#define lba_claim_dev_resources(dev)
+#define lba_claim_dev_resources(dev) do { } while (0)
+#define truncate_pat_collision(r,n) (0)
#endif
-
/*
** The algorithm is generic code.
** But it needs to access local data structures to get the IRQ base.
@@ -747,6 +807,9 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&ioport_resource, 2);
BUG();
}
+ /* advertize Host bridge resources to PCI bus */
+ bus->resource[0] = &(ldev->hba.io_space);
+ i = 1;
if (ldev->hba.elmmio_space.start) {
err = request_resource(&iomem_resource,
@@ -760,23 +823,35 @@ lba_fixup_bus(struct pci_bus *bus)
/* lba_dump_res(&iomem_resource, 2); */
/* BUG(); */
- }
+ } else
+ bus->resource[i++] = &(ldev->hba.elmmio_space);
}
- err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
- if (err < 0) {
- /* FIXME overlaps with elmmio will fail here.
- * Need to prune (or disable) the distributed range.
- *
- * BEWARE: conflicts with this lmmio range may be
- * elmmio range which is pointing down another rope.
- */
-
- printk("FAILED: lba_fixup_bus() request for "
+
+ /* Overlaps with elmmio can (and should) fail here.
+ * We will prune (or ignore) the distributed range.
+ *
+ * FIXME: SBA code should register all elmmio ranges first.
+ * that would take care of elmmio ranges routed
+ * to a different rope (already discovered) from
+ * getting registered *after* LBA code has already
+ * registered it's distributed lmmio range.
+ */
+ if (truncate_pat_collision(&iomem_resource,
+ &(ldev->hba.lmmio_space))) {
+
+ printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
+ ldev->hba.lmmio_space.start,
+ ldev->hba.lmmio_space.end);
+ } else {
+ err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
+ if (err < 0) {
+ printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
"lmmio_space [%lx/%lx]\n",
ldev->hba.lmmio_space.start,
ldev->hba.lmmio_space.end);
- /* lba_dump_res(&iomem_resource, 2); */
+ } else
+ bus->resource[i++] = &(ldev->hba.lmmio_space);
}
#ifdef CONFIG_64BIT
@@ -791,18 +866,10 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&iomem_resource, 2);
BUG();
}
+ bus->resource[i++] = &(ldev->hba.gmmio_space);
}
#endif
- /* advertize Host bridge resources to PCI bus */
- bus->resource[0] = &(ldev->hba.io_space);
- bus->resource[1] = &(ldev->hba.lmmio_space);
- i=2;
- if (ldev->hba.elmmio_space.start)
- bus->resource[i++] = &(ldev->hba.elmmio_space);
- if (ldev->hba.gmmio_space.start)
- bus->resource[i++] = &(ldev->hba.gmmio_space);
-
}
list_for_each(ln, &bus->devices) {
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 95bd07b8b61b..3627a2d7f79f 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -3,7 +3,7 @@
*
* (c) Copyright 2000 Red Hat Software
* (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
- * (c) Copyright 2001-2004 Helge Deller <deller@gmx.de>
+ * (c) Copyright 2001-2005 Helge Deller <deller@gmx.de>
* (c) Copyright 2001 Randolph Chung <tausq@debian.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/utsname.h>
+#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
@@ -56,13 +57,13 @@
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_type __read_mostly = -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 unsigned int led_heartbeat __read_mostly = 1;
+static unsigned int led_diskio __read_mostly = 1;
+static unsigned int led_lanrxtx __read_mostly = 1;
+static char lcd_text[32] __read_mostly;
+static char lcd_text_default[32] __read_mostly;
static struct workqueue_struct *led_wq;
@@ -108,7 +109,7 @@ struct pdc_chassis_lcd_info_ret_block {
/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's
* HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */
static struct pdc_chassis_lcd_info_ret_block
-lcd_info __attribute__((aligned(8))) =
+lcd_info __attribute__((aligned(8))) __read_mostly =
{
.model = DISPLAY_MODEL_LCD,
.lcd_width = 16,
@@ -144,7 +145,7 @@ static int start_task(void)
device_initcall(start_task);
/* ptr to LCD/LED-specific function */
-static void (*led_func_ptr) (unsigned char);
+static void (*led_func_ptr) (unsigned char) __read_mostly;
#ifdef CONFIG_PROC_FS
static int led_proc_read(char *page, char **start, off_t off, int count,
@@ -347,7 +348,7 @@ static void led_LCD_driver(unsigned char leds)
**
** led_get_net_activity()
**
- ** calculate if there was TX- or RX-troughput on the network interfaces
+ ** calculate if there was TX- or RX-throughput on the network interfaces
** (analog to dev_get_info() from net/core/dev.c)
**
*/
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 273a74179720..42a3c54e8e6c 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -42,9 +42,9 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/sched.h> /* for capable() */
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
@@ -56,7 +56,7 @@
#include <asm/uaccess.h>
#include <asm/hardware.h>
-#define PDCS_VERSION "0.09"
+#define PDCS_VERSION "0.10"
#define PDCS_ADDR_PPRI 0x00
#define PDCS_ADDR_OSID 0x40
@@ -70,7 +70,7 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
MODULE_LICENSE("GPL");
MODULE_VERSION(PDCS_VERSION);
-static unsigned long pdcs_size = 0;
+static unsigned long pdcs_size __read_mostly;
/* This struct defines what we need to deal with a parisc pdc path entry */
struct pdcspath_entry {
@@ -194,7 +194,8 @@ pdcspath_store(struct pdcspath_entry *entry)
return -EIO;
}
- entry->ready = 1;
+ /* kobject is already registered */
+ entry->ready = 2;
DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
@@ -653,15 +654,21 @@ pdcs_register_pathentries(void)
{
unsigned short i;
struct pdcspath_entry *entry;
+ int err;
for (i = 0; (entry = pdcspath_entries[i]); i++) {
if (pdcspath_fetch(entry) < 0)
continue;
- kobject_set_name(&entry->kobj, "%s", entry->name);
+ if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
+ return err;
kobj_set_kset_s(entry, paths_subsys);
- kobject_register(&entry->kobj);
-
+ if ((err = kobject_register(&entry->kobj)))
+ return err;
+
+ /* kobject is now registered */
+ entry->ready = 2;
+
if (!entry->dev)
continue;
@@ -675,14 +682,14 @@ pdcs_register_pathentries(void)
/**
* pdcs_unregister_pathentries - Routine called when unregistering the module.
*/
-static inline void __exit
+static inline void
pdcs_unregister_pathentries(void)
{
unsigned short i;
struct pdcspath_entry *entry;
for (i = 0; (entry = pdcspath_entries[i]); i++)
- if (entry->ready)
+ if (entry->ready >= 2)
kobject_unregister(&entry->kobj);
}
@@ -704,7 +711,7 @@ pdc_stable_init(void)
/* For now we'll register the pdc subsys within this driver */
if ((rc = firmware_register(&pdc_subsys)))
- return rc;
+ goto fail_firmreg;
/* Don't forget the info entry */
for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
@@ -713,12 +720,25 @@ pdc_stable_init(void)
/* register the paths subsys as a subsystem of pdc subsys */
kset_set_kset_s(&paths_subsys, pdc_subsys);
- subsystem_register(&paths_subsys);
+ if ((rc= subsystem_register(&paths_subsys)))
+ goto fail_subsysreg;
/* now we create all "files" for the paths subsys */
- pdcs_register_pathentries();
+ if ((rc = pdcs_register_pathentries()))
+ goto fail_pdcsreg;
+
+ return rc;
- return 0;
+fail_pdcsreg:
+ pdcs_unregister_pathentries();
+ subsystem_unregister(&paths_subsys);
+
+fail_subsysreg:
+ firmware_unregister(&pdc_subsys);
+
+fail_firmreg:
+ printk(KERN_INFO "PDC Stable Storage bailing out\n");
+ return rc;
}
static void __exit
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index ff75e9296df9..54b2b7f20b96 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -2,7 +2,7 @@
* linux/arch/parisc/kernel/power.c
* HP PARISC soft power switch support driver
*
- * Copyright (c) 2001-2002 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de>
* All rights reserved.
*
*
@@ -102,7 +102,7 @@ static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL);
static void poweroff(void)
{
- static int powering_off;
+ static int powering_off __read_mostly;
if (powering_off)
return;
@@ -113,7 +113,7 @@ static void poweroff(void)
/* local time-counter for shutdown */
-static int shutdown_timer;
+static int shutdown_timer __read_mostly;
/* check, give feedback and start shutdown after one second */
static void process_shutdown(void)
@@ -139,7 +139,7 @@ static void process_shutdown(void)
DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
/* soft power switch enabled/disabled */
-int pwrsw_enabled = 1;
+int pwrsw_enabled __read_mostly = 1;
/*
* On gecko style machines (e.g. 712/xx and 715/xx)
@@ -149,7 +149,7 @@ int pwrsw_enabled = 1;
*/
static void gecko_tasklet_func(unsigned long unused)
{
- if (!pwrsw_enabled)
+ if (unlikely(!pwrsw_enabled))
return;
if (__getDIAG(25) & 0x80000000) {
@@ -173,7 +173,7 @@ static void polling_tasklet_func(unsigned long soft_power_reg)
{
unsigned long current_status;
- if (!pwrsw_enabled)
+ if (unlikely(!pwrsw_enabled))
return;
current_status = gsc_readl(soft_power_reg);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index b8241561da45..f605dea57224 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 && !M32R
+ depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
---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
@@ -121,6 +121,7 @@ config PARPORT_GSC
tristate
default GSC
depends on PARPORT
+ select PARPORT_NOT_PC
config PARPORT_SUNBPP
tristate "Sparc hardware (EXPERIMENTAL)"
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 18e85ccdae67..9302b8fd7461 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2371,8 +2371,10 @@ void parport_pc_unregister_port (struct parport *p)
spin_lock(&ports_lock);
list_del_init(&priv->list);
spin_unlock(&ports_lock);
+#if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA)
if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma);
+#endif
if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p);
release_region(p->base, 3);
@@ -2380,14 +2382,12 @@ void parport_pc_unregister_port (struct parport *p)
release_region(p->base + 3, p->size - 3);
if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3);
-#ifdef CONFIG_PARPORT_PC_FIFO
-#ifdef HAS_DMA
+#if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA)
if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE,
priv->dma_buf,
priv->dma_handle);
#endif
-#endif
kfree (p->private_data);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index d3dad0aac7cb..76dd077e3184 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -464,7 +464,7 @@ static struct pci_driver parport_serial_pci_driver = {
static int __init parport_serial_init (void)
{
- return pci_module_init (&parport_serial_pci_driver);
+ return pci_register_driver (&parport_serial_pci_driver);
}
static void __exit parport_serial_exit (void)
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 8e21f6ab89a1..509a5b3ae998 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -794,12 +794,14 @@ static int enable_device(struct acpiphp_slot *slot)
if (PCI_SLOT(dev->devfn) != slot->device)
continue;
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass);
+ if (pass && dev->subordinate)
+ pci_bus_size_bridges(dev->subordinate);
+ }
}
}
- pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
pci_enable_bridges(bus);
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index 092491e25ef2..cb88404c89fe 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -317,6 +317,7 @@ struct controller {
u16 vendor_id;
struct work_struct int_task_event;
wait_queue_head_t queue; /* sleep & wake process */
+ struct dentry *dentry; /* debugfs dentry */
};
struct irq_mapping {
@@ -399,8 +400,11 @@ struct resource_lists {
#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
-/* sysfs functions for the hotplug controller info */
-extern void cpqhp_create_ctrl_files (struct controller *ctrl);
+/* debugfs functions for the hotplug controller info */
+extern void cpqhp_initialize_debugfs (void);
+extern void cpqhp_shutdown_debugfs (void);
+extern void cpqhp_create_debugfs_files (struct controller *ctrl);
+extern void cpqhp_remove_debugfs_files (struct controller *ctrl);
/* controller functions */
extern void cpqhp_pushbutton_thread (unsigned long event_pointer);
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 9aed8efe6a11..b3659ffccac9 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -327,7 +327,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
void __iomem *smbios_start,
void __iomem *smbios_table)
{
- struct slot *new_slot;
+ struct slot *slot;
+ struct hotplug_slot *hotplug_slot;
+ struct hotplug_slot_info *hotplug_slot_info;
u8 number_of_slots;
u8 slot_device;
u8 slot_number;
@@ -345,93 +347,105 @@ static int ctrl_slot_setup(struct controller *ctrl,
slot_number = ctrl->first_slot;
while (number_of_slots) {
- new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
- if (!new_slot)
+ slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
goto error;
- memset(new_slot, 0, sizeof(struct slot));
- new_slot->hotplug_slot = kmalloc(sizeof(*(new_slot->hotplug_slot)),
+ memset(slot, 0, sizeof(struct slot));
+ slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot)
+ if (!slot->hotplug_slot)
goto error_slot;
- memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+ hotplug_slot = slot->hotplug_slot;
+ memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
- new_slot->hotplug_slot->info =
- kmalloc(sizeof(*(new_slot->hotplug_slot->info)),
+ hotplug_slot->info =
+ kmalloc(sizeof(*(hotplug_slot->info)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot->info)
+ if (!hotplug_slot->info)
goto error_hpslot;
- memset(new_slot->hotplug_slot->info, 0,
+ hotplug_slot_info = hotplug_slot->info;
+ memset(hotplug_slot_info, 0,
sizeof(struct hotplug_slot_info));
- new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
- if (!new_slot->hotplug_slot->name)
+ hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+
+ if (!hotplug_slot->name)
goto error_info;
- new_slot->ctrl = ctrl;
- new_slot->bus = ctrl->bus;
- new_slot->device = slot_device;
- new_slot->number = slot_number;
- dbg("slot->number = %d\n",new_slot->number);
+ slot->ctrl = ctrl;
+ slot->bus = ctrl->bus;
+ slot->device = slot_device;
+ slot->number = slot_number;
+ dbg("slot->number = %d\n", slot->number);
slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
slot_entry);
- while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) {
+ while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
+ slot->number)) {
slot_entry = get_SMBIOS_entry(smbios_start,
smbios_table, 9, slot_entry);
}
- new_slot->p_sm_slot = slot_entry;
+ slot->p_sm_slot = slot_entry;
- init_timer(&new_slot->task_event);
- new_slot->task_event.expires = jiffies + 5 * HZ;
- new_slot->task_event.function = cpqhp_pushbutton_thread;
+ init_timer(&slot->task_event);
+ slot->task_event.expires = jiffies + 5 * HZ;
+ slot->task_event.function = cpqhp_pushbutton_thread;
//FIXME: these capabilities aren't used but if they are
// they need to be correctly implemented
- new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
- new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
+ slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+ slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
- if (is_slot64bit(new_slot))
- new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
- if (is_slot66mhz(new_slot))
- new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
+ if (is_slot64bit(slot))
+ slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+ if (is_slot66mhz(slot))
+ slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
if (ctrl->speed == PCI_SPEED_66MHz)
- new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+ slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
- ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+ ctrl_slot =
+ slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
// Check presence
- new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+ slot->capabilities |=
+ ((((~tempdword) >> 23) |
+ ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
// Check the switch state
- new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+ slot->capabilities |=
+ ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
// Check the slot enable
- new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+ slot->capabilities |=
+ ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
/* register this slot with the hotplug pci core */
- new_slot->hotplug_slot->release = &release_slot;
- new_slot->hotplug_slot->private = new_slot;
- make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
- new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+ hotplug_slot->release = &release_slot;
+ hotplug_slot->private = slot;
+ make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
+ hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
- new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot);
- new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot);
- new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot);
- new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot);
+ hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
+ hotplug_slot_info->attention_status =
+ cpq_get_attention_status(ctrl, slot);
+ hotplug_slot_info->latch_status =
+ cpq_get_latch_status(ctrl, slot);
+ hotplug_slot_info->adapter_status =
+ get_presence_status(ctrl, slot);
- dbg ("registering bus %d, dev %d, number %d, "
+ dbg("registering bus %d, dev %d, number %d, "
"ctrl->slot_device_offset %d, slot %d\n",
- new_slot->bus, new_slot->device,
- new_slot->number, ctrl->slot_device_offset,
+ slot->bus, slot->device,
+ slot->number, ctrl->slot_device_offset,
slot_number);
- result = pci_hp_register (new_slot->hotplug_slot);
+ result = pci_hp_register(hotplug_slot);
if (result) {
- err ("pci_hp_register failed with error %d\n", result);
+ err("pci_hp_register failed with error %d\n", result);
goto error_name;
}
- new_slot->next = ctrl->slot;
- ctrl->slot = new_slot;
+ slot->next = ctrl->slot;
+ ctrl->slot = slot;
number_of_slots--;
slot_device++;
@@ -439,15 +453,14 @@ static int ctrl_slot_setup(struct controller *ctrl,
}
return 0;
-
error_name:
- kfree(new_slot->hotplug_slot->name);
+ kfree(hotplug_slot->name);
error_info:
- kfree(new_slot->hotplug_slot->info);
+ kfree(hotplug_slot_info);
error_hpslot:
- kfree(new_slot->hotplug_slot);
+ kfree(hotplug_slot);
error_slot:
- kfree(new_slot);
+ kfree(slot);
error:
return result;
}
@@ -466,6 +479,8 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
old_slot = next_slot;
}
+ cpqhp_remove_debugfs_files(ctrl);
+
//Free IRQ associated with hot plug device
free_irq(ctrl->interrupt, ctrl);
//Unmap the memory
@@ -1262,7 +1277,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
// Done with exclusive hardware access
up(&ctrl->crit_sect);
- cpqhp_create_ctrl_files(ctrl);
+ cpqhp_create_debugfs_files(ctrl);
return 0;
@@ -1502,6 +1517,7 @@ static int __init cpqhpc_init(void)
cpqhp_debug = debug;
info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ cpqhp_initialize_debugfs();
result = pci_register_driver(&cpqhpc_driver);
dbg("pci_register_driver = %d\n", result);
return result;
@@ -1515,6 +1531,7 @@ static void __exit cpqhpc_cleanup(void)
dbg("pci_unregister_driver\n");
pci_unregister_driver(&cpqhpc_driver);
+ cpqhp_shutdown_debugfs();
}
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 10a5a7674a8a..771ed34b1819 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -2630,29 +2630,15 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
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 */
- temp_word = p_mem_node->base >> 16;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- temp_word = (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);
+ memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+ p_mem_node->next = NULL;
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+ /* set Pre Mem base and Limit registers */
+ temp_word = p_mem_node->base >> 16;
+ rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
- kfree(hold_p_mem_node);
- hold_p_mem_node = NULL;
- }
+ temp_word = (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);
/* Adjust this to compensate for extra adjustment in first loop */
irqs.barber_pole--;
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 4c11048ad51b..bbfeed767ff1 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -33,22 +33,15 @@
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
+#include <linux/debugfs.h>
#include "cpqphp.h"
-
-/* A few routines that create sysfs entries for the hot plug controller */
-
-static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
+static int show_ctrl (struct controller *ctrl, char *buf)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
- char * out = buf;
+ char *out = buf;
int index;
struct pci_resource *res;
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
-
out += sprintf(buf, "Free resources: memory\n");
index = 11;
res = ctrl->mem_head;
@@ -80,22 +73,16 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
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)
+static int show_dev (struct controller *ctrl, char *buf)
{
- 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;
+ slot = ctrl->slot;
while (slot) {
new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
@@ -134,10 +121,117 @@ static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char
return out - buf;
}
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
-void cpqhp_create_ctrl_files (struct controller *ctrl)
+static int spew_debug_info(struct controller *ctrl, char *data, int size)
{
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+ int used;
+
+ used = size - show_ctrl(ctrl, data);
+ used = (size - used) - show_dev(ctrl, &data[used]);
+ return used;
+}
+
+struct ctrl_dbg {
+ int size;
+ char *data;
+ struct controller *ctrl;
+};
+
+#define MAX_OUTPUT (4*PAGE_SIZE)
+
+static int open(struct inode *inode, struct file *file)
+{
+ struct controller *ctrl = inode->u.generic_ip;
+ struct ctrl_dbg *dbg;
+ int retval = -ENOMEM;
+
+ lock_kernel();
+ dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
+ if (!dbg)
+ goto exit;
+ dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
+ if (!dbg->data) {
+ kfree(dbg);
+ goto exit;
+ }
+ dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT);
+ file->private_data = dbg;
+ retval = 0;
+exit:
+ unlock_kernel();
+ return retval;
+}
+
+static loff_t lseek(struct file *file, loff_t off, int whence)
+{
+ struct ctrl_dbg *dbg;
+ loff_t new = -1;
+
+ lock_kernel();
+ dbg = file->private_data;
+
+ switch (whence) {
+ case 0:
+ new = off;
+ break;
+ case 1:
+ new = file->f_pos + off;
+ break;
+ }
+ if (new < 0 || new > dbg->size) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ unlock_kernel();
+ return (file->f_pos = new);
}
+
+static ssize_t read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct ctrl_dbg *dbg = file->private_data;
+ return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size);
+}
+
+static int release(struct inode *inode, struct file *file)
+{
+ struct ctrl_dbg *dbg = file->private_data;
+
+ kfree(dbg->data);
+ kfree(dbg);
+ return 0;
+}
+
+static struct file_operations debug_ops = {
+ .owner = THIS_MODULE,
+ .open = open,
+ .llseek = lseek,
+ .read = read,
+ .release = release,
+};
+
+static struct dentry *root;
+
+void cpqhp_initialize_debugfs(void)
+{
+ if (!root)
+ root = debugfs_create_dir("cpqhp", NULL);
+}
+
+void cpqhp_shutdown_debugfs(void)
+{
+ debugfs_remove(root);
+}
+
+void cpqhp_create_debugfs_files(struct controller *ctrl)
+{
+ ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops);
+}
+
+void cpqhp_remove_debugfs_files(struct controller *ctrl)
+{
+ if (ctrl->dentry)
+ debugfs_remove(ctrl->dentry);
+ ctrl->dentry = NULL;
+}
+
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index b1ba429e0a2d..155133fe5c12 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -969,7 +969,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
debug ("io 32\n");
need_io_upper = TRUE;
}
- if ((io_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+ if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
debug ("pfmem 64\n");
need_pfmem_upper = TRUE;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 6a61b9f286e1..0aac6a61337d 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -32,6 +32,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/sched.h> /* signal_pending() */
#include <linux/pcieport_if.h>
#include "pci_hotplug.h"
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 8df704860348..4fb569018a24 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -103,7 +103,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
static int init_slots(struct controller *ctrl)
{
- struct slot *new_slot;
+ struct slot *slot;
+ struct hpc_ops *hpc_ops;
+ struct hotplug_slot *hotplug_slot;
+ struct hotplug_slot_info *hotplug_slot_info;
u8 number_of_slots;
u8 slot_device;
u32 slot_number;
@@ -114,59 +117,66 @@ static int init_slots(struct controller *ctrl)
slot_number = ctrl->first_slot;
while (number_of_slots) {
- new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
- if (!new_slot)
+ slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
goto error;
- memset(new_slot, 0, sizeof(struct slot));
- new_slot->hotplug_slot =
- kmalloc(sizeof(*(new_slot->hotplug_slot)),
+ memset(slot, 0, sizeof(struct slot));
+ slot->hotplug_slot =
+ kmalloc(sizeof(*(slot->hotplug_slot)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot)
+ if (!slot->hotplug_slot)
goto error_slot;
- memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+ hotplug_slot = slot->hotplug_slot;
+ memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
- new_slot->hotplug_slot->info =
- kmalloc(sizeof(*(new_slot->hotplug_slot->info)),
+ hotplug_slot->info =
+ kmalloc(sizeof(*(hotplug_slot->info)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot->info)
+ if (!hotplug_slot->info)
goto error_hpslot;
- memset(new_slot->hotplug_slot->info, 0,
+ hotplug_slot_info = hotplug_slot->info;
+ memset(hotplug_slot_info, 0,
sizeof(struct hotplug_slot_info));
- new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE,
- GFP_KERNEL);
- if (!new_slot->hotplug_slot->name)
+ hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+ if (!hotplug_slot->name)
goto error_info;
- new_slot->ctrl = ctrl;
- new_slot->bus = ctrl->slot_bus;
- new_slot->device = slot_device;
- new_slot->hpc_ops = ctrl->hpc_ops;
+ slot->ctrl = ctrl;
+ slot->bus = ctrl->slot_bus;
+ slot->device = slot_device;
+ slot->hpc_ops = hpc_ops = ctrl->hpc_ops;
- new_slot->number = ctrl->first_slot;
- new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
+ slot->number = ctrl->first_slot;
+ slot->hp_slot = slot_device - ctrl->slot_device_offset;
/* register this slot with the hotplug pci core */
- new_slot->hotplug_slot->private = new_slot;
- new_slot->hotplug_slot->release = &release_slot;
- make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
- new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops;
-
- new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
- new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
- new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
- new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
-
- dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n",
- new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
- result = pci_hp_register (new_slot->hotplug_slot);
+ hotplug_slot->private = slot;
+ hotplug_slot->release = &release_slot;
+ make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
+ hotplug_slot->ops = &pciehp_hotplug_slot_ops;
+
+ hpc_ops->get_power_status(slot,
+ &(hotplug_slot_info->power_status));
+ hpc_ops->get_attention_status(slot,
+ &(hotplug_slot_info->attention_status));
+ hpc_ops->get_latch_status(slot,
+ &(hotplug_slot_info->latch_status));
+ hpc_ops->get_adapter_status(slot,
+ &(hotplug_slot_info->adapter_status));
+
+ dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
+ "slot_device_offset=%x\n",
+ slot->bus, slot->device, slot->hp_slot, slot->number,
+ ctrl->slot_device_offset);
+ result = pci_hp_register(hotplug_slot);
if (result) {
err ("pci_hp_register failed with error %d\n", result);
goto error_name;
}
- new_slot->next = ctrl->slot;
- ctrl->slot = new_slot;
+ slot->next = ctrl->slot;
+ ctrl->slot = slot;
number_of_slots--;
slot_device++;
@@ -176,13 +186,13 @@ static int init_slots(struct controller *ctrl)
return 0;
error_name:
- kfree(new_slot->hotplug_slot->name);
+ kfree(hotplug_slot->name);
error_info:
- kfree(new_slot->hotplug_slot->info);
+ kfree(hotplug_slot_info);
error_hpslot:
- kfree(new_slot->hotplug_slot);
+ kfree(hotplug_slot);
error_slot:
- kfree(new_slot);
+ kfree(slot);
error:
return result;
}
@@ -502,7 +512,7 @@ static void __exit unload_pciehpd(void)
}
-int hpdriver_context = 0;
+static int hpdriver_context = 0;
static void pciehp_remove (struct pcie_device *device)
{
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0b8b26beb163..77e530321de2 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -30,6 +30,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/signal.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@@ -784,8 +787,13 @@ static int hpc_power_on_slot(struct slot * slot)
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
+ /* Enable detection that we turned off at slot power-off time */
if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ slot_cmd = slot_cmd |
+ PWR_FAULT_DETECT_ENABLE |
+ MRL_DETECT_ENABLE |
+ PRSN_DETECT_ENABLE |
+ HP_INTR_ENABLE;
retval = pcie_write_cmd(slot, slot_cmd);
@@ -830,8 +838,18 @@ static int hpc_power_off_slot(struct slot * slot)
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
+ /*
+ * If we get MRL or presence detect interrupts now, the isr
+ * will notice the sticky power-fault bit too and issue power
+ * indicator change commands. This will lead to an endless loop
+ * of command completions, since the power-fault bit remains on
+ * till the slot is powered on again.
+ */
if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ slot_cmd = (slot_cmd &
+ ~PWR_FAULT_DETECT_ENABLE &
+ ~MRL_DETECT_ENABLE &
+ ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
retval = pcie_write_cmd(slot, slot_cmd);
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 647673a7d224..4017fb03a0b8 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -34,6 +34,31 @@
#include "../pci.h"
#include "pciehp.h"
+static int pciehp_add_bridge(struct pci_dev *dev)
+{
+ struct pci_bus *parent = dev->bus;
+ int pass, busnr, start = parent->secondary;
+ int end = parent->subordinate;
+
+ for (busnr = start; busnr <= end; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(parent), busnr))
+ break;
+ }
+ if (busnr-- > end) {
+ err("No bus number available for hot-added bridge %s\n",
+ pci_name(dev));
+ return -1;
+ }
+ for (pass = 0; pass < 2; pass++)
+ busnr = pci_scan_bridge(parent, dev, busnr, pass);
+ if (!dev->subordinate)
+ return -1;
+ pci_bus_size_bridges(dev->subordinate);
+ pci_bus_assign_resources(parent);
+ pci_enable_bridges(parent);
+ pci_bus_add_devices(parent);
+ return 0;
+}
int pciehp_configure_device(struct slot *p_slot)
{
@@ -55,8 +80,8 @@ int pciehp_configure_device(struct slot *p_slot)
}
for (fn = 0; fn < 8; fn++) {
- if (!(dev = pci_find_slot(p_slot->bus,
- PCI_DEVFN(p_slot->device, fn))))
+ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
+ if (!dev)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot hot-add display device %s\n",
@@ -65,27 +90,7 @@ int pciehp_configure_device(struct slot *p_slot)
}
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;
- }
- if (busnr >= end) {
- err("No free bus for hot-added bridge\n");
- continue;
- }
- 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);
+ pciehp_add_bridge(dev);
}
/* TBD: program firmware provided _HPP values */
/* program_fw_provided_values(dev); */
@@ -93,7 +98,6 @@ int pciehp_configure_device(struct slot *p_slot)
pci_bus_assign_resources(parent);
pci_bus_add_devices(parent);
- pci_enable_bridges(parent);
return 0;
}
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index ae244e218620..2bdb30f68bf8 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -174,7 +174,9 @@ int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
acpi_status status;
acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
struct pci_dev *pdev = dev;
+ struct pci_bus *parent;
u8 *path_name;
+
/*
* Per PCI firmware specification, we should run the ACPI _OSC
* method to get control of hotplug hardware before using it.
@@ -190,17 +192,18 @@ int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
*/
if (!pdev || !pdev->bus->parent)
break;
+ parent = pdev->bus->parent;
dbg("Could not find %s in acpi namespace, trying parent\n",
pci_name(pdev));
- if (!pdev->bus->parent->self)
+ if (!parent->self)
/* Parent must be a host bridge */
handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(pdev->bus->parent),
- pdev->bus->parent->number);
+ pci_domain_nr(parent),
+ parent->number);
else
handle = DEVICE_ACPI_HANDLE(
- &(pdev->bus->parent->self->dev));
- pdev = pdev->bus->parent->self;
+ &(parent->self->dev));
+ pdev = parent->self;
}
while (handle) {
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index cc03609f45d0..7d93dbaf628d 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -112,28 +112,6 @@ static struct slot *find_slot(struct device_node *dn)
return NULL;
}
-static void rpadlpar_claim_one_bus(struct pci_bus *b)
-{
- struct list_head *ld;
- struct pci_bus *child_bus;
-
- for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
- struct pci_dev *dev = pci_dev_b(ld);
- int i;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *r = &dev->resource[i];
-
- if (r->parent || !r->start || !r->flags)
- continue;
- rpaphp_claim_resource(dev, i);
- }
- }
-
- list_for_each_entry(child_bus, &b->children, node)
- rpadlpar_claim_one_bus(child_bus);
-}
-
static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
struct device_node *dev_dn)
{
@@ -154,7 +132,8 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
struct pci_controller *phb = pdn->phb;
struct pci_dev *dev = NULL;
- rpaphp_eeh_init_nodes(dn);
+ eeh_add_device_tree_early(dn);
+
/* Add EADS device to PHB bus, adding new entry to bus->devices */
dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
if (!dev) {
@@ -170,7 +149,7 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
rpaphp_init_new_devs(dev->subordinate);
/* Claim new bus resources */
- rpadlpar_claim_one_bus(dev->bus);
+ pcibios_claim_one_bus(dev->bus);
/* ioremap() for child bus, which may or may not succeed */
(void) remap_bus_range(dev->bus);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 4b35097b3d9f..396b54b0c847 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -62,28 +62,6 @@ struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
-int rpaphp_claim_resource(struct pci_dev *dev, int resource)
-{
- struct resource *res = &dev->resource[resource];
- struct resource *root = pci_find_parent_resource(dev, res);
- char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
- int err = -EINVAL;
-
- if (root != NULL) {
- err = request_resource(root, res);
- }
-
- if (err) {
- err("PCI: %s region %d of %s %s [%lx:%lx]\n",
- root ? "Address space collision on" :
- "No parent found for",
- resource, dtype, pci_name(dev), res->start, res->end);
- }
- return err;
-}
-
-EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
-
static int rpaphp_get_sensor_state(struct slot *slot, int *state)
{
int rc;
@@ -177,7 +155,7 @@ void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
if (r->parent || !r->start || !r->flags)
continue;
- rpaphp_claim_resource(dev, i);
+ pci_claim_resource(dev, i);
}
}
}
@@ -287,18 +265,6 @@ rpaphp_pci_config_slot(struct pci_bus *bus)
return dev;
}
-void rpaphp_eeh_init_nodes(struct device_node *dn)
-{
- struct device_node *sib;
-
- for (sib = dn->child; sib; sib = sib->sibling)
- rpaphp_eeh_init_nodes(sib);
- eeh_add_device_early(dn);
- return;
-
-}
-EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes);
-
static void print_slot_pci_funcs(struct pci_bus *bus)
{
struct device_node *dn;
@@ -324,7 +290,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus)
if (!dn)
goto exit;
- rpaphp_eeh_init_nodes(dn);
+ eeh_add_device_tree_early(dn);
dev = rpaphp_pci_config_slot(bus);
if (!dev) {
err("%s: can't find any devices.\n", __FUNCTION__);
@@ -370,13 +336,14 @@ EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
static int setup_pci_hotplug_slot_info(struct slot *slot)
{
+ struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
+
dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
__FUNCTION__);
- rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status);
+ rpaphp_get_power_status(slot, &hotplug_slot_info->power_status);
rpaphp_get_pci_adapter_status(slot, 1,
- &slot->hotplug_slot->info->
- adapter_status);
- if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
+ &hotplug_slot_info->adapter_status);
+ if (hotplug_slot_info->adapter_status == NOT_VALID) {
err("%s: NOT_VALID: skip dn->full_name=%s\n",
__FUNCTION__, slot->dn->full_name);
return -EINVAL;
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 08ad26a0cae7..ce0e9b6ce833 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -98,6 +98,10 @@ struct controller {
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
+ u32 cap_offset;
+ unsigned long mmio_base;
+ unsigned long mmio_size;
+ volatile int cmd_busy;
};
struct hotplug_params {
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 63628e01dd43..a2b3f0010cec 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -65,6 +65,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
+static int get_address (struct hotplug_slot *slot, u32 *value);
static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
@@ -77,6 +78,7 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
.get_attention_status = get_attention_status,
.get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status,
+ .get_address = get_address,
.get_max_bus_speed = get_max_bus_speed,
.get_cur_bus_speed = get_cur_bus_speed,
};
@@ -314,6 +316,18 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
+static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+
+ dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+ *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+
+ return 0;
+}
+
static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
@@ -377,8 +391,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_ctrl;
}
- ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
-
pci_set_drvdata(pdev, ctrl);
ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 58619359ad08..25ccb0e47593 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -248,7 +248,6 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
up(&ctrl->crit_sect);
return WRONG_BUS_FREQUENCY;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
@@ -330,9 +329,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return -1;
}
-
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
if (rc) {
@@ -352,7 +348,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return WRONG_BUS_FREQUENCY;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
@@ -367,7 +362,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
@@ -494,7 +488,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
@@ -532,9 +525,6 @@ static int board_added(struct slot *p_slot)
p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -552,8 +542,6 @@ err_exit:
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) {
@@ -603,8 +591,6 @@ static int remove_board(struct slot *p_slot)
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) {
@@ -621,8 +607,6 @@ static int remove_board(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -676,9 +660,6 @@ static void shpchp_pushbutton_thread (unsigned long slot)
p_slot->hpc_ops->green_led_off(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (p_slot->ctrl);
-
/* Done with exclusive hardware access */
up(&p_slot->ctrl->crit_sect);
}
@@ -790,14 +771,9 @@ static void interrupt_event_handler(struct controller *ctrl)
down(&ctrl->crit_sect);
p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
break;
@@ -806,12 +782,8 @@ static void interrupt_event_handler(struct controller *ctrl)
down(&ctrl->crit_sect);
p_slot->hpc_ops->green_led_off(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -845,14 +817,9 @@ static void interrupt_event_handler(struct controller *ctrl)
/* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -870,12 +837,8 @@ static void interrupt_event_handler(struct controller *ctrl)
down(&ctrl->crit_sect);
p_slot->hpc_ops->set_attention_status(p_slot, 1);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->green_led_off(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 9987a6fd65b8..b4226ff3a854 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -275,6 +275,25 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
return;
}
+static inline int shpc_wait_cmd(struct controller *ctrl)
+{
+ int retval = 0;
+ unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000;
+ unsigned long timeout = msecs_to_jiffies(timeout_msec);
+ int rc = wait_event_interruptible_timeout(ctrl->queue,
+ !ctrl->cmd_busy, timeout);
+ if (!rc) {
+ retval = -EIO;
+ err("Command not completed in %d msec\n", timeout_msec);
+ } else if (rc < 0) {
+ retval = -EINTR;
+ info("Command was interrupted by a signal\n");
+ }
+ ctrl->cmd_busy = 0;
+
+ return retval;
+}
+
static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
{
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
@@ -314,8 +333,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
/* To make sure the Controller Busy bit is 0 before we send out the
* command.
*/
+ slot->ctrl->cmd_busy = 1;
writew(temp_word, php_ctlr->creg + CMD);
+ /*
+ * Wait for command completion.
+ */
+ retval = shpc_wait_cmd(slot->ctrl);
+
DBG_LEAVE_ROUTINE
return retval;
}
@@ -604,7 +629,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
if (pi == 2) {
- *mode = (sec_bus_status & 0x0100) >> 7;
+ *mode = (sec_bus_status & 0x0100) >> 8;
} else {
retval = -1;
}
@@ -791,7 +816,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
}
if (php_ctlr->pci_dev) {
iounmap(php_ctlr->creg);
- release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
+ release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
php_ctlr->pci_dev = NULL;
}
@@ -1058,12 +1083,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if (intr_loc & 0x0001) {
/*
* Command Complete Interrupt Pending
- * RO only - clear by writing 0 to the Command Completion
+ * RO only - clear by writing 1 to the Command Completion
* Detect bit in Controller SERR-INT register
*/
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- temp_dword &= 0xfffeffff;
+ temp_dword &= 0xfffdffff;
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+ ctrl->cmd_busy = 0;
wake_up_interruptible(&ctrl->queue);
}
@@ -1121,7 +1147,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
int retval = 0;
u8 pi;
u32 slot_avail1, slot_avail2;
- int slot_num;
DBG_ENTER_ROUTINE
@@ -1140,39 +1165,39 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
if (pi == 2) {
- if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27) ) != 0 )
+ if (slot_avail2 & SLOT_133MHZ_PCIX_533)
bus_speed = PCIX_133MHZ_533;
- else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23) ) != 0 )
+ else if (slot_avail2 & SLOT_100MHZ_PCIX_533)
bus_speed = PCIX_100MHZ_533;
- else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19) ) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ_PCIX_533)
bus_speed = PCIX_66MHZ_533;
- else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15) ) != 0 )
+ else if (slot_avail2 & SLOT_133MHZ_PCIX_266)
bus_speed = PCIX_133MHZ_266;
- else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11) ) != 0 )
+ else if (slot_avail2 & SLOT_100MHZ_PCIX_266)
bus_speed = PCIX_100MHZ_266;
- else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7) ) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ_PCIX_266)
bus_speed = PCIX_66MHZ_266;
- else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 )
+ else if (slot_avail1 & SLOT_133MHZ_PCIX)
bus_speed = PCIX_133MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 )
+ else if (slot_avail1 & SLOT_100MHZ_PCIX)
bus_speed = PCIX_100MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 )
+ else if (slot_avail1 & SLOT_66MHZ_PCIX)
bus_speed = PCIX_66MHZ;
- else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ)
bus_speed = PCI_66MHZ;
- else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 )
+ else if (slot_avail1 & SLOT_33MHZ)
bus_speed = PCI_33MHZ;
else bus_speed = PCI_SPEED_UNKNOWN;
} else {
- if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 )
+ if (slot_avail1 & SLOT_133MHZ_PCIX)
bus_speed = PCIX_133MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 )
+ else if (slot_avail1 & SLOT_100MHZ_PCIX)
bus_speed = PCIX_100MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 )
+ else if (slot_avail1 & SLOT_66MHZ_PCIX)
bus_speed = PCIX_66MHZ;
- else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ)
bus_speed = PCI_66MHZ;
- else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 )
+ else if (slot_avail1 & SLOT_33MHZ)
bus_speed = PCI_33MHZ;
else bus_speed = PCI_SPEED_UNKNOWN;
}
@@ -1321,19 +1346,34 @@ static struct hpc_ops shpchp_hpc_ops = {
.check_cmd_status = hpc_check_cmd_status,
};
+inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
+ u32 *value)
+{
+ int rc;
+ u32 cap_offset = ctrl->cap_offset;
+ struct pci_dev *pdev = ctrl->pci_dev;
+
+ rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
+ if (rc)
+ return rc;
+ return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
+}
+
int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
{
struct php_ctlr_state_s *php_ctlr, *p;
void *instance_id = ctrl;
- int rc;
+ int rc, num_slots = 0;
u8 hp_slot;
static int first = 1;
- u32 shpc_cap_offset, shpc_base_offset;
+ u32 shpc_base_offset;
u32 tempdword, slot_reg;
u8 i;
DBG_ENTER_ROUTINE
+ ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
+
spin_lock_init(&list_lock);
php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
@@ -1348,41 +1388,45 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
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 */
+ /* amd shpc driver doesn't use Base Offset; assume 0 */
+ ctrl->mmio_base = pci_resource_start(pdev, 0);
+ ctrl->mmio_size = pci_resource_len(pdev, 0);
} else {
- if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
- err("%s : shpc_cap_offset == 0\n", __FUNCTION__);
+ ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
+ if (!ctrl->cap_offset) {
+ err("%s : cap_offset == 0\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset);
-
- rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET);
+ dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
+
+ rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset);
if (rc) {
- err("%s : pci_word_config_byte failed\n", __FUNCTION__);
+ err("%s: cannot read base_offset\n", __FUNCTION__);
goto abort_free_ctlr;
}
-
- rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset);
+
+ rc = shpc_indirect_creg_read(ctrl, 3, &tempdword);
if (rc) {
- err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+ err("%s: cannot read slot config\n", __FUNCTION__);
goto abort_free_ctlr;
}
+ num_slots = tempdword & SLOT_NUM;
+ dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
- for (i = 0; i <= 14; i++) {
- rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i);
- if (rc) {
- err("%s : pci_word_config_byte failed\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword);
+ for (i = 0; i < 9 + num_slots; i++) {
+ rc = shpc_indirect_creg_read(ctrl, i, &tempdword);
if (rc) {
- err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+ err("%s: cannot read creg (index = %d)\n",
+ __FUNCTION__, i);
goto abort_free_ctlr;
}
dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
tempdword);
}
+
+ ctrl->mmio_base =
+ pci_resource_start(pdev, 0) + shpc_base_offset;
+ ctrl->mmio_size = 0x24 + 0x4 * num_slots;
}
if (first) {
@@ -1396,16 +1440,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
if (pci_enable_device(pdev))
goto abort_free_ctlr;
- if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) {
+ if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
err("%s: cannot reserve MMIO region\n", __FUNCTION__);
goto abort_free_ctlr;
}
- php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
+ php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
if (!php_ctlr->creg) {
- err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0),
- pci_resource_start(pdev, 0) + shpc_base_offset);
- release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
+ err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
+ ctrl->mmio_size, ctrl->mmio_base);
+ release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
goto abort_free_ctlr;
}
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 38009bc0fd5d..19e1a5e1e30b 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -89,10 +89,11 @@ int shpchp_configure_device(struct slot *p_slot)
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));
+ dev = pci_get_slot(parent, 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);
+ pci_dev_put(dev);
return -EINVAL;
}
@@ -103,12 +104,13 @@ int shpchp_configure_device(struct slot *p_slot)
}
for (fn = 0; fn < 8; fn++) {
- if (!(dev = pci_find_slot(p_slot->bus,
- PCI_DEVFN(p_slot->device, fn))))
+ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
+ if (!dev)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot hot-add display device %s\n",
pci_name(dev));
+ pci_dev_put(dev);
continue;
}
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
@@ -124,18 +126,21 @@ int shpchp_configure_device(struct slot *p_slot)
}
if (busnr >= end) {
err("No free bus for hot-added bridge\n");
+ pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
err("Cannot add new bus for %s\n",
pci_name(dev));
+ pci_dev_put(dev);
continue;
}
child->subordinate = pci_do_scan_bus(child);
pci_bus_size_bridges(child);
}
program_fw_provided_values(dev);
+ pci_dev_put(dev);
}
pci_bus_assign_resources(parent);
@@ -149,17 +154,19 @@ int shpchp_unconfigure_device(struct slot *p_slot)
int rc = 0;
int j;
u8 bctl = 0;
-
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
for (j=0; j<8 ; j++) {
- struct pci_dev* temp = pci_find_slot(p_slot->bus,
+ struct pci_dev* temp = pci_get_slot(parent,
(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));
+ pci_dev_put(temp);
continue;
}
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
@@ -167,10 +174,12 @@ int shpchp_unconfigure_device(struct slot *p_slot)
if (bctl & PCI_BRIDGE_CTL_VGA) {
err("Cannot remove display device %s\n",
pci_name(temp));
+ pci_dev_put(temp);
continue;
}
}
pci_remove_bus_device(temp);
+ pci_dev_put(temp);
}
return rc;
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 7146b69b812c..0aa14c92b570 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
- drv->driver.probe = pci_device_probe;
- drv->driver.remove = pci_device_remove;
/* FIXME, once all of the existing PCI drivers have been fixed to set
* the pci shutdown function, this test can go away. */
if (!drv->driver.shutdown)
@@ -513,6 +511,8 @@ struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
.uevent = pci_uevent,
+ .probe = pci_device_probe,
+ .remove = pci_device_remove,
.suspend = pci_device_suspend,
.resume = pci_device_resume,
.dev_attrs = pci_dev_attrs,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8e287a828d5d..d2a633efa10a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -19,6 +19,7 @@
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
+#if 0
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
@@ -63,6 +64,8 @@ pci_max_busnr(void)
return max;
}
+#endif /* 0 */
+
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
{
u8 id;
@@ -587,7 +590,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
{
u8 pin;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin)
return -1;
pin--;
@@ -917,8 +920,6 @@ EXPORT_SYMBOL_GPL(pci_restore_bars);
EXPORT_SYMBOL(pci_enable_device_bars);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_device);
-EXPORT_SYMBOL(pci_max_busnr);
-EXPORT_SYMBOL(pci_bus_max_busnr);
EXPORT_SYMBOL(pci_find_capability);
EXPORT_SYMBOL(pci_bus_find_capability);
EXPORT_SYMBOL(pci_release_regions);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 294849d24590..a6dfee2f6d2b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -26,20 +26,15 @@ extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
extern int pci_proc_detach_device(struct pci_dev *dev);
-extern int pci_proc_attach_bus(struct pci_bus *bus);
extern int pci_proc_detach_bus(struct pci_bus *bus);
#else
static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; }
static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; }
-static inline int pci_proc_attach_bus(struct pci_bus *bus) { return 0; }
static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
#endif
/* Functions for PCI Hotplug drivers to use */
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);
-extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
extern void pci_remove_legacy_files(struct pci_bus *bus);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 467a4ceccf10..e4e5f1e8d816 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -238,8 +238,8 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
device->driver = NULL;
device->driver_data = NULL;
device->release = release_pcie_device; /* callback to free pcie dev */
- sprintf(&device->bus_id[0], "pcie%02x",
- get_descriptor_id(port_type, service_type));
+ snprintf(device->bus_id, sizeof(device->bus_id), "%s:pcie%02x",
+ pci_name(parent), get_descriptor_id(port_type, service_type));
device->parent = &parent->dev;
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fce2cb2112d8..adfad4fd6a13 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -264,8 +264,10 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
- res->start = base;
- res->end = limit + 0xfff;
+ if (!res->start)
+ res->start = base;
+ if (!res->end)
+ res->end = limit + 0xfff;
}
res = child->resource[1];
@@ -431,7 +433,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
{
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
- u32 buses, i;
+ u32 buses, i, j = 0;
u16 bctl;
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
@@ -541,10 +543,29 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
* as cards with a PCI-to-PCI bridge can be
* inserted later.
*/
- for (i=0; i<CARDBUS_RESERVE_BUSNR; i++)
+ for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) {
+ struct pci_bus *parent = bus;
if (pci_find_bus(pci_domain_nr(bus),
max+i+1))
break;
+ while (parent->parent) {
+ if ((!pcibios_assign_all_busses()) &&
+ (parent->subordinate > max) &&
+ (parent->subordinate <= max+i)) {
+ j = 1;
+ }
+ parent = parent->parent;
+ }
+ if (j) {
+ /*
+ * Often, there are two cardbus bridges
+ * -- try to leave one valid bus number
+ * for each one.
+ */
+ i /= 2;
+ break;
+ }
+ }
max += i;
pci_fixup_parent_subordinate_busnr(child, max);
}
@@ -559,6 +580,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
+ while (bus->parent) {
+ if ((child->subordinate > bus->subordinate) ||
+ (child->number > bus->subordinate) ||
+ (child->number < bus->number) ||
+ (child->subordinate < bus->number)) {
+ printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be "
+ "hidden behind%s bridge #%02x (-#%02x)%s\n",
+ child->number, child->subordinate,
+ bus->self->transparent ? " transparent" : " ",
+ bus->number, bus->subordinate,
+ pcibios_assign_all_busses() ? " " :
+ " (try 'pci=assign-busses')");
+ }
+ bus = bus->parent;
+ }
+
return max;
}
@@ -571,6 +608,7 @@ static void pci_read_irq(struct pci_dev *dev)
unsigned char irq;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
+ dev->pin = irq;
if (irq)
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
dev->irq = irq;
@@ -624,6 +662,7 @@ static int pci_setup_device(struct pci_dev * dev)
/* The PCI-to-PCI bridge spec requires that subtractive
decoding (i.e. transparent) bridge must have programming
interface code of 0x01. */
+ pci_read_irq(dev);
dev->transparent = ((dev->class & 0xff) == 1);
pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
break;
@@ -678,7 +717,7 @@ static void pci_release_dev(struct device *dev)
* reading the dword at 0x100 which must either be 0 or a valid extended
* capability header.
*/
-static int pci_cfg_space_size(struct pci_dev *dev)
+int pci_cfg_space_size(struct pci_dev *dev)
{
int pos;
u32 status;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 9eb465727fce..92a885760832 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -25,7 +25,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
loff_t new = -1;
struct inode *inode = file->f_dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
switch (whence) {
case 0:
new = off;
@@ -41,7 +41,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
new = -EINVAL;
else
file->f_pos = new;
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return new;
}
@@ -431,6 +431,7 @@ int pci_proc_detach_device(struct pci_dev *dev)
return 0;
}
+#if 0
int pci_proc_attach_bus(struct pci_bus* bus)
{
struct proc_dir_entry *de = bus->procdir;
@@ -447,6 +448,7 @@ int pci_proc_attach_bus(struct pci_bus* bus)
}
return 0;
}
+#endif /* 0 */
int pci_proc_detach_bus(struct pci_bus* bus)
{
@@ -612,7 +614,6 @@ __initcall(pci_proc_init);
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_proc_attach_device);
-EXPORT_SYMBOL(pci_proc_attach_bus);
EXPORT_SYMBOL(pci_proc_detach_bus);
#endif
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index f28ebdd3958a..dda6099903c1 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1142,6 +1142,9 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
case 0x27c4:
ich = 7;
break;
+ case 0x2828: /* ICH8M */
+ ich = 8;
+ break;
default:
/* we do not handle this PCI device */
return;
@@ -1161,7 +1164,7 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
else
return; /* not in combined mode */
} else {
- WARN_ON((ich != 6) && (ich != 7));
+ WARN_ON((ich != 6) && (ich != 7) && (ich != 8));
tmp &= 0x3; /* interesting bits 1:0 */
if (tmp & (1 << 0))
comb = (1 << 2); /* PATA port 0, SATA port 1 */
@@ -1342,6 +1345,32 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
pci_do_fixups(dev, start, end);
}
+/* Enable 1k I/O space granularity on the Intel P64H2 */
+static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
+{
+ u16 en1k;
+ u8 io_base_lo, io_limit_lo;
+ unsigned long base, limit;
+ struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
+
+ pci_read_config_word(dev, 0x40, &en1k);
+
+ if (en1k & 0x200) {
+ printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n");
+
+ pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+ pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+ base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
+ limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
+
+ if (base <= limit) {
+ res->start = base;
+ res->end = limit + 0x3ff;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
+
EXPORT_SYMBOL(pcie_mch_quirk);
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_fixup_device);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 27a294b6965d..1a6bf9de166f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -48,6 +48,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
* in question is not being used by a driver.
* Returns 0 on success.
*/
+#if 0
int pci_remove_device_safe(struct pci_dev *dev)
{
if (pci_dev_driver(dev))
@@ -55,7 +56,7 @@ int pci_remove_device_safe(struct pci_dev *dev)
pci_destroy_dev(dev);
return 0;
}
-EXPORT_SYMBOL(pci_remove_device_safe);
+#endif /* 0 */
void pci_remove_bus(struct pci_bus *pci_bus)
{
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0252582b91cd..0a424a4e8187 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -311,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
/* initialize common fields */
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
- driver->drv.probe = pcmcia_device_probe;
- driver->drv.remove = pcmcia_device_remove;
return driver_register(&driver->drv);
}
@@ -920,6 +918,37 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]);
pcmcia_device_stringattr(prod_id3, prod_id[2]);
pcmcia_device_stringattr(prod_id4, prod_id[3]);
+
+static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+ if (p_dev->dev.power.power_state.event != PM_EVENT_ON)
+ return sprintf(buf, "off\n");
+ else
+ return sprintf(buf, "on\n");
+}
+
+static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ int ret = 0;
+
+ if (!count)
+ return -EINVAL;
+
+ if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) &&
+ (!strncmp(buf, "off", 3)))
+ ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
+ else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) &&
+ (!strncmp(buf, "on", 2)))
+ dpm_runtime_resume(dev);
+
+ return ret ? ret : count;
+}
+
+
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -945,8 +974,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- if (!count)
- return -EINVAL;
+
+ if (!count)
+ return -EINVAL;
down(&p_dev->socket->skt_sem);
p_dev->allow_func_id_match = 1;
@@ -959,6 +989,7 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
static struct device_attribute pcmcia_dev_attrs[] = {
__ATTR(function, 0444, func_show, NULL),
+ __ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state),
__ATTR_RO(func_id),
__ATTR_RO(manf_id),
__ATTR_RO(card_id),
@@ -1167,6 +1198,8 @@ struct bus_type pcmcia_bus_type = {
.uevent = pcmcia_bus_uevent,
.match = pcmcia_bus_match,
.dev_attrs = pcmcia_dev_attrs,
+ .probe = pcmcia_device_probe,
+ .remove = pcmcia_device_remove,
.suspend = pcmcia_dev_suspend,
.resume = pcmcia_dev_resume,
};
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 5d957dfe23d9..fda06941e730 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -171,27 +171,22 @@ static int __init mst_pcmcia_init(void)
{
int ret;
- mst_pcmcia_device = kzalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL);
+ mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
if (!mst_pcmcia_device)
return -ENOMEM;
- mst_pcmcia_device->name = "pxa2xx-pcmcia";
+
mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
- ret = platform_device_register(mst_pcmcia_device);
+ ret = platform_device_add(mst_pcmcia_device);
+
if (ret)
- kfree(mst_pcmcia_device);
+ platform_device_put(mst_pcmcia_device);
return ret;
}
static void __exit mst_pcmcia_exit(void)
{
- /*
- * This call is supposed to free our mst_pcmcia_device.
- * Unfortunately platform_device don't have a free method, and
- * we can't assume it's free of any reference at this point so we
- * can't free it either.
- */
platform_device_unregister(mst_pcmcia_device);
}
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index b5fdeec20b15..fd3647368955 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -36,9 +36,18 @@
struct scoop_pcmcia_config *platform_scoop_config;
#define SCOOP_DEV platform_scoop_config->devs
-static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev)
+static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
{
+ struct scoop_pcmcia_dev *scoopdev = &SCOOP_DEV[skt->nr];
+
reset_scoop(scoopdev->dev);
+
+ /* Shared power controls need to be handled carefully */
+ if (platform_scoop_config->power_ctrl)
+ platform_scoop_config->power_ctrl(scoopdev->dev, 0x0000, skt->nr);
+ else
+ write_scoop_reg(scoopdev->dev, SCOOP_CPR, 0x0000);
+
scoopdev->keep_vs = NO_KEEP_VS;
scoopdev->keep_rd = 0;
}
@@ -208,26 +217,17 @@ 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_DEV[skt->nr]);
+ sharpsl_pcmcia_init_reset(skt);
/* Enable interrupt */
write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0);
write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101);
SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS;
-
- if (machine_is_collie())
- /* We need to disable SS_OUTPUT_ENA here. */
- write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[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_DEV[skt->nr]);
-
- if (machine_is_collie())
- /* We need to disable SS_OUTPUT_ENA here. */
- write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080);
+ sharpsl_pcmcia_init_reset(skt);
}
static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -263,30 +263,25 @@ static int __init sharpsl_pcmcia_init(void)
{
int ret;
- sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs;
- sharpsl_pcmcia_device = kzalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
+ sharpsl_pcmcia_ops.nr = platform_scoop_config->num_devs;
+ sharpsl_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+
if (!sharpsl_pcmcia_device)
return -ENOMEM;
- sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
- sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev;
+ sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev;
+
+ ret = platform_device_add(sharpsl_pcmcia_device);
- ret = platform_device_register(sharpsl_pcmcia_device);
if (ret)
- kfree(sharpsl_pcmcia_device);
+ platform_device_put(sharpsl_pcmcia_device);
return ret;
}
static void __exit sharpsl_pcmcia_exit(void)
{
- /*
- * This call is supposed to free our sharpsl_pcmcia_device.
- * Unfortunately platform_device don't have a free method, and
- * we can't assume it's free of any reference at this point so we
- * can't free it either.
- */
platform_device_unregister(sharpsl_pcmcia_device);
}
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 7a7744662d54..5ab1cdef7c48 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -98,6 +98,30 @@ static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, si
}
static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
+
+static ssize_t pccard_show_card_pm_state(struct class_device *dev, char *buf)
+{
+ struct pcmcia_socket *s = to_socket(dev);
+ return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on");
+}
+
+static ssize_t pccard_store_card_pm_state(struct class_device *dev, const char *buf, size_t count)
+{
+ ssize_t ret = -EINVAL;
+ struct pcmcia_socket *s = to_socket(dev);
+
+ if (!count)
+ return -EINVAL;
+
+ if (!(s->state & SOCKET_SUSPEND) && !strncmp(buf, "off", 3))
+ ret = pcmcia_suspend_card(s);
+ else if ((s->state & SOCKET_SUSPEND) && !strncmp(buf, "on", 2))
+ ret = pcmcia_resume_card(s);
+
+ return ret ? -ENODEV : count;
+}
+static CLASS_DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state);
+
static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count)
{
ssize_t ret;
@@ -320,6 +344,7 @@ static struct class_device_attribute *pccard_socket_attributes[] = {
&class_device_attr_card_vpp,
&class_device_attr_card_vcc,
&class_device_attr_card_insert,
+ &class_device_attr_card_pm_state,
&class_device_attr_card_eject,
&class_device_attr_card_irq_mask,
&class_device_attr_available_resources_setup_done,
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 24c547ef512b..0574efd7828a 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -1,7 +1,7 @@
/*
* vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
#include "i82365.h"
MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_LICENSE("GPL");
#define CARD_MAX_SLOTS 2
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index 1b277d2c1c96..57f38dba0a48 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -6,7 +6,7 @@
* NEC VRC4173 CARDU driver for Socket Services
* (This device doesn't support CardBus. it is supporting only 16bit PC Card.)
*
- * Copyright 2002,2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -41,7 +41,7 @@
#include "vrc4173_cardu.h"
MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_LICENSE("GPL");
static int vrc4173_cardu_slots;
@@ -561,7 +561,7 @@ static int __devinit vrc4173_cardu_init(void)
{
vrc4173_cardu_slots = 0;
- return pci_module_init(&vrc4173_cardu_driver);
+ return pci_register_driver(&vrc4173_cardu_driver);
}
static void __devexit vrc4173_cardu_exit(void)
diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h
index 113726f7cf92..7d77c74120c1 100644
--- a/drivers/pcmcia/vrc4173_cardu.h
+++ b/drivers/pcmcia/vrc4173_cardu.h
@@ -5,7 +5,7 @@
* BRIEF MODULE DESCRIPTION
* Include file for NEC VRC4173 CARDU.
*
- * Copyright 2002 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 15fb758a9e52..7cafacdd12b0 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -195,6 +195,8 @@ static int pnp_bus_resume(struct device *dev)
struct bus_type pnp_bus_type = {
.name = "pnp",
.match = pnp_bus_match,
+ .probe = pnp_device_probe,
+ .remove = pnp_device_remove,
.suspend = pnp_bus_suspend,
.resume = pnp_bus_resume,
};
@@ -215,8 +217,6 @@ int pnp_register_driver(struct pnp_driver *drv)
drv->driver.name = drv->name;
drv->driver.bus = &pnp_bus_type;
- drv->driver.probe = pnp_device_probe;
- drv->driver.remove = pnp_device_remove;
count = driver_register(&drv->driver);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 816479ad217b..f104577f73e0 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -27,12 +27,15 @@
static int num = 0;
+/* We need only to blacklist devices that have already an acpi driver that
+ * can't use pnp layer. We don't need to blacklist device that are directly
+ * used by the kernel (PCI root, ...), as it is harmless and there were
+ * already present in pnpbios. But there is an exception for devices that
+ * have irqs (PIC, Timer) because we call acpi_register_gsi.
+ * Finaly only devices that have a CRS method need to be in this list.
+ */
static char __initdata excluded_id_list[] =
- "PNP0C0A," /* Battery */
- "PNP0C0C,PNP0C0E,PNP0C0D," /* Button */
"PNP0C09," /* EC */
- "PNP0C0B," /* Fan */
- "PNP0A03," /* PCI root */
"PNP0C0F," /* Link device */
"PNP0000," /* PIC */
"PNP0100," /* Timer */
@@ -131,7 +134,8 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
struct pnp_id *dev_id;
struct pnp_dev *dev;
- if (!ispnpidacpi(acpi_device_hid(device)) ||
+ status = acpi_get_handle(device->handle, "_CRS", &temp);
+ if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
is_exclusive_device(device))
return 0;
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index dc749609699a..5480119ff9d3 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -147,8 +147,6 @@ int rio_register_driver(struct rio_driver *rdrv)
/* initialize common driver fields */
rdrv->driver.name = rdrv->name;
rdrv->driver.bus = &rio_bus_type;
- rdrv->driver.probe = rio_device_probe;
- rdrv->driver.remove = rio_device_remove;
/* register with core */
return driver_register(&rdrv->driver);
@@ -204,7 +202,9 @@ static struct device rio_bus = {
struct bus_type rio_bus_type = {
.name = "rapidio",
.match = rio_match_bus,
- .dev_attrs = rio_dev_attrs
+ .dev_attrs = rio_dev_attrs,
+ .probe = rio_device_probe,
+ .remove = rio_device_remove,
};
/**
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 4f7ed4bd3be9..94e30fe4b8f3 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
#include "rio.h"
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 30a11436e241..bef9316e95df 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -15,6 +15,7 @@
#include <linux/rio.h>
#include <linux/rio_drv.h>
#include <linux/stat.h>
+#include <linux/sched.h> /* for capable() */
#include "rio.h"
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 3ca1011ceaac..5e382470faa2 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -23,6 +23,7 @@
#include <linux/rio_regs.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/slab.h>
#include "rio.h"
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index f779f674dfa0..ef4c687e7c01 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -18,6 +18,7 @@
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/buffer_head.h>
+#include <linux/hdreg.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -1634,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device)
blk_queue_max_hw_segments(device->request_queue, -1L);
blk_queue_max_segment_size(device->request_queue, -1L);
blk_queue_segment_boundary(device->request_queue, -1L);
- blk_queue_ordered(device->request_queue, 1);
+ blk_queue_ordered(device->request_queue, QUEUE_ORDERED_TAG, NULL);
}
/*
@@ -1723,12 +1724,35 @@ dasd_release(struct inode *inp, struct file *filp)
return 0;
}
+/*
+ * Return disk geometry.
+ */
+static int
+dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct dasd_device *device;
+
+ device = bdev->bd_disk->private_data;
+ if (!device)
+ return -ENODEV;
+
+ if (!device->discipline ||
+ !device->discipline->fill_geometry)
+ return -EINVAL;
+
+ device->discipline->fill_geometry(device, geo);
+ geo->start = get_start_sect(bdev) >> device->s2b_shift;
+ return 0;
+}
+
struct block_device_operations
dasd_device_operations = {
.owner = THIS_MODULE,
.open = dasd_open,
.release = dasd_release,
.ioctl = dasd_ioctl,
+ .compat_ioctl = dasd_compat_ioctl,
+ .getgeo = dasd_getgeo,
};
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 2fb05c4a528c..e4b401500b01 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -527,6 +527,7 @@ void dasd_ioctl_exit(void);
int dasd_ioctl_no_register(struct module *, int, dasd_ioctl_fn_t);
int dasd_ioctl_no_unregister(struct module *, int, dasd_ioctl_fn_t);
int dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+long dasd_compat_ioctl(struct file *, unsigned int, unsigned long);
/* externals in dasd_proc.c */
int dasd_proc_init(void);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 044b75371990..9396fcacb8f8 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -118,6 +118,18 @@ dasd_ioctl(struct inode *inp, struct file *filp,
return -EINVAL;
}
+long
+dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int rval;
+
+ lock_kernel();
+ rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
+}
+
static int
dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
{
@@ -486,33 +498,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
}
/*
- * Return disk geometry.
- */
-static int
-dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
-{
- struct hd_geometry geo = { 0, };
- struct dasd_device *device;
-
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
-
- if (device == NULL || device->discipline == NULL ||
- device->discipline->fill_geometry == NULL)
- return -EINVAL;
-
- geo = (struct hd_geometry) {};
- device->discipline->fill_geometry(device, &geo);
- geo.start = get_start_sect(bdev) >> device->s2b_shift;
- if (copy_to_user((struct hd_geometry __user *) args, &geo,
- sizeof (struct hd_geometry)))
- return -EFAULT;
-
- return 0;
-}
-
-/*
* List of static ioctls.
*/
static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
@@ -528,7 +513,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
{ BIODASDPRRST, dasd_ioctl_reset_profile },
{ BLKROSET, dasd_ioctl_set_ro },
{ DASDAPIVER, dasd_ioctl_api_version },
- { HDIO_GETGEO, dasd_ioctl_getgeo },
{ -1, NULL }
};
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index bf3a67c3cc5e..54ecd548c318 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -328,31 +328,27 @@ fail:
return 0;
}
-static int xpram_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct hd_geometry __user *geo;
unsigned long size;
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
+
/*
* get geometry: we have to fake one... trim the size to a
* multiple of 64 (32k): tell we have 16 sectors, 4 heads,
* whatever cylinders. Tell also that data starts at sector. 4.
*/
- geo = (struct hd_geometry __user *) arg;
size = (xpram_pages * 8) & ~0x3f;
- put_user(size >> 6, &geo->cylinders);
- put_user(4, &geo->heads);
- put_user(16, &geo->sectors);
- put_user(4, &geo->start);
+ geo->cylinders = size >> 6;
+ geo->heads = 4;
+ geo->sectors = 16;
+ geo->start = 4;
return 0;
}
static struct block_device_operations xpram_devops =
{
.owner = THIS_MODULE,
- .ioctl = xpram_ioctl,
+ .getgeo = xpram_getgeo,
};
/*
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 75419cf9d353..1f060914cfa4 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/vt_kern.h>
#include <linux/init.h>
#include <linux/console.h>
@@ -432,8 +433,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
if (count > slen)
count = slen;
} else
- if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)
- count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
EBCASC(raw->inbuf, count);
cchar = ctrlchar_handle(raw->inbuf, count, tty);
switch (cchar & CTRLCHAR_MASK) {
@@ -441,28 +440,20 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
break;
case CTRLCHAR_CTRL:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = cchar;
+ tty_insert_flip_char(tty, cchar, TTY_NORMAL);
tty_flip_buffer_push(raw->tty);
break;
case CTRLCHAR_NONE:
- memcpy(tty->flip.char_buf_ptr,
- raw->inbuf, count);
if (count < 2 ||
- (strncmp(raw->inbuf+count-2, "^n", 2) &&
- strncmp(raw->inbuf+count-2, "\252n", 2)) ) {
- /* don't add the auto \n */
- tty->flip.char_buf_ptr[count] = '\n';
- memset(tty->flip.flag_buf_ptr,
- TTY_NORMAL, count + 1);
+ (strncmp(raw->inbuf+count-2, "\252n", 2) &&
+ strncmp(raw->inbuf+count-2, "^n", 2)) ) {
+ /* add the auto \n */
+ raw->inbuf[count] = '\n';
count++;
} else
- count-=2;
- tty->flip.char_buf_ptr += count;
- tty->flip.flag_buf_ptr += count;
- tty->flip.count += count;
+ count -= 2;
+ tty_insert_flip_string(tty, raw->inbuf, count);
tty_flip_buffer_push(raw->tty);
break;
}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 735a7fcdeff5..5f6fa4c67843 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -319,9 +319,8 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
/*
* process ioctl commands for the tube driver
*/
-static int
-fs3270_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static long
+fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct fs3270 *fp;
struct raw3270_iocb iocb;
@@ -331,6 +330,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
if (!fp)
return -ENODEV;
rc = 0;
+ lock_kernel();
switch (cmd) {
case TUBICMD:
fp->read_command = arg;
@@ -356,6 +356,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
rc = -EFAULT;
break;
}
+ unlock_kernel();
return rc;
}
@@ -491,12 +492,13 @@ fs3270_close(struct inode *inode, struct file *filp)
}
static struct file_operations fs3270_fops = {
- .owner = THIS_MODULE, /* owner */
- .read = fs3270_read, /* read */
- .write = fs3270_write, /* write */
- .ioctl = fs3270_ioctl, /* ioctl */
- .open = fs3270_open, /* open */
- .release = fs3270_close, /* release */
+ .owner = THIS_MODULE, /* owner */
+ .read = fs3270_read, /* read */
+ .write = fs3270_write, /* write */
+ .unlocked_ioctl = fs3270_ioctl, /* ioctl */
+ .compat_ioctl = fs3270_ioctl, /* ioctl */
+ .open = fs3270_open, /* open */
+ .release = fs3270_close, /* release */
};
/*
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index a20d7c89341d..6cbf067f1a8f 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -13,6 +13,7 @@
#include <linux/kmod.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/slab.h>
@@ -496,25 +497,19 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
case CTRLCHAR_SYSRQ:
break;
case CTRLCHAR_CTRL:
- sclp_tty->flip.count++;
- *sclp_tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *sclp_tty->flip.char_buf_ptr++ = cchar;
+ tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
tty_flip_buffer_push(sclp_tty);
break;
case CTRLCHAR_NONE:
/* send (normal) input to line discipline */
- memcpy(sclp_tty->flip.char_buf_ptr, buf, count);
if (count < 2 ||
- (strncmp ((const char *) buf + count - 2, "^n", 2) &&
- strncmp ((const char *) buf + count - 2, "\0252n", 2))) {
- sclp_tty->flip.char_buf_ptr[count] = '\n';
- count++;
+ (strncmp((const char *) buf + count - 2, "^n", 2) &&
+ strncmp((const char *) buf + count - 2, "\252n", 2))) {
+ /* add the auto \n */
+ tty_insert_flip_string(sclp_tty, buf, count);
+ tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
} else
- count -= 2;
- memset(sclp_tty->flip.flag_buf_ptr, TTY_NORMAL, count);
- sclp_tty->flip.char_buf_ptr += count;
- sclp_tty->flip.flag_buf_ptr += count;
- sclp_tty->flip.count += count;
+ tty_insert_flip_string(sclp_tty, buf, count - 2);
tty_flip_buffer_push(sclp_tty);
break;
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 06bd85824d7b..9e02625c82cf 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/mm.h>
@@ -482,16 +483,7 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
/* Send input to line discipline */
buffer++;
count--;
- /* Prevent buffer overrun by discarding input. Note that
- * because buffer_push works asynchronously, we cannot wait
- * for the buffer to be emptied. */
- if (count + sclp_vt220_tty->flip.count > TTY_FLIPBUF_SIZE)
- count = TTY_FLIPBUF_SIZE - sclp_vt220_tty->flip.count;
- memcpy(sclp_vt220_tty->flip.char_buf_ptr, buffer, count);
- memset(sclp_vt220_tty->flip.flag_buf_ptr, TTY_NORMAL, count);
- sclp_vt220_tty->flip.char_buf_ptr += count;
- sclp_vt220_tty->flip.flag_buf_ptr += count;
- sclp_vt220_tty->flip.count += count;
+ tty_insert_flip_string(sclp_vt220_tty, buffer, count);
tty_flip_buffer_push(sclp_vt220_tty);
break;
}
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 86262a13f7c6..5ce7ca38ace0 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -37,6 +37,8 @@ static int tapechar_open(struct inode *,struct file *);
static int tapechar_release(struct inode *,struct file *);
static int tapechar_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
+static long tapechar_compat_ioctl(struct file *, unsigned int,
+ unsigned long);
static struct file_operations tape_fops =
{
@@ -44,6 +46,7 @@ static struct file_operations tape_fops =
.read = tapechar_read,
.write = tapechar_write,
.ioctl = tapechar_ioctl,
+ .compat_ioctl = tapechar_compat_ioctl,
.open = tapechar_open,
.release = tapechar_release,
};
@@ -463,6 +466,23 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
return device->discipline->ioctl_fn(device, no, data);
}
+static long
+tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+ struct tape_device *device = filp->private_data;
+ int rval = -ENOIOCTLCMD;
+
+ if (device->discipline->ioctl_fn) {
+ lock_kernel();
+ rval = device->discipline->ioctl_fn(device, no, data);
+ unlock_kernel();
+ if (rval == -EINVAL)
+ rval = -ENOIOCTLCMD;
+ }
+
+ return rval;
+}
+
/*
* Initialize character device frontend.
*/
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 83e6a060668e..cd2cc28e16a7 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -2,12 +2,12 @@
* drivers/s390/cio/airq.c
* S/390 common I/O routines -- support for adapter interruptions
*
- * $Revision: 1.12 $
+ * $Revision: 1.15 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
*/
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index daf21e03b21d..72f27c151c09 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.39 $
+ * $Revision: 1.42 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
*/
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e849289d4f3c..6c077ad71edc 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
- * $Revision: 1.33 $
+ * $Revision: 1.35 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/module.h>
#include <linux/errno.h>
@@ -52,11 +52,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
return 0;
}
-static struct bus_type ccwgroup_bus_type = {
- .name = "ccwgroup",
- .match = ccwgroup_bus_match,
- .uevent = ccwgroup_uevent,
-};
+static struct bus_type ccwgroup_bus_type;
static inline void
__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
@@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev)
return 0;
}
+static struct bus_type ccwgroup_bus_type = {
+ .name = "ccwgroup",
+ .match = ccwgroup_bus_match,
+ .uevent = ccwgroup_uevent,
+ .probe = ccwgroup_probe,
+ .remove = ccwgroup_remove,
+};
+
int
ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
{
@@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
cdriver->driver = (struct device_driver) {
.bus = &ccwgroup_bus_type,
.name = cdriver->name,
- .probe = ccwgroup_probe,
- .remove = ccwgroup_remove,
};
return driver_register(&cdriver->driver);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 7270808c02d1..2cbb724791a8 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.126 $
+ * $Revision: 1.128 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
*/
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 7376bc87206d..6223b06d27d5 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.138 $
+ * $Revision: 1.140 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index e565193650c7..516108779f60 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
- * $Revision: 1.93 $
+ * $Revision: 1.96 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struct device_driver *drv)
return 0;
}
+static int
+css_probe (struct device *dev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ sch->driver = container_of (dev->driver, struct css_driver, drv);
+ return (sch->driver->probe ? sch->driver->probe(sch) : 0);
+}
+
+static int
+css_remove (struct device *dev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ return (sch->driver->remove ? sch->driver->remove(sch) : 0);
+}
+
+static void
+css_shutdown (struct device *dev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ if (sch->driver->shutdown)
+ sch->driver->shutdown(sch);
+}
+
struct bus_type css_bus_type = {
- .name = "css",
- .match = &css_bus_match,
+ .name = "css",
+ .match = css_bus_match,
+ .probe = css_probe,
+ .remove = css_remove,
+ .shutdown = css_shutdown,
};
subsys_initcall(init_channel_subsystem);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 251ebd7a7d3a..b6375861cb37 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -115,6 +115,7 @@ struct ccw_device_private {
* Currently, we only care about I/O subchannels (type 0), these
* have a ccw_device connected to them.
*/
+struct subchannel;
struct css_driver {
unsigned int subchannel_type;
struct device_driver drv;
@@ -122,6 +123,9 @@ struct css_driver {
int (*notify)(struct device *, int);
void (*verify)(struct device *);
void (*termination)(struct device *);
+ int (*probe)(struct subchannel *);
+ int (*remove)(struct subchannel *);
+ void (*shutdown)(struct subchannel *);
};
/*
@@ -143,7 +147,7 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
struct channel_subsystem {
u8 cssid;
int valid;
- struct channel_path *chps[__MAX_CHPID];
+ struct channel_path *chps[__MAX_CHPID + 1];
struct device device;
struct pgid global_pgid;
};
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index fa3e4c0a2536..a67e7e60e330 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
- * $Revision: 1.137 $
+ * $Revision: 1.140 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
#include <linux/config.h>
@@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **envp, int num_envp,
return 0;
}
-struct bus_type ccw_bus_type = {
- .name = "ccw",
- .match = &ccw_bus_match,
- .uevent = &ccw_uevent,
-};
+struct bus_type ccw_bus_type;
-static int io_subchannel_probe (struct device *);
-static int io_subchannel_remove (struct device *);
+static int io_subchannel_probe (struct subchannel *);
+static int io_subchannel_remove (struct subchannel *);
void io_subchannel_irq (struct device *);
static int io_subchannel_notify(struct device *, int);
static void io_subchannel_verify(struct device *);
static void io_subchannel_ioterm(struct device *);
-static void io_subchannel_shutdown(struct device *);
+static void io_subchannel_shutdown(struct subchannel *);
struct css_driver io_subchannel_driver = {
.subchannel_type = SUBCHANNEL_TYPE_IO,
.drv = {
.name = "io_subchannel",
.bus = &css_bus_type,
- .probe = &io_subchannel_probe,
- .remove = &io_subchannel_remove,
- .shutdown = &io_subchannel_shutdown,
},
.irq = io_subchannel_irq,
.notify = io_subchannel_notify,
.verify = io_subchannel_verify,
.termination = io_subchannel_ioterm,
+ .probe = io_subchannel_probe,
+ .remove = io_subchannel_remove,
+ .shutdown = io_subchannel_shutdown,
};
struct workqueue_struct *ccw_device_work;
@@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
}
static int
-io_subchannel_probe (struct device *pdev)
+io_subchannel_probe (struct subchannel *sch)
{
- struct subchannel *sch;
struct ccw_device *cdev;
int rc;
unsigned long flags;
- sch = to_subchannel(pdev);
if (sch->dev.driver_data) {
/*
* This subchannel already has an associated ccw_device.
@@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev)
memset(cdev->private, 0, sizeof(struct ccw_device_private));
atomic_set(&cdev->private->onoff, 0);
cdev->dev = (struct device) {
- .parent = pdev,
+ .parent = &sch->dev,
.release = ccw_device_release,
};
INIT_LIST_HEAD(&cdev->private->kick_work.entry);
@@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev)
return -ENODEV;
}
- rc = io_subchannel_recog(cdev, to_subchannel(pdev));
+ rc = io_subchannel_recog(cdev, sch);
if (rc) {
spin_lock_irqsave(&sch->lock, flags);
sch->dev.driver_data = NULL;
@@ -883,17 +877,17 @@ ccw_device_unregister(void *data)
}
static int
-io_subchannel_remove (struct device *dev)
+io_subchannel_remove (struct subchannel *sch)
{
struct ccw_device *cdev;
unsigned long flags;
- if (!dev->driver_data)
+ if (!sch->dev.driver_data)
return 0;
- cdev = dev->driver_data;
+ cdev = sch->dev.driver_data;
/* Set ccw device to not operational and drop reference. */
spin_lock_irqsave(cdev->ccwlock, flags);
- dev->driver_data = NULL;
+ sch->dev.driver_data = NULL;
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
/*
@@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev)
}
static void
-io_subchannel_shutdown(struct device *dev)
+io_subchannel_shutdown(struct subchannel *sch)
{
- struct subchannel *sch;
struct ccw_device *cdev;
int ret;
- sch = to_subchannel(dev);
- cdev = dev->driver_data;
+ cdev = sch->dev.driver_data;
if (cio_is_console(sch->schid))
return;
@@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev)
return 0;
}
+struct bus_type ccw_bus_type = {
+ .name = "ccw",
+ .match = ccw_bus_match,
+ .uevent = ccw_uevent,
+ .probe = ccw_device_probe,
+ .remove = ccw_device_remove,
+};
+
int
ccw_driver_register (struct ccw_driver *cdriver)
{
@@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver)
drv->bus = &ccw_bus_type;
drv->name = cdriver->name;
- drv->probe = ccw_device_probe;
- drv->remove = ccw_device_remove;
return driver_register(drv);
}
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 23d12b65e5fa..b302779e7cff 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 04ceba343db8..e60b2d8103b8 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Sense ID functions.
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 143b6c25a4e6..8b0218949b62 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.58 $
+ * $Revision: 1.61 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/config.h>
#include <linux/module.h>
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 052832d03d38..d2a5b04d7cba 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Path Group ID functions.
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index db09c209098b..dad4dd9887c9 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Status accumulation and basic sense functions.
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 30a836ffc31f..77be2c39bfe4 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -7,7 +7,7 @@
*
* Copyright 2000,2002 IBM Corporation
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>
- * 2.6 cio integration by Cornelia Huck <cohuck@de.ibm.com>
+ * 2.6 cio integration by Cornelia Huck <cornelia.huck@de.ibm.com>
*
* Restriction: only 63 iqdio subchannels would have its own indicator,
* after that, subsequent subchannels share one indicator
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.114 $"
+#define VERSION_QDIO_C "$Revision: 1.117 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 135ae04e6e75..2f54d033d7cf 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -30,7 +30,6 @@
#include <linux/delay.h> // mdelay
#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>
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 0db4f57a6a95..1901feef07d9 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
+ * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $
*
* CTC / ESCON network driver
*
@@ -8,7 +8,7 @@
* Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <cohuck@de.ibm.com>
+ * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
*
* Documentation used:
* - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -37,7 +37,7 @@
* 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.78 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $
*
*/
#undef DEBUG
@@ -248,7 +248,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.78 $";
+ char vbuf[] = "$Revision: 1.79 $";
char *version = vbuf;
if (printed)
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 968f2c113efe..93d1725eb79b 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -101,25 +102,17 @@ static spinlock_t ctc_tty_lock;
static int
ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
{
- int c;
int len;
struct tty_struct *tty;
DBF_TEXT(trace, 5, __FUNCTION__);
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
len = skb->len;
- if (c >= len) {
- memcpy(tty->flip.char_buf_ptr, skb->data, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
- tty_flip_buffer_push(tty);
- kfree_skb(skb);
- return 1;
- }
+ tty_insert_flip_string(tty, skb->data, len);
+ tty_flip_buffer_push(tty);
+ kfree_skb(skb);
+ return 1;
}
}
return 0;
@@ -138,19 +131,12 @@ ctc_tty_readmodem(ctc_tty_info *info)
DBF_TEXT(trace, 5, __FUNCTION__);
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- int c = TTY_FLIPBUF_SIZE - tty->flip.count;
struct sk_buff *skb;
- if ((c > 0) && (skb = skb_dequeue(&info->rx_queue))) {
+ if ((skb = skb_dequeue(&info->rx_queue))) {
int len = skb->len;
- if (len > c)
- len = c;
- memcpy(tty->flip.char_buf_ptr, skb->data, len);
+ tty_insert_flip_string(tty, skb->data, len);
skb_pull(skb, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
tty_flip_buffer_push(tty);
if (skb->len > 0)
skb_queue_head(&info->rx_queue, skb);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 77dacb465732..2014fb7a4881 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,11 +1,11 @@
/*
- * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $
+ * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $
*
* CTC / LCS ccw_device driver
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Arnd Bergmann <arndb@de.ibm.com>
- * Cornelia Huck <cohuck@de.ibm.com>
+ * Cornelia Huck <cornelia.huck@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
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 69425a7a6e98..ac4c4b83fe17 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,12 +1,13 @@
/*
- * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $
+ * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $
*
* IUCV network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
*
- * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com)
+ * Sysfs integration and all bugs therein by Cornelia Huck
+ * (cornelia.huck@de.ibm.com)
*
* Documentation used:
* the source of the original IUCV driver by:
@@ -30,7 +31,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.66 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.69 $
*
*/
@@ -2076,7 +2077,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write);
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.66 $";
+ char vbuf[] = "$Revision: 1.69 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
index 566cc3d185b6..206518c7d332 100644
--- a/drivers/s390/s390_rdev.c
+++ b/drivers/s390/s390_rdev.c
@@ -1,11 +1,11 @@
/*
* drivers/s390/s390_rdev.c
* s390 root device
- * $Revision: 1.2 $
+ * $Revision: 1.4 $
*
* Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck (cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Carsten Otte (cotte@de.ibm.com)
*/
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 5e84c5aa7779..167fef39d8a7 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1125,6 +1125,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_free_low_mem_buffers(adapter);
/* free memory of adapter data structure and queues */
zfcp_qdio_free_queues(adapter);
+ kfree(adapter->fc_stats);
+ kfree(adapter->stats_reset_data);
ZFCP_LOG_TRACE("freeing adapter structure\n");
kfree(adapter);
out:
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d81b737d68cc..9bb511083a26 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -921,7 +921,6 @@ struct zfcp_adapter {
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 hydra_version; /* Hydra version */
u32 fsf_lic_version;
u32 adapter_features; /* FCP channel features */
@@ -978,6 +977,9 @@ struct zfcp_adapter {
struct zfcp_adapter_mempool pool; /* Adapter memory pools */
struct qdio_initialize qdio_init_data; /* for qdio_establish */
struct device generic_services; /* directory for WKA ports */
+ struct fc_host_statistics *fc_stats;
+ struct fsf_qtcb_bottom_port *stats_reset_data;
+ unsigned long stats_reset;
};
/*
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index ee7314d8c2da..c065cb836c97 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -2613,7 +2613,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
case ZFCP_ERP_STEP_UNINITIALIZED:
case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
case ZFCP_ERP_STEP_PORT_CLOSING:
- if (adapter->fc_topology == FSF_TOPO_P2P) {
+ if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
if (port->wwpn != adapter->peer_wwpn) {
ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
"on adapter %s.\nPeer WWPN "
@@ -3403,7 +3403,7 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
/**
* zfcp_erp_action_cleanup
*
- * Register unit with scsi stack if appropiate and fix reference counts.
+ * Register unit with scsi stack if appropriate and fix reference counts.
* Note: Temporary units are not registered with scsi stack.
*/
static void
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 59587951c847..cbfab09899c8 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -964,6 +964,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
| ZFCP_STATUS_COMMON_ERP_FAILED);
break;
+ case FSF_STATUS_READ_NOTIFICATION_LOST:
+ ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "
+ "adapter %s%s%s%s%s%s%s%s%s\n",
+ zfcp_get_busid_by_adapter(adapter),
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_INCOMING_ELS) ?
+ ", incoming ELS" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_SENSE_DATA) ?
+ ", sense data" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_LINK_STATUS) ?
+ ", link status change" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_PORT_CLOSED) ?
+ ", port close" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?
+ ", bit error exception" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED) ?
+ ", ACT update" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_HARDENED) ?
+ ", ACT hardening" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?
+ ", adapter feature change" : "");
+
+ if (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED)
+ zfcp_erp_adapter_access_changed(adapter);
+ break;
+
case FSF_STATUS_READ_CFDC_UPDATED:
ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
@@ -1954,6 +1988,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_CFDC |
FSF_FEATURE_LUN_SHARING |
+ FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
/* start QDIO request for this FSF request */
@@ -2008,27 +2043,30 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
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->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);
+ if (fc_host_permanent_port_name(shost) == -1)
+ fc_host_permanent_port_name(shost) =
+ fc_host_port_name(shost);
+ if (bottom->fc_topology == FSF_TOPO_P2P) {
+ adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
+ adapter->peer_wwpn = bottom->plogi_payload.wwpn;
+ adapter->peer_wwnn = bottom->plogi_payload.wwnn;
+ fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+ } else if (bottom->fc_topology == FSF_TOPO_FABRIC)
+ fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+ else if (bottom->fc_topology == FSF_TOPO_AL)
+ fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+ else
+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
} else {
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;
+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
adapter->hydra_version = 0;
}
- if (adapter->fc_topology == FSF_TOPO_P2P) {
- adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
- adapter->peer_wwpn = bottom->plogi_payload.wwpn;
- adapter->peer_wwnn = bottom->plogi_payload.wwnn;
- }
-
if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
adapter->hardware_version = bottom->hardware_version;
memcpy(fc_host_serial_number(shost), bottom->serial_number,
@@ -2097,8 +2135,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
return -EIO;
- switch (adapter->fc_topology) {
- case FSF_TOPO_P2P:
+ switch (fc_host_port_type(adapter->scsi_host)) {
+ case FC_PORTTYPE_PTP:
ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
"configuration detected at adapter %s\n"
"Peer WWNN 0x%016llx, "
@@ -2111,7 +2149,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 0,
"top-p-to-p");
break;
- case FSF_TOPO_AL:
+ case FC_PORTTYPE_NLPORT:
ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
"topology detected at adapter %s "
"unsupported, shutting down adapter\n",
@@ -2120,7 +2158,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"top-al");
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
- case FSF_TOPO_FABRIC:
+ case FC_PORTTYPE_NPORT:
ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
"network detected at adapter %s.\n",
zfcp_get_busid_by_adapter(adapter));
@@ -2133,7 +2171,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"of a type known to the zfcp "
"driver, shutting down adapter\n",
zfcp_get_busid_by_adapter(adapter));
- adapter->fc_topology = FSF_TOPO_ERROR;
debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"unknown-topo");
zfcp_erp_adapter_shutdown(adapter, 0);
@@ -2293,14 +2330,13 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
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);
- }
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ fc_host_permanent_port_name(shost) = bottom->wwpn;
+ else
+ fc_host_permanent_port_name(shost) =
+ fc_host_port_name(shost);
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ fc_host_supported_speeds(shost) = bottom->supported_speed;
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 48719f055952..e734415cae6d 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -166,6 +166,7 @@
#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004
#define FSF_STATUS_READ_LINK_DOWN 0x00000005
#define FSF_STATUS_READ_LINK_UP 0x00000006
+#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009
#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C
@@ -179,6 +180,16 @@
#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001
#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002
+/* status subtypes for unsolicited status notification lost */
+#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001
+#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002
+#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004
+#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008
+#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010
+#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020
+#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040
+#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
+
/* status subtypes for CFDC */
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
@@ -188,7 +199,6 @@
#define FSF_TOPO_P2P 0x00000001
#define FSF_TOPO_FABRIC 0x00000002
#define FSF_TOPO_AL 0x00000003
-#define FSF_TOPO_FABRIC_VIRT 0x00000004
/* data direction for FCP commands */
#define FSF_DATADIR_WRITE 0x00000001
@@ -211,6 +221,7 @@
/* channel features */
#define FSF_FEATURE_CFDC 0x00000002
#define FSF_FEATURE_LUN_SHARING 0x00000004
+#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 66608d13a634..3c2cbcccbf54 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8,
static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
scsi_lun_t);
-static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int,
- scsi_id_t);
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
@@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
return retval;
}
-static struct zfcp_port *
-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 (port->rport && (id == port->rport->scsi_target_id))
- return port;
- }
- return (struct zfcp_port *) NULL;
-}
-
/**
* zfcp_scsi_eh_abort_handler - abort the specified SCSI command
* @scpnt: pointer to scsi_cmnd to be aborted
@@ -731,70 +717,164 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
/*
* Support functions for FC transport class
*/
-static void
-zfcp_get_port_id(struct scsi_target *starget)
+static struct fc_host_statistics*
+zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
- struct zfcp_port *port;
- unsigned long flags;
+ struct fc_host_statistics *fc_stats;
- read_lock_irqsave(&zfcp_data.config_lock, flags);
- port = zfcp_port_lookup(adapter, starget->channel, starget->id);
- if (port)
- fc_starget_port_id(starget) = port->d_id;
- else
- fc_starget_port_id(starget) = -1;
- read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ if (!adapter->fc_stats) {
+ fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
+ if (!fc_stats)
+ return NULL;
+ adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
+ }
+ memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
+ return adapter->fc_stats;
}
static void
-zfcp_get_port_name(struct scsi_target *starget)
+zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
+ struct fsf_qtcb_bottom_port *data,
+ struct fsf_qtcb_bottom_port *old)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
- struct zfcp_port *port;
- unsigned long flags;
+ fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -
+ old->seconds_since_last_reset;
+ fc_stats->tx_frames = data->tx_frames - old->tx_frames;
+ fc_stats->tx_words = data->tx_words - old->tx_words;
+ fc_stats->rx_frames = data->rx_frames - old->rx_frames;
+ fc_stats->rx_words = data->rx_words - old->rx_words;
+ fc_stats->lip_count = data->lip - old->lip;
+ fc_stats->nos_count = data->nos - old->nos;
+ fc_stats->error_frames = data->error_frames - old->error_frames;
+ fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
+ fc_stats->link_failure_count = data->link_failure - old->link_failure;
+ fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
+ fc_stats->loss_of_signal_count = data->loss_of_signal -
+ old->loss_of_signal;
+ fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -
+ old->psp_error_counts;
+ fc_stats->invalid_tx_word_count = data->invalid_tx_words -
+ old->invalid_tx_words;
+ fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
+ fc_stats->fcp_input_requests = data->input_requests -
+ old->input_requests;
+ fc_stats->fcp_output_requests = data->output_requests -
+ old->output_requests;
+ fc_stats->fcp_control_requests = data->control_requests -
+ old->control_requests;
+ fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
+ fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
+}
- read_lock_irqsave(&zfcp_data.config_lock, flags);
- port = zfcp_port_lookup(adapter, starget->channel, starget->id);
- if (port)
- fc_starget_port_name(starget) = port->wwpn;
- else
- fc_starget_port_name(starget) = -1;
- read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+static void
+zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
+ struct fsf_qtcb_bottom_port *data)
+{
+ fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
+ fc_stats->tx_frames = data->tx_frames;
+ fc_stats->tx_words = data->tx_words;
+ fc_stats->rx_frames = data->rx_frames;
+ fc_stats->rx_words = data->rx_words;
+ fc_stats->lip_count = data->lip;
+ fc_stats->nos_count = data->nos;
+ fc_stats->error_frames = data->error_frames;
+ fc_stats->dumped_frames = data->dumped_frames;
+ fc_stats->link_failure_count = data->link_failure;
+ fc_stats->loss_of_sync_count = data->loss_of_sync;
+ fc_stats->loss_of_signal_count = data->loss_of_signal;
+ fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
+ fc_stats->invalid_tx_word_count = data->invalid_tx_words;
+ fc_stats->invalid_crc_count = data->invalid_crcs;
+ fc_stats->fcp_input_requests = data->input_requests;
+ fc_stats->fcp_output_requests = data->output_requests;
+ fc_stats->fcp_control_requests = data->control_requests;
+ fc_stats->fcp_input_megabytes = data->input_mb;
+ fc_stats->fcp_output_megabytes = data->output_mb;
+}
+
+/**
+ * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
+ *
+ * assumption: scsi_transport_fc synchronizes calls of
+ * get_fc_host_stats and reset_fc_host_stats
+ * (XXX to be checked otherwise introduce locking)
+ */
+static struct fc_host_statistics *
+zfcp_get_fc_host_stats(struct Scsi_Host *shost)
+{
+ struct zfcp_adapter *adapter;
+ struct fc_host_statistics *fc_stats;
+ struct fsf_qtcb_bottom_port *data;
+ int ret;
+
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ fc_stats = zfcp_init_fc_host_stats(adapter);
+ if (!fc_stats)
+ return NULL;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+ memset(data, 0, sizeof(*data));
+
+ ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+ if (ret) {
+ kfree(data);
+ return NULL; /* XXX return zeroed fc_stats? */
+ }
+
+ if (adapter->stats_reset &&
+ ((jiffies/HZ - adapter->stats_reset) <
+ data->seconds_since_last_reset)) {
+ zfcp_adjust_fc_host_stats(fc_stats, data,
+ adapter->stats_reset_data);
+ } else
+ zfcp_set_fc_host_stats(fc_stats, data);
+
+ kfree(data);
+ return fc_stats;
}
static void
-zfcp_get_node_name(struct scsi_target *starget)
+zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
- struct zfcp_port *port;
- unsigned long flags;
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_port *data, *old_data;
+ int ret;
- read_lock_irqsave(&zfcp_data.config_lock, flags);
- port = zfcp_port_lookup(adapter, starget->channel, starget->id);
- if (port)
- fc_starget_node_name(starget) = port->wwnn;
- else
- fc_starget_node_name(starget) = -1;
- read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return;
+ memset(data, 0, sizeof(*data));
+
+ ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+ if (ret == 0) {
+ adapter->stats_reset = jiffies/HZ;
+ old_data = adapter->stats_reset_data;
+ adapter->stats_reset_data = data; /* finally freed in
+ adater_dequeue */
+ kfree(old_data);
+ }
}
struct fc_function_template zfcp_transport_functions = {
- .get_starget_port_id = zfcp_get_port_id,
- .get_starget_port_name = zfcp_get_port_name,
- .get_starget_node_name = zfcp_get_node_name,
.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_permanent_port_name = 1,
.show_host_supported_classes = 1,
+ .show_host_supported_speeds = 1,
.show_host_maxframe_size = 1,
.show_host_serial_number = 1,
+ .get_fc_host_stats = zfcp_get_fc_host_stats,
+ .reset_fc_host_stats = zfcp_reset_fc_host_stats,
+ /* no functions registered for following dynamic attributes but
+ directly set by LLDD */
+ .show_host_port_type = 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 0cd435280e7d..9f262250043a 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -33,14 +33,6 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
-static const char fc_topologies[5][25] = {
- "<error>",
- "point-to-point",
- "fabric",
- "arbitrated loop",
- "fabric (virt. adapter)"
-};
-
/**
* ZFCP_DEFINE_ADAPTER_ATTR
* @_name: name of show attribute
@@ -69,12 +61,8 @@ 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_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(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));
@@ -259,9 +247,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.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,
NULL
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index c55e82d91deb..3924eb38805c 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -65,8 +65,6 @@ static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_
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(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
@@ -245,8 +243,6 @@ static struct attribute *zfcp_port_common_attrs[] = {
&dev_attr_failed.attr,
&dev_attr_in_recovery.attr,
&dev_attr_status.attr,
- &dev_attr_wwnn.attr,
- &dev_attr_d_id.attr,
&dev_attr_access_denied.attr,
NULL
};
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 0556642c9e1d..2f50815f65c7 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -65,7 +65,6 @@ static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
-ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -138,7 +137,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
zfcp_sysfs_unit_failed_store);
static struct attribute *zfcp_unit_attrs[] = {
- &dev_attr_scsi_lun.attr,
&dev_attr_failed.attr,
&dev_attr_in_recovery.attr,
&dev_attr_status.attr,
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index 92e6c5639dd3..015db40ad8a4 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = {
/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/
static unsigned char * tmp_buf = NULL;
-static DECLARE_MUTEX(tmp_buf_sem);
DECLARE_TASK_QUEUE(tq_aurora);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3ff74f472249..31c497542272 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -73,6 +73,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -615,7 +616,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
void __user *argp = (void __user *)arg;
/* Only let one of these through at a time */
- if (down_interruptible(&tw_dev->ioctl_sem)) {
+ if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
retval = TW_IOCTL_ERROR_OS_EINTR;
goto out;
}
@@ -852,7 +853,7 @@ out3:
/* Now free ioctl buf memory */
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
out2:
- up(&tw_dev->ioctl_sem);
+ mutex_unlock(&tw_dev->ioctl_lock);
out:
return retval;
} /* End twa_chrdev_ioctl() */
@@ -1182,7 +1183,7 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev)
tw_dev->error_sequence_id = 1;
tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- init_MUTEX(&tw_dev->ioctl_sem);
+ mutex_init(&tw_dev->ioctl_lock);
init_waitqueue_head(&tw_dev->ioctl_wqueue);
retval = 0;
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 46f22cdc8298..1b16d57f0314 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -672,7 +672,7 @@ typedef struct TAG_TW_Device_Extension {
u32 ioctl_msec;
int chrdev_request_id;
wait_queue_head_t ioctl_wqueue;
- struct semaphore ioctl_sem;
+ struct mutex ioctl_lock;
char aen_clobber;
unsigned short working_srl;
unsigned short working_branch;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 283f6d25892b..25f678d0780b 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -203,6 +203,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -888,7 +889,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
/* Only let one of these through at a time */
- if (down_interruptible(&tw_dev->ioctl_sem))
+ if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
return -EINTR;
/* First copy down the buffer length */
@@ -1029,7 +1030,7 @@ out2:
/* Now free ioctl buf memory */
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
out:
- up(&tw_dev->ioctl_sem);
+ mutex_unlock(&tw_dev->ioctl_lock);
return retval;
} /* End tw_chrdev_ioctl() */
@@ -1270,7 +1271,7 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
tw_dev->pending_tail = TW_Q_START;
tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- init_MUTEX(&tw_dev->ioctl_sem);
+ mutex_init(&tw_dev->ioctl_lock);
init_waitqueue_head(&tw_dev->ioctl_wqueue);
return 0;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 4f81fc39ec57..31fe5ea15920 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -420,7 +420,7 @@ typedef struct TAG_TW_Device_Extension {
u32 max_sector_count;
u32 aen_count;
struct Scsi_Host *host;
- struct semaphore ioctl_sem;
+ struct mutex ioctl_lock;
unsigned short aen_queue[TW_Q_LENGTH];
unsigned char aen_head;
unsigned char aen_tail;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 9d6040bfa064..1c459343292b 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2216,6 +2216,7 @@ static int __init BusLogic_init(void)
HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
HostAdapter->Bus = ProbeInfo->Bus;
HostAdapter->Device = ProbeInfo->Device;
+ HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
/*
@@ -2296,7 +2297,7 @@ static int __init BusLogic_init(void)
scsi_host_put(Host);
} else {
BusLogic_InitializeHostStructure(HostAdapter, Host);
- scsi_add_host(Host, NULL);
+ scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
scsi_scan_host(Host);
BusLogicHostAdapterCount++;
}
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 5beed4f6d985..8d64f0bed628 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -149,7 +149,7 @@ typedef SCCBMGR_INFO * PSCCBMGR_INFO;
#define PCI_BUS_CARD 0x03
#define VESA_BUS_CARD 0x04
-/* SCCB struc used for both SCCB and UCB manager compiles!
+/* SCCB struct used for both SCCB and UCB manager compiles!
* The UCB Manager treats the SCCB as it's 'native hardware structure'
*/
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index f062ea0f813a..320e765fa0cd 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o
obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o
obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o
obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o
-obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp.o oktagon_io.o
+obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp_mod.o
obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o
obj-$(CONFIG_MAC_SCSI) += mac_scsi.o
obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o
@@ -80,7 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
-obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx/
+obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
obj-$(CONFIG_SCSI_LPFC) += lpfc/
obj-$(CONFIG_SCSI_PAS16) += pas16.o
obj-$(CONFIG_SCSI_SEAGATE) += seagate.o
@@ -164,6 +164,7 @@ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
libata-objs := libata-core.o libata-scsi.o
+oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o
# Files generated that shall be removed upon make clean
clean-files := 53c7xx_d.h 53c700_d.h \
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 640590bd014a..c7dd0154d012 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -1799,6 +1799,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
*/
int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */
int fifocnt = 0;
+ unsigned char *p = phys_to_virt((unsigned long)SCptr->SCp.ptr);
oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK;
@@ -1860,7 +1861,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
/* read fifo */
for(j=0;j<fifocnt;j++)
- SCptr->SCp.ptr[i++] = esp_read(eregs->esp_fdata);
+ p[i++] = esp_read(eregs->esp_fdata);
ESPDATA(("(%d) ", i));
@@ -1882,7 +1883,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
/* fill fifo */
for(j=0;j<this_count;j++)
- esp_write(eregs->esp_fdata, SCptr->SCp.ptr[i++]);
+ esp_write(eregs->esp_fdata, p[i++]);
/* how many left if this goes out ?? */
hmuch -= this_count;
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
deleted file mode 100644
index 4193865d419c..000000000000
--- a/drivers/scsi/aacraid/README
+++ /dev/null
@@ -1,74 +0,0 @@
-AACRAID Driver for Linux (take two)
-
-Introduction
--------------------------
-The aacraid driver adds support for Adaptec (http://www.adaptec.com)
-RAID controllers. This is a major rewrite from the original
-Adaptec supplied driver. It has signficantly cleaned up both the code
-and the running binary size (the module is less than half the size of
-the original).
-
-Supported Cards/Chipsets
--------------------------
- Adaptec 2020S
- Adaptec 2025S
- Adaptec 2120S
- Adaptec 2130S
- Adaptec 2200S
- Adaptec 2230S
- Adaptec 2240S
- Adaptec 2410SA
- Adaptec 2610SA
- Adaptec 2810SA
- Adaptec 21610SA
- Adaptec 3230S
- Adaptec 3240S
- Adaptec 4000SAS
- Adaptec 4005SAS
- Adaptec 4800SAS
- Adaptec 4805SAS
- Adaptec 5400S
- Dell PERC 2 Quad Channel
- Dell PERC 2/Si
- Dell PERC 3/Si
- Dell PERC 3/Di
- Dell CERC 2
- HP NetRAID-4M
- Legend S220
- Legend S230
- IBM ServeRAID 8i
- ICP 9014R0
- ICP 9024R0
- ICP 9047MA
- ICP 9087MA
- ICP 9085LI
- ICP 5085AU
-
-People
--------------------------
-Alan Cox <alan@redhat.com>
-Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,
- small cleanups/fixes)
-Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)
-Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
- added new ioctls, changed scsi interface to use new error handler,
- increased the number of fibs and outstanding commands to a container)
-
- (fixed 64bit and 64G memory model, changed confusing naming convention
- where fibs that go to the hardware are consistently called hw_fibs and
- not just fibs like the name of the driver tracking structure)
-Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
-
-Original Driver
--------------------------
-Adaptec Unix OEM Product Group
-
-Mailing List
--------------------------
-linux-scsi@vger.kernel.org (Interested parties troll here)
-Also note this is very different to Brian's original driver
-so don't expect him to support it.
-Adaptec does support this driver. Contact either tech support or Mark Salyzyn.
-
-Original by Brian Boerner February 2001
-Rewritten by Alan Cox, November 2001
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 30fd8d6e3f31..66dbb6d2c506 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -532,6 +532,13 @@ struct aac_driver_ident
#define AAC_QUIRK_MASTER 0x0008
/*
+ * Some adapter firmware perform poorly when it must split up scatter gathers
+ * in order to deal with the limits of the underlying CHIM. This limit in this
+ * class of adapters is 17 scatter gather elements.
+ */
+#define AAC_QUIRK_17SG 0x0010
+
+/*
* The adapter interface specs all queues to be located in the same
* physically contigous block. The host structure that defines the
* commuication queues will assume they are each a separate physically
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index ef623bd965f5..4fe79cd7c957 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -85,6 +85,10 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
if (size < le16_to_cpu(kfib->header.SenderSize))
size = le16_to_cpu(kfib->header.SenderSize);
if (size > dev->max_fib_size) {
+ if (size > 2048) {
+ retval = -EINVAL;
+ goto cleanup;
+ }
/* Highjack the hw_fib */
hw_fib = fibptr->hw_fib;
hw_fib_pa = fibptr->hw_fib_pa;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 3cb68af90456..0bf5f9a943e8 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
-#include <linux/ioctl32.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
#include <asm/semaphore.h>
@@ -201,10 +200,10 @@ static struct aac_driver_ident aac_drivers[] = {
{ 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) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
- { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+ { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
@@ -575,7 +574,15 @@ static ssize_t aac_show_model(struct class_device *class_dev,
struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
int len;
- len = snprintf(buf, PAGE_SIZE, "%s\n",
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+ char * cp = dev->supplement_adapter_info.AdapterTypeText;
+ while (*cp && *cp != ' ')
+ ++cp;
+ while (*cp == ' ')
+ ++cp;
+ len = snprintf(buf, PAGE_SIZE, "%s\n", cp);
+ } else
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
aac_drivers[dev->cardtype].model);
return len;
}
@@ -586,7 +593,15 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
int len;
- len = snprintf(buf, PAGE_SIZE, "%s\n",
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+ char * cp = dev->supplement_adapter_info.AdapterTypeText;
+ while (*cp && *cp != ' ')
+ ++cp;
+ len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+ (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText),
+ dev->supplement_adapter_info.AdapterTypeText);
+ } else
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
aac_drivers[dev->cardtype].vname);
return len;
}
@@ -838,6 +853,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
= (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
}
+ if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
+ (aac->scsi_host_ptr->sg_tablesize > 17)) {
+ aac->scsi_host_ptr->sg_tablesize = 17;
+ aac->scsi_host_ptr->max_sectors
+ = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
+
/*
* Firware printf works only with older firmware.
*/
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index d113290b5fc0..19bd346951dd 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -276,6 +276,16 @@ static const struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ESB2 */
{ PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH7-M DH */
+ { PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8M */
+ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8M */
{ } /* terminate list */
};
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index ac8de03c9fa2..6c2c395554ff 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -42,13 +42,13 @@ config AIC7XXX_CMDS_PER_DEVICE
config AIC7XXX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
depends on SCSI_AIC7XXX
- default "15000"
+ default "5000"
---help---
The number of milliseconds to delay after an initial bus reset.
The bus settle delay following all error recovery actions is
dictated by the SCSI layer and is not affected by this value.
- Default: 15000 (15 seconds)
+ Default: 5000 (5 seconds)
config AIC7XXX_PROBE_EISA_VL
bool "Probe for EISA and VL AIC7XXX Adapters"
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 653fb0b42aea..2cfdbef447db 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.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/aic79xx.h#95 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
*
* $FreeBSD$
*/
@@ -75,8 +75,7 @@ struct scb_platform_data;
#define INITIATOR_WILDCARD (~0)
#define SCB_LIST_NULL 0xFF00
#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))
-#define QOUTFIFO_ENTRY_VALID 0x8000
-#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
+#define QOUTFIFO_ENTRY_VALID 0x80
#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
#define SCSIID_TARGET(ahd, scsiid) \
@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state;
typedef void ahd_callback_t (void *);
+struct ahd_completion
+{
+ uint16_t tag;
+ uint8_t sg_status;
+ uint8_t valid_tag;
+};
+
struct ahd_softc {
bus_space_tag_t tags[2];
bus_space_handle_t bshs[2];
@@ -1062,6 +1068,7 @@ struct ahd_softc {
struct scb_data scb_data;
struct hardware_scb *next_queued_hscb;
+ struct map_node *next_queued_hscb_map;
/*
* SCBs that have been sent to the controller
@@ -1140,16 +1147,23 @@ struct ahd_softc {
ahd_flag flags;
struct seeprom_config *seep_config;
- /* Values to store in the SEQCTL register for pause and unpause */
- uint8_t unpause;
- uint8_t pause;
-
/* Command Queues */
+ struct ahd_completion *qoutfifo;
uint16_t qoutfifonext;
uint16_t qoutfifonext_valid_tag;
uint16_t qinfifonext;
uint16_t qinfifo[AHD_SCB_MAX];
- uint16_t *qoutfifo;
+
+ /*
+ * Our qfreeze count. The sequencer compares
+ * this value with its own counter to determine
+ * whether to allow selections to occur.
+ */
+ uint16_t qfreeze_cnt;
+
+ /* Values to store in the SEQCTL register for pause and unpause */
+ uint8_t unpause;
+ uint8_t pause;
/* Critical Section Data */
struct cs *critical_sections;
@@ -1197,8 +1211,7 @@ struct ahd_softc {
*/
bus_dma_tag_t parent_dmat;
bus_dma_tag_t shared_data_dmat;
- bus_dmamap_t shared_data_dmamap;
- dma_addr_t shared_data_busaddr;
+ struct map_node shared_data_map;
/* Information saved through suspend/resume cycles */
struct ahd_suspend_state suspend_state;
@@ -1296,9 +1309,9 @@ struct ahd_devinfo {
};
/****************************** PCI Structures ********************************/
-#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/
-#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */
-#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */
+#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/
+#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */
+#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */
typedef int (ahd_device_setup_t)(struct ahd_softc *);
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index cca58edc8648..3a3204703b15 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
mvi MODE_PTR, MK_MODE(src, dst); \
}
-#define TOGGLE_DFF_MODE \
- if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
- call toggle_dff_mode_work_around; \
- } else { \
- xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \
- }
-
#define RESTORE_MODE(mode) \
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
mov mode call set_mode_work_around; \
@@ -1199,7 +1192,7 @@ register TARGPCISTAT {
/*
* LQ Packet In
- * The last LQ Packet received
+ * The last LQ Packet recieved
*/
register LQIN {
address 0x020
@@ -3542,10 +3535,34 @@ scratch_ram {
COMPLETE_DMA_SCB_HEAD {
size 2
}
- /* Counting semaphore to prevent new select-outs */
+ /*
+ * tail of list of SCBs that have
+ * completed but need to be uploaded
+ * to the host prior to being completed.
+ */
+ COMPLETE_DMA_SCB_TAIL {
+ size 2
+ }
+ /*
+ * head of list of SCBs that have
+ * been uploaded to the host, but cannot
+ * be completed until the QFREEZE is in
+ * full effect (i.e. no selections pending).
+ */
+ COMPLETE_ON_QFREEZE_HEAD {
+ size 2
+ }
+ /*
+ * Counting semaphore to prevent new select-outs
+ * The queue is frozen so long as the sequencer
+ * and kernel freeze counts differ.
+ */
QFREEZE_COUNT {
size 2
}
+ KERNEL_QFREEZE_COUNT {
+ size 2
+ }
/*
* Mode to restore on legacy idle loop exit.
*/
@@ -3625,6 +3642,17 @@ scratch_ram {
size 1
}
/*
+ * Kernel and sequencer offsets into the queue of
+ * incoming target mode command descriptors. The
+ * queue is full when the KERNEL_TQINPOS == TQINPOS.
+ */
+ KERNEL_TQINPOS {
+ size 1
+ }
+ TQINPOS {
+ size 1
+ }
+ /*
* Base address of our shared data with the kernel driver in host
* memory. This includes the qoutfifo and target mode
* incoming command queue.
@@ -3639,17 +3667,6 @@ scratch_ram {
QOUTFIFO_NEXT_ADDR {
size 4
}
- /*
- * Kernel and sequencer offsets into the queue of
- * incoming target mode command descriptors. The
- * queue is full when the KERNEL_TQINPOS == TQINPOS.
- */
- KERNEL_TQINPOS {
- size 1
- }
- TQINPOS {
- size 1
- }
ARG_1 {
size 1
mask SEND_MSG 0x80
@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download
const SG_SIZEOF download
const PKT_OVERRUN_BUFOFFSET download
const SCB_TRANSFER_SIZE download
+const CACHELINE_MASK download
/*
* BIOS SCB offsets
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq
index 65339bc1ca99..bef1f9d369b6 100644
--- a/drivers/scsi/aic7xxx/aic79xx.seq
+++ b/drivers/scsi/aic7xxx/aic79xx.seq
@@ -40,7 +40,7 @@
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_"
@@ -68,13 +68,47 @@ no_error_set:
}
SET_MODE(M_SCSI, M_SCSI)
test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
- test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;
+ test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list;
+ /*
+ * If the kernel has caught up with us, thaw the queue.
+ */
+ mov A, KERNEL_QFREEZE_COUNT;
+ cmp QFREEZE_COUNT, A jne check_frozen_completions;
+ mov A, KERNEL_QFREEZE_COUNT[1];
+ cmp QFREEZE_COUNT[1], A jne check_frozen_completions;
+ and SEQ_FLAGS2, ~SELECTOUT_QFROZEN;
+ jmp check_waiting_list;
+check_frozen_completions:
+ test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus;
+BEGIN_CRITICAL;
+ /*
+ * If we have completions stalled waiting for the qfreeze
+ * to take effect, move them over to the complete_scb list
+ * now that no selections are pending.
+ */
+ cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus;
+ /*
+ * Find the end of the qfreeze list. The first element has
+ * to be treated specially.
+ */
+ bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists;
+ /*
+ * Now the normal loop.
+ */
+ bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1;
+join_lists:
+ bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+ bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2;
+ mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL;
+ jmp idle_loop_checkbus;
+check_waiting_list:
cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
/*
* ENSELO is cleared by a SELDO, so we must test for SELDO
* one last time.
*/
-BEGIN_CRITICAL;
test SSTAT0, SELDO jnz select_out;
END_CRITICAL;
call start_selection;
@@ -90,6 +124,13 @@ idle_loop_check_nonpackreq:
test SSTAT2, NONPACKREQ jz . + 2;
call unexpected_nonpkt_phase_find_ctxt;
if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ /*
+ * On Rev A. hardware, the busy LED is only
+ * turned on automaically during selections
+ * and re-selections. Make the LED status
+ * more useful by forcing it to be on so
+ * long as one of our data FIFOs is active.
+ */
and A, FIFO0FREE|FIFO1FREE, DFFSTAT;
cmp A, FIFO0FREE|FIFO1FREE jne . + 3;
and SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
@@ -101,9 +142,9 @@ idle_loop_check_nonpackreq:
call idle_loop_cchan;
jmp idle_loop;
-BEGIN_CRITICAL;
idle_loop_gsfifo:
SET_MODE(M_SCSI, M_SCSI)
+BEGIN_CRITICAL;
idle_loop_gsfifo_in_scsi_mode:
test LQISTAT2, LQIGSAVAIL jz return;
/*
@@ -152,11 +193,15 @@ END_CRITICAL;
idle_loop_service_fifos:
SET_MODE(M_DFF0, M_DFF0)
+BEGIN_CRITICAL;
test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
call longjmp;
+END_CRITICAL;
idle_loop_next_fifo:
SET_MODE(M_DFF1, M_DFF1)
+BEGIN_CRITICAL;
test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
+END_CRITICAL;
return:
ret;
@@ -170,7 +215,6 @@ BEGIN_CRITICAL;
test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
test CCSCBCTL, CCSCBDONE jz return;
-END_CRITICAL;
/* FALLTHROUGH */
scbdma_tohost_done:
test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
@@ -180,26 +224,18 @@ scbdma_tohost_done:
* bad SCSI status (currently only for underruns), we
* queue the SCB for normal completion. Otherwise, we
* wait until any select-out activity has halted, and
- * then notify the host so that the transaction can be
- * dealt with.
+ * then queue the completion.
*/
- test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
and CCSCBCTL, ~(CCARREN|CCSCBEN);
bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2;
+ mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL;
+ test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;
+ bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2;
+ bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret;
+scbdma_queue_completion:
bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
-scbdma_notify_host:
- SET_MODE(M_SCSI, M_SCSI)
- test SCSISEQ0, ENSELO jnz return;
- test SSTAT0, (SELDO|SELINGO) jnz return;
- SET_MODE(M_CCHAN, M_CCHAN)
- /*
- * Remove SCB and notify host.
- */
- and CCSCBCTL, ~(CCARREN|CCSCBEN);
- bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
- SET_SEQINTCODE(BAD_SCB_STATUS)
- ret;
fill_qoutfifo_dmadone:
and CCSCBCTL, ~(CCARREN|CCSCBEN);
call qoutfifo_updated;
@@ -208,6 +244,7 @@ fill_qoutfifo_dmadone:
test QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
+END_CRITICAL;
qoutfifo_updated:
/*
@@ -324,14 +361,15 @@ fill_qoutfifo:
* Keep track of the SCBs we are dmaing just
* in case the DMA fails or is aborted.
*/
- mov A, QOUTFIFO_ENTRY_VALID_TAG;
bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;
mvi CCSCBCTL, CCSCBRESET;
bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;
+ mov A, QOUTFIFO_NEXT_ADDR;
bmov SCBPTR, COMPLETE_SCB_HEAD, 2;
fill_qoutfifo_loop:
- mov CCSCBRAM, SCBPTR;
- or CCSCBRAM, A, SCBPTR[1];
+ bmov CCSCBRAM, SCBPTR, 2;
+ mov CCSCBRAM, SCB_SGPTR[0];
+ mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG;
mov NONE, SDSCB_QOFF;
inc INT_COALESCING_CMDCOUNT;
add CMDS_PENDING, -1;
@@ -339,6 +377,18 @@ fill_qoutfifo_loop:
cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;
cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;
test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;
+ /*
+ * Don't cross an ADB or Cachline boundary when DMA'ing
+ * completion entries. In PCI mode, at least in 32/33
+ * configurations, the SCB DMA engine may lose its place
+ * in the data-stream should the target force a retry on
+ * something other than an 8byte aligned boundary. In
+ * PCI-X mode, we do this to avoid split transactions since
+ * many chipsets seem to be unable to format proper split
+ * completions to continue the data transfer.
+ */
+ add SINDEX, A, CCSCBADDR;
+ test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done;
bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
jmp fill_qoutfifo_loop;
fill_qoutfifo_done:
@@ -354,7 +404,6 @@ dma_complete_scb:
bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
bmov SCBHADDR, SCB_BUSADDR, 4;
mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
-END_CRITICAL;
/*
* Either post or fetch an SCB from host memory. The caller
@@ -371,9 +420,19 @@ dma_scb:
mvi SCBHCNT, SCB_TRANSFER_SIZE;
mov CCSCBCTL, SINDEX ret;
-BEGIN_CRITICAL;
setjmp:
- bmov LONGJMP_ADDR, STACK, 2 ret;
+ /*
+ * At least on the A, a return in the same
+ * instruction as the bmov results in a return
+ * to the caller, not to the new address at the
+ * top of the stack. Since we want the latter
+ * (we use setjmp to register a handler from an
+ * interrupt context but not invoke that handler
+ * until we return to our idle loop), use a
+ * separate ret instruction.
+ */
+ bmov LONGJMP_ADDR, STACK, 2;
+ ret;
setjmp_inline:
bmov LONGJMP_ADDR, STACK, 2;
longjmp:
@@ -392,11 +451,6 @@ set_mode_work_around:
mvi SEQINTCTL, INTVEC1DSL;
mov MODE_PTR, SINDEX;
clr SEQINTCTL ret;
-
-toggle_dff_mode_work_around:
- mvi SEQINTCTL, INTVEC1DSL;
- xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
- clr SEQINTCTL ret;
}
@@ -490,6 +544,21 @@ allocate_fifo1:
SET_SRC_MODE M_SCSI;
SET_DST_MODE M_SCSI;
select_in:
+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ /*
+ * On Rev A. hardware, the busy LED is only
+ * turned on automaically during selections
+ * and re-selections. Make the LED status
+ * more useful by forcing it to be on from
+ * the point of selection until our idle
+ * loop determines that neither of our FIFOs
+ * are busy. This handles the non-packetized
+ * case nicely as we will not return to the
+ * idle loop until the busfree at the end of
+ * each transaction.
+ */
+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;
+ }
if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
/*
* Test to ensure that the bus has not
@@ -528,6 +597,21 @@ SET_SRC_MODE M_SCSI;
SET_DST_MODE M_SCSI;
select_out:
BEGIN_CRITICAL;
+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ /*
+ * On Rev A. hardware, the busy LED is only
+ * turned on automaically during selections
+ * and re-selections. Make the LED status
+ * more useful by forcing it to be on from
+ * the point of re-selection until our idle
+ * loop determines that neither of our FIFOs
+ * are busy. This handles the non-packetized
+ * case nicely as we will not return to the
+ * idle loop until the busfree at the end of
+ * each transaction.
+ */
+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;
+ }
/* Clear out all SCBs that have been successfully sent. */
if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
/*
@@ -1000,15 +1084,9 @@ not_found_ITloop:
/*
* We received a "command complete" message. Put the SCB on the complete
* queue and trigger a completion interrupt via the idle loop. Before doing
- * so, check to see if there
- * is a residual or the status byte is something other than STATUS_GOOD (0).
- * In either of these conditions, we upload the SCB back to the host so it can
- * process this information. In the case of a non zero status byte, we
- * additionally interrupt the kernel driver synchronously, allowing it to
- * decide if sense should be retrieved. If the kernel driver wishes to request
- * sense, it will fill the kernel SCB with a request sense command, requeue
- * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting
- * RETURN_1 to SEND_SENSE.
+ * so, check to see if there is a residual or the status byte is something
+ * other than STATUS_GOOD (0). In either of these conditions, we upload the
+ * SCB back to the host so it can process this information.
*/
mesgin_complete:
@@ -1053,6 +1131,7 @@ complete_nomsg:
call queue_scb_completion;
jmp await_busfree;
+BEGIN_CRITICAL;
freeze_queue:
/* Cancel any pending select-out. */
test SSTAT0, SELDO|SELINGO jnz . + 2;
@@ -1063,6 +1142,7 @@ freeze_queue:
adc QFREEZE_COUNT[1], A;
or SEQ_FLAGS2, SELECTOUT_QFROZEN;
mov A, ACCUM_SAVE ret;
+END_CRITICAL;
/*
* Complete the current FIFO's SCB if data for this same
@@ -1085,8 +1165,10 @@ queue_scb_completion:
test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
complete:
+BEGIN_CRITICAL;
bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+END_CRITICAL;
bad_status:
cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
call freeze_queue;
@@ -1097,9 +1179,18 @@ upload_scb:
* it on the host.
*/
bmov SCB_TAG, SCBPTR, 2;
- bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
+BEGIN_CRITICAL;
+ or SCB_SGPTR, SG_STATUS_VALID;
+ mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;
+ cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;
bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
- or SCB_SGPTR, SG_STATUS_VALID ret;
+ bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;
+add_dma_scb_tail:
+ bmov REG0, SCBPTR, 2;
+ bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;
+ bmov SCB_NEXT_COMPLETE, REG0, 2;
+ bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;
+END_CRITICAL;
/*
* Is it a disconnect message? Set a flag in the SCB to remind us
@@ -1146,8 +1237,18 @@ SET_DST_MODE M_DFF1;
await_busfree_clrchn:
mvi DFFSXFRCTL, CLRCHN;
await_busfree_not_m_dff:
- call clear_target_state;
+ /* clear target specific flags */
+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
test SSTAT1,REQINIT|BUSFREE jz .;
+ /*
+ * We only set BUSFREE status once either a new
+ * phase has been detected or we are really
+ * BUSFREE. This allows the driver to know
+ * that we are active on the bus even though
+ * no identified transaction exists should a
+ * timeout occur while awaiting busfree.
+ */
+ mvi LASTPHASE, P_BUSFREE;
test SSTAT1, BUSFREE jnz idle_loop;
SET_SEQINTCODE(MISSED_BUSFREE)
@@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo:
call allocate_fifo;
jmp mesgin_done;
-clear_target_state:
- mvi LASTPHASE, P_BUSFREE;
- /* clear target specific flags */
- mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
-
phase_lock:
if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
/*
@@ -1298,6 +1394,47 @@ service_fifo:
test CCSGCTL, CCSGENACK jnz return;
/*
+ * Should the other FIFO get the S/G cache first? If
+ * both FIFOs have been allocated since we last checked
+ * any FIFO, it is important that we service a FIFO
+ * that is not actively on the bus first. This guarantees
+ * that a FIFO will be freed to handle snapshot requests for
+ * any FIFO that is still on the bus. Chips with RTI do not
+ * perform snapshots, so don't bother with this test there.
+ */
+ if ((ahd->features & AHD_RTI) == 0) {
+ /*
+ * If we're not still receiving SCSI data,
+ * it is safe to allocate the S/G cache to
+ * this FIFO.
+ */
+ test DFCNTRL, SCSIEN jz idle_sgfetch_start;
+
+ /*
+ * Switch to the other FIFO. Non-RTI chips
+ * also have the "set mode" bug, so we must
+ * disable interrupts during the switch.
+ */
+ mvi SEQINTCTL, INTVEC1DSL;
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+
+ /*
+ * If the other FIFO needs loading, then it
+ * must not have claimed the S/G cache yet
+ * (SG_CACHE_AVAIL would have been cleared in
+ * the orginal FIFO mode and we test this above).
+ * Return to the idle loop so we can process the
+ * FIFO not currently on the bus first.
+ */
+ test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;
+ clr SEQINTCTL ret;
+idle_sgfetch_okay:
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+ clr SEQINTCTL;
+ }
+
+idle_sgfetch_start:
+ /*
* We fetch a "cacheline aligned" and sized amount of data
* so we don't end up referencing a non-existant page.
* Cacheline aligned is in quotes because the kernel will
@@ -1308,7 +1445,7 @@ service_fifo:
mvi SGHCNT, SG_PREFETCH_CNT;
if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
/*
- * Need two instruction between "touches" of SGHADDR.
+ * Need two instructions between "touches" of SGHADDR.
*/
nop;
}
@@ -1658,7 +1795,7 @@ export seq_isr:
* savepointer in the current FIFO. We do this so that
* a pending CTXTDONE or SAVEPTR is visible in the active
* FIFO. This status is the only way we can detect if we
- * have lost the race (e.g. host paused us) and our attepts
+ * have lost the race (e.g. host paused us) and our attempts
* to disable the channel occurred after all REQs were
* already seen and acked (REQINIT never comes true).
*/
@@ -1667,7 +1804,7 @@ export seq_isr:
test DFCNTRL, DIRECTION jz interrupt_return;
and DFCNTRL, ~SCSIEN;
snapshot_wait_data_valid:
- test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
+ test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;
test SSTAT1, REQINIT jz snapshot_wait_data_valid;
snapshot_data_valid:
or DFCNTRL, SCSIEN;
@@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status:
dec SCB_FIFO_USE_COUNT;
test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
mvi DFFSXFRCTL, CLRCHN ret;
-END_CRITICAL;
/*
* LAST_SEG_DONE status has been seen in the current FIFO.
@@ -1843,7 +1979,6 @@ END_CRITICAL;
* Check for overrun and see if we can complete this command.
*/
pkt_last_seg_done:
-BEGIN_CRITICAL;
/*
* Mark transfer as completed.
*/
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 4e8f00df978d..db8f5ce99ee3 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_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/aic79xx.c#202 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
*/
#ifdef __linux__
@@ -332,6 +330,14 @@ ahd_restart(struct ahd_softc *ahd)
ahd_outb(ahd, SCSISEQ1,
ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+ /*
+ * Clear any pending sequencer interrupt. It is no
+ * longer relevant since we're resetting the Program
+ * Counter.
+ */
+ ahd_outb(ahd, CLRINT, CLRSEQINT);
+
ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
ahd_unpause(ahd);
}
@@ -373,13 +379,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
saved_modes = ahd_save_modes(ahd);
/*
- * Complete any SCBs that just finished being
- * DMA'ed into the qoutfifo.
- */
- ahd_run_qoutfifo(ahd);
-
- /*
- * Flush the good status FIFO for compelted packetized commands.
+ * Flush the good status FIFO for completed packetized commands.
*/
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
saved_scbptr = ahd_get_scbptr(ahd);
@@ -387,8 +387,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
u_int fifo_mode;
u_int i;
- scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
- | ahd_inb(ahd, GSFIFO);
+ scbid = ahd_inw(ahd, GSFIFO);
scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL) {
printf("%s: Warning - GSFIFO SCB %d invalid\n",
@@ -401,22 +400,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
* the host before completing the command.
*/
fifo_mode = 0;
+rescan_fifos:
for (i = 0; i < 2; i++) {
/* Toggle to the other mode. */
fifo_mode ^= 1;
ahd_set_modes(ahd, fifo_mode, fifo_mode);
+
if (ahd_scb_active_in_fifo(ahd, scb) == 0)
continue;
ahd_run_data_fifo(ahd, scb);
/*
- * Clearing this transaction in this FIFO may
- * cause a CFG4DATA for this same transaction
- * to assert in the other FIFO. Make sure we
- * loop one more time and check the other FIFO.
+ * Running this FIFO may cause a CFG4DATA for
+ * this same transaction to assert in the other
+ * FIFO or a new snapshot SAVEPTRS interrupt
+ * in this FIFO. Even running a FIFO may not
+ * clear the transaction if we are still waiting
+ * for data to drain to the host. We must loop
+ * until the transaction is not active in either
+ * FIFO just to be sure. Reset our loop counter
+ * so we will visit both FIFOs again before
+ * declaring this transaction finished. We
+ * also delay a bit so that status has a chance
+ * to change before we look at this FIFO again.
*/
- i = 0;
+ ahd_delay(200);
+ goto rescan_fifos;
}
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_set_scbptr(ahd, scbid);
@@ -429,19 +439,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
/*
* The transfer completed with a residual.
* Place this SCB on the complete DMA list
- * so that we Update our in-core copy of the
+ * so that we update our in-core copy of the
* SCB before completing the command.
*/
ahd_outb(ahd, SCB_SCSI_STATUS, 0);
ahd_outb(ahd, SCB_SGPTR,
ahd_inb_scbram(ahd, SCB_SGPTR)
| SG_STATUS_VALID);
- ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+ ahd_outw(ahd, SCB_TAG, scbid);
+ ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
- ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
- if (SCBID_IS_NULL(comp_head))
- ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,
- SCB_GET_TAG(scb));
+ if (SCBID_IS_NULL(comp_head)) {
+ ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+ } else {
+ u_int tail;
+
+ tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
+ ahd_set_scbptr(ahd, tail);
+ ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+ ahd_set_scbptr(ahd, scbid);
+ }
} else
ahd_complete_scb(ahd, scb);
}
@@ -465,9 +484,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
break;
ahd_delay(200);
}
- if ((ccscbctl & CCSCBDIR) != 0)
+ /*
+ * We leave the sequencer to cleanup in the case of DMA's to
+ * update the qoutfifo. In all other cases (DMA's to the
+ * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
+ * we disable the DMA engine so that the sequencer will not
+ * attempt to handle the DMA completion.
+ */
+ if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
+ /*
+ * Complete any SCBs that just finished
+ * being DMA'ed into the qoutfifo.
+ */
+ ahd_run_qoutfifo(ahd);
+
saved_scbptr = ahd_get_scbptr(ahd);
/*
* Manually update/complete any completed SCBs that are waiting to be
@@ -494,6 +526,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
scbid = next_scbid;
}
ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+
+ scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+ while (!SCBID_IS_NULL(scbid)) {
+
+ ahd_set_scbptr(ahd, scbid);
+ next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+ scb = ahd_lookup_scb(ahd, scbid);
+ if (scb == NULL) {
+ printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
+ ahd_name(ahd), scbid);
+ continue;
+ }
+
+ ahd_complete_scb(ahd, scb);
+ scbid = next_scbid;
+ }
+ ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
while (!SCBID_IS_NULL(scbid)) {
@@ -558,150 +608,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
{
u_int seqintsrc;
- while (1) {
- seqintsrc = ahd_inb(ahd, SEQINTSRC);
- if ((seqintsrc & CFG4DATA) != 0) {
- uint32_t datacnt;
- uint32_t sgptr;
-
- /*
- * Clear full residual flag.
- */
- sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
- ahd_outb(ahd, SCB_SGPTR, sgptr);
+ seqintsrc = ahd_inb(ahd, SEQINTSRC);
+ if ((seqintsrc & CFG4DATA) != 0) {
+ uint32_t datacnt;
+ uint32_t sgptr;
- /*
- * Load datacnt and address.
- */
- datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
- if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
- sgptr |= LAST_SEG;
- ahd_outb(ahd, SG_STATE, 0);
- } else
- ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
- ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
- ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
- ahd_outb(ahd, SG_CACHE_PRE, sgptr);
- ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
+ /*
+ * Clear full residual flag.
+ */
+ sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+ ahd_outb(ahd, SCB_SGPTR, sgptr);
- /*
- * Initialize Residual Fields.
- */
- ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
- ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+ /*
+ * Load datacnt and address.
+ */
+ datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+ if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+ sgptr |= LAST_SEG;
+ ahd_outb(ahd, SG_STATE, 0);
+ } else
+ ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+ ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+ ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+ ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+ ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
- /*
- * Mark the SCB as having a FIFO in use.
- */
- ahd_outb(ahd, SCB_FIFO_USE_COUNT,
- ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
+ /*
+ * Initialize Residual Fields.
+ */
+ ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+ ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
- /*
- * Install a "fake" handler for this FIFO.
- */
- ahd_outw(ahd, LONGJMP_ADDR, 0);
+ /*
+ * Mark the SCB as having a FIFO in use.
+ */
+ ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+ ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
- /*
- * Notify the hardware that we have satisfied
- * this sequencer interrupt.
- */
- ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
- } else if ((seqintsrc & SAVEPTRS) != 0) {
- uint32_t sgptr;
- uint32_t resid;
+ /*
+ * Install a "fake" handler for this FIFO.
+ */
+ ahd_outw(ahd, LONGJMP_ADDR, 0);
- if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
- /*
- * Snapshot Save Pointers. Clear
- * the snapshot and continue.
- */
- ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
- continue;
- }
+ /*
+ * Notify the hardware that we have satisfied
+ * this sequencer interrupt.
+ */
+ ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+ } else if ((seqintsrc & SAVEPTRS) != 0) {
+ uint32_t sgptr;
+ uint32_t resid;
+ if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
/*
- * Disable S/G fetch so the DMA engine
- * is available to future users.
+ * Snapshot Save Pointers. All that
+ * is necessary to clear the snapshot
+ * is a CLRCHN.
*/
- if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
- ahd_outb(ahd, CCSGCTL, 0);
- ahd_outb(ahd, SG_STATE, 0);
+ goto clrchn;
+ }
- /*
- * Flush the data FIFO. Strickly only
- * necessary for Rev A parts.
- */
- ahd_outb(ahd, DFCNTRL,
- ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+ /*
+ * Disable S/G fetch so the DMA engine
+ * is available to future users.
+ */
+ if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+ ahd_outb(ahd, CCSGCTL, 0);
+ ahd_outb(ahd, SG_STATE, 0);
- /*
- * Calculate residual.
- */
- sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
- resid = ahd_inl(ahd, SHCNT);
- resid |=
- ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
- ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
- if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
- /*
- * Must back up to the correct S/G element.
- * Typically this just means resetting our
- * low byte to the offset in the SG_CACHE,
- * but if we wrapped, we have to correct
- * the other bytes of the sgptr too.
- */
- if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
- && (sgptr & 0x80) == 0)
- sgptr -= 0x100;
- sgptr &= ~0xFF;
- sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
- & SG_ADDR_MASK;
- ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
- ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
- } else if ((resid & AHD_SG_LEN_MASK) == 0) {
- ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
- sgptr | SG_LIST_NULL);
- }
- /*
- * Save Pointers.
- */
- ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
- ahd_outl(ahd, SCB_DATACNT, resid);
- ahd_outl(ahd, SCB_SGPTR, sgptr);
- ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
- ahd_outb(ahd, SEQIMODE,
- ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
- /*
- * If the data is to the SCSI bus, we are
- * done, otherwise wait for FIFOEMP.
- */
- if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
- break;
- } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
- uint32_t sgptr;
- uint64_t data_addr;
- uint32_t data_len;
- u_int dfcntrl;
+ /*
+ * Flush the data FIFO. Strickly only
+ * necessary for Rev A parts.
+ */
+ ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+ /*
+ * Calculate residual.
+ */
+ sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+ resid = ahd_inl(ahd, SHCNT);
+ resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+ ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+ if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
/*
- * Disable S/G fetch so the DMA engine
- * is available to future users.
+ * Must back up to the correct S/G element.
+ * Typically this just means resetting our
+ * low byte to the offset in the SG_CACHE,
+ * but if we wrapped, we have to correct
+ * the other bytes of the sgptr too.
*/
- if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
- ahd_outb(ahd, CCSGCTL, 0);
- ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
- }
+ if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+ && (sgptr & 0x80) == 0)
+ sgptr -= 0x100;
+ sgptr &= ~0xFF;
+ sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+ & SG_ADDR_MASK;
+ ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+ ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+ } else if ((resid & AHD_SG_LEN_MASK) == 0) {
+ ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+ sgptr | SG_LIST_NULL);
+ }
+ /*
+ * Save Pointers.
+ */
+ ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+ ahd_outl(ahd, SCB_DATACNT, resid);
+ ahd_outl(ahd, SCB_SGPTR, sgptr);
+ ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+ ahd_outb(ahd, SEQIMODE,
+ ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+ /*
+ * If the data is to the SCSI bus, we are
+ * done, otherwise wait for FIFOEMP.
+ */
+ if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+ goto clrchn;
+ } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+ uint32_t sgptr;
+ uint64_t data_addr;
+ uint32_t data_len;
+ u_int dfcntrl;
- /*
- * Wait for the DMA engine to notice that the
- * host transfer is enabled and that there is
- * space in the S/G FIFO for new segments before
- * loading more segments.
- */
- if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)
- continue;
- if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)
- continue;
+ /*
+ * Disable S/G fetch so the DMA engine
+ * is available to future users. We won't
+ * be using the DMA engine to load segments.
+ */
+ if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
+ ahd_outb(ahd, CCSGCTL, 0);
+ ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+ }
+
+ /*
+ * Wait for the DMA engine to notice that the
+ * host transfer is enabled and that there is
+ * space in the S/G FIFO for new segments before
+ * loading more segments.
+ */
+ if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
+ && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
/*
* Determine the offset of the next S/G
@@ -748,7 +794,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
* Advertise the segment to the hardware.
*/
dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
- if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+ if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
/*
* Use SCSIENWRDIS so that SCSIEN
* is never modified by this
@@ -757,35 +803,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
dfcntrl |= SCSIENWRDIS;
}
ahd_outb(ahd, DFCNTRL, dfcntrl);
- } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
- & LAST_SEG_DONE) != 0) {
-
- /*
- * Transfer completed to the end of SG list
- * and has flushed to the host.
- */
- ahd_outb(ahd, SCB_SGPTR,
- ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
- break;
- } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
- break;
}
- ahd_delay(200);
+ } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
+
+ /*
+ * Transfer completed to the end of SG list
+ * and has flushed to the host.
+ */
+ ahd_outb(ahd, SCB_SGPTR,
+ ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+ goto clrchn;
+ } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+clrchn:
+ /*
+ * Clear any handler for this FIFO, decrement
+ * the FIFO use count for the SCB, and release
+ * the FIFO.
+ */
+ ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
+ ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+ ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
+ ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
}
- /*
- * Clear any handler for this FIFO, decrement
- * the FIFO use count for the SCB, and release
- * the FIFO.
- */
- ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
- ahd_outb(ahd, SCB_FIFO_USE_COUNT,
- ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
- ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
}
+/*
+ * Look for entries in the QoutFIFO that have completed.
+ * The valid_tag completion field indicates the validity
+ * of the entry - the valid value toggles each time through
+ * the queue. We use the sg_status field in the completion
+ * entry to avoid referencing the hscb if the completion
+ * occurred with no errors and no residual. sg_status is
+ * a copy of the first byte (little endian) of the sgptr
+ * hscb field.
+ */
void
ahd_run_qoutfifo(struct ahd_softc *ahd)
{
+ struct ahd_completion *completion;
struct scb *scb;
u_int scb_index;
@@ -793,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
panic("ahd_run_qoutfifo recursion");
ahd->flags |= AHD_RUNNING_QOUTFIFO;
ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
- while ((ahd->qoutfifo[ahd->qoutfifonext]
- & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {
+ for (;;) {
+ completion = &ahd->qoutfifo[ahd->qoutfifonext];
- scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]
- & ~QOUTFIFO_ENTRY_VALID_LE);
+ if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
+ break;
+
+ scb_index = ahd_le16toh(completion->tag);
scb = ahd_lookup_scb(ahd, scb_index);
if (scb == NULL) {
printf("%s: WARNING no command for scb %d "
@@ -805,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
ahd_name(ahd), scb_index,
ahd->qoutfifonext);
ahd_dump_card_state(ahd);
- } else
- ahd_complete_scb(ahd, scb);
+ } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
+ ahd_handle_scb_status(ahd, scb);
+ } else {
+ ahd_done(ahd, scb);
+ }
ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
if (ahd->qoutfifonext == 0)
- ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE;
+ ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
}
ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
}
@@ -876,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), seqintcode);
#endif
switch (seqintcode) {
- case BAD_SCB_STATUS:
- {
- struct scb *scb;
- u_int scbid;
- int cmds_pending;
-
- scbid = ahd_get_scbptr(ahd);
- scb = ahd_lookup_scb(ahd, scbid);
- if (scb != NULL) {
- ahd_complete_scb(ahd, scb);
- } else {
- printf("%s: WARNING no command for scb %d "
- "(bad status)\n", ahd_name(ahd), scbid);
- ahd_dump_card_state(ahd);
- }
- cmds_pending = ahd_inw(ahd, CMDS_PENDING);
- if (cmds_pending > 0)
- ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
- break;
- }
case ENTERING_NONPACK:
{
struct scb *scb;
@@ -1060,7 +1100,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_outb(ahd, SAVED_LUN, 0);
ahd_outb(ahd, SEQ_FLAGS, 0);
ahd_assert_atn(ahd);
- scb->flags &= ~(SCB_PACKETIZED);
+ scb->flags &= ~SCB_PACKETIZED;
scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
ahd_freeze_devq(ahd, scb);
ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
@@ -1503,9 +1543,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
&& (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
scb = NULL;
- /* Make sure the sequencer is in a safe location. */
- ahd_clear_critical_section(ahd);
-
if ((status0 & IOERR) != 0) {
u_int now_lvd;
@@ -1521,26 +1558,35 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
ahd_setup_iocell_workaround(ahd);
ahd_unpause(ahd);
} else if ((status0 & OVERRUN) != 0) {
+
printf("%s: SCSI offset overrun detected. Resetting bus.\n",
ahd_name(ahd));
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
} else if ((status & SCSIRSTI) != 0) {
+
printf("%s: Someone reset channel A\n", ahd_name(ahd));
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
} else if ((status & SCSIPERR) != 0) {
+
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
ahd_handle_transmission_error(ahd);
} else if (lqostat0 != 0) {
+
printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
ahd_outb(ahd, CLRLQOINT0, lqostat0);
- if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
+ if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
ahd_outb(ahd, CLRLQOINT1, 0);
- }
} else if ((status & SELTO) != 0) {
u_int scbid;
/* Stop the selection */
ahd_outb(ahd, SCSISEQ0, 0);
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
/* No more pending messages */
ahd_clear_msg_state(ahd);
@@ -1573,24 +1619,27 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
scbid);
}
#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.
- */
ahd_scb_devinfo(ahd, &devinfo, scb);
- ahd_force_renegotiation(ahd, &devinfo);
ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
ahd_freeze_devq(ahd, 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.
+ */
+ ahd_handle_devreset(ahd, &devinfo,
+ CAM_LUN_WILDCARD,
+ CAM_SEL_TIMEOUT,
+ "Selection Timeout",
+ /*verbose_level*/1);
}
ahd_outb(ahd, CLRINT, CLRSCSIINT);
ahd_iocell_first_selection(ahd);
ahd_unpause(ahd);
} else if ((status0 & (SELDI|SELDO)) != 0) {
+
ahd_iocell_first_selection(ahd);
ahd_unpause(ahd);
} else if (status3 != 0) {
@@ -1598,6 +1647,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), status3);
ahd_outb(ahd, CLRSINT3, status3);
} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
+
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
ahd_handle_lqiphase_error(ahd, lqistat1);
} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
/*
@@ -1622,6 +1675,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
*/
ahd_outb(ahd, SCSISEQ0, 0);
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
/*
* Determine what we were up to at the time of
* the busfree.
@@ -1659,7 +1715,16 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
clear_fifo = 0;
packetized = (lqostat1 & LQOBUSFREE) != 0;
if (!packetized
- && ahd_inb(ahd, LASTPHASE) == P_BUSFREE)
+ && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
+ && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
+ && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
+ || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
+ /*
+ * Assume packetized if we are not
+ * on the bus in a non-packetized
+ * capacity and any pending selection
+ * was a packetized selection.
+ */
packetized = 1;
break;
}
@@ -2310,8 +2375,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
"PRGMCNT == 0x%x\n",
ahd_lookup_phase_entry(lastphase)->phasemsg,
aborted,
- ahd_inb(ahd, PRGMCNT)
- | (ahd_inb(ahd, PRGMCNT+1) << 8));
+ ahd_inw(ahd, PRGMCNT));
ahd_dump_card_state(ahd);
}
/* Always restart the sequencer. */
@@ -2474,8 +2538,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
u_int i;
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- seqaddr = ahd_inb(ahd, CURADDR)
- | (ahd_inb(ahd, CURADDR+1) << 8);
+ seqaddr = ahd_inw(ahd, CURADDR);
cs = ahd->critical_sections;
for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
@@ -3196,14 +3259,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
- && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) {
+ && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
+ && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
/*
* Slow down our CRC interval to be
- * compatible with devices that can't
- * handle a CRC at full speed.
+ * compatible with non-packetized
+ * U160 devices that can't handle a
+ * CRC at full speed.
*/
con_opts |= ENSLOWCRC;
}
+
+ if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
+ /*
+ * On H2A4, revert to a slower slewrate
+ * on non-paced transfers.
+ */
+ iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
+ ~AHD_SLEWRATE_MASK;
+ }
}
ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
@@ -3292,11 +3366,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
* Force the sequencer to reinitialize the selection for
* the command at the head of the execution queue if it
* has already been setup. The negotiation changes may
- * effect whether we select-out with ATN.
+ * effect whether we select-out with ATN. It is only
+ * safe to clear ENSELO when the bus is not free and no
+ * selection is in progres or completed.
*/
saved_modes = ahd_save_modes(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
+ if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
+ && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
+ ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
saved_scbptr = ahd_get_scbptr(ahd);
/* Ensure that the hscbs down on the card match the new information */
for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
@@ -4909,10 +4987,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
* Determine initial values for data_addr and data_cnt
* for resuming the data phase.
*/
- sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24)
- | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)
- | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)
- | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
+ sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
sgptr &= SG_PTR_MASK;
resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
@@ -4930,10 +5005,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
dataptr = ahd_le64toh(sg->addr)
+ (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
- resid;
- ahd_outb(ahd, HADDR + 7, dataptr >> 56);
- ahd_outb(ahd, HADDR + 6, dataptr >> 48);
- ahd_outb(ahd, HADDR + 5, dataptr >> 40);
- ahd_outb(ahd, HADDR + 4, dataptr >> 32);
+ ahd_outl(ahd, HADDR + 4, dataptr >> 32);
} else {
struct ahd_dma_seg *sg;
@@ -4948,10 +5020,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
ahd_outb(ahd, HADDR + 4,
(ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
}
- ahd_outb(ahd, HADDR + 3, dataptr >> 24);
- ahd_outb(ahd, HADDR + 2, dataptr >> 16);
- ahd_outb(ahd, HADDR + 1, dataptr >> 8);
- ahd_outb(ahd, HADDR, dataptr);
+ ahd_outl(ahd, HADDR, dataptr);
ahd_outb(ahd, HCNT + 2, resid >> 16);
ahd_outb(ahd, HCNT + 1, resid >> 8);
ahd_outb(ahd, HCNT, resid);
@@ -5011,13 +5080,14 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
AHD_TRANS_CUR, /*paused*/TRUE);
ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
- /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE);
+ /*ppr_options*/0, AHD_TRANS_CUR,
+ /*paused*/TRUE);
- ahd_send_async(ahd, devinfo->channel, devinfo->target,
- lun, AC_SENT_BDR, NULL);
+ if (status != CAM_SEL_TIMEOUT)
+ ahd_send_async(ahd, devinfo->channel, devinfo->target,
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
- if (message != NULL
- && (verbose_level <= bootverbose))
+ if (message != NULL && bootverbose)
printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
message, devinfo->channel, devinfo->target, found);
}
@@ -5203,13 +5273,13 @@ ahd_free(struct ahd_softc *ahd)
/* FALLTHROUGH */
case 4:
ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap);
+ ahd->shared_data_map.dmamap);
/* FALLTHROUGH */
case 3:
ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
- ahd->shared_data_dmamap);
+ ahd->shared_data_map.dmamap);
ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap);
+ ahd->shared_data_map.dmamap);
/* FALLTHROUGH */
case 2:
ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
@@ -5975,16 +6045,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
newcount = MIN(newcount, scb_data->sgs_left);
newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
- scb_data->sense_left -= newcount;
- scb_data->scbs_left -= newcount;
- scb_data->sgs_left -= newcount;
for (i = 0; i < newcount; i++) {
- u_int col_tag;
-
struct scb_platform_data *pdata;
+ u_int col_tag;
#ifndef __linux__
int error;
#endif
+
next_scb = (struct scb *)malloc(sizeof(*next_scb),
M_DEVBUF, M_NOWAIT);
if (next_scb == NULL)
@@ -6041,6 +6108,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
sense_data += AHD_SENSE_BUFSIZE;
sense_busaddr += AHD_SENSE_BUFSIZE;
scb_data->numscbs++;
+ scb_data->sense_left--;
+ scb_data->scbs_left--;
+ scb_data->sgs_left--;
}
}
@@ -6088,7 +6158,6 @@ static const char *termstat_strings[] = {
int
ahd_init(struct ahd_softc *ahd)
{
- uint8_t *base_vaddr;
uint8_t *next_vaddr;
dma_addr_t next_baddr;
size_t driver_data_size;
@@ -6156,7 +6225,7 @@ ahd_init(struct ahd_softc *ahd)
* for the target mode role, we must additionally provide space for
* the incoming target command fifo.
*/
- driver_data_size = AHD_SCB_MAX * sizeof(uint16_t)
+ driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
+ sizeof(struct hardware_scb);
if ((ahd->features & AHD_TARGETMODE) != 0)
driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6178,20 +6247,23 @@ ahd_init(struct ahd_softc *ahd)
/* Allocation of driver data */
if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
- (void **)&base_vaddr,
- BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) {
+ (void **)&ahd->shared_data_map.vaddr,
+ BUS_DMA_NOWAIT,
+ &ahd->shared_data_map.dmamap) != 0) {
return (ENOMEM);
}
ahd->init_level++;
/* And permanently map it in */
- ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
- base_vaddr, driver_data_size, ahd_dmamap_cb,
- &ahd->shared_data_busaddr, /*flags*/0);
- ahd->qoutfifo = (uint16_t *)base_vaddr;
+ ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+ ahd->shared_data_map.vaddr, driver_data_size,
+ ahd_dmamap_cb, &ahd->shared_data_map.physaddr,
+ /*flags*/0);
+ ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
- next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t);
+ next_baddr = ahd->shared_data_map.physaddr
+ + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
if ((ahd->features & AHD_TARGETMODE) != 0) {
ahd->targetcmds = (struct target_cmd *)next_vaddr;
next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6212,6 +6284,7 @@ ahd_init(struct ahd_softc *ahd)
* specially from the DMA safe memory chunk used for the QOUTFIFO.
*/
ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
+ ahd->next_queued_hscb_map = &ahd->shared_data_map;
ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
ahd->init_level++;
@@ -6517,10 +6590,10 @@ ahd_chip_init(struct ahd_softc *ahd)
/* All of our queues are empty */
ahd->qoutfifonext = 0;
- ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE;
- ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8);
+ ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
+ ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
for (i = 0; i < AHD_QOUT_SIZE; i++)
- ahd->qoutfifo[i] = 0;
+ ahd->qoutfifo[i].valid_tag = 0;
ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
ahd->qinfifonext = 0;
@@ -6553,24 +6626,22 @@ ahd_chip_init(struct ahd_softc *ahd)
ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+ ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
/*
* The Freeze Count is 0.
*/
+ ahd->qfreeze_cnt = 0;
ahd_outw(ahd, QFREEZE_COUNT, 0);
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
/*
* Tell the sequencer where it can find our arrays in memory.
*/
- busaddr = ahd->shared_data_busaddr;
- ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF);
- ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);
+ busaddr = ahd->shared_data_map.physaddr;
+ ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
+ ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
/*
* Setup the allowed SCSI Sequences based on operational mode.
@@ -6619,10 +6690,7 @@ ahd_chip_init(struct ahd_softc *ahd)
* Tell the sequencer which SCB will be the next one it receives.
*/
busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
/*
* Default to coalescing disabled.
@@ -6926,43 +6994,34 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
{
u_int intstat;
u_int maxloops;
- u_int qfreeze_cnt;
maxloops = 1000;
ahd->flags |= AHD_ALL_INTERRUPTS;
ahd_pause(ahd);
/*
- * Increment the QFreeze Count so that the sequencer
- * will not start new selections. We do this only
+ * Freeze the outgoing selections. We do this only
* until we are safely paused without further selections
* pending.
*/
- ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1);
+ ahd->qfreeze_cnt--;
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
do {
- struct scb *waiting_scb;
ahd_unpause(ahd);
+ /*
+ * Give the sequencer some time to service
+ * any active selections.
+ */
+ ahd_delay(500);
+
ahd_intr(ahd);
ahd_pause(ahd);
- ahd_clear_critical_section(ahd);
intstat = ahd_inb(ahd, INTSTAT);
- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
- ahd_outb(ahd, SCSISEQ0,
- ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
- /*
- * In the non-packetized case, the sequencer (for Rev A),
- * relies on ENSELO remaining set after SELDO. The hardware
- * auto-clears ENSELO in the packetized case.
- */
- waiting_scb = ahd_lookup_scb(ahd,
- ahd_inw(ahd, WAITING_TID_HEAD));
- if (waiting_scb != NULL
- && (waiting_scb->flags & SCB_PACKETIZED) == 0
- && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)
- ahd_outb(ahd, SCSISEQ0,
- ahd_inb(ahd, SCSISEQ0) | ENSELO);
+ if ((intstat & INT_PEND) == 0) {
+ ahd_clear_critical_section(ahd);
+ intstat = ahd_inb(ahd, INTSTAT);
+ }
} while (--maxloops
&& (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
@@ -6973,17 +7032,8 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
printf("Infinite interrupt loop, INTSTAT = %x",
ahd_inb(ahd, INTSTAT));
}
- qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
- if (qfreeze_cnt == 0) {
- printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",
- ahd_name(ahd));
- } else {
- qfreeze_cnt--;
- }
- ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
- if (qfreeze_cnt == 0)
- ahd_outb(ahd, SEQ_FLAGS2,
- ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
+ ahd->qfreeze_cnt++;
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
ahd_flush_qoutfifo(ahd);
@@ -7155,10 +7205,7 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
uint32_t busaddr;
busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
} else {
prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
ahd_sync_scb(ahd, prev_scb,
@@ -7265,10 +7312,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
*/
ahd->qinfifonext = qinstart;
busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
while (qinpos != qintail) {
scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
@@ -7330,6 +7374,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
* appropriate, traverse the SCBs of each "their id"
* looking for matches.
*/
+ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
savedscbptr = ahd_get_scbptr(ahd);
tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
tid_prev = SCB_LIST_NULL;
@@ -7399,7 +7444,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
u_int prev;
int found;
- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
found = 0;
prev = SCB_LIST_NULL;
next = *list_head;
@@ -7466,7 +7511,7 @@ static void
ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
u_int tid_cur, u_int tid_next)
{
- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
if (SCBID_IS_NULL(tid_cur)) {
@@ -7506,7 +7551,7 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
{
u_int tail_offset;
- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
if (!SCBID_IS_NULL(prev)) {
ahd_set_scbptr(ahd, prev);
ahd_outw(ahd, SCB_NEXT, next);
@@ -7739,7 +7784,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
*/
ahd_clear_msg_state(ahd);
ahd_outb(ahd, SIMODE1,
- ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
+ ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
if (initiate_reset)
ahd_reset_current_bus(ahd);
@@ -7910,30 +7955,35 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
void
ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
{
- struct hardware_scb *hscb;
- u_int qfreeze_cnt;
+ struct hardware_scb *hscb;
+ int paused;
/*
* The sequencer freezes its select-out queue
* anytime a SCSI status error occurs. We must
- * handle the error and decrement the QFREEZE count
- * to allow the sequencer to continue.
+ * handle the error and increment our qfreeze count
+ * to allow the sequencer to continue. We don't
+ * bother clearing critical sections here since all
+ * operations are on data structures that the sequencer
+ * is not touching once the queue is frozen.
*/
hscb = scb->hscb;
+ if (ahd_is_paused(ahd)) {
+ paused = 1;
+ } else {
+ paused = 0;
+ ahd_pause(ahd);
+ }
+
/* Freeze the queue until the client sees the error. */
ahd_freeze_devq(ahd, scb);
ahd_freeze_scb(scb);
- qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
- if (qfreeze_cnt == 0) {
- printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd));
- } else {
- qfreeze_cnt--;
- ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
- }
- if (qfreeze_cnt == 0)
- ahd_outb(ahd, SEQ_FLAGS2,
- ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
+ ahd->qfreeze_cnt++;
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
+
+ if (paused == 0)
+ ahd_unpause(ahd);
/* Don't want to clobber the original sense code */
if ((scb->flags & SCB_SENSE) != 0) {
@@ -8317,8 +8367,7 @@ ahd_dumpseq(struct ahd_softc* ahd)
max_prog = 2048;
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
- ahd_outb(ahd, PRGMCNT, 0);
- ahd_outb(ahd, PRGMCNT+1, 0);
+ ahd_outw(ahd, PRGMCNT, 0);
for (i = 0; i < max_prog; i++) {
uint8_t ins_bytes[4];
@@ -8347,13 +8396,14 @@ ahd_loadseq(struct ahd_softc *ahd)
u_int sg_prefetch_cnt_limit;
u_int sg_prefetch_align;
u_int sg_size;
+ u_int cacheline_mask;
uint8_t download_consts[DOWNLOAD_CONST_COUNT];
if (bootverbose)
printf("%s: Downloading Sequencer Program...",
ahd_name(ahd));
-#if DOWNLOAD_CONST_COUNT != 7
+#if DOWNLOAD_CONST_COUNT != 8
#error "Download Const Mismatch"
#endif
/*
@@ -8389,6 +8439,9 @@ ahd_loadseq(struct ahd_softc *ahd)
/* Round down to the nearest power of 2. */
while (powerof2(sg_prefetch_align) == 0)
sg_prefetch_align--;
+
+ cacheline_mask = sg_prefetch_align - 1;
+
/*
* If the cacheline boundary is greater than half our prefetch RAM
* we risk not being able to fetch even a single complete S/G
@@ -8429,12 +8482,12 @@ ahd_loadseq(struct ahd_softc *ahd)
download_consts[PKT_OVERRUN_BUFOFFSET] =
(ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
+ download_consts[CACHELINE_MASK] = cacheline_mask;
cur_patch = patches;
downloaded = 0;
skip_addr = 0;
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
- ahd_outb(ahd, PRGMCNT, 0);
- ahd_outb(ahd, PRGMCNT+1, 0);
+ ahd_outw(ahd, PRGMCNT, 0);
for (i = 0; i < sizeof(seqprog)/4; i++) {
if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
@@ -8727,7 +8780,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
"%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
ahd_name(ahd),
- ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8),
+ ahd_inw(ahd, CURADDR),
ahd_build_mode_state(ahd, ahd->saved_src_mode,
ahd->saved_dst_mode));
if (paused)
@@ -8843,6 +8896,15 @@ ahd_dump_card_state(struct ahd_softc *ahd)
scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
}
printf("\n");
+ printf("Sequencer On QFreeze and Complete list: ");
+ scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+ i = 0;
+ while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
+ ahd_set_scbptr(ahd, scb_index);
+ printf("%d ", scb_index);
+ scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+ }
+ printf("\n");
ahd_set_scbptr(ahd, saved_scb_index);
dffstat = ahd_inb(ahd, DFFSTAT);
for (i = 0; i < 2; i++) {
@@ -9077,7 +9139,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd)
{
int cnt;
- cnt = 20;
+ cnt = 5000;
while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
ahd_delay(5);
@@ -9423,13 +9485,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
if ((ahd->features & AHD_MULTI_TID) != 0) {
u_int targid_mask;
- targid_mask = ahd_inb(ahd, TARGID)
- | (ahd_inb(ahd, TARGID + 1) << 8);
-
+ targid_mask = ahd_inw(ahd, TARGID);
targid_mask |= target_mask;
- ahd_outb(ahd, TARGID, targid_mask);
- ahd_outb(ahd, TARGID+1, (targid_mask >> 8));
-
+ ahd_outw(ahd, TARGID, targid_mask);
ahd_update_scsiid(ahd, targid_mask);
} else {
u_int our_id;
@@ -9543,14 +9601,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
if (ahd->features & AHD_MULTI_TID) {
u_int targid_mask;
- targid_mask = ahd_inb(ahd, TARGID)
- | (ahd_inb(ahd, TARGID + 1)
- << 8);
-
+ targid_mask = ahd_inw(ahd, TARGID);
targid_mask &= ~target_mask;
- ahd_outb(ahd, TARGID, targid_mask);
- ahd_outb(ahd, TARGID+1,
- (targid_mask >> 8));
+ ahd_outw(ahd, TARGID, targid_mask);
ahd_update_scsiid(ahd, targid_mask);
}
}
@@ -9651,7 +9704,7 @@ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
cmd->cmd_valid = 0;
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap,
+ ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
sizeof(struct target_cmd),
BUS_DMASYNC_PREREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index d80bc5161fb1..91c4f7f484b1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.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/aic79xx_inline.h#51 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $
*
* $FreeBSD$
*/
@@ -522,12 +522,21 @@ do { \
static __inline uint16_t
ahd_inw(struct ahd_softc *ahd, u_int port)
{
+ /*
+ * Read high byte first as some registers increment
+ * or have other side effects when the low byte is
+ * read.
+ */
return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
}
static __inline void
ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
{
+ /*
+ * Write low byte first to accomodate registers
+ * such as PRGMCNT where the order maters.
+ */
ahd_outb(ahd, port, value & 0xFF);
ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
}
@@ -684,7 +693,7 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
* Razor #528
*/
value = ahd_inb(ahd, offset);
- if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)
+ if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
ahd_inb(ahd, MODE_PTR);
return (value);
}
@@ -727,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
static __inline void
ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
{
- struct hardware_scb *q_hscb;
+ struct hardware_scb *q_hscb;
+ struct map_node *q_hscb_map;
uint32_t saved_hscb_busaddr;
/*
@@ -743,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
* locate the correct SCB by SCB_TAG.
*/
q_hscb = ahd->next_queued_hscb;
+ q_hscb_map = ahd->next_queued_hscb_map;
saved_hscb_busaddr = q_hscb->hscb_busaddr;
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
q_hscb->hscb_busaddr = saved_hscb_busaddr;
@@ -750,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
/* Now swap HSCB pointers. */
ahd->next_queued_hscb = scb->hscb;
+ ahd->next_queued_hscb_map = scb->hscb_map;
scb->hscb = q_hscb;
+ scb->hscb_map = q_hscb_map;
/* Now define the mapping from tag to SCB in the scbindex */
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
@@ -824,8 +837,9 @@ static __inline int ahd_intr(struct ahd_softc *ahd);
static __inline void
ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
{
- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
- /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op);
+ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+ /*offset*/0,
+ /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
}
static __inline void
@@ -834,7 +848,7 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap,
+ ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, 0),
sizeof(struct target_cmd) * AHD_TMODE_CMDS,
op);
@@ -854,17 +868,17 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
u_int retval;
retval = 0;
- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
- /*offset*/ahd->qoutfifonext, /*len*/2,
- BUS_DMASYNC_POSTREAD);
- if ((ahd->qoutfifo[ahd->qoutfifonext]
- & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)
+ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+ /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
+ /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
+ if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
+ == ahd->qoutfifonext_valid_tag)
retval |= AHD_RUN_QOUTFIFO;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0
&& (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap,
+ ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
/*len*/sizeof(struct target_cmd),
BUS_DMASYNC_POSTREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 1c8f872e2dd4..2567e29960bd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
if ((tstate->auto_negotiate & mask) != 0) {
scb->flags |= SCB_AUTO_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE;
+ } else if (cmd->cmnd[0] == INQUIRY
+ && (tinfo->curr.offset != 0
+ || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT
+ || tinfo->curr.ppr_options != 0)
+ && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {
+ /*
+ * The SCSI spec requires inquiry
+ * commands to complete without
+ * reporting unit attention conditions.
+ * Because of this, an inquiry command
+ * that occurs just after a device is
+ * reset will result in a data phase
+ * with mismatched negotiated rates.
+ * The core already forces a renegotiation
+ * for reset events that are visible to
+ * our controller or that we initiate,
+ * but a third party device reset or a
+ * hot-plug insertion can still cause this
+ * issue. Therefore, we force a re-negotiation
+ * for every inquiry command unless we
+ * are async.
+ */
+ scb->flags |= SCB_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
}
if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
@@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int paused;
int wait;
int disconnected;
+ int found;
ahd_mode_state saved_modes;
unsigned long flags;
@@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
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) {
+ if (disconnected && ((last_phase != P_BUSFREE) ||
+ (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
struct scb *bus_scb;
bus_scb = ahd_lookup_scb(ahd, active_scbptr);
@@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* 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
+ if (SCB_GET_TAG(pending_scb) == active_scbptr
|| (flag == SCB_DEVICE_RESET
- && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) {
+ && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
/*
* 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;
+ pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
ahd_outb(ahd, MSG_OUT, HOST_MSG);
ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
- scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
+ scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n");
wait = TRUE;
+ } else if (last_phase != P_BUSFREE
+ && ahd_inb(ahd, SCSIPHASE) == 0) {
+ /*
+ * SCB is not identified, there
+ * is no pending REQ, and the sequencer
+ * has not seen a busfree. Looks like
+ * a stuck connection waiting to
+ * go busfree. Reset the bus.
+ */
+ found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
+ /*Initiate Reset*/TRUE);
+ printf("%s: Issued Channel %c Bus Reset. "
+ "%d SCBs aborted\n", ahd_name(ahd),
+ cmd->device->channel + 'A', found);
} 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;
+ pending_scb->flags |= SCB_RECOVERY_SCB|flag;
ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0;
@@ -2296,16 +2335,17 @@ done:
timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout;
add_timer(&timer);
- printf("Recovery code sleeping\n");
+ printf("%s: Recovery code sleeping\n", ahd_name(ahd));
down(&ahd->platform_data->eh_sem);
- printf("Recovery code awake\n");
+ printf("%s: Recovery code awake\n", ahd_name(ahd));
ret = del_timer_sync(&timer);
if (ret == 0) {
- printf("Timer Expired\n");
+ printf("%s: Timer Expired (active %d)\n",
+ ahd_name(ahd), dev->active);
retval = FAILED;
}
}
- ahd_unlock(ahd, &flags);
+ ahd_unlock(ahd, &flags);
return (retval);
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index bc44222d6cc3..cb74fccc8100 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -252,7 +252,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#define AIC79XX_DRIVER_VERSION "1.3.11"
+#define AIC79XX_DRIVER_VERSION "3.0"
/*************************** Device Data Structures ***************************/
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 2131db60018a..196a6344b037 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,9 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $
*/
#ifdef __linux__
@@ -114,6 +112,13 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
"Adaptec 29320ALP Ultra320 SCSI adapter",
ahd_aic7901_setup
},
+ /* aic7901A based controllers */
+ {
+ ID_AHA_29320LP,
+ ID_ALL_MASK,
+ "Adaptec 29320LP Ultra320 SCSI adapter",
+ ahd_aic7901A_setup
+ },
/* aic7902 based controllers */
{
ID_AHA_29320,
@@ -128,12 +133,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
ahd_aic7902_setup
},
{
- ID_AHA_29320LP,
- ID_ALL_MASK,
- "Adaptec 29320LP Ultra320 SCSI adapter",
- ahd_aic7901A_setup
- },
- {
ID_AHA_39320,
ID_ALL_MASK,
"Adaptec 39320 Ultra320 SCSI adapter",
@@ -146,6 +145,12 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
ahd_aic7902_setup
},
{
+ ID_AHA_39320_B_DELL,
+ ID_ALL_MASK,
+ "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",
+ ahd_aic7902_setup
+ },
+ {
ID_AHA_39320A,
ID_ALL_MASK,
"Adaptec 39320A Ultra320 SCSI adapter",
@@ -668,6 +673,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
* Now set the termination based on what we found.
*/
sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
+ ahd->flags &= ~AHD_TERM_ENB_A;
if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
ahd->flags |= AHD_TERM_ENB_A;
sxfrctl1 |= STPWEN;
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h
index b5cfeabdfecf..da45153668c7 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.h
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.h
@@ -53,14 +53,15 @@
#define ID_AHA_29320ALP 0x8017900500449005ull
#define ID_AIC7901A 0x801E9005FFFF9005ull
-#define ID_AHA_29320 0x8012900500429005ull
-#define ID_AHA_29320B 0x8013900500439005ull
#define ID_AHA_29320LP 0x8014900500449005ull
#define ID_AIC7902 0x801F9005FFFF9005ull
#define ID_AIC7902_B 0x801D9005FFFF9005ull
#define ID_AHA_39320 0x8010900500409005ull
+#define ID_AHA_29320 0x8012900500429005ull
+#define ID_AHA_29320B 0x8013900500439005ull
#define ID_AHA_39320_B 0x8015900500409005ull
+#define ID_AHA_39320_B_DELL 0x8015900501681028ull
#define ID_AHA_39320A 0x8016900500409005ull
#define ID_AHA_39320D 0x8011900500419005ull
#define ID_AHA_39320D_B 0x801C900500419005ull
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index c01ac39090d9..8763b158856b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
*/
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahd_reg_parse_entry {
@@ -83,17 +83,17 @@ ahd_reg_print_t ahd_hs_mailbox_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrseqintstat_print;
+ahd_reg_print_t ahd_seqintstat_print;
#else
-#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
+#define ahd_seqintstat_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_seqintstat_print;
+ahd_reg_print_t ahd_clrseqintstat_print;
#else
-#define ahd_seqintstat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
+#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -412,17 +412,17 @@ ahd_reg_print_t ahd_sxfrctl0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_businitid_print;
+ahd_reg_print_t ahd_dlcount_print;
#else
-#define ahd_businitid_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
+#define ahd_dlcount_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dlcount_print;
+ahd_reg_print_t ahd_businitid_print;
#else
-#define ahd_dlcount_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
+#define ahd_businitid_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -517,13 +517,6 @@ ahd_reg_print_t ahd_selid_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sblkctl_print;
-#else
-#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_optionmode_print;
#else
#define ahd_optionmode_print(regvalue, cur_col, wrap) \
@@ -531,10 +524,10 @@ ahd_reg_print_t ahd_optionmode_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sstat0_print;
+ahd_reg_print_t ahd_sblkctl_print;
#else
-#define ahd_sstat0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
+#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -545,6 +538,13 @@ ahd_reg_print_t ahd_clrsint0_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sstat0_print;
+#else
+#define ahd_sstat0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_simode0_print;
#else
#define ahd_simode0_print(regvalue, cur_col, wrap) \
@@ -573,17 +573,17 @@ ahd_reg_print_t ahd_sstat2_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint2_print;
+ahd_reg_print_t ahd_simode2_print;
#else
-#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
+#define ahd_simode2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_simode2_print;
+ahd_reg_print_t ahd_clrsint2_print;
#else
-#define ahd_simode2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
+#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -685,13 +685,6 @@ ahd_reg_print_t ahd_clrsint3_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqomode0_print;
-#else
-#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqostat0_print;
#else
#define ahd_lqostat0_print(regvalue, cur_col, wrap) \
@@ -706,6 +699,20 @@ ahd_reg_print_t ahd_clrlqoint0_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_lqomode0_print;
+#else
+#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_lqomode1_print;
+#else
+#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqostat1_print;
#else
#define ahd_lqostat1_print(regvalue, cur_col, wrap) \
@@ -720,13 +727,6 @@ ahd_reg_print_t ahd_clrlqoint1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqomode1_print;
-#else
-#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqostat2_print;
#else
#define ahd_lqostat2_print(regvalue, cur_col, wrap) \
@@ -909,17 +909,17 @@ ahd_reg_print_t ahd_annexcol_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scschkn_print;
+ahd_reg_print_t ahd_annexdat_print;
#else
-#define ahd_scschkn_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
+#define ahd_annexdat_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_annexdat_print;
+ahd_reg_print_t ahd_scschkn_print;
#else
-#define ahd_annexdat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap)
+#define ahd_scschkn_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1000,17 +1000,17 @@ ahd_reg_print_t ahd_pll400ctl1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll400cnt0_print;
+ahd_reg_print_t ahd_unfairness_print;
#else
-#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
+#define ahd_unfairness_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_unfairness_print;
+ahd_reg_print_t ahd_pll400cnt0_print;
#else
-#define ahd_unfairness_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
+#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1056,13 +1056,6 @@ ahd_reg_print_t ahd_hodmaen_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghaddr_print;
-#else
-#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scbhaddr_print;
#else
#define ahd_scbhaddr_print(regvalue, cur_col, wrap) \
@@ -1070,10 +1063,10 @@ ahd_reg_print_t ahd_scbhaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghcnt_print;
+ahd_reg_print_t ahd_sghaddr_print;
#else
-#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1084,6 +1077,13 @@ ahd_reg_print_t ahd_scbhcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sghcnt_print;
+#else
+#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dff_thrsh_print;
#else
#define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \
@@ -1154,13 +1154,6 @@ ahd_reg_print_t ahd_nsenable_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg1_print;
-#else
-#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmcrxmsg1_print;
#else
#define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \
@@ -1168,17 +1161,17 @@ ahd_reg_print_t ahd_cmcrxmsg1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg2_print;
+ahd_reg_print_t ahd_dchrxmsg1_print;
#else
-#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
+#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg2_print;
+ahd_reg_print_t ahd_dchrxmsg2_print;
#else
-#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
+#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1196,6 +1189,13 @@ ahd_reg_print_t ahd_ost_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ovlyrxmsg2_print;
+#else
+#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dchrxmsg3_print;
#else
#define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1203,6 +1203,13 @@ ahd_reg_print_t ahd_dchrxmsg3_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ovlyrxmsg3_print;
+#else
+#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmcrxmsg3_print;
#else
#define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1217,13 +1224,6 @@ ahd_reg_print_t ahd_pcixctl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg3_print;
-#else
-#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_ovlyseqbcnt_print;
#else
#define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1231,13 +1231,6 @@ ahd_reg_print_t ahd_ovlyseqbcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcseqbcnt_print;
-#else
-#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dchseqbcnt_print;
#else
#define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1245,17 +1238,17 @@ ahd_reg_print_t ahd_dchseqbcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcspltstat0_print;
+ahd_reg_print_t ahd_cmcseqbcnt_print;
#else
-#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
+#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyspltstat0_print;
+ahd_reg_print_t ahd_cmcspltstat0_print;
#else
-#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
+#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1266,10 +1259,10 @@ ahd_reg_print_t ahd_dchspltstat0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchspltstat1_print;
+ahd_reg_print_t ahd_ovlyspltstat0_print;
#else
-#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1287,6 +1280,13 @@ ahd_reg_print_t ahd_ovlyspltstat1_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dchspltstat1_print;
+#else
+#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_sgrxmsg0_print;
#else
#define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \
@@ -1378,17 +1378,17 @@ ahd_reg_print_t ahd_sgspltstat0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sfunct_print;
+ahd_reg_print_t ahd_sgspltstat1_print;
#else
-#define ahd_sfunct_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
+#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgspltstat1_print;
+ahd_reg_print_t ahd_sfunct_print;
#else
-#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
+#define ahd_sfunct_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1504,17 +1504,17 @@ ahd_reg_print_t ahd_ccsgaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbaddr_print;
+ahd_reg_print_t ahd_ccscbadr_bk_print;
#else
-#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
+#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbadr_bk_print;
+ahd_reg_print_t ahd_ccscbaddr_print;
#else
-#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
+#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1525,17 +1525,17 @@ ahd_reg_print_t ahd_cmc_rambist_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccsgctl_print;
+ahd_reg_print_t ahd_ccscbctl_print;
#else
-#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
+#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbctl_print;
+ahd_reg_print_t ahd_ccsgctl_print;
#else
-#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap)
+#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1707,13 +1707,6 @@ ahd_reg_print_t ahd_wrtbiascalc_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfptrs_print;
-#else
-#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_rcvrbiascalc_print;
#else
#define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \
@@ -1721,10 +1714,10 @@ ahd_reg_print_t ahd_rcvrbiascalc_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfbkptr_print;
+ahd_reg_print_t ahd_dfptrs_print;
#else
-#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1735,6 +1728,13 @@ ahd_reg_print_t ahd_skewcalc_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dfbkptr_print;
+#else
+#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dfdbctl_print;
#else
#define ahd_dfdbctl_print(regvalue, cur_col, wrap) \
@@ -1826,17 +1826,17 @@ ahd_reg_print_t ahd_dindex_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr1_print;
+ahd_reg_print_t ahd_brkaddr0_print;
#else
-#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
+#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr0_print;
+ahd_reg_print_t ahd_brkaddr1_print;
#else
-#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
+#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1889,13 +1889,6 @@ ahd_reg_print_t ahd_stack_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_curaddr_print;
-#else
-#define ahd_curaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_intvec1_addr_print;
#else
#define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \
@@ -1903,10 +1896,10 @@ ahd_reg_print_t ahd_intvec1_addr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_intvec2_addr_print;
+ahd_reg_print_t ahd_curaddr_print;
#else
-#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
+#define ahd_curaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1917,6 +1910,13 @@ ahd_reg_print_t ahd_lastaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_intvec2_addr_print;
+#else
+#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_longjmp_addr_print;
#else
#define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \
@@ -1994,192 +1994,213 @@ ahd_reg_print_t ahd_complete_dma_scb_head_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_complete_dma_scb_tail_print;
+#else
+#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_complete_on_qfreeze_head_print;
+#else
+#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_qfreeze_count_print;
#else
#define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_kernel_qfreeze_count_print;
+#else
+#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_saved_mode_print;
#else
#define ahd_saved_mode_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_msg_out_print;
#else
#define ahd_msg_out_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dmaparams_print;
#else
#define ahd_dmaparams_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seq_flags_print;
#else
#define ahd_seq_flags_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_saved_scsiid_print;
#else
#define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_saved_lun_print;
#else
#define ahd_saved_lun_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lastphase_print;
#else
#define ahd_lastphase_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print;
#else
#define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_shared_data_addr_print;
+ahd_reg_print_t ahd_kernel_tqinpos_print;
#else
-#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap)
+#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_qoutfifo_next_addr_print;
+ahd_reg_print_t ahd_tqinpos_print;
#else
-#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap)
+#define ahd_tqinpos_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_kernel_tqinpos_print;
+ahd_reg_print_t ahd_shared_data_addr_print;
#else
-#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap)
+#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_tqinpos_print;
+ahd_reg_print_t ahd_qoutfifo_next_addr_print;
#else
-#define ahd_tqinpos_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap)
+#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_arg_1_print;
#else
#define ahd_arg_1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_arg_2_print;
#else
#define ahd_arg_2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_last_msg_print;
#else
#define ahd_last_msg_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scsiseq_template_print;
#else
#define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_initiator_tag_print;
#else
#define ahd_initiator_tag_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seq_flags2_print;
#else
#define ahd_seq_flags2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_allocfifo_scbptr_print;
#else
#define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_timer_print;
#else
#define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_maxcmds_print;
#else
#define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_mincmds_print;
#else
#define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmds_pending_print;
#else
#define ahd_cmds_pending_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_cmdcount_print;
#else
#define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_local_hs_mailbox_print;
#else
#define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmdsize_table_print;
#else
#define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -2434,13 +2455,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define HOST_TQINPOS 0x80
#define ENINT_COALESCE 0x40
-#define CLRSEQINTSTAT 0x0c
-#define CLRSEQ_SWTMRTO 0x10
-#define CLRSEQ_SEQINT 0x08
-#define CLRSEQ_SCSIINT 0x04
-#define CLRSEQ_PCIINT 0x02
-#define CLRSEQ_SPLTINT 0x01
-
#define SEQINTSTAT 0x0c
#define SEQ_SWTMRTO 0x10
#define SEQ_SEQINT 0x08
@@ -2448,6 +2462,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SEQ_PCIINT 0x02
#define SEQ_SPLTINT 0x01
+#define CLRSEQINTSTAT 0x0c
+#define CLRSEQ_SWTMRTO 0x10
+#define CLRSEQ_SEQINT 0x08
+#define CLRSEQ_SCSIINT 0x04
+#define CLRSEQ_PCIINT 0x02
+#define CLRSEQ_SPLTINT 0x01
+
#define SWTIMER 0x0e
#define SNSCB_QOFF 0x10
@@ -2623,10 +2644,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define BIOSCANCELEN 0x10
#define SPIOEN 0x08
-#define BUSINITID 0x3c
-
#define DLCOUNT 0x3c
+#define BUSINITID 0x3c
+
#define SXFRCTL1 0x3d
#define BITBUCKET 0x80
#define ENSACHK 0x40
@@ -2693,13 +2714,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SELID_MASK 0xf0
#define ONEBIT 0x08
-#define SBLKCTL 0x4a
-#define DIAGLEDEN 0x80
-#define DIAGLEDON 0x40
-#define ENAB40 0x08
-#define ENAB20 0x04
-#define SELWIDE 0x02
-
#define OPTIONMODE 0x4a
#define OPTIONMODE_DEFAULTS 0x02
#define BIOSCANCTL 0x80
@@ -2709,15 +2723,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENDGFORMCHK 0x04
#define AUTO_MSGOUT_DE 0x02
-#define SSTAT0 0x4b
-#define TARGET 0x80
-#define SELDO 0x40
-#define SELDI 0x20
-#define SELINGO 0x10
-#define IOERR 0x08
-#define OVERRUN 0x04
-#define SPIORDY 0x02
-#define ARBDO 0x01
+#define SBLKCTL 0x4a
+#define DIAGLEDEN 0x80
+#define DIAGLEDON 0x40
+#define ENAB40 0x08
+#define ENAB20 0x04
+#define SELWIDE 0x02
#define CLRSINT0 0x4b
#define CLRSELDO 0x40
@@ -2728,6 +2739,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRSPIORDY 0x02
#define CLRARBDO 0x01
+#define SSTAT0 0x4b
+#define TARGET 0x80
+#define SELDO 0x40
+#define SELDI 0x20
+#define SELINGO 0x10
+#define IOERR 0x08
+#define OVERRUN 0x04
+#define SPIORDY 0x02
+#define ARBDO 0x01
+
#define SIMODE0 0x4b
#define ENSELDO 0x40
#define ENSELDI 0x20
@@ -2768,17 +2789,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define BUSFREE_DFF0 0x80
#define BUSFREE_LQO 0x40
+#define SIMODE2 0x4d
+#define ENWIDE_RES 0x04
+#define ENSDONE 0x02
+#define ENDMADONE 0x01
+
#define CLRSINT2 0x4d
#define CLRNONPACKREQ 0x20
#define CLRWIDE_RES 0x04
#define CLRSDONE 0x02
#define CLRDMADONE 0x01
-#define SIMODE2 0x4d
-#define ENWIDE_RES 0x04
-#define ENSDONE 0x02
-#define ENDMADONE 0x01
-
#define PERRDIAG 0x4e
#define HIZERO 0x80
#define HIPERR 0x40
@@ -2871,13 +2892,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRNTRAMPERR 0x02
#define CLROSRAMPERR 0x01
-#define LQOMODE0 0x54
-#define ENLQOTARGSCBPERR 0x10
-#define ENLQOSTOPT2 0x08
-#define ENLQOATNLQ 0x04
-#define ENLQOATNPKT 0x02
-#define ENLQOTCRC 0x01
-
#define LQOSTAT0 0x54
#define LQOTARGSCBPERR 0x10
#define LQOSTOPT2 0x08
@@ -2892,6 +2906,20 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRLQOATNPKT 0x02
#define CLRLQOTCRC 0x01
+#define LQOMODE0 0x54
+#define ENLQOTARGSCBPERR 0x10
+#define ENLQOSTOPT2 0x08
+#define ENLQOATNLQ 0x04
+#define ENLQOATNPKT 0x02
+#define ENLQOTCRC 0x01
+
+#define LQOMODE1 0x55
+#define ENLQOINITSCBPERR 0x10
+#define ENLQOSTOPI2 0x08
+#define ENLQOBADQAS 0x04
+#define ENLQOBUSFREE 0x02
+#define ENLQOPHACHGINPKT 0x01
+
#define LQOSTAT1 0x55
#define LQOINITSCBPERR 0x10
#define LQOSTOPI2 0x08
@@ -2906,13 +2934,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRLQOBUSFREE 0x02
#define CLRLQOPHACHGINPKT 0x01
-#define LQOMODE1 0x55
-#define ENLQOINITSCBPERR 0x10
-#define ENLQOSTOPI2 0x08
-#define ENLQOBADQAS 0x04
-#define ENLQOBUSFREE 0x02
-#define ENLQOPHACHGINPKT 0x01
-
#define LQOSTAT2 0x56
#define LQOPKT 0xe0
#define LQOWAITFIFO 0x10
@@ -3028,6 +3049,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ANNEXCOL 0x65
+#define ANNEXDAT 0x66
+
#define SCSCHKN 0x66
#define STSELSKIDDIS 0x40
#define CURRFIFODEF 0x20
@@ -3037,8 +3060,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SHVALIDSTDIS 0x02
#define LSTSGCLRDIS 0x01
-#define ANNEXDAT 0x66
-
#define IOWNID 0x67
#define PLL960CTL0 0x68
@@ -3071,10 +3092,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define PLL_CNTCLR 0x40
#define PLL_RST 0x01
-#define PLL400CNT0 0x6e
-
#define UNFAIRNESS 0x6e
+#define PLL400CNT0 0x6e
+
#define HADDR 0x70
#define PLLDELAY 0x70
@@ -3088,14 +3109,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define HODMAEN 0x7a
-#define SGHADDR 0x7c
-
#define SCBHADDR 0x7c
-#define SGHCNT 0x84
+#define SGHADDR 0x7c
#define SCBHCNT 0x84
+#define SGHCNT 0x84
+
#define DFF_THRSH 0x88
#define WR_DFTHRSH 0x70
#define RD_DFTHRSH 0x07
@@ -3113,8 +3134,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define RD_DFTHRSH_63 0x03
#define RD_DFTHRSH_50 0x02
#define RD_DFTHRSH_25 0x01
-#define WR_DFTHRSH_MIN 0x00
#define RD_DFTHRSH_MIN 0x00
+#define WR_DFTHRSH_MIN 0x00
#define ROMADDR 0x8a
@@ -3150,20 +3171,22 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DCH1NSEN 0x02
#define DCH0NSEN 0x01
-#define DCHRXMSG1 0x91
-
#define CMCRXMSG1 0x91
-#define DCHRXMSG2 0x92
+#define DCHRXMSG1 0x91
-#define OVLYRXMSG2 0x92
+#define DCHRXMSG2 0x92
#define CMCRXMSG2 0x92
#define OST 0x92
+#define OVLYRXMSG2 0x92
+
#define DCHRXMSG3 0x93
+#define OVLYRXMSG3 0x93
+
#define CMCRXMSG3 0x93
#define PCIXCTL 0x93
@@ -3175,26 +3198,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define TSCSERREN 0x02
#define CMPABCDIS 0x01
-#define OVLYRXMSG3 0x93
-
#define OVLYSEQBCNT 0x94
-#define CMCSEQBCNT 0x94
-
#define DCHSEQBCNT 0x94
-#define CMCSPLTSTAT0 0x96
+#define CMCSEQBCNT 0x94
-#define OVLYSPLTSTAT0 0x96
+#define CMCSPLTSTAT0 0x96
#define DCHSPLTSTAT0 0x96
-#define DCHSPLTSTAT1 0x97
+#define OVLYSPLTSTAT0 0x96
#define CMCSPLTSTAT1 0x97
#define OVLYSPLTSTAT1 0x97
+#define DCHSPLTSTAT1 0x97
+
#define SGRXMSG0 0x98
#define CDNUM 0xf8
#define CFNUM 0x07
@@ -3244,13 +3265,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define RXSCEMSG 0x02
#define RXSPLTRSP 0x01
+#define SGSPLTSTAT1 0x9f
+#define RXDATABUCKET 0x01
+
#define SFUNCT 0x9f
#define TEST_GROUP 0xf0
#define TEST_NUM 0x0f
-#define SGSPLTSTAT1 0x9f
-#define RXDATABUCKET 0x01
-
#define DF0PCISTAT 0xa0
#define REG0 0xa0
@@ -3299,10 +3320,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CCSGADDR 0xac
-#define CCSCBADDR 0xac
-
#define CCSCBADR_BK 0xac
+#define CCSCBADDR 0xac
+
#define CMC_RAMBIST 0xad
#define SG_ELEMENT_SIZE 0x80
#define SCBRAMBIST_FAIL 0x40
@@ -3311,14 +3332,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CMC_BUFFER_BIST_FAIL 0x02
#define CMC_BUFFER_BIST_EN 0x01
-#define CCSGCTL 0xad
-#define CCSGEN 0x0c
-#define CCSGDONE 0x80
-#define SG_CACHE_AVAIL 0x10
-#define CCSGENACK 0x08
-#define SG_FETCH_REQ 0x02
-#define CCSGRESET 0x01
-
#define CCSCBCTL 0xad
#define CCSCBDONE 0x80
#define ARRDONE 0x40
@@ -3327,6 +3340,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CCSCBDIR 0x04
#define CCSCBRESET 0x01
+#define CCSGCTL 0xad
+#define CCSGEN 0x0c
+#define CCSGDONE 0x80
+#define SG_CACHE_AVAIL 0x10
+#define CCSGENACK 0x08
+#define SG_FETCH_REQ 0x02
+#define CCSGRESET 0x01
+
#define CCSGRAM 0xb0
#define FLEXADR 0xb0
@@ -3356,8 +3377,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SEEDAT 0xbc
#define SEECTL 0xbe
-#define SEEOP_EWEN 0x40
#define SEEOP_WALL 0x40
+#define SEEOP_EWEN 0x40
#define SEEOP_EWDS 0x40
#define SEEOPCODE 0x70
#define SEERST 0x02
@@ -3414,14 +3435,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define WRTBIASCALC 0xc7
-#define DFPTRS 0xc8
-
#define RCVRBIASCALC 0xc8
-#define DFBKPTR 0xc9
+#define DFPTRS 0xc8
#define SKEWCALC 0xc9
+#define DFBKPTR 0xc9
+
#define DFDBCTL 0xcb
#define DFF_CIO_WR_RDY 0x20
#define DFF_CIO_RD_RDY 0x10
@@ -3475,11 +3496,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DINDEX 0xe4
+#define BRKADDR0 0xe6
+
#define BRKADDR1 0xe6
#define BRKDIS 0x80
-#define BRKADDR0 0xe6
-
#define ALLONES 0xe8
#define ALLZEROS 0xea
@@ -3494,14 +3515,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define STACK 0xf2
-#define CURADDR 0xf4
-
#define INTVEC1_ADDR 0xf4
-#define INTVEC2_ADDR 0xf6
+#define CURADDR 0xf4
#define LASTADDR 0xf6
+#define INTVEC2_ADDR 0xf6
+
#define LONGJMP_ADDR 0xf8
#define ACCUM_SAVE 0xfa
@@ -3524,25 +3545,31 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define COMPLETE_DMA_SCB_HEAD 0x12c
-#define QFREEZE_COUNT 0x12e
+#define COMPLETE_DMA_SCB_TAIL 0x12e
+
+#define COMPLETE_ON_QFREEZE_HEAD 0x130
+
+#define QFREEZE_COUNT 0x132
-#define SAVED_MODE 0x130
+#define KERNEL_QFREEZE_COUNT 0x134
-#define MSG_OUT 0x131
+#define SAVED_MODE 0x136
-#define DMAPARAMS 0x132
+#define MSG_OUT 0x137
+
+#define DMAPARAMS 0x138
#define PRELOADEN 0x80
#define WIDEODD 0x40
#define SCSIEN 0x20
#define SDMAEN 0x10
#define SDMAENACK 0x10
-#define HDMAENACK 0x08
#define HDMAEN 0x08
+#define HDMAENACK 0x08
#define DIRECTION 0x04
#define FIFOFLUSH 0x02
#define FIFORESET 0x01
-#define SEQ_FLAGS 0x133
+#define SEQ_FLAGS 0x139
#define NOT_IDENTIFIED 0x80
#define NO_CDB_SENT 0x40
#define TARGET_CMD_IS_TAGGED 0x40
@@ -3553,11 +3580,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SPHASE_PENDING 0x02
#define NO_DISCONNECT 0x01
-#define SAVED_SCSIID 0x134
+#define SAVED_SCSIID 0x13a
-#define SAVED_LUN 0x135
+#define SAVED_LUN 0x13b
-#define LASTPHASE 0x136
+#define LASTPHASE 0x13c
#define PHASE_MASK 0xe0
#define CDI 0x80
#define IOI 0x40
@@ -3572,18 +3599,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define P_DATAOUT_DT 0x20
#define P_DATAOUT 0x00
-#define QOUTFIFO_ENTRY_VALID_TAG 0x137
+#define QOUTFIFO_ENTRY_VALID_TAG 0x13d
-#define SHARED_DATA_ADDR 0x138
+#define KERNEL_TQINPOS 0x13e
-#define QOUTFIFO_NEXT_ADDR 0x13c
+#define TQINPOS 0x13f
-#define KERNEL_TQINPOS 0x140
+#define SHARED_DATA_ADDR 0x140
-#define TQINPOS 0x141
+#define QOUTFIFO_NEXT_ADDR 0x144
-#define ARG_1 0x142
-#define RETURN_1 0x142
+#define ARG_1 0x148
+#define RETURN_1 0x148
#define SEND_MSG 0x80
#define SEND_SENSE 0x40
#define SEND_REJ 0x20
@@ -3593,12 +3620,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CONT_MSG_LOOP_READ 0x03
#define CONT_MSG_LOOP_TARG 0x02
-#define ARG_2 0x143
-#define RETURN_2 0x143
+#define ARG_2 0x149
+#define RETURN_2 0x149
-#define LAST_MSG 0x144
+#define LAST_MSG 0x14a
-#define SCSISEQ_TEMPLATE 0x145
+#define SCSISEQ_TEMPLATE 0x14b
#define MANUALCTL 0x40
#define ENSELI 0x20
#define ENRSELI 0x10
@@ -3606,27 +3633,27 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENAUTOATNP 0x02
#define ALTSTIM 0x01
-#define INITIATOR_TAG 0x146
+#define INITIATOR_TAG 0x14c
-#define SEQ_FLAGS2 0x147
+#define SEQ_FLAGS2 0x14d
#define SELECTOUT_QFROZEN 0x04
#define TARGET_MSG_PENDING 0x02
-#define ALLOCFIFO_SCBPTR 0x148
+#define ALLOCFIFO_SCBPTR 0x14e
-#define INT_COALESCING_TIMER 0x14a
+#define INT_COALESCING_TIMER 0x150
-#define INT_COALESCING_MAXCMDS 0x14c
+#define INT_COALESCING_MAXCMDS 0x152
-#define INT_COALESCING_MINCMDS 0x14d
+#define INT_COALESCING_MINCMDS 0x153
-#define CMDS_PENDING 0x14e
+#define CMDS_PENDING 0x154
-#define INT_COALESCING_CMDCOUNT 0x150
+#define INT_COALESCING_CMDCOUNT 0x156
-#define LOCAL_HS_MAILBOX 0x151
+#define LOCAL_HS_MAILBOX 0x157
-#define CMDSIZE_TABLE 0x152
+#define CMDSIZE_TABLE 0x158
#define SCB_BASE 0x180
@@ -3701,6 +3728,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_DISCONNECTED_LISTS 0x1b8
+#define AHD_TIMER_MAX_US 0x18ffe7
+#define AHD_TIMER_MAX_TICKS 0xffff
+#define AHD_SENSE_BUFSIZE 0x100
+#define BUS_8_BIT 0x00
+#define TARGET_CMD_CMPLT 0xfe
+#define SEEOP_WRAL_ADDR 0x40
+#define AHD_AMPLITUDE_DEF 0x07
+#define AHD_PRECOMP_CUTBACK_37 0x07
+#define AHD_PRECOMP_SHIFT 0x00
+#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04
#define AHD_TIMER_US_PER_TICK 0x19
#define SCB_TRANSFER_SIZE_FULL_LUN 0x38
#define STATUS_QUEUE_FULL 0x28
@@ -3724,28 +3761,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define B_CURRFIFO_0 0x02
#define LUNLEN_SINGLE_LEVEL_LUN 0x0f
#define NVRAM_SCB_OFFSET 0x2c
-#define AHD_TIMER_MAX_US 0x18ffe7
-#define AHD_TIMER_MAX_TICKS 0xffff
#define STATUS_PKT_SENSE 0xff
#define CMD_GROUP_CODE_SHIFT 0x05
-#define AHD_SENSE_BUFSIZE 0x100
#define MAX_OFFSET_PACED_BUG 0x7f
-#define BUS_8_BIT 0x00
#define STIMESEL_BUG_ADJ 0x08
#define STIMESEL_MIN 0x18
#define STIMESEL_SHIFT 0x03
#define CCSGRAM_MAXSEGS 0x10
#define INVALID_ADDR 0x80
-#define TARGET_CMD_CMPLT 0xfe
-#define SEEOP_WRAL_ADDR 0x40
#define SEEOP_ERAL_ADDR 0x80
-#define AHD_AMPLITUDE_DEF 0x07
#define AHD_SLEWRATE_DEF_REVB 0x08
-#define AHD_PRECOMP_CUTBACK_37 0x07
#define AHD_PRECOMP_CUTBACK_17 0x04
-#define AHD_PRECOMP_SHIFT 0x00
#define AHD_PRECOMP_MASK 0x07
-#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04
#define SRC_MODE_SHIFT 0x00
#define PKT_OVERRUN_BUFSIZE 0x200
#define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30
@@ -3761,6 +3788,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
/* Downloaded Constant Definitions */
+#define CACHELINE_MASK 0x07
#define SCB_TRANSFER_SIZE 0x06
#define PKT_OVERRUN_BUFOFFSET 0x05
#define SG_SIZEOF 0x04
@@ -3768,9 +3796,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SG_PREFETCH_ALIGN_MASK 0x02
#define SG_PREFETCH_CNT_LIMIT 0x01
#define SG_PREFETCH_CNT 0x00
-#define DOWNLOAD_CONST_COUNT 0x07
+#define DOWNLOAD_CONST_COUNT 0x08
/* Exported Labels */
-#define LABEL_seq_isr 0x269
-#define LABEL_timer_isr 0x265
+#define LABEL_seq_isr 0x285
+#define LABEL_timer_isr 0x281
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index 3098a757e3d7..a4137c985376 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_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/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $
*/
#include "aic79xx_osm.h"
@@ -172,21 +172,6 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0b, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
- { "CLRSEQ_SPLTINT", 0x01, 0x01 },
- { "CLRSEQ_PCIINT", 0x02, 0x02 },
- { "CLRSEQ_SCSIINT", 0x04, 0x04 },
- { "CLRSEQ_SEQINT", 0x08, 0x08 },
- { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
-};
-
-int
-ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
- 0x0c, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
{ "SEQ_SPLTINT", 0x01, 0x01 },
{ "SEQ_PCIINT", 0x02, 0x02 },
@@ -202,6 +187,21 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0c, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
+ { "CLRSEQ_SPLTINT", 0x01, 0x01 },
+ { "CLRSEQ_PCIINT", 0x02, 0x02 },
+ { "CLRSEQ_SCSIINT", 0x04, 0x04 },
+ { "CLRSEQ_SEQINT", 0x08, 0x08 },
+ { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
+};
+
+int
+ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
+ 0x0c, regvalue, cur_col, wrap));
+}
+
int
ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -670,16 +670,16 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "BUSINITID",
+ return (ahd_print_register(NULL, 0, "DLCOUNT",
0x3c, regvalue, cur_col, wrap));
}
int
-ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DLCOUNT",
+ return (ahd_print_register(NULL, 0, "BUSINITID",
0x3c, regvalue, cur_col, wrap));
}
@@ -859,21 +859,6 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x49, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
- { "SELWIDE", 0x02, 0x02 },
- { "ENAB20", 0x04, 0x04 },
- { "ENAB40", 0x08, 0x08 },
- { "DIAGLEDON", 0x40, 0x40 },
- { "DIAGLEDEN", 0x80, 0x80 }
-};
-
-int
-ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
- 0x4a, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
{ "AUTO_MSGOUT_DE", 0x02, 0x02 },
{ "ENDGFORMCHK", 0x04, 0x04 },
@@ -891,22 +876,19 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4a, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
- { "ARBDO", 0x01, 0x01 },
- { "SPIORDY", 0x02, 0x02 },
- { "OVERRUN", 0x04, 0x04 },
- { "IOERR", 0x08, 0x08 },
- { "SELINGO", 0x10, 0x10 },
- { "SELDI", 0x20, 0x20 },
- { "SELDO", 0x40, 0x40 },
- { "TARGET", 0x80, 0x80 }
+static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
+ { "SELWIDE", 0x02, 0x02 },
+ { "ENAB20", 0x04, 0x04 },
+ { "ENAB40", 0x08, 0x08 },
+ { "DIAGLEDON", 0x40, 0x40 },
+ { "DIAGLEDEN", 0x80, 0x80 }
};
int
-ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
- 0x4b, regvalue, cur_col, wrap));
+ return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
+ 0x4a, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
@@ -926,6 +908,24 @@ ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4b, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
+ { "ARBDO", 0x01, 0x01 },
+ { "SPIORDY", 0x02, 0x02 },
+ { "OVERRUN", 0x04, 0x04 },
+ { "IOERR", 0x08, 0x08 },
+ { "SELINGO", 0x10, 0x10 },
+ { "SELDI", 0x20, 0x20 },
+ { "SELDO", 0x40, 0x40 },
+ { "TARGET", 0x80, 0x80 }
+};
+
+int
+ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
+ 0x4b, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
{ "ENARBDO", 0x01, 0x01 },
{ "ENSPIORDY", 0x02, 0x02 },
@@ -998,30 +998,30 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4d, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
- { "CLRDMADONE", 0x01, 0x01 },
- { "CLRSDONE", 0x02, 0x02 },
- { "CLRWIDE_RES", 0x04, 0x04 },
- { "CLRNONPACKREQ", 0x20, 0x20 }
+static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
+ { "ENDMADONE", 0x01, 0x01 },
+ { "ENSDONE", 0x02, 0x02 },
+ { "ENWIDE_RES", 0x04, 0x04 }
};
int
-ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2",
+ return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
0x4d, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
- { "ENDMADONE", 0x01, 0x01 },
- { "ENSDONE", 0x02, 0x02 },
- { "ENWIDE_RES", 0x04, 0x04 }
+static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
+ { "CLRDMADONE", 0x01, 0x01 },
+ { "CLRSDONE", 0x02, 0x02 },
+ { "CLRWIDE_RES", 0x04, 0x04 },
+ { "CLRNONPACKREQ", 0x20, 0x20 }
};
int
-ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
+ return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2",
0x4d, regvalue, cur_col, wrap));
}
@@ -1220,21 +1220,6 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x53, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
- { "ENLQOTCRC", 0x01, 0x01 },
- { "ENLQOATNPKT", 0x02, 0x02 },
- { "ENLQOATNLQ", 0x04, 0x04 },
- { "ENLQOSTOPT2", 0x08, 0x08 },
- { "ENLQOTARGSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
- 0x54, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
{ "LQOTCRC", 0x01, 0x01 },
{ "LQOATNPKT", 0x02, 0x02 },
@@ -1265,6 +1250,36 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x54, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
+ { "ENLQOTCRC", 0x01, 0x01 },
+ { "ENLQOATNPKT", 0x02, 0x02 },
+ { "ENLQOATNLQ", 0x04, 0x04 },
+ { "ENLQOSTOPT2", 0x08, 0x08 },
+ { "ENLQOTARGSCBPERR", 0x10, 0x10 }
+};
+
+int
+ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
+ 0x54, regvalue, cur_col, wrap));
+}
+
+static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
+ { "ENLQOPHACHGINPKT", 0x01, 0x01 },
+ { "ENLQOBUSFREE", 0x02, 0x02 },
+ { "ENLQOBADQAS", 0x04, 0x04 },
+ { "ENLQOSTOPI2", 0x08, 0x08 },
+ { "ENLQOINITSCBPERR", 0x10, 0x10 }
+};
+
+int
+ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
+ 0x55, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
{ "LQOPHACHGINPKT", 0x01, 0x01 },
{ "LQOBUSFREE", 0x02, 0x02 },
@@ -1295,21 +1310,6 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x55, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
- { "ENLQOPHACHGINPKT", 0x01, 0x01 },
- { "ENLQOBUSFREE", 0x02, 0x02 },
- { "ENLQOBADQAS", 0x04, 0x04 },
- { "ENLQOSTOPI2", 0x08, 0x08 },
- { "ENLQOINITSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
- 0x55, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
{ "LQOSTOP0", 0x01, 0x01 },
{ "LQOPHACHGOUTPKT", 0x02, 0x02 },
@@ -1594,6 +1594,13 @@ ahd_annexcol_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x65, regvalue, cur_col, wrap));
}
+int
+ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "ANNEXDAT",
+ 0x66, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
{ "LSTSGCLRDIS", 0x01, 0x01 },
{ "SHVALIDSTDIS", 0x02, 0x02 },
@@ -1612,13 +1619,6 @@ ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ANNEXDAT",
- 0x66, regvalue, cur_col, wrap));
-}
-
-int
ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "IOWNID",
@@ -1728,16 +1728,16 @@ ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "PLL400CNT0",
+ return (ahd_print_register(NULL, 0, "UNFAIRNESS",
0x6e, regvalue, cur_col, wrap));
}
int
-ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "UNFAIRNESS",
+ return (ahd_print_register(NULL, 0, "PLL400CNT0",
0x6e, regvalue, cur_col, wrap));
}
@@ -1788,30 +1788,30 @@ ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SGHADDR",
+ return (ahd_print_register(NULL, 0, "SCBHADDR",
0x7c, regvalue, cur_col, wrap));
}
int
-ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SCBHADDR",
+ return (ahd_print_register(NULL, 0, "SGHADDR",
0x7c, regvalue, cur_col, wrap));
}
int
-ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SGHCNT",
+ return (ahd_print_register(NULL, 0, "SCBHCNT",
0x84, regvalue, cur_col, wrap));
}
int
-ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SCBHCNT",
+ return (ahd_print_register(NULL, 0, "SGHCNT",
0x84, regvalue, cur_col, wrap));
}
@@ -1950,25 +1950,25 @@ ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x91, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
+static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
{ "CBNUM", 0xff, 0xff }
};
int
-ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
+ return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
0x91, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
+static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
{ "CBNUM", 0xff, 0xff }
};
int
-ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
+ return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
0x91, regvalue, cur_col, wrap));
}
@@ -1983,17 +1983,6 @@ ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x92, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
- { "MINDEX", 0xff, 0xff }
-};
-
-int
-ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
- 0x92, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = {
{ "MINDEX", 0xff, 0xff }
};
@@ -2012,6 +2001,17 @@ ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x92, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
+ { "MINDEX", 0xff, 0xff }
+};
+
+int
+ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
+ 0x92, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = {
{ "MCLASS", 0x0f, 0x0f }
};
@@ -2023,6 +2023,17 @@ ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x93, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
+ { "MCLASS", 0x0f, 0x0f }
+};
+
+int
+ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
+ 0x93, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = {
{ "MCLASS", 0x0f, 0x0f }
};
@@ -2051,17 +2062,6 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x93, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
- { "MCLASS", 0x0f, 0x0f }
-};
-
-int
-ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
- 0x93, regvalue, cur_col, wrap));
-}
-
int
ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -2070,16 +2070,16 @@ ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
+ return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
0x94, regvalue, cur_col, wrap));
}
int
-ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
+ return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
0x94, regvalue, cur_col, wrap));
}
@@ -2101,7 +2101,7 @@ ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x96, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
+static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
{ "RXSPLTRSP", 0x01, 0x01 },
{ "RXSCEMSG", 0x02, 0x02 },
{ "RXOVRUN", 0x04, 0x04 },
@@ -2113,13 +2113,13 @@ static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
};
int
-ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
+ return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0",
0x96, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
+static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
{ "RXSPLTRSP", 0x01, 0x01 },
{ "RXSCEMSG", 0x02, 0x02 },
{ "RXOVRUN", 0x04, 0x04 },
@@ -2131,42 +2131,42 @@ static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
};
int
-ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0",
+ return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
0x96, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
+static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
{ "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
+ return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
0x97, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
+static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
{ "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
+ return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
0x97, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
+static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
{ "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
+ return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
0x97, regvalue, cur_col, wrap));
}
@@ -2320,26 +2320,26 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9e, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
- { "TEST_NUM", 0x0f, 0x0f },
- { "TEST_GROUP", 0xf0, 0xf0 }
+static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
+ { "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
+ return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
0x9f, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
- { "RXDATABUCKET", 0x01, 0x01 }
+static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
+ { "TEST_NUM", 0x0f, 0x0f },
+ { "TEST_GROUP", 0xf0, 0xf0 }
};
int
-ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
+ return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
0x9f, regvalue, cur_col, wrap));
}
@@ -2537,16 +2537,16 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CCSCBADDR",
+ return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
0xac, regvalue, cur_col, wrap));
}
int
-ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
+ return (ahd_print_register(NULL, 0, "CCSCBADDR",
0xac, regvalue, cur_col, wrap));
}
@@ -2566,22 +2566,6 @@ ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xad, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
- { "CCSGRESET", 0x01, 0x01 },
- { "SG_FETCH_REQ", 0x02, 0x02 },
- { "CCSGENACK", 0x08, 0x08 },
- { "SG_CACHE_AVAIL", 0x10, 0x10 },
- { "CCSGDONE", 0x80, 0x80 },
- { "CCSGEN", 0x0c, 0x0c }
-};
-
-int
-ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
- 0xad, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
{ "CCSCBRESET", 0x01, 0x01 },
{ "CCSCBDIR", 0x04, 0x04 },
@@ -2598,6 +2582,22 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xad, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
+ { "CCSGRESET", 0x01, 0x01 },
+ { "SG_FETCH_REQ", 0x02, 0x02 },
+ { "CCSGENACK", 0x08, 0x08 },
+ { "SG_CACHE_AVAIL", 0x10, 0x10 },
+ { "CCSGDONE", 0x80, 0x80 },
+ { "CCSGEN", 0x0c, 0x0c }
+};
+
+int
+ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
+ 0xad, regvalue, cur_col, wrap));
+}
+
int
ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -2841,30 +2841,30 @@ ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DFPTRS",
+ return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
0xc8, regvalue, cur_col, wrap));
}
int
-ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
+ return (ahd_print_register(NULL, 0, "DFPTRS",
0xc8, regvalue, cur_col, wrap));
}
int
-ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DFBKPTR",
+ return (ahd_print_register(NULL, 0, "SKEWCALC",
0xc9, regvalue, cur_col, wrap));
}
int
-ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SKEWCALC",
+ return (ahd_print_register(NULL, 0, "DFBKPTR",
0xc9, regvalue, cur_col, wrap));
}
@@ -3001,6 +3001,13 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xe4, regvalue, cur_col, wrap));
}
+int
+ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "BRKADDR0",
+ 0xe6, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = {
{ "BRKDIS", 0x80, 0x80 }
};
@@ -3013,13 +3020,6 @@ ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "BRKADDR0",
- 0xe6, regvalue, cur_col, wrap));
-}
-
-int
ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ALLONES",
@@ -3069,30 +3069,30 @@ ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CURADDR",
+ return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
0xf4, regvalue, cur_col, wrap));
}
int
-ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
+ return (ahd_print_register(NULL, 0, "CURADDR",
0xf4, regvalue, cur_col, wrap));
}
int
-ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
+ return (ahd_print_register(NULL, 0, "LASTADDR",
0xf6, regvalue, cur_col, wrap));
}
int
-ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "LASTADDR",
+ return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
0xf6, regvalue, cur_col, wrap));
}
@@ -3174,24 +3174,45 @@ ahd_complete_dma_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
+ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL",
+ 0x12e, regvalue, cur_col, wrap));
+}
+
+int
+ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD",
+ 0x130, regvalue, cur_col, wrap));
+}
+
+int
ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "QFREEZE_COUNT",
- 0x12e, regvalue, cur_col, wrap));
+ 0x132, regvalue, cur_col, wrap));
+}
+
+int
+ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT",
+ 0x134, regvalue, cur_col, wrap));
}
int
ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SAVED_MODE",
- 0x130, regvalue, cur_col, wrap));
+ 0x136, regvalue, cur_col, wrap));
}
int
ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "MSG_OUT",
- 0x131, regvalue, cur_col, wrap));
+ 0x137, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
@@ -3211,7 +3232,7 @@ int
ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS",
- 0x132, regvalue, cur_col, wrap));
+ 0x138, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
@@ -3230,21 +3251,21 @@ int
ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS",
- 0x133, regvalue, cur_col, wrap));
+ 0x139, regvalue, cur_col, wrap));
}
int
ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SAVED_SCSIID",
- 0x134, regvalue, cur_col, wrap));
+ 0x13a, regvalue, cur_col, wrap));
}
int
ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SAVED_LUN",
- 0x135, regvalue, cur_col, wrap));
+ 0x13b, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
@@ -3267,42 +3288,42 @@ int
ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE",
- 0x136, regvalue, cur_col, wrap));
+ 0x13c, regvalue, cur_col, wrap));
}
int
ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG",
- 0x137, regvalue, cur_col, wrap));
+ 0x13d, regvalue, cur_col, wrap));
}
int
-ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
- 0x138, regvalue, cur_col, wrap));
+ return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
+ 0x13e, regvalue, cur_col, wrap));
}
int
-ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
- 0x13c, regvalue, cur_col, wrap));
+ return (ahd_print_register(NULL, 0, "TQINPOS",
+ 0x13f, regvalue, cur_col, wrap));
}
int
-ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
+ return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
0x140, regvalue, cur_col, wrap));
}
int
-ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "TQINPOS",
- 0x141, regvalue, cur_col, wrap));
+ return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
+ 0x144, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t ARG_1_parse_table[] = {
@@ -3320,21 +3341,21 @@ int
ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1",
- 0x142, regvalue, cur_col, wrap));
+ 0x148, regvalue, cur_col, wrap));
}
int
ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ARG_2",
- 0x143, regvalue, cur_col, wrap));
+ 0x149, regvalue, cur_col, wrap));
}
int
ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "LAST_MSG",
- 0x144, regvalue, cur_col, wrap));
+ 0x14a, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
@@ -3350,14 +3371,14 @@ int
ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE",
- 0x145, regvalue, cur_col, wrap));
+ 0x14b, regvalue, cur_col, wrap));
}
int
ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INITIATOR_TAG",
- 0x146, regvalue, cur_col, wrap));
+ 0x14c, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
@@ -3369,63 +3390,63 @@ int
ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
- 0x147, regvalue, cur_col, wrap));
+ 0x14d, regvalue, cur_col, wrap));
}
int
ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR",
- 0x148, regvalue, cur_col, wrap));
+ 0x14e, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER",
- 0x14a, regvalue, cur_col, wrap));
+ 0x150, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS",
- 0x14c, regvalue, cur_col, wrap));
+ 0x152, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS",
- 0x14d, regvalue, cur_col, wrap));
+ 0x153, regvalue, cur_col, wrap));
}
int
ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "CMDS_PENDING",
- 0x14e, regvalue, cur_col, wrap));
+ 0x154, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT",
- 0x150, regvalue, cur_col, wrap));
+ 0x156, regvalue, cur_col, wrap));
}
int
ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX",
- 0x151, regvalue, cur_col, wrap));
+ 0x157, regvalue, cur_col, wrap));
}
int
ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE",
- 0x152, regvalue, cur_col, wrap));
+ 0x158, regvalue, cur_col, wrap));
}
int
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
index 77c471f934e0..b1e5365be230 100644
--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
@@ -2,215 +2,228 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
*/
static uint8_t seqprog[] = {
0xff, 0x02, 0x06, 0x78,
- 0x00, 0xea, 0x50, 0x59,
+ 0x00, 0xea, 0x64, 0x59,
0x01, 0xea, 0x04, 0x30,
0xff, 0x04, 0x0c, 0x78,
- 0x19, 0xea, 0x50, 0x59,
+ 0x19, 0xea, 0x64, 0x59,
0x19, 0xea, 0x04, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x60, 0x3a, 0x1a, 0x68,
- 0x04, 0x47, 0x1b, 0x68,
- 0xff, 0x21, 0x1b, 0x70,
- 0x40, 0x4b, 0x92, 0x69,
- 0x00, 0xe2, 0x54, 0x59,
- 0x40, 0x4b, 0x92, 0x69,
- 0x20, 0x4b, 0x82, 0x69,
- 0xfc, 0x42, 0x24, 0x78,
- 0x10, 0x40, 0x24, 0x78,
- 0x00, 0xe2, 0xc4, 0x5d,
- 0x20, 0x4d, 0x28, 0x78,
- 0x00, 0xe2, 0xc4, 0x5d,
+ 0x60, 0x3a, 0x3a, 0x68,
+ 0x04, 0x4d, 0x35, 0x78,
+ 0x01, 0x34, 0xc1, 0x31,
+ 0x00, 0x32, 0x21, 0x60,
+ 0x01, 0x35, 0xc1, 0x31,
+ 0x00, 0x33, 0x21, 0x60,
+ 0xfb, 0x4d, 0x9b, 0x0a,
+ 0x00, 0xe2, 0x34, 0x40,
+ 0x50, 0x4b, 0x3a, 0x68,
+ 0xff, 0x31, 0x3b, 0x70,
+ 0x02, 0x30, 0x51, 0x31,
+ 0xff, 0x8d, 0x2d, 0x70,
+ 0x02, 0x8c, 0x51, 0x31,
+ 0xff, 0x8d, 0x29, 0x60,
+ 0x02, 0x28, 0x19, 0x33,
+ 0x02, 0x30, 0x51, 0x32,
+ 0xff, 0xea, 0x62, 0x02,
+ 0x00, 0xe2, 0x3a, 0x40,
+ 0xff, 0x21, 0x3b, 0x70,
+ 0x40, 0x4b, 0xaa, 0x69,
+ 0x00, 0xe2, 0x68, 0x59,
+ 0x40, 0x4b, 0xaa, 0x69,
+ 0x20, 0x4b, 0x96, 0x69,
+ 0xfc, 0x42, 0x44, 0x78,
+ 0x10, 0x40, 0x44, 0x78,
+ 0x00, 0xe2, 0xfc, 0x5d,
+ 0x20, 0x4d, 0x48, 0x78,
+ 0x00, 0xe2, 0xfc, 0x5d,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x30, 0x60,
+ 0x30, 0xe0, 0x50, 0x60,
0x7f, 0x4a, 0x94, 0x08,
- 0x00, 0xe2, 0x32, 0x40,
+ 0x00, 0xe2, 0x52, 0x40,
0xc0, 0x4a, 0x94, 0x00,
- 0x00, 0xe2, 0x3e, 0x58,
- 0x00, 0xe2, 0x56, 0x58,
- 0x00, 0xe2, 0x66, 0x58,
+ 0x00, 0xe2, 0x5e, 0x58,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x00, 0xe2, 0x86, 0x58,
0x00, 0xe2, 0x06, 0x40,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x01, 0x52, 0x64, 0x78,
+ 0x01, 0x52, 0x84, 0x78,
0x02, 0x58, 0x50, 0x31,
0xff, 0xea, 0x10, 0x0b,
- 0xff, 0x97, 0x4f, 0x78,
- 0x50, 0x4b, 0x4a, 0x68,
+ 0xff, 0x97, 0x6f, 0x78,
+ 0x50, 0x4b, 0x6a, 0x68,
0xbf, 0x3a, 0x74, 0x08,
- 0x14, 0xea, 0x50, 0x59,
+ 0x14, 0xea, 0x64, 0x59,
0x14, 0xea, 0x04, 0x00,
0x08, 0x92, 0x25, 0x03,
- 0xff, 0x90, 0x3f, 0x68,
- 0x00, 0xe2, 0x56, 0x5b,
- 0x00, 0xe2, 0x3e, 0x40,
- 0x00, 0xea, 0x44, 0x59,
+ 0xff, 0x90, 0x5f, 0x68,
+ 0x00, 0xe2, 0x76, 0x5b,
+ 0x00, 0xe2, 0x5e, 0x40,
+ 0x00, 0xea, 0x5e, 0x59,
0x01, 0xea, 0x00, 0x30,
- 0x80, 0xf9, 0x5e, 0x68,
- 0x00, 0xe2, 0x42, 0x59,
- 0x11, 0xea, 0x44, 0x59,
+ 0x80, 0xf9, 0x7e, 0x68,
+ 0x00, 0xe2, 0x5c, 0x59,
+ 0x11, 0xea, 0x5e, 0x59,
0x11, 0xea, 0x00, 0x00,
- 0x80, 0xf9, 0x42, 0x79,
+ 0x80, 0xf9, 0x5c, 0x79,
0xff, 0xea, 0xd4, 0x0d,
- 0x22, 0xea, 0x44, 0x59,
+ 0x22, 0xea, 0x5e, 0x59,
0x22, 0xea, 0x00, 0x00,
- 0x10, 0x16, 0x70, 0x78,
- 0x01, 0x0b, 0xa2, 0x32,
+ 0x10, 0x16, 0x90, 0x78,
0x10, 0x16, 0x2c, 0x00,
- 0x18, 0xad, 0x00, 0x79,
- 0x04, 0xad, 0xca, 0x68,
- 0x80, 0xad, 0x64, 0x78,
- 0x10, 0xad, 0x98, 0x78,
- 0xff, 0x88, 0x83, 0x68,
+ 0x01, 0x0b, 0xae, 0x32,
+ 0x18, 0xad, 0x12, 0x79,
+ 0x04, 0xad, 0xdc, 0x68,
+ 0x80, 0xad, 0x84, 0x78,
+ 0x10, 0xad, 0xaa, 0x78,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0x8c, 0x59, 0x32,
+ 0xff, 0x8d, 0xa1, 0x60,
+ 0xff, 0xea, 0x5e, 0x02,
+ 0xff, 0x88, 0xa7, 0x78,
+ 0x02, 0x30, 0x19, 0x33,
+ 0x02, 0xa8, 0x60, 0x36,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
- 0x33, 0xea, 0x44, 0x59,
- 0x33, 0xea, 0x00, 0x00,
- 0x40, 0x3a, 0x64, 0x68,
- 0x50, 0x4b, 0x64, 0x68,
- 0x22, 0xea, 0x44, 0x59,
- 0x22, 0xea, 0x00, 0x00,
- 0xe7, 0xad, 0x5a, 0x09,
- 0x02, 0x8c, 0x59, 0x32,
- 0x1a, 0xea, 0x50, 0x59,
- 0x1a, 0xea, 0x04, 0x00,
- 0xff, 0xea, 0xd4, 0x0d,
0xe7, 0xad, 0x5a, 0x09,
- 0x00, 0xe2, 0xa6, 0x58,
+ 0x00, 0xe2, 0xb8, 0x58,
0xff, 0xea, 0x56, 0x02,
- 0x04, 0x7c, 0x78, 0x32,
- 0x20, 0x16, 0x64, 0x78,
- 0x04, 0x38, 0x79, 0x32,
- 0x80, 0x37, 0x6f, 0x16,
- 0xff, 0x2d, 0xb5, 0x60,
- 0xff, 0x29, 0xb5, 0x60,
- 0x40, 0x51, 0xc5, 0x78,
- 0xff, 0x4f, 0xb5, 0x68,
- 0xff, 0x4d, 0xc1, 0x19,
- 0x00, 0x4e, 0xd5, 0x19,
- 0x00, 0xe2, 0xc4, 0x50,
- 0x01, 0x4c, 0xc1, 0x31,
- 0x00, 0x50, 0xd5, 0x19,
- 0x00, 0xe2, 0xc4, 0x48,
- 0x80, 0x18, 0x64, 0x78,
- 0x02, 0x4a, 0x1d, 0x30,
+ 0x04, 0x7c, 0x88, 0x32,
+ 0x20, 0x16, 0x84, 0x78,
+ 0x04, 0x40, 0x89, 0x32,
+ 0x80, 0x3d, 0x7b, 0x16,
+ 0xff, 0x2d, 0xc7, 0x60,
+ 0xff, 0x29, 0xc7, 0x60,
+ 0x40, 0x57, 0xd7, 0x78,
+ 0xff, 0x55, 0xc7, 0x68,
+ 0xff, 0x53, 0xc1, 0x19,
+ 0x00, 0x54, 0xd5, 0x19,
+ 0x00, 0xe2, 0xd6, 0x50,
+ 0x01, 0x52, 0xc1, 0x31,
+ 0x00, 0x56, 0xd5, 0x19,
+ 0x00, 0xe2, 0xd6, 0x48,
+ 0x80, 0x18, 0x84, 0x78,
+ 0x02, 0x50, 0x1d, 0x30,
0x10, 0xea, 0x18, 0x00,
0x60, 0x18, 0x30, 0x00,
0x7f, 0x18, 0x30, 0x0c,
0x02, 0xea, 0x02, 0x00,
- 0xff, 0xea, 0xa0, 0x0a,
+ 0xff, 0xea, 0xac, 0x0a,
0x80, 0x18, 0x30, 0x04,
- 0x40, 0xad, 0x64, 0x78,
+ 0x40, 0xad, 0x84, 0x78,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0xa8, 0x40, 0x31,
0xff, 0xea, 0xc0, 0x09,
- 0x01, 0x4e, 0x9d, 0x1a,
- 0x00, 0x4f, 0x9f, 0x22,
+ 0x01, 0x54, 0xa9, 0x1a,
+ 0x00, 0x55, 0xab, 0x22,
0x01, 0x94, 0x6d, 0x33,
- 0x01, 0xea, 0x20, 0x33,
+ 0xff, 0xea, 0x20, 0x0b,
0x04, 0xac, 0x49, 0x32,
0xff, 0xea, 0x5a, 0x03,
0xff, 0xea, 0x5e, 0x03,
0x01, 0x10, 0xd4, 0x31,
- 0x10, 0x92, 0xf5, 0x68,
+ 0x10, 0x92, 0x07, 0x69,
0x3d, 0x93, 0xc5, 0x29,
0xfe, 0xe2, 0xc4, 0x09,
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x50, 0x31,
0x02, 0xa0, 0xda, 0x31,
- 0xff, 0xa9, 0xf4, 0x70,
+ 0xff, 0xa9, 0x06, 0x71,
0x02, 0xa0, 0x58, 0x37,
- 0xff, 0x21, 0xfd, 0x70,
+ 0xff, 0x21, 0x0f, 0x71,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x5c, 0x33,
0x02, 0xa0, 0x44, 0x36,
0x02, 0xa0, 0x40, 0x32,
0x02, 0xa0, 0x44, 0x36,
- 0x04, 0x47, 0x05, 0x69,
- 0x40, 0x16, 0x30, 0x69,
- 0xff, 0x2d, 0x35, 0x61,
- 0xff, 0x29, 0x65, 0x70,
- 0x01, 0x37, 0xc1, 0x31,
+ 0x04, 0x4d, 0x17, 0x69,
+ 0x40, 0x16, 0x48, 0x69,
+ 0xff, 0x2d, 0x4d, 0x61,
+ 0xff, 0x29, 0x85, 0x70,
0x02, 0x28, 0x55, 0x32,
0x01, 0xea, 0x5a, 0x01,
- 0x04, 0x3c, 0xf9, 0x30,
+ 0x04, 0x44, 0xf9, 0x30,
+ 0x01, 0x44, 0xc1, 0x31,
0x02, 0x28, 0x51, 0x31,
- 0x01, 0xa8, 0x60, 0x31,
- 0x00, 0xa9, 0x60, 0x01,
+ 0x02, 0xa8, 0x60, 0x31,
+ 0x01, 0xa4, 0x61, 0x31,
+ 0x01, 0x3d, 0x61, 0x31,
0x01, 0x14, 0xd4, 0x31,
- 0x01, 0x50, 0xa1, 0x1a,
- 0xff, 0x4e, 0x9d, 0x1a,
- 0xff, 0x4f, 0x9f, 0x22,
- 0xff, 0x8d, 0x29, 0x71,
- 0x80, 0xac, 0x28, 0x71,
- 0x20, 0x16, 0x28, 0x69,
+ 0x01, 0x56, 0xad, 0x1a,
+ 0xff, 0x54, 0xa9, 0x1a,
+ 0xff, 0x55, 0xab, 0x22,
+ 0xff, 0x8d, 0x41, 0x71,
+ 0x80, 0xac, 0x40, 0x71,
+ 0x20, 0x16, 0x40, 0x69,
+ 0x00, 0xac, 0xc4, 0x19,
+ 0x07, 0xe2, 0x40, 0xf9,
0x02, 0x8c, 0x51, 0x31,
- 0x00, 0xe2, 0x12, 0x41,
+ 0x00, 0xe2, 0x24, 0x41,
0x01, 0xac, 0x08, 0x31,
0x09, 0xea, 0x5a, 0x01,
0x02, 0x8c, 0x51, 0x32,
0xff, 0xea, 0x1a, 0x07,
0x04, 0x24, 0xf9, 0x30,
- 0x1d, 0xea, 0x3a, 0x41,
+ 0x1d, 0xea, 0x52, 0x41,
0x02, 0x2c, 0x51, 0x31,
0x04, 0xa8, 0xf9, 0x30,
- 0x19, 0xea, 0x3a, 0x41,
+ 0x19, 0xea, 0x52, 0x41,
0x06, 0xea, 0x08, 0x81,
0x01, 0xe2, 0x5a, 0x35,
- 0x02, 0xf2, 0xf0, 0x35,
+ 0x02, 0xf2, 0xf0, 0x31,
+ 0xff, 0xea, 0xd4, 0x0d,
0x02, 0xf2, 0xf0, 0x31,
0x02, 0xf8, 0xe4, 0x35,
0x80, 0xea, 0xb2, 0x01,
0x01, 0xe2, 0x00, 0x30,
0xff, 0xea, 0xb2, 0x0d,
- 0x80, 0xea, 0xb2, 0x01,
- 0x11, 0x00, 0x00, 0x10,
- 0xff, 0xea, 0xb2, 0x0d,
0x01, 0xe2, 0x04, 0x30,
0x01, 0xea, 0x04, 0x34,
0x02, 0x20, 0xbd, 0x30,
0x02, 0x20, 0xb9, 0x30,
0x02, 0x20, 0x51, 0x31,
0x4c, 0x93, 0xd7, 0x28,
- 0x10, 0x92, 0x63, 0x79,
+ 0x10, 0x92, 0x77, 0x79,
0x01, 0x6b, 0xc0, 0x30,
0x02, 0x64, 0xc8, 0x00,
0x40, 0x3a, 0x74, 0x04,
- 0x00, 0xe2, 0x56, 0x58,
- 0x33, 0xea, 0x44, 0x59,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x64, 0x61,
- 0x20, 0x3f, 0x7a, 0x69,
- 0x10, 0x3f, 0x64, 0x79,
+ 0x30, 0xe0, 0x78, 0x61,
+ 0x20, 0x3f, 0x8e, 0x69,
+ 0x10, 0x3f, 0x78, 0x79,
0x02, 0xea, 0x7e, 0x00,
- 0x00, 0xea, 0x44, 0x59,
+ 0x00, 0xea, 0x5e, 0x59,
0x01, 0xea, 0x00, 0x30,
- 0x02, 0x48, 0x51, 0x35,
+ 0x02, 0x4e, 0x51, 0x35,
0x01, 0xea, 0x7e, 0x00,
- 0x11, 0xea, 0x44, 0x59,
+ 0x11, 0xea, 0x5e, 0x59,
0x11, 0xea, 0x00, 0x00,
- 0x02, 0x48, 0x51, 0x35,
+ 0x02, 0x4e, 0x51, 0x35,
+ 0xc0, 0x4a, 0x94, 0x00,
+ 0x04, 0x41, 0x9c, 0x79,
0x08, 0xea, 0x98, 0x00,
0x08, 0x57, 0xae, 0x00,
0x08, 0x3c, 0x78, 0x00,
- 0xf0, 0x49, 0x68, 0x0a,
+ 0xf0, 0x49, 0x74, 0x0a,
0x0f, 0x67, 0xc0, 0x09,
- 0x00, 0x34, 0x69, 0x02,
+ 0x00, 0x3a, 0x75, 0x02,
0x20, 0xea, 0x96, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x40, 0x3a, 0xae, 0x69,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0xc0, 0x4a, 0x94, 0x00,
+ 0x40, 0x3a, 0xc8, 0x69,
0x02, 0x55, 0x06, 0x68,
- 0x02, 0x56, 0xae, 0x69,
- 0xff, 0x5b, 0xae, 0x61,
+ 0x02, 0x56, 0xc8, 0x69,
+ 0xff, 0x5b, 0xc8, 0x61,
0x02, 0x20, 0x51, 0x31,
0x80, 0xea, 0xb2, 0x01,
0x44, 0xea, 0x00, 0x00,
@@ -218,237 +231,246 @@ static uint8_t seqprog[] = {
0x33, 0xea, 0x00, 0x00,
0xff, 0xea, 0xb2, 0x09,
0xff, 0xe0, 0xc0, 0x19,
- 0xff, 0xe0, 0xb0, 0x79,
+ 0xff, 0xe0, 0xca, 0x79,
0x02, 0xac, 0x51, 0x31,
- 0x00, 0xe2, 0xa6, 0x41,
+ 0x00, 0xe2, 0xc0, 0x41,
0x02, 0x5e, 0x50, 0x31,
0x02, 0xa8, 0xb8, 0x30,
0x02, 0x5c, 0x50, 0x31,
- 0xff, 0xad, 0xc1, 0x71,
+ 0xff, 0xad, 0xdb, 0x71,
0x02, 0xac, 0x41, 0x31,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x5c, 0x33,
0x02, 0xa0, 0x44, 0x32,
- 0x00, 0xe2, 0xca, 0x41,
- 0x10, 0x92, 0xcb, 0x69,
+ 0x00, 0xe2, 0xe4, 0x41,
+ 0x10, 0x92, 0xe5, 0x69,
0x3d, 0x93, 0xc9, 0x29,
0x01, 0xe4, 0xc8, 0x01,
0x01, 0xea, 0xca, 0x01,
0xff, 0xea, 0xda, 0x01,
0x02, 0x20, 0x51, 0x31,
0x02, 0xae, 0x41, 0x32,
- 0xff, 0x21, 0xd3, 0x61,
+ 0xff, 0x21, 0xed, 0x61,
0xff, 0xea, 0x46, 0x02,
0x02, 0x5c, 0x50, 0x31,
0x40, 0xea, 0x96, 0x00,
- 0x02, 0x56, 0xcc, 0x6d,
- 0x01, 0x55, 0xcc, 0x6d,
- 0x10, 0x92, 0xdf, 0x79,
- 0x10, 0x40, 0xe8, 0x69,
- 0x01, 0x56, 0xe8, 0x79,
+ 0x02, 0x56, 0x04, 0x6e,
+ 0x01, 0x55, 0x04, 0x6e,
+ 0x10, 0x92, 0xf9, 0x79,
+ 0x10, 0x40, 0x02, 0x6a,
+ 0x01, 0x56, 0x02, 0x7a,
0xff, 0x97, 0x07, 0x78,
- 0x13, 0xea, 0x50, 0x59,
+ 0x13, 0xea, 0x64, 0x59,
0x13, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x06, 0x40,
0xbf, 0x3a, 0x74, 0x08,
+ 0x04, 0x41, 0x08, 0x7a,
0x08, 0xea, 0x98, 0x00,
0x08, 0x57, 0xae, 0x00,
- 0x01, 0x93, 0x69, 0x32,
- 0x01, 0x94, 0x6b, 0x32,
- 0x40, 0xea, 0x66, 0x02,
+ 0x01, 0x93, 0x75, 0x32,
+ 0x01, 0x94, 0x77, 0x32,
+ 0x40, 0xea, 0x72, 0x02,
0x08, 0x3c, 0x78, 0x00,
- 0x80, 0xea, 0x62, 0x02,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0x01, 0x36, 0xc1, 0x31,
- 0x9f, 0xe0, 0x4c, 0x7c,
- 0x80, 0xe0, 0x0c, 0x72,
- 0xa0, 0xe0, 0x44, 0x72,
- 0xc0, 0xe0, 0x3a, 0x72,
- 0xe0, 0xe0, 0x74, 0x72,
- 0x01, 0xea, 0x50, 0x59,
+ 0x80, 0xea, 0x6e, 0x02,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0x01, 0x3c, 0xc1, 0x31,
+ 0x9f, 0xe0, 0x84, 0x7c,
+ 0x80, 0xe0, 0x28, 0x72,
+ 0xa0, 0xe0, 0x64, 0x72,
+ 0xc0, 0xe0, 0x5a, 0x72,
+ 0xe0, 0xe0, 0x94, 0x72,
+ 0x01, 0xea, 0x64, 0x59,
0x01, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x80, 0x33, 0x13, 0x7a,
- 0x03, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x80, 0x39, 0x2f, 0x7a,
+ 0x03, 0xea, 0x64, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0xee, 0x00, 0x1a, 0x6a,
+ 0xee, 0x00, 0x36, 0x6a,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x02, 0xa8, 0x90, 0x32,
- 0x00, 0xe2, 0x6a, 0x59,
+ 0x02, 0xa8, 0x9c, 0x32,
+ 0x00, 0xe2, 0x7e, 0x59,
0xef, 0x96, 0xd5, 0x19,
- 0x00, 0xe2, 0x2a, 0x52,
+ 0x00, 0xe2, 0x46, 0x52,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x30, 0x42,
+ 0x00, 0xe2, 0x4c, 0x42,
0x01, 0x96, 0xd1, 0x30,
0x10, 0x80, 0x89, 0x31,
0x20, 0xea, 0x32, 0x00,
- 0xbf, 0x33, 0x67, 0x0a,
- 0x20, 0x19, 0x32, 0x6a,
- 0x02, 0x4d, 0xf8, 0x69,
- 0x40, 0x33, 0x67, 0x02,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x80, 0x33, 0xb5, 0x6a,
+ 0xbf, 0x39, 0x73, 0x0a,
+ 0x10, 0x4c, 0x56, 0x6a,
+ 0x20, 0x19, 0x4e, 0x6a,
+ 0x20, 0x19, 0x52, 0x6a,
+ 0x02, 0x4d, 0x14, 0x6a,
+ 0x40, 0x39, 0x73, 0x02,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x80, 0x39, 0xd5, 0x6a,
0x01, 0x44, 0x10, 0x33,
0x08, 0x92, 0x25, 0x03,
- 0x00, 0xe2, 0xf8, 0x41,
+ 0x00, 0xe2, 0x14, 0x42,
0x10, 0xea, 0x80, 0x00,
- 0x01, 0x31, 0xc5, 0x31,
- 0x80, 0xe2, 0x60, 0x62,
- 0x10, 0x92, 0x85, 0x6a,
+ 0x01, 0x37, 0xc5, 0x31,
+ 0x80, 0xe2, 0x80, 0x62,
+ 0x10, 0x92, 0xa5, 0x6a,
0xc0, 0x94, 0xc5, 0x01,
- 0x40, 0x92, 0x51, 0x6a,
+ 0x40, 0x92, 0x71, 0x6a,
0xbf, 0xe2, 0xc4, 0x09,
- 0x20, 0x92, 0x65, 0x7a,
+ 0x20, 0x92, 0x85, 0x7a,
0x01, 0xe2, 0x88, 0x30,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0xa0, 0x36, 0x6d, 0x62,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0xa0, 0x3c, 0x8d, 0x62,
0x23, 0x92, 0x89, 0x08,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0xa0, 0x36, 0x6d, 0x62,
- 0x00, 0xa8, 0x64, 0x42,
- 0xff, 0xe2, 0x64, 0x62,
- 0x00, 0xe2, 0x84, 0x42,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0xa0, 0x3c, 0x8d, 0x62,
+ 0x00, 0xa8, 0x84, 0x42,
+ 0xff, 0xe2, 0x84, 0x62,
+ 0x00, 0xe2, 0xa4, 0x42,
0x40, 0xea, 0x98, 0x00,
0x01, 0xe2, 0x88, 0x30,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0xa0, 0x36, 0x43, 0x72,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0xa0, 0x3c, 0x63, 0x72,
0x40, 0xea, 0x98, 0x00,
- 0x01, 0x31, 0x89, 0x32,
- 0x08, 0xea, 0x62, 0x02,
- 0x00, 0xe2, 0xf8, 0x41,
- 0xe0, 0xea, 0xd4, 0x5b,
- 0x80, 0xe0, 0xc0, 0x6a,
- 0x04, 0xe0, 0x66, 0x73,
- 0x02, 0xe0, 0x96, 0x73,
- 0x00, 0xea, 0x1e, 0x73,
- 0x03, 0xe0, 0xa6, 0x73,
- 0x23, 0xe0, 0x96, 0x72,
- 0x08, 0xe0, 0xbc, 0x72,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0x07, 0xea, 0x50, 0x59,
+ 0x01, 0x37, 0x95, 0x32,
+ 0x08, 0xea, 0x6e, 0x02,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0xe0, 0xea, 0xfe, 0x5b,
+ 0x80, 0xe0, 0xe0, 0x6a,
+ 0x04, 0xe0, 0x92, 0x73,
+ 0x02, 0xe0, 0xc4, 0x73,
+ 0x00, 0xea, 0x3e, 0x73,
+ 0x03, 0xe0, 0xd4, 0x73,
+ 0x23, 0xe0, 0xb6, 0x72,
+ 0x08, 0xe0, 0xdc, 0x72,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0x07, 0xea, 0x64, 0x59,
0x07, 0xea, 0x04, 0x00,
- 0x08, 0x42, 0xf9, 0x71,
- 0x04, 0x42, 0x93, 0x62,
- 0x01, 0x43, 0x89, 0x30,
- 0x00, 0xe2, 0x84, 0x42,
+ 0x08, 0x48, 0x15, 0x72,
+ 0x04, 0x48, 0xb3, 0x62,
+ 0x01, 0x49, 0x89, 0x30,
+ 0x00, 0xe2, 0xa4, 0x42,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0x84, 0x42,
- 0x01, 0x00, 0x60, 0x32,
- 0x33, 0xea, 0x44, 0x59,
+ 0x00, 0xe2, 0xa4, 0x42,
+ 0x01, 0x00, 0x6c, 0x32,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x4c, 0x34, 0xc1, 0x28,
+ 0x4c, 0x3a, 0xc1, 0x28,
0x01, 0x64, 0xc0, 0x31,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x01, 0xe0, 0xba, 0x7a,
- 0xa0, 0xea, 0xca, 0x5b,
- 0x01, 0xa0, 0xba, 0x62,
- 0x01, 0x84, 0xaf, 0x7a,
- 0x01, 0x95, 0xbd, 0x6a,
- 0x05, 0xea, 0x50, 0x59,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x01, 0xe0, 0xda, 0x7a,
+ 0xa0, 0xea, 0xf4, 0x5b,
+ 0x01, 0xa0, 0xda, 0x62,
+ 0x01, 0x84, 0xcf, 0x7a,
+ 0x01, 0x95, 0xdd, 0x6a,
+ 0x05, 0xea, 0x64, 0x59,
0x05, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x03, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x03, 0xea, 0x64, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x07, 0xea, 0xdc, 0x5b,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x07, 0xea, 0x06, 0x5c,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x3f, 0xe0, 0x6a, 0x0a,
- 0xc0, 0x34, 0xc1, 0x09,
- 0x00, 0x35, 0x51, 0x01,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x3f, 0xe0, 0x76, 0x0a,
+ 0xc0, 0x3a, 0xc1, 0x09,
+ 0x00, 0x3b, 0x51, 0x01,
0xff, 0xea, 0x52, 0x09,
- 0x30, 0x34, 0xc5, 0x09,
+ 0x30, 0x3a, 0xc5, 0x09,
0x3d, 0xe2, 0xc4, 0x29,
0xb8, 0xe2, 0xc4, 0x19,
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x40, 0x31,
- 0xff, 0xa1, 0xdc, 0x72,
+ 0xff, 0xa1, 0xfc, 0x72,
0x02, 0xe8, 0xda, 0x31,
0x02, 0xa0, 0x50, 0x31,
- 0x00, 0xe2, 0xfe, 0x42,
- 0x80, 0x33, 0x67, 0x02,
+ 0x00, 0xe2, 0x1e, 0x43,
+ 0x80, 0x39, 0x73, 0x02,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0x01, 0x33, 0x67, 0x02,
- 0xe0, 0x36, 0x19, 0x63,
- 0x02, 0x33, 0x67, 0x02,
- 0x20, 0x46, 0x12, 0x63,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0x01, 0x39, 0x73, 0x02,
+ 0xe0, 0x3c, 0x39, 0x63,
+ 0x02, 0x39, 0x73, 0x02,
+ 0x20, 0x46, 0x32, 0x63,
0xff, 0xea, 0x52, 0x09,
- 0xa8, 0xea, 0xca, 0x5b,
- 0x04, 0x92, 0xf9, 0x7a,
- 0x01, 0x34, 0xc1, 0x31,
- 0x00, 0x93, 0xf9, 0x62,
- 0x01, 0x35, 0xc1, 0x31,
- 0x00, 0x94, 0x03, 0x73,
+ 0xa8, 0xea, 0xf4, 0x5b,
+ 0x04, 0x92, 0x19, 0x7b,
+ 0x01, 0x3a, 0xc1, 0x31,
+ 0x00, 0x93, 0x19, 0x63,
+ 0x01, 0x3b, 0xc1, 0x31,
+ 0x00, 0x94, 0x23, 0x73,
0x01, 0xa9, 0x52, 0x11,
- 0xff, 0xa9, 0xee, 0x6a,
- 0x00, 0xe2, 0x12, 0x43,
- 0x10, 0x33, 0x67, 0x02,
- 0x04, 0x92, 0x13, 0x7b,
+ 0xff, 0xa9, 0x0e, 0x6b,
+ 0x00, 0xe2, 0x32, 0x43,
+ 0x10, 0x39, 0x73, 0x02,
+ 0x04, 0x92, 0x33, 0x7b,
0xfb, 0x92, 0x25, 0x0b,
- 0xff, 0xea, 0x66, 0x0a,
- 0x01, 0xa4, 0x0d, 0x6b,
- 0x02, 0xa8, 0x90, 0x32,
- 0x00, 0xe2, 0x6a, 0x59,
- 0x10, 0x92, 0xbd, 0x7a,
- 0xff, 0xea, 0xdc, 0x5b,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x04, 0xea, 0x50, 0x59,
+ 0xff, 0xea, 0x72, 0x0a,
+ 0x01, 0xa4, 0x2d, 0x6b,
+ 0x02, 0xa8, 0x9c, 0x32,
+ 0x00, 0xe2, 0x7e, 0x59,
+ 0x10, 0x92, 0xdd, 0x7a,
+ 0xff, 0xea, 0x06, 0x5c,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x04, 0xea, 0x64, 0x59,
0x04, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x04, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x04, 0xea, 0x64, 0x59,
0x04, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x08, 0x92, 0xb5, 0x7a,
- 0xc0, 0x33, 0x29, 0x7b,
- 0x80, 0x33, 0xb5, 0x6a,
- 0xff, 0x88, 0x29, 0x6b,
- 0x40, 0x33, 0xb5, 0x6a,
- 0x10, 0x92, 0x2f, 0x7b,
- 0x0a, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x08, 0x92, 0xd5, 0x7a,
+ 0xc0, 0x39, 0x49, 0x7b,
+ 0x80, 0x39, 0xd5, 0x6a,
+ 0xff, 0x88, 0x49, 0x6b,
+ 0x40, 0x39, 0xd5, 0x6a,
+ 0x10, 0x92, 0x4f, 0x7b,
+ 0x0a, 0xea, 0x64, 0x59,
0x0a, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x4e, 0x5b,
- 0x00, 0xe2, 0x82, 0x43,
- 0x50, 0x4b, 0x36, 0x6b,
+ 0x00, 0xe2, 0x6e, 0x5b,
+ 0x00, 0xe2, 0xae, 0x43,
+ 0x50, 0x4b, 0x56, 0x6b,
0xbf, 0x3a, 0x74, 0x08,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
- 0x01, 0x2e, 0x5d, 0x1a,
- 0x00, 0x2f, 0x5f, 0x22,
- 0x04, 0x47, 0x8f, 0x02,
+ 0x01, 0x32, 0x65, 0x1a,
+ 0x00, 0x33, 0x67, 0x22,
+ 0x04, 0x4d, 0x9b, 0x02,
0x01, 0xfa, 0xc0, 0x35,
- 0x02, 0xa8, 0x84, 0x32,
+ 0x02, 0xa8, 0x90, 0x32,
0x02, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x02, 0x42, 0x51, 0x31,
- 0xff, 0x90, 0x65, 0x68,
- 0xff, 0x88, 0x5b, 0x6b,
- 0x01, 0xa4, 0x57, 0x6b,
- 0x02, 0xa4, 0x5f, 0x6b,
- 0x01, 0x84, 0x5f, 0x7b,
+ 0x02, 0x48, 0x51, 0x31,
+ 0xff, 0x90, 0x85, 0x68,
+ 0xff, 0x88, 0x7b, 0x6b,
+ 0x01, 0xa4, 0x77, 0x6b,
+ 0x02, 0xa4, 0x7f, 0x6b,
+ 0x01, 0x84, 0x7f, 0x7b,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
- 0xff, 0x88, 0x5f, 0x73,
- 0x00, 0xe2, 0x32, 0x5b,
+ 0xff, 0x88, 0x7f, 0x73,
+ 0x00, 0xe2, 0x52, 0x5b,
0x02, 0xa8, 0x20, 0x33,
- 0x02, 0x2c, 0x19, 0x33,
+ 0x04, 0xa4, 0x49, 0x03,
+ 0xff, 0xea, 0x1a, 0x03,
+ 0xff, 0x2d, 0x8b, 0x63,
0x02, 0xa8, 0x58, 0x32,
- 0x04, 0xa4, 0x49, 0x07,
- 0xc0, 0x33, 0xb5, 0x6a,
+ 0x02, 0xa8, 0x5c, 0x36,
+ 0x02, 0xa8, 0x40, 0x31,
+ 0x02, 0x2e, 0x51, 0x31,
+ 0x02, 0xa0, 0x18, 0x33,
+ 0x02, 0xa0, 0x5c, 0x36,
+ 0xc0, 0x39, 0xd5, 0x6a,
0x04, 0x92, 0x25, 0x03,
- 0x20, 0x92, 0x83, 0x6b,
+ 0x20, 0x92, 0xaf, 0x6b,
0x02, 0xa8, 0x40, 0x31,
- 0xc0, 0x34, 0xc1, 0x09,
- 0x00, 0x35, 0x51, 0x01,
+ 0xc0, 0x3a, 0xc1, 0x09,
+ 0x00, 0x3b, 0x51, 0x01,
0xff, 0xea, 0x52, 0x09,
- 0x30, 0x34, 0xc5, 0x09,
+ 0x30, 0x3a, 0xc5, 0x09,
0x3d, 0xe2, 0xc4, 0x29,
0xb8, 0xe2, 0xc4, 0x19,
0x01, 0xea, 0xc6, 0x01,
@@ -458,69 +480,75 @@ static uint8_t seqprog[] = {
0xf7, 0x57, 0xae, 0x08,
0x08, 0xea, 0x98, 0x00,
0x01, 0x44, 0xd4, 0x31,
- 0xee, 0x00, 0x8c, 0x6b,
+ 0xee, 0x00, 0xb8, 0x6b,
0x02, 0xea, 0xb4, 0x00,
- 0x00, 0xe2, 0xb4, 0x5b,
- 0x09, 0x4c, 0x8e, 0x7b,
+ 0xc0, 0xea, 0x72, 0x02,
+ 0x09, 0x4c, 0xba, 0x7b,
+ 0x01, 0xea, 0x78, 0x02,
0x08, 0x4c, 0x06, 0x68,
- 0x0b, 0xea, 0x50, 0x59,
+ 0x0b, 0xea, 0x64, 0x59,
0x0b, 0xea, 0x04, 0x00,
0x01, 0x44, 0xd4, 0x31,
- 0x20, 0x33, 0xf9, 0x79,
- 0x00, 0xe2, 0x9e, 0x5b,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x01, 0x84, 0xa3, 0x7b,
+ 0x20, 0x39, 0x15, 0x7a,
+ 0x00, 0xe2, 0xcc, 0x5b,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x01, 0x84, 0xd1, 0x7b,
0x01, 0xa4, 0x49, 0x07,
0x08, 0x60, 0x30, 0x33,
0x08, 0x80, 0x41, 0x37,
- 0xdf, 0x33, 0x67, 0x0a,
- 0xee, 0x00, 0xb0, 0x6b,
+ 0xdf, 0x39, 0x73, 0x0a,
+ 0xee, 0x00, 0xde, 0x6b,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x00, 0xe2, 0x6a, 0x59,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x01, 0xea, 0x6c, 0x02,
- 0xc0, 0xea, 0x66, 0x06,
- 0xff, 0x42, 0xc4, 0x6b,
- 0x01, 0x41, 0xb8, 0x6b,
- 0x02, 0x41, 0xb8, 0x7b,
- 0xff, 0x42, 0xc4, 0x6b,
- 0x01, 0x41, 0xb8, 0x6b,
- 0x02, 0x41, 0xb8, 0x7b,
- 0xff, 0x42, 0xc4, 0x7b,
- 0x04, 0x4c, 0xb8, 0x6b,
- 0xe0, 0x41, 0x6c, 0x0e,
+ 0x00, 0xe2, 0x7e, 0x59,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0xff, 0x42, 0xee, 0x6b,
+ 0x01, 0x41, 0xe2, 0x6b,
+ 0x02, 0x41, 0xe2, 0x7b,
+ 0xff, 0x42, 0xee, 0x6b,
+ 0x01, 0x41, 0xe2, 0x6b,
+ 0x02, 0x41, 0xe2, 0x7b,
+ 0xff, 0x42, 0xee, 0x7b,
+ 0x04, 0x4c, 0xe2, 0x6b,
+ 0xe0, 0x41, 0x78, 0x0e,
0x01, 0x44, 0xd4, 0x31,
- 0xff, 0x42, 0xcc, 0x7b,
- 0x04, 0x4c, 0xcc, 0x6b,
- 0xe0, 0x41, 0x6c, 0x0a,
- 0xe0, 0x36, 0xf9, 0x61,
+ 0xff, 0x42, 0xf6, 0x7b,
+ 0x04, 0x4c, 0xf6, 0x6b,
+ 0xe0, 0x41, 0x78, 0x0a,
+ 0xe0, 0x3c, 0x15, 0x62,
0xff, 0xea, 0xca, 0x09,
0x01, 0xe2, 0xc8, 0x31,
0x01, 0x46, 0xda, 0x35,
0x01, 0x44, 0xd4, 0x35,
0x10, 0xea, 0x80, 0x00,
- 0x01, 0xe2, 0x62, 0x36,
- 0x04, 0xa6, 0xe4, 0x7b,
+ 0x01, 0xe2, 0x6e, 0x36,
+ 0x04, 0xa6, 0x0e, 0x7c,
0xff, 0xea, 0x5a, 0x09,
0xff, 0xea, 0x4c, 0x0d,
- 0x01, 0xa6, 0x02, 0x6c,
- 0x10, 0xad, 0x64, 0x78,
- 0x80, 0xad, 0xfa, 0x6b,
- 0x08, 0xad, 0x64, 0x68,
+ 0x01, 0xa6, 0x3a, 0x6c,
+ 0x10, 0xad, 0x84, 0x78,
+ 0x80, 0xad, 0x32, 0x6c,
+ 0x08, 0xad, 0x84, 0x68,
+ 0x20, 0x19, 0x26, 0x7c,
+ 0x80, 0xea, 0xb2, 0x01,
+ 0x11, 0x00, 0x00, 0x10,
+ 0x02, 0xa6, 0x22, 0x7c,
+ 0xff, 0xea, 0xb2, 0x0d,
+ 0x11, 0x00, 0x00, 0x10,
+ 0xff, 0xea, 0xb2, 0x09,
0x04, 0x84, 0xf9, 0x30,
0x00, 0xea, 0x08, 0x81,
0xff, 0xea, 0xd4, 0x09,
0x02, 0x84, 0xf9, 0x88,
0x0d, 0xea, 0x5a, 0x01,
0x04, 0xa6, 0x4c, 0x05,
- 0x04, 0xa6, 0x64, 0x78,
+ 0x04, 0xa6, 0x84, 0x78,
0xff, 0xea, 0x5a, 0x09,
0x03, 0x84, 0x59, 0x89,
0x03, 0xea, 0x4c, 0x01,
- 0x80, 0x1a, 0x64, 0x78,
- 0x08, 0x19, 0x64, 0x78,
+ 0x80, 0x1a, 0x84, 0x78,
+ 0x08, 0x19, 0x84, 0x78,
0x08, 0xb0, 0xe0, 0x30,
0x04, 0xb0, 0xe0, 0x30,
0x03, 0xb0, 0xf0, 0x30,
@@ -533,259 +561,259 @@ static uint8_t seqprog[] = {
0x00, 0x86, 0x0d, 0x23,
0x00, 0x87, 0x0f, 0x23,
0x01, 0x84, 0xc5, 0x31,
- 0x80, 0x83, 0x25, 0x7c,
+ 0x80, 0x83, 0x5d, 0x7c,
0x02, 0xe2, 0xc4, 0x01,
0xff, 0xea, 0x4c, 0x09,
0x01, 0xe2, 0x36, 0x30,
0xc8, 0x19, 0x32, 0x00,
0x88, 0x19, 0x32, 0x00,
0x01, 0xac, 0xd4, 0x99,
- 0x00, 0xe2, 0x64, 0x50,
+ 0x00, 0xe2, 0x84, 0x50,
0xfe, 0xa6, 0x4c, 0x0d,
0x0b, 0x98, 0xe1, 0x30,
0xfd, 0xa4, 0x49, 0x09,
- 0x80, 0xa3, 0x39, 0x7c,
+ 0x80, 0xa3, 0x71, 0x7c,
0x02, 0xa4, 0x48, 0x01,
0x01, 0xa4, 0x36, 0x30,
0xa8, 0xea, 0x32, 0x00,
0xfd, 0xa4, 0x49, 0x0b,
0x05, 0xa3, 0x07, 0x33,
- 0x80, 0x83, 0x45, 0x6c,
+ 0x80, 0x83, 0x7d, 0x6c,
0x02, 0xea, 0x4c, 0x05,
0xff, 0xea, 0x4c, 0x0d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x02, 0xa6, 0xe6, 0x6b,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x02, 0xa6, 0x10, 0x6c,
0x80, 0xf9, 0xf2, 0x05,
- 0xc0, 0x33, 0x53, 0x7c,
- 0x03, 0xea, 0x50, 0x59,
+ 0xc0, 0x39, 0x8b, 0x7c,
+ 0x03, 0xea, 0x64, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0x20, 0x33, 0x77, 0x7c,
- 0x01, 0x84, 0x5d, 0x6c,
- 0x06, 0xea, 0x50, 0x59,
+ 0x20, 0x39, 0xaf, 0x7c,
+ 0x01, 0x84, 0x95, 0x6c,
+ 0x06, 0xea, 0x64, 0x59,
0x06, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x7a, 0x44,
- 0x01, 0x00, 0x60, 0x32,
- 0xee, 0x00, 0x66, 0x6c,
+ 0x00, 0xe2, 0xb2, 0x44,
+ 0x01, 0x00, 0x6c, 0x32,
+ 0xee, 0x00, 0x9e, 0x6c,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
0x80, 0x3d, 0x7a, 0x00,
- 0xfc, 0x42, 0x68, 0x7c,
+ 0xfc, 0x42, 0xa0, 0x7c,
0x7f, 0x3d, 0x7a, 0x08,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x09, 0xea, 0x50, 0x59,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x09, 0xea, 0x64, 0x59,
0x09, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x01, 0xa4, 0x5d, 0x6c,
- 0x00, 0xe2, 0x30, 0x5c,
- 0x20, 0x33, 0x67, 0x02,
- 0x01, 0x00, 0x60, 0x32,
- 0x02, 0xa6, 0x82, 0x7c,
- 0x00, 0xe2, 0x46, 0x5c,
- 0x00, 0xe2, 0x56, 0x58,
- 0x00, 0xe2, 0x66, 0x58,
- 0x00, 0xe2, 0x3a, 0x58,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x20, 0x19, 0x82, 0x6c,
- 0x00, 0xe2, 0xb2, 0x5c,
- 0x04, 0x19, 0x9c, 0x6c,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x01, 0xa4, 0x95, 0x6c,
+ 0x00, 0xe2, 0x68, 0x5c,
+ 0x20, 0x39, 0x73, 0x02,
+ 0x01, 0x00, 0x6c, 0x32,
+ 0x02, 0xa6, 0xba, 0x7c,
+ 0x00, 0xe2, 0x7e, 0x5c,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x00, 0xe2, 0x86, 0x58,
+ 0x00, 0xe2, 0x5a, 0x58,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x20, 0x19, 0xba, 0x6c,
+ 0x00, 0xe2, 0xea, 0x5c,
+ 0x04, 0x19, 0xd4, 0x6c,
0x02, 0x19, 0x32, 0x00,
- 0x01, 0x84, 0x9d, 0x7c,
- 0x01, 0x1b, 0x96, 0x7c,
- 0x01, 0x1a, 0x9c, 0x6c,
- 0x00, 0xe2, 0x4c, 0x44,
- 0x80, 0x4b, 0xa2, 0x6c,
- 0x01, 0x4c, 0x9e, 0x7c,
- 0x03, 0x42, 0x4c, 0x6c,
- 0x00, 0xe2, 0xe0, 0x5b,
+ 0x01, 0x84, 0xd5, 0x7c,
+ 0x01, 0x1b, 0xce, 0x7c,
+ 0x01, 0x1a, 0xd4, 0x6c,
+ 0x00, 0xe2, 0x84, 0x44,
+ 0x80, 0x4b, 0xda, 0x6c,
+ 0x01, 0x4c, 0xd6, 0x7c,
+ 0x03, 0x42, 0x84, 0x6c,
+ 0x00, 0xe2, 0x0a, 0x5c,
0x80, 0xf9, 0xf2, 0x01,
- 0x04, 0x33, 0xf9, 0x79,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x08, 0x5d, 0xba, 0x6c,
- 0x00, 0xe2, 0x56, 0x58,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x02, 0x1b, 0xaa, 0x7c,
- 0x08, 0x5d, 0xb8, 0x7c,
+ 0x04, 0x39, 0x15, 0x7a,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x08, 0x5d, 0xf2, 0x6c,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x02, 0x1b, 0xe2, 0x7c,
+ 0x08, 0x5d, 0xf0, 0x7c,
0x03, 0x68, 0x00, 0x37,
0x01, 0x84, 0x09, 0x07,
- 0x80, 0x1b, 0xc4, 0x7c,
- 0x80, 0x84, 0xc5, 0x6c,
+ 0x80, 0x1b, 0xfc, 0x7c,
+ 0x80, 0x84, 0xfd, 0x6c,
0xff, 0x85, 0x0b, 0x1b,
0xff, 0x86, 0x0d, 0x23,
0xff, 0x87, 0x0f, 0x23,
0xf8, 0x1b, 0x08, 0x0b,
0xff, 0xea, 0x06, 0x0b,
0x03, 0x68, 0x00, 0x37,
- 0x00, 0xe2, 0xc4, 0x58,
+ 0x00, 0xe2, 0xd6, 0x58,
0x10, 0xea, 0x18, 0x00,
0xf9, 0xd9, 0xb2, 0x0d,
0x01, 0xd9, 0xb2, 0x05,
0x01, 0x52, 0x48, 0x31,
- 0x20, 0xa4, 0xee, 0x7c,
- 0x20, 0x5b, 0xee, 0x7c,
- 0x80, 0xf9, 0xfc, 0x7c,
+ 0x20, 0xa4, 0x26, 0x7d,
+ 0x20, 0x5b, 0x26, 0x7d,
+ 0x80, 0xf9, 0x34, 0x7d,
0x02, 0xea, 0xb4, 0x00,
0x11, 0x00, 0x00, 0x10,
- 0x04, 0x19, 0x08, 0x7d,
+ 0x04, 0x19, 0x40, 0x7d,
0xdf, 0x19, 0x32, 0x08,
- 0x60, 0x5b, 0xe6, 0x6c,
- 0x01, 0x4c, 0xe2, 0x7c,
+ 0x60, 0x5b, 0x40, 0x6d,
+ 0x01, 0x4c, 0x1a, 0x7d,
0x20, 0x19, 0x32, 0x00,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xea, 0xb4, 0x00,
0x01, 0xd9, 0xb2, 0x05,
- 0x10, 0x5b, 0x00, 0x6d,
- 0x08, 0x5b, 0x0a, 0x6d,
- 0x20, 0x5b, 0xfa, 0x6c,
- 0x02, 0x5b, 0x2a, 0x6d,
- 0x0e, 0xea, 0x50, 0x59,
+ 0x10, 0x5b, 0x38, 0x6d,
+ 0x08, 0x5b, 0x42, 0x6d,
+ 0x20, 0x5b, 0x32, 0x6d,
+ 0x02, 0x5b, 0x62, 0x6d,
+ 0x0e, 0xea, 0x64, 0x59,
0x0e, 0xea, 0x04, 0x00,
- 0x80, 0xf9, 0xea, 0x6c,
+ 0x80, 0xf9, 0x22, 0x6d,
0xdf, 0x5c, 0xb8, 0x08,
0x01, 0xd9, 0xb2, 0x05,
- 0x01, 0xa4, 0xe5, 0x6d,
- 0x00, 0xe2, 0x30, 0x5c,
- 0x00, 0xe2, 0x34, 0x5d,
+ 0x01, 0xa4, 0x1d, 0x6e,
+ 0x00, 0xe2, 0x68, 0x5c,
+ 0x00, 0xe2, 0x6c, 0x5d,
0x01, 0x90, 0x21, 0x1b,
0x01, 0xd9, 0xb2, 0x05,
- 0x00, 0xe2, 0x32, 0x5b,
+ 0x00, 0xe2, 0x52, 0x5b,
0xf3, 0x96, 0xd5, 0x19,
- 0x00, 0xe2, 0x18, 0x55,
- 0x80, 0x96, 0x19, 0x6d,
- 0x0f, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x50, 0x55,
+ 0x80, 0x96, 0x51, 0x6d,
+ 0x0f, 0xea, 0x64, 0x59,
0x0f, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x20, 0x45,
+ 0x00, 0xe2, 0x58, 0x45,
0x04, 0x8c, 0xe1, 0x30,
0x01, 0xea, 0xf2, 0x00,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0xff, 0x97, 0x27, 0x7d,
- 0x14, 0xea, 0x50, 0x59,
+ 0xff, 0x97, 0x5f, 0x7d,
+ 0x14, 0xea, 0x64, 0x59,
0x14, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x96, 0x5d,
+ 0x00, 0xe2, 0xce, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x8e, 0x5d,
+ 0x00, 0xe2, 0xc6, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
- 0x02, 0xa6, 0x44, 0x7d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x20, 0x5b, 0x52, 0x6d,
- 0xfc, 0x42, 0x3e, 0x7d,
- 0x10, 0x40, 0x40, 0x6d,
- 0x20, 0x4d, 0x42, 0x7d,
- 0x08, 0x5d, 0x52, 0x6d,
- 0x02, 0xa6, 0xe6, 0x6b,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x20, 0x5b, 0x52, 0x6d,
- 0x01, 0x1b, 0x72, 0x6d,
- 0xfc, 0x42, 0x4e, 0x7d,
- 0x10, 0x40, 0x50, 0x6d,
- 0x20, 0x4d, 0x64, 0x78,
- 0x08, 0x5d, 0x64, 0x78,
+ 0x02, 0xa6, 0x7c, 0x7d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x20, 0x5b, 0x8a, 0x6d,
+ 0xfc, 0x42, 0x76, 0x7d,
+ 0x10, 0x40, 0x78, 0x6d,
+ 0x20, 0x4d, 0x7a, 0x7d,
+ 0x08, 0x5d, 0x8a, 0x6d,
+ 0x02, 0xa6, 0x10, 0x6c,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x20, 0x5b, 0x8a, 0x6d,
+ 0x01, 0x1b, 0xaa, 0x6d,
+ 0xfc, 0x42, 0x86, 0x7d,
+ 0x10, 0x40, 0x88, 0x6d,
+ 0x20, 0x4d, 0x84, 0x78,
+ 0x08, 0x5d, 0x84, 0x78,
0x02, 0x19, 0x32, 0x00,
0x01, 0x5b, 0x40, 0x31,
- 0x00, 0xe2, 0xb2, 0x5c,
- 0x00, 0xe2, 0x9e, 0x5b,
+ 0x00, 0xe2, 0xea, 0x5c,
+ 0x00, 0xe2, 0xcc, 0x5b,
0x20, 0xea, 0xb6, 0x00,
- 0x00, 0xe2, 0xe0, 0x5b,
+ 0x00, 0xe2, 0x0a, 0x5c,
0x20, 0x5c, 0xb8, 0x00,
- 0x04, 0x19, 0x68, 0x6d,
- 0x01, 0x1a, 0x68, 0x6d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x01, 0x1a, 0x64, 0x78,
+ 0x04, 0x19, 0xa0, 0x6d,
+ 0x01, 0x1a, 0xa0, 0x6d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x01, 0x1a, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
- 0x20, 0xa0, 0xcc, 0x7d,
+ 0x20, 0xa0, 0x04, 0x7e,
0xff, 0x90, 0x21, 0x1b,
- 0x08, 0x92, 0x43, 0x6b,
+ 0x08, 0x92, 0x63, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x01, 0xa4, 0x49, 0x03,
- 0x40, 0x5b, 0x82, 0x6d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x40, 0x5b, 0x82, 0x6d,
- 0x04, 0x5d, 0xe6, 0x7d,
- 0x01, 0x1a, 0xe6, 0x7d,
- 0x20, 0x4d, 0x64, 0x78,
- 0x40, 0x5b, 0xcc, 0x7d,
- 0x04, 0x5d, 0xe6, 0x7d,
- 0x01, 0x1a, 0xe6, 0x7d,
+ 0x40, 0x5b, 0xba, 0x6d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x40, 0x5b, 0xba, 0x6d,
+ 0x04, 0x5d, 0x1e, 0x7e,
+ 0x01, 0x1a, 0x1e, 0x7e,
+ 0x20, 0x4d, 0x84, 0x78,
+ 0x40, 0x5b, 0x04, 0x7e,
+ 0x04, 0x5d, 0x1e, 0x7e,
+ 0x01, 0x1a, 0x1e, 0x7e,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0x90, 0x21, 0x1b,
- 0x08, 0x92, 0x43, 0x6b,
+ 0x08, 0x92, 0x63, 0x6b,
0x02, 0xea, 0xb4, 0x04,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x01, 0x1b, 0x64, 0x78,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x01, 0x1b, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xea, 0xb4, 0x04,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x01, 0x1b, 0xaa, 0x6d,
- 0x40, 0x5b, 0xb8, 0x7d,
- 0x01, 0x1b, 0xaa, 0x6d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x01, 0x1b, 0xe2, 0x6d,
+ 0x40, 0x5b, 0xf0, 0x7d,
+ 0x01, 0x1b, 0xe2, 0x6d,
0x02, 0x19, 0x32, 0x00,
- 0x01, 0x1a, 0x64, 0x78,
+ 0x01, 0x1a, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0xea, 0x10, 0x03,
0x08, 0x92, 0x25, 0x03,
- 0x00, 0xe2, 0x42, 0x43,
- 0x01, 0x1a, 0xb4, 0x7d,
- 0x40, 0x5b, 0xb0, 0x7d,
- 0x01, 0x1a, 0x9e, 0x6d,
- 0xfc, 0x42, 0x64, 0x78,
- 0x01, 0x1a, 0xb8, 0x6d,
- 0x10, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x62, 0x43,
+ 0x01, 0x1a, 0xec, 0x7d,
+ 0x40, 0x5b, 0xe8, 0x7d,
+ 0x01, 0x1a, 0xd6, 0x6d,
+ 0xfc, 0x42, 0x84, 0x78,
+ 0x01, 0x1a, 0xf0, 0x6d,
+ 0x10, 0xea, 0x64, 0x59,
0x10, 0xea, 0x04, 0x00,
- 0xfc, 0x42, 0x64, 0x78,
- 0x10, 0x40, 0xbe, 0x6d,
- 0x20, 0x4d, 0x64, 0x78,
- 0x40, 0x5b, 0x9e, 0x6d,
- 0x01, 0x1a, 0x64, 0x78,
+ 0xfc, 0x42, 0x84, 0x78,
+ 0x10, 0x40, 0xf6, 0x6d,
+ 0x20, 0x4d, 0x84, 0x78,
+ 0x40, 0x5b, 0xd6, 0x6d,
+ 0x01, 0x1a, 0x84, 0x78,
0x01, 0x90, 0x21, 0x1b,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x64, 0x60,
- 0x40, 0x4b, 0x64, 0x68,
+ 0x30, 0xe0, 0x84, 0x60,
+ 0x40, 0x4b, 0x84, 0x68,
0xff, 0xea, 0x52, 0x01,
- 0xee, 0x00, 0xd2, 0x6d,
+ 0xee, 0x00, 0x0c, 0x6e,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0x90, 0x21, 0x1b,
0x02, 0xea, 0xb4, 0x00,
0x20, 0xea, 0x9a, 0x00,
- 0xf3, 0x42, 0xde, 0x6d,
- 0x12, 0xea, 0x50, 0x59,
+ 0xf3, 0x42, 0x16, 0x6e,
+ 0x12, 0xea, 0x64, 0x59,
0x12, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x0d, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x0d, 0xea, 0x64, 0x59,
0x0d, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
+ 0x00, 0xe2, 0x14, 0x42,
0x01, 0x90, 0x21, 0x1b,
- 0x11, 0xea, 0x50, 0x59,
+ 0x11, 0xea, 0x64, 0x59,
0x11, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x32, 0x5b,
+ 0x00, 0xe2, 0x52, 0x5b,
0x08, 0x5a, 0xb4, 0x00,
- 0x00, 0xe2, 0x0c, 0x5e,
+ 0x00, 0xe2, 0x44, 0x5e,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x80, 0x1a, 0xfa, 0x7d,
- 0x00, 0xe2, 0x0c, 0x5e,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x80, 0x1a, 0x32, 0x7e,
+ 0x00, 0xe2, 0x44, 0x5e,
0x80, 0x19, 0x32, 0x00,
- 0x40, 0x5b, 0x00, 0x6e,
- 0x08, 0x5a, 0x00, 0x7e,
- 0x20, 0x4d, 0x64, 0x78,
+ 0x40, 0x5b, 0x38, 0x6e,
+ 0x08, 0x5a, 0x38, 0x7e,
+ 0x20, 0x4d, 0x84, 0x78,
0x02, 0x84, 0x09, 0x03,
- 0x40, 0x5b, 0xcc, 0x7d,
+ 0x40, 0x5b, 0x04, 0x7e,
0xff, 0x90, 0x21, 0x1b,
0x80, 0xf9, 0xf2, 0x01,
- 0x08, 0x92, 0x43, 0x6b,
+ 0x08, 0x92, 0x63, 0x6b,
0x02, 0xea, 0xb4, 0x04,
- 0x01, 0x38, 0xe1, 0x30,
- 0x05, 0x39, 0xe3, 0x98,
+ 0x01, 0x40, 0xe1, 0x30,
+ 0x05, 0x41, 0xe3, 0x98,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
- 0x00, 0x3a, 0xe5, 0x20,
- 0x00, 0x3b, 0xe7, 0x20,
+ 0x00, 0x42, 0xe5, 0x20,
+ 0x00, 0x43, 0xe7, 0x20,
0x01, 0xfa, 0xc0, 0x31,
0x04, 0xea, 0xe8, 0x30,
0xff, 0xea, 0xf0, 0x08,
@@ -794,12 +822,20 @@ static uint8_t seqprog[] = {
};
typedef int ahd_patch_func_t (struct ahd_softc *ahd);
+static ahd_patch_func_t ahd_patch23_func;
+
+static int
+ahd_patch23_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+}
+
static ahd_patch_func_t ahd_patch22_func;
static int
ahd_patch22_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+ return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
}
static ahd_patch_func_t ahd_patch21_func;
@@ -807,7 +843,7 @@ static ahd_patch_func_t ahd_patch21_func;
static int
ahd_patch21_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
+ return ((ahd->flags & AHD_INITIATORROLE) != 0);
}
static ahd_patch_func_t ahd_patch20_func;
@@ -815,7 +851,7 @@ static ahd_patch_func_t ahd_patch20_func;
static int
ahd_patch20_func(struct ahd_softc *ahd)
{
- return ((ahd->features & AHD_RTI) == 0);
+ return ((ahd->flags & AHD_TARGETROLE) != 0);
}
static ahd_patch_func_t ahd_patch19_func;
@@ -823,7 +859,7 @@ static ahd_patch_func_t ahd_patch19_func;
static int
ahd_patch19_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_INITIATORROLE) != 0);
+ return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
}
static ahd_patch_func_t ahd_patch18_func;
@@ -831,7 +867,7 @@ static ahd_patch_func_t ahd_patch18_func;
static int
ahd_patch18_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_TARGETROLE) != 0);
+ return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
}
static ahd_patch_func_t ahd_patch17_func;
@@ -839,7 +875,7 @@ static ahd_patch_func_t ahd_patch17_func;
static int
ahd_patch17_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
+ return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
}
static ahd_patch_func_t ahd_patch16_func;
@@ -847,7 +883,7 @@ static ahd_patch_func_t ahd_patch16_func;
static int
ahd_patch16_func(struct ahd_softc *ahd)
{
- return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
+ return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
}
static ahd_patch_func_t ahd_patch15_func;
@@ -855,7 +891,7 @@ static ahd_patch_func_t ahd_patch15_func;
static int
ahd_patch15_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
+ return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
}
static ahd_patch_func_t ahd_patch14_func;
@@ -863,7 +899,7 @@ static ahd_patch_func_t ahd_patch14_func;
static int
ahd_patch14_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
+ return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
}
static ahd_patch_func_t ahd_patch13_func;
@@ -871,7 +907,7 @@ static ahd_patch_func_t ahd_patch13_func;
static int
ahd_patch13_func(struct ahd_softc *ahd)
{
- return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
+ return ((ahd->features & AHD_RTI) == 0);
}
static ahd_patch_func_t ahd_patch12_func;
@@ -879,7 +915,7 @@ static ahd_patch_func_t ahd_patch12_func;
static int
ahd_patch12_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
+ return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
}
static ahd_patch_func_t ahd_patch11_func;
@@ -887,7 +923,7 @@ static ahd_patch_func_t ahd_patch11_func;
static int
ahd_patch11_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
+ return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
}
static ahd_patch_func_t ahd_patch10_func;
@@ -895,7 +931,7 @@ static ahd_patch_func_t ahd_patch10_func;
static int
ahd_patch10_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
+ return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
}
static ahd_patch_func_t ahd_patch9_func;
@@ -903,7 +939,7 @@ static ahd_patch_func_t ahd_patch9_func;
static int
ahd_patch9_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
+ return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0);
}
static ahd_patch_func_t ahd_patch8_func;
@@ -992,147 +1028,149 @@ static struct patch {
{ ahd_patch0_func, 5, 1, 1 },
{ ahd_patch2_func, 6, 1, 2 },
{ ahd_patch0_func, 7, 1, 1 },
- { ahd_patch3_func, 20, 5, 1 },
- { ahd_patch2_func, 29, 1, 2 },
- { ahd_patch0_func, 30, 1, 1 },
- { ahd_patch1_func, 37, 1, 2 },
- { ahd_patch0_func, 38, 1, 1 },
- { ahd_patch2_func, 43, 1, 2 },
- { ahd_patch0_func, 44, 1, 1 },
- { ahd_patch2_func, 47, 1, 2 },
- { ahd_patch0_func, 48, 1, 1 },
- { ahd_patch2_func, 51, 1, 2 },
- { ahd_patch0_func, 52, 1, 1 },
- { ahd_patch2_func, 65, 1, 2 },
- { ahd_patch0_func, 66, 1, 1 },
- { ahd_patch2_func, 69, 1, 2 },
- { ahd_patch0_func, 70, 1, 1 },
- { ahd_patch1_func, 73, 1, 2 },
- { ahd_patch0_func, 74, 1, 1 },
- { ahd_patch4_func, 107, 1, 1 },
- { ahd_patch2_func, 162, 6, 1 },
- { ahd_patch1_func, 168, 2, 1 },
- { ahd_patch5_func, 170, 1, 1 },
- { ahd_patch2_func, 179, 1, 2 },
- { ahd_patch0_func, 180, 1, 1 },
- { ahd_patch6_func, 181, 2, 2 },
- { ahd_patch0_func, 183, 6, 3 },
- { ahd_patch2_func, 186, 1, 2 },
- { ahd_patch0_func, 187, 1, 1 },
- { ahd_patch2_func, 190, 1, 2 },
- { ahd_patch0_func, 191, 1, 1 },
- { ahd_patch7_func, 193, 2, 1 },
- { ahd_patch5_func, 201, 16, 2 },
- { ahd_patch0_func, 217, 1, 1 },
- { ahd_patch8_func, 237, 2, 1 },
- { ahd_patch1_func, 241, 1, 2 },
- { ahd_patch0_func, 242, 1, 1 },
- { ahd_patch7_func, 245, 2, 1 },
- { ahd_patch1_func, 259, 1, 2 },
- { ahd_patch0_func, 260, 1, 1 },
- { ahd_patch1_func, 263, 1, 2 },
- { ahd_patch0_func, 264, 1, 1 },
- { ahd_patch2_func, 267, 1, 2 },
- { ahd_patch0_func, 268, 1, 1 },
- { ahd_patch1_func, 323, 1, 2 },
- { ahd_patch0_func, 324, 1, 1 },
- { ahd_patch2_func, 332, 1, 2 },
- { ahd_patch0_func, 333, 1, 1 },
- { ahd_patch2_func, 336, 1, 2 },
- { ahd_patch0_func, 337, 1, 1 },
- { ahd_patch1_func, 343, 1, 2 },
- { ahd_patch0_func, 344, 1, 1 },
- { ahd_patch1_func, 346, 1, 2 },
- { ahd_patch0_func, 347, 1, 1 },
- { ahd_patch9_func, 366, 1, 1 },
- { ahd_patch9_func, 369, 1, 1 },
- { ahd_patch9_func, 371, 1, 1 },
- { ahd_patch9_func, 383, 1, 1 },
- { ahd_patch1_func, 393, 1, 2 },
- { ahd_patch0_func, 394, 1, 1 },
- { ahd_patch1_func, 396, 1, 2 },
- { ahd_patch0_func, 397, 1, 1 },
- { ahd_patch1_func, 405, 1, 2 },
- { ahd_patch0_func, 406, 1, 1 },
- { ahd_patch2_func, 419, 1, 2 },
- { ahd_patch0_func, 420, 1, 1 },
- { ahd_patch10_func, 450, 1, 1 },
- { ahd_patch1_func, 457, 1, 2 },
- { ahd_patch0_func, 458, 1, 1 },
- { ahd_patch2_func, 470, 1, 2 },
- { ahd_patch0_func, 471, 1, 1 },
- { ahd_patch11_func, 476, 6, 2 },
- { ahd_patch0_func, 482, 1, 1 },
- { ahd_patch12_func, 505, 1, 1 },
- { ahd_patch13_func, 514, 1, 1 },
- { ahd_patch14_func, 515, 1, 2 },
- { ahd_patch0_func, 516, 1, 1 },
- { ahd_patch15_func, 519, 1, 1 },
- { ahd_patch14_func, 520, 1, 1 },
- { ahd_patch16_func, 531, 1, 2 },
- { ahd_patch0_func, 532, 1, 1 },
- { ahd_patch1_func, 551, 1, 2 },
- { ahd_patch0_func, 552, 1, 1 },
- { ahd_patch1_func, 555, 1, 2 },
- { ahd_patch0_func, 556, 1, 1 },
- { ahd_patch2_func, 561, 1, 2 },
- { ahd_patch0_func, 562, 1, 1 },
- { ahd_patch2_func, 566, 1, 2 },
- { ahd_patch0_func, 567, 1, 1 },
- { ahd_patch1_func, 568, 1, 2 },
- { ahd_patch0_func, 569, 1, 1 },
- { ahd_patch2_func, 580, 1, 2 },
- { ahd_patch0_func, 581, 1, 1 },
- { ahd_patch17_func, 585, 1, 1 },
- { ahd_patch18_func, 590, 1, 1 },
- { ahd_patch19_func, 591, 2, 1 },
- { ahd_patch18_func, 595, 1, 2 },
- { ahd_patch0_func, 596, 1, 1 },
- { ahd_patch2_func, 599, 1, 2 },
- { ahd_patch0_func, 600, 1, 1 },
- { ahd_patch2_func, 615, 1, 2 },
- { ahd_patch0_func, 616, 1, 1 },
- { ahd_patch20_func, 617, 14, 1 },
- { ahd_patch1_func, 635, 1, 2 },
- { ahd_patch0_func, 636, 1, 1 },
- { ahd_patch20_func, 637, 1, 1 },
- { ahd_patch1_func, 649, 1, 2 },
- { ahd_patch0_func, 650, 1, 1 },
- { ahd_patch1_func, 657, 1, 2 },
- { ahd_patch0_func, 658, 1, 1 },
- { ahd_patch17_func, 681, 1, 1 },
- { ahd_patch17_func, 719, 1, 1 },
- { ahd_patch1_func, 730, 1, 2 },
- { ahd_patch0_func, 731, 1, 1 },
- { ahd_patch1_func, 748, 1, 2 },
- { ahd_patch0_func, 749, 1, 1 },
- { ahd_patch1_func, 751, 1, 2 },
- { ahd_patch0_func, 752, 1, 1 },
- { ahd_patch1_func, 755, 1, 2 },
- { ahd_patch0_func, 756, 1, 1 },
- { ahd_patch21_func, 758, 1, 2 },
- { ahd_patch0_func, 759, 2, 1 },
- { ahd_patch22_func, 762, 4, 2 },
- { ahd_patch0_func, 766, 1, 1 },
- { ahd_patch22_func, 774, 11, 1 }
+ { ahd_patch3_func, 36, 5, 1 },
+ { ahd_patch2_func, 45, 1, 2 },
+ { ahd_patch0_func, 46, 1, 1 },
+ { ahd_patch1_func, 53, 1, 2 },
+ { ahd_patch0_func, 54, 1, 1 },
+ { ahd_patch2_func, 59, 1, 2 },
+ { ahd_patch0_func, 60, 1, 1 },
+ { ahd_patch2_func, 63, 1, 2 },
+ { ahd_patch0_func, 64, 1, 1 },
+ { ahd_patch2_func, 67, 1, 2 },
+ { ahd_patch0_func, 68, 1, 1 },
+ { ahd_patch4_func, 116, 1, 1 },
+ { ahd_patch2_func, 175, 3, 1 },
+ { ahd_patch1_func, 178, 2, 1 },
+ { ahd_patch5_func, 180, 1, 1 },
+ { ahd_patch2_func, 189, 1, 2 },
+ { ahd_patch0_func, 190, 1, 1 },
+ { ahd_patch6_func, 191, 2, 2 },
+ { ahd_patch0_func, 193, 6, 3 },
+ { ahd_patch2_func, 196, 1, 2 },
+ { ahd_patch0_func, 197, 1, 1 },
+ { ahd_patch2_func, 200, 1, 2 },
+ { ahd_patch0_func, 201, 1, 1 },
+ { ahd_patch3_func, 203, 1, 1 },
+ { ahd_patch7_func, 204, 3, 1 },
+ { ahd_patch3_func, 213, 1, 1 },
+ { ahd_patch5_func, 214, 16, 2 },
+ { ahd_patch0_func, 230, 1, 1 },
+ { ahd_patch8_func, 250, 2, 1 },
+ { ahd_patch1_func, 254, 1, 2 },
+ { ahd_patch0_func, 255, 1, 1 },
+ { ahd_patch7_func, 258, 3, 1 },
+ { ahd_patch1_func, 273, 1, 2 },
+ { ahd_patch0_func, 274, 1, 1 },
+ { ahd_patch1_func, 277, 1, 2 },
+ { ahd_patch0_func, 278, 1, 1 },
+ { ahd_patch2_func, 281, 1, 2 },
+ { ahd_patch0_func, 282, 1, 1 },
+ { ahd_patch9_func, 295, 2, 2 },
+ { ahd_patch0_func, 297, 1, 1 },
+ { ahd_patch1_func, 339, 1, 2 },
+ { ahd_patch0_func, 340, 1, 1 },
+ { ahd_patch2_func, 348, 1, 2 },
+ { ahd_patch0_func, 349, 1, 1 },
+ { ahd_patch2_func, 352, 1, 2 },
+ { ahd_patch0_func, 353, 1, 1 },
+ { ahd_patch1_func, 359, 1, 2 },
+ { ahd_patch0_func, 360, 1, 1 },
+ { ahd_patch1_func, 362, 1, 2 },
+ { ahd_patch0_func, 363, 1, 1 },
+ { ahd_patch10_func, 382, 1, 1 },
+ { ahd_patch10_func, 385, 1, 1 },
+ { ahd_patch10_func, 387, 1, 1 },
+ { ahd_patch10_func, 399, 1, 1 },
+ { ahd_patch1_func, 409, 1, 2 },
+ { ahd_patch0_func, 410, 1, 1 },
+ { ahd_patch1_func, 412, 1, 2 },
+ { ahd_patch0_func, 413, 1, 1 },
+ { ahd_patch1_func, 421, 1, 2 },
+ { ahd_patch0_func, 422, 1, 1 },
+ { ahd_patch2_func, 435, 1, 2 },
+ { ahd_patch0_func, 436, 1, 1 },
+ { ahd_patch11_func, 472, 1, 1 },
+ { ahd_patch1_func, 480, 1, 2 },
+ { ahd_patch0_func, 481, 1, 1 },
+ { ahd_patch2_func, 493, 1, 2 },
+ { ahd_patch0_func, 494, 1, 1 },
+ { ahd_patch12_func, 497, 6, 2 },
+ { ahd_patch0_func, 503, 1, 1 },
+ { ahd_patch13_func, 524, 7, 1 },
+ { ahd_patch14_func, 533, 1, 1 },
+ { ahd_patch15_func, 542, 1, 1 },
+ { ahd_patch16_func, 543, 1, 2 },
+ { ahd_patch0_func, 544, 1, 1 },
+ { ahd_patch17_func, 547, 1, 1 },
+ { ahd_patch16_func, 548, 1, 1 },
+ { ahd_patch18_func, 559, 1, 2 },
+ { ahd_patch0_func, 560, 1, 1 },
+ { ahd_patch1_func, 579, 1, 2 },
+ { ahd_patch0_func, 580, 1, 1 },
+ { ahd_patch1_func, 583, 1, 2 },
+ { ahd_patch0_func, 584, 1, 1 },
+ { ahd_patch2_func, 589, 1, 2 },
+ { ahd_patch0_func, 590, 1, 1 },
+ { ahd_patch2_func, 594, 1, 2 },
+ { ahd_patch0_func, 595, 1, 1 },
+ { ahd_patch1_func, 596, 1, 2 },
+ { ahd_patch0_func, 597, 1, 1 },
+ { ahd_patch2_func, 608, 1, 2 },
+ { ahd_patch0_func, 609, 1, 1 },
+ { ahd_patch19_func, 613, 1, 1 },
+ { ahd_patch20_func, 618, 1, 1 },
+ { ahd_patch21_func, 619, 2, 1 },
+ { ahd_patch20_func, 623, 1, 2 },
+ { ahd_patch0_func, 624, 1, 1 },
+ { ahd_patch2_func, 627, 1, 2 },
+ { ahd_patch0_func, 628, 1, 1 },
+ { ahd_patch2_func, 643, 1, 2 },
+ { ahd_patch0_func, 644, 1, 1 },
+ { ahd_patch13_func, 645, 14, 1 },
+ { ahd_patch1_func, 663, 1, 2 },
+ { ahd_patch0_func, 664, 1, 1 },
+ { ahd_patch13_func, 665, 1, 1 },
+ { ahd_patch1_func, 677, 1, 2 },
+ { ahd_patch0_func, 678, 1, 1 },
+ { ahd_patch1_func, 685, 1, 2 },
+ { ahd_patch0_func, 686, 1, 1 },
+ { ahd_patch19_func, 709, 1, 1 },
+ { ahd_patch19_func, 747, 1, 1 },
+ { ahd_patch1_func, 758, 1, 2 },
+ { ahd_patch0_func, 759, 1, 1 },
+ { ahd_patch1_func, 776, 1, 2 },
+ { ahd_patch0_func, 777, 1, 1 },
+ { ahd_patch1_func, 779, 1, 2 },
+ { ahd_patch0_func, 780, 1, 1 },
+ { ahd_patch1_func, 783, 1, 2 },
+ { ahd_patch0_func, 784, 1, 1 },
+ { ahd_patch22_func, 786, 1, 2 },
+ { ahd_patch0_func, 787, 2, 1 },
+ { ahd_patch23_func, 790, 4, 2 },
+ { ahd_patch0_func, 794, 1, 1 },
+ { ahd_patch23_func, 802, 11, 1 }
};
static struct cs {
uint16_t begin;
uint16_t end;
} critical_sections[] = {
- { 11, 12 },
- { 13, 14 },
- { 29, 42 },
- { 56, 59 },
- { 101, 128 },
- { 129, 157 },
- { 159, 162 },
- { 170, 178 },
- { 201, 250 },
- { 681, 697 },
- { 697, 711 },
- { 721, 725 }
+ { 17, 28 },
+ { 29, 30 },
+ { 47, 58 },
+ { 61, 63 },
+ { 65, 66 },
+ { 72, 92 },
+ { 110, 137 },
+ { 138, 175 },
+ { 180, 188 },
+ { 213, 264 },
+ { 425, 433 },
+ { 443, 445 },
+ { 448, 457 },
+ { 709, 739 },
+ { 749, 753 }
};
static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index fd389e9f9460..051970efba68 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -375,7 +375,7 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
struct scsi_cmnd *cmd);
static void ahc_linux_sem_timeout(u_long arg);
static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
-static void ahc_linux_release_simq(u_long arg);
+static void ahc_linux_release_simq(struct ahc_softc *ahc);
static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
@@ -1073,7 +1073,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
return (ENOMEM);
*((struct ahc_softc **)host->hostdata) = ahc;
- ahc_lock(ahc, &s);
ahc->platform_data->host = host;
host->can_queue = AHC_MAX_QUEUE;
host->cmd_per_lun = 2;
@@ -1084,7 +1083,9 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
host->max_lun = AHC_NUM_LUNS;
host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
host->sg_tablesize = AHC_NSEG;
+ ahc_lock(ahc, &s);
ahc_set_unit(ahc, ahc_linux_unit++);
+ ahc_unlock(ahc, &s);
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (new_name != NULL) {
@@ -1094,7 +1095,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
host->unique_id = ahc->unit;
ahc_linux_initialize_scsi_bus(ahc);
ahc_intr_enable(ahc, TRUE);
- ahc_unlock(ahc, &s);
host->transportt = ahc_linux_transport_template;
@@ -1120,10 +1120,13 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
{
int i;
int numtarg;
+ unsigned long s;
i = 0;
numtarg = 0;
+ ahc_lock(ahc, &s);
+
if (aic7xxx_no_reset != 0)
ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);
@@ -1170,16 +1173,12 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
ahc_update_neg_request(ahc, &devinfo, tstate,
tinfo, AHC_NEG_ALWAYS);
}
+ ahc_unlock(ahc, &s);
/* Give the bus some time to recover */
if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
ahc_linux_freeze_simq(ahc);
- init_timer(&ahc->platform_data->reset_timer);
- ahc->platform_data->reset_timer.data = (u_long)ahc;
- ahc->platform_data->reset_timer.expires =
- jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
- ahc->platform_data->reset_timer.function =
- ahc_linux_release_simq;
- add_timer(&ahc->platform_data->reset_timer);
+ msleep(AIC7XXX_RESET_DELAY);
+ ahc_linux_release_simq(ahc);
}
}
@@ -2059,6 +2058,9 @@ ahc_linux_sem_timeout(u_long arg)
static void
ahc_linux_freeze_simq(struct ahc_softc *ahc)
{
+ unsigned long s;
+
+ ahc_lock(ahc, &s);
ahc->platform_data->qfrozen++;
if (ahc->platform_data->qfrozen == 1) {
scsi_block_requests(ahc->platform_data->host);
@@ -2068,17 +2070,15 @@ ahc_linux_freeze_simq(struct ahc_softc *ahc)
CAM_LUN_WILDCARD, SCB_LIST_NULL,
ROLE_INITIATOR, CAM_REQUEUE_REQ);
}
+ ahc_unlock(ahc, &s);
}
static void
-ahc_linux_release_simq(u_long arg)
+ahc_linux_release_simq(struct ahc_softc *ahc)
{
- struct ahc_softc *ahc;
u_long s;
int unblock_reqs;
- ahc = (struct ahc_softc *)arg;
-
unblock_reqs = 0;
ahc_lock(ahc, &s);
if (ahc->platform_data->qfrozen > 0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index f2a95447142c..e0edacae895f 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -223,9 +223,6 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
*/
#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op)
-/************************** Timer DataStructures ******************************/
-typedef struct timer_list ahc_timer_t;
-
/********************************** Includes **********************************/
#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
#define AIC_DEBUG_REGISTERS 1
@@ -235,30 +232,9 @@ typedef struct timer_list ahc_timer_t;
#include "aic7xxx.h"
/***************************** Timer Facilities *******************************/
-#define ahc_timer_init init_timer
-#define ahc_timer_stop del_timer_sync
-typedef void ahc_linux_callback_t (u_long);
-static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
- ahc_callback_t *func, void *arg);
-static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec);
-
-static __inline void
-ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg)
-{
- struct ahc_softc *ahc;
-
- ahc = (struct ahc_softc *)arg;
- del_timer(timer);
- timer->data = (u_long)arg;
- timer->expires = jiffies + (usec * HZ)/1000000;
- timer->function = (ahc_linux_callback_t*)func;
- add_timer(timer);
-}
-
static __inline void
ahc_scb_timer_reset(struct scb *scb, u_int usec)
{
- mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
}
/***************************** SMP support ************************************/
@@ -393,7 +369,6 @@ struct ahc_platform_data {
spinlock_t spin_lock;
u_int qfrozen;
- struct timer_list reset_timer;
struct semaphore eh_sem;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHC_LINUX_NOIRQ ((uint32_t)~0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index b3b2e2237eb3..5f586140e057 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -39,9 +39,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_pci.c#69 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $
*/
#ifdef __linux__
@@ -393,6 +391,12 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
ahc_aic7892_setup
},
+ {
+ ID_AHA_2915_30LP,
+ ID_ALL_MASK,
+ "Adaptec 2915/30LP Ultra160 SCSI adapter",
+ ahc_aic7892_setup
+ },
/* aic7895 based controllers */
{
ID_AHA_2940U_DUAL,
@@ -1193,9 +1197,19 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* use for this test.
*/
hcntrl = ahc_inb(ahc, HCNTRL);
+
if (hcntrl == 0xFF)
goto fail;
+ if ((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;
+ }
+
/*
* Next create a situation where write combining
* or read prefetching could be initiated by the
@@ -1307,6 +1321,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
sd.sd_chip = C56_66;
}
ahc_release_seeprom(&sd);
+
+ /* Remember the SEEPROM type for later */
+ if (sd.sd_chip == C56_66)
+ ahc->flags |= AHC_LARGE_SEEPROM;
}
if (!have_seeprom) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.h b/drivers/scsi/aic7xxx/aic7xxx_pci.h
index be27fcb20346..263f85da405e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.h
@@ -105,6 +105,7 @@
#define ID_AHA_29160C 0x0080900562209005ull
#define ID_AHA_29160B 0x00809005E2209005ull
#define ID_AHA_19160B 0x0081900562A19005ull
+#define ID_AHA_2915_30LP 0x0082900502109005ull
#define ID_AIC7896 0x005F9005FFFF9005ull
#define ID_AIC7896_ARO 0x00539005FFFF9005ull
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 33d56c344944..770f1647e4d6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -1290,7 +1290,7 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);
*
***************************************************************************/
-static inline unsigned char
+static unsigned char
aic_inb(struct aic7xxx_host *p, long port)
{
#ifdef MMAPIO
@@ -1309,7 +1309,7 @@ aic_inb(struct aic7xxx_host *p, long port)
#endif
}
-static inline void
+static void
aic_outb(struct aic7xxx_host *p, unsigned char val, long port)
{
#ifdef MMAPIO
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 09ed05727bcb..dda5a5f79c53 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -146,7 +146,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/ecard.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 804125e35fc3..a28940156703 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -33,7 +33,6 @@
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/ecard.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 81e266be26d0..e6c9491dc5c0 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -13,7 +13,6 @@
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/system.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 3a7a46b0dc41..583d2d8c8335 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -31,7 +31,6 @@
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 4d1e8f52c924..3ffec7efc9d5 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -35,7 +35,6 @@
#include <linux/dma-mapping.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/pgtable.h>
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 3333d7b39139..3113bdcedb13 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -22,7 +22,6 @@
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include "../scsi.h"
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 557788ec4eec..fc3ca051ceed 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -157,6 +157,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ } /* terminate list */
};
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
index 763e409a1ff3..3867ac2de4c2 100644
--- a/drivers/scsi/blz1230.c
+++ b/drivers/scsi/blz1230.c
@@ -224,7 +224,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void dma_dump_state(struct NCR_ESP *esp)
{
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -298,7 +298,7 @@ static int dma_irq_p(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
index d72d05fffdfa..4ebe69e32756 100644
--- a/drivers/scsi/blz2060.c
+++ b/drivers/scsi/blz2060.c
@@ -190,7 +190,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void dma_dump_state(struct NCR_ESP *esp)
{
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -251,7 +251,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 0920220f3313..c3f27285db1b 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,9 +20,9 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/chio.h> /* here are all the ioctls */
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -112,7 +112,7 @@ typedef struct {
u_int counts[CH_TYPES];
u_int unit_attention;
u_int voltags;
- struct semaphore lock;
+ struct mutex lock;
} scsi_changer;
static LIST_HEAD(ch_devlist);
@@ -566,7 +566,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
u_char data[16];
unsigned int i;
- down(&ch->lock);
+ mutex_lock(&ch->lock);
for (i = 0; i < ch->counts[type]; i++) {
if (0 != ch_read_element_status
(ch, ch->firsts[type]+i,data)) {
@@ -583,7 +583,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
if (0 != retval)
break;
}
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -688,11 +688,11 @@ static int ch_ioctl(struct inode * inode, struct file * file,
dprintk("CHIOPOSITION: invalid parameter\n");
return -EBADSLT;
}
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_position(ch,0,
ch->firsts[pos.cp_type] + pos.cp_unit,
pos.cp_flags & CP_INVERT);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -709,12 +709,12 @@ static int ch_ioctl(struct inode * inode, struct file * file,
return -EBADSLT;
}
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_move(ch,0,
ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
ch->firsts[mv.cm_totype] + mv.cm_tounit,
mv.cm_flags & CM_INVERT);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -732,14 +732,14 @@ static int ch_ioctl(struct inode * inode, struct file * file,
return -EBADSLT;
}
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_exchange
(ch,0,
ch->firsts[mv.ce_srctype] + mv.ce_srcunit,
ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -773,7 +773,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
return -ENOMEM;
- down(&ch->lock);
+ mutex_lock(&ch->lock);
voltag_retry:
memset(cmd,0,sizeof(cmd));
@@ -824,7 +824,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
goto voltag_retry;
}
kfree(buffer);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
if (copy_to_user(argp, &cge, sizeof (cge)))
return -EFAULT;
@@ -833,9 +833,9 @@ static int ch_ioctl(struct inode * inode, struct file * file,
case CHIOINITELEM:
{
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_init_elem(ch);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -852,12 +852,12 @@ static int ch_ioctl(struct inode * inode, struct file * file,
return -EBADSLT;
}
elem = ch->firsts[csv.csv_type] + csv.csv_unit;
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_set_voltag(ch, elem,
csv.csv_flags & CSV_AVOLTAG,
csv.csv_flags & CSV_CLEARTAG,
csv.csv_voltag);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -930,7 +930,7 @@ static int ch_probe(struct device *dev)
memset(ch,0,sizeof(*ch));
ch->minor = ch_devcount;
sprintf(ch->name,"ch%d",ch->minor);
- init_MUTEX(&ch->lock);
+ mutex_init(&ch->lock);
ch->device = sd;
ch_readconfig(ch);
if (init)
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
index f9b940e56430..a4a4fac5c0a1 100644
--- a/drivers/scsi/cyberstorm.c
+++ b/drivers/scsi/cyberstorm.c
@@ -223,7 +223,7 @@ static void dma_dump_state(struct NCR_ESP *esp)
esp->esp_id, ((struct cyber_dma_registers *)
(esp->dregs))->cond_reg));
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -322,7 +322,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
index a3caabfd7557..3a803d73bc5f 100644
--- a/drivers/scsi/cyberstormII.c
+++ b/drivers/scsi/cyberstormII.c
@@ -200,7 +200,7 @@ static void dma_dump_state(struct NCR_ESP *esp)
esp->esp_id, ((struct cyberII_dma_registers *)
(esp->dregs))->cond_reg));
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -259,7 +259,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 6252b9ddc01e..6e6b293dcb28 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -61,6 +61,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/ioport.h>
+#include <linux/mutex.h>
#include <asm/processor.h> /* for boot_cpu_data */
#include <asm/pgtable.h>
@@ -106,7 +107,7 @@ static dpt_sig_S DPTI_sig = {
*============================================================================
*/
-static DECLARE_MUTEX(adpt_configuration_lock);
+static DEFINE_MUTEX(adpt_configuration_lock);
static struct i2o_sys_tbl *sys_tbl = NULL;
static int sys_tbl_ind = 0;
@@ -537,13 +538,13 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of
*/
// Find HBA (host bus adapter) we are looking for
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->host == host) {
break; /* found adapter */
}
}
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
if (pHba == NULL) {
return 0;
}
@@ -898,6 +899,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
if(pci_enable_device(pDev)) {
return -EINVAL;
}
+
+ if (pci_request_regions(pDev, "dpt_i2o")) {
+ PERROR("dpti: adpt_config_hba: pci request region failed\n");
+ return -EINVAL;
+ }
+
pci_set_master(pDev);
if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) &&
pci_set_dma_mask(pDev, 0xffffffffULL))
@@ -923,10 +930,6 @@ 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);
@@ -958,7 +961,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
}
memset(pHba, 0, sizeof(adpt_hba));
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
if(hba_chain != NULL){
for(p = hba_chain; p->next; p = p->next);
@@ -971,7 +974,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
sprintf(pHba->name, "dpti%d", hba_count);
hba_count++;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
pHba->pDev = pDev;
pHba->base_addr_phys = base_addr0_phys;
@@ -1027,7 +1030,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
struct adpt_device* pNext;
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
// scsi_unregister calls our adpt_release which
// does a quiese
if(pHba->host){
@@ -1046,7 +1049,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
}
hba_count--;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
iounmap(pHba->base_addr_virt);
pci_release_regions(pHba->pDev);
@@ -1549,7 +1552,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
{
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
d->controller=pHba;
d->owner=NULL;
d->next=pHba->devices;
@@ -1560,7 +1563,7 @@ static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
pHba->devices=d;
*d->dev_name = 0;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
return 0;
}
@@ -1575,24 +1578,24 @@ static int adpt_open(struct inode *inode, struct file *file)
if (minor >= hba_count) {
return -ENXIO;
}
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->unit == minor) {
break; /* found adapter */
}
}
if (pHba == NULL) {
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
return -ENXIO;
}
// if(pHba->in_use){
- // up(&adpt_configuration_lock);
+ // mutex_unlock(&adpt_configuration_lock);
// return -EBUSY;
// }
pHba->in_use = 1;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
return 0;
}
@@ -1606,13 +1609,13 @@ static int adpt_close(struct inode *inode, struct file *file)
if (minor >= hba_count) {
return -ENXIO;
}
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->unit == minor) {
break; /* found adapter */
}
}
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
if (pHba == NULL) {
return -ENXIO;
}
@@ -1910,13 +1913,13 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
if (minor >= DPTI_MAX_HBA){
return -ENXIO;
}
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->unit == minor) {
break; /* found adapter */
}
}
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
if(pHba == NULL){
return -ENXIO;
}
diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
index ccee68b52f7e..8ae9c406a83b 100644
--- a/drivers/scsi/fastlane.c
+++ b/drivers/scsi/fastlane.c
@@ -268,7 +268,7 @@ static void dma_dump_state(struct NCR_ESP *esp)
esp->esp_id, ((struct fastlane_dma_registers *)
(esp->dregs))->cond_reg));
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -368,7 +368,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index a6deb016584c..bd3ffdf6c800 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -328,7 +328,7 @@
* hdr_channel:x x - number of virtual bus for host drives
* shared_access:Y disable driver reserve/release protocol to
* access a shared resource from several nodes,
- * appropiate controller firmware required
+ * appropriate controller firmware required
* shared_access:N enable driver reserve/release protocol
* probe_eisa_isa:Y scan for EISA/ISA controllers
* probe_eisa_isa:N do not scan for EISA/ISA controllers
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 66783c860a19..588107923499 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -156,16 +156,16 @@ EXPORT_SYMBOL(scsi_host_set_state);
void scsi_remove_host(struct Scsi_Host *shost)
{
unsigned long flags;
- down(&shost->scan_mutex);
+ mutex_lock(&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);
+ mutex_unlock(&shost->scan_mutex);
return;
}
spin_unlock_irqrestore(shost->host_lock, flags);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
scsi_forget_host(shost);
scsi_proc_host_rm(shost);
@@ -320,7 +320,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
INIT_LIST_HEAD(&shost->starved_list);
init_waitqueue_head(&shost->host_wait);
- init_MUTEX(&shost->scan_mutex);
+ mutex_init(&shost->scan_mutex);
shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */
shost->dma_channel = 0xff;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 3882d48a42bf..e5e1ca44e1ee 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1319,6 +1319,9 @@ ips_slave_configure(struct scsi_device * SDptr)
min = ha->max_cmds - 1;
scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
}
+
+ SDptr->skip_ms_page_8 = 1;
+ SDptr->skip_ms_page_3f = 1;
return 0;
}
#endif
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 10bcf42cb65c..780bfcc67096 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/kfifo.h>
#include <linux/scatterlist.h>
+#include <linux/mutex.h>
#include <net/tcp.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -86,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
{
sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
ibuf->sent = 0;
+ ibuf->use_sendmsg = 0;
}
static inline void
iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
{
- ibuf->sg.page = (void*)vbuf;
- ibuf->sg.offset = (unsigned int)-1;
+ ibuf->sg.page = virt_to_page(vbuf);
+ ibuf->sg.offset = offset_in_page(vbuf);
ibuf->sg.length = size;
ibuf->sent = 0;
-}
-
-static inline void*
-iscsi_buf_iov_base(struct iscsi_buf *ibuf)
-{
- return (char*)ibuf->sg.page + ibuf->sent;
+ ibuf->use_sendmsg = 1;
}
static inline void
iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
{
+ ibuf->sg.page = sg->page;
+ ibuf->sg.offset = sg->offset;
+ ibuf->sg.length = sg->length;
/*
* Fastpath: sg element fits into single page
*/
- if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) {
- ibuf->sg.page = sg->page;
- ibuf->sg.offset = sg->offset;
- ibuf->sg.length = sg->length;
- } else
- iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length);
+ if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
+ ibuf->use_sendmsg = 0;
+ else
+ ibuf->use_sendmsg = 1;
ibuf->sent = 0;
}
@@ -356,7 +354,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
struct scsi_cmnd *sc = ctask->sc;
conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
- if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+ if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
int res_count = be32_to_cpu(rhdr->residual_count);
if (res_count > 0 &&
@@ -366,9 +364,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
} else
sc->result = (DID_BAD_TARGET << 16) |
rhdr->cmd_status;
- } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
- else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) {
+ } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
sc->resid = be32_to_cpu(rhdr->residual_count);
sc->result = (DID_OK << 16) | rhdr->cmd_status;
} else
@@ -529,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
__kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
__kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
- schedule_work(&conn->xmitwork);
+ scsi_queue_work(session->host, &conn->xmitwork);
conn->r2t_pdus_cnt++;
spin_unlock(&session->lock);
@@ -686,7 +682,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
switch(conn->in.opcode) {
case ISCSI_OP_LOGIN_RSP:
case ISCSI_OP_TEXT_RSP:
- case ISCSI_OP_LOGOUT_RSP:
+ case ISCSI_OP_LOGOUT_RSP:
rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (rc)
@@ -727,12 +723,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
}
spin_unlock(&session->lock);
break;
- case ISCSI_OP_NOOP_IN:
+ case ISCSI_OP_NOOP_IN:
if (hdr->ttt != ISCSI_RESERVED_TAG) {
rc = ISCSI_ERR_PROTO;
break;
}
- rc = iscsi_check_assign_cmdsn(session,
+ rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (rc)
break;
@@ -767,7 +763,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
rc = iscsi_recv_pdu(iscsi_handle(conn),
hdr, NULL, 0);
- } else
+ } else
rc = ISCSI_ERR_PROTO;
break;
case ISCSI_OP_REJECT:
@@ -929,7 +925,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
sc->request_bufflen, ctask->data_offset);
if (rc == -EAGAIN)
return rc;
- if (conn->datadgst_en)
+ if (conn->datadgst_en)
iscsi_recv_digest_update(conn, sc->request_buffer, i);
rc = 0;
goto done;
@@ -1024,7 +1020,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
conn->in.hdr = &conn->hdr;
conn->senselen = (conn->data[0] << 8) | conn->data[1];
rc = iscsi_cmd_rsp(conn, conn->in.ctask);
- if (!rc && conn->datadgst_en)
+ if (!rc && conn->datadgst_en)
iscsi_recv_digest_update(conn, conn->data,
conn->in.datalen);
}
@@ -1051,7 +1047,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
conn->data, conn->in.datalen);
- if (!rc && conn->datadgst_en &&
+ if (!rc && conn->datadgst_en &&
conn->in.opcode != ISCSI_OP_LOGIN_RSP)
iscsi_recv_digest_update(conn, conn->data,
conn->in.datalen);
@@ -1271,7 +1267,7 @@ iscsi_write_space(struct sock *sk)
conn->old_write_space(sk);
debug_tcp("iscsi_write_space: cid %d\n", conn->id);
clear_bit(SUSPEND_BIT, &conn->suspend_tx);
- schedule_work(&conn->xmitwork);
+ scsi_queue_work(conn->session->host, &conn->xmitwork);
}
static void
@@ -1312,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
* @buf: buffer to write from
* @size: actual size to write
* @flags: socket's flags
- *
- * Notes:
- * depending on buffer will use tcp_sendpage() or tcp_sendmsg().
- * buf->sg.offset == -1 tells us that buffer is non S/G and forces
- * to use tcp_sendmsg().
*/
static inline int
-iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
+iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
{
- int res;
-
- if ((int)buf->sg.offset >= 0) {
- int offset = buf->sg.offset + buf->sent;
-
- /* tcp_sendpage */
- res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags);
- } else {
- struct msghdr msg;
-
- buf->iov.iov_base = iscsi_buf_iov_base(buf);
- buf->iov.iov_len = size;
-
- memset(&msg, 0, sizeof(struct msghdr));
-
- /* tcp_sendmsg */
- res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size);
- }
+ struct socket *sk = conn->sock;
+ int offset = buf->sg.offset + buf->sent;
- return res;
+ /*
+ * if we got use_sg=0 or are sending something we kmallocd
+ * then we did not have to do kmap (kmap returns page_address)
+ *
+ * if we got use_sg > 0, but had to drop down, we do not
+ * set clustering so this should only happen for that
+ * slab case.
+ */
+ if (buf->use_sendmsg)
+ return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+ else
+ return conn->sendpage(sk, buf->sg.page, offset, size, flags);
}
/**
@@ -1355,7 +1341,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
static inline int
iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
{
- struct socket *sk = conn->sock;
int flags = 0; /* MSG_DONTWAIT; */
int res, size;
@@ -1364,7 +1349,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
if (buf->sent + size != buf->sg.length || datalen)
flags |= MSG_MORE;
- res = iscsi_send(sk, buf, size, flags);
+ res = iscsi_send(conn, buf, size, flags);
debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
if (res >= 0) {
conn->txdata_octets += res;
@@ -1395,7 +1380,6 @@ static inline int
iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
int *count, int *sent)
{
- struct socket *sk = conn->sock;
int flags = 0; /* MSG_DONTWAIT; */
int res, size;
@@ -1406,7 +1390,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
if (buf->sent + size != buf->sg.length || *count != size)
flags |= MSG_MORE;
- res = iscsi_send(sk, buf, size, flags);
+ res = iscsi_send(conn, buf, size, flags);
debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
size, buf->sent, *count, *sent, res);
if (res >= 0) {
@@ -1434,20 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
ctask->digest_count = 4;
}
-static inline void
-iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf)
-{
- struct scatterlist sg;
-
- if (buf->sg.offset != -1)
- crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1);
- else {
- sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length);
- crypto_digest_update(conn->data_tx_tfm, &sg, 1);
- }
-}
-
-static inline int
+static int
iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
struct iscsi_buf *buf, uint32_t *digest, int final)
{
@@ -1680,7 +1651,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
zero_data(ctask->hdr.dlength);
}
- iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
+ iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
sizeof(struct iscsi_hdr));
conn->scsicmd_pdus_cnt++;
}
@@ -1746,7 +1717,7 @@ static inline int
handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
ctask->xmstate &= ~XMSTATE_R_HDR;
- if (conn->hdrdgst_en)
+ if (conn->hdrdgst_en)
iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
BUG_ON(ctask->xmstate != XMSTATE_IDLE);
@@ -1760,7 +1731,7 @@ static inline int
handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
ctask->xmstate &= ~XMSTATE_W_HDR;
- if (conn->hdrdgst_en)
+ if (conn->hdrdgst_en)
iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
ctask->xmstate |= XMSTATE_W_HDR;
@@ -1809,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
return -EAGAIN;
}
if (conn->datadgst_en)
- iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm,
+ &ctask->sendbuf.sg, 1);
if (!ctask->imm_count)
break;
@@ -1894,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
* so pass it
*/
if (conn->datadgst_en && ctask->sent - start > 0)
- iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm,
+ &ctask->sendbuf.sg, 1);
if (!ctask->data_count)
break;
@@ -1972,7 +1945,7 @@ solicit_again:
BUG_ON(r2t->data_count < 0);
if (conn->datadgst_en)
- iscsi_buf_data_digest_update(conn, &r2t->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
if (r2t->data_count) {
BUG_ON(ctask->sc->use_sg == 0);
@@ -2054,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
}
if (conn->datadgst_en) {
- iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
/* imm data? */
if (!dtask) {
if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
@@ -2148,7 +2121,7 @@ unsolicit_head_again:
solicit_head_again:
r2t = ctask->r2t;
if (conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &r2t->headbuf,
+ iscsi_hdr_digest(conn, &r2t->headbuf,
(u8*)r2t->dtask->hdrext);
if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
ctask->xmstate &= ~XMSTATE_SOL_DATA;
@@ -2300,10 +2273,10 @@ iscsi_xmitworker(void *data)
/*
* serialize Xmit worker on a per-connection basis.
*/
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
if (iscsi_data_xmit(conn))
- schedule_work(&conn->xmitwork);
- up(&conn->xmitsema);
+ scsi_queue_work(conn->session->host, &conn->xmitwork);
+ mutex_unlock(&conn->xmitmutex);
}
#define FAILURE_BAD_HOST 1
@@ -2367,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
spin_unlock(&session->lock);
- if (!in_interrupt() && !down_trylock(&conn->xmitsema)) {
- spin_unlock_irq(host->host_lock);
- if (iscsi_data_xmit(conn))
- schedule_work(&conn->xmitwork);
- up(&conn->xmitsema);
- spin_lock_irq(host->host_lock);
- } else
- schedule_work(&conn->xmitwork);
-
+ scsi_queue_work(host, &conn->xmitwork);
return 0;
reject:
@@ -2462,17 +2427,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
kfree(items);
}
-static iscsi_connh_t
-iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
+static struct iscsi_cls_conn *
+iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
{
- struct iscsi_session *session = iscsi_ptr(sessionh);
- struct iscsi_conn *conn = NULL;
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ struct iscsi_conn *conn;
+ struct iscsi_cls_conn *cls_conn;
- conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
- if (conn == NULL)
- goto conn_alloc_fail;
- memset(conn, 0, sizeof(struct iscsi_conn));
+ cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
+ conn_idx);
+ if (!cls_conn)
+ return NULL;
+ conn = cls_conn->dd_data;
+ memset(conn, 0, sizeof(struct iscsi_conn));
conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
conn->id = conn_idx;
@@ -2531,10 +2499,10 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
goto max_recv_dlenght_alloc_fail;
init_timer(&conn->tmabort_timer);
- init_MUTEX(&conn->xmitsema);
+ mutex_init(&conn->xmitmutex);
init_waitqueue_head(&conn->ehwait);
- return iscsi_handle(conn);
+ return cls_conn;
max_recv_dlenght_alloc_fail:
spin_lock_bh(&session->lock);
@@ -2550,18 +2518,18 @@ immqueue_alloc_fail:
writequeue_alloc_fail:
kfifo_free(conn->xmitqueue);
xmitqueue_alloc_fail:
- kfree(conn);
-conn_alloc_fail:
- return iscsi_handle(NULL);
+ iscsi_destroy_conn(cls_conn);
+ return NULL;
}
static void
-iscsi_conn_destroy(iscsi_connh_t connh)
+iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
+ unsigned long flags;
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
set_bit(SUSPEND_BIT, &conn->suspend_tx);
if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) {
struct sock *sk = conn->sock->sk;
@@ -2592,19 +2560,19 @@ iscsi_conn_destroy(iscsi_connh_t connh)
}
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
/*
* Block until all in-progress commands for this connection
* time out or fail.
*/
for (;;) {
- spin_lock_bh(&conn->lock);
+ spin_lock_irqsave(session->host->host_lock, flags);
if (!session->host->host_busy) { /* OK for ERL == 0 */
- spin_unlock_bh(&conn->lock);
+ spin_unlock_irqrestore(session->host->host_lock, flags);
break;
}
- spin_unlock_bh(&conn->lock);
+ spin_unlock_irqrestore(session->host->host_lock, flags);
msleep_interruptible(500);
printk("conn_destroy(): host_busy %d host_failed %d\n",
session->host->host_busy, session->host->host_failed);
@@ -2652,7 +2620,8 @@ iscsi_conn_destroy(iscsi_connh_t connh)
kfifo_free(conn->writequeue);
kfifo_free(conn->immqueue);
kfifo_free(conn->mgmtqueue);
- kfree(conn);
+
+ iscsi_destroy_conn(cls_conn);
}
static int
@@ -2713,6 +2682,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
*/
iscsi_conn_set_callbacks(conn);
+ conn->sendpage = conn->sock->ops->sendpage;
+
/*
* set receive state machine into initial state
*/
@@ -2796,7 +2767,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
set_bit(SUSPEND_BIT, &conn->suspend_rx);
write_unlock_bh(&sk->sk_callback_lock);
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
spin_lock_irqsave(session->host->host_lock, flags);
spin_lock(&session->lock);
@@ -2878,7 +2849,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
conn->datadgst_en = 0;
}
}
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
}
static int
@@ -2963,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
else
__kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
- schedule_work(&conn->xmitwork);
-
+ scsi_queue_work(session->host, &conn->xmitwork);
return 0;
}
@@ -3029,12 +2999,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
* 1) connection-level failure;
* 2) recovery due protocol error;
*/
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
spin_lock_bh(&session->lock);
if (session->state != ISCSI_STATE_LOGGED_IN) {
if (session->state == ISCSI_STATE_TERMINATE) {
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
goto failed;
}
spin_unlock_bh(&session->lock);
@@ -3052,7 +3022,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
* 2) session was re-open during time out of ctask.
*/
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
goto success;
}
conn->tmabort_state = TMABORT_INITIAL;
@@ -3107,7 +3077,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
conn->tmabort_state == TMABORT_SUCCESS) {
conn->tmabort_state = TMABORT_INITIAL;
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
goto success;
}
conn->tmabort_state = TMABORT_INITIAL;
@@ -3116,7 +3086,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
spin_unlock_bh(&session->lock);
}
}
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
/*
@@ -3182,7 +3152,7 @@ failed:
exit:
del_timer_sync(&conn->tmabort_timer);
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
if (conn->sock) {
struct sock *sk = conn->sock->sk;
@@ -3190,7 +3160,7 @@ exit:
iscsi_ctask_cleanup(conn, ctask);
write_unlock_bh(&sk->sk_callback_lock);
}
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
return rc;
}
@@ -3281,17 +3251,23 @@ static struct scsi_host_template iscsi_sht = {
.this_id = -1,
};
-static iscsi_sessionh_t
-iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
+static struct iscsi_transport iscsi_tcp_transport;
+
+static struct Scsi_Host *
+iscsi_session_create(struct scsi_transport_template *scsit,
+ uint32_t initial_cmdsn)
{
- int cmd_i;
+ struct Scsi_Host *shost;
struct iscsi_session *session;
+ int cmd_i;
- session = iscsi_hostdata(host->hostdata);
- memset(session, 0, sizeof(struct iscsi_session));
+ shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
+ if (!shost)
+ return NULL;
- session->host = host;
- session->id = host->host_no;
+ session = iscsi_hostdata(shost->hostdata);
+ memset(session, 0, sizeof(struct iscsi_session));
+ session->host = shost;
session->state = ISCSI_STATE_LOGGED_IN;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = ISCSI_XMIT_CMDS_MAX;
@@ -3335,7 +3311,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
if (iscsi_r2tpool_alloc(session))
goto r2tpool_alloc_fail;
- return iscsi_handle(session);
+ return shost;
r2tpool_alloc_fail:
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
@@ -3345,15 +3321,15 @@ immdata_alloc_fail:
mgmtpool_alloc_fail:
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
cmdpool_alloc_fail:
- return iscsi_handle(NULL);
+ return NULL;
}
static void
-iscsi_session_destroy(iscsi_sessionh_t sessionh)
+iscsi_session_destroy(struct Scsi_Host *shost)
{
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
int cmd_i;
struct iscsi_data_task *dtask, *n;
- struct iscsi_session *session = iscsi_ptr(sessionh);
for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
@@ -3369,6 +3345,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh)
iscsi_r2tpool_free(session);
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+
+ iscsi_transport_destroy_session(shost);
}
static int
@@ -3467,6 +3445,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
if (conn->data_rx_tfm)
crypto_free_tfm(conn->data_rx_tfm);
}
+ conn->sendpage = conn->datadgst_en ?
+ sock_no_sendpage : conn->sock->ops->sendpage;
break;
case ISCSI_PARAM_INITIAL_R2T_EN:
session->initial_r2t_en = value;
@@ -3515,25 +3495,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
}
static int
-iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
- uint32_t *value)
+iscsi_session_get_param(struct Scsi_Host *shost,
+ enum iscsi_param param, uint32_t *value)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
- struct iscsi_session *session = conn->session;
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
switch(param) {
- case ISCSI_PARAM_MAX_RECV_DLENGTH:
- *value = conn->max_recv_dlength;
- break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- *value = conn->max_xmit_dlength;
- break;
- case ISCSI_PARAM_HDRDGST_EN:
- *value = conn->hdrdgst_en;
- break;
- case ISCSI_PARAM_DATADGST_EN:
- *value = conn->datadgst_en;
- break;
case ISCSI_PARAM_INITIAL_R2T_EN:
*value = session->initial_r2t_en;
break;
@@ -3571,6 +3538,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
return 0;
}
+static int
+iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
+{
+ struct iscsi_conn *conn = data;
+
+ switch(param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ *value = conn->max_recv_dlength;
+ break;
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ *value = conn->max_xmit_dlength;
+ break;
+ case ISCSI_PARAM_HDRDGST_EN:
+ *value = conn->hdrdgst_en;
+ break;
+ case ISCSI_PARAM_DATADGST_EN:
+ *value = conn->datadgst_en;
+ break;
+ default:
+ return ISCSI_ERR_PARAM_NOT_FOUND;
+ }
+
+ return 0;
+}
+
static void
iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
{
@@ -3601,9 +3593,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
struct iscsi_conn *conn = iscsi_ptr(connh);
int rc;
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
return rc;
}
@@ -3615,6 +3607,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
| CAP_DATADGST,
.host_template = &iscsi_sht,
.hostdata_size = sizeof(struct iscsi_session),
+ .conndata_size = sizeof(struct iscsi_conn),
.max_conn = 1,
.max_cmd_len = ISCSI_TCP_MAX_CMD_LEN,
.create_session = iscsi_session_create,
@@ -3623,7 +3616,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
.bind_conn = iscsi_conn_bind,
.destroy_conn = iscsi_conn_destroy,
.set_param = iscsi_conn_set_param,
- .get_param = iscsi_conn_get_param,
+ .get_conn_param = iscsi_conn_get_param,
+ .get_session_param = iscsi_session_get_param,
.start_conn = iscsi_conn_start,
.stop_conn = iscsi_conn_stop,
.send_pdu = iscsi_conn_send_pdu,
@@ -3633,8 +3627,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
static int __init
iscsi_tcp_init(void)
{
- int error;
-
if (iscsi_max_lun < 1) {
printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
return -EINVAL;
@@ -3647,11 +3639,10 @@ iscsi_tcp_init(void)
if (!taskcache)
return -ENOMEM;
- error = iscsi_register_transport(&iscsi_tcp_transport);
- if (error)
+ if (!iscsi_register_transport(&iscsi_tcp_transport))
kmem_cache_destroy(taskcache);
- return error;
+ return 0;
}
static void __exit
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 855f2dfd18af..f95e61b76f70 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -158,7 +158,7 @@ struct iscsi_conn {
struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */
struct kfifo *xmitqueue; /* data-path cmd queue */
struct work_struct xmitwork; /* per-conn. xmit workqueue */
- struct semaphore xmitsema; /* serializes connection xmit,
+ struct mutex xmitmutex; /* serializes connection xmit,
* access to kfifos: *
* xmitqueue, writequeue, *
* immqueue, mgmtqueue */
@@ -191,6 +191,8 @@ struct iscsi_conn {
uint32_t sendpage_failures_cnt;
uint32_t discontiguous_hdr_cnt;
uint32_t eh_abort_cnt;
+
+ ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
};
struct iscsi_session {
@@ -240,8 +242,8 @@ struct iscsi_session {
struct iscsi_buf {
struct scatterlist sg;
- struct kvec iov;
unsigned int sent;
+ char use_sendmsg;
};
struct iscsi_data_task {
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index f55b9b3f7b37..46c4cdbaee86 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -611,6 +611,10 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
if (dev->flags & ATA_DFLAG_PIO) {
tf->protocol = ATA_PROT_PIO;
index = dev->multi_count ? 0 : 8;
+ } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+ /* Unable to use DMA due to host limitation */
+ tf->protocol = ATA_PROT_PIO;
+ index = dev->multi_count ? 0 : 4;
} else {
tf->protocol = ATA_PROT_DMA;
index = 16;
@@ -1051,18 +1055,22 @@ 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)) {
+ /* Usual case. Word 53 indicates word 64 is valid */
+ if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
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 ;
+ /* If word 64 isn't valid then Word 51 high byte 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] >> 8) & 0xFF)) - 1 ;
return modes;
+ /* But wait.. there's more. Design your standards by committee and
+ you too can get a free iordy field to process. However its the
+ speeds not the modes that are supported... Note drivers using the
+ timing API will get this right anyway */
}
struct ata_exec_internal_arg {
@@ -1165,6 +1173,39 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
}
/**
+ * ata_pio_need_iordy - check if iordy needed
+ * @adev: ATA device
+ *
+ * Check if the current speed of the device requires IORDY. Used
+ * by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+ int pio;
+ int speed = adev->pio_mode - XFER_PIO_0;
+
+ if (speed < 2)
+ return 0;
+ if (speed > 2)
+ return 1;
+
+ /* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+ if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */
+ pio = adev->id[ATA_ID_EIDE_PIO];
+ /* Is the speed faster than the drive allows non IORDY ? */
+ if (pio) {
+ /* This is cycle times not frequency - watch the logic! */
+ if (pio > 240) /* PIO2 is 240nS per cycle */
+ return 1;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/**
* ata_dev_identify - obtain IDENTIFY x DEVICE page
* @ap: port on which device we wish to probe resides
* @device: device bus address, starting at zero
@@ -1415,7 +1456,7 @@ void ata_dev_config(struct ata_port *ap, unsigned int i)
ap->udma_mask &= ATA_UDMA5;
ap->host->max_sectors = ATA_MAX_SECTORS;
ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
- ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+ ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
}
if (ap->ops->dev_config)
@@ -1747,7 +1788,7 @@ static const struct {
{ ATA_SHIFT_PIO, XFER_PIO_0 },
};
-static inline u8 base_from_shift(unsigned int shift)
+static u8 base_from_shift(unsigned int shift)
{
int i;
@@ -3056,10 +3097,21 @@ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int do_write)
{
- if (ap->flags & ATA_FLAG_MMIO)
- ata_mmio_data_xfer(ap, buf, buflen, do_write);
- else
- ata_pio_data_xfer(ap, buf, buflen, do_write);
+ /* Make the crap hardware pay the costs not the good stuff */
+ if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
+ unsigned long flags;
+ local_irq_save(flags);
+ if (ap->flags & ATA_FLAG_MMIO)
+ ata_mmio_data_xfer(ap, buf, buflen, do_write);
+ else
+ ata_pio_data_xfer(ap, buf, buflen, do_write);
+ local_irq_restore(flags);
+ } else {
+ if (ap->flags & ATA_FLAG_MMIO)
+ ata_mmio_data_xfer(ap, buf, buflen, do_write);
+ else
+ ata_pio_data_xfer(ap, buf, buflen, do_write);
+ }
}
/**
@@ -5122,6 +5174,7 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
EXPORT_SYMBOL_GPL(ata_timing_compute);
EXPORT_SYMBOL_GPL(ata_timing_merge);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 9ee8218404c0..dafabeefc5b3 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -150,7 +150,7 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba)
return psb;
}
-struct lpfc_scsi_buf*
+static struct lpfc_scsi_buf*
lpfc_get_scsi_buf(struct lpfc_hba * phba)
{
struct lpfc_scsi_buf * lpfc_cmd = NULL;
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 932dcf0366eb..311a4122bd70 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -432,11 +432,12 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
struct Scsi_Host *host;
void *dma_cmd_space;
unsigned char *clkprop;
- int proplen;
+ int proplen, rc = -ENODEV;
if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
- printk(KERN_ERR "mac53c94: expected 2 addrs and intrs (got %d/%d)\n",
- node->n_addrs, node->n_intrs);
+ printk(KERN_ERR "mac53c94: expected 2 addrs and intrs"
+ " (got %d/%d)\n",
+ macio_resource_count(mdev), macio_irq_count(mdev));
return -ENODEV;
}
@@ -448,6 +449,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state));
if (host == NULL) {
printk(KERN_ERR "mac53c94: couldn't register host");
+ rc = -ENOMEM;
goto out_release;
}
@@ -486,6 +488,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
if (dma_cmd_space == 0) {
printk(KERN_ERR "mac53c94: couldn't allocate dma "
"command space for %s\n", node->full_name);
+ rc = -ENOMEM;
goto out_free;
}
state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space);
@@ -495,18 +498,21 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
mac53c94_init(state);
- if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94", state)) {
+ if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94",state)) {
printk(KERN_ERR "mac53C94: can't get irq %d for %s\n",
state->intr, node->full_name);
goto out_free_dma;
}
- /* XXX FIXME: handle failure */
- scsi_add_host(host, &mdev->ofdev.dev);
- scsi_scan_host(host);
+ rc = scsi_add_host(host, &mdev->ofdev.dev);
+ if (rc != 0)
+ goto out_release_irq;
+ scsi_scan_host(host);
return 0;
+ out_release_irq:
+ free_irq(state->intr, state);
out_free_dma:
kfree(state->dma_cmd_space);
out_free:
@@ -518,7 +524,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
out_release:
macio_release_resources(mdev);
- return -ENODEV;
+ return rc;
}
static int mac53c94_remove(struct macio_dev *mdev)
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 4a6feb1e5e3d..d101a8a6f4e8 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4479,7 +4479,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
* serialized. This is so because we want to reserve maximum number of
* available command ids for the I/O commands.
*/
- down(&adapter->int_mtx);
+ mutex_lock(&adapter->int_mtx);
scb = &adapter->int_scb;
memset(scb, 0, sizeof(scb_t));
@@ -4527,7 +4527,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
mc->cmd, mc->opcode, mc->subopcode, scmd->result);
}
- up(&adapter->int_mtx);
+ mutex_unlock(&adapter->int_mtx);
return rval;
}
@@ -4866,7 +4866,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->has_64bit_addr = 0;
}
- init_MUTEX(&adapter->int_mtx);
+ mutex_init(&adapter->int_mtx);
init_completion(&adapter->int_waitq);
adapter->this_id = DEFAULT_INITIATOR_ID;
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 6f9078025748..4b3e0d6e5afa 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -2,7 +2,7 @@
#define __MEGARAID_H__
#include <linux/spinlock.h>
-
+#include <linux/mutex.h>
#define MEGARAID_VERSION \
"v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
@@ -889,7 +889,7 @@ typedef struct {
scb_t int_scb;
Scsi_Cmnd int_scmd;
- struct semaphore int_mtx; /* To synchronize the internal
+ struct mutex int_mtx; /* To synchronize the internal
commands */
struct completion int_waitq; /* wait queue for internal
cmds */
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index d18a4bc2498c..bf9f7f7ba354 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -1266,7 +1266,7 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
* return the scb from the head of the free list. NULL if there are none
* available
**/
-static inline scb_t *
+static scb_t *
megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
{
struct list_head *head = &adapter->kscb_pool;
@@ -1329,7 +1329,7 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
*
* prepare the scatter-gather list
*/
-static inline int
+static int
megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
{
struct scatterlist *sgl;
@@ -1402,7 +1402,7 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
*
* post the command to the controller if mailbox is availble.
*/
-static inline int
+static int
mbox_post_cmd(adapter_t *adapter, scb_t *scb)
{
mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
@@ -2070,7 +2070,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
*
* Returns: 1 if the interrupt is valid, 0 otherwise
*/
-static inline int
+static int
megaraid_ack_sequence(adapter_t *adapter)
{
mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
@@ -2208,7 +2208,7 @@ megaraid_isr(int irq, void *devp, struct pt_regs *regs)
*
* DMA sync if required.
*/
-static inline void
+static void
megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
{
mbox_ccb_t *ccb;
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index eb8c390a0fa3..3d9e67d6849d 100644
--- a/drivers/scsi/megaraid/megaraid_mm.h
+++ b/drivers/scsi/megaraid/megaraid_mm.h
@@ -22,7 +22,6 @@
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/list.h>
-#include <linux/ioctl32.h>
#include "mbox_defs.h"
#include "megaraid_ioctl.h"
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 3c32e69afcd9..511ed52a5807 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -35,6 +35,7 @@
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/compat.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -72,7 +73,7 @@ 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);
+static DEFINE_MUTEX(megasas_async_queue_mutex);
/**
* megasas_get_cmd - Get a command from the free pool
@@ -80,7 +81,7 @@ static DECLARE_MUTEX(megasas_async_queue_mutex);
*
* Returns a free command from the pool
*/
-static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
*instance)
{
unsigned long flags;
@@ -262,7 +263,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
* If successful, this function returns the number of SG elements. Otherwise,
* it returnes -1.
*/
-static inline int
+static int
megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
union megasas_sgl *mfi_sgl)
{
@@ -310,7 +311,7 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
* If successful, this function returns the number of SG elements. Otherwise,
* it returnes -1.
*/
-static inline int
+static int
megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
union megasas_sgl *mfi_sgl)
{
@@ -359,7 +360,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
* This function prepares CDB commands. These are typcially pass-through
* commands to the devices.
*/
-static inline int
+static int
megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
struct megasas_cmd *cmd)
{
@@ -440,7 +441,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
*
* Frames (and accompanying SGLs) for regular SCSI IOs use this function.
*/
-static inline int
+static int
megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
struct megasas_cmd *cmd)
{
@@ -562,7 +563,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
* @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
+static struct megasas_cmd *megasas_build_cmd(struct megasas_instance
*instance,
struct scsi_cmnd *scp,
int *frame_count)
@@ -913,7 +914,7 @@ megasas_complete_abort(struct megasas_instance *instance,
* @instance: Adapter soft state
* @cmd: Completed command
*/
-static inline void
+static void
megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
{
dma_addr_t buf_h;
@@ -957,7 +958,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
* an alternate status (as in the case of aborted
* commands)
*/
-static inline void
+static void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status)
{
@@ -1104,7 +1105,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
* SCSI mid-layer instead of the status
* returned by the FW
*/
-static inline int
+static int
megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
{
u32 status;
@@ -2362,11 +2363,11 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
{
int rc;
- down(&megasas_async_queue_mutex);
+ mutex_lock(&megasas_async_queue_mutex);
rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
- up(&megasas_async_queue_mutex);
+ mutex_unlock(&megasas_async_queue_mutex);
if (rc >= 0) {
/* For sanity check when we get ioctl */
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index bdccf73cf9fe..d6d2125f9044 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1869,7 +1869,8 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs"
- " (got %d,%d)\n", mesh->n_addrs, mesh->n_intrs);
+ " (got %d,%d)\n", macio_resource_count(mdev),
+ macio_irq_count(mdev));
return -ENODEV;
}
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
index 5d9c9ada814f..dee426f8c07b 100644
--- a/drivers/scsi/oktagon_esp.c
+++ b/drivers/scsi/oktagon_esp.c
@@ -490,7 +490,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 5205c4e7d6ff..5758b2566d7f 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,4 +1,4 @@
-config SCSI_QLA2XXX
+config SCSI_QLA_FC
tristate "QLogic QLA2XXX Fibre Channel Support"
depends on PCI && SCSI
select SCSI_FC_ATTRS
@@ -22,49 +22,57 @@ config SCSI_QLA2XXX
Upon request, the driver caches the firmware image until
the driver is unloaded.
+ Firmware images can be retrieved from:
+
+ ftp://ftp.qlogic.com/outgoing/linux/firmware/
+
NOTE: The original method of building firmware-loader
modules has been deprecated as the firmware-images will
be removed from the kernel sources.
config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
bool " Use firmware-loader modules (DEPRECATED)"
- depends on SCSI_QLA2XXX
+ depends on SCSI_QLA_FC
+ help
+ This option offers you the deprecated firmware-loader
+ modules that have been obsoleted by the usage of the
+ Firmware Loader interface in the qla2xxx driver.
config SCSI_QLA21XX
tristate " Build QLogic ISP2100 firmware-module"
- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 21xx (ISP2100) host adapter family.
config SCSI_QLA22XX
tristate " Build QLogic ISP2200 firmware-module"
- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 22xx (ISP2200) host adapter family.
config SCSI_QLA2300
tristate " Build QLogic ISP2300 firmware-module"
- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
adapter family.
config SCSI_QLA2322
tristate " Build QLogic ISP2322 firmware-module"
- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 2322 (ISP2322) host adapter family.
config SCSI_QLA6312
tristate " Build QLogic ISP63xx firmware-module"
- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
adapter family.
config SCSI_QLA24XX
tristate " Build QLogic ISP24xx firmware-module"
- depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index 40c0de125889..d028bc50ccf7 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -3,7 +3,7 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
-obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o
+obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
qla2100-y := ql2100.o ql2100_fw.o
qla2200-y := ql2200.o ql2200_fw.o
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 2efca52dff50..b17ee62dd1a9 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -541,7 +541,7 @@ struct fc_function_template qla2xxx_transport_functions = {
void
qla2x00_init_host_attr(scsi_qla_host_t *ha)
{
- 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_node_name(ha->host) = wwn_to_u64(ha->node_name);
+ fc_host_port_name(ha->host) = wwn_to_u64(ha->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 5c5d2315cfab..2d9b12ffe09c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1003,10 +1003,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
fw = (struct qla24xx_fw_dump *) ha->fw_dump24;
rval = QLA_SUCCESS;
- fw->hccr = RD_REG_DWORD(&reg->hccr);
+ fw->host_status = RD_REG_DWORD(&reg->host_status);
/* Pause RISC. */
- if ((fw->hccr & HCCRX_RISC_PAUSE) == 0) {
+ if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
HCCRX_CLR_HOST_INT);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
@@ -1021,16 +1021,54 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
}
}
- /* Disable interrupts. */
- WRT_REG_DWORD(&reg->ictrl, 0);
- RD_REG_DWORD(&reg->ictrl);
-
if (rval == QLA_SUCCESS) {
/* Host interface registers. */
dmp_reg = (uint32_t __iomem *)(reg + 0);
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+ /* Disable interrupts. */
+ WRT_REG_DWORD(&reg->ictrl, 0);
+ RD_REG_DWORD(&reg->ictrl);
+
+ /* Shadow registers. */
+ WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
+ RD_REG_DWORD(&reg->iobase_addr);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0000000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0100000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0200000);
+ 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);
+ WRT_REG_DWORD(dmp_reg, 0xB0300000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0400000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0500000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0600000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
+
/* Mailbox registers. */
mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
@@ -1308,43 +1346,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
for (cnt = 0; cnt < 16; cnt++)
*iter_reg++ = RD_REG_DWORD(dmp_reg++);
- WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
- RD_REG_DWORD(&reg->iobase_addr);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0000000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0100000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0200000);
- 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);
- WRT_REG_DWORD(dmp_reg, 0xB0300000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0400000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0500000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0600000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
-
/* Local memory controller registers. */
iter_reg = fw->lmc_reg;
WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
@@ -1677,7 +1678,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
ha->fw_major_version, ha->fw_minor_version,
ha->fw_subminor_version, ha->fw_attributes);
- qla_uprintf(&uiter, "\nHCCR Register\n%04x\n", fw->hccr);
+ qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status);
qla_uprintf(&uiter, "\nHost Interface Registers");
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) {
@@ -1687,6 +1688,14 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]);
}
+ qla_uprintf(&uiter, "\n\nShadow Registers");
+ for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
+ if (cnt % 8 == 0)
+ qla_uprintf(&uiter, "\n");
+
+ qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
+ }
+
qla_uprintf(&uiter, "\n\nMailbox Registers");
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) {
if (cnt % 8 == 0)
@@ -1855,14 +1864,6 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]);
}
- qla_uprintf(&uiter, "\n\nShadow Registers");
- for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
- if (cnt % 8 == 0)
- qla_uprintf(&uiter, "\n");
-
- qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
- }
-
qla_uprintf(&uiter, "\n\nLMC Registers");
for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) {
if (cnt % 8 == 0)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 935a59a8c054..ab6afeaa2f2c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -227,8 +227,9 @@ struct qla2100_fw_dump {
#define FW_DUMP_SIZE_24XX 0x2B0000
struct qla24xx_fw_dump {
- uint32_t hccr;
+ uint32_t host_status;
uint32_t host_reg[32];
+ uint32_t shadow_reg[7];
uint16_t mailbox_reg[32];
uint32_t xseq_gp_reg[128];
uint32_t xseq_0_reg[16];
@@ -250,7 +251,6 @@ struct qla24xx_fw_dump {
uint32_t rcvt0_data_dma_reg[32];
uint32_t rcvt1_data_dma_reg[32];
uint32_t risc_gp_reg[128];
- uint32_t shadow_reg[7];
uint32_t lmc_reg[112];
uint32_t fpm_hdw_reg[192];
uint32_t fb_hdw_reg[176];
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index bec81adcf4fd..32be4c14cccb 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -62,6 +62,7 @@ extern int qlport_down_retry;
extern int ql2xplogiabsentdevice;
extern int ql2xloginretrycount;
extern int ql2xfdmienable;
+extern int ql2xprocessrscn;
extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
@@ -96,10 +97,7 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
* Global Function Prototypes in qla_mbx.c source file.
*/
extern int
-qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t);
-
-extern int
-qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
+qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
extern int
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index cd6f7c3cfe68..d620a8e8a614 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -538,6 +538,7 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
ct_req->req.rff_id.port_id[1] = ha->d_id.b.area;
ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa;
+ ct_req->req.rff_id.fc4_feature = BIT_1;
ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */
/* Execute MS IOCB */
@@ -1529,9 +1530,9 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
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_QLA24XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(4);
else if (IS_QLA23XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(2);
else
@@ -1553,9 +1554,6 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
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;
}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 7d973bd9022b..a91fea69ad63 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1014,11 +1014,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha)
int rval;
/* Update Serial Link options. */
- if ((ha->fw_seriallink_options24[0] & BIT_0) == 0)
+ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
return;
- rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1],
- ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]);
+ rval = qla2x00_set_serdes_params(ha,
+ le16_to_cpu(ha->fw_seriallink_options24[1]),
+ le16_to_cpu(ha->fw_seriallink_options24[2]),
+ le16_to_cpu(ha->fw_seriallink_options24[3]));
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to update Serial Link options (%x).\n", rval);
@@ -1939,6 +1941,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
"information -- get_port_database=%x, "
"loop_id=0x%04x\n",
ha->host_no, rval2, new_fcport->loop_id));
+ DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
+ ha->host_no));
+ set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
continue;
}
@@ -2648,7 +2653,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
switch (format) {
case 0:
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
+ if (ql2xprocessrscn &&
+ !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
!IS_QLA6312(ha) && !IS_QLA6322(ha) &&
!IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
ha->flags.init_done) {
@@ -3402,6 +3408,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
ha->node_name = icb->node_name;
ha->port_name = icb->port_name;
+ icb->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+
ha->retry_count = le16_to_cpu(nv->login_retry_count);
/* Set minimum login_timeout to 4 seconds. */
@@ -3667,8 +3675,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
for (i = 0; i < dlen; i++)
dcode[i] = swab32(dcode[i]);
- rval = qla2x00_load_ram_ext(ha, ha->request_dma,
- risc_addr, dlen);
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
@@ -3868,8 +3876,8 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
for (i = 0; i < dlen; i++)
dcode[i] = swab32(fwcode[i]);
- rval = qla2x00_load_ram_ext(ha, ha->request_dma,
- risc_addr, dlen);
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5181d966fecb..f63af081d4ff 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -519,7 +519,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
* us, create a new entry in our rscn fcports list and handle
* the event like an RSCN.
*/
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
+ if (ql2xprocessrscn &&
+ !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
!IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
ha->flags.init_done && mb[1] != 0xffff &&
((ha->operating_mode == P2P && mb[1] != 0) ||
@@ -963,15 +964,16 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
break;
case CS_DATA_UNDERRUN:
- DEBUG2(printk(KERN_INFO
- "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n",
- ha->host_no, cp->device->id, cp->device->lun, comp_status,
- scsi_status));
-
resid = resid_len;
if (scsi_status & SS_RESIDUAL_UNDER) {
cp->resid = resid;
CMD_RESID_LEN(cp) = resid;
+ } else {
+ DEBUG2(printk(KERN_INFO
+ "scsi(%ld:%d:%d) UNDERRUN status detected "
+ "0x%x-0x%x.\n", ha->host_no, cp->device->id,
+ cp->device->lun, comp_status, scsi_status));
+
}
/*
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9746cd1e664b..3099b379de9d 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -196,7 +196,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
/* Check for pending interrupts. */
qla2x00_poll(ha);
- udelay(10); /* v4.27 */
+ if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
+ !ha->flags.mbox_int)
+ msleep(10);
} /* while */
}
@@ -325,113 +327,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
return rval;
}
-/*
- * qla2x00_load_ram
- * Load adapter RAM using DMA.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
int
-qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr,
- uint16_t risc_code_size)
+qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
+ uint32_t risc_code_size)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t req_len;
- dma_addr_t nml_dma;
- uint32_t nml_len;
- uint32_t normalized;
-
- DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n",
- ha->host_no);)
- req_len = risc_code_size;
- nml_dma = 0;
- nml_len = 0;
-
- normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma,
- &nml_len);
-
- /* Load first segment */
- mcp->mb[0] = MBC_LOAD_RISC_RAM;
- mcp->mb[1] = risc_addr;
- mcp->mb[2] = MSW(req_dma);
- mcp->mb[3] = LSW(req_dma);
- mcp->mb[4] = (uint16_t)req_len;
- mcp->mb[6] = MSW(MSD(req_dma));
- mcp->mb[7] = LSW(MSD(req_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
-
- /* Load second segment - if necessary */
- if (normalized && (rval == QLA_SUCCESS)) {
- mcp->mb[0] = MBC_LOAD_RISC_RAM;
- mcp->mb[1] = risc_addr + (uint16_t)req_len;
- mcp->mb[2] = MSW(nml_dma);
- mcp->mb[3] = LSW(nml_dma);
- mcp->mb[4] = (uint16_t)nml_len;
- mcp->mb[6] = MSW(MSD(nml_dma));
- mcp->mb[7] = LSW(MSD(nml_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
- }
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
- if (rval == QLA_SUCCESS) {
- /* Empty */
- DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);)
+ if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
+ mcp->mb[8] = MSW(risc_addr);
+ mcp->out_mb = MBX_8|MBX_0;
} else {
- /* Empty */
- DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x "
- "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);)
+ mcp->mb[0] = MBC_LOAD_RISC_RAM;
+ mcp->out_mb = MBX_0;
}
- return rval;
-}
-
-/*
- * qla2x00_load_ram_ext
- * Load adapter extended RAM using DMA.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma,
- uint32_t risc_addr, uint32_t risc_code_size)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
-
- DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
-
- mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
mcp->mb[1] = LSW(risc_addr);
mcp->mb[2] = MSW(req_dma);
mcp->mb[3] = LSW(req_dma);
mcp->mb[6] = MSW(MSD(req_dma));
mcp->mb[7] = LSW(MSD(req_dma));
- mcp->mb[8] = MSW(risc_addr);
- mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
mcp->mb[4] = MSW(risc_code_size);
mcp->mb[5] = LSW(risc_code_size);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 24304300d7b5..4916847d84ec 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -71,6 +71,12 @@ MODULE_PARM_DESC(ql2xfdmienable,
"Enables FDMI registratons "
"Default is 0 - no FDMI. 1 - perfom FDMI.");
+int ql2xprocessrscn;
+module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xprocessrscn,
+ "Option to enable port RSCN handling via a series of less"
+ "fabric intrusive ADISCs and PLOGIs.");
+
/*
* SCSI host template entry points
*/
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index d54d2a99c3d3..f4d755a643e4 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -573,6 +573,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
}
} while (0);
+ /* Enable flash write-protection. */
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
+
/* Disable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index f7937f7f9c68..d537192a1edb 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.01.03-k"
+#define QLA2XXX_VERSION "8.01.04-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 1
-#define QLA_DRIVER_PATCH_VER 3
+#define QLA_DRIVER_PATCH_VER 4
#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 5ec5f44602ac..50c398aab557 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -148,9 +148,11 @@ static struct {
{ RAID_LEVEL_LINEAR, "linear" },
{ RAID_LEVEL_0, "raid0" },
{ RAID_LEVEL_1, "raid1" },
+ { RAID_LEVEL_10, "raid10" },
{ RAID_LEVEL_3, "raid3" },
{ RAID_LEVEL_4, "raid4" },
{ RAID_LEVEL_5, "raid5" },
+ { RAID_LEVEL_50, "raid50" },
{ RAID_LEVEL_6, "raid6" },
};
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index c0cf52cb975a..bbbb55eeb73a 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -29,6 +29,12 @@
* NV-specific details such as register offsets, SATA phy location,
* hotplug info, etc.
*
+ * 0.10
+ * - Fixed spurious interrupts issue seen with the Maxtor 6H500F0 500GB
+ * drive. Also made the check_hotplug() callbacks return whether there
+ * was a hotplug interrupt or not. This was not the source of the
+ * spurious interrupts, but is the right thing to do anyway.
+ *
* 0.09
* - Fixed bug introduced by 0.08's MCP51 and MCP55 support.
*
@@ -124,10 +130,10 @@ 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);
static void nv_enable_hotplug(struct ata_probe_ent *probe_ent);
static void nv_disable_hotplug(struct ata_host_set *host_set);
-static void nv_check_hotplug(struct ata_host_set *host_set);
+static int nv_check_hotplug(struct ata_host_set *host_set);
static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent);
static void nv_disable_hotplug_ck804(struct ata_host_set *host_set);
-static void nv_check_hotplug_ck804(struct ata_host_set *host_set);
+static int nv_check_hotplug_ck804(struct ata_host_set *host_set);
enum nv_host_type
{
@@ -176,7 +182,7 @@ struct nv_host_desc
enum nv_host_type host_type;
void (*enable_hotplug)(struct ata_probe_ent *probe_ent);
void (*disable_hotplug)(struct ata_host_set *host_set);
- void (*check_hotplug)(struct ata_host_set *host_set);
+ int (*check_hotplug)(struct ata_host_set *host_set);
};
static struct nv_host_desc nv_device_tbl[] = {
@@ -309,12 +315,16 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN)))
handled += ata_host_intr(ap, qc);
+ else
+ // No request pending? Clear interrupt status
+ // anyway, in case there's one pending.
+ ap->ops->check_status(ap);
}
}
if (host->host_desc->check_hotplug)
- host->host_desc->check_hotplug(host_set);
+ handled += host->host_desc->check_hotplug(host_set);
spin_unlock_irqrestore(&host_set->lock, flags);
@@ -497,7 +507,7 @@ static void nv_disable_hotplug(struct ata_host_set *host_set)
outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
}
-static void nv_check_hotplug(struct ata_host_set *host_set)
+static int nv_check_hotplug(struct ata_host_set *host_set)
{
u8 intr_status;
@@ -522,7 +532,11 @@ static void nv_check_hotplug(struct ata_host_set *host_set)
if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Secondary device removed\n");
+
+ return 1;
}
+
+ return 0;
}
static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent)
@@ -560,7 +574,7 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set)
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
}
-static void nv_check_hotplug_ck804(struct ata_host_set *host_set)
+static int nv_check_hotplug_ck804(struct ata_host_set *host_set)
{
u8 intr_status;
@@ -585,7 +599,11 @@ static void nv_check_hotplug_ck804(struct ata_host_set *host_set)
if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Secondary device removed\n");
+
+ return 1;
}
+
+ return 0;
}
static int __init nv_init(void)
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 3d1ea09a06a1..b0b0a69b3563 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -66,6 +66,7 @@ enum {
board_2037x = 0, /* FastTrak S150 TX2plus */
board_20319 = 1, /* FastTrak S150 TX4 */
board_20619 = 2, /* FastTrak TX4000 */
+ board_20771 = 3, /* FastTrak TX2300 */
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
@@ -190,6 +191,16 @@ static const struct ata_port_info pdc_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_pata_ops,
},
+
+ /* board_20771 */
+ {
+ .sht = &pdc_ata_sht,
+ .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_sata_ops,
+ },
};
static const struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -226,6 +237,8 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20619 },
+ { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20771 },
{ } /* terminate list */
};
@@ -706,6 +719,9 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
case board_2037x:
probe_ent->n_ports = 2;
break;
+ case board_20771:
+ probe_ent->n_ports = 2;
+ break;
case board_20619:
probe_ent->n_ports = 4;
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 668373590aa4..d8472563fde8 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -470,6 +470,7 @@ static const struct pci_device_id k2_sata_pci_tbl[] = {
{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ }
};
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 180676d7115a..245ca99a641e 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -55,6 +55,7 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -69,7 +70,6 @@
#include "scsi_logging.h"
static void scsi_done(struct scsi_cmnd *cmd);
-static int scsi_retry_command(struct scsi_cmnd *cmd);
/*
* Definitions and constants.
@@ -210,7 +210,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
.gfp_mask = __GFP_DMA,
};
-static DECLARE_MUTEX(host_cmd_pool_mutex);
+static DEFINE_MUTEX(host_cmd_pool_mutex);
static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
gfp_t gfp_mask)
@@ -331,7 +331,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
* Select a command slab for this host and create it if not
* yet existant.
*/
- down(&host_cmd_pool_mutex);
+ mutex_lock(&host_cmd_pool_mutex);
pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
if (!pool->users) {
pool->slab = kmem_cache_create(pool->name,
@@ -343,7 +343,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
pool->users++;
shost->cmd_pool = pool;
- up(&host_cmd_pool_mutex);
+ mutex_unlock(&host_cmd_pool_mutex);
/*
* Get one backup command for this host.
@@ -360,7 +360,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
kmem_cache_destroy(pool->slab);
return -ENOMEM;
fail:
- up(&host_cmd_pool_mutex);
+ mutex_unlock(&host_cmd_pool_mutex);
return -ENOMEM;
}
@@ -382,10 +382,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
kmem_cache_free(shost->cmd_pool->slab, cmd);
}
- down(&host_cmd_pool_mutex);
+ mutex_lock(&host_cmd_pool_mutex);
if (!--shost->cmd_pool->users)
kmem_cache_destroy(shost->cmd_pool->slab);
- up(&host_cmd_pool_mutex);
+ mutex_unlock(&host_cmd_pool_mutex);
}
#ifdef CONFIG_SCSI_LOGGING
@@ -752,7 +752,7 @@ static void scsi_done(struct scsi_cmnd *cmd)
* isn't running --- used by scsi_times_out */
void __scsi_done(struct scsi_cmnd *cmd)
{
- unsigned long flags;
+ struct request *rq = cmd->request;
/*
* Set the serial numbers back to zero
@@ -763,71 +763,14 @@ void __scsi_done(struct scsi_cmnd *cmd)
if (cmd->result)
atomic_inc(&cmd->device->ioerr_cnt);
+ BUG_ON(!rq);
+
/*
- * Next, enqueue the command into the done queue.
- * It is a per-CPU queue, so we just disable local interrupts
- * and need no spinlock.
+ * The uptodate/nbytes values don't matter, as we allow partial
+ * completes and thus will check this in the softirq callback
*/
- local_irq_save(flags);
- list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q));
- raise_softirq_irqoff(SCSI_SOFTIRQ);
- local_irq_restore(flags);
-}
-
-/**
- * scsi_softirq - Perform post-interrupt processing of finished SCSI commands.
- *
- * This is the consumer of the done queue.
- *
- * This is called with all interrupts enabled. This should reduce
- * interrupt latency, stack depth, and reentrancy of the low-level
- * drivers.
- */
-static void scsi_softirq(struct softirq_action *h)
-{
- int disposition;
- LIST_HEAD(local_q);
-
- local_irq_disable();
- list_splice_init(&__get_cpu_var(scsi_done_q), &local_q);
- local_irq_enable();
-
- 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)) {
- sdev_printk(KERN_ERR, cmd->device,
- "timing out command, waited %lus\n",
- wait_for/HZ);
- disposition = SUCCESS;
- }
-
- scsi_log_completion(cmd, disposition);
- switch (disposition) {
- case SUCCESS:
- scsi_finish_command(cmd);
- break;
- case NEEDS_RETRY:
- scsi_retry_command(cmd);
- break;
- case ADD_TO_MLQUEUE:
- scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
- break;
- default:
- if (!scsi_eh_scmd_add(cmd, 0))
- scsi_finish_command(cmd);
- }
- }
+ rq->completion_data = cmd;
+ blk_complete_request(rq);
}
/*
@@ -840,7 +783,7 @@ static void scsi_softirq(struct softirq_action *h)
* level drivers should not become re-entrant as a result of
* this.
*/
-static int scsi_retry_command(struct scsi_cmnd *cmd)
+int scsi_retry_command(struct scsi_cmnd *cmd)
{
/*
* Restore the SCSI command state.
@@ -1273,38 +1216,6 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
}
EXPORT_SYMBOL(scsi_device_cancel);
-#ifdef CONFIG_HOTPLUG_CPU
-static int scsi_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- int cpu = (unsigned long)hcpu;
-
- switch(action) {
- case CPU_DEAD:
- /* Drain scsi_done_q. */
- local_irq_disable();
- list_splice_init(&per_cpu(scsi_done_q, cpu),
- &__get_cpu_var(scsi_done_q));
- raise_softirq_irqoff(SCSI_SOFTIRQ);
- local_irq_enable();
- break;
- default:
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block __devinitdata scsi_cpu_nb = {
- .notifier_call = scsi_cpu_notify,
-};
-
-#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb)
-#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb)
-#else
-#define register_scsi_cpu()
-#define unregister_scsi_cpu()
-#endif /* CONFIG_HOTPLUG_CPU */
-
MODULE_DESCRIPTION("SCSI core");
MODULE_LICENSE("GPL");
@@ -1338,8 +1249,6 @@ static int __init init_scsi(void)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
devfs_mk_dir("scsi");
- open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
- register_scsi_cpu();
printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0;
@@ -1367,7 +1276,6 @@ static void __exit exit_scsi(void)
devfs_remove("scsi");
scsi_exit_procfs();
scsi_exit_queue();
- unregister_scsi_cpu();
}
subsys_initcall(init_scsi);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3ded9daaf4a0..0e529f8171c4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus;
static struct device_driver sdebug_driverfs_driver = {
.name = sdebug_proc_name,
.bus = &pseudo_lld_bus,
- .probe = sdebug_driver_probe,
- .remove = sdebug_driver_remove,
};
static const int check_condition_result =
@@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct device *dev,
static struct bus_type pseudo_lld_bus = {
.name = "pseudo",
.match = pseudo_lld_bus_match,
+ .probe = sdebug_driver_probe,
+ .remove = sdebug_driver_remove,
};
static void sdebug_release_adapter(struct device * dev)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ba93d6e66d48..3574ba935af8 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1212,7 +1212,7 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
return -EOPNOTSUPP;
}
-static void scsi_generic_done(struct scsi_cmnd *cmd)
+static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
{
BUG_ON(!blk_pc_request(cmd->request));
/*
@@ -1224,7 +1224,7 @@ static void scsi_generic_done(struct scsi_cmnd *cmd)
scsi_io_completion(cmd, cmd->bufflen, 0);
}
-void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
+static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
{
struct request *req = cmd->request;
@@ -1241,8 +1241,8 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
cmd->transfersize = req->data_len;
cmd->allowed = req->retries;
cmd->timeout_per_command = req->timeout;
+ cmd->done = scsi_blk_pc_done;
}
-EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
@@ -1339,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* happening now.
*/
if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
- struct scsi_driver *drv;
int ret;
/*
@@ -1371,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
/*
* Initialize the actual SCSI command for this request.
*/
- if (req->rq_disk) {
+ if (req->flags & REQ_BLOCK_PC) {
+ scsi_setup_blk_pc_cmnd(cmd);
+ } else if (req->rq_disk) {
+ struct scsi_driver *drv;
+
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 {
- scsi_setup_blk_pc_cmnd(cmd);
- cmd->done = scsi_generic_done;
}
}
@@ -1493,6 +1493,41 @@ static void scsi_kill_request(struct request *req, request_queue_t *q)
__scsi_done(cmd);
}
+static void scsi_softirq_done(struct request *rq)
+{
+ struct scsi_cmnd *cmd = rq->completion_data;
+ unsigned long wait_for = cmd->allowed * cmd->timeout_per_command;
+ int disposition;
+
+ INIT_LIST_HEAD(&cmd->eh_entry);
+
+ disposition = scsi_decide_disposition(cmd);
+ if (disposition != SUCCESS &&
+ time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ sdev_printk(KERN_ERR, cmd->device,
+ "timing out command, waited %lus\n",
+ wait_for/HZ);
+ disposition = SUCCESS;
+ }
+
+ scsi_log_completion(cmd, disposition);
+
+ switch (disposition) {
+ case SUCCESS:
+ scsi_finish_command(cmd);
+ break;
+ case NEEDS_RETRY:
+ scsi_retry_command(cmd);
+ break;
+ case ADD_TO_MLQUEUE:
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
+ break;
+ default:
+ if (!scsi_eh_scmd_add(cmd, 0))
+ scsi_finish_command(cmd);
+ }
+}
+
/*
* Function: scsi_request_fn()
*
@@ -1667,6 +1702,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary);
blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
+ blk_queue_softirq_done(q, scsi_softirq_done);
if (!shost->use_clustering)
clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index f04e7e11f57a..27c48274e8cb 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -26,12 +26,6 @@ struct Scsi_Host;
#define SCSI_SENSE_VALID(scmd) \
(((scmd)->sense_buffer[0] & 0x70) == 0x70)
-/*
- * Special value for scanning to specify scanning or rescanning of all
- * possible channels, (target) ids, or luns on a given shost.
- */
-#define SCAN_WILD_CARD ~0
-
/* hosts.c */
extern int scsi_init_hosts(void);
extern void scsi_exit_hosts(void);
@@ -44,6 +38,7 @@ extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
struct scsi_request *sreq);
extern void __scsi_release_request(struct scsi_request *sreq);
extern void __scsi_done(struct scsi_cmnd *cmd);
+extern int scsi_retry_command(struct scsi_cmnd *cmd);
#ifdef CONFIG_SCSI_LOGGING
void scsi_log_send(struct scsi_cmnd *cmd);
void scsi_log_completion(struct scsi_cmnd *cmd, int disposition);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index a50958b1b6ee..07be62bbaaea 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -25,11 +25,13 @@
#include <linux/errno.h>
#include <linux/blkdev.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
#include "scsi_priv.h"
#include "scsi_logging.h"
@@ -41,7 +43,7 @@
static struct proc_dir_entry *proc_scsi;
/* Protect sht->present and sht->proc_dir */
-static DECLARE_MUTEX(global_host_template_sem);
+static DEFINE_MUTEX(global_host_template_mutex);
static int proc_scsi_read(char *buffer, char **start, off_t offset,
int length, int *eof, void *data)
@@ -83,7 +85,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
if (!sht->proc_info)
return;
- down(&global_host_template_sem);
+ mutex_lock(&global_host_template_mutex);
if (!sht->present++) {
sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
if (!sht->proc_dir)
@@ -92,7 +94,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
else
sht->proc_dir->owner = sht->module;
}
- up(&global_host_template_sem);
+ mutex_unlock(&global_host_template_mutex);
}
void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
@@ -100,12 +102,12 @@ void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
if (!sht->proc_info)
return;
- down(&global_host_template_sem);
+ mutex_lock(&global_host_template_mutex);
if (!--sht->present && sht->proc_dir) {
remove_proc_entry(sht->proc_name, proc_scsi);
sht->proc_dir = NULL;
}
- up(&global_host_template_sem);
+ mutex_unlock(&global_host_template_mutex);
}
void scsi_proc_host_add(struct Scsi_Host *shost)
@@ -199,7 +201,10 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
if (IS_ERR(shost))
return PTR_ERR(shost);
- error = scsi_scan_host_selected(shost, channel, id, lun, 1);
+ if (shost->transportt->user_scan)
+ error = shost->transportt->user_scan(shost, channel, id, lun);
+ else
+ error = scsi_scan_host_selected(shost, channel, id, lun, 1);
scsi_host_put(shost);
return error;
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 05ebb9cef961..752fb5da3de4 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -334,19 +334,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
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__);
@@ -1283,20 +1270,21 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
struct scsi_device *sdev;
struct device *parent = &shost->shost_gendev;
int res;
- struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+ struct scsi_target *starget;
+ starget = scsi_alloc_target(parent, channel, id);
if (!starget)
return ERR_PTR(-ENOMEM);
get_device(&starget->dev);
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
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);
+ mutex_unlock(&shost->scan_mutex);
scsi_target_reap(starget);
put_device(&starget->dev);
@@ -1404,10 +1392,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
{
struct Scsi_Host *shost = dev_to_shost(parent);
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
if (scsi_host_scan_allowed(shost))
__scsi_scan_target(parent, channel, id, lun, rescan);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_scan_target);
@@ -1454,7 +1442,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
if (scsi_host_scan_allowed(shost)) {
if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel;
@@ -1464,7 +1452,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
else
scsi_scan_channel(shost, channel, id, lun, rescan);
}
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
return 0;
}
@@ -1522,7 +1510,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
struct scsi_device *sdev = NULL;
struct scsi_target *starget;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
if (!scsi_host_scan_allowed(shost))
goto out;
starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
@@ -1536,7 +1524,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
}
put_device(&starget->dev);
out:
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
return sdev;
}
EXPORT_SYMBOL(scsi_get_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index ea7f3a433572..a77b32deaf8f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -106,7 +106,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str)
return -EINVAL;
if (check_set(&lun, s3))
return -EINVAL;
- res = scsi_scan_host_selected(shost, channel, id, lun, 1);
+ if (shost->transportt->user_scan)
+ res = shost->transportt->user_scan(shost, channel, id, lun);
+ else
+ res = scsi_scan_host_selected(shost, channel, id, lun, 1);
return res;
}
@@ -745,9 +748,9 @@ void scsi_remove_device(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
__scsi_remove_device(sdev);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_remove_device);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 685b997306cf..f2c9acf11bd0 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -295,6 +295,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
*/
fc_host_node_name(shost) = -1;
fc_host_port_name(shost) = -1;
+ fc_host_permanent_port_name(shost) = -1;
fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
memset(fc_host_supported_fc4s(shost), 0,
sizeof(fc_host_supported_fc4s(shost)));
@@ -795,6 +796,8 @@ static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
+ unsigned long long);
fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
@@ -1090,17 +1093,23 @@ static int fc_rport_match(struct attribute_container *cont,
/*
* Must be called with shost->host_lock held
*/
-static struct device *fc_target_parent(struct Scsi_Host *shost,
- int channel, uint id)
+static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+ uint id, uint lun)
{
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;
+ list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+ if (rport->scsi_target_id == -1)
+ continue;
- return NULL;
+ if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
+ (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
+ scsi_scan_target(&rport->dev, rport->channel,
+ rport->scsi_target_id, lun, 1);
+ }
+ }
+
+ return 0;
}
struct scsi_transport_template *
@@ -1139,7 +1148,7 @@ 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;
+ i->t.user_scan = fc_user_scan;
/*
* Setup SCSI Target Attributes.
@@ -1160,6 +1169,7 @@ fc_attach_transport(struct fc_function_template *ft)
count=0;
SETUP_HOST_ATTRIBUTE_RD(node_name);
SETUP_HOST_ATTRIBUTE_RD(port_name);
+ SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
SETUP_HOST_ATTRIBUTE_RD(supported_classes);
SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e08462d50c97..59a1c9d9d3bd 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -21,11 +21,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 <linux/mempool.h>
+#include <linux/mutex.h>
#include <net/tcp.h>
-
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
@@ -45,11 +43,6 @@ struct iscsi_internal {
*/
struct list_head sessions;
/*
- * lock to serialize access to the sessions list which must
- * be taken after the rx_queue_sema
- */
- spinlock_t session_lock;
- /*
* based on transport capabilities, at register time we set these
* bits to tell the transport class it wants attributes displayed
* in sysfs or that it can support different iSCSI Data-Path
@@ -70,7 +63,7 @@ struct iscsi_internal {
/*
* list of registered transports and lock that must
* be held while accessing list. The iscsi_transport_lock must
- * be acquired after the rx_queue_sema.
+ * be acquired after the rx_queue_mutex.
*/
static LIST_HEAD(iscsi_transports);
static DEFINE_SPINLOCK(iscsi_transport_lock);
@@ -145,7 +138,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
static struct sock *nls;
static int daemon_pid;
-static DECLARE_MUTEX(rx_queue_sema);
+static DEFINE_MUTEX(rx_queue_mutex);
struct mempool_zone {
mempool_t *pool;
@@ -156,7 +149,7 @@ struct mempool_zone {
spinlock_t freelock;
};
-static struct mempool_zone z_reply;
+static struct mempool_zone *z_reply;
/*
* Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
@@ -171,50 +164,271 @@ static struct mempool_zone z_reply;
#define Z_MAX_ERROR 16
#define Z_HIWAT_ERROR 12
-struct iscsi_if_conn {
- struct list_head conn_list; /* item in connlist */
- struct list_head session_list; /* item in session->connections */
- iscsi_connh_t connh;
- int active; /* must be accessed with the connlock */
- struct Scsi_Host *host; /* originated shost */
- struct device dev; /* sysfs transport/container device */
- struct iscsi_transport *transport;
- struct mempool_zone z_error;
- struct mempool_zone z_pdu;
- struct list_head freequeue;
-};
+static LIST_HEAD(connlist);
+static DEFINE_SPINLOCK(connlock);
-#define iscsi_dev_to_if_conn(_dev) \
- container_of(_dev, struct iscsi_if_conn, dev)
+/*
+ * The following functions can be used by LLDs that allocate
+ * their own scsi_hosts or by software iscsi LLDs
+ */
+static void iscsi_session_release(struct device *dev)
+{
+ struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
+ struct iscsi_transport *transport = session->transport;
+ struct Scsi_Host *shost;
-#define iscsi_cdev_to_if_conn(_cdev) \
- iscsi_dev_to_if_conn(_cdev->dev)
+ shost = iscsi_session_to_shost(session);
+ scsi_host_put(shost);
+ kfree(session);
+ module_put(transport->owner);
+}
-static LIST_HEAD(connlist);
-static DEFINE_SPINLOCK(connlock);
+static int iscsi_is_session_dev(const struct device *dev)
+{
+ return dev->release == iscsi_session_release;
+}
-struct iscsi_if_session {
- struct list_head list; /* item in session_list */
- struct list_head connections;
- iscsi_sessionh_t sessionh;
- struct iscsi_transport *transport;
- struct device dev; /* sysfs transport/container device */
-};
+/**
+ * iscsi_create_session - create iscsi class session
+ * @shost: scsi host
+ * @transport: iscsi transport
+ *
+ * This can be called from a LLD or iscsi_transport
+ **/
+struct iscsi_cls_session *
+iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+{
+ struct iscsi_cls_session *session;
+ int err;
+
+ if (!try_module_get(transport->owner))
+ return NULL;
+
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ goto module_put;
+ session->transport = transport;
+
+ /* this is released in the dev's release function */
+ scsi_host_get(shost);
+ snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
+ session->dev.parent = &shost->shost_gendev;
+ session->dev.release = iscsi_session_release;
+ err = device_register(&session->dev);
+ if (err) {
+ dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
+ "register session's dev\n");
+ goto free_session;
+ }
+ transport_register_device(&session->dev);
+
+ return session;
+
+free_session:
+ kfree(session);
+module_put:
+ module_put(transport->owner);
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_session);
+
+/**
+ * iscsi_destroy_session - destroy iscsi session
+ * @session: iscsi_session
+ *
+ * Can be called by a LLD or iscsi_transport. There must not be
+ * any running connections.
+ **/
+int iscsi_destroy_session(struct iscsi_cls_session *session)
+{
+ transport_unregister_device(&session->dev);
+ device_unregister(&session->dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+
+static void iscsi_conn_release(struct device *dev)
+{
+ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ struct device *parent = conn->dev.parent;
+
+ kfree(conn);
+ put_device(parent);
+}
+
+static int iscsi_is_conn_dev(const struct device *dev)
+{
+ return dev->release == iscsi_conn_release;
+}
+
+/**
+ * iscsi_create_conn - create iscsi class connection
+ * @session: iscsi cls session
+ * @cid: connection id
+ *
+ * This can be called from a LLD or iscsi_transport. The connection
+ * is child of the session so cid must be unique for all connections
+ * on the session.
+ **/
+struct iscsi_cls_conn *
+iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+{
+ struct iscsi_transport *transport = session->transport;
+ struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ struct iscsi_cls_conn *conn;
+ int err;
+
+ conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
+ if (!conn)
+ return NULL;
+
+ if (transport->conndata_size)
+ conn->dd_data = &conn[1];
+
+ INIT_LIST_HEAD(&conn->conn_list);
+ conn->transport = transport;
+
+ /* this is released in the dev's release function */
+ if (!get_device(&session->dev))
+ goto free_conn;
+ snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+ shost->host_no, cid);
+ conn->dev.parent = &session->dev;
+ conn->dev.release = iscsi_conn_release;
+ err = device_register(&conn->dev);
+ if (err) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
+ "connection's dev\n");
+ goto release_parent_ref;
+ }
+ transport_register_device(&conn->dev);
+ return conn;
+
+release_parent_ref:
+ put_device(&session->dev);
+free_conn:
+ kfree(conn);
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_conn);
+
+/**
+ * iscsi_destroy_conn - destroy iscsi class connection
+ * @session: iscsi cls session
+ *
+ * This can be called from a LLD or iscsi_transport.
+ **/
+int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+{
+ transport_unregister_device(&conn->dev);
+ device_unregister(&conn->dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
+
+/*
+ * These functions are used only by software iscsi_transports
+ * which do not allocate and more their scsi_hosts since this
+ * is initiated from userspace.
+ */
+
+/*
+ * iSCSI Session's hostdata organization:
+ *
+ * *------------------* <== hostdata_session(host->hostdata)
+ * | ptr to class sess|
+ * |------------------| <== iscsi_hostdata(host->hostdata)
+ * | transport's data |
+ * *------------------*
+ */
+
+#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \
+ _t->hostdata_size % sizeof(unsigned long))
+
+#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+
+/**
+ * iscsi_transport_create_session - create iscsi cls session and host
+ * scsit: scsi transport template
+ * transport: iscsi transport template
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+struct Scsi_Host *
+iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ struct iscsi_transport *transport)
+{
+ struct iscsi_cls_session *session;
+ struct Scsi_Host *shost;
+
+ shost = scsi_host_alloc(transport->host_template,
+ hostdata_privsize(transport));
+ if (!shost) {
+ printk(KERN_ERR "iscsi: can not allocate SCSI host for "
+ "session\n");
+ return NULL;
+ }
+
+ shost->max_id = 1;
+ shost->max_channel = 0;
+ shost->max_lun = transport->max_lun;
+ shost->max_cmd_len = transport->max_cmd_len;
+ shost->transportt = scsit;
+ shost->transportt->create_work_queue = 1;
+
+ if (scsi_add_host(shost, NULL))
+ goto free_host;
+
+ session = iscsi_create_session(shost, transport);
+ if (!session)
+ goto remove_host;
-#define iscsi_dev_to_if_session(_dev) \
- container_of(_dev, struct iscsi_if_session, dev)
+ *(unsigned long*)shost->hostdata = (unsigned long)session;
+ return shost;
+
+remove_host:
+ scsi_remove_host(shost);
+free_host:
+ scsi_host_put(shost);
+ return NULL;
+}
-#define iscsi_cdev_to_if_session(_cdev) \
- iscsi_dev_to_if_session(_cdev->dev)
+EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
-#define iscsi_if_session_to_shost(_session) \
- dev_to_shost(_session->dev.parent)
+/**
+ * iscsi_transport_destroy_session - destroy session and scsi host
+ * shost: scsi host
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+int iscsi_transport_destroy_session(struct Scsi_Host *shost)
+{
+ struct iscsi_cls_session *session;
-static struct iscsi_if_conn*
+ scsi_remove_host(shost);
+ session = hostdata_session(shost->hostdata);
+ iscsi_destroy_session(session);
+ /* ref from host alloc */
+ scsi_host_put(shost);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
+
+/*
+ * iscsi interface functions
+ */
+static struct iscsi_cls_conn*
iscsi_if_find_conn(uint64_t key)
{
unsigned long flags;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
spin_lock_irqsave(&connlock, flags);
list_for_each_entry(conn, &connlist, conn_list)
@@ -249,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
}
static void*
-mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
{
struct mempool_zone *zone = pool_data;
@@ -281,14 +495,21 @@ mempool_zone_complete(struct mempool_zone *zone)
spin_unlock_irqrestore(&zone->freelock, flags);
}
-static int
-mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
- unsigned hiwat)
+static struct mempool_zone *
+mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
{
+ struct mempool_zone *zp;
+
+ zp = kzalloc(sizeof(*zp), GFP_KERNEL);
+ if (!zp)
+ return NULL;
+
zp->pool = mempool_create(max, mempool_zone_alloc_skb,
mempool_zone_free_skb, zp);
- if (!zp->pool)
- return -ENOMEM;
+ if (!zp->pool) {
+ kfree(zp);
+ return NULL;
+ }
zp->size = size;
zp->hiwat = hiwat;
@@ -297,9 +518,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
spin_lock_init(&zp->freelock);
atomic_set(&zp->allocated, 0);
- return 0;
+ return zp;
}
+static void mempool_zone_destroy(struct mempool_zone *zp)
+{
+ mempool_destroy(zp->pool);
+ kfree(zp);
+}
static struct sk_buff*
mempool_zone_get_skb(struct mempool_zone *zone)
@@ -339,7 +565,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
char *pdu;
int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
data_size);
@@ -347,13 +573,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
conn = iscsi_if_find_conn(connh);
BUG_ON(!conn);
- mempool_zone_complete(&conn->z_pdu);
+ mempool_zone_complete(conn->z_pdu);
- skb = mempool_zone_get_skb(&conn->z_pdu);
+ skb = mempool_zone_get_skb(conn->z_pdu);
if (!skb) {
iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
- printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n",
- conn->host->host_no);
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
+ "control PDU: OOM\n");
return -ENOMEM;
}
@@ -362,14 +588,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
memset(ev, 0, sizeof(*ev));
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_RECV_PDU;
- if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
+ if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
ev->iferror = -ENOMEM;
ev->r.recv_req.conn_handle = connh;
pdu = (char*)ev + sizeof(*ev);
memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
- return iscsi_unicast_skb(&conn->z_pdu, skb);
+ return iscsi_unicast_skb(conn->z_pdu, skb);
}
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
@@ -378,18 +604,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
int len = NLMSG_SPACE(sizeof(*ev));
conn = iscsi_if_find_conn(connh);
BUG_ON(!conn);
- mempool_zone_complete(&conn->z_error);
+ mempool_zone_complete(conn->z_error);
- skb = mempool_zone_get_skb(&conn->z_error);
+ skb = mempool_zone_get_skb(conn->z_error);
if (!skb) {
- printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n",
- conn->host->host_no, error);
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
+ "conn error (%d)\n", error);
return;
}
@@ -397,15 +623,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
ev = NLMSG_DATA(nlh);
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_CONN_ERROR;
- if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat)
+ if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
ev->iferror = -ENOMEM;
ev->r.connerror.error = error;
ev->r.connerror.conn_handle = connh;
- iscsi_unicast_skb(&conn->z_error, skb);
+ iscsi_unicast_skb(conn->z_error, skb);
- printk(KERN_INFO "iscsi%d: detected conn error (%d)\n",
- conn->host->host_no, error);
+ dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+ error);
}
EXPORT_SYMBOL_GPL(iscsi_conn_error);
@@ -419,9 +645,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
int flags = multi ? NLM_F_MULTI : 0;
int t = done ? NLMSG_DONE : type;
- mempool_zone_complete(&z_reply);
+ mempool_zone_complete(z_reply);
- skb = mempool_zone_get_skb(&z_reply);
+ skb = mempool_zone_get_skb(z_reply);
/*
* FIXME:
* user is supposed to react on iferror == -ENOMEM;
@@ -432,366 +658,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
nlh->nlmsg_flags = flags;
memcpy(NLMSG_DATA(nlh), payload, size);
- return iscsi_unicast_skb(&z_reply, skb);
+ return iscsi_unicast_skb(z_reply, skb);
}
-/*
- * iSCSI Session's hostdata organization:
- *
- * *------------------* <== host->hostdata
- * | transport |
- * |------------------| <== iscsi_hostdata(host->hostdata)
- * | transport's data |
- * |------------------| <== hostdata_session(host->hostdata)
- * | interface's data |
- * *------------------*
- */
+static int
+iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+ struct nlmsghdr *nlh)
+{
+ struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ struct iscsi_stats *stats;
+ struct sk_buff *skbstat;
+ struct iscsi_cls_conn *conn;
+ struct nlmsghdr *nlhstat;
+ struct iscsi_uevent *evstat;
+ int len = NLMSG_SPACE(sizeof(*ev) +
+ sizeof(struct iscsi_stats) +
+ sizeof(struct iscsi_stats_custom) *
+ ISCSI_STATS_CUSTOM_MAX);
+ int err = 0;
-#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \
- _t->hostdata_size % sizeof(unsigned long) + \
- sizeof(struct iscsi_if_session))
+ conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
+ if (!conn)
+ return -EEXIST;
-#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \
- ((struct iscsi_transport *) \
- iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
+ do {
+ int actual_size;
-static void iscsi_if_session_dev_release(struct device *dev)
-{
- struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
- struct iscsi_transport *transport = session->transport;
- struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
- struct iscsi_if_conn *conn, *tmp;
- unsigned long flags;
+ mempool_zone_complete(conn->z_pdu);
- /* now free connections */
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry_safe(conn, tmp, &session->connections,
- session_list) {
- list_del(&conn->session_list);
- mempool_destroy(conn->z_pdu.pool);
- mempool_destroy(conn->z_error.pool);
- kfree(conn);
- }
- spin_unlock_irqrestore(&connlock, flags);
- scsi_host_put(shost);
- module_put(transport->owner);
+ skbstat = mempool_zone_get_skb(conn->z_pdu);
+ if (!skbstat) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
+ "deliver stats: OOM\n");
+ return -ENOMEM;
+ }
+
+ nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
+ (len - sizeof(*nlhstat)), 0);
+ evstat = NLMSG_DATA(nlhstat);
+ memset(evstat, 0, sizeof(*evstat));
+ evstat->transport_handle = iscsi_handle(conn->transport);
+ evstat->type = nlh->nlmsg_type;
+ if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+ evstat->iferror = -ENOMEM;
+ evstat->u.get_stats.conn_handle =
+ ev->u.get_stats.conn_handle;
+ stats = (struct iscsi_stats *)
+ ((char*)evstat + sizeof(*evstat));
+ memset(stats, 0, sizeof(*stats));
+
+ transport->get_stats(ev->u.get_stats.conn_handle, stats);
+ actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+ sizeof(struct iscsi_stats) +
+ sizeof(struct iscsi_stats_custom) *
+ stats->custom_length);
+ actual_size -= sizeof(*nlhstat);
+ actual_size = NLMSG_LENGTH(actual_size);
+ skb_trim(skb, NLMSG_ALIGN(actual_size));
+ nlhstat->nlmsg_len = actual_size;
+
+ err = iscsi_unicast_skb(conn->z_pdu, skbstat);
+ } while (err < 0 && err != -ECONNREFUSED);
+
+ return err;
}
static int
iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
{
struct iscsi_transport *transport = priv->iscsi_transport;
- struct iscsi_if_session *session;
struct Scsi_Host *shost;
- unsigned long flags;
- int error;
-
- if (!try_module_get(transport->owner))
- return -EPERM;
- shost = scsi_host_alloc(transport->host_template,
- hostdata_privsize(transport));
- if (!shost) {
- ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
- printk(KERN_ERR "iscsi: can not allocate SCSI host for "
- "session\n");
- error = -ENOMEM;
- goto out_module_put;
- }
- shost->max_id = 1;
- shost->max_channel = 0;
- shost->max_lun = transport->max_lun;
- shost->max_cmd_len = transport->max_cmd_len;
- shost->transportt = &priv->t;
-
- /* store struct iscsi_transport in hostdata */
- *(uint64_t*)shost->hostdata = ev->transport_handle;
+ if (!transport->create_session)
+ return -EINVAL;
- ev->r.c_session_ret.session_handle = transport->create_session(
- ev->u.c_session.initial_cmdsn, shost);
- if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) {
- error = 0;
- goto out_host_put;
- }
+ shost = transport->create_session(&priv->t,
+ ev->u.c_session.initial_cmdsn);
+ if (!shost)
+ return -ENOMEM;
- /* host_no becomes assigned SID */
+ ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
ev->r.c_session_ret.sid = shost->host_no;
- /* initialize session */
- session = hostdata_session(shost->hostdata);
- INIT_LIST_HEAD(&session->connections);
- INIT_LIST_HEAD(&session->list);
- session->sessionh = ev->r.c_session_ret.session_handle;
- session->transport = transport;
-
- error = scsi_add_host(shost, NULL);
- if (error)
- goto out_destroy_session;
-
- /*
- * this is released in the dev's release function)
- */
- scsi_host_get(shost);
- snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
- session->dev.parent = &shost->shost_gendev;
- session->dev.release = iscsi_if_session_dev_release;
- error = device_register(&session->dev);
- if (error) {
- printk(KERN_ERR "iscsi: could not register session%d's dev\n",
- shost->host_no);
- goto out_remove_host;
- }
- transport_register_device(&session->dev);
-
- /* add this session to the list of active sessions */
- spin_lock_irqsave(&priv->session_lock, flags);
- list_add(&session->list, &priv->sessions);
- spin_unlock_irqrestore(&priv->session_lock, flags);
-
return 0;
-
-out_remove_host:
- scsi_remove_host(shost);
-out_destroy_session:
- transport->destroy_session(ev->r.c_session_ret.session_handle);
- ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
-out_host_put:
- scsi_host_put(shost);
-out_module_put:
- module_put(transport->owner);
- return error;
}
static int
iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
{
struct iscsi_transport *transport = priv->iscsi_transport;
+
struct Scsi_Host *shost;
- struct iscsi_if_session *session;
- unsigned long flags;
- struct iscsi_if_conn *conn;
- int error = 0;
+
+ if (!transport->destroy_session)
+ return -EINVAL;
shost = scsi_host_lookup(ev->u.d_session.sid);
if (shost == ERR_PTR(-ENXIO))
return -EEXIST;
- session = hostdata_session(shost->hostdata);
- /* check if we have active connections */
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry(conn, &session->connections, session_list) {
- if (conn->active) {
- printk(KERN_ERR "iscsi%d: can not destroy session: "
- "has active connection (%p)\n",
- shost->host_no, iscsi_ptr(conn->connh));
- spin_unlock_irqrestore(&connlock, flags);
- error = EIO;
- goto out_release_ref;
- }
- }
- spin_unlock_irqrestore(&connlock, flags);
-
- scsi_remove_host(shost);
- transport->destroy_session(ev->u.d_session.session_handle);
- transport_unregister_device(&session->dev);
- device_unregister(&session->dev);
-
- /* remove this session from the list of active sessions */
- spin_lock_irqsave(&priv->session_lock, flags);
- list_del(&session->list);
- spin_unlock_irqrestore(&priv->session_lock, flags);
-
- /* ref from host alloc */
- scsi_host_put(shost);
-out_release_ref:
- /* ref from host lookup */
- scsi_host_put(shost);
- return error;
-}
-
-static void iscsi_if_conn_dev_release(struct device *dev)
-{
- struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
- struct Scsi_Host *shost = conn->host;
-
- scsi_host_put(shost);
+ if (transport->destroy_session)
+ transport->destroy_session(shost);
+ /* ref from host lookup */
+ scsi_host_put(shost);
+ return 0;
}
static int
-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
-{
- struct iscsi_if_session *session;
+iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
struct Scsi_Host *shost;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
unsigned long flags;
- int error;
+
+ if (!transport->create_conn)
+ return -EINVAL;
shost = scsi_host_lookup(ev->u.c_conn.sid);
if (shost == ERR_PTR(-ENXIO))
return -EEXIST;
- session = hostdata_session(shost->hostdata);
- conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL);
- if (!conn) {
- error = -ENOMEM;
- goto out_release_ref;
- }
- memset(conn, 0, sizeof(struct iscsi_if_conn));
- INIT_LIST_HEAD(&conn->session_list);
- INIT_LIST_HEAD(&conn->conn_list);
- conn->host = shost;
- conn->transport = transport;
+ conn = transport->create_conn(shost, ev->u.c_conn.cid);
+ if (!conn)
+ goto release_ref;
- error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU,
+ conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
NLMSG_SPACE(sizeof(struct iscsi_uevent) +
sizeof(struct iscsi_hdr) +
DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
Z_HIWAT_PDU);
- if (error) {
- printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new "
- "conn\n", shost->host_no);
- goto out_free_conn;
+ if (!conn->z_pdu) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+ "pdu zone for new conn\n");
+ goto destroy_conn;
}
- error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR,
+
+ conn->z_error = mempool_zone_init(Z_MAX_ERROR,
NLMSG_SPACE(sizeof(struct iscsi_uevent)),
Z_HIWAT_ERROR);
- if (error) {
- printk(KERN_ERR "iscsi%d: can not allocate error zone for "
- "new conn\n", shost->host_no);
- goto out_free_pdu_pool;
- }
-
- ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
- ev->u.c_conn.cid);
- if (!ev->r.handle) {
- error = -ENODEV;
- goto out_free_error_pool;
+ if (!conn->z_error) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+ "error zone for new conn\n");
+ goto free_pdu_pool;
}
- conn->connh = ev->r.handle;
-
- /*
- * this is released in the dev's release function
- */
- if (!scsi_host_get(shost))
- goto out_destroy_conn;
- snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
- shost->host_no, ev->u.c_conn.cid);
- conn->dev.parent = &session->dev;
- conn->dev.release = iscsi_if_conn_dev_release;
- error = device_register(&conn->dev);
- if (error) {
- printk(KERN_ERR "iscsi%d: could not register connections%u "
- "dev\n", shost->host_no, ev->u.c_conn.cid);
- goto out_release_parent_ref;
- }
- transport_register_device(&conn->dev);
+ ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
spin_lock_irqsave(&connlock, flags);
list_add(&conn->conn_list, &connlist);
- list_add(&conn->session_list, &session->connections);
conn->active = 1;
spin_unlock_irqrestore(&connlock, flags);
scsi_host_put(shost);
return 0;
-out_release_parent_ref:
+free_pdu_pool:
+ mempool_zone_destroy(conn->z_pdu);
+destroy_conn:
+ if (transport->destroy_conn)
+ transport->destroy_conn(conn->dd_data);
+release_ref:
scsi_host_put(shost);
-out_destroy_conn:
- transport->destroy_conn(ev->r.handle);
-out_free_error_pool:
- mempool_destroy(conn->z_error.pool);
-out_free_pdu_pool:
- mempool_destroy(conn->z_pdu.pool);
-out_free_conn:
- kfree(conn);
-out_release_ref:
- scsi_host_put(shost);
- return error;
+ return -ENOMEM;
}
static int
iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
{
unsigned long flags;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
+ struct mempool_zone *z_error, *z_pdu;
conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
if (!conn)
return -EEXIST;
- transport->destroy_conn(ev->u.d_conn.conn_handle);
+ if (!transport->destroy_conn)
+ return -EINVAL;
spin_lock_irqsave(&connlock, flags);
conn->active = 0;
list_del(&conn->conn_list);
spin_unlock_irqrestore(&connlock, flags);
- transport_unregister_device(&conn->dev);
- device_unregister(&conn->dev);
- return 0;
-}
-
-static int
-iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
- struct nlmsghdr *nlh)
-{
- struct iscsi_uevent *ev = NLMSG_DATA(nlh);
- struct iscsi_stats *stats;
- struct sk_buff *skbstat;
- struct iscsi_if_conn *conn;
- struct nlmsghdr *nlhstat;
- struct iscsi_uevent *evstat;
- int len = NLMSG_SPACE(sizeof(*ev) +
- sizeof(struct iscsi_stats) +
- sizeof(struct iscsi_stats_custom) *
- ISCSI_STATS_CUSTOM_MAX);
- int err = 0;
-
- conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
- if (!conn)
- return -EEXIST;
-
- do {
- int actual_size;
-
- mempool_zone_complete(&conn->z_pdu);
-
- skbstat = mempool_zone_get_skb(&conn->z_pdu);
- if (!skbstat) {
- printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
- conn->host->host_no);
- return -ENOMEM;
- }
-
- nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
- (len - sizeof(*nlhstat)), 0);
- evstat = NLMSG_DATA(nlhstat);
- memset(evstat, 0, sizeof(*evstat));
- evstat->transport_handle = iscsi_handle(conn->transport);
- evstat->type = nlh->nlmsg_type;
- if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
- evstat->iferror = -ENOMEM;
- evstat->u.get_stats.conn_handle =
- ev->u.get_stats.conn_handle;
- stats = (struct iscsi_stats *)
- ((char*)evstat + sizeof(*evstat));
- memset(stats, 0, sizeof(*stats));
+ z_pdu = conn->z_pdu;
+ z_error = conn->z_error;
- transport->get_stats(ev->u.get_stats.conn_handle, stats);
- actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
- sizeof(struct iscsi_stats) +
- sizeof(struct iscsi_stats_custom) *
- stats->custom_length);
- actual_size -= sizeof(*nlhstat);
- actual_size = NLMSG_LENGTH(actual_size);
- skb_trim(skb, NLMSG_ALIGN(actual_size));
- nlhstat->nlmsg_len = actual_size;
+ if (transport->destroy_conn)
+ transport->destroy_conn(conn);
- err = iscsi_unicast_skb(&conn->z_pdu, skbstat);
- } while (err < 0 && err != -ECONNREFUSED);
+ mempool_zone_destroy(z_pdu);
+ mempool_zone_destroy(z_error);
- return err;
+ return 0;
}
static int
@@ -881,7 +938,7 @@ iscsi_if_rx(struct sock *sk, int len)
{
struct sk_buff *skb;
- down(&rx_queue_sema);
+ mutex_lock(&rx_queue_mutex);
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
while (skb->len >= NLMSG_SPACE(0)) {
int err;
@@ -915,17 +972,20 @@ iscsi_if_rx(struct sock *sk, int len)
err = iscsi_if_send_reply(
NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
- if (atomic_read(&z_reply.allocated) >=
- z_reply.hiwat)
+ if (atomic_read(&z_reply->allocated) >=
+ z_reply->hiwat)
ev->iferror = -ENOMEM;
} while (err < 0 && err != -ECONNREFUSED);
skb_pull(skb, rlen);
}
kfree_skb(skb);
}
- up(&rx_queue_sema);
+ mutex_unlock(&rx_queue_mutex);
}
+#define iscsi_cdev_to_conn(_cdev) \
+ iscsi_dev_to_conn(_cdev->dev)
+
/*
* iSCSI connection attrs
*/
@@ -934,12 +994,10 @@ static ssize_t \
show_conn_int_param_##param(struct class_device *cdev, char *buf) \
{ \
uint32_t value = 0; \
- struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \
- struct iscsi_internal *priv; \
+ struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
+ struct iscsi_transport *t = conn->transport; \
\
- priv = to_iscsi_internal(conn->host->transportt); \
- if (priv->param_mask & (1 << param)) \
- priv->iscsi_transport->get_param(conn->connh, param, &value); \
+ t->get_conn_param(conn->dd_data, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -954,6 +1012,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
+#define iscsi_cdev_to_session(_cdev) \
+ iscsi_dev_to_session(_cdev->dev)
+
/*
* iSCSI session attrs
*/
@@ -962,20 +1023,11 @@ static ssize_t \
show_session_int_param_##param(struct class_device *cdev, char *buf) \
{ \
uint32_t value = 0; \
- struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \
- struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \
- struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
- struct iscsi_if_conn *conn = NULL; \
- unsigned long flags; \
- \
- spin_lock_irqsave(&connlock, flags); \
- if (!list_empty(&session->connections)) \
- conn = list_entry(session->connections.next, \
- struct iscsi_if_conn, session_list); \
- spin_unlock_irqrestore(&connlock, flags); \
+ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct Scsi_Host *shost = iscsi_session_to_shost(session); \
+ struct iscsi_transport *t = session->transport; \
\
- if (conn && (priv->param_mask & (1 << param))) \
- priv->iscsi_transport->get_param(conn->connh, param, &value);\
+ t->get_session_param(shost, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -1004,23 +1056,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
count++; \
}
-static int iscsi_is_session_dev(const struct device *dev)
-{
- return dev->release == iscsi_if_session_dev_release;
-}
-
static int iscsi_session_match(struct attribute_container *cont,
struct device *dev)
{
- struct iscsi_if_session *session;
+ struct iscsi_cls_session *session;
struct Scsi_Host *shost;
struct iscsi_internal *priv;
if (!iscsi_is_session_dev(dev))
return 0;
- session = iscsi_dev_to_if_session(dev);
- shost = iscsi_if_session_to_shost(session);
+ session = iscsi_dev_to_session(dev);
+ shost = iscsi_session_to_shost(session);
if (!shost->transportt)
return 0;
@@ -1031,23 +1078,21 @@ static int iscsi_session_match(struct attribute_container *cont,
return &priv->session_cont.ac == cont;
}
-static int iscsi_is_conn_dev(const struct device *dev)
-{
- return dev->release == iscsi_if_conn_dev_release;
-}
-
static int iscsi_conn_match(struct attribute_container *cont,
struct device *dev)
{
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_session *session;
+ struct iscsi_cls_conn *conn;
struct Scsi_Host *shost;
struct iscsi_internal *priv;
if (!iscsi_is_conn_dev(dev))
return 0;
- conn = iscsi_dev_to_if_conn(dev);
- shost = conn->host;
+ conn = iscsi_dev_to_conn(dev);
+ session = iscsi_dev_to_session(conn->dev.parent);
+ shost = iscsi_session_to_shost(session);
+
if (!shost->transportt)
return 0;
@@ -1058,7 +1103,8 @@ static int iscsi_conn_match(struct attribute_container *cont,
return &priv->conn_cont.ac == cont;
}
-int iscsi_register_transport(struct iscsi_transport *tt)
+struct scsi_transport_template *
+iscsi_register_transport(struct iscsi_transport *tt)
{
struct iscsi_internal *priv;
unsigned long flags;
@@ -1068,15 +1114,14 @@ int iscsi_register_transport(struct iscsi_transport *tt)
priv = iscsi_if_transport_lookup(tt);
if (priv)
- return -EEXIST;
+ return NULL;
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
- return -ENOMEM;
+ return NULL;
memset(priv, 0, sizeof(*priv));
INIT_LIST_HEAD(&priv->list);
INIT_LIST_HEAD(&priv->sessions);
- spin_lock_init(&priv->session_lock);
priv->iscsi_transport = tt;
priv->cdev.class = &iscsi_transport_class;
@@ -1142,13 +1187,13 @@ int iscsi_register_transport(struct iscsi_transport *tt)
spin_unlock_irqrestore(&iscsi_transport_lock, flags);
printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
- return 0;
+ return &priv->t;
unregister_cdev:
class_device_unregister(&priv->cdev);
free_priv:
kfree(priv);
- return err;
+ return NULL;
}
EXPORT_SYMBOL_GPL(iscsi_register_transport);
@@ -1159,19 +1204,11 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
BUG_ON(!tt);
- down(&rx_queue_sema);
+ mutex_lock(&rx_queue_mutex);
priv = iscsi_if_transport_lookup(tt);
BUG_ON (!priv);
- spin_lock_irqsave(&priv->session_lock, flags);
- if (!list_empty(&priv->sessions)) {
- spin_unlock_irqrestore(&priv->session_lock, flags);
- up(&rx_queue_sema);
- return -EPERM;
- }
- spin_unlock_irqrestore(&priv->session_lock, flags);
-
spin_lock_irqsave(&iscsi_transport_lock, flags);
list_del(&priv->list);
spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -1181,7 +1218,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
class_device_unregister(&priv->cdev);
- up(&rx_queue_sema);
+ mutex_unlock(&rx_queue_mutex);
return 0;
}
@@ -1194,14 +1231,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
if (event == NETLINK_URELEASE &&
n->protocol == NETLINK_ISCSI && n->pid) {
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
unsigned long flags;
- mempool_zone_complete(&z_reply);
+ mempool_zone_complete(z_reply);
spin_lock_irqsave(&connlock, flags);
list_for_each_entry(conn, &connlist, conn_list) {
- mempool_zone_complete(&conn->z_error);
- mempool_zone_complete(&conn->z_pdu);
+ mempool_zone_complete(conn->z_error);
+ mempool_zone_complete(conn->z_pdu);
}
spin_unlock_irqrestore(&connlock, flags);
}
@@ -1234,15 +1271,15 @@ static __init int iscsi_transport_init(void)
goto unregister_session_class;
nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
- THIS_MODULE);
+ THIS_MODULE);
if (!nls) {
err = -ENOBUFS;
goto unregister_notifier;
}
- err = mempool_zone_init(&z_reply, Z_MAX_REPLY,
+ z_reply = mempool_zone_init(Z_MAX_REPLY,
NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
- if (!err)
+ if (z_reply)
return 0;
sock_release(nls->sk_socket);
@@ -1259,7 +1296,7 @@ unregister_transport_class:
static void __exit iscsi_transport_exit(void)
{
- mempool_destroy(z_reply.pool);
+ mempool_zone_destroy(z_reply);
sock_release(nls->sk_socket);
netlink_unregister_notifier(&iscsi_nl_notifier);
transport_class_unregister(&iscsi_connection_class);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index edabbd05d258..a3e0b7bc2d7b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/string.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
@@ -62,7 +63,7 @@ struct sas_internal {
struct sas_host_attrs {
struct list_head rphy_list;
- spinlock_t lock;
+ struct mutex lock;
u32 next_target_id;
};
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
@@ -165,7 +166,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *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);
+ mutex_init(&sas_host->lock);
sas_host->next_target_id = 0;
return 0;
}
@@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
transport_add_device(&rphy->dev);
transport_configure_device(&rphy->dev);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_add_tail(&rphy->list, &sas_host->rphy_list);
if (identify->device_type == SAS_END_DEVICE &&
(identify->target_port_protocols &
@@ -634,10 +635,10 @@ int sas_rphy_add(struct sas_rphy *rphy)
rphy->scsi_target_id = sas_host->next_target_id++;
else
rphy->scsi_target_id = -1;
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
if (rphy->scsi_target_id != -1) {
- scsi_scan_target(&rphy->dev, parent->number,
+ scsi_scan_target(&rphy->dev, parent->port_identifier,
rphy->scsi_target_id, ~0, 0);
}
@@ -661,9 +662,9 @@ 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);
+ mutex_lock(&sas_host->lock);
list_del(&rphy->list);
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
transport_destroy_device(&rphy->dev);
put_device(rphy->dev.parent);
@@ -687,15 +688,27 @@ sas_rphy_delete(struct sas_rphy *rphy)
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);
+ switch (rphy->identify.device_type) {
+ case SAS_END_DEVICE:
+ scsi_remove_target(dev);
+ break;
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
+ device_for_each_child(dev, NULL, do_sas_phy_delete);
+ break;
+ default:
+ break;
+ }
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_del(&rphy->list);
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
+
+ parent->rphy = NULL;
put_device(&parent->dev);
}
@@ -719,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy);
* SCSI scan helper
*/
-static struct device *sas_target_parent(struct Scsi_Host *shost,
- int channel, uint id)
+static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ uint id, uint lun)
{
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
struct sas_rphy *rphy;
- struct device *dev = NULL;
- spin_lock(&sas_host->lock);
+ mutex_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;
+
+ if (rphy->scsi_target_id == -1)
+ continue;
+
+ if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
+ (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
+ scsi_scan_target(&rphy->dev, parent->port_identifier,
+ rphy->scsi_target_id, lun, 1);
+ }
}
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
- return dev;
+ return 0;
}
@@ -780,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft)
return NULL;
memset(i, 0, sizeof(struct sas_internal));
- i->t.target_parent = sas_target_parent;
+ i->t.user_scan = sas_user_scan;
i->t.host_attrs.ac.attrs = &i->host_attrs[0];
i->t.host_attrs.ac.class = &sas_host_class.class;
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 46da6fe10ad5..7ee95eb83dda 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -24,7 +24,7 @@
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/blkdev.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
@@ -48,7 +48,7 @@
/* Private data accessors (keep these out of the header file) */
#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
-#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem)
+#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
struct spi_internal {
struct scsi_transport_template t;
@@ -242,7 +242,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc,
spi_hold_mcs(starget) = 0;
spi_dv_pending(starget) = 0;
spi_initial_dv(starget) = 0;
- init_MUTEX(&spi_dv_sem(starget));
+ mutex_init(&spi_dv_mutex(starget));
return 0;
}
@@ -915,7 +915,7 @@ spi_dv_device(struct scsi_device *sdev)
scsi_target_quiesce(starget);
spi_dv_pending(starget) = 1;
- down(&spi_dv_sem(starget));
+ mutex_lock(&spi_dv_mutex(starget));
starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");
@@ -923,7 +923,7 @@ spi_dv_device(struct scsi_device *sdev)
starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");
- up(&spi_dv_sem(starget));
+ mutex_unlock(&spi_dv_mutex(starget));
spi_dv_pending(starget) = 0;
scsi_target_resume(starget);
@@ -1075,7 +1075,7 @@ static const char * const extended_msgs[] = {
/* 0x04 */ "Parallel Protocol Request"
};
-void print_nego(const unsigned char *msg, int per, int off, int width)
+static void print_nego(const unsigned char *msg, int per, int off, int width)
{
if (per) {
char buf[20];
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 32d4d8d7b9f3..930db398d107 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -49,6 +49,7 @@
#include <linux/blkpg.h>
#include <linux/kref.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -111,7 +112,7 @@ static DEFINE_SPINLOCK(sd_index_lock);
/* This semaphore is used to mediate the 0->1 reference get in the
* face of object destruction (i.e. we can't allow a get on an
* object after last put) */
-static DECLARE_MUTEX(sd_ref_sem);
+static DEFINE_MUTEX(sd_ref_mutex);
static int sd_revalidate_disk(struct gendisk *disk);
static void sd_rw_intr(struct scsi_cmnd * SCpnt);
@@ -193,9 +194,9 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
{
struct scsi_disk *sdkp;
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
sdkp = __scsi_disk_get(disk);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
return sdkp;
}
@@ -203,11 +204,11 @@ static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
{
struct scsi_disk *sdkp;
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
sdkp = dev_get_drvdata(dev);
if (sdkp)
sdkp = __scsi_disk_get(sdkp->disk);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
return sdkp;
}
@@ -215,10 +216,10 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
{
struct scsi_device *sdev = sdkp->device;
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
kref_put(&sdkp->kref, scsi_disk_release);
scsi_device_put(sdev);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
}
/**
@@ -231,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
**/
static int sd_init_command(struct scsi_cmnd * SCpnt)
{
- unsigned int this_count, timeout;
- struct gendisk *disk;
- sector_t block;
struct scsi_device *sdp = SCpnt->device;
struct request *rq = SCpnt->request;
-
- timeout = sdp->timeout;
-
- /*
- * SG_IO from block layer already setup, just copy cdb basically
- */
- if (blk_pc_request(rq)) {
- scsi_setup_blk_pc_cmnd(SCpnt);
- if (rq->timeout)
- timeout = rq->timeout;
-
- goto queue;
- }
-
- /*
- * we only do REQ_CMD and REQ_BLOCK_PC
- */
- if (!blk_fs_request(rq))
- return 0;
-
- disk = rq->rq_disk;
- block = rq->sector;
- this_count = SCpnt->request_bufflen >> 9;
+ struct gendisk *disk = rq->rq_disk;
+ sector_t block = rq->sector;
+ unsigned int this_count = SCpnt->request_bufflen >> 9;
+ unsigned int timeout = sdp->timeout;
SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
"count=%d\n", disk->disk_name,
@@ -401,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->transfersize = sdp->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = SD_MAX_RETRIES;
-
-queue:
SCpnt->timeout_per_command = timeout;
/*
@@ -527,7 +504,7 @@ static int sd_release(struct inode *inode, struct file *filp)
return 0;
}
-static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc)
+static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdp = sdkp->device;
@@ -545,15 +522,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *
else
scsicam_bios_param(bdev, sdkp->capacity, diskinfo);
- if (put_user(diskinfo[0], &loc->heads))
- return -EFAULT;
- if (put_user(diskinfo[1], &loc->sectors))
- return -EFAULT;
- if (put_user(diskinfo[2], &loc->cylinders))
- return -EFAULT;
- if (put_user((unsigned)get_start_sect(bdev),
- (unsigned long __user *)&loc->start))
- return -EFAULT;
+ geo->heads = diskinfo[0];
+ geo->sectors = diskinfo[1];
+ geo->cylinders = diskinfo[2];
return 0;
}
@@ -593,12 +564,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
if (!scsi_block_when_processing_errors(sdp) || !error)
return error;
- if (cmd == HDIO_GETGEO) {
- if (!arg)
- return -EINVAL;
- return sd_hdio_getgeo(bdev, p);
- }
-
/*
* Send SCSI addressing ioctls directly to mid level, send other
* ioctls to block level and then onto mid level if they can't be
@@ -800,6 +765,7 @@ static struct block_device_operations sd_fops = {
.open = sd_open,
.release = sd_release,
.ioctl = sd_ioctl,
+ .getgeo = sd_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = sd_compat_ioctl,
#endif
@@ -847,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
relatively rare error condition, no care is taken to avoid
unnecessary additional work such as memcpy's that could be avoided.
*/
-
- /*
- * If SG_IO from block layer then set good_bytes to stop retries;
- * else if errors, check them, and if necessary prepare for
- * (partial) retries.
- */
- if (blk_pc_request(SCpnt->request))
- good_bytes = this_count;
- else if (driver_byte(result) != 0 &&
+ if (driver_byte(result) != 0 &&
sense_valid && !sense_deferred) {
switch (sshdr.sense_key) {
case MEDIUM_ERROR:
@@ -1646,10 +1604,10 @@ static int sd_remove(struct device *dev)
del_gendisk(sdkp->disk);
sd_shutdown(dev);
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
dev_set_drvdata(dev, NULL);
kref_put(&sdkp->kref, scsi_disk_release);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
return 0;
}
@@ -1658,7 +1616,7 @@ static int sd_remove(struct device *dev)
* scsi_disk_release - Called to free the scsi_disk structure
* @kref: pointer to embedded kref
*
- * sd_ref_sem must be held entering this routine. Because it is
+ * sd_ref_mutex must be held entering this routine. Because it is
* called on last put, you should always use the scsi_disk_get()
* scsi_disk_put() helpers which manipulate the semaphore directly
* and never do a direct kref_put().
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 221e96e2620a..78aad9582bcf 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2493,7 +2493,7 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
}
if (resp) {
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- memset(resp, 0, resSz);
+ memset(page_address(resp), 0, resSz);
if (retSzp)
*retSzp = resSz;
}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index a4d9be7c6874..997f8e30509b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -44,6 +44,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/blkdev.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -90,7 +91,7 @@ static DEFINE_SPINLOCK(sr_index_lock);
/* This semaphore is used to mediate the 0->1 reference get in the
* face of object destruction (i.e. we can't allow a get on an
* object after last put) */
-static DECLARE_MUTEX(sr_ref_sem);
+static DEFINE_MUTEX(sr_ref_mutex);
static int sr_open(struct cdrom_device_info *, int);
static void sr_release(struct cdrom_device_info *);
@@ -133,7 +134,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
{
struct scsi_cd *cd = NULL;
- down(&sr_ref_sem);
+ mutex_lock(&sr_ref_mutex);
if (disk->private_data == NULL)
goto out;
cd = scsi_cd(disk);
@@ -146,18 +147,18 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
kref_put(&cd->kref, sr_kref_release);
cd = NULL;
out:
- up(&sr_ref_sem);
+ mutex_unlock(&sr_ref_mutex);
return cd;
}
-static inline void scsi_cd_put(struct scsi_cd *cd)
+static void scsi_cd_put(struct scsi_cd *cd)
{
struct scsi_device *sdev = cd->device;
- down(&sr_ref_sem);
+ mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
scsi_device_put(sdev);
- up(&sr_ref_sem);
+ mutex_unlock(&sr_ref_mutex);
}
/*
@@ -237,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
case ILLEGAL_REQUEST:
if (!(SCpnt->sense_buffer[0] & 0x90))
break;
- if (!blk_fs_request(SCpnt->request))
- break;
error_sector = (SCpnt->sense_buffer[3] << 24) |
(SCpnt->sense_buffer[4] << 16) |
(SCpnt->sense_buffer[5] << 8) |
@@ -317,23 +316,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
}
/*
- * these are already setup, just copy cdb basically
- */
- if (SCpnt->request->flags & REQ_BLOCK_PC) {
- scsi_setup_blk_pc_cmnd(SCpnt);
-
- if (SCpnt->timeout_per_command)
- timeout = SCpnt->timeout_per_command;
-
- goto queue;
- }
-
- if (!(SCpnt->request->flags & REQ_CMD)) {
- blk_dump_rq_flags(SCpnt->request, "sr unsup command");
- return 0;
- }
-
- /*
* we do lazy blocksize switching (when reading XA sectors,
* see CDROMREADMODE2 ioctl)
*/
@@ -421,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
*/
SCpnt->transfersize = cd->device->sector_size;
SCpnt->underflow = this_count << 9;
-
-queue:
SCpnt->allowed = MAX_RETRIES;
SCpnt->timeout_per_command = timeout;
@@ -762,8 +742,9 @@ static void get_capabilities(struct scsi_cd *cd)
/* failed, drive doesn't have capabilities mode page */
cd->cdi.speed = 1;
cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
- CDC_DVD | CDC_DVD_RAM |
- CDC_SELECT_DISC | CDC_SELECT_SPEED);
+ CDC_DVD | CDC_DVD_RAM |
+ CDC_SELECT_DISC | CDC_SELECT_SPEED |
+ CDC_MRW | CDC_MRW_W | CDC_RAM);
kfree(buffer);
printk("%s: scsi-1 drive\n", cd->cdi.name);
return;
@@ -845,7 +826,7 @@ static int sr_packet(struct cdrom_device_info *cdi,
* sr_kref_release - Called to free the scsi_cd structure
* @kref: pointer to embedded kref
*
- * sr_ref_sem must be held entering this routine. Because it is
+ * sr_ref_mutex must be held entering this routine. Because it is
* called on last put, you should always use the scsi_cd_get()
* scsi_cd_put() helpers which manipulate the semaphore directly
* and never do a direct kref_put().
@@ -874,9 +855,9 @@ static int sr_remove(struct device *dev)
del_gendisk(cd->disk);
- down(&sr_ref_sem);
+ mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
- up(&sr_ref_sem);
+ mutex_unlock(&sr_ref_mutex);
return 0;
}
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 6e45ac3c43c5..5d02ff4db6cc 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -31,6 +31,79 @@ static int xa_test = 0;
module_param(xa_test, int, S_IRUGO | S_IWUSR);
+/* primitive to determine whether we need to have GFP_DMA set based on
+ * the status of the unchecked_isa_dma flag in the host structure */
+#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
+
+
+static int sr_read_tochdr(struct cdrom_device_info *cdi,
+ struct cdrom_tochdr *tochdr)
+{
+ struct scsi_cd *cd = cdi->handle;
+ struct packet_command cgc;
+ int result;
+ unsigned char *buffer;
+
+ buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+ if (!buffer)
+ return -ENOMEM;
+
+ memset(&cgc, 0, sizeof(struct packet_command));
+ cgc.timeout = IOCTL_TIMEOUT;
+ cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+ cgc.cmd[8] = 12; /* LSB of length */
+ cgc.buffer = buffer;
+ cgc.buflen = 12;
+ cgc.quiet = 1;
+ cgc.data_direction = DMA_FROM_DEVICE;
+
+ result = sr_do_ioctl(cd, &cgc);
+
+ tochdr->cdth_trk0 = buffer[2];
+ tochdr->cdth_trk1 = buffer[3];
+
+ kfree(buffer);
+ return result;
+}
+
+static int sr_read_tocentry(struct cdrom_device_info *cdi,
+ struct cdrom_tocentry *tocentry)
+{
+ struct scsi_cd *cd = cdi->handle;
+ struct packet_command cgc;
+ int result;
+ unsigned char *buffer;
+
+ buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+ if (!buffer)
+ return -ENOMEM;
+
+ memset(&cgc, 0, sizeof(struct packet_command));
+ cgc.timeout = IOCTL_TIMEOUT;
+ cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+ cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
+ cgc.cmd[6] = tocentry->cdte_track;
+ cgc.cmd[8] = 12; /* LSB of length */
+ cgc.buffer = buffer;
+ cgc.buflen = 12;
+ cgc.data_direction = DMA_FROM_DEVICE;
+
+ result = sr_do_ioctl(cd, &cgc);
+
+ tocentry->cdte_ctrl = buffer[5] & 0xf;
+ tocentry->cdte_adr = buffer[5] >> 4;
+ tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
+ if (tocentry->cdte_format == CDROM_MSF) {
+ tocentry->cdte_addr.msf.minute = buffer[9];
+ tocentry->cdte_addr.msf.second = buffer[10];
+ tocentry->cdte_addr.msf.frame = buffer[11];
+ } else
+ tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
+ + buffer[10]) << 8) + buffer[11];
+
+ kfree(buffer);
+ return result;
+}
#define IOCTL_RETRIES 3
@@ -45,7 +118,8 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
struct packet_command cgc;
int ntracks, ret;
- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr)))
+ ret = sr_read_tochdr(cdi, &tochdr);
+ if (ret)
return ret;
ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
@@ -60,9 +134,11 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
trk1_te.cdte_track = ti->cdti_trk1;
trk1_te.cdte_format = CDROM_MSF;
- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te)))
+ ret = sr_read_tocentry(cdi, &trk0_te);
+ if (ret)
return ret;
- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te)))
+ ret = sr_read_tocentry(cdi, &trk1_te);
+ if (ret)
return ret;
memset(&cgc, 0, sizeof(struct packet_command));
@@ -78,6 +154,30 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
return sr_do_ioctl(cdi->handle, &cgc);
}
+static int sr_play_trkind(struct cdrom_device_info *cdi,
+ struct cdrom_ti *ti)
+
+{
+ struct scsi_cd *cd = cdi->handle;
+ struct packet_command cgc;
+ int result;
+
+ memset(&cgc, 0, sizeof(struct packet_command));
+ cgc.timeout = IOCTL_TIMEOUT;
+ cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
+ cgc.cmd[4] = ti->cdti_trk0;
+ cgc.cmd[5] = ti->cdti_ind0;
+ cgc.cmd[7] = ti->cdti_trk1;
+ cgc.cmd[8] = ti->cdti_ind1;
+ cgc.data_direction = DMA_NONE;
+
+ result = sr_do_ioctl(cd, &cgc);
+ if (result == -EDRIVE_CANT_DO_THIS)
+ result = sr_fake_playtrkind(cdi, ti);
+
+ return result;
+}
+
/* We do our own retries because we want to know what the specific
error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */
@@ -229,13 +329,14 @@ int sr_disk_status(struct cdrom_device_info *cdi)
int i, rc, have_datatracks = 0;
/* look for data tracks */
- if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h)))
+ rc = sr_read_tochdr(cdi, &toc_h);
+ if (rc)
return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
toc_e.cdte_track = i;
toc_e.cdte_format = CDROM_LBA;
- if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e))
+ if (sr_read_tocentry(cdi, &toc_e))
return CDS_NO_INFO;
if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {
have_datatracks = 1;
@@ -262,10 +363,6 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
return 0;
}
-/* primitive to determine whether we need to have GFP_DMA set based on
- * the status of the unchecked_isa_dma flag in the host structure */
-#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
-
int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
{
Scsi_CD *cd = cdi->handle;
@@ -329,93 +426,16 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
{
- Scsi_CD *cd = cdi->handle;
- struct packet_command cgc;
- int result;
- unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
-
- if (!buffer)
- return -ENOMEM;
-
- memset(&cgc, 0, sizeof(struct packet_command));
- cgc.timeout = IOCTL_TIMEOUT;
-
switch (cmd) {
case CDROMREADTOCHDR:
- {
- struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
-
- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[8] = 12; /* LSB of length */
- cgc.buffer = buffer;
- cgc.buflen = 12;
- cgc.quiet = 1;
- cgc.data_direction = DMA_FROM_DEVICE;
-
- result = sr_do_ioctl(cd, &cgc);
-
- tochdr->cdth_trk0 = buffer[2];
- tochdr->cdth_trk1 = buffer[3];
-
- break;
- }
-
+ return sr_read_tochdr(cdi, arg);
case CDROMREADTOCENTRY:
- {
- struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
-
- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
- cgc.cmd[6] = tocentry->cdte_track;
- cgc.cmd[8] = 12; /* LSB of length */
- cgc.buffer = buffer;
- cgc.buflen = 12;
- cgc.data_direction = DMA_FROM_DEVICE;
-
- result = sr_do_ioctl(cd, &cgc);
-
- tocentry->cdte_ctrl = buffer[5] & 0xf;
- tocentry->cdte_adr = buffer[5] >> 4;
- tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
- if (tocentry->cdte_format == CDROM_MSF) {
- tocentry->cdte_addr.msf.minute = buffer[9];
- tocentry->cdte_addr.msf.second = buffer[10];
- tocentry->cdte_addr.msf.frame = buffer[11];
- } else
- tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
- + buffer[10]) << 8) + buffer[11];
-
- break;
- }
-
- case CDROMPLAYTRKIND: {
- struct cdrom_ti* ti = (struct cdrom_ti*)arg;
-
- cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
- cgc.cmd[4] = ti->cdti_trk0;
- cgc.cmd[5] = ti->cdti_ind0;
- cgc.cmd[7] = ti->cdti_trk1;
- cgc.cmd[8] = ti->cdti_ind1;
- cgc.data_direction = DMA_NONE;
-
- result = sr_do_ioctl(cd, &cgc);
- if (result == -EDRIVE_CANT_DO_THIS)
- result = sr_fake_playtrkind(cdi, ti);
-
- break;
- }
-
+ return sr_read_tocentry(cdi, arg);
+ case CDROMPLAYTRKIND:
+ return sr_play_trkind(cdi, arg);
default:
- result = -EINVAL;
+ return -EINVAL;
}
-
-#if 0
- if (result)
- printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);
-#endif
-
- kfree(buffer);
- return result;
}
/* -----------------------------------------------------------------------
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c4aade8f5345..13b1d3aac265 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -38,6 +38,7 @@ static const char *verstr = "20050830";
#include <linux/devfs_fs_kernel.h>
#include <linux/cdev.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
@@ -193,7 +194,6 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
static int st_probe(struct device *);
static int st_remove(struct device *);
-static int st_init_command(struct scsi_cmnd *);
static void do_create_driverfs_files(void);
static void do_remove_driverfs_files(void);
@@ -206,7 +206,6 @@ static struct scsi_driver st_template = {
.probe = st_probe,
.remove = st_remove,
},
- .init_command = st_init_command,
};
static int st_compression(struct scsi_tape *, int);
@@ -220,7 +219,7 @@ 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);
+static DEFINE_MUTEX(st_ref_mutex);
#include "osst_detect.h"
@@ -237,7 +236,7 @@ static struct scsi_tape *scsi_tape_get(int dev)
{
struct scsi_tape *STp = NULL;
- down(&st_ref_sem);
+ mutex_lock(&st_ref_mutex);
write_lock(&st_dev_arr_lock);
if (dev < st_dev_max && scsi_tapes != NULL)
@@ -259,7 +258,7 @@ out_put:
STp = NULL;
out:
write_unlock(&st_dev_arr_lock);
- up(&st_ref_sem);
+ mutex_unlock(&st_ref_mutex);
return STp;
}
@@ -267,10 +266,10 @@ static void scsi_tape_put(struct scsi_tape *STp)
{
struct scsi_device *sdev = STp->device;
- down(&st_ref_sem);
+ mutex_lock(&st_ref_mutex);
kref_put(&STp->kref, scsi_tape_release);
scsi_device_put(sdev);
- up(&st_ref_sem);
+ mutex_unlock(&st_ref_mutex);
}
struct st_reject_data {
@@ -4141,9 +4140,9 @@ static int st_remove(struct device *dev)
}
}
- down(&st_ref_sem);
+ mutex_lock(&st_ref_mutex);
kref_put(&tpnt->kref, scsi_tape_release);
- up(&st_ref_sem);
+ mutex_unlock(&st_ref_mutex);
return 0;
}
}
@@ -4156,7 +4155,7 @@ static int st_remove(struct device *dev)
* 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
+ * st_ref_mutex 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().
@@ -4180,29 +4179,6 @@ static void scsi_tape_release(struct kref *kref)
return;
}
-static void st_intr(struct scsi_cmnd *SCpnt)
-{
- /*
- * The caller should be checking the request's errors
- * value.
- */
- scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
-}
-
-/*
- * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)
- * interface for REQ_BLOCK_PC commands.
- */
-static int st_init_command(struct scsi_cmnd *SCpnt)
-{
- if (!(SCpnt->request->flags & REQ_BLOCK_PC))
- return 0;
-
- scsi_setup_blk_pc_cmnd(SCpnt);
- SCpnt->done = st_intr;
- return 1;
-}
-
static int __init init_st(void)
{
validate_options();
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index fd63add6a577..fb53eeaee617 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -465,7 +465,7 @@ wd33c93_execute(struct Scsi_Host *instance)
*/
cmd = (struct scsi_cmnd *) hostdata->input_Q;
- prev = 0;
+ prev = NULL;
while (cmd) {
if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)))
break;
@@ -1569,7 +1569,7 @@ wd33c93_abort(struct scsi_cmnd * cmd)
*/
tmp = (struct scsi_cmnd *) hostdata->input_Q;
- prev = 0;
+ prev = NULL;
while (tmp) {
if (tmp == cmd) {
if (prev)
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index b5cf39468d18..221999bcf8fe 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -94,15 +94,6 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
status = *CSR_UARTFLG;
while (!(status & 0x10) && max_count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
ch = *CSR_UARTDR;
flag = TTY_NORMAL;
port->icount.rx++;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 67e9afa000c1..8cbf0fc5a225 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD;
* memory if large numbers of serial ports are open.
*/
static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */
-DECLARE_MUTEX(tmp_buf_sem);
static inline int serial_paranoia_check(struct m68k_serial *info,
char *name, const char *routine)
@@ -294,7 +293,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
{
struct tty_struct *tty = info->tty;
m68328_uart *uart = &uart_addr[info->line];
- unsigned char ch;
+ unsigned char ch, flag;
/*
* This do { } while() loop will get ALL chars out of Rx FIFO
@@ -332,26 +331,24 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
/*
* Make sure that we do not overflow the buffer
*/
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty_request_buffer_room(tty, 1) == 0) {
schedule_work(&tty->flip.work);
return;
}
+ flag = TTY_NORMAL;
+
if(rx & URX_PARITY_ERROR) {
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
status_handle(info, rx);
} else if(rx & URX_OVRUN) {
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
status_handle(info, rx);
} else if(rx & URX_FRAME_ERROR) {
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ flag = TTY_FRAME;
status_handle(info, rx);
- } else {
- *tty->flip.flag_buf_ptr++ = 0; /* XXX */
}
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
-
+ tty_insert_flip_char(tty, ch, flag);
#ifndef CONFIG_XCOPILOT_BUGS
} while((rx = uart->urx.w) & URX_DATA_READY);
#endif
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 170c9d2a749c..60f5a5dc17f1 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -394,7 +394,7 @@ static void rs_360_start(struct tty_struct *tty)
static _INLINE_ void receive_chars(ser_info_t *info)
{
struct tty_struct *tty = info->tty;
- unsigned char ch, *cp;
+ unsigned char ch, flag, *cp;
/*int ignored = 0;*/
int i;
ushort status;
@@ -438,24 +438,15 @@ static _INLINE_ void receive_chars(ser_info_t *info)
cp = (char *)bdp->buf;
status = bdp->status;
- /* Check to see if there is room in the tty buffer for
- * the characters in our BD buffer. If not, we exit
- * now, leaving the BD with the characters. We'll pick
- * them up again on the next receive interrupt (which could
- * be a timeout).
- */
- if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
- break;
-
while (i-- > 0) {
ch = *cp++;
- *tty->flip.char_buf_ptr = ch;
icount->rx++;
#ifdef SERIAL_DEBUG_INTR
printk("DR%02x:%02x...", ch, status);
#endif
- *tty->flip.flag_buf_ptr = 0;
+ flag = TTY_NORMAL;
+
if (status & (BD_SC_BR | BD_SC_FR |
BD_SC_PR | BD_SC_OV)) {
/*
@@ -490,30 +481,18 @@ static _INLINE_ void receive_chars(ser_info_t *info)
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & BD_SC_PR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & BD_SC_FR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (status & BD_SC_OV) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr =
- TTY_OVERRUN;
- }
- }
+ flag = TTY_FRAME;
}
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
+ if (status & BD_SC_OV)
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
/* This BD is ready to be used again. Clear status.
@@ -541,12 +520,7 @@ static _INLINE_ void receive_break(ser_info_t *info)
/* Check to see if there is room in the tty buffer for
* the break. If not, we exit now, losing the break. FIXME
*/
- if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
- return;
- *(tty->flip.flag_buf_ptr++) = TTY_BREAK;
- *(tty->flip.char_buf_ptr++) = 0;
- tty->flip.count++;
-
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
schedule_work(&tty->flip.work);
}
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d2bcd1f87cd6..bc36edff2058 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -41,6 +41,7 @@
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/nmi.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -54,6 +55,8 @@
*/
static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
+static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
+
/*
* Debugging.
*/
@@ -296,7 +299,7 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
#endif
-static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
+static unsigned int serial_in(struct uart_8250_port *up, int offset)
{
offset = map_8250_in_reg(up, offset) << up->port.regshift;
@@ -321,7 +324,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
}
}
-static _INLINE_ void
+static void
serial_out(struct uart_8250_port *up, int offset, int value)
{
offset = map_8250_out_reg(up, offset) << up->port.regshift;
@@ -1131,7 +1134,7 @@ static void serial8250_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
-static _INLINE_ void
+static void
receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
@@ -1140,19 +1143,6 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
char flag;
do {
- /* 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) {
- 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
- */
- }
ch = serial_inp(up, UART_RX);
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1217,7 +1207,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
*status = lsr;
}
-static _INLINE_ void transmit_chars(struct uart_8250_port *up)
+static void transmit_chars(struct uart_8250_port *up)
{
struct circ_buf *xmit = &up->port.info->xmit;
int count;
@@ -1255,25 +1245,24 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
__stop_tx(up);
}
-static _INLINE_ void check_modem_status(struct uart_8250_port *up)
+static unsigned int check_modem_status(struct uart_8250_port *up)
{
- int status;
-
- status = serial_in(up, UART_MSR);
+ unsigned int status = serial_in(up, UART_MSR);
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI) {
+ if (status & UART_MSR_TERI)
+ up->port.icount.rng++;
+ if (status & UART_MSR_DDSR)
+ up->port.icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+ wake_up_interruptible(&up->port.info->delta_msr_wait);
+ }
- wake_up_interruptible(&up->port.info->delta_msr_wait);
+ return status;
}
/*
@@ -1282,7 +1271,11 @@ static _INLINE_ void check_modem_status(struct uart_8250_port *up)
static inline void
serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
{
- unsigned int status = serial_inp(up, UART_LSR);
+ unsigned int status;
+
+ spin_lock(&up->port.lock);
+
+ status = serial_inp(up, UART_LSR);
DEBUG_INTR("status = %x...", status);
@@ -1291,6 +1284,8 @@ serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
check_modem_status(up);
if (status & UART_LSR_THRE)
transmit_chars(up);
+
+ spin_unlock(&up->port.lock);
}
/*
@@ -1326,9 +1321,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r
iir = serial_in(up, UART_IIR);
if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
serial8250_handle_port(up, regs);
- spin_unlock(&up->port.lock);
handled = 1;
@@ -1427,11 +1420,8 @@ static void serial8250_timeout(unsigned long data)
unsigned int iir;
iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
+ if (!(iir & UART_IIR_NO_INT))
serial8250_handle_port(up, NULL);
- spin_unlock(&up->port.lock);
- }
timeout = up->port.timeout;
timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
@@ -1454,10 +1444,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
static unsigned int serial8250_get_mctrl(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char status;
+ unsigned int status;
unsigned int ret;
- status = serial_in(up, UART_MSR);
+ status = check_modem_status(up);
ret = 0;
if (status & UART_MSR_DCD)
@@ -2118,7 +2108,7 @@ static void __init serial8250_isa_init_ports(void)
return;
first = 0;
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
up->port.line = i;
@@ -2137,7 +2127,7 @@ static void __init serial8250_isa_init_ports(void)
}
for (i = 0, up = serial8250_ports;
- i < ARRAY_SIZE(old_serial_port) && i < UART_NR;
+ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
i++, up++) {
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
@@ -2159,7 +2149,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
serial8250_isa_init_ports();
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
up->port.dev = dev;
@@ -2262,7 +2252,7 @@ static int serial8250_console_setup(struct console *co, char *options)
* if so, search for the first available port that does have
* console support.
*/
- if (co->index >= UART_NR)
+ if (co->index >= nr_uarts)
co->index = 0;
port = &serial8250_ports[co->index].port;
if (!port->iobase && !port->membase)
@@ -2298,11 +2288,9 @@ static int __init find_port(struct uart_port *p)
int line;
struct uart_port *port;
- for (line = 0; line < UART_NR; line++) {
+ for (line = 0; line < nr_uarts; line++) {
port = &serial8250_ports[line].port;
- if (p->iotype == port->iotype &&
- p->iobase == port->iobase &&
- p->membase == port->membase)
+ if (uart_match_port(p, port))
return line;
}
return -ENODEV;
@@ -2422,7 +2410,7 @@ static int __devexit serial8250_remove(struct platform_device *dev)
{
int i;
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
if (up->port.dev == &dev->dev)
@@ -2466,6 +2454,7 @@ static struct platform_driver serial8250_isa_driver = {
.resume = serial8250_resume,
.driver = {
.name = "serial8250",
+ .owner = THIS_MODULE,
},
};
@@ -2480,7 +2469,7 @@ static struct platform_device *serial8250_isa_devs;
* 16x50 serial ports to be configured at run-time, to support PCMCIA
* modems and PCI multiport cards.
*/
-static DECLARE_MUTEX(serial_sem);
+static DEFINE_MUTEX(serial_mutex);
static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
{
@@ -2489,7 +2478,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
/*
* First, find a port entry which matches.
*/
- for (i = 0; i < UART_NR; i++)
+ for (i = 0; i < nr_uarts; i++)
if (uart_match_port(&serial8250_ports[i].port, port))
return &serial8250_ports[i];
@@ -2498,7 +2487,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
* free entry. We look for one which hasn't been previously
* used (indicated by zero iobase).
*/
- for (i = 0; i < UART_NR; i++)
+ for (i = 0; i < nr_uarts; i++)
if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
serial8250_ports[i].port.iobase == 0)
return &serial8250_ports[i];
@@ -2507,7 +2496,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
* That also failed. Last resort is to find any entry which
* doesn't have a real port associated with it.
*/
- for (i = 0; i < UART_NR; i++)
+ for (i = 0; i < nr_uarts; i++)
if (serial8250_ports[i].port.type == PORT_UNKNOWN)
return &serial8250_ports[i];
@@ -2535,7 +2524,7 @@ int serial8250_register_port(struct uart_port *port)
if (port->uartclk == 0)
return -EINVAL;
- down(&serial_sem);
+ mutex_lock(&serial_mutex);
uart = serial8250_find_match_or_unused(port);
if (uart) {
@@ -2557,7 +2546,7 @@ int serial8250_register_port(struct uart_port *port)
if (ret == 0)
ret = uart->port.line;
}
- up(&serial_sem);
+ mutex_unlock(&serial_mutex);
return ret;
}
@@ -2574,7 +2563,7 @@ void serial8250_unregister_port(int line)
{
struct uart_8250_port *uart = &serial8250_ports[line];
- down(&serial_sem);
+ mutex_lock(&serial_mutex);
uart_remove_one_port(&serial8250_reg, &uart->port);
if (serial8250_isa_devs) {
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
@@ -2584,7 +2573,7 @@ void serial8250_unregister_port(int line)
} else {
uart->port.dev = NULL;
}
- up(&serial_sem);
+ mutex_unlock(&serial_mutex);
}
EXPORT_SYMBOL(serial8250_unregister_port);
@@ -2592,8 +2581,11 @@ static int __init serial8250_init(void)
{
int ret, i;
+ if (nr_uarts > UART_NR)
+ nr_uarts = UART_NR;
+
printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ "
- "%d ports, IRQ sharing %sabled\n", (int) UART_NR,
+ "%d ports, IRQ sharing %sabled\n", nr_uarts,
share_irqs ? "en" : "dis");
for (i = 0; i < NR_IRQS; i++)
@@ -2603,21 +2595,27 @@ static int __init serial8250_init(void)
if (ret)
goto out;
- serial8250_isa_devs = platform_device_register_simple("serial8250",
- PLAT8250_DEV_LEGACY, NULL, 0);
- if (IS_ERR(serial8250_isa_devs)) {
- ret = PTR_ERR(serial8250_isa_devs);
- goto unreg;
+ serial8250_isa_devs = platform_device_alloc("serial8250",
+ PLAT8250_DEV_LEGACY);
+ if (!serial8250_isa_devs) {
+ ret = -ENOMEM;
+ goto unreg_uart_drv;
}
+ ret = platform_device_add(serial8250_isa_devs);
+ if (ret)
+ goto put_dev;
+
serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
ret = platform_driver_register(&serial8250_isa_driver);
if (ret == 0)
goto out;
- platform_device_unregister(serial8250_isa_devs);
- unreg:
+ platform_device_del(serial8250_isa_devs);
+ put_dev:
+ platform_device_put(serial8250_isa_devs);
+ unreg_uart_drv:
uart_unregister_driver(&serial8250_reg);
out:
return ret;
@@ -2653,6 +2651,9 @@ module_param(share_irqs, uint, 0644);
MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
" (unsafe)");
+module_param(nr_uarts, uint, 0644);
+MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+
#ifdef CONFIG_SERIAL_8250_RSA
module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index a607b98016db..490606b87095 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -51,12 +51,6 @@ struct serial8250_config {
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
-#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
-#define _INLINE_ inline
-#else
-#define _INLINE_
-#endif
-
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 8adca0ce267f..2a912153321e 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -837,8 +837,8 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
return quirk;
}
-static _INLINE_ int
-get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
+static inline int get_pci_irq(struct pci_dev *dev,
+ struct pciserial_board *board)
{
if (board->flags & FL_NOIRQ)
return 0;
@@ -853,14 +853,15 @@ get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
* driver_data member.
*
* The makeup of these names are:
- * pbn_bn{_bt}_n_baud
+ * pbn_bn{_bt}_n_baud{_offsetinhex}
*
- * bn = PCI BAR number
- * bt = Index using PCI BARs
- * n = number of serial ports
- * baud = baud rate
+ * bn = PCI BAR number
+ * bt = Index using PCI BARs
+ * n = number of serial ports
+ * baud = baud rate
+ * offsetinhex = offset for each sequential port (in hex)
*
- * This table is sorted by (in order): baud, bt, bn, n.
+ * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
*
* Please note: in theory if n = 1, _bt infix should make no difference.
* ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
@@ -881,6 +882,13 @@ enum pci_board_num_t {
pbn_b0_4_1152000,
+ pbn_b0_2_1843200,
+ pbn_b0_4_1843200,
+
+ pbn_b0_2_1843200_200,
+ pbn_b0_4_1843200_200,
+ pbn_b0_8_1843200_200,
+
pbn_b0_bt_1_115200,
pbn_b0_bt_2_115200,
pbn_b0_bt_8_115200,
@@ -904,6 +912,8 @@ enum pci_board_num_t {
pbn_b1_4_921600,
pbn_b1_8_921600,
+ pbn_b1_2_1250000,
+
pbn_b1_bt_2_921600,
pbn_b1_1_1382400,
@@ -930,6 +940,7 @@ enum pci_board_num_t {
pbn_b2_bt_2_921600,
pbn_b2_bt_4_921600,
+ pbn_b3_2_115200,
pbn_b3_4_115200,
pbn_b3_8_115200,
@@ -1029,6 +1040,38 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
+ [pbn_b0_2_1843200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1843200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_4_1843200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1843200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_2_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_4_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_8_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+
[pbn_b0_bt_1_115200] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
@@ -1141,6 +1184,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 8,
},
+ [pbn_b1_2_1250000] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+ .base_baud = 1250000,
+ .uart_offset = 8,
+ },
[pbn_b1_bt_2_921600] = {
.flags = FL_BASE1|FL_BASE_BARS,
@@ -1263,6 +1312,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
+ [pbn_b3_2_115200] = {
+ .flags = FL_BASE3,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[pbn_b3_4_115200] = {
.flags = FL_BASE3,
.num_ports = 4,
@@ -1801,6 +1856,66 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
pbn_b1_4_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
+ pbn_b1_2_1250000 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
+ pbn_b0_2_1843200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
+ pbn_b0_4_1843200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
+ pbn_b0_8_1843200_200 },
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -2164,6 +2279,9 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_nec_nile4 },
+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b3_2_115200 },
{ PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b3_4_115200 },
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 812bae62c8ec..9fd1925de361 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -95,6 +95,16 @@ config SERIAL_8250_NR_UARTS
PCI enumeration and any ports that may be added at run-time
via hot-plug, or any ISA multi-port serial cards.
+config SERIAL_8250_RUNTIME_UARTS
+ int "Number of 8250/16550 serial ports to register at runtime"
+ depends on SERIAL_8250
+ default "4"
+ help
+ Set this to the maximum number of serial ports you want
+ the kernel to register at boot time. This can be overriden
+ with the module parameter "nr_uarts", or boot-time parameter
+ 8250.nr_uarts
+
config SERIAL_8250_EXTENDED
bool "Extended 8250/16550 serial driver options"
depends on SERIAL_8250
@@ -180,7 +190,6 @@ config SERIAL_8250_BOCA
To compile this driver as a module, choose M here: the module
will be called 8250_boca.
-
config SERIAL_8250_HUB6
tristate "Support Hub6 cards"
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@@ -270,6 +279,40 @@ config SERIAL_AMBA_PL011_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
+config SERIAL_AT91
+ bool "AT91RM9200 serial port support"
+ depends on ARM && ARCH_AT91RM9200
+ select SERIAL_CORE
+ help
+ This enables the driver for the on-chip UARTs of the AT91RM9200
+ processor.
+
+config SERIAL_AT91_CONSOLE
+ bool "Support for console on AT91RM9200 serial port"
+ depends on SERIAL_AT91=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Say Y here if you wish to use a UART on the AT91RM9200 as the system
+ console (the system console is the device which receives all kernel
+ messages and warnings and which allows logins in single user mode).
+
+config SERIAL_AT91_TTYAT
+ bool "Install as device ttyAT0-4 instead of ttyS0-4"
+ depends on SERIAL_AT91=y
+ help
+ Say Y here if you wish to have the five internal AT91RM9200 UARTs
+ appear as /dev/ttyAT0-4 (major 204, minor 154-158) instead of the
+ normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if
+ you also want other UARTs, such as external 8250/16C550 compatible
+ UARTs.
+ The ttySn nodes are legally reserved for the 8250 serial driver
+ but are often misused by other serial drivers.
+
+ To use this, you should create suitable ttyATn device nodes in
+ /dev/, and pass "console=ttyATn" to the kernel.
+
+ Say Y if you have an external 8250/16C550 UART. If unsure, say N.
+
config SERIAL_CLPS711X
tristate "CLPS711X serial port support"
depends on ARM && ARCH_CLPS711X
@@ -359,29 +402,6 @@ config SERIAL_21285_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
-config SERIAL_UART00
- bool "Excalibur serial port (uart00) support"
- depends on ARM && ARCH_CAMELOT
- select SERIAL_CORE
- help
- Say Y here if you want to use the hard logic uart on Excalibur. This
- driver also supports soft logic implementations of this uart core.
-
-config SERIAL_UART00_CONSOLE
- bool "Support for console on Excalibur serial port"
- depends on SERIAL_UART00
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you want to support a serial console on an Excalibur
- hard logic uart or uart00 IP core.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyS1". (Try "man bootparam" or see the documentation of
- your boot loader (lilo or loadlin) about how to pass options to the
- kernel at boot time.)
-
config SERIAL_MPSC
bool "Marvell MPSC serial port support"
depends on PPC32 && MV64X60
@@ -827,7 +847,7 @@ config SERIAL_M32R_SIO_CONSOLE
config SERIAL_M32R_PLDSIO
bool "M32R SIO I/F on a PLD"
- depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT)
+ depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT)
default n
help
Say Y here if you want to use the M32R serial controller
@@ -873,7 +893,7 @@ config SERIAL_VR41XX_CONSOLE
config SERIAL_JSM
tristate "Digi International NEO PCI Support"
- depends on PCI
+ depends on PCI && BROKEN
select SERIAL_CORE
help
This is a driver for Digi International's Neo series
@@ -896,4 +916,12 @@ config SERIAL_SGI_IOC4
and wish to use the serial ports on this card, say Y.
Otherwise, say N.
+config SERIAL_SGI_IOC3
+ tristate "SGI Altix IOC3 serial support"
+ depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3
+ select SERIAL_CORE
+ help
+ If you have an SGI Altix with an IOC3 serial card,
+ say Y or M. Otherwise, say N.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d7c7c7180e33..eaf8e01db198 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
obj-$(CONFIG_SERIAL_PXA) += pxa.o
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
-obj-$(CONFIG_SERIAL_UART00) += uart00.o
obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
@@ -57,3 +56,5 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
+obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
+obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index ddd0307fece2..3490022e9fdc 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -47,12 +47,12 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_serial.h>
#define UART_NR 2
@@ -154,15 +154,6 @@ pl010_rx_chars(struct uart_port *port)
status = UART_GET_FR(port);
while (UART_RX_DATA(status) && max_count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts.
- */
- }
-
ch = UART_GET_CHAR(port);
flag = TTY_NORMAL;
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index d84476ee6592..034a029e356e 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -47,12 +47,12 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
-#include <asm/hardware/amba_serial.h>
#define UART_NR 14
@@ -120,15 +120,6 @@ pl011_rx_chars(struct uart_amba_port *uap)
status = readw(uap->port.membase + UART01x_FR);
while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
flag = TTY_NORMAL;
uap->port.icount.rx++;
@@ -761,10 +752,6 @@ static int pl011_probe(struct amba_device *dev, void *id)
goto unmap;
}
- ret = clk_use(uap->clk);
- if (ret)
- goto putclk;
-
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;
@@ -782,8 +769,6 @@ static int pl011_probe(struct amba_device *dev, void *id)
if (ret) {
amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL;
- clk_unuse(uap->clk);
- putclk:
clk_put(uap->clk);
unmap:
iounmap(base);
@@ -808,7 +793,6 @@ static int pl011_remove(struct amba_device *dev)
amba_ports[i] = NULL;
iounmap(uap->port.membase);
- clk_unuse(uap->clk);
clk_put(uap->clk);
kfree(uap);
return 0;
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
new file mode 100644
index 000000000000..2113feb75c39
--- /dev/null
+++ b/drivers/serial/at91_serial.c
@@ -0,0 +1,892 @@
+/*
+ * linux/drivers/char/at91_serial.c
+ *
+ * Driver for Atmel AT91RM9200 Serial ports
+ *
+ * Copyright (C) 2003 Rick Bronson
+ *
+ * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * This program is free software; you can redistribute 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/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/tty_flip.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/at91rm9200_usart.h>
+#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/board.h>
+#include <asm/arch/pio.h>
+
+
+#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#ifdef CONFIG_SERIAL_AT91_TTYAT
+
+/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we
+ * should coexist with the 8250 driver, such as if we have an external 16C550
+ * UART. */
+#define SERIAL_AT91_MAJOR 204
+#define MINOR_START 154
+#define AT91_DEVICENAME "ttyAT"
+
+#else
+
+/* Use device name ttyS, major 4, minor 64-68. This is the usual serial port
+ * name, but it is legally reserved for the 8250 driver. */
+#define SERIAL_AT91_MAJOR TTY_MAJOR
+#define MINOR_START 64
+#define AT91_DEVICENAME "ttyS"
+
+#endif
+
+#define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU)
+#define AT91_ISR_PASS_LIMIT 256
+
+#define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR)
+#define UART_GET_MR(port) readl((port)->membase + AT91_US_MR)
+#define UART_PUT_MR(port,v) writel(v, (port)->membase + AT91_US_MR)
+#define UART_PUT_IER(port,v) writel(v, (port)->membase + AT91_US_IER)
+#define UART_PUT_IDR(port,v) writel(v, (port)->membase + AT91_US_IDR)
+#define UART_GET_IMR(port) readl((port)->membase + AT91_US_IMR)
+#define UART_GET_CSR(port) readl((port)->membase + AT91_US_CSR)
+#define UART_GET_CHAR(port) readl((port)->membase + AT91_US_RHR)
+#define UART_PUT_CHAR(port,v) writel(v, (port)->membase + AT91_US_THR)
+#define UART_GET_BRGR(port) readl((port)->membase + AT91_US_BRGR)
+#define UART_PUT_BRGR(port,v) writel(v, (port)->membase + AT91_US_BRGR)
+#define UART_PUT_RTOR(port,v) writel(v, (port)->membase + AT91_US_RTOR)
+
+// #define UART_GET_CR(port) readl((port)->membase + AT91_US_CR) // is write-only
+
+ /* PDC registers */
+#define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR)
+#define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR)
+#define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR)
+#define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR)
+#define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR)
+#define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR)
+
+
+static int (*at91_open)(struct uart_port *);
+static void (*at91_close)(struct uart_port *);
+
+#ifdef SUPPORT_SYSRQ
+static struct console at91_console;
+#endif
+
+/*
+ * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
+ */
+static u_int at91_tx_empty(struct uart_port *port)
+{
+ return (UART_GET_CSR(port) & AT91_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+}
+
+/*
+ * Set state of the modem control output lines
+ */
+static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ unsigned int control = 0;
+
+ /*
+ * Errata #39: RTS0 is not internally connected to PA21. We need to drive
+ * the pin manually.
+ */
+ if (port->mapbase == AT91_VA_BASE_US0) {
+ if (mctrl & TIOCM_RTS)
+ at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
+ else
+ at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+ }
+
+ if (mctrl & TIOCM_RTS)
+ control |= AT91_US_RTSEN;
+ else
+ control |= AT91_US_RTSDIS;
+
+ if (mctrl & TIOCM_DTR)
+ control |= AT91_US_DTREN;
+ else
+ control |= AT91_US_DTRDIS;
+
+ UART_PUT_CR(port,control);
+}
+
+/*
+ * Get state of the modem control input lines
+ */
+static u_int at91_get_mctrl(struct uart_port *port)
+{
+ unsigned int status, ret = 0;
+
+ status = UART_GET_CSR(port);
+
+ /*
+ * The control signals are active low.
+ */
+ if (!(status & AT91_US_DCD))
+ ret |= TIOCM_CD;
+ if (!(status & AT91_US_CTS))
+ ret |= TIOCM_CTS;
+ if (!(status & AT91_US_DSR))
+ ret |= TIOCM_DSR;
+ if (!(status & AT91_US_RI))
+ ret |= TIOCM_RI;
+
+ return ret;
+}
+
+/*
+ * Stop transmitting.
+ */
+static void at91_stop_tx(struct uart_port *port)
+{
+ UART_PUT_IDR(port, AT91_US_TXRDY);
+ port->read_status_mask &= ~AT91_US_TXRDY;
+}
+
+/*
+ * Start transmitting.
+ */
+static void at91_start_tx(struct uart_port *port)
+{
+ port->read_status_mask |= AT91_US_TXRDY;
+ UART_PUT_IER(port, AT91_US_TXRDY);
+}
+
+/*
+ * Stop receiving - port is in process of being closed.
+ */
+static void at91_stop_rx(struct uart_port *port)
+{
+ UART_PUT_IDR(port, AT91_US_RXRDY);
+}
+
+/*
+ * Enable modem status interrupts
+ */
+static void at91_enable_ms(struct uart_port *port)
+{
+ port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
+ UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
+}
+
+/*
+ * Control the transmission of a break signal
+ */
+static void at91_break_ctl(struct uart_port *port, int break_state)
+{
+ if (break_state != 0)
+ UART_PUT_CR(port, AT91_US_STTBRK); /* start break */
+ else
+ UART_PUT_CR(port, AT91_US_STPBRK); /* stop break */
+}
+
+/*
+ * Characters received (called from interrupt handler)
+ */
+static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
+{
+ struct tty_struct *tty = port->info->tty;
+ unsigned int status, ch, flg;
+
+ status = UART_GET_CSR(port) & port->read_status_mask;
+ while (status & (AT91_US_RXRDY)) {
+ ch = UART_GET_CHAR(port);
+
+ port->icount.rx++;
+
+ flg = TTY_NORMAL;
+
+ /*
+ * note that the error handling code is
+ * out of the main execution path
+ */
+ if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) {
+ UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */
+ if (status & (AT91_US_PARE))
+ port->icount.parity++;
+ if (status & (AT91_US_FRAME))
+ port->icount.frame++;
+ if (status & (AT91_US_OVRE))
+ port->icount.overrun++;
+
+ if (status & AT91_US_PARE)
+ flg = TTY_PARITY;
+ else if (status & AT91_US_FRAME)
+ flg = TTY_FRAME;
+ if (status & AT91_US_OVRE) {
+ /*
+ * overrun does *not* affect the character
+ * we read from the FIFO
+ */
+ tty_insert_flip_char(tty, ch, flg);
+ ch = 0;
+ flg = TTY_OVERRUN;
+ }
+#ifdef SUPPORT_SYSRQ
+ port->sysrq = 0;
+#endif
+ }
+
+ if (uart_handle_sysrq_char(port, ch, regs))
+ goto ignore_char;
+
+ tty_insert_flip_char(tty, ch, flg);
+
+ ignore_char:
+ status = UART_GET_CSR(port) & port->read_status_mask;
+ }
+
+ tty_flip_buffer_push(tty);
+}
+
+/*
+ * Transmit characters (called from interrupt handler)
+ */
+static void at91_tx_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->info->xmit;
+
+ if (port->x_char) {
+ UART_PUT_CHAR(port, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ at91_stop_tx(port);
+ return;
+ }
+
+ while (UART_GET_CSR(port) & AT91_US_TXRDY) {
+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ at91_stop_tx(port);
+}
+
+/*
+ * Interrupt handler
+ */
+static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = dev_id;
+ unsigned int status, pending, pass_counter = 0;
+
+ status = UART_GET_CSR(port);
+ pending = status & port->read_status_mask;
+ if (pending) {
+ do {
+ if (pending & AT91_US_RXRDY)
+ at91_rx_chars(port, regs);
+
+ /* Clear the relevent break bits */
+ if (pending & AT91_US_RXBRK) {
+ UART_PUT_CR(port, AT91_US_RSTSTA);
+ port->icount.brk++;
+ uart_handle_break(port);
+ }
+
+ // TODO: All reads to CSR will clear these interrupts!
+ if (pending & AT91_US_RIIC) port->icount.rng++;
+ if (pending & AT91_US_DSRIC) port->icount.dsr++;
+ if (pending & AT91_US_DCDIC)
+ uart_handle_dcd_change(port, !(status & AT91_US_DCD));
+ if (pending & AT91_US_CTSIC)
+ uart_handle_cts_change(port, !(status & AT91_US_CTS));
+ if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC))
+ wake_up_interruptible(&port->info->delta_msr_wait);
+
+ if (pending & AT91_US_TXRDY)
+ at91_tx_chars(port);
+ if (pass_counter++ > AT91_ISR_PASS_LIMIT)
+ break;
+
+ status = UART_GET_CSR(port);
+ pending = status & port->read_status_mask;
+ } while (pending);
+ }
+ return IRQ_HANDLED;
+}
+
+/*
+ * Perform initialization and enable port for reception
+ */
+static int at91_startup(struct uart_port *port)
+{
+ int retval;
+
+ /*
+ * Ensure that no interrupts are enabled otherwise when
+ * request_irq() is called we could get stuck trying to
+ * handle an unexpected interrupt
+ */
+ UART_PUT_IDR(port, -1);
+
+ /*
+ * Allocate the IRQ
+ */
+ retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
+ if (retval) {
+ printk("at91_serial: at91_startup - Can't get irq\n");
+ return retval;
+ }
+
+ /*
+ * If there is a specific "open" function (to register
+ * control line interrupts)
+ */
+ if (at91_open) {
+ retval = at91_open(port);
+ if (retval) {
+ free_irq(port->irq, port);
+ return retval;
+ }
+ }
+
+ port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE
+ | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK;
+ /*
+ * Finally, enable the serial port
+ */
+ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
+ UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */
+ UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */
+ return 0;
+}
+
+/*
+ * Disable the port
+ */
+static void at91_shutdown(struct uart_port *port)
+{
+ /*
+ * Disable all interrupts, port and break condition.
+ */
+ UART_PUT_CR(port, AT91_US_RSTSTA);
+ UART_PUT_IDR(port, -1);
+
+ /*
+ * Free the interrupt
+ */
+ free_irq(port->irq, port);
+
+ /*
+ * If there is a specific "close" function (to unregister
+ * control line interrupts)
+ */
+ if (at91_close)
+ at91_close(port);
+}
+
+/*
+ * Power / Clock management.
+ */
+static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
+{
+ switch (state) {
+ case 0:
+ /*
+ * Enable the peripheral clock for this serial port.
+ * This is called on uart_open() or a resume event.
+ */
+ at91_sys_write(AT91_PMC_PCER, 1 << port->irq);
+ break;
+ case 3:
+ /*
+ * Disable the peripheral clock for this serial port.
+ * This is called on uart_close() or a suspend event.
+ */
+ if (port->irq != AT91_ID_SYS) /* is this a shared clock? */
+ at91_sys_write(AT91_PMC_PCDR, 1 << port->irq);
+ break;
+ default:
+ printk(KERN_ERR "at91_serial: unknown pm %d\n", state);
+ }
+}
+
+/*
+ * Change the port parameters
+ */
+static void at91_set_termios(struct uart_port *port, struct termios * termios, struct termios * old)
+{
+ unsigned long flags;
+ unsigned int mode, imr, quot, baud;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ quot = uart_get_divisor(port, baud);
+
+ /* Get current mode register */
+ mode = UART_GET_MR(port) & ~(AT91_US_CHRL | AT91_US_NBSTOP | AT91_US_PAR);
+
+ /* byte size */
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ mode |= AT91_US_CHRL_5;
+ break;
+ case CS6:
+ mode |= AT91_US_CHRL_6;
+ break;
+ case CS7:
+ mode |= AT91_US_CHRL_7;
+ break;
+ default:
+ mode |= AT91_US_CHRL_8;
+ break;
+ }
+
+ /* stop bits */
+ if (termios->c_cflag & CSTOPB)
+ mode |= AT91_US_NBSTOP_2;
+
+ /* parity */
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */
+ if (termios->c_cflag & PARODD)
+ mode |= AT91_US_PAR_MARK;
+ else
+ mode |= AT91_US_PAR_SPACE;
+ }
+ else if (termios->c_cflag & PARODD)
+ mode |= AT91_US_PAR_ODD;
+ else
+ mode |= AT91_US_PAR_EVEN;
+ }
+ else
+ mode |= AT91_US_PAR_NONE;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port->read_status_mask |= AT91_US_OVRE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= AT91_US_RXBRK;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= (AT91_US_FRAME | AT91_US_PARE);
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= AT91_US_RXBRK;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= AT91_US_OVRE;
+ }
+
+ // TODO: Ignore all characters if CREAD is set.
+
+ /* update the per-port timeout */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ /* disable interrupts and drain transmitter */
+ imr = UART_GET_IMR(port); /* get interrupt mask */
+ UART_PUT_IDR(port, -1); /* disable all interrupts */
+ while (!(UART_GET_CSR(port) & AT91_US_TXEMPTY)) { barrier(); }
+
+ /* disable receiver and transmitter */
+ UART_PUT_CR(port, AT91_US_TXDIS | AT91_US_RXDIS);
+
+ /* set the parity, stop bits and data size */
+ UART_PUT_MR(port, mode);
+
+ /* set the baud rate */
+ UART_PUT_BRGR(port, quot);
+ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
+ UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);
+
+ /* restore interrupts */
+ UART_PUT_IER(port, imr);
+
+ /* CTS flow-control and modem-status interrupts */
+ if (UART_ENABLE_MS(port, termios->c_cflag))
+ port->ops->enable_ms(port);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * Return string describing the specified port
+ */
+static const char *at91_type(struct uart_port *port)
+{
+ return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void at91_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase,
+ (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K);
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int at91_request_port(struct uart_port *port)
+{
+ return request_mem_region(port->mapbase,
+ (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K,
+ "at91_serial") != NULL ? 0 : -EBUSY;
+
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void at91_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_AT91RM9200;
+ at91_request_port(port);
+ }
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ int ret = 0;
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
+ ret = -EINVAL;
+ if (port->irq != ser->irq)
+ ret = -EINVAL;
+ if (ser->io_type != SERIAL_IO_MEM)
+ ret = -EINVAL;
+ if (port->uartclk / 16 != ser->baud_base)
+ ret = -EINVAL;
+ if ((void *)port->mapbase != ser->iomem_base)
+ ret = -EINVAL;
+ if (port->iobase != ser->port)
+ ret = -EINVAL;
+ if (ser->hub6 != 0)
+ ret = -EINVAL;
+ return ret;
+}
+
+static struct uart_ops at91_pops = {
+ .tx_empty = at91_tx_empty,
+ .set_mctrl = at91_set_mctrl,
+ .get_mctrl = at91_get_mctrl,
+ .stop_tx = at91_stop_tx,
+ .start_tx = at91_start_tx,
+ .stop_rx = at91_stop_rx,
+ .enable_ms = at91_enable_ms,
+ .break_ctl = at91_break_ctl,
+ .startup = at91_startup,
+ .shutdown = at91_shutdown,
+ .set_termios = at91_set_termios,
+ .type = at91_type,
+ .release_port = at91_release_port,
+ .request_port = at91_request_port,
+ .config_port = at91_config_port,
+ .verify_port = at91_verify_port,
+ .pm = at91_serial_pm,
+};
+
+static struct uart_port at91_ports[AT91_NR_UART];
+
+void __init at91_init_ports(void)
+{
+ static int first = 1;
+ int i;
+
+ if (!first)
+ return;
+ first = 0;
+
+ for (i = 0; i < AT91_NR_UART; i++) {
+ at91_ports[i].iotype = UPIO_MEM;
+ at91_ports[i].flags = UPF_BOOT_AUTOCONF;
+ at91_ports[i].uartclk = at91_master_clock;
+ at91_ports[i].ops = &at91_pops;
+ at91_ports[i].fifosize = 1;
+ at91_ports[i].line = i;
+ }
+}
+
+void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
+{
+ if (fns->enable_ms)
+ at91_pops.enable_ms = fns->enable_ms;
+ if (fns->get_mctrl)
+ at91_pops.get_mctrl = fns->get_mctrl;
+ if (fns->set_mctrl)
+ at91_pops.set_mctrl = fns->set_mctrl;
+ at91_open = fns->open;
+ at91_close = fns->close;
+ at91_pops.pm = fns->pm;
+ at91_pops.set_wake = fns->set_wake;
+}
+
+/*
+ * Setup ports.
+ */
+void __init at91_register_uart(int idx, int port)
+{
+ if ((idx < 0) || (idx >= AT91_NR_UART)) {
+ printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
+ return;
+ }
+
+ switch (port) {
+ case 0:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US0;
+ at91_ports[idx].irq = AT91_ID_US0;
+ AT91_CfgPIO_USART0();
+ break;
+ case 1:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US1;
+ at91_ports[idx].irq = AT91_ID_US1;
+ AT91_CfgPIO_USART1();
+ break;
+ case 2:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US2;
+ at91_ports[idx].irq = AT91_ID_US2;
+ AT91_CfgPIO_USART2();
+ break;
+ case 3:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US3;
+ at91_ports[idx].irq = AT91_ID_US3;
+ AT91_CfgPIO_USART3();
+ break;
+ case 4:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU;
+ at91_ports[idx].mapbase = AT91_VA_BASE_DBGU;
+ at91_ports[idx].irq = AT91_ID_SYS;
+ AT91_CfgPIO_DBGU();
+ break;
+ default:
+ printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port);
+ }
+}
+
+#ifdef CONFIG_SERIAL_AT91_CONSOLE
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void at91_console_write(struct console *co, const char *s, u_int count)
+{
+ struct uart_port *port = at91_ports + co->index;
+ unsigned int status, i, imr;
+
+ /*
+ * First, save IMR and then disable interrupts
+ */
+ imr = UART_GET_IMR(port); /* get interrupt mask */
+ UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY);
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; i < count; i++) {
+ do {
+ status = UART_GET_CSR(port);
+ } while (!(status & AT91_US_TXRDY));
+ UART_PUT_CHAR(port, s[i]);
+ if (s[i] == '\n') {
+ do {
+ status = UART_GET_CSR(port);
+ } while (!(status & AT91_US_TXRDY));
+ UART_PUT_CHAR(port, '\r');
+ }
+ }
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore IMR
+ */
+ do {
+ status = UART_GET_CSR(port);
+ } while (!(status & AT91_US_TXRDY));
+ UART_PUT_IER(port, imr); /* set interrupts back the way they were */
+}
+
+/*
+ * If the port was already initialised (eg, by a boot loader), try to determine
+ * the current setup.
+ */
+static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
+{
+ unsigned int mr, quot;
+
+// TODO: CR is a write-only register
+// unsigned int cr;
+//
+// cr = UART_GET_CR(port) & (AT91_US_RXEN | AT91_US_TXEN);
+// if (cr == (AT91_US_RXEN | AT91_US_TXEN)) {
+// /* ok, the port was enabled */
+// }
+
+ mr = UART_GET_MR(port) & AT91_US_CHRL;
+ if (mr == AT91_US_CHRL_8)
+ *bits = 8;
+ else
+ *bits = 7;
+
+ mr = UART_GET_MR(port) & AT91_US_PAR;
+ if (mr == AT91_US_PAR_EVEN)
+ *parity = 'e';
+ else if (mr == AT91_US_PAR_ODD)
+ *parity = 'o';
+
+ quot = UART_GET_BRGR(port);
+ *baud = port->uartclk / (16 * (quot));
+}
+
+static int __init at91_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ port = uart_get_console(at91_ports, AT91_NR_UART, co);
+
+ /*
+ * Enable the serial console, in-case bootloader did not do it.
+ */
+ at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */
+ UART_PUT_IDR(port, -1); /* disable interrupts */
+ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
+ UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else
+ at91_console_get_options(port, &baud, &parity, &bits);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver at91_uart;
+
+static struct console at91_console = {
+ .name = AT91_DEVICENAME,
+ .write = at91_console_write,
+ .device = uart_console_device,
+ .setup = at91_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &at91_uart,
+};
+
+#define AT91_CONSOLE_DEVICE &at91_console
+
+static int __init at91_console_init(void)
+{
+ at91_init_ports();
+
+ at91_console.index = at91_console_port;
+ register_console(&at91_console);
+ return 0;
+}
+console_initcall(at91_console_init);
+
+#else
+#define AT91_CONSOLE_DEVICE NULL
+#endif
+
+static struct uart_driver at91_uart = {
+ .owner = THIS_MODULE,
+ .driver_name = AT91_DEVICENAME,
+ .dev_name = AT91_DEVICENAME,
+ .devfs_name = AT91_DEVICENAME,
+ .major = SERIAL_AT91_MAJOR,
+ .minor = MINOR_START,
+ .nr = AT91_NR_UART,
+ .cons = AT91_CONSOLE_DEVICE,
+};
+
+static int __init at91_serial_init(void)
+{
+ int ret, i;
+
+ at91_init_ports();
+
+ ret = uart_register_driver(&at91_uart);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (at91_serial_map[i] >= 0)
+ uart_add_one_port(&at91_uart, &at91_ports[i]);
+ }
+
+ return 0;
+}
+
+static void __exit at91_serial_exit(void)
+{
+ int i;
+
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (at91_serial_map[i] >= 0)
+ uart_remove_one_port(&at91_uart, &at91_ports[i]);
+ }
+
+ uart_unregister_driver(&at91_uart);
+}
+
+module_init(at91_serial_init);
+module_exit(at91_serial_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("AT91 generic serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index a274ebf256a1..ceb5d7f37bbd 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -241,18 +241,12 @@ static _INLINE_ void
receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
int max_count = 256;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return; // if TTY_DONT_FLIP is set
- }
ch = serial_inp(up, UART_RX);
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -292,30 +286,23 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
#endif
if (*status & UART_LSR_BI) {
DEBUG_INTR("handling break....");
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if (*status & UART_LSR_OE)
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
*status = serial_inp(up, UART_LSR);
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 87ef368384fb..8ef999481f93 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -104,8 +104,6 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
while (!(status & SYSFLG_URXFE)) {
ch = clps_readl(UARTDR(port));
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
port->icount.rx++;
flg = TTY_NORMAL;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 987d22b53c22..16af5626c243 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -608,7 +608,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
p = cpm2cpu_addr(bdp->cbd_bufaddr);
- *p++ = xmit->buf[xmit->tail];
+ *p++ = port->x_char;
bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY;
/* Get next BD. */
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 08c42c000188..be12623d8544 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -442,6 +442,7 @@ static char *serial_version = "$Revision: 1.25 $";
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1315,11 +1316,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-#ifdef DECLARE_MUTEX
-static DECLARE_MUTEX(tmp_buf_sem);
-#else
-static struct semaphore tmp_buf_sem = MUTEX;
-#endif
+static DEFINE_MUTEX(tmp_buf_mutex);
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
static void update_char_time(struct e100_serial * info)
@@ -3661,7 +3658,7 @@ rs_raw_write(struct tty_struct * tty, int from_user,
* design.
*/
if (from_user) {
- down(&tmp_buf_sem);
+ mutex_lock(&tmp_buf_mutex);
while (1) {
int c1;
c = CIRC_SPACE_TO_END(info->xmit.head,
@@ -3692,7 +3689,7 @@ rs_raw_write(struct tty_struct * tty, int from_user,
count -= c;
ret += c;
}
- up(&tmp_buf_sem);
+ mutex_unlock(&tmp_buf_mutex);
} else {
cli();
while (count) {
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 4d8516d1bb71..a64ba26a94e8 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -216,8 +216,6 @@ static inline void dz_receive_chars(struct dz_port *dport)
if (!tty)
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
icount->rx++;
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index eb31125c6a30..144a7a352b28 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -729,19 +729,20 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
unsigned short int status;
struct uart_icount *icount;
unsigned long offset;
+ unsigned char flag;
trace(icom_port, "RCV_COMPLETE", 0);
rcv_buff = icom_port->next_rcv;
status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
while (status & SA_FL_RCV_DONE) {
+ int first = -1;
trace(icom_port, "FID_STATUS", status);
count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
+ count = tty_buffer_request_room(tty, count);
trace(icom_port, "RCV_COUNT", count);
- if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
- count = TTY_FLIPBUF_SIZE - tty->flip.count;
trace(icom_port, "REAL_COUNT", count);
@@ -749,15 +750,10 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
icom_port->recv_buf_pci;
- memcpy(tty->flip.char_buf_ptr,(unsigned char *)
- ((unsigned long)icom_port->recv_buf + offset), count);
-
+ /* Block copy all but the last byte as this may have status */
if (count > 0) {
- tty->flip.count += count - 1;
- tty->flip.char_buf_ptr += count - 1;
-
- memset(tty->flip.flag_buf_ptr, 0, count);
- tty->flip.flag_buf_ptr += count - 1;
+ first = icom_port->recv_buf[offset];
+ tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
}
icount = &icom_port->uart_port.icount;
@@ -765,12 +761,14 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
/* Break detect logic */
if ((status & SA_FLAGS_FRAME_ERROR)
- && (tty->flip.char_buf_ptr[0] == 0x00)) {
+ && first == 0) {
status &= ~SA_FLAGS_FRAME_ERROR;
status |= SA_FLAGS_BREAK_DET;
trace(icom_port, "BREAK_DET", 0);
}
+ flag = TTY_NORMAL;
+
if (status &
(SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
@@ -797,33 +795,26 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
status &= icom_port->read_status_mask;
if (status & SA_FLAGS_BREAK_DET) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (status & SA_FLAGS_PARITY_ERROR) {
trace(icom_port, "PARITY_ERROR", 0);
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (status & SA_FLAGS_FRAME_ERROR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
-
- if (status & SA_FLAGS_OVERRUN) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
- }
+ flag = TTY_FRAME;
+
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- ignore_char:
- icom_port->statStg->rcv[rcv_buff].flags = 0;
+ tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
+
+ if (status & SA_FLAGS_OVERRUN)
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ignore_char:
+ icom_port->statStg->rcv[rcv_buff].flags = 0;
icom_port->statStg->rcv[rcv_buff].leLength = 0;
icom_port->statStg->rcv[rcv_buff].WorkingLength =
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 83c4c1216587..587cc6a95114 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -256,9 +256,6 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
error_return:
tty_insert_flip_char(tty, rx, flg);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto out;
-
ignore_char:
rx = URXD0((u32)sport->port.membase);
} while(rx & URXD_CHARRDY);
@@ -502,7 +499,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) {
ucr2 |= UCR2_PREN;
- if (!(termios->c_cflag & PARODD))
+ if (termios->c_cflag & PARODD)
ucr2 |= UCR2_PROE;
}
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
new file mode 100644
index 000000000000..8097cd91f16b
--- /dev/null
+++ b/drivers/serial/ioc3_serial.c
@@ -0,0 +1,2197 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+/*
+ * This file contains a module version of the ioc3 serial driver. This
+ * includes all the support functions needed (support functions, etc.)
+ * and the serial driver itself.
+ */
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/circ_buf.h>
+#include <linux/serial_reg.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/serial_core.h>
+#include <linux/ioc3.h>
+
+/*
+ * Interesting things about the ioc3
+ */
+
+#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */
+#define PORTS_PER_CARD 2
+#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS)
+#define MAX_CARDS 8
+#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS)
+
+/* determine given the sio_ir what port it applies to */
+#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1
+
+
+/*
+ * we have 2 logical ports (rs232, rs422) for each physical port
+ * evens are rs232, odds are rs422
+ */
+#define GET_PHYSICAL_PORT(_x) ((_x) >> 1)
+#define GET_LOGICAL_PORT(_x) ((_x) & 1)
+#define IS_PHYSICAL_PORT(_x) !((_x) & 1)
+#define IS_RS232(_x) !((_x) & 1)
+
+static unsigned int Num_of_ioc3_cards;
+static unsigned int Submodule_slot;
+
+/* defining this will get you LOTS of great debug info */
+//#define DEBUG_INTERRUPTS
+#define DPRINT_CONFIG(_x...) ;
+//#define DPRINT_CONFIG(_x...) printk _x
+#define NOT_PROGRESS() ;
+//#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__)
+
+/* number of characters we want to transmit to the lower level at a time */
+#define MAX_CHARS 256
+#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */
+
+/* Device name we're using */
+#define DEVICE_NAME "ttySIOC"
+#define DEVICE_MAJOR 204
+#define DEVICE_MINOR 116
+
+/* flags for next_char_state */
+#define NCS_BREAK 0x1
+#define NCS_PARITY 0x2
+#define NCS_FRAMING 0x4
+#define NCS_OVERRUN 0x8
+
+/* cause we need SOME parameters ... */
+#define MIN_BAUD_SUPPORTED 1200
+#define MAX_BAUD_SUPPORTED 115200
+
+/* protocol types supported */
+#define PROTO_RS232 0
+#define PROTO_RS422 1
+
+/* Notification types */
+#define N_DATA_READY 0x01
+#define N_OUTPUT_LOWAT 0x02
+#define N_BREAK 0x04
+#define N_PARITY_ERROR 0x08
+#define N_FRAMING_ERROR 0x10
+#define N_OVERRUN_ERROR 0x20
+#define N_DDCD 0x40
+#define N_DCTS 0x80
+
+#define N_ALL_INPUT (N_DATA_READY | N_BREAK \
+ | N_PARITY_ERROR | N_FRAMING_ERROR \
+ | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define N_ALL_OUTPUT N_OUTPUT_LOWAT
+
+#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \
+ | N_OVERRUN_ERROR)
+
+#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \
+ | N_PARITY_ERROR | N_FRAMING_ERROR \
+ | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv)
+#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16))
+#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
+
+/* Some masks */
+#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
+ | UART_LCR_WLEN7 | UART_LCR_WLEN8)
+#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
+
+#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable)
+
+#define RING_BUF_SIZE 4096
+#define BUF_SIZE_BIT SBBR_L_SIZE
+#define PROD_CONS_MASK PROD_CONS_PTR_4K
+
+#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
+
+/* driver specific - one per card */
+struct ioc3_card {
+ struct {
+ /* uart ports are allocated here */
+ struct uart_port icp_uart_port[LOGICAL_PORTS];
+ /* the ioc3_port used for this port */
+ struct ioc3_port *icp_port;
+ } ic_port[PORTS_PER_CARD];
+ /* currently enabled interrupts */
+ uint32_t ic_enable;
+};
+
+/* Local port info for each IOC3 serial port */
+struct ioc3_port {
+ /* handy reference material */
+ struct uart_port *ip_port;
+ struct ioc3_card *ip_card;
+ struct ioc3_driver_data *ip_idd;
+ struct ioc3_submodule *ip_is;
+
+ /* pci mem addresses for this port */
+ struct ioc3_serialregs __iomem *ip_serial_regs;
+ struct ioc3_uartregs __iomem *ip_uart_regs;
+
+ /* Ring buffer page for this port */
+ dma_addr_t ip_dma_ringbuf;
+ /* vaddr of ring buffer */
+ struct ring_buffer *ip_cpu_ringbuf;
+
+ /* Rings for this port */
+ struct ring *ip_inring;
+ struct ring *ip_outring;
+
+ /* Hook to port specific values */
+ struct port_hooks *ip_hooks;
+
+ spinlock_t ip_lock;
+
+ /* Various rx/tx parameters */
+ int ip_baud;
+ int ip_tx_lowat;
+ int ip_rx_timeout;
+
+ /* Copy of notification bits */
+ int ip_notify;
+
+ /* Shadow copies of various registers so we don't need to PIO
+ * read them constantly
+ */
+ uint32_t ip_sscr;
+ uint32_t ip_tx_prod;
+ uint32_t ip_rx_cons;
+ unsigned char ip_flags;
+};
+
+/* tx low water mark. We need to notify the driver whenever tx is getting
+ * close to empty so it can refill the tx buffer and keep things going.
+ * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
+ * have no trouble getting in more chars in time (I certainly hope so).
+ */
+#define TX_LOWAT_LATENCY 1000
+#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
+#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
+
+/* Flags per port */
+#define INPUT_HIGH 0x01
+ /* used to signify that we have turned off the rx_high
+ * temporarily - we need to drain the fifo and don't
+ * want to get blasted with interrupts.
+ */
+#define DCD_ON 0x02
+ /* DCD state is on */
+#define LOWAT_WRITTEN 0x04
+#define READ_ABORTED 0x08
+ /* the read was aborted - used to avaoid infinate looping
+ * in the interrupt handler
+ */
+#define INPUT_ENABLE 0x10
+
+/* Since each port has different register offsets and bitmasks
+ * for everything, we'll store those that we need in tables so we
+ * don't have to be constantly checking the port we are dealing with.
+ */
+struct port_hooks {
+ uint32_t intr_delta_dcd;
+ uint32_t intr_delta_cts;
+ uint32_t intr_tx_mt;
+ uint32_t intr_rx_timer;
+ uint32_t intr_rx_high;
+ uint32_t intr_tx_explicit;
+ uint32_t intr_clear;
+ uint32_t intr_all;
+ char rs422_select_pin;
+};
+
+static struct port_hooks hooks_array[PORTS_PER_CARD] = {
+ /* values for port A */
+ {
+ .intr_delta_dcd = SIO_IR_SA_DELTA_DCD,
+ .intr_delta_cts = SIO_IR_SA_DELTA_CTS,
+ .intr_tx_mt = SIO_IR_SA_TX_MT,
+ .intr_rx_timer = SIO_IR_SA_RX_TIMER,
+ .intr_rx_high = SIO_IR_SA_RX_HIGH,
+ .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT,
+ .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL
+ | SIO_IR_SA_RX_HIGH
+ | SIO_IR_SA_RX_TIMER
+ | SIO_IR_SA_DELTA_DCD
+ | SIO_IR_SA_DELTA_CTS
+ | SIO_IR_SA_INT
+ | SIO_IR_SA_TX_EXPLICIT
+ | SIO_IR_SA_MEMERR),
+ .intr_all = SIO_IR_SA,
+ .rs422_select_pin = GPPR_UARTA_MODESEL_PIN,
+ },
+
+ /* values for port B */
+ {
+ .intr_delta_dcd = SIO_IR_SB_DELTA_DCD,
+ .intr_delta_cts = SIO_IR_SB_DELTA_CTS,
+ .intr_tx_mt = SIO_IR_SB_TX_MT,
+ .intr_rx_timer = SIO_IR_SB_RX_TIMER,
+ .intr_rx_high = SIO_IR_SB_RX_HIGH,
+ .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT,
+ .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL
+ | SIO_IR_SB_RX_HIGH
+ | SIO_IR_SB_RX_TIMER
+ | SIO_IR_SB_DELTA_DCD
+ | SIO_IR_SB_DELTA_CTS
+ | SIO_IR_SB_INT
+ | SIO_IR_SB_TX_EXPLICIT
+ | SIO_IR_SB_MEMERR),
+ .intr_all = SIO_IR_SB,
+ .rs422_select_pin = GPPR_UARTB_MODESEL_PIN,
+ }
+};
+
+struct ring_entry {
+ union {
+ struct {
+ uint32_t alldata;
+ uint32_t allsc;
+ } all;
+ struct {
+ char data[4]; /* data bytes */
+ char sc[4]; /* status/control */
+ } s;
+ } u;
+};
+
+/* Test the valid bits in any of the 4 sc chars using "allsc" member */
+#define RING_ANY_VALID \
+ ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101)
+
+#define ring_sc u.s.sc
+#define ring_data u.s.data
+#define ring_allsc u.all.allsc
+
+/* Number of entries per ring buffer. */
+#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
+
+/* An individual ring */
+struct ring {
+ struct ring_entry entries[ENTRIES_PER_RING];
+};
+
+/* The whole enchilada */
+struct ring_buffer {
+ struct ring TX_A;
+ struct ring RX_A;
+ struct ring TX_B;
+ struct ring RX_B;
+};
+
+/* Get a ring from a port struct */
+#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
+
+/* for Infinite loop detection */
+#define MAXITER 10000000
+
+
+/**
+ * set_baud - Baud rate setting code
+ * @port: port to set
+ * @baud: baud rate to use
+ */
+static int set_baud(struct ioc3_port *port, int baud)
+{
+ int divisor;
+ int actual_baud;
+ int diff;
+ int lcr, prediv;
+ struct ioc3_uartregs __iomem *uart;
+
+ for (prediv = 6; prediv < 64; prediv++) {
+ divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv));
+ if (!divisor)
+ continue; /* invalid divisor */
+ actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv));
+
+ diff = actual_baud - baud;
+ if (diff < 0)
+ diff = -diff;
+
+ /* if we're within 1% we've found a match */
+ if (diff * 100 <= actual_baud)
+ break;
+ }
+
+ /* if the above loop completed, we didn't match
+ * the baud rate. give up.
+ */
+ if (prediv == 64) {
+ NOT_PROGRESS();
+ return 1;
+ }
+
+ uart = port->ip_uart_regs;
+ lcr = readb(&uart->iu_lcr);
+
+ writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr);
+ writeb((unsigned char)divisor, &uart->iu_dll);
+ writeb((unsigned char)(divisor >> 8), &uart->iu_dlm);
+ writeb((unsigned char)prediv, &uart->iu_scr);
+ writeb((unsigned char)lcr, &uart->iu_lcr);
+
+ return 0;
+}
+
+/**
+ * get_ioc3_port - given a uart port, return the control structure
+ * @the_port: uart port to find
+ */
+static struct ioc3_port *get_ioc3_port(struct uart_port *the_port)
+{
+ struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev);
+ struct ioc3_card *card_ptr = idd->data[Submodule_slot];
+ int ii, jj;
+
+ if (!card_ptr) {
+ NOT_PROGRESS();
+ return NULL;
+ }
+ for (ii = 0; ii < PORTS_PER_CARD; ii++) {
+ for (jj = 0; jj < LOGICAL_PORTS; jj++) {
+ if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj])
+ return card_ptr->ic_port[ii].icp_port;
+ }
+ }
+ NOT_PROGRESS();
+ return NULL;
+}
+
+/**
+ * port_init - Initialize the sio and ioc3 hardware for a given port
+ * called per port from attach...
+ * @port: port to initialize
+ */
+static int inline port_init(struct ioc3_port *port)
+{
+ uint32_t sio_cr;
+ struct port_hooks *hooks = port->ip_hooks;
+ struct ioc3_uartregs __iomem *uart;
+ int reset_loop_counter = 0xfffff;
+ struct ioc3_driver_data *idd = port->ip_idd;
+
+ /* Idle the IOC3 serial interface */
+ writel(SSCR_RESET, &port->ip_serial_regs->sscr);
+
+ /* Wait until any pending bus activity for this port has ceased */
+ do {
+ sio_cr = readl(&idd->vma->sio_cr);
+ if (reset_loop_counter-- <= 0) {
+ printk(KERN_WARNING
+ "IOC3 unable to come out of reset"
+ " scr 0x%x\n", sio_cr);
+ return -1;
+ }
+ } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) &&
+ (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA)
+ || sio_cr == SIO_CR_ARB_DIAG_TXB
+ || sio_cr == SIO_CR_ARB_DIAG_RXA
+ || sio_cr == SIO_CR_ARB_DIAG_RXB));
+
+ /* Finish reset sequence */
+ writel(0, &port->ip_serial_regs->sscr);
+
+ /* Once RESET is done, reload cached tx_prod and rx_cons values
+ * and set rings to empty by making prod == cons
+ */
+ port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
+ writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
+ port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+ writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
+
+ /* Disable interrupts for this 16550 */
+ uart = port->ip_uart_regs;
+ writeb(0, &uart->iu_lcr);
+ writeb(0, &uart->iu_ier);
+
+ /* Set the default baud */
+ set_baud(port, port->ip_baud);
+
+ /* Set line control to 8 bits no parity */
+ writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr);
+ /* UART_LCR_STOP == 1 stop */
+
+ /* Enable the FIFOs */
+ writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr);
+ /* then reset 16550 FIFOs */
+ writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+ &uart->iu_fcr);
+
+ /* Clear modem control register */
+ writeb(0, &uart->iu_mcr);
+
+ /* Clear deltas in modem status register */
+ writel(0, &port->ip_serial_regs->shadow);
+
+ /* Only do this once per port pair */
+ if (port->ip_hooks == &hooks_array[0]) {
+ unsigned long ring_pci_addr;
+ uint32_t __iomem *sbbr_l, *sbbr_h;
+
+ sbbr_l = &idd->vma->sbbr_l;
+ sbbr_h = &idd->vma->sbbr_h;
+ ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
+ DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
+ __FUNCTION__, (void *)ring_pci_addr));
+
+ writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
+ writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
+ }
+
+ /* Set the receive timeout value to 10 msec */
+ writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr);
+
+ /* Set rx threshold, enable DMA */
+ /* Set high water mark at 3/4 of full ring */
+ port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
+
+ /* uart experiences pauses at high baud rate reducing actual
+ * throughput by 10% or so unless we enable high speed polling
+ * XXX when this hardware bug is resolved we should revert to
+ * normal polling speed
+ */
+ port->ip_sscr |= SSCR_HIGH_SPD;
+
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Disable and clear all serial related interrupt bits */
+ port->ip_card->ic_enable &= ~hooks->intr_clear;
+ ioc3_disable(port->ip_is, idd, hooks->intr_clear);
+ ioc3_ack(port->ip_is, idd, hooks->intr_clear);
+ return 0;
+}
+
+/**
+ * enable_intrs - enable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static void enable_intrs(struct ioc3_port *port, uint32_t mask)
+{
+ if ((port->ip_card->ic_enable & mask) != mask) {
+ port->ip_card->ic_enable |= mask;
+ ioc3_enable(port->ip_is, port->ip_idd, mask);
+ }
+}
+
+/**
+ * local_open - local open a port
+ * @port: port to open
+ */
+static inline int local_open(struct ioc3_port *port)
+{
+ int spiniter = 0;
+
+ port->ip_flags = INPUT_ENABLE;
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr | SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER) {
+ NOT_PROGRESS();
+ return -1;
+ }
+ }
+ }
+
+ /* Reset the input fifo. If the uart received chars while the port
+ * was closed and DMA is not enabled, the uart may have a bunch of
+ * chars hanging around in its rx fifo which will not be discarded
+ * by rclr in the upper layer. We must get rid of them here.
+ */
+ writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
+ &port->ip_uart_regs->iu_fcr);
+
+ writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr);
+ /* UART_LCR_STOP == 1 stop */
+
+ /* Re-enable DMA, set default threshold to intr whenever there is
+ * data available.
+ */
+ port->ip_sscr &= ~SSCR_RX_THRESHOLD;
+ port->ip_sscr |= 1; /* default threshold */
+
+ /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
+ * flag if it was set above
+ */
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ port->ip_tx_lowat = 1;
+ return 0;
+}
+
+/**
+ * set_rx_timeout - Set rx timeout and threshold values.
+ * @port: port to use
+ * @timeout: timeout value in ticks
+ */
+static inline int set_rx_timeout(struct ioc3_port *port, int timeout)
+{
+ int threshold;
+
+ port->ip_rx_timeout = timeout;
+
+ /* Timeout is in ticks. Let's figure out how many chars we
+ * can receive at the current baud rate in that interval
+ * and set the rx threshold to that amount. There are 4 chars
+ * per ring entry, so we'll divide the number of chars that will
+ * arrive in timeout by 4.
+ * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
+ */
+ threshold = timeout * port->ip_baud / 4000;
+ if (threshold == 0)
+ threshold = 1; /* otherwise we'll intr all the time! */
+
+ if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD)
+ return 1;
+
+ port->ip_sscr &= ~SSCR_RX_THRESHOLD;
+ port->ip_sscr |= threshold;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Now set the rx timeout to the given value
+ * again timeout * SRTR_HZ / HZ
+ */
+ timeout = timeout * SRTR_HZ / 100;
+ if (timeout > SRTR_CNT)
+ timeout = SRTR_CNT;
+ writel(timeout, &port->ip_serial_regs->srtr);
+ return 0;
+}
+
+/**
+ * config_port - config the hardware
+ * @port: port to config
+ * @baud: baud rate for the port
+ * @byte_size: data size
+ * @stop_bits: number of stop bits
+ * @parenb: parity enable ?
+ * @parodd: odd parity ?
+ */
+static inline int
+config_port(struct ioc3_port *port,
+ int baud, int byte_size, int stop_bits, int parenb, int parodd)
+{
+ char lcr, sizebits;
+ int spiniter = 0;
+
+ DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
+ "parodd %d\n",
+ __FUNCTION__, ((struct uart_port *)port->ip_port)->line,
+ baud, byte_size, stop_bits, parenb, parodd));
+
+ if (set_baud(port, baud))
+ return 1;
+
+ switch (byte_size) {
+ case 5:
+ sizebits = UART_LCR_WLEN5;
+ break;
+ case 6:
+ sizebits = UART_LCR_WLEN6;
+ break;
+ case 7:
+ sizebits = UART_LCR_WLEN7;
+ break;
+ case 8:
+ sizebits = UART_LCR_WLEN8;
+ break;
+ default:
+ return 1;
+ }
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr | SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER)
+ return -1;
+ }
+ }
+
+ /* Clear relevant fields in lcr */
+ lcr = readb(&port->ip_uart_regs->iu_lcr);
+ lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
+ UART_LCR_PARITY | LCR_MASK_STOP_BITS);
+
+ /* Set byte size in lcr */
+ lcr |= sizebits;
+
+ /* Set parity */
+ if (parenb) {
+ lcr |= UART_LCR_PARITY;
+ if (!parodd)
+ lcr |= UART_LCR_EPAR;
+ }
+
+ /* Set stop bits */
+ if (stop_bits)
+ lcr |= UART_LCR_STOP /* 2 stop bits */ ;
+
+ writeb(lcr, &port->ip_uart_regs->iu_lcr);
+
+ /* Re-enable the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ port->ip_baud = baud;
+
+ /* When we get within this number of ring entries of filling the
+ * entire ring on tx, place an EXPLICIT intr to generate a lowat
+ * notification when output has drained.
+ */
+ port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
+ if (port->ip_tx_lowat == 0)
+ port->ip_tx_lowat = 1;
+
+ set_rx_timeout(port, 2);
+ return 0;
+}
+
+/**
+ * do_write - Write bytes to the port. Returns the number of bytes
+ * actually written. Called from transmit_chars
+ * @port: port to use
+ * @buf: the stuff to write
+ * @len: how many bytes in 'buf'
+ */
+static inline int do_write(struct ioc3_port *port, char *buf, int len)
+{
+ int prod_ptr, cons_ptr, total = 0;
+ struct ring *outring;
+ struct ring_entry *entry;
+ struct port_hooks *hooks = port->ip_hooks;
+
+ BUG_ON(!(len >= 0));
+
+ prod_ptr = port->ip_tx_prod;
+ cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
+ outring = port->ip_outring;
+
+ /* Maintain a 1-entry red-zone. The ring buffer is full when
+ * (cons - prod) % ring_size is 1. Rather than do this subtraction
+ * in the body of the loop, I'll do it now.
+ */
+ cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
+
+ /* Stuff the bytes into the output */
+ while ((prod_ptr != cons_ptr) && (len > 0)) {
+ int xx;
+
+ /* Get 4 bytes (one ring entry) at a time */
+ entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
+
+ /* Invalidate all entries */
+ entry->ring_allsc = 0;
+
+ /* Copy in some bytes */
+ for (xx = 0; (xx < 4) && (len > 0); xx++) {
+ entry->ring_data[xx] = *buf++;
+ entry->ring_sc[xx] = TXCB_VALID;
+ len--;
+ total++;
+ }
+
+ /* If we are within some small threshold of filling up the
+ * entire ring buffer, we must place an EXPLICIT intr here
+ * to generate a lowat interrupt in case we subsequently
+ * really do fill up the ring and the caller goes to sleep.
+ * No need to place more than one though.
+ */
+ if (!(port->ip_flags & LOWAT_WRITTEN) &&
+ ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
+ <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) {
+ port->ip_flags |= LOWAT_WRITTEN;
+ entry->ring_sc[0] |= TXCB_INT_WHEN_DONE;
+ }
+
+ /* Go on to next entry */
+ prod_ptr += sizeof(struct ring_entry);
+ prod_ptr &= PROD_CONS_MASK;
+ }
+
+ /* If we sent something, start DMA if necessary */
+ if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) {
+ port->ip_sscr |= SSCR_DMA_EN;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+
+ /* Store the new producer pointer. If tx is disabled, we stuff the
+ * data into the ring buffer, but we don't actually start tx.
+ */
+ if (!uart_tx_stopped(port->ip_port)) {
+ writel(prod_ptr, &port->ip_serial_regs->stpir);
+
+ /* If we are now transmitting, enable tx_mt interrupt so we
+ * can disable DMA if necessary when the tx finishes.
+ */
+ if (total > 0)
+ enable_intrs(port, hooks->intr_tx_mt);
+ }
+ port->ip_tx_prod = prod_ptr;
+
+ return total;
+}
+
+/**
+ * disable_intrs - disable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static inline void disable_intrs(struct ioc3_port *port, uint32_t mask)
+{
+ if (port->ip_card->ic_enable & mask) {
+ ioc3_disable(port->ip_is, port->ip_idd, mask);
+ port->ip_card->ic_enable &= ~mask;
+ }
+}
+
+/**
+ * set_notification - Modify event notification
+ * @port: port to use
+ * @mask: events mask
+ * @set_on: set ?
+ */
+static int set_notification(struct ioc3_port *port, int mask, int set_on)
+{
+ struct port_hooks *hooks = port->ip_hooks;
+ uint32_t intrbits, sscrbits;
+
+ BUG_ON(!mask);
+
+ intrbits = sscrbits = 0;
+
+ if (mask & N_DATA_READY)
+ intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
+ if (mask & N_OUTPUT_LOWAT)
+ intrbits |= hooks->intr_tx_explicit;
+ if (mask & N_DDCD) {
+ intrbits |= hooks->intr_delta_dcd;
+ sscrbits |= SSCR_RX_RING_DCD;
+ }
+ if (mask & N_DCTS)
+ intrbits |= hooks->intr_delta_cts;
+
+ if (set_on) {
+ enable_intrs(port, intrbits);
+ port->ip_notify |= mask;
+ port->ip_sscr |= sscrbits;
+ } else {
+ disable_intrs(port, intrbits);
+ port->ip_notify &= ~mask;
+ port->ip_sscr &= ~sscrbits;
+ }
+
+ /* We require DMA if either DATA_READY or DDCD notification is
+ * currently requested. If neither of these is requested and
+ * there is currently no tx in progress, DMA may be disabled.
+ */
+ if (port->ip_notify & (N_DATA_READY | N_DDCD))
+ port->ip_sscr |= SSCR_DMA_EN;
+ else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt))
+ port->ip_sscr &= ~SSCR_DMA_EN;
+
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ return 0;
+}
+
+/**
+ * set_mcr - set the master control reg
+ * @the_port: port to use
+ * @mask1: mcr mask
+ * @mask2: shadow mask
+ */
+static inline int set_mcr(struct uart_port *the_port,
+ int mask1, int mask2)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ uint32_t shadow;
+ int spiniter = 0;
+ char mcr;
+
+ if (!port)
+ return -1;
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr | SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER)
+ return -1;
+ }
+ }
+ shadow = readl(&port->ip_serial_regs->shadow);
+ mcr = (shadow & 0xff000000) >> 24;
+
+ /* Set new value */
+ mcr |= mask1;
+ shadow |= mask2;
+ writeb(mcr, &port->ip_uart_regs->iu_mcr);
+ writel(shadow, &port->ip_serial_regs->shadow);
+
+ /* Re-enable the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ return 0;
+}
+
+/**
+ * ioc3_set_proto - set the protocol for the port
+ * @port: port to use
+ * @proto: protocol to use
+ */
+static int ioc3_set_proto(struct ioc3_port *port, int proto)
+{
+ struct port_hooks *hooks = port->ip_hooks;
+
+ switch (proto) {
+ default:
+ case PROTO_RS232:
+ /* Clear the appropriate GIO pin */
+ DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__));
+ writel(0, (&port->ip_idd->vma->gppr[0]
+ + hooks->rs422_select_pin));
+ break;
+
+ case PROTO_RS422:
+ /* Set the appropriate GIO pin */
+ DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__));
+ writel(1, (&port->ip_idd->vma->gppr[0]
+ + hooks->rs422_select_pin));
+ break;
+ }
+ return 0;
+}
+
+/**
+ * transmit_chars - upper level write, called with the_port->lock
+ * @the_port: port to write
+ */
+static void transmit_chars(struct uart_port *the_port)
+{
+ int xmit_count, tail, head;
+ int result;
+ char *start;
+ struct tty_struct *tty;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ struct uart_info *info;
+
+ if (!the_port)
+ return;
+ if (!port)
+ return;
+
+ info = the_port->info;
+ tty = info->tty;
+
+ if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) {
+ /* Nothing to do or hw stopped */
+ set_notification(port, N_ALL_OUTPUT, 0);
+ return;
+ }
+
+ head = info->xmit.head;
+ tail = info->xmit.tail;
+ start = (char *)&info->xmit.buf[tail];
+
+ /* write out all the data or until the end of the buffer */
+ xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
+ if (xmit_count > 0) {
+ result = do_write(port, start, xmit_count);
+ if (result > 0) {
+ /* booking */
+ xmit_count -= result;
+ the_port->icount.tx += result;
+ /* advance the pointers */
+ tail += result;
+ tail &= UART_XMIT_SIZE - 1;
+ info->xmit.tail = tail;
+ start = (char *)&info->xmit.buf[tail];
+ }
+ }
+ if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(the_port);
+
+ if (uart_circ_empty(&info->xmit)) {
+ set_notification(port, N_OUTPUT_LOWAT, 0);
+ } else {
+ set_notification(port, N_OUTPUT_LOWAT, 1);
+ }
+}
+
+/**
+ * ioc3_change_speed - change the speed of the port
+ * @the_port: port to change
+ * @new_termios: new termios settings
+ * @old_termios: old termios settings
+ */
+static void
+ioc3_change_speed(struct uart_port *the_port,
+ struct termios *new_termios, struct termios *old_termios)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ unsigned int cflag;
+ int baud;
+ int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
+ struct uart_info *info = the_port->info;
+
+ cflag = new_termios->c_cflag;
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ new_data = 5;
+ break;
+ case CS6:
+ new_data = 6;
+ break;
+ case CS7:
+ new_data = 7;
+ break;
+ case CS8:
+ new_data = 8;
+ break;
+ default:
+ /* cuz we always need a default ... */
+ new_data = 5;
+ break;
+ }
+ if (cflag & CSTOPB) {
+ new_stop = 1;
+ }
+ if (cflag & PARENB) {
+ new_parity_enable = 1;
+ if (cflag & PARODD)
+ new_parity = 1;
+ }
+ baud = uart_get_baud_rate(the_port, new_termios, old_termios,
+ MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
+ DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud,
+ the_port->line));
+
+ if (!the_port->fifosize)
+ the_port->fifosize = FIFO_SIZE;
+ uart_update_timeout(the_port, cflag, baud);
+
+ 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);
+ if (I_IGNBRK(info->tty)) {
+ the_port->ignore_status_mask &= ~N_BREAK;
+ if (I_IGNPAR(info->tty))
+ the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
+ }
+ if (!(cflag & CREAD)) {
+ /* ignore everything */
+ the_port->ignore_status_mask &= ~N_DATA_READY;
+ }
+
+ if (cflag & CRTSCTS) {
+ /* enable hardware flow control */
+ port->ip_sscr |= SSCR_HFC_EN;
+ }
+ else {
+ /* disable hardware flow control */
+ port->ip_sscr &= ~SSCR_HFC_EN;
+ }
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Set the configuration and proper notification call */
+ DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
+ "config_port(baud %d data %d stop %d penable %d "
+ " parity %d), notification 0x%x\n",
+ __FUNCTION__, (void *)port, the_port->line, cflag, baud,
+ new_data, new_stop, new_parity_enable, new_parity,
+ the_port->ignore_status_mask));
+
+ if ((config_port(port, baud, /* baud */
+ new_data, /* byte size */
+ new_stop, /* stop bits */
+ new_parity_enable, /* set parity */
+ new_parity)) >= 0) { /* parity 1==odd */
+ set_notification(port, the_port->ignore_status_mask, 1);
+ }
+}
+
+/**
+ * ic3_startup_local - Start up the serial port - returns >= 0 if no errors
+ * @the_port: Port to operate on
+ */
+static inline int ic3_startup_local(struct uart_port *the_port)
+{
+ struct ioc3_port *port;
+
+ if (!the_port) {
+ NOT_PROGRESS();
+ return -1;
+ }
+
+ port = get_ioc3_port(the_port);
+ if (!port) {
+ NOT_PROGRESS();
+ return -1;
+ }
+
+ local_open(port);
+
+ /* set the protocol */
+ ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 :
+ PROTO_RS422);
+ return 0;
+}
+
+/*
+ * ioc3_cb_output_lowat - called when the output low water mark is hit
+ * @port: port to output
+ */
+static void ioc3_cb_output_lowat(struct ioc3_port *port)
+{
+ unsigned long pflags;
+
+ /* the_port->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);
+ }
+}
+
+/*
+ * ioc3_cb_post_ncs - called for some basic errors
+ * @port: port to use
+ * @ncs: event
+ */
+static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs)
+{
+ struct uart_icount *icount;
+
+ icount = &the_port->icount;
+
+ if (ncs & NCS_BREAK)
+ icount->brk++;
+ if (ncs & NCS_FRAMING)
+ icount->frame++;
+ if (ncs & NCS_OVERRUN)
+ icount->overrun++;
+ if (ncs & NCS_PARITY)
+ icount->parity++;
+}
+
+/**
+ * do_read - Read in bytes from the port. Return the number of bytes
+ * actually read.
+ * @the_port: port to use
+ * @buf: place to put the stuff we read
+ * @len: how big 'buf' is
+ */
+
+static inline int do_read(struct uart_port *the_port, char *buf, int len)
+{
+ int prod_ptr, cons_ptr, total;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ struct ring *inring;
+ struct ring_entry *entry;
+ struct port_hooks *hooks = port->ip_hooks;
+ int byte_num;
+ char *sc;
+ int loop_counter;
+
+ BUG_ON(!(len >= 0));
+ BUG_ON(!port);
+
+ /* There is a nasty timing issue in the IOC3. When the rx_timer
+ * expires or the rx_high condition arises, we take an interrupt.
+ * At some point while servicing the interrupt, we read bytes from
+ * the ring buffer and re-arm the rx_timer. However the rx_timer is
+ * not started until the first byte is received *after* it is armed,
+ * and any bytes pending in the rx construction buffers are not drained
+ * to memory until either there are 4 bytes available or the rx_timer
+ * expires. This leads to a potential situation where data is left
+ * in the construction buffers forever - 1 to 3 bytes were received
+ * after the interrupt was generated but before the rx_timer was
+ * re-armed. At that point as long as no subsequent bytes are received
+ * the timer will never be started and the bytes will remain in the
+ * construction buffer forever. The solution is to execute a DRAIN
+ * command after rearming the timer. This way any bytes received before
+ * the DRAIN will be drained to memory, and any bytes received after
+ * the DRAIN will start the TIMER and be drained when it expires.
+ * Luckily, this only needs to be done when the DMA buffer is empty
+ * since there is no requirement that this function return all
+ * available data as long as it returns some.
+ */
+ /* Re-arm the timer */
+
+ writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
+
+ prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+ cons_ptr = port->ip_rx_cons;
+
+ if (prod_ptr == cons_ptr) {
+ int reset_dma = 0;
+
+ /* Input buffer appears empty, do a flush. */
+
+ /* DMA must be enabled for this to work. */
+ if (!(port->ip_sscr & SSCR_DMA_EN)) {
+ port->ip_sscr |= SSCR_DMA_EN;
+ reset_dma = 1;
+ }
+
+ /* Potential race condition: we must reload the srpir after
+ * issuing the drain command, otherwise we could think the rx
+ * buffer is empty, then take a very long interrupt, and when
+ * we come back it's full and we wait forever for the drain to
+ * complete.
+ */
+ writel(port->ip_sscr | SSCR_RX_DRAIN,
+ &port->ip_serial_regs->sscr);
+ prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+
+ /* We must not wait for the DRAIN to complete unless there are
+ * at least 8 bytes (2 ring entries) available to receive the
+ * data otherwise the DRAIN will never complete and we'll
+ * deadlock here.
+ * In fact, to make things easier, I'll just ignore the flush if
+ * there is any data at all now available.
+ */
+ if (prod_ptr == cons_ptr) {
+ loop_counter = 0;
+ while (readl(&port->ip_serial_regs->sscr) &
+ SSCR_RX_DRAIN) {
+ loop_counter++;
+ if (loop_counter > MAXITER)
+ return -1;
+ }
+
+ /* SIGH. We have to reload the prod_ptr *again* since
+ * the drain may have caused it to change
+ */
+ prod_ptr = readl(&port->ip_serial_regs->srpir)
+ & PROD_CONS_MASK;
+ }
+ if (reset_dma) {
+ port->ip_sscr &= ~SSCR_DMA_EN;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ }
+ inring = port->ip_inring;
+ port->ip_flags &= ~READ_ABORTED;
+
+ total = 0;
+ loop_counter = 0xfffff; /* to avoid hangs */
+
+ /* Grab bytes from the hardware */
+ while ((prod_ptr != cons_ptr) && (len > 0)) {
+ entry = (struct ring_entry *)((caddr_t) inring + cons_ptr);
+
+ if (loop_counter-- <= 0) {
+ printk(KERN_WARNING "IOC3 serial: "
+ "possible hang condition/"
+ "port stuck on read (line %d).\n",
+ the_port->line);
+ break;
+ }
+
+ /* According to the producer pointer, this ring entry
+ * must contain some data. But if the PIO happened faster
+ * than the DMA, the data may not be available yet, so let's
+ * wait until it arrives.
+ */
+ if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
+ /* Indicate the read is aborted so we don't disable
+ * the interrupt thinking that the consumer is
+ * congested.
+ */
+ port->ip_flags |= READ_ABORTED;
+ len = 0;
+ break;
+ }
+
+ /* Load the bytes/status out of the ring entry */
+ for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
+ sc = &(entry->ring_sc[byte_num]);
+
+ /* Check for change in modem state or overrun */
+ if ((*sc & RXSB_MODEM_VALID)
+ && (port->ip_notify & N_DDCD)) {
+ /* Notify upper layer if DCD dropped */
+ if ((port->ip_flags & DCD_ON)
+ && !(*sc & RXSB_DCD)) {
+ /* If we have already copied some data,
+ * return it. We'll pick up the carrier
+ * drop on the next pass. That way we
+ * don't throw away the data that has
+ * already been copied back to
+ * the caller's buffer.
+ */
+ if (total > 0) {
+ len = 0;
+ break;
+ }
+ port->ip_flags &= ~DCD_ON;
+
+ /* Turn off this notification so the
+ * carrier drop protocol won't see it
+ * again when it does a read.
+ */
+ *sc &= ~RXSB_MODEM_VALID;
+
+ /* To keep things consistent, we need
+ * to update the consumer pointer so
+ * the next reader won't come in and
+ * try to read the same ring entries
+ * again. This must be done here before
+ * the dcd change.
+ */
+
+ if ((entry->ring_allsc & RING_ANY_VALID)
+ == 0) {
+ cons_ptr += (int)sizeof
+ (struct ring_entry);
+ cons_ptr &= PROD_CONS_MASK;
+ }
+ writel(cons_ptr,
+ &port->ip_serial_regs->srcir);
+ port->ip_rx_cons = cons_ptr;
+
+ /* Notify upper layer of carrier drop */
+ if ((port->ip_notify & N_DDCD)
+ && port->ip_port) {
+ uart_handle_dcd_change
+ (port->ip_port, 0);
+ wake_up_interruptible
+ (&the_port->info->
+ delta_msr_wait);
+ }
+
+ /* If we had any data to return, we
+ * would have returned it above.
+ */
+ return 0;
+ }
+ }
+ if (*sc & RXSB_MODEM_VALID) {
+ /* Notify that an input overrun occurred */
+ if ((*sc & RXSB_OVERRUN)
+ && (port->ip_notify & N_OVERRUN_ERROR)) {
+ ioc3_cb_post_ncs(the_port, NCS_OVERRUN);
+ }
+ /* Don't look at this byte again */
+ *sc &= ~RXSB_MODEM_VALID;
+ }
+
+ /* Check for valid data or RX errors */
+ if ((*sc & RXSB_DATA_VALID) &&
+ ((*sc & (RXSB_PAR_ERR
+ | RXSB_FRAME_ERR | RXSB_BREAK))
+ && (port->ip_notify & (N_PARITY_ERROR
+ | N_FRAMING_ERROR
+ | N_BREAK)))) {
+ /* There is an error condition on the next byte.
+ * If we have already transferred some bytes,
+ * we'll stop here. Otherwise if this is the
+ * first byte to be read, we'll just transfer
+ * it alone after notifying the
+ * upper layer of its status.
+ */
+ if (total > 0) {
+ len = 0;
+ break;
+ } else {
+ if ((*sc & RXSB_PAR_ERR) &&
+ (port->
+ ip_notify & N_PARITY_ERROR)) {
+ ioc3_cb_post_ncs(the_port,
+ NCS_PARITY);
+ }
+ if ((*sc & RXSB_FRAME_ERR) &&
+ (port->
+ ip_notify & N_FRAMING_ERROR)) {
+ ioc3_cb_post_ncs(the_port,
+ NCS_FRAMING);
+ }
+ if ((*sc & RXSB_BREAK)
+ && (port->ip_notify & N_BREAK)) {
+ ioc3_cb_post_ncs
+ (the_port, NCS_BREAK);
+ }
+ len = 1;
+ }
+ }
+ if (*sc & RXSB_DATA_VALID) {
+ *sc &= ~RXSB_DATA_VALID;
+ *buf = entry->ring_data[byte_num];
+ buf++;
+ len--;
+ total++;
+ }
+ }
+
+ /* If we used up this entry entirely, go on to the next one,
+ * otherwise we must have run out of buffer space, so
+ * leave the consumer pointer here for the next read in case
+ * there are still unread bytes in this entry.
+ */
+ if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
+ cons_ptr += (int)sizeof(struct ring_entry);
+ cons_ptr &= PROD_CONS_MASK;
+ }
+ }
+
+ /* Update consumer pointer and re-arm rx timer interrupt */
+ writel(cons_ptr, &port->ip_serial_regs->srcir);
+ port->ip_rx_cons = cons_ptr;
+
+ /* If we have now dipped below the rx high water mark and we have
+ * rx_high interrupt turned off, we can now turn it back on again.
+ */
+ if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
+ & PROD_CONS_MASK) <
+ ((port->
+ ip_sscr &
+ SSCR_RX_THRESHOLD)
+ << PROD_CONS_PTR_OFF))) {
+ port->ip_flags &= ~INPUT_HIGH;
+ enable_intrs(port, hooks->intr_rx_high);
+ }
+ return total;
+}
+
+/**
+ * receive_chars - upper level read.
+ * @the_port: port to read from
+ */
+static int receive_chars(struct uart_port *the_port)
+{
+ struct tty_struct *tty;
+ unsigned char ch[MAX_CHARS];
+ int read_count = 0, read_room, flip = 0;
+ struct uart_info *info = the_port->info;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ unsigned long pflags;
+
+ /* Make sure all the pointers are "good" ones */
+ if (!info)
+ return 0;
+ if (!info->tty)
+ return 0;
+
+ if (!(port->ip_flags & INPUT_ENABLE))
+ return 0;
+
+ spin_lock_irqsave(&the_port->lock, pflags);
+ tty = info->tty;
+
+ read_count = do_read(the_port, ch, MAX_CHARS);
+ if (read_count > 0) {
+ flip = 1;
+ read_room = tty_buffer_request_room(tty, read_count);
+ tty_insert_flip_string(tty, ch, read_room);
+ the_port->icount.rx += read_count;
+ }
+ spin_unlock_irqrestore(&the_port->lock, pflags);
+
+ if (flip)
+ tty_flip_buffer_push(tty);
+
+ return read_count;
+}
+
+/**
+ * ioc3uart_intr_one - lowest level (per port) interrupt handler.
+ * @is : submodule
+ * @idd: driver data
+ * @pending: interrupts to handle
+ * @regs: pt_regs
+ */
+
+static int inline
+ioc3uart_intr_one(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd,
+ unsigned int pending, struct pt_regs *regs)
+{
+ int port_num = GET_PORT_FROM_SIO_IR(pending);
+ struct port_hooks *hooks;
+ unsigned int rx_high_rd_aborted = 0;
+ unsigned long flags;
+ struct uart_port *the_port;
+ struct ioc3_port *port;
+ int loop_counter;
+ struct ioc3_card *card_ptr;
+ unsigned int sio_ir;
+
+ card_ptr = idd->data[is->id];
+ port = card_ptr->ic_port[port_num].icp_port;
+ hooks = port->ip_hooks;
+
+ /* Possible race condition here: The tx_mt interrupt bit may be
+ * cleared without the intervention of the interrupt handler,
+ * e.g. by a write. If the top level interrupt handler reads a
+ * tx_mt, then some other processor does a write, starting up
+ * output, then we come in here, see the tx_mt and stop DMA, the
+ * output started by the other processor will hang. Thus we can
+ * only rely on tx_mt being legitimate if it is read while the
+ * port lock is held. Therefore this bit must be ignored in the
+ * passed in interrupt mask which was read by the top level
+ * interrupt handler since the port lock was not held at the time
+ * it was read. We can only rely on this bit being accurate if it
+ * is read while the port lock is held. So we'll clear it for now,
+ * and reload it later once we have the port lock.
+ */
+
+ sio_ir = pending & ~(hooks->intr_tx_mt);
+ spin_lock_irqsave(&port->ip_lock, flags);
+
+ loop_counter = MAXITER; /* to avoid hangs */
+
+ do {
+ uint32_t shadow;
+
+ if (loop_counter-- <= 0) {
+ printk(KERN_WARNING "IOC3 serial: "
+ "possible hang condition/"
+ "port stuck on interrupt (line %d).\n",
+ ((struct uart_port *)port->ip_port)->line);
+ break;
+ }
+ /* Handle a DCD change */
+ if (sio_ir & hooks->intr_delta_dcd) {
+ ioc3_ack(is, idd, hooks->intr_delta_dcd);
+ shadow = readl(&port->ip_serial_regs->shadow);
+
+ if ((port->ip_notify & N_DDCD)
+ && (shadow & SHADOW_DCD)
+ && (port->ip_port)) {
+ the_port = port->ip_port;
+ uart_handle_dcd_change(the_port,
+ shadow & SHADOW_DCD);
+ wake_up_interruptible
+ (&the_port->info->delta_msr_wait);
+ } else if ((port->ip_notify & N_DDCD)
+ && !(shadow & SHADOW_DCD)) {
+ /* Flag delta DCD/no DCD */
+ uart_handle_dcd_change(port->ip_port,
+ shadow & SHADOW_DCD);
+ port->ip_flags |= DCD_ON;
+ }
+ }
+
+ /* Handle a CTS change */
+ if (sio_ir & hooks->intr_delta_cts) {
+ ioc3_ack(is, idd, hooks->intr_delta_cts);
+ shadow = readl(&port->ip_serial_regs->shadow);
+
+ if ((port->ip_notify & N_DCTS) && (port->ip_port)) {
+ the_port = port->ip_port;
+ uart_handle_cts_change(the_port, shadow
+ & SHADOW_CTS);
+ wake_up_interruptible
+ (&the_port->info->delta_msr_wait);
+ }
+ }
+
+ /* rx timeout interrupt. Must be some data available. Put this
+ * before the check for rx_high since servicing this condition
+ * may cause that condition to clear.
+ */
+ if (sio_ir & hooks->intr_rx_timer) {
+ ioc3_ack(is, idd, hooks->intr_rx_timer);
+ if ((port->ip_notify & N_DATA_READY)
+ && (port->ip_port)) {
+ receive_chars(port->ip_port);
+ }
+ }
+
+ /* rx high interrupt. Must be after rx_timer. */
+ else if (sio_ir & hooks->intr_rx_high) {
+ /* Data available, notify upper layer */
+ if ((port->ip_notify & N_DATA_READY) && port->ip_port) {
+ receive_chars(port->ip_port);
+ }
+
+ /* We can't ACK this interrupt. If receive_chars didn't
+ * cause the condition to clear, we'll have to disable
+ * the interrupt until the data is drained.
+ * If the read was aborted, don't disable the interrupt
+ * as this may cause us to hang indefinitely. An
+ * aborted read generally means that this interrupt
+ * hasn't been delivered to the cpu yet anyway, even
+ * though we see it as asserted when we read the sio_ir.
+ */
+ if ((sio_ir = PENDING(card_ptr, idd))
+ & hooks->intr_rx_high) {
+ if (port->ip_flags & READ_ABORTED) {
+ rx_high_rd_aborted++;
+ }
+ else {
+ card_ptr->ic_enable &= ~hooks->intr_rx_high;
+ port->ip_flags |= INPUT_HIGH;
+ }
+ }
+ }
+
+ /* We got a low water interrupt: notify upper layer to
+ * send more data. Must come before tx_mt since servicing
+ * this condition may cause that condition to clear.
+ */
+ if (sio_ir & hooks->intr_tx_explicit) {
+ port->ip_flags &= ~LOWAT_WRITTEN;
+ ioc3_ack(is, idd, hooks->intr_tx_explicit);
+ if (port->ip_notify & N_OUTPUT_LOWAT)
+ ioc3_cb_output_lowat(port);
+ }
+
+ /* Handle tx_mt. Must come after tx_explicit. */
+ else if (sio_ir & hooks->intr_tx_mt) {
+ /* If we are expecting a lowat notification
+ * and we get to this point it probably means that for
+ * some reason the tx_explicit didn't work as expected
+ * (that can legitimately happen if the output buffer is
+ * filled up in just the right way).
+ * So send the notification now.
+ */
+ if (port->ip_notify & N_OUTPUT_LOWAT) {
+ ioc3_cb_output_lowat(port);
+
+ /* We need to reload the sio_ir since the lowat
+ * call may have caused another write to occur,
+ * clearing the tx_mt condition.
+ */
+ sio_ir = PENDING(card_ptr, idd);
+ }
+
+ /* If the tx_mt condition still persists even after the
+ * lowat call, we've got some work to do.
+ */
+ if (sio_ir & hooks->intr_tx_mt) {
+ /* If we are not currently expecting DMA input,
+ * and the transmitter has just gone idle,
+ * there is no longer any reason for DMA, so
+ * disable it.
+ */
+ if (!(port->ip_notify
+ & (N_DATA_READY | N_DDCD))) {
+ BUG_ON(!(port->ip_sscr
+ & SSCR_DMA_EN));
+ port->ip_sscr &= ~SSCR_DMA_EN;
+ writel(port->ip_sscr,
+ &port->ip_serial_regs->sscr);
+ }
+ /* Prevent infinite tx_mt interrupt */
+ card_ptr->ic_enable &= ~hooks->intr_tx_mt;
+ }
+ }
+ sio_ir = PENDING(card_ptr, idd);
+
+ /* if the read was aborted and only hooks->intr_rx_high,
+ * clear hooks->intr_rx_high, so we do not loop forever.
+ */
+
+ if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
+ sio_ir &= ~hooks->intr_rx_high;
+ }
+ } while (sio_ir & hooks->intr_all);
+
+ spin_unlock_irqrestore(&port->ip_lock, flags);
+ ioc3_enable(is, idd, card_ptr->ic_enable);
+ return 0;
+}
+
+/**
+ * ioc3uart_intr - field all serial interrupts
+ * @is : submodule
+ * @idd: driver data
+ * @pending: interrupts to handle
+ * @regs: pt_regs
+ *
+ */
+
+static int ioc3uart_intr(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd,
+ unsigned int pending, struct pt_regs *regs)
+{
+ int ret = 0;
+
+ /*
+ * The upper level interrupt handler sends interrupts for both ports
+ * here. So we need to call for each port with its interrupts.
+ */
+
+ if (pending & SIO_IR_SA)
+ ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs);
+ if (pending & SIO_IR_SB)
+ ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs);
+
+ return ret;
+}
+
+/**
+ * ic3_type
+ * @port: Port to operate with (we ignore since we only have one port)
+ *
+ */
+static const char *ic3_type(struct uart_port *the_port)
+{
+ if (IS_RS232(the_port->line))
+ return "SGI IOC3 Serial [rs232]";
+ else
+ return "SGI IOC3 Serial [rs422]";
+}
+
+/**
+ * ic3_tx_empty - Is the transmitter empty?
+ * @port: Port to operate on
+ *
+ */
+static unsigned int ic3_tx_empty(struct uart_port *the_port)
+{
+ unsigned int ret = 0;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT)
+ ret = TIOCSER_TEMT;
+ return ret;
+}
+
+/**
+ * ic3_stop_tx - stop the transmitter
+ * @port: Port to operate on
+ *
+ */
+static void ic3_stop_tx(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (port)
+ set_notification(port, N_OUTPUT_LOWAT, 0);
+}
+
+/**
+ * ic3_stop_rx - stop the receiver
+ * @port: Port to operate on
+ *
+ */
+static void ic3_stop_rx(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (port)
+ port->ip_flags &= ~INPUT_ENABLE;
+}
+
+/**
+ * null_void_function
+ * @port: Port to operate on
+ *
+ */
+static void null_void_function(struct uart_port *the_port)
+{
+}
+
+/**
+ * ic3_shutdown - shut down the port - free irq and disable
+ * @port: port to shut down
+ *
+ */
+static void ic3_shutdown(struct uart_port *the_port)
+{
+ unsigned long port_flags;
+ struct ioc3_port *port;
+ struct uart_info *info;
+
+ port = get_ioc3_port(the_port);
+ if (!port)
+ return;
+
+ info = the_port->info;
+ wake_up_interruptible(&info->delta_msr_wait);
+
+ spin_lock_irqsave(&the_port->lock, port_flags);
+ set_notification(port, N_ALL, 0);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
+}
+
+/**
+ * ic3_set_mctrl - set control lines (dtr, rts, etc)
+ * @port: Port to operate on
+ * @mctrl: Lines to set/unset
+ *
+ */
+static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
+{
+ unsigned char mcr = 0;
+
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ set_mcr(the_port, mcr, SHADOW_DTR);
+}
+
+/**
+ * ic3_get_mctrl - get control line info
+ * @port: port to operate on
+ *
+ */
+static unsigned int ic3_get_mctrl(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ uint32_t shadow;
+ unsigned int ret = 0;
+
+ if (!port)
+ return 0;
+
+ shadow = readl(&port->ip_serial_regs->shadow);
+ if (shadow & SHADOW_DCD)
+ ret |= TIOCM_CD;
+ if (shadow & SHADOW_DR)
+ ret |= TIOCM_DSR;
+ if (shadow & SHADOW_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+/**
+ * ic3_start_tx - Start transmitter. Called with the_port->lock
+ * @port: Port to operate on
+ *
+ */
+static void ic3_start_tx(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (port) {
+ set_notification(port, N_OUTPUT_LOWAT, 1);
+ enable_intrs(port, port->ip_hooks->intr_tx_mt);
+ }
+}
+
+/**
+ * ic3_break_ctl - handle breaks
+ * @port: Port to operate on
+ * @break_state: Break state
+ *
+ */
+static void ic3_break_ctl(struct uart_port *the_port, int break_state)
+{
+}
+
+/**
+ * ic3_startup - Start up the serial port - always return 0 (We're always on)
+ * @port: Port to operate on
+ *
+ */
+static int ic3_startup(struct uart_port *the_port)
+{
+ int retval;
+ struct ioc3_port *port;
+ struct ioc3_card *card_ptr;
+ unsigned long port_flags;
+
+ if (!the_port) {
+ NOT_PROGRESS();
+ return -ENODEV;
+ }
+ port = get_ioc3_port(the_port);
+ if (!port) {
+ NOT_PROGRESS();
+ return -ENODEV;
+ }
+ card_ptr = port->ip_card;
+ port->ip_port = the_port;
+
+ if (!card_ptr) {
+ NOT_PROGRESS();
+ return -ENODEV;
+ }
+
+ /* Start up the serial port */
+ spin_lock_irqsave(&the_port->lock, port_flags);
+ retval = ic3_startup_local(the_port);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
+ return retval;
+}
+
+/**
+ * ic3_set_termios - set termios stuff
+ * @port: port to operate on
+ * @termios: New settings
+ * @termios: Old
+ *
+ */
+static void
+ic3_set_termios(struct uart_port *the_port,
+ struct termios *termios, struct termios *old_termios)
+{
+ unsigned long port_flags;
+
+ spin_lock_irqsave(&the_port->lock, port_flags);
+ ioc3_change_speed(the_port, termios, old_termios);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
+}
+
+/**
+ * ic3_request_port - allocate resources for port - no op....
+ * @port: port to operate on
+ *
+ */
+static int ic3_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+/* Associate the uart functions above - given to serial core */
+static struct uart_ops ioc3_ops = {
+ .tx_empty = ic3_tx_empty,
+ .set_mctrl = ic3_set_mctrl,
+ .get_mctrl = ic3_get_mctrl,
+ .stop_tx = ic3_stop_tx,
+ .start_tx = ic3_start_tx,
+ .stop_rx = ic3_stop_rx,
+ .enable_ms = null_void_function,
+ .break_ctl = ic3_break_ctl,
+ .startup = ic3_startup,
+ .shutdown = ic3_shutdown,
+ .set_termios = ic3_set_termios,
+ .type = ic3_type,
+ .release_port = null_void_function,
+ .request_port = ic3_request_port,
+};
+
+/*
+ * Boot-time initialization code
+ */
+
+static struct uart_driver ioc3_uart = {
+ .owner = THIS_MODULE,
+ .driver_name = "ioc3_serial",
+ .dev_name = DEVICE_NAME,
+ .major = DEVICE_MAJOR,
+ .minor = DEVICE_MINOR,
+ .nr = MAX_LOGICAL_PORTS
+};
+
+/**
+ * ioc3_serial_core_attach - register with serial core
+ * This is done during pci probing
+ * @is: submodule struct for this
+ * @idd: handle for this card
+ */
+static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd)
+{
+ struct ioc3_port *port;
+ struct uart_port *the_port;
+ struct ioc3_card *card_ptr = idd->data[is->id];
+ int ii, phys_port;
+ struct pci_dev *pdev = idd->pdev;
+
+ DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
+ __FUNCTION__, pdev, (void *)card_ptr));
+
+ if (!card_ptr)
+ return -ENODEV;
+
+ /* once around for each logical port on this card */
+ for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
+ phys_port = GET_PHYSICAL_PORT(ii);
+ the_port = &card_ptr->ic_port[phys_port].
+ icp_uart_port[GET_LOGICAL_PORT(ii)];
+ port = card_ptr->ic_port[phys_port].icp_port;
+ port->ip_port = the_port;
+
+ DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
+ __FUNCTION__, (void *)the_port, (void *)port,
+ phys_port, ii));
+
+ /* membase, iobase and mapbase just need to be non-0 */
+ the_port->membase = (unsigned char __iomem *)1;
+ the_port->iobase = (pdev->bus->number << 16) | ii;
+ the_port->line = (Num_of_ioc3_cards << 2) | ii;
+ the_port->mapbase = 1;
+ the_port->type = PORT_16550A;
+ the_port->fifosize = FIFO_SIZE;
+ the_port->ops = &ioc3_ops;
+ the_port->irq = idd->irq_io;
+ the_port->dev = &pdev->dev;
+
+ if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
+ printk(KERN_WARNING
+ "%s: unable to add port %d bus %d\n",
+ __FUNCTION__, the_port->line, pdev->bus->number);
+ } else {
+ DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
+ the_port->line, the_port->irq, pdev->bus->number));
+ }
+
+ /* all ports are rs232 for now */
+ if (IS_PHYSICAL_PORT(ii))
+ ioc3_set_proto(port, PROTO_RS232);
+ }
+ return 0;
+}
+
+/**
+ * ioc3uart_remove - register detach function
+ * @is: submodule struct for this submodule
+ * @idd: ioc3 driver data for this submodule
+ */
+
+static int ioc3uart_remove(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd)
+{
+ struct ioc3_card *card_ptr = idd->data[is->id];
+ struct uart_port *the_port;
+ struct ioc3_port *port;
+ int ii;
+
+ if (card_ptr) {
+ for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
+ the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
+ icp_uart_port[GET_LOGICAL_PORT(ii)];
+ if (the_port)
+ uart_remove_one_port(&ioc3_uart, the_port);
+ port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port;
+ if (port && IS_PHYSICAL_PORT(ii)
+ && (GET_PHYSICAL_PORT(ii) == 0)) {
+ pci_free_consistent(port->ip_idd->pdev,
+ TOTAL_RING_BUF_SIZE,
+ (void *)port->ip_cpu_ringbuf,
+ port->ip_dma_ringbuf);
+ kfree(port);
+ card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
+ icp_port = NULL;
+ }
+ }
+ kfree(card_ptr);
+ idd->data[is->id] = NULL;
+ }
+ return 0;
+}
+
+/**
+ * ioc3uart_probe - card probe function called from shim driver
+ * @is: submodule struct for this submodule
+ * @idd: ioc3 driver data for this card
+ */
+
+static int __devinit
+ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+{
+ struct pci_dev *pdev = idd->pdev;
+ struct ioc3_card *card_ptr;
+ int ret = 0;
+ struct ioc3_port *port;
+ struct ioc3_port *ports[PORTS_PER_CARD];
+ int phys_port;
+
+ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
+
+ card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL);
+ if (!card_ptr) {
+ printk(KERN_WARNING "ioc3_attach_one"
+ ": unable to get memory for the IOC3\n");
+ return -ENOMEM;
+ }
+ memset(card_ptr, 0, sizeof(struct ioc3_card));
+ idd->data[is->id] = card_ptr;
+ Submodule_slot = is->id;
+
+ writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) |
+ ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) |
+ (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr);
+
+ pci_write_config_dword(pdev, PCI_LAT, 0xff00);
+
+ /* Enable serial port mode select generic PIO pins as outputs */
+ ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL);
+
+ /* Create port structures for each port */
+ for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
+ port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL);
+ if (!port) {
+ printk(KERN_WARNING
+ "IOC3 serial memory not available for port\n");
+ goto out4;
+ }
+ memset(port, 0, sizeof(struct ioc3_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.
+ */
+ ports[phys_port] = port;
+
+ /* init to something useful */
+ card_ptr->ic_port[phys_port].icp_port = port;
+ port->ip_is = is;
+ port->ip_idd = idd;
+ port->ip_baud = 9600;
+ port->ip_card = card_ptr;
+ port->ip_hooks = &hooks_array[phys_port];
+
+ /* Setup each port */
+ if (phys_port == 0) {
+ port->ip_serial_regs = &idd->vma->port_a;
+ port->ip_uart_regs = &idd->vma->sregs.uarta;
+
+ DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
+ "ip_uart_regs 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+ /* setup ring buffers */
+ port->ip_cpu_ringbuf = pci_alloc_consistent(pdev,
+ TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf);
+
+ BUG_ON(!((((int64_t) port->ip_dma_ringbuf) &
+ (TOTAL_RING_BUF_SIZE - 1)) == 0));
+ port->ip_inring = RING(port, RX_A);
+ port->ip_outring = RING(port, TX_A);
+ DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
+ "ip_outring 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+ }
+ else {
+ port->ip_serial_regs = &idd->vma->port_b;
+ port->ip_uart_regs = &idd->vma->sregs.uartb;
+
+ DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
+ "ip_uart_regs 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+ /* share the ring buffers */
+ port->ip_dma_ringbuf =
+ ports[phys_port - 1]->ip_dma_ringbuf;
+ port->ip_cpu_ringbuf =
+ ports[phys_port - 1]->ip_cpu_ringbuf;
+ port->ip_inring = RING(port, RX_B);
+ port->ip_outring = RING(port, TX_B);
+ DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
+ "ip_outring 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+ }
+
+ DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
+ __FUNCTION__,
+ phys_port, (void *)port, (void *)card_ptr));
+ DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+ /* Initialize the hardware for IOC3 */
+ port_init(port);
+
+ DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
+ "outring 0x%p\n",
+ __FUNCTION__,
+ phys_port, (void *)port,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+
+ }
+
+ /* register port with the serial core */
+
+ if ((ret = ioc3_serial_core_attach(is, idd)))
+ goto out4;
+
+ Num_of_ioc3_cards++;
+
+ return ret;
+
+ /* error exits that give back resources */
+out4:
+ kfree(card_ptr);
+ return ret;
+}
+
+static struct ioc3_submodule ioc3uart_submodule = {
+ .name = "IOC3uart",
+ .probe = ioc3uart_probe,
+ .remove = ioc3uart_remove,
+ /* call .intr for both ports initially */
+ .irq_mask = SIO_IR_SA | SIO_IR_SB,
+ .intr = ioc3uart_intr,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * ioc3_detect - module init called,
+ */
+static int __devinit ioc3uart_init(void)
+{
+ int ret;
+
+ /* register with serial core */
+ if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register IOC3 uart serial driver\n",
+ __FUNCTION__);
+ return ret;
+ }
+ ret = ioc3_register_submodule(&ioc3uart_submodule);
+ if (ret)
+ uart_unregister_driver(&ioc3_uart);
+ return ret;
+}
+
+static void __devexit ioc3uart_exit(void)
+{
+ ioc3_unregister_submodule(&ioc3uart_submodule);
+ uart_unregister_driver(&ioc3_uart);
+}
+
+module_init(ioc3uart_init);
+module_exit(ioc3uart_exit);
+
+MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
+MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 771676abee60..1d85533d46d2 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -2327,19 +2327,13 @@ static void receive_chars(struct uart_port *the_port)
spin_lock_irqsave(&the_port->lock, pflags);
tty = info->tty;
- if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count)
- request_count = TTY_FLIPBUF_SIZE - tty->flip.count;
+ request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2);
if (request_count > 0) {
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;
- tty->flip.flag_buf_ptr += read_count;
- tty->flip.count += read_count;
+ tty_insert_flip_string(tty, ch, read_count);
icount->rx += read_count;
}
}
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index ef132349f310..66f117d15065 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -259,13 +259,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */
while (1) {
- unsigned char ch, r1;
-
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return; /* XXX Ignores SysRq when we need it most. Fix. */
- }
+ unsigned char ch, r1, flag;
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -303,8 +297,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
}
/* A real serial line, record the character and status. */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
if (r1 & BRK_ABRT) {
@@ -321,28 +314,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
up->port.icount.overrun++;
r1 &= up->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto next_char;
if (up->port.ignore_status_mask == 0xff ||
- (r1 & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ (r1 & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
next_char:
ch = readb(&channel->control);
ZSDELAY();
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b0ecc7537ce5..b48066a64a7d 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -331,17 +331,12 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status,
{
struct tty_struct *tty = up->port.info->tty;
unsigned char ch;
+ unsigned char flag;
int max_count = 256;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return; // if TTY_DONT_FLIP is set
- }
ch = sio_in(up, SIORXB);
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -380,30 +375,24 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status,
if (*status & UART_LSR_BI) {
DEBUG_INTR("handling break....");
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (*status & UART_LSR_OE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
*status = serial_in(up, UART_LSR);
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 47f7404cb045..d957a3a9edf1 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -313,7 +313,7 @@ static inline void receive_chars(struct mcf_serial *info)
{
volatile unsigned char *uartp;
struct tty_struct *tty = info->tty;
- unsigned char status, ch;
+ unsigned char status, ch, flag;
if (!tty)
return;
@@ -321,10 +321,6 @@ static inline void receive_chars(struct mcf_serial *info)
uartp = info->addr;
while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
ch = uartp[MCFUART_URB];
info->stats.rx++;
@@ -335,29 +331,24 @@ static inline void receive_chars(struct mcf_serial *info)
}
#endif
- tty->flip.count++;
+ flag = TTY_NORMAL;
if (status & MCFUART_USR_RXERR) {
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
if (status & MCFUART_USR_RXBREAK) {
info->stats.rxbreak++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (status & MCFUART_USR_RXPARITY) {
info->stats.rxparity++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (status & MCFUART_USR_RXOVERRUN) {
info->stats.rxoverrun++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
} else if (status & MCFUART_USR_RXFRAMING) {
info->stats.rxframing++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- } else {
- /* This should never happen... */
- *tty->flip.flag_buf_ptr++ = 0;
+ flag = TTY_FRAME;
}
- } else {
- *tty->flip.flag_buf_ptr++ = 0;
}
- *tty->flip.char_buf_ptr++ = ch;
+ tty_insert_flip_char(tty, ch, flag);
}
schedule_work(&tty->flip.work);
@@ -1525,7 +1516,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_ICR0 + MCFINT_UART0 + info->line);
- *icrp = 0x33; /* UART0 with level 6, priority 3 */
+ *icrp = 0x30 + info->line; /* level 6, line based priority */
imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_IMRL);
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 1288d6203e94..61dd17d7bace 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -405,17 +405,13 @@ static inline int
mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
{
struct tty_struct *tty = port->info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
unsigned short status;
/* While we can read, do so ! */
while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
MPC52xx_PSC_SR_RXRDY) {
- /* If we are full, just stop reading */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
/* Get the char */
ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
@@ -428,45 +424,35 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
#endif
/* Store it */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = 0;
+
+ flag = TTY_NORMAL;
port->icount.rx++;
if ( status & (MPC52xx_PSC_SR_PE |
MPC52xx_PSC_SR_FE |
- MPC52xx_PSC_SR_RB |
- MPC52xx_PSC_SR_OE) ) {
+ MPC52xx_PSC_SR_RB) ) {
if (status & MPC52xx_PSC_SR_RB) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
uart_handle_break(port);
} else if (status & MPC52xx_PSC_SR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & MPC52xx_PSC_SR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (status & MPC52xx_PSC_SR_OE) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
+ flag = TTY_FRAME;
/* Clear error condition */
out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);
}
-
- tty->flip.char_buf_ptr++;
- tty->flip.flag_buf_ptr++;
- tty->flip.count++;
-
+ tty_insert_flip_char(tty, ch, flag);
+ if (status & MPC52xx_PSC_SR_OE) {
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
}
tty_flip_buffer_push(tty);
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 8f83e4007ecd..0ca83ac31d07 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -769,12 +769,12 @@ mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs)
bytes_in = be16_to_cpu(rxre->bytecnt);
/* Following use of tty struct directly is deprecated */
- if (unlikely((tty->flip.count + bytes_in) >= TTY_FLIPBUF_SIZE)){
+ if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) {
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
- * If this failed then we will throw awa the bytes
- * but mst do so to clear interrupts.
+ * If this failed then we will throw away the bytes
+ * but must do so to clear interrupts.
*/
}
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 7633132a10aa..4e49168c3176 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -223,11 +223,6 @@ static void mux_read(struct uart_port *port)
if (MUX_EOFIFO(data))
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = data & 0xffu;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
port->icount.rx++;
if (MUX_BREAK(data)) {
@@ -239,9 +234,7 @@ static void mux_read(struct uart_port *port)
if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
continue;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
}
if (start_count != port->icount.rx) {
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 5ddd8ab1f108..4e03a87f3fb4 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -60,6 +60,7 @@
#include <linux/pmu.h>
#include <linux/bitops.h>
#include <linux/sysrq.h>
+#include <linux/mutex.h>
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -68,7 +69,6 @@
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
#include <asm/macio.h>
-#include <asm/semaphore.h>
#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -96,7 +96,7 @@ MODULE_LICENSE("GPL");
*/
static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS];
static int pmz_ports_count;
-static DECLARE_MUTEX(pmz_irq_sem);
+static DEFINE_MUTEX(pmz_irq_mutex);
static struct uart_driver pmz_uart_reg = {
.owner = THIS_MODULE,
@@ -210,10 +210,9 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
struct pt_regs *regs)
{
struct tty_struct *tty = NULL;
- unsigned char ch, r1, drop, error;
+ unsigned char ch, r1, drop, error, flag;
int loops = 0;
- retry:
/* The interrupt can be enabled when the port isn't open, typically
* that happens when using one port is open and the other closed (stale
* interrupt) or when one port is used as a console.
@@ -246,20 +245,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
error = 0;
drop = 0;
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- /* Have to drop the lock here */
- pmz_debug("pmz: flip overflow\n");
- spin_unlock(&uap->port.lock);
- tty->flip.work.func((void *)tty);
- spin_lock(&uap->port.lock);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- drop = 1;
- if (ZS_IS_ASLEEP(uap))
- return NULL;
- if (!ZS_IS_OPEN(uap))
- goto retry;
- }
-
r1 = read_zsreg(uap, R1);
ch = read_zsdata(uap);
@@ -295,8 +280,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
if (drop)
goto next_char;
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
uap->port.icount.rx++;
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
@@ -316,26 +300,19 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
uap->port.icount.overrun++;
r1 &= uap->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uap->port.ignore_status_mask == 0xff ||
(r1 & uap->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
}
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
next_char:
/* We can get stuck in an infinite loop getting char 0 when the
* line is in a wrong HW state, we break that here.
@@ -945,7 +922,7 @@ static int pmz_startup(struct uart_port *port)
if (uap->node == NULL)
return -ENODEV;
- down(&pmz_irq_sem);
+ mutex_lock(&pmz_irq_mutex);
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
@@ -963,11 +940,11 @@ static int pmz_startup(struct uart_port *port)
dev_err(&uap->dev->ofdev.dev,
"Unable to register zs interrupt handler.\n");
pmz_set_scc_power(uap, 0);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
return -ENXIO;
}
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
/* Right now, we deal with delay by blocking here, I'll be
* smarter later on
@@ -1004,7 +981,7 @@ static void pmz_shutdown(struct uart_port *port)
if (uap->node == NULL)
return;
- down(&pmz_irq_sem);
+ mutex_lock(&pmz_irq_mutex);
/* Release interrupt handler */
free_irq(uap->port.irq, uap);
@@ -1025,7 +1002,7 @@ static void pmz_shutdown(struct uart_port *port)
if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) {
spin_unlock_irqrestore(&port->lock, flags);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
return;
}
@@ -1042,7 +1019,7 @@ static void pmz_shutdown(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
pmz_debug("pmz: shutdown() done.\n");
}
@@ -1431,11 +1408,14 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
char name[1];
} *slots;
int len;
+ struct resource r_ports, r_rxdma, r_txdma;
/*
* Request & map chip registers
*/
- uap->port.mapbase = np->addrs[0].address;
+ if (of_address_to_resource(np, 0, &r_ports))
+ return -ENODEV;
+ uap->port.mapbase = r_ports.start;
uap->port.membase = ioremap(uap->port.mapbase, 0x1000);
uap->control_reg = uap->port.membase;
@@ -1445,16 +1425,20 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
* Request & map DBDMA registers
*/
#ifdef HAS_DBDMA
- if (np->n_addrs >= 3 && np->n_intrs >= 3)
+ if (of_address_to_resource(np, 1, &r_txdma) == 0 &&
+ of_address_to_resource(np, 2, &r_rxdma) == 0)
uap->flags |= PMACZILOG_FLAG_HAS_DMA;
+#else
+ memset(&r_txdma, 0, sizeof(struct resource));
+ memset(&r_rxdma, 0, sizeof(struct resource));
#endif
if (ZS_HAS_DMA(uap)) {
- uap->tx_dma_regs = ioremap(np->addrs[np->n_addrs - 2].address, 0x1000);
+ uap->tx_dma_regs = ioremap(r_txdma.start, 0x100);
if (uap->tx_dma_regs == NULL) {
uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
goto no_dma;
}
- uap->rx_dma_regs = ioremap(np->addrs[np->n_addrs - 1].address, 0x1000);
+ uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100);
if (uap->rx_dma_regs == NULL) {
iounmap(uap->tx_dma_regs);
uap->tx_dma_regs = NULL;
@@ -1607,8 +1591,8 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
state = pmz_uart_reg.state + uap->port.line;
- down(&pmz_irq_sem);
- down(&state->sem);
+ mutex_lock(&pmz_irq_mutex);
+ mutex_lock(&state->mutex);
spin_lock_irqsave(&uap->port.lock, flags);
@@ -1639,8 +1623,8 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
/* Shut the chip down */
pmz_set_scc_power(uap, 0);
- up(&state->sem);
- up(&pmz_irq_sem);
+ mutex_unlock(&state->mutex);
+ mutex_unlock(&pmz_irq_mutex);
pmz_debug("suspend, switching complete\n");
@@ -1667,8 +1651,8 @@ static int pmz_resume(struct macio_dev *mdev)
state = pmz_uart_reg.state + uap->port.line;
- down(&pmz_irq_sem);
- down(&state->sem);
+ mutex_lock(&pmz_irq_mutex);
+ mutex_lock(&state->mutex);
spin_lock_irqsave(&uap->port.lock, flags);
if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) {
@@ -1700,8 +1684,8 @@ static int pmz_resume(struct macio_dev *mdev)
}
bail:
- up(&state->sem);
- up(&pmz_irq_sem);
+ mutex_unlock(&state->mutex);
+ mutex_unlock(&pmz_irq_mutex);
/* Right now, we deal with delay by blocking here, I'll be
* smarter later on
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index cc998b99a19f..10535f00301f 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -107,14 +107,6 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
int max_count = 256;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
ch = serial_in(up, UART_RX);
flag = TTY_NORMAL;
up->port.icount.rx++;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 47681c4654e4..eb4883efb7c6 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -72,12 +72,12 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
@@ -323,16 +323,6 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
-
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
uerstat = rd_regl(port, S3C2410_UERSTAT);
ch = rd_regb(port, S3C2410_URXH);
@@ -782,11 +772,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
- clk_unuse(ourport->baudclk);
ourport->baudclk = NULL;
}
- clk_use(clk);
clk_enable(clk);
ourport->clksrc = clksrc;
@@ -1077,9 +1065,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->clk = clk_get(&platdev->dev, "uart");
- if (ourport->clk != NULL && !IS_ERR(ourport->clk))
- clk_use(ourport->clk);
-
dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
port->mapbase, port->membase, port->irq, port->uartclk);
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 25a086458ab9..1bd93168f504 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -201,8 +201,6 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
while (status & UTSR1_TO_SM(UTSR1_RNE)) {
ch = UART_GET_CHAR(sport);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
sport->port.icount.rx++;
flg = TTY_NORMAL;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index c17d680e3f04..943770470b9d 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -33,6 +33,7 @@
#include <linux/device.h>
#include <linux/serial.h> /* for serial_state and serial_icounter_struct */
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -47,7 +48,7 @@
/*
* This is used to lock changes in serial line configuration.
*/
-static DECLARE_MUTEX(port_sem);
+static DEFINE_MUTEX(port_mutex);
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
@@ -637,7 +638,7 @@ static int uart_set_info(struct uart_state *state,
* module insertion/removal doesn't change anything
* under us.
*/
- down(&state->sem);
+ mutex_lock(&state->mutex);
change_irq = new_serial.irq != port->irq;
@@ -796,7 +797,7 @@ static int uart_set_info(struct uart_state *state,
} else
retval = uart_startup(state, 1);
exit:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return retval;
}
@@ -833,7 +834,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
struct uart_port *port = state->port;
int result = -EIO;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
result = port->mctrl;
@@ -842,7 +843,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
result |= port->ops->get_mctrl(port);
spin_unlock_irq(&port->lock);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return result;
}
@@ -855,13 +856,13 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
struct uart_port *port = state->port;
int ret = -EIO;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
uart_update_mctrl(port, set, clear);
ret = 0;
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return ret;
}
@@ -872,12 +873,12 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
BUG_ON(!kernel_locked());
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (port->type != PORT_UNKNOWN)
port->ops->break_ctl(port, break_state);
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
static int uart_do_autoconfig(struct uart_state *state)
@@ -893,7 +894,7 @@ static int uart_do_autoconfig(struct uart_state *state)
* changing, and hence any extra opens of the port while
* we're auto-configuring.
*/
- if (down_interruptible(&state->sem))
+ if (mutex_lock_interruptible(&state->mutex))
return -ERESTARTSYS;
ret = -EBUSY;
@@ -919,7 +920,7 @@ static int uart_do_autoconfig(struct uart_state *state)
ret = uart_startup(state, 1);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return ret;
}
@@ -1073,7 +1074,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
if (ret != -ENOIOCTLCMD)
goto out;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (tty_hung_up_p(filp)) {
ret = -EIO;
@@ -1097,7 +1098,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
}
}
out_up:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
out:
return ret;
}
@@ -1185,7 +1186,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
DPRINTK("uart_close(%d) called\n", port->line);
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (tty_hung_up_p(filp))
goto done;
@@ -1259,7 +1260,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&state->info->open_wait);
done:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -1333,7 +1334,7 @@ static void uart_hangup(struct tty_struct *tty)
BUG_ON(!kernel_locked());
DPRINTK("uart_hangup(%d)\n", state->port->line);
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
uart_flush_buffer(tty);
uart_shutdown(state);
@@ -1343,7 +1344,7 @@ static void uart_hangup(struct tty_struct *tty)
wake_up_interruptible(&state->info->open_wait);
wake_up_interruptible(&state->info->delta_msr_wait);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
/*
@@ -1440,14 +1441,15 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)
* modem is ready for us.
*/
spin_lock_irq(&port->lock);
+ port->ops->enable_ms(port);
mctrl = port->ops->get_mctrl(port);
spin_unlock_irq(&port->lock);
if (mctrl & TIOCM_CAR)
break;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
schedule();
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (signal_pending(current))
break;
@@ -1471,9 +1473,9 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
{
struct uart_state *state;
- down(&port_sem);
+ mutex_lock(&port_mutex);
state = drv->state + line;
- if (down_interruptible(&state->sem)) {
+ if (mutex_lock_interruptible(&state->mutex)) {
state = ERR_PTR(-ERESTARTSYS);
goto out;
}
@@ -1481,7 +1483,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
state->count++;
if (!state->port) {
state->count--;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
state = ERR_PTR(-ENXIO);
goto out;
}
@@ -1502,13 +1504,13 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
(unsigned long)state);
} else {
state->count--;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
state = ERR_PTR(-ENOMEM);
}
}
out:
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return state;
}
@@ -1569,7 +1571,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
if (tty_hung_up_p(filp)) {
retval = -EAGAIN;
state->count--;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
goto fail;
}
@@ -1589,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
*/
if (retval == 0)
retval = uart_block_til_ready(filp, state);
- up(&state->sem);
+ mutex_unlock(&state->mutex);
/*
* If this is the first open to succeed, adjust things to suit.
@@ -1865,7 +1867,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (state->info && state->info->flags & UIF_INITIALIZED) {
struct uart_ops *ops = port->ops;
@@ -1894,7 +1896,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
uart_change_pm(state, 3);
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return 0;
}
@@ -1903,7 +1905,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
- down(&state->sem);
+ mutex_lock(&state->mutex);
uart_change_pm(state, 0);
@@ -1952,7 +1954,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
}
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return 0;
}
@@ -2047,7 +2049,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
if (info && info->tty)
tty_vhangup(info->tty);
- down(&state->sem);
+ mutex_lock(&state->mutex);
state->info = NULL;
@@ -2070,7 +2072,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
kfree(info);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
static struct tty_operations uart_ops = {
@@ -2159,7 +2161,7 @@ int uart_register_driver(struct uart_driver *drv)
state->close_delay = 500; /* .5 seconds */
state->closing_wait = 30000; /* 30 seconds */
- init_MUTEX(&state->sem);
+ mutex_init(&state->mutex);
}
retval = tty_register_driver(normal);
@@ -2218,7 +2220,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
state = drv->state + port->line;
- down(&port_sem);
+ mutex_lock(&port_mutex);
if (state->port) {
ret = -EINVAL;
goto out;
@@ -2254,7 +2256,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
register_console(port->cons);
out:
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return ret;
}
@@ -2278,7 +2280,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
printk(KERN_ALERT "Removing wrong port: %p != %p\n",
state->port, port);
- down(&port_sem);
+ mutex_lock(&port_mutex);
/*
* Remove the devices from devfs
@@ -2287,7 +2289,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
uart_unconfigure_port(drv, state);
state->port = NULL;
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return 0;
}
@@ -2307,7 +2309,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
return (port1->iobase == port2->iobase) &&
(port1->hub6 == port2->hub6);
case UPIO_MEM:
- return (port1->membase == port2->membase);
+ return (port1->mapbase == port2->mapbase);
}
return 0;
}
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 96969cb960a9..c30333694fde 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -785,6 +785,8 @@ static struct pcmcia_device_id serial_ids[] = {
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_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
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 d01dbe5da3b9..d4a1f0e798c1 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -148,15 +148,6 @@ lh7a40xuart_rx_chars (struct uart_port* port)
unsigned int data, flag;/* Received data and status */
while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
data = UR (port, UART_R_DATA);
flag = TTY_NORMAL;
++port->icount.rx;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index f10c86d60b64..ee98a867bc6d 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -52,6 +52,7 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -303,17 +304,6 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
char flag;
do {
- /* 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) {
- 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 */
- }
ch = sio_in(up, TXX9_SIRFIFO);
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1029,7 +1019,7 @@ 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);
+static DEFINE_MUTEX(serial_txx9_mutex);
/**
* serial_txx9_register_port - register a serial port
@@ -1048,7 +1038,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
struct uart_txx9_port *uart;
int ret = -ENOSPC;
- down(&serial_txx9_sem);
+ mutex_lock(&serial_txx9_mutex);
for (i = 0; i < UART_NR; i++) {
uart = &serial_txx9_ports[i];
if (uart->port.type == PORT_UNKNOWN)
@@ -1069,7 +1059,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
if (ret == 0)
ret = uart->port.line;
}
- up(&serial_txx9_sem);
+ mutex_unlock(&serial_txx9_mutex);
return ret;
}
@@ -1084,7 +1074,7 @@ static void __devexit serial_txx9_unregister_port(int line)
{
struct uart_txx9_port *uart = &serial_txx9_ports[line];
- down(&serial_txx9_sem);
+ mutex_lock(&serial_txx9_mutex);
uart_remove_one_port(&serial_txx9_reg, &uart->port);
uart->port.flags = 0;
uart->port.type = PORT_UNKNOWN;
@@ -1093,7 +1083,7 @@ static void __devexit serial_txx9_unregister_port(int line)
uart->port.membase = 0;
uart->port.dev = NULL;
uart_add_one_port(&serial_txx9_reg, &uart->port);
- up(&serial_txx9_sem);
+ mutex_unlock(&serial_txx9_mutex);
}
/*
@@ -1195,7 +1185,7 @@ static int __init serial_txx9_init(void)
serial_txx9_register_ports(&serial_txx9_reg);
#ifdef ENABLE_SERIAL_TXX9_PCI
- ret = pci_module_init(&serial_txx9_pci_driver);
+ ret = pci_register_driver(&serial_txx9_pci_driver);
#endif
}
return ret;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 430754ebac8a..a9e070759628 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -482,6 +482,7 @@ static inline void sci_receive_chars(struct uart_port *port,
struct tty_struct *tty = port->info->tty;
int i, count, copied = 0;
unsigned short status;
+ unsigned char flag;
status = sci_in(port, SCxSR);
if (!(status & SCxSR_RDxF(port)))
@@ -499,8 +500,7 @@ static inline void sci_receive_chars(struct uart_port *port,
#endif
/* Don't copy more bytes than there is room for in the buffer */
- if (tty->flip.count + count > TTY_FLIPBUF_SIZE)
- count = TTY_FLIPBUF_SIZE - tty->flip.count;
+ count = tty_buffer_request_room(tty, count);
/* If for any reason we can't copy more data, we're done! */
if (count == 0)
@@ -512,8 +512,7 @@ static inline void sci_receive_chars(struct uart_port *port,
|| uart_handle_sysrq_char(port, c, regs)) {
count = 0;
} else {
- tty->flip.char_buf_ptr[0] = c;
- tty->flip.flag_buf_ptr[0] = TTY_NORMAL;
+ tty_insert_flip_char(tty, c, TTY_NORMAL);
}
} else {
for (i=0; i<count; i++) {
@@ -542,26 +541,21 @@ static inline void sci_receive_chars(struct uart_port *port,
}
/* Store data and status */
- tty->flip.char_buf_ptr[i] = c;
if (status&SCxSR_FER(port)) {
- tty->flip.flag_buf_ptr[i] = TTY_FRAME;
+ flag = TTY_FRAME;
pr_debug("sci: frame error\n");
} else if (status&SCxSR_PER(port)) {
- tty->flip.flag_buf_ptr[i] = TTY_PARITY;
+ flag = TTY_PARITY;
pr_debug("sci: parity error\n");
- } else {
- tty->flip.flag_buf_ptr[i] = TTY_NORMAL;
- }
+ } else
+ flag = TTY_NORMAL;
+ tty_insert_flip_char(tty, c, flag);
}
}
sci_in(port, SCxSR); /* dummy read */
sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
- /* Update the kernel buffer end */
- tty->flip.count += count;
- tty->flip.char_buf_ptr += count;
- tty->flip.flag_buf_ptr += count;
copied += count;
port->icount.rx += count;
}
@@ -608,48 +602,45 @@ static inline int sci_handle_errors(struct uart_port *port)
unsigned short status = sci_in(port, SCxSR);
struct tty_struct *tty = port->info->tty;
- if (status&SCxSR_ORER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if (status&SCxSR_ORER(port)) {
/* overrun error */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ if(tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+ copied++;
pr_debug("sci: overrun error\n");
}
- if (status&SCxSR_FER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if (status&SCxSR_FER(port)) {
if (sci_rxd_in(port) == 0) {
/* Notify of BREAK */
struct sci_port * sci_port = (struct sci_port *)port;
- if(!sci_port->break_flag) {
- sci_port->break_flag = 1;
- sci_schedule_break_timer((struct sci_port *)port);
+ if(!sci_port->break_flag) {
+ sci_port->break_flag = 1;
+ sci_schedule_break_timer((struct sci_port *)port);
/* Do sysrq handling. */
- if(uart_handle_break(port)) {
+ if(uart_handle_break(port))
return 0;
- }
pr_debug("sci: BREAK detected\n");
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+ copied++;
}
}
else {
/* frame error */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ if(tty_insert_flip_char(tty, 0, TTY_FRAME))
+ copied++;
pr_debug("sci: frame error\n");
}
}
- if (status&SCxSR_PER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if (status&SCxSR_PER(port)) {
+ if(tty_insert_flip_char(tty, 0, TTY_PARITY))
+ copied++;
/* parity error */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
pr_debug("sci: parity error\n");
}
- if (copied) {
- tty->flip.count += copied;
+ if (copied)
tty_flip_buffer_push(tty);
- }
return copied;
}
@@ -661,15 +652,14 @@ static inline int sci_handle_breaks(struct uart_port *port)
struct tty_struct *tty = port->info->tty;
struct sci_port *s = &sci_ports[port->line];
- if (!s->break_flag && status & SCxSR_BRK(port) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if (!s->break_flag && status & SCxSR_BRK(port))
#if defined(CONFIG_CPU_SH3)
/* Debounce break */
s->break_flag = 1;
#endif
/* Notify of BREAK */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+ copied++;
pr_debug("sci: BREAK detected\n");
}
@@ -677,19 +667,15 @@ static inline int sci_handle_breaks(struct uart_port *port)
/* XXX: Handle SCIF overrun error */
if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
sci_out(port, SCLSR, 0);
- if(tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
copied++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
pr_debug("sci: overrun error\n");
}
}
#endif
- if (copied) {
- tty->flip.count += copied;
+ if (copied)
tty_flip_buffer_push(tty);
- }
-
return copied;
}
@@ -732,12 +718,9 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs)
struct tty_struct *tty = port->info->tty;
sci_out(port, SCLSR, 0);
- if(tty->flip.count<TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
- tty->flip.count++;
- tty_flip_buffer_push(tty);
- pr_debug("scif: overrun error\n");
- }
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_flip_buffer_push(tty);
+ pr_debug("scif: overrun error\n");
}
#endif
sci_rx_interrupt(irq, ptr, regs);
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 313f9df24a2d..43e67d6c29d4 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -6,7 +6,7 @@
* driver for that.
*
*
- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc. 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
@@ -519,11 +519,7 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs,
/* record the character to pass up to the tty layer */
if (tty) {
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- if (tty->flip.count == TTY_FLIPBUF_SIZE)
+ if(tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
break;
}
port->sc_port.icount.rx++;
@@ -833,8 +829,8 @@ static int __init sn_sal_module_init(void)
misc.name = DEVICE_NAME_DYNAMIC;
retval = misc_register(&misc);
if (retval != 0) {
- printk
- ("Failed to register console device using misc_register.\n");
+ printk(KERN_WARNING "Failed to register console "
+ "device using misc_register.\n");
return -ENODEV;
}
sal_console_uart.major = MISC_MAJOR;
@@ -946,88 +942,75 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
{
unsigned long flags = 0;
struct sn_cons_port *port = &sal_console_port;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static int stole_lock = 0;
-#endif
BUG_ON(!port->sc_is_asynch);
/* We can't look at the xmit buffer if we're not registered with serial core
* yet. So only do the fancy recovery after registering
*/
- if (port->sc_port.info) {
-
- /* somebody really wants this output, might be an
- * oops, kdb, panic, etc. make sure they get it. */
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
- if (spin_is_locked(&port->sc_port.lock)) {
- int lhead = port->sc_port.info->xmit.head;
- int ltail = port->sc_port.info->xmit.tail;
- int counter, got_lock = 0;
+ if (!port->sc_port.info) {
+ /* Not yet registered with serial core - simple case */
+ puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+ return;
+ }
- /*
- * We attempt to determine if someone has died with the
- * lock. We wait ~20 secs after the head and tail ptrs
- * stop moving and assume the lock holder is not functional
- * and plow ahead. If the lock is freed within the time out
- * period we re-get the lock and go ahead normally. We also
- * remember if we have plowed ahead so that we don't have
- * to wait out the time out period again - the asumption
- * is that we will time out again.
- */
+ /* somebody really wants this output, might be an
+ * oops, kdb, panic, etc. make sure they get it. */
+ if (spin_is_locked(&port->sc_port.lock)) {
+ int lhead = port->sc_port.info->xmit.head;
+ int ltail = port->sc_port.info->xmit.tail;
+ int counter, got_lock = 0;
+
+ /*
+ * We attempt to determine if someone has died with the
+ * lock. We wait ~20 secs after the head and tail ptrs
+ * stop moving and assume the lock holder is not functional
+ * and plow ahead. If the lock is freed within the time out
+ * period we re-get the lock and go ahead normally. We also
+ * remember if we have plowed ahead so that we don't have
+ * to wait out the time out period again - the asumption
+ * is that we will time out again.
+ */
- for (counter = 0; counter < 150; mdelay(125), counter++) {
- if (!spin_is_locked(&port->sc_port.lock)
- || stole_lock) {
- if (!stole_lock) {
- spin_lock_irqsave(&port->
- sc_port.lock,
- flags);
- got_lock = 1;
- }
- break;
- } else {
- /* still locked */
- if ((lhead !=
- port->sc_port.info->xmit.head)
- || (ltail !=
- port->sc_port.info->xmit.
- tail)) {
- lhead =
- port->sc_port.info->xmit.
- head;
- ltail =
- port->sc_port.info->xmit.
- tail;
- counter = 0;
- }
+ for (counter = 0; counter < 150; mdelay(125), counter++) {
+ if (!spin_is_locked(&port->sc_port.lock)
+ || stole_lock) {
+ if (!stole_lock) {
+ spin_lock_irqsave(&port->sc_port.lock,
+ flags);
+ got_lock = 1;
}
- }
- /* flush anything in the serial core xmit buffer, raw */
- sn_transmit_chars(port, 1);
- if (got_lock) {
- spin_unlock_irqrestore(&port->sc_port.lock,
- flags);
- stole_lock = 0;
+ break;
} else {
- /* fell thru */
- stole_lock = 1;
+ /* still locked */
+ if ((lhead != port->sc_port.info->xmit.head)
+ || (ltail !=
+ port->sc_port.info->xmit.tail)) {
+ lhead =
+ port->sc_port.info->xmit.head;
+ ltail =
+ port->sc_port.info->xmit.tail;
+ counter = 0;
+ }
}
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
- } else {
- stole_lock = 0;
-#endif
- spin_lock_irqsave(&port->sc_port.lock, flags);
- sn_transmit_chars(port, 1);
+ }
+ /* flush anything in the serial core xmit buffer, raw */
+ sn_transmit_chars(port, 1);
+ if (got_lock) {
spin_unlock_irqrestore(&port->sc_port.lock, flags);
-
- puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+ stole_lock = 0;
+ } else {
+ /* fell thru */
+ stole_lock = 1;
}
-#endif
- }
- else {
- /* Not yet registered with serial core - simple case */
+ puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+ } else {
+ stole_lock = 0;
+ spin_lock_irqsave(&port->sc_port.lock, flags);
+ sn_transmit_chars(port, 1);
+ spin_unlock_irqrestore(&port->sc_port.lock, flags);
+
puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
}
}
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index 5fc4a62173d9..fa4ae94243c2 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -34,6 +34,7 @@ sunserial_console_termios(struct console *con)
char *mode_prop = "ttyX-mode";
char *cd_prop = "ttyX-ignore-cd";
char *dtr_prop = "ttyX-rts-dtr-off";
+ char *ssp_console_modes_prop = "ssp-console-modes";
int baud, bits, stop, cflag;
char parity;
int carrier = 0;
@@ -43,14 +44,39 @@ sunserial_console_termios(struct console *con)
if (!serial_console)
return;
- if (serial_console == 1) {
+ switch (serial_console) {
+ case PROMDEV_OTTYA:
mode_prop[3] = 'a';
cd_prop[3] = 'a';
dtr_prop[3] = 'a';
- } else {
+ break;
+
+ case PROMDEV_OTTYB:
mode_prop[3] = 'b';
cd_prop[3] = 'b';
dtr_prop[3] = 'b';
+ break;
+
+ case PROMDEV_ORSC:
+
+ nd = prom_pathtoinode("rsc");
+ if (!nd) {
+ strcpy(mode, "115200,8,n,1,-");
+ goto no_options;
+ }
+
+ if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
+ strcpy(mode, "115200,8,n,1,-");
+ goto no_options;
+ }
+
+ memset(mode, 0, sizeof(mode));
+ prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
+ goto no_options;
+
+ default:
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
}
topnd = prom_getchild(prom_root_node);
@@ -110,6 +136,10 @@ no_options:
case 9600: cflag |= B9600; break;
case 19200: cflag |= B19200; break;
case 38400: cflag |= B38400; break;
+ case 57600: cflag |= B57600; break;
+ case 115200: cflag |= B115200; break;
+ case 230400: cflag |= B230400; break;
+ case 460800: cflag |= B460800; break;
default: baud = 9600; cflag |= B9600; break;
}
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index ba9381fd3f2d..8bcaebcc0ad7 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -159,21 +159,14 @@ receive_chars(struct uart_sunsab_port *up,
saw_console_brk = 1;
for (i = 0; i < count; i++) {
- unsigned char ch = buf[i];
+ unsigned char ch = buf[i], flag;
if (tty == NULL) {
uart_handle_sysrq_char(&up->port, ch, regs);
continue;
}
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return tty; // if TTY_DONT_FLIP is set
- }
-
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR |
@@ -209,34 +202,21 @@ receive_chars(struct uart_sunsab_port *up,
stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff);
if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (stat->sreg.isr0 & SAB82532_ISR0_PERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (stat->sreg.isr0 & SAB82532_ISR0_FERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
continue;
if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
- (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0){
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((stat->sreg.isr0 & SAB82532_ISR0_RFO) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
if (saw_console_brk)
@@ -917,9 +897,6 @@ static int sunsab_console_setup(struct console *con, char *options)
sunserial_console_termios(con);
- /* Firmware console speed is limited to 150-->38400 baud so
- * this hackish cflag thing is OK.
- */
switch (con->cflag & CBAUD) {
case B150: baud = 150; break;
case B300: baud = 300; break;
@@ -930,6 +907,10 @@ static int sunsab_console_setup(struct console *con, char *options)
default: case B9600: baud = 9600; break;
case B19200: baud = 19200; break;
case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
};
/*
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f0738533f39a..9a3665b34d97 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -323,19 +323,13 @@ static _INLINE_ struct tty_struct *
receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
int max_count = 256;
int saw_console_brk = 0;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return tty; // if TTY_DONT_FLIP is set
- }
ch = serial_inp(up, UART_RX);
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -377,31 +371,23 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs
}
if (*status & UART_LSR_BI) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if (*status & UART_LSR_OE)
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
ignore_char:
*status = serial_inp(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 7653d6cf05af..3c72484adea7 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -319,7 +319,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
struct pt_regs *regs)
{
struct tty_struct *tty;
- unsigned char ch, r1;
+ unsigned char ch, r1, flag;
tty = NULL;
if (up->port.info != NULL && /* Unopened serial console */
@@ -362,19 +362,8 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
continue;
}
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- /*
- * The 8250 bails out of the loop here,
- * but we need to read everything, or die.
- */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
- }
-
/* A real serial line, record the character and status. */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
if (r1 & BRK_ABRT) {
@@ -391,28 +380,21 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
up->port.icount.overrun++;
r1 &= up->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
continue;
if (up->port.ignore_status_mask == 0xff ||
(r1 & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
}
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
return tty;
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c
deleted file mode 100644
index 47b504ff38b2..000000000000
--- a/drivers/serial/uart00.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * linux/drivers/serial/uart00.c
- *
- * Driver for UART00 serial ports
- *
- * Based on drivers/char/serial_amba.c, by ARM Limited &
- * Deep Blue Solutions Ltd.
- * Copyright 2001 Altera Corporation
- *
- * Update for 2.6.4 by Dirk Behme <dirk.behme@de.bosch.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
- *
- * $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $
- *
- */
-#include <linux/config.h>
-
-#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/sizes.h>
-
-#include <asm/arch/excalibur.h>
-#define UART00_TYPE (volatile unsigned int*)
-#include <asm/arch/uart00.h>
-#include <asm/arch/int_ctrl00.h>
-
-#define UART_NR 2
-
-#define SERIAL_UART00_NAME "ttyUA"
-#define SERIAL_UART00_MAJOR 204
-#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
-#define SERIAL_UART00_NR UART_NR
-#define UART_PORT_SIZE 0x50
-
-#define UART00_ISR_PASS_LIMIT 256
-
-/*
- * Access macros for the UART00 UARTs
- */
-#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
-#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
-#define UART_GET_IES(p) inl(UART_IES((p)->membase))
-#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
-#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
-#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
-#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
-#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
-#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
-#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
-#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
-#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
-#define UART_GET_MC(p) inl(UART_MC((p)->membase))
-#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
-#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
-#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
-#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
-#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
-#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
-#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
-#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)
-{
- UART_PUT_IEC(port, UART_IEC_TIE_MSK);
-}
-
-static void uart00_stop_rx(struct uart_port *port)
-{
- UART_PUT_IEC(port, UART_IEC_RE_MSK);
-}
-
-static void uart00_enable_ms(struct uart_port *port)
-{
- UART_PUT_IES(port, UART_IES_ME_MSK);
-}
-
-static void
-uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
-{
- struct tty_struct *tty = port->info->tty;
- unsigned int status, ch, rds, flg, ignored = 0;
-
- status = UART_GET_RSR(port);
- while (UART_RX_DATA(status)) {
- /*
- * We need to read rds before reading the
- * character from the fifo
- */
- rds = UART_GET_RDS(port);
- ch = UART_GET_CHAR(port);
- port->icount.rx++;
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
-
- flg = TTY_NORMAL;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|
- UART_RDS_PE_MSK |UART_RDS_PE_MSK))
- goto handle_error;
- if (uart_handle_sysrq_char(port, ch, regs))
- goto ignore_char;
-
- error_return:
- tty_insert_flip_char(tty, ch, flg);
-
- ignore_char:
- status = UART_GET_RSR(port);
- }
- out:
- tty_flip_buffer_push(tty);
- return;
-
- handle_error:
- if (rds & UART_RDS_BI_MSK) {
- status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
- port->icount.brk++;
- if (uart_handle_break(port))
- goto ignore_char;
- } else if (rds & UART_RDS_PE_MSK)
- port->icount.parity++;
- else if (rds & UART_RDS_FE_MSK)
- port->icount.frame++;
- if (rds & UART_RDS_OE_MSK)
- port->icount.overrun++;
-
- if (rds & port->ignore_status_mask) {
- if (++ignored > 100)
- goto out;
- goto ignore_char;
- }
- rds &= port->read_status_mask;
-
- if (rds & UART_RDS_BI_MSK)
- flg = TTY_BREAK;
- else if (rds & UART_RDS_PE_MSK)
- flg = TTY_PARITY;
- else if (rds & UART_RDS_FE_MSK)
- flg = TTY_FRAME;
-
- if (rds & UART_RDS_OE_MSK) {
- /*
- * CHECK: does overrun affect the current character?
- * ASSUMPTION: it does not.
- */
- tty_insert_flip_char(tty, ch, flg);
- ch = 0;
- flg = TTY_OVERRUN;
- }
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
- goto error_return;
-}
-
-static void uart00_tx_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->info->xmit;
- int count;
-
- if (port->x_char) {
- while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
- barrier();
- UART_PUT_CHAR(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- uart00_stop_tx(port);
- return;
- }
-
- count = port->fifosize >> 1;
- do {
- while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
- barrier();
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- uart00_stop_tx(port);
-}
-
-static void uart00_start_tx(struct uart_port *port)
-{
- UART_PUT_IES(port, UART_IES_TIE_MSK);
- uart00_tx_chars(port);
-}
-
-static void uart00_modem_status(struct uart_port *port)
-{
- unsigned int status;
-
- status = UART_GET_MSR(port);
-
- if (!(status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
- UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK)))
- return;
-
- if (status & UART_MSR_DDCD_MSK)
- uart_handle_dcd_change(port, status & UART_MSR_DCD_MSK);
-
- if (status & UART_MSR_DDSR_MSK)
- port->icount.dsr++;
-
- if (status & UART_MSR_DCTS_MSK)
- uart_handle_cts_change(port, status & UART_MSR_CTS_MSK);
-
- wake_up_interruptible(&port->info->delta_msr_wait);
-}
-
-static irqreturn_t uart00_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct uart_port *port = dev_id;
- unsigned int status, pass_counter = 0;
-
- status = UART_GET_INT_STATUS(port);
- do {
- if (status & UART_ISR_RI_MSK)
- uart00_rx_chars(port, regs);
- if (status & UART_ISR_MI_MSK)
- uart00_modem_status(port);
- if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
- uart00_tx_chars(port);
- if (pass_counter++ > UART00_ISR_PASS_LIMIT)
- break;
-
- status = UART_GET_INT_STATUS(port);
- } while (status);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int uart00_tx_empty(struct uart_port *port)
-{
- return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int uart00_get_mctrl(struct uart_port *port)
-{
- unsigned int result = 0;
- unsigned int status;
-
- status = UART_GET_MSR(port);
- if (status & UART_MSR_DCD_MSK)
- result |= TIOCM_CAR;
- if (status & UART_MSR_DSR_MSK)
- result |= TIOCM_DSR;
- if (status & UART_MSR_CTS_MSK)
- result |= TIOCM_CTS;
- if (status & UART_MSR_RI_MSK)
- result |= TIOCM_RI;
-
- return result;
-}
-
-static void uart00_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-static void uart00_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned long flags;
- unsigned int mcr;
-
- spin_lock_irqsave(&port->lock, flags);
- mcr = UART_GET_MCR(port);
- if (break_state == -1)
- mcr |= UART_MCR_BR_MSK;
- else
- mcr &= ~UART_MCR_BR_MSK;
- UART_PUT_MCR(port, mcr);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void
-uart00_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
-{
- unsigned int uart_mc, old_ies, baud, quot;
- unsigned long flags;
-
- /*
- * We don't support CREAD (yet)
- */
- termios->c_cflag |= CREAD;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- /* byte size and parity */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- uart_mc = UART_MC_CLS_CHARLEN_5;
- break;
- case CS6:
- uart_mc = UART_MC_CLS_CHARLEN_6;
- break;
- case CS7:
- uart_mc = UART_MC_CLS_CHARLEN_7;
- break;
- default: // CS8
- uart_mc = UART_MC_CLS_CHARLEN_8;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- uart_mc|= UART_MC_ST_TWO;
- if (termios->c_cflag & PARENB) {
- uart_mc |= UART_MC_PE_MSK;
- if (!(termios->c_cflag & PARODD))
- uart_mc |= UART_MC_EP_MSK;
- }
-
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = UART_RDS_OE_MSK;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= UART_RDS_BI_MSK;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= UART_RDS_BI_MSK;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns to (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_RDS_OE_MSK;
- }
-
- /* first, disable everything */
- old_ies = UART_GET_IES(port);
-
- if (UART_ENABLE_MS(port, termios->c_cflag))
- old_ies |= UART_IES_ME_MSK;
-
- /* Set baud rate */
- UART_PUT_DIV_LO(port, (quot & 0xff));
- UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-
- UART_PUT_MC(port, uart_mc);
- UART_PUT_IES(port, old_ies);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int uart00_startup(struct uart_port *port)
-{
- int result;
-
- /*
- * Allocate the IRQ
- */
- result = request_irq(port->irq, uart00_int, 0, "uart00", port);
- if (result) {
- printk(KERN_ERR "Request of irq %d failed\n", port->irq);
- return result;
- }
-
- /*
- * Finally, enable interrupts. Use the TII interrupt to minimise
- * the number of interrupts generated. If higher performance is
- * needed, consider using the TI interrupt with a suitable FIFO
- * threshold
- */
- UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
-
- return 0;
-}
-
-static void uart00_shutdown(struct uart_port *port)
-{
- /*
- * disable all interrupts, disable the port
- */
- UART_PUT_IEC(port, 0xff);
-
- /* disable break condition and fifos */
- UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
-
- /*
- * Free the interrupt
- */
- free_irq(port->irq, port);
-}
-
-static const char *uart00_type(struct uart_port *port)
-{
- return port->type == PORT_UART00 ? "Altera UART00" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'
- */
-static void uart00_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, UART_PORT_SIZE);
-
-#ifdef CONFIG_ARCH_CAMELOT
- if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) {
- iounmap(port->membase);
- }
-#endif
-}
-
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int uart00_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00")
- != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void uart00_config_port(struct uart_port *port, int flags)
-{
-
- /*
- * Map the io memory if this is a soft uart
- */
- if (!port->membase)
- port->membase = ioremap_nocache(port->mapbase,SZ_4K);
-
- if (!port->membase)
- printk(KERN_ERR "serial00: cannot map io memory\n");
- else
- port->type = PORT_UART00;
-
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops uart00_pops = {
- .tx_empty = uart00_tx_empty,
- .set_mctrl = uart00_set_mctrl_null,
- .get_mctrl = uart00_get_mctrl,
- .stop_tx = uart00_stop_tx,
- .start_tx = uart00_start_tx,
- .stop_rx = uart00_stop_rx,
- .enable_ms = uart00_enable_ms,
- .break_ctl = uart00_break_ctl,
- .startup = uart00_startup,
- .shutdown = uart00_shutdown,
- .set_termios = uart00_set_termios,
- .type = uart00_type,
- .release_port = uart00_release_port,
- .request_port = uart00_request_port,
- .config_port = uart00_config_port,
- .verify_port = uart00_verify_port,
-};
-
-
-#ifdef CONFIG_ARCH_CAMELOT
-static struct uart_port epxa10db_port = {
- .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
- .mapbase = EXC_UART00_BASE,
- .iotype = SERIAL_IO_MEM,
- .irq = IRQ_UART,
- .uartclk = EXC_AHB2_CLK_FREQUENCY,
- .fifosize = 16,
- .ops = &uart00_pops,
- .flags = ASYNC_BOOT_AUTOCONF,
-};
-#endif
-
-
-#ifdef CONFIG_SERIAL_UART00_CONSOLE
-static void uart00_console_write(struct console *co, const char *s, unsigned count)
-{
-#ifdef CONFIG_ARCH_CAMELOT
- struct uart_port *port = &epxa10db_port;
- unsigned int status, old_ies;
- int i;
-
- /*
- * First save the CR then disable the interrupts
- */
- old_ies = UART_GET_IES(port);
- UART_PUT_IEC(port,0xff);
-
- /*
- * Now, do each character
- */
- for (i = 0; i < count; i++) {
- do {
- status = UART_GET_TSR(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, s[i]);
- if (s[i] == '\n') {
- do {
- status = UART_GET_TSR(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, '\r');
- }
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IES
- */
- do {
- status = UART_GET_TSR(port);
- } while (status & UART_TSR_TX_LEVEL_MSK);
- UART_PUT_IES(port, old_ies);
-#endif
-}
-
-static void __init
-uart00_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- unsigned int uart_mc, quot;
-
- uart_mc = UART_GET_MC(port);
-
- *parity = 'n';
- if (uart_mc & UART_MC_PE_MSK) {
- if (uart_mc & UART_MC_EP_MSK)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- switch (uart_mc & UART_MC_CLS_MSK) {
- case UART_MC_CLS_CHARLEN_5:
- *bits = 5;
- break;
- case UART_MC_CLS_CHARLEN_6:
- *bits = 6;
- break;
- case UART_MC_CLS_CHARLEN_7:
- *bits = 7;
- break;
- case UART_MC_CLS_CHARLEN_8:
- *bits = 8;
- break;
- }
- quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
- *baud = port->uartclk / (16 *quot );
-}
-
-static int __init uart00_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
-#ifdef CONFIG_ARCH_CAMELOT
- port = &epxa10db_port; ;
-#else
- return -ENODEV;
-#endif
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- uart00_console_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-extern struct uart_driver uart00_reg;
-static struct console uart00_console = {
- .name = SERIAL_UART00_NAME,
- .write = uart00_console_write,
- .device = uart_console_device,
- .setup = uart00_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = 0,
- .data = &uart00_reg,
-};
-
-static int __init uart00_console_init(void)
-{
- register_console(&uart00_console);
- return 0;
-}
-console_initcall(uart00_console_init);
-
-#define UART00_CONSOLE &uart00_console
-#else
-#define UART00_CONSOLE NULL
-#endif
-
-static struct uart_driver uart00_reg = {
- .owner = NULL,
- .driver_name = SERIAL_UART00_NAME,
- .dev_name = SERIAL_UART00_NAME,
- .major = SERIAL_UART00_MAJOR,
- .minor = SERIAL_UART00_MINOR,
- .nr = UART_NR,
- .cons = UART00_CONSOLE,
-};
-
-struct dev_port_entry{
- unsigned int base_addr;
- struct uart_port *port;
-};
-
-#ifdef CONFIG_PLD_HOTSWAP
-
-static struct dev_port_entry dev_port_map[UART_NR];
-
-/*
- * Keep a mapping of dev_info addresses -> port lines to use when
- * removing ports dev==NULL indicates unused entry
- */
-
-struct uart00_ps_data{
- unsigned int clk;
- unsigned int fifosize;
-};
-
-int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
-{
- struct uart00_ps_data* dev_ps=dev_ps_data;
- struct uart_port * port;
- int i,result;
-
- i=0;
- while(dev_port_map[i].port)
- i++;
-
- if(i==UART_NR){
- printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
- return 0;
- }
-
- port=kmalloc(sizeof(struct uart_port),GFP_KERNEL);
- if(!port)
- return -ENOMEM;
-
- printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
- port->membase=0;
- port->mapbase=dev_info->base_addr;
- port->iotype=SERIAL_IO_MEM;
- port->irq=dev_info->irq;
- port->uartclk=dev_ps->clk;
- port->fifosize=dev_ps->fifosize;
- port->ops=&uart00_pops;
- port->line=i;
- port->flags=ASYNC_BOOT_AUTOCONF;
-
- result=uart_add_one_port(&uart00_reg, port);
- if(result){
- printk("uart_add_one_port returned %d\n",result);
- return result;
- }
- dev_port_map[i].base_addr=dev_info->base_addr;
- dev_port_map[i].port=port;
- printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i);
- return 0;
-
-}
-
-int uart00_remove_devices(void)
-{
- int i,result;
-
-
- result=0;
- for(i=1;i<UART_NR;i++){
- if(dev_port_map[i].base_addr){
- result=uart_remove_one_port(&uart00_reg, dev_port_map[i].port);
- if(result)
- return result;
-
- /* port removed sucessfully, so now tidy up */
- kfree(dev_port_map[i].port);
- dev_port_map[i].base_addr=0;
- dev_port_map[i].port=NULL;
- }
- }
- return 0;
-
-}
-
-struct pld_hotswap_ops uart00_pldhs_ops={
- .name = "uart00",
- .add_device = uart00_add_device,
- .remove_devices = uart00_remove_devices,
-};
-
-#endif
-
-static int __init uart00_init(void)
-{
- int result;
-
- printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n");
-
- printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs"
- " - these WILL change in the future\n");
-
- result = uart_register_driver(&uart00_reg);
- if (result)
- return result;
-#ifdef CONFIG_ARCH_CAMELOT
- result = uart_add_one_port(&uart00_reg,&epxa10db_port);
-#endif
- if (result)
- uart_unregister_driver(&uart00_reg);
-
-#ifdef CONFIG_PLD_HOTSWAP
- pldhs_register_driver(&uart00_pldhs_ops);
-#endif
- return result;
-}
-
-__initcall(uart00_init);
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 865d4dea65df..d61494d185cd 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Serial Interface Unit.
*
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* Based on drivers/serial/8250.c, by Russell King.
*
@@ -371,11 +371,6 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status,
lsr = *status;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- }
-
ch = siu_read(port, UART_RX);
port->icount.rx++;
flag = TTY_NORMAL;
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 7bdab2a7f59c..94b229031198 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -175,8 +175,6 @@ int superhyway_register_driver(struct superhyway_driver *drv)
{
drv->drv.name = drv->name;
drv->drv.bus = &superhyway_bus_type;
- drv->drv.probe = superhyway_device_probe;
- drv->drv.remove = superhyway_device_remove;
return driver_register(&drv->drv);
}
@@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = {
#ifdef CONFIG_SYSFS
.dev_attrs = superhyway_dev_attrs,
#endif
+ .probe = superhyway_device_probe,
+ .remove = superhyway_device_remove,
};
static int __init superhyway_bus_init(void)
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
index 13b8d249da5c..d95265b187a3 100644
--- a/drivers/sn/Kconfig
+++ b/drivers/sn/Kconfig
@@ -17,4 +17,18 @@ config SGI_IOC4
If you have an SGI Altix with an IOC4-based
I/O controller say Y. Otherwise say N.
+config SGI_IOC3
+ tristate "SGI IOC3 Base IO support"
+ depends on (IA64_GENERIC || IA64_SGI_SN2)
+ default m
+ ---help---
+ This option enables basic support for the SGI IOC3-based Base IO
+ controller card. This option does not enable any specific
+ functions on such a card, but provides necessary infrastructure
+ for other drivers to utilize.
+
+ If you have an SGI Altix with an IOC3-based
+ I/O controller or a PCI IOC3 serial card say Y.
+ Otherwise say N.
+
endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index c2a284185372..2cda011597c0 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_SGI_IOC4) += ioc4.o
+obj-$(CONFIG_SGI_IOC3) += ioc3.o
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
new file mode 100644
index 000000000000..aaa009f4a7bf
--- /dev/null
+++ b/drivers/sn/ioc3.c
@@ -0,0 +1,851 @@
+/*
+ * SGI IOC3 master driver and IRQ demuxer
+ *
+ * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
+ * Heavily based on similar work by:
+ * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
+ * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ioc3.h>
+#include <linux/rwsem.h>
+
+#define IOC3_PCI_SIZE 0x100000
+
+static LIST_HEAD(ioc3_devices);
+static int ioc3_counter;
+static DECLARE_RWSEM(ioc3_devices_rwsem);
+
+static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
+static struct ioc3_submodule *ioc3_ethernet;
+static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED;
+
+/* NIC probing code */
+
+#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */
+
+static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
+{
+ return (pulse << 10) | (sample << 2);
+}
+
+static int nic_wait(struct ioc3_driver_data *idd)
+{
+ volatile unsigned mcr;
+
+ do {
+ mcr = (volatile unsigned)idd->vma->mcr;
+ } while (!(mcr & 2));
+
+ return mcr & 1;
+}
+
+static int nic_reset(struct ioc3_driver_data *idd)
+{
+ int presence;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ idd->vma->mcr = mcr_pack(500, 65);
+ presence = nic_wait(idd);
+ local_irq_restore(flags);
+
+ udelay(500);
+
+ return presence;
+}
+
+static inline int nic_read_bit(struct ioc3_driver_data *idd)
+{
+ int result;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ idd->vma->mcr = mcr_pack(6, 13);
+ result = nic_wait(idd);
+ local_irq_restore(flags);
+
+ udelay(500);
+
+ return result;
+}
+
+static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
+{
+ if (bit)
+ idd->vma->mcr = mcr_pack(6, 110);
+ else
+ idd->vma->mcr = mcr_pack(80, 30);
+
+ nic_wait(idd);
+}
+
+static unsigned nic_read_byte(struct ioc3_driver_data *idd)
+{
+ unsigned result = 0;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ result = (result >> 1) | (nic_read_bit(idd) << 7);
+
+ return result;
+}
+
+static void nic_write_byte(struct ioc3_driver_data *idd, int byte)
+{
+ int i, bit;
+
+ for (i = 8; i; i--) {
+ bit = byte & 1;
+ byte >>= 1;
+
+ nic_write_bit(idd, bit);
+ }
+}
+
+static unsigned long
+nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr)
+{
+ int a, b, index, disc;
+
+ nic_reset(idd);
+
+ /* Search ROM. */
+ nic_write_byte(idd, 0xF0);
+
+ /* Algorithm from ``Book of iButton Standards''. */
+ for (index = 0, disc = 0; index < 64; index++) {
+ a = nic_read_bit(idd);
+ b = nic_read_bit(idd);
+
+ if (a && b) {
+ printk(KERN_WARNING "IOC3 NIC search failed.\n");
+ *last = 0;
+ return 0;
+ }
+
+ if (!a && !b) {
+ if (index == *last) {
+ addr |= 1UL << index;
+ } else if (index > *last) {
+ addr &= ~(1UL << index);
+ disc = index;
+ } else if ((addr & (1UL << index)) == 0)
+ disc = index;
+ nic_write_bit(idd, (addr>>index)&1);
+ continue;
+ } else {
+ if (a)
+ addr |= 1UL << index;
+ else
+ addr &= ~(1UL << index);
+ nic_write_bit(idd, a);
+ continue;
+ }
+ }
+ *last = disc;
+ return addr;
+}
+
+static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr)
+{
+ int index;
+
+ nic_reset(idd);
+ nic_write_byte(idd, 0xF0);
+ for (index = 0; index < 64; index++) {
+ nic_read_bit(idd);
+ nic_read_bit(idd);
+ nic_write_bit(idd, (addr>>index)&1);
+ }
+}
+
+static void crc16_byte(unsigned int *crc, unsigned char db)
+{
+ int i;
+
+ for(i=0;i<8;i++) {
+ *crc <<= 1;
+ if((db^(*crc>>16)) & 1)
+ *crc ^= 0x8005;
+ db >>= 1;
+ }
+ *crc &= 0xFFFF;
+}
+
+static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc)
+{
+ while(size--)
+ crc16_byte(&crc, *(dbs++));
+ return crc;
+}
+
+static void crc8_byte(unsigned int *crc, unsigned char db)
+{
+ int i,f;
+
+ for(i=0;i<8;i++) {
+ f = (*crc ^ db) & 1;
+ *crc >>= 1;
+ db >>= 1;
+ if(f)
+ *crc ^= 0x8c;
+ }
+ *crc &= 0xff;
+}
+
+static unsigned int crc8_addr(unsigned long addr)
+{
+ int i;
+ unsigned int crc = 0x00;
+
+ for(i=0;i<8;i++)
+ crc8_byte(&crc, addr>>(i<<3));
+ return crc;
+}
+
+static void
+read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page,
+ unsigned char *redir, unsigned char *data)
+{
+ int loops = 16, i;
+
+ while(redir[page] != 0xFF) {
+ page = redir[page]^0xFF;
+ loops--;
+ if(loops<0) {
+ printk(KERN_ERR "IOC3: NIC circular redirection\n");
+ return;
+ }
+ }
+ loops = 3;
+ while(loops>0) {
+ nic_addr(idd, addr);
+ nic_write_byte(idd, 0xF0);
+ nic_write_byte(idd, (page << 5) & 0xE0);
+ nic_write_byte(idd, (page >> 3) & 0x1F);
+ for(i=0;i<0x20;i++)
+ data[i] = nic_read_byte(idd);
+ if(crc16_area(data, 0x20, 0x0000) == 0x800d)
+ return;
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in data page\n");
+ for(i=0;i<0x20;i++)
+ data[i] = 0x00;
+}
+
+static void
+read_redir_map(struct ioc3_driver_data *idd, unsigned long addr,
+ unsigned char *redir)
+{
+ int i,j,loops = 3,crc_ok;
+ unsigned int crc;
+
+ while(loops>0) {
+ crc_ok = 1;
+ nic_addr(idd, addr);
+ nic_write_byte(idd, 0xAA);
+ nic_write_byte(idd, 0x00);
+ nic_write_byte(idd, 0x01);
+ for(i=0;i<64;i+=8) {
+ for(j=0;j<8;j++)
+ redir[i+j] = nic_read_byte(idd);
+ crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000);
+ crc16_byte(&crc, nic_read_byte(idd));
+ crc16_byte(&crc, nic_read_byte(idd));
+ if(crc != 0x800d)
+ crc_ok = 0;
+ }
+ if(crc_ok)
+ return;
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in redirection page\n");
+ for(i=0;i<64;i++)
+ redir[i] = 0xFF;
+}
+
+static void read_nic(struct ioc3_driver_data *idd, unsigned long addr)
+{
+ unsigned char redir[64];
+ unsigned char data[64],part[32];
+ int i,j;
+
+ /* read redirections */
+ read_redir_map(idd, addr, redir);
+ /* read data pages */
+ read_redir_page(idd, addr, 0, redir, data);
+ read_redir_page(idd, addr, 1, redir, data+32);
+ /* assemble the part # */
+ j=0;
+ for(i=0;i<19;i++)
+ if(data[i+11] != ' ')
+ part[j++] = data[i+11];
+ for(i=0;i<6;i++)
+ if(data[i+32] != ' ')
+ part[j++] = data[i+32];
+ part[j] = 0;
+ /* skip Octane power supplies */
+ if(!strncmp(part, "060-0035-", 9))
+ return;
+ if(!strncmp(part, "060-0038-", 9))
+ return;
+ strcpy(idd->nic_part, part);
+ /* assemble the serial # */
+ j=0;
+ for(i=0;i<10;i++)
+ if(data[i+1] != ' ')
+ idd->nic_serial[j++] = data[i+1];
+ idd->nic_serial[j] = 0;
+}
+
+static void read_mac(struct ioc3_driver_data *idd, unsigned long addr)
+{
+ int i, loops = 3;
+ unsigned char data[13];
+
+ while(loops>0) {
+ nic_addr(idd, addr);
+ nic_write_byte(idd, 0xF0);
+ nic_write_byte(idd, 0x00);
+ nic_write_byte(idd, 0x00);
+ nic_read_byte(idd);
+ for(i=0;i<13;i++)
+ data[i] = nic_read_byte(idd);
+ if(crc16_area(data, 13, 0x0000) == 0x800d) {
+ for(i=10;i>4;i--)
+ idd->nic_mac[10-i] = data[i];
+ return;
+ }
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in MAC address\n");
+ for(i=0;i<6;i++)
+ idd->nic_mac[i] = 0x00;
+}
+
+static void probe_nic(struct ioc3_driver_data *idd)
+{
+ int save = 0, loops = 3;
+ unsigned long first, addr;
+
+ idd->vma->gpcr_s = GPCR_MLAN_EN;
+
+ while(loops>0) {
+ idd->nic_part[0] = 0;
+ idd->nic_serial[0] = 0;
+ addr = first = nic_find(idd, &save, 0);
+ if(!first)
+ return;
+ while(1) {
+ if(crc8_addr(addr))
+ break;
+ else {
+ switch(addr & 0xFF) {
+ case 0x0B:
+ read_nic(idd, addr);
+ break;
+ case 0x09:
+ case 0x89:
+ case 0x91:
+ read_mac(idd, addr);
+ break;
+ }
+ }
+ addr = nic_find(idd, &save, addr);
+ if(addr == first)
+ return;
+ }
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in NIC address\n");
+}
+
+/* Interrupts */
+
+static inline void
+write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&idd->ir_lock, flags);
+ switch (which) {
+ case IOC3_W_IES:
+ writel(val, &idd->vma->sio_ies);
+ break;
+ case IOC3_W_IEC:
+ writel(val, &idd->vma->sio_iec);
+ break;
+ }
+ spin_unlock_irqrestore(&idd->ir_lock, flags);
+}
+static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd)
+{
+ unsigned long flag;
+ uint32_t intrs = 0;
+
+ spin_lock_irqsave(&idd->ir_lock, flag);
+ intrs = readl(&idd->vma->sio_ir);
+ intrs &= readl(&idd->vma->sio_ies);
+ spin_unlock_irqrestore(&idd->ir_lock, flag);
+ return intrs;
+}
+
+static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs)
+{
+ unsigned long flags;
+ struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
+ int handled = 1, id;
+ unsigned int pending;
+
+ read_lock_irqsave(&ioc3_submodules_lock, flags);
+
+ if(idd->dual_irq && idd->vma->eisr) {
+ /* send Ethernet IRQ to the driver */
+ if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
+ ioc3_ethernet->intr) {
+ handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
+ idd, 0, regs);
+ }
+ }
+ pending = get_pending_intrs(idd); /* look at the IO IRQs */
+
+ for(id=0;id<IOC3_MAX_SUBMODULES;id++) {
+ if(idd->active[id] && ioc3_submodules[id]
+ && (pending & ioc3_submodules[id]->irq_mask)
+ && ioc3_submodules[id]->intr) {
+ write_ireg(idd, ioc3_submodules[id]->irq_mask,
+ IOC3_W_IEC);
+ if(!ioc3_submodules[id]->intr(ioc3_submodules[id],
+ idd, pending & ioc3_submodules[id]->irq_mask,
+ regs))
+ pending &= ~ioc3_submodules[id]->irq_mask;
+ if (ioc3_submodules[id]->reset_mask)
+ write_ireg(idd, ioc3_submodules[id]->irq_mask,
+ IOC3_W_IES);
+ }
+ }
+ read_unlock_irqrestore(&ioc3_submodules_lock, flags);
+ if(pending) {
+ printk(KERN_WARNING
+ "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending);
+ write_ireg(idd, pending, IOC3_W_IEC);
+ handled = 1;
+ }
+ return handled?IRQ_HANDLED:IRQ_NONE;
+}
+
+static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs)
+{
+ unsigned long flags;
+ struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
+ int handled = 1;
+
+ if(!idd->dual_irq)
+ return IRQ_NONE;
+ read_lock_irqsave(&ioc3_submodules_lock, flags);
+ if(ioc3_ethernet && idd->active[ioc3_ethernet->id]
+ && ioc3_ethernet->intr)
+ handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0,
+ regs);
+ read_unlock_irqrestore(&ioc3_submodules_lock, flags);
+ return handled?IRQ_HANDLED:IRQ_NONE;
+}
+
+void ioc3_enable(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd, unsigned int irqs)
+{
+ write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES);
+}
+
+void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd,
+ unsigned int irqs)
+{
+ writel(irqs & is->irq_mask, &idd->vma->sio_ir);
+}
+
+void ioc3_disable(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd, unsigned int irqs)
+{
+ write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC);
+}
+
+void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&idd->gpio_lock, flags);
+ writel(val, &idd->vma->gpcr_s);
+ spin_unlock_irqrestore(&idd->gpio_lock, flags);
+}
+
+/* Keep it simple, stupid! */
+static int find_slot(void **tab, int max)
+{
+ int i;
+ for(i=0;i<max;i++)
+ if(!(tab[i]))
+ return i;
+ return -1;
+}
+
+/* Register an IOC3 submodule */
+int ioc3_register_submodule(struct ioc3_submodule *is)
+{
+ struct ioc3_driver_data *idd;
+ int alloc_id;
+ unsigned long flags;
+
+ write_lock_irqsave(&ioc3_submodules_lock, flags);
+ alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
+ if(alloc_id != -1) {
+ ioc3_submodules[alloc_id] = is;
+ if(is->ethernet) {
+ if(ioc3_ethernet==NULL)
+ ioc3_ethernet=is;
+ else
+ printk(KERN_WARNING
+ "IOC3 Ethernet module already registered!\n");
+ }
+ }
+ write_unlock_irqrestore(&ioc3_submodules_lock, flags);
+
+ if(alloc_id == -1) {
+ printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n");
+ return -ENOMEM;
+ }
+
+ is->id=alloc_id;
+
+ /* Initialize submodule for each IOC3 */
+ if (!is->probe)
+ return 0;
+
+ down_read(&ioc3_devices_rwsem);
+ list_for_each_entry(idd, &ioc3_devices, list) {
+ /* set to 1 for IRQs in probe */
+ idd->active[alloc_id] = 1;
+ idd->active[alloc_id] = !is->probe(is, idd);
+ }
+ up_read(&ioc3_devices_rwsem);
+
+ return 0;
+}
+
+/* Unregister an IOC3 submodule */
+void ioc3_unregister_submodule(struct ioc3_submodule *is)
+{
+ struct ioc3_driver_data *idd;
+ unsigned long flags;
+
+ write_lock_irqsave(&ioc3_submodules_lock, flags);
+ if(ioc3_submodules[is->id]==is)
+ ioc3_submodules[is->id]=NULL;
+ else
+ printk(KERN_WARNING
+ "IOC3 submodule %s has wrong ID.\n",is->name);
+ if(ioc3_ethernet==is)
+ ioc3_ethernet = NULL;
+ write_unlock_irqrestore(&ioc3_submodules_lock, flags);
+
+ /* Remove submodule for each IOC3 */
+ down_read(&ioc3_devices_rwsem);
+ list_for_each_entry(idd, &ioc3_devices, list)
+ if(idd->active[is->id]) {
+ if(is->remove)
+ if(is->remove(is, idd))
+ printk(KERN_WARNING
+ "%s: IOC3 submodule %s remove failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__, module_name(is->owner),
+ pci_name(idd->pdev));
+ idd->active[is->id] = 0;
+ if(is->irq_mask)
+ write_ireg(idd, is->irq_mask, IOC3_W_IEC);
+ }
+ up_read(&ioc3_devices_rwsem);
+}
+
+/*********************
+ * Device management *
+ *********************/
+
+static char *
+ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3",
+ "MENET 4", "CADduo", "Altix Serial"};
+
+static int ioc3_class(struct ioc3_driver_data *idd)
+{
+ int res = IOC3_CLASS_NONE;
+ /* NIC-based logic */
+ if(!strncmp(idd->nic_part, "030-0891-", 9))
+ res = IOC3_CLASS_BASE_IP30;
+ if(!strncmp(idd->nic_part, "030-1155-", 9))
+ res = IOC3_CLASS_CADDUO;
+ if(!strncmp(idd->nic_part, "030-1657-", 9))
+ res = IOC3_CLASS_SERIAL;
+ if(!strncmp(idd->nic_part, "030-1664-", 9))
+ res = IOC3_CLASS_SERIAL;
+ /* total random heuristics */
+#ifdef CONFIG_SGI_IP27
+ if(!idd->nic_part[0])
+ res = IOC3_CLASS_BASE_IP27;
+#endif
+ /* print educational message */
+ printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n",
+ idd->nic_part, idd->nic_serial, ioc3_class_names[res]);
+ return res;
+}
+/* Adds a new instance of an IOC3 card */
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+ struct ioc3_driver_data *idd;
+ uint32_t pcmd;
+ int ret, id;
+
+ /* Enable IOC3 and take ownership of it */
+ if ((ret = pci_enable_device(pdev))) {
+ printk(KERN_WARNING
+ "%s: Failed to enable IOC3 device for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ goto out;
+ }
+ pci_set_master(pdev);
+
+#ifdef USE_64BIT_DMA
+ ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (!ret) {
+ ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
+ "for consistent allocations\n",
+ __FUNCTION__);
+ }
+ }
+#endif
+
+ /* Set up per-IOC3 data */
+ idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
+ if (!idd) {
+ printk(KERN_WARNING
+ "%s: Failed to allocate IOC3 data for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_idd;
+ }
+ memset(idd, 0, sizeof(struct ioc3_driver_data));
+ spin_lock_init(&idd->ir_lock);
+ spin_lock_init(&idd->gpio_lock);
+ idd->pdev = pdev;
+
+ /* Map all IOC3 registers. These are shared between subdevices
+ * so the main IOC3 module manages them.
+ */
+ idd->pma = pci_resource_start(pdev, 0);
+ if (!idd->pma) {
+ printk(KERN_WARNING
+ "%s: Unable to find IOC3 resource "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+ if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
+ printk(KERN_WARNING
+ "%s: Unable to request IOC3 region "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+ idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE);
+ if (!idd->vma) {
+ printk(KERN_WARNING
+ "%s: Unable to remap IOC3 region "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_misc_region;
+ }
+
+ /* Track PCI-device specific data */
+ pci_set_drvdata(pdev, idd);
+ down_write(&ioc3_devices_rwsem);
+ list_add(&idd->list, &ioc3_devices);
+ idd->id = ioc3_counter++;
+ up_write(&ioc3_devices_rwsem);
+
+ idd->gpdr_shadow = idd->vma->gpdr;
+
+ /* Read IOC3 NIC contents */
+ probe_nic(idd);
+
+ /* Detect IOC3 class */
+ idd->class = ioc3_class(idd);
+
+ /* Initialize IOC3 */
+ pci_read_config_dword(pdev, PCI_COMMAND, &pcmd);
+ pci_write_config_dword(pdev, PCI_COMMAND,
+ pcmd | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR |
+ PCI_SCR_DROP_MODE_EN);
+
+ write_ireg(idd, ~0, IOC3_W_IEC);
+ writel(~0, &idd->vma->sio_ir);
+
+ /* Set up IRQs */
+ if(idd->class == IOC3_CLASS_BASE_IP30
+ || idd->class == IOC3_CLASS_BASE_IP27) {
+ writel(0, &idd->vma->eier);
+ writel(~0, &idd->vma->eisr);
+
+ idd->dual_irq = 1;
+ if (!request_irq(pdev->irq, ioc3_intr_eth, SA_SHIRQ,
+ "ioc3-eth", (void *)idd)) {
+ idd->irq_eth = pdev->irq;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq);
+ }
+ if (!request_irq(pdev->irq+2, ioc3_intr_io, SA_SHIRQ,
+ "ioc3-io", (void *)idd)) {
+ idd->irq_io = pdev->irq+2;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq+2);
+ }
+ } else {
+ if (!request_irq(pdev->irq, ioc3_intr_io, SA_SHIRQ,
+ "ioc3", (void *)idd)) {
+ idd->irq_io = pdev->irq;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq);
+ }
+ }
+
+ /* Add this IOC3 to all submodules */
+ read_lock(&ioc3_submodules_lock);
+ for(id=0;id<IOC3_MAX_SUBMODULES;id++)
+ if(ioc3_submodules[id] && ioc3_submodules[id]->probe) {
+ idd->active[id] = 1;
+ idd->active[id] = !ioc3_submodules[id]->probe
+ (ioc3_submodules[id], idd);
+ }
+ read_unlock(&ioc3_submodules_lock);
+
+ printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev));
+
+ return 0;
+
+out_misc_region:
+ release_region(idd->pma, IOC3_PCI_SIZE);
+out_pci:
+ kfree(idd);
+out_idd:
+ pci_disable_device(pdev);
+out:
+ return ret;
+}
+
+/* Removes a particular instance of an IOC3 card. */
+static void ioc3_remove(struct pci_dev *pdev)
+{
+ int id;
+ struct ioc3_driver_data *idd;
+
+ idd = pci_get_drvdata(pdev);
+
+ /* Remove this IOC3 from all submodules */
+ read_lock(&ioc3_submodules_lock);
+ for(id=0;id<IOC3_MAX_SUBMODULES;id++)
+ if(idd->active[id]) {
+ if(ioc3_submodules[id] && ioc3_submodules[id]->remove)
+ if(ioc3_submodules[id]->remove(ioc3_submodules[id],
+ idd))
+ printk(KERN_WARNING
+ "%s: IOC3 submodule 0x%s remove failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__,
+ module_name(ioc3_submodules[id]->owner),
+ pci_name(pdev));
+ idd->active[id] = 0;
+ }
+ read_unlock(&ioc3_submodules_lock);
+
+ /* Clear and disable all IRQs */
+ write_ireg(idd, ~0, IOC3_W_IEC);
+ writel(~0, &idd->vma->sio_ir);
+
+ /* Release resources */
+ free_irq(idd->irq_io, (void *)idd);
+ if(idd->dual_irq)
+ free_irq(idd->irq_eth, (void *)idd);
+ iounmap(idd->vma);
+ release_region(idd->pma, IOC3_PCI_SIZE);
+
+ /* Disable IOC3 and relinquish */
+ pci_disable_device(pdev);
+
+ /* Remove and free driver data */
+ down_write(&ioc3_devices_rwsem);
+ list_del(&idd->list);
+ up_write(&ioc3_devices_rwsem);
+ kfree(idd);
+}
+
+static struct pci_device_id ioc3_id_table[] = {
+ {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID},
+ {0}
+};
+
+static struct pci_driver ioc3_driver = {
+ .name = "IOC3",
+ .id_table = ioc3_id_table,
+ .probe = ioc3_probe,
+ .remove = ioc3_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, ioc3_id_table);
+
+/*********************
+ * Module management *
+ *********************/
+
+/* Module load */
+static int __devinit ioc3_init(void)
+{
+ if (ia64_platform_is("sn2"))
+ return pci_register_driver(&ioc3_driver);
+ return 0;
+}
+
+/* Module unload */
+static void __devexit ioc3_exit(void)
+{
+ pci_unregister_driver(&ioc3_driver);
+}
+
+module_init(ioc3_init);
+module_exit(ioc3_exit);
+
+MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>");
+MODULE_DESCRIPTION("PCI driver for SGI IOC3");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc3_register_submodule);
+EXPORT_SYMBOL(ioc3_unregister_submodule);
+EXPORT_SYMBOL(ioc3_ack);
+EXPORT_SYMBOL(ioc3_gpcr_set);
+EXPORT_SYMBOL(ioc3_disable);
+EXPORT_SYMBOL(ioc3_enable);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
new file mode 100644
index 000000000000..b77dbd63e596
--- /dev/null
+++ b/drivers/spi/Kconfig
@@ -0,0 +1,109 @@
+#
+# SPI driver configuration
+#
+# NOTE: the reason this doesn't show SPI slave support is mostly that
+# nobody's needed a slave side API yet. The master-role API is not
+# fully appropriate there, so it'd need some thought to do well.
+#
+menu "SPI support"
+
+config SPI
+ bool "SPI support"
+ help
+ The "Serial Peripheral Interface" is a low level synchronous
+ protocol. Chips that support SPI can have data transfer rates
+ up to several tens of Mbit/sec. Chips are addressed with a
+ controller and a chipselect. Most SPI slaves don't support
+ dynamic device discovery; some are even write-only or read-only.
+
+ SPI is widely used by microcontollers to talk with sensors,
+ eeprom and flash memory, codecs and various other controller
+ chips, analog to digital (and d-to-a) converters, and more.
+ MMC and SD cards can be accessed using SPI protocol; and for
+ DataFlash cards used in MMC sockets, SPI must always be used.
+
+ SPI is one of a family of similar protocols using a four wire
+ interface (select, clock, data in, data out) including Microwire
+ (half duplex), SSP, SSI, and PSP. This driver framework should
+ work with most such devices and controllers.
+
+config SPI_DEBUG
+ boolean "Debug support for SPI drivers"
+ depends on SPI && DEBUG_KERNEL
+ help
+ Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
+ sysfs, and debugfs support in SPI controller and protocol drivers.
+
+#
+# MASTER side ... talking to discrete SPI slave chips including microcontrollers
+#
+
+config SPI_MASTER
+# boolean "SPI Master Support"
+ boolean
+ default SPI
+ help
+ If your system has an master-capable SPI controller (which
+ provides the clock and chipselect), you can enable that
+ controller and the protocol drivers for the SPI slave chips
+ that are connected.
+
+comment "SPI Master Controller Drivers"
+ depends on SPI_MASTER
+
+config SPI_BITBANG
+ tristate "Bitbanging SPI master"
+ depends on SPI_MASTER && EXPERIMENTAL
+ help
+ With a few GPIO pins, your system can bitbang the SPI protocol.
+ Select this to get SPI support through I/O pins (GPIO, parallel
+ port, etc). Or, some systems' SPI master controller drivers use
+ this code to manage the per-word or per-transfer accesses to the
+ hardware shift registers.
+
+ This is library code, and is automatically selected by drivers that
+ need it. You only need to select this explicitly to support driver
+ modules that aren't part of this kernel tree.
+
+config SPI_BUTTERFLY
+ tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This uses a custom parallel port cable to connect to an AVR
+ Butterfly <http://www.atmel.com/products/avr/butterfly>, an
+ inexpensive battery powered microcontroller evaluation board.
+ This same cable can be used to flash new firmware.
+
+config SPI_BUTTERFLY
+ tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This uses a custom parallel port cable to connect to an AVR
+ Butterfly <http://www.atmel.com/products/avr/butterfly>, an
+ inexpensive battery powered microcontroller evaluation board.
+ This same cable can be used to flash new firmware.
+
+#
+# Add new SPI master controllers in alphabetical order above this line
+#
+
+
+#
+# There are lots of SPI device types, with sensors and memory
+# being probably the most widely used ones.
+#
+comment "SPI Protocol Masters"
+ depends on SPI_MASTER
+
+
+#
+# Add new SPI protocol masters in alphabetical order above this line
+#
+
+
+# (slave support would go here)
+
+endmenu # "SPI support"
+
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
new file mode 100644
index 000000000000..c2c87e845abf
--- /dev/null
+++ b/drivers/spi/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for kernel SPI drivers.
+#
+
+ifeq ($(CONFIG_SPI_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+# small core, mostly translating board-specific
+# config declarations into driver model code
+obj-$(CONFIG_SPI_MASTER) += spi.o
+
+# SPI master controller drivers (bus)
+obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
+obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
+# ... add above this line ...
+
+# SPI protocol drivers (device/link on bus)
+# ... add above this line ...
+
+# SPI slave controller drivers (upstream link)
+# ... add above this line ...
+
+# SPI slave drivers (protocol for that link)
+# ... add above this line ...
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
new file mode 100644
index 000000000000..791c4dc550ae
--- /dev/null
+++ b/drivers/spi/spi.c
@@ -0,0 +1,642 @@
+/*
+ * spi.c - SPI init/core code
+ *
+ * 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.
+ *
+ * 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/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/spi/spi.h>
+
+
+/* SPI bustype and spi_master class are registered after board init code
+ * provides the SPI device tables, ensuring that both are present by the
+ * time controller driver registration causes spi_devices to "enumerate".
+ */
+static void spidev_release(struct device *dev)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ /* spi masters may cleanup for released devices */
+ if (spi->master->cleanup)
+ spi->master->cleanup(spi);
+
+ spi_master_put(spi->master);
+ kfree(dev);
+}
+
+static ssize_t
+modalias_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias);
+}
+
+static struct device_attribute spi_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
+/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
+ * and the sysfs version makes coldplug work too.
+ */
+
+static int spi_match_device(struct device *dev, struct device_driver *drv)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
+}
+
+static int spi_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ envp[0] = buffer;
+ snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
+ envp[1] = NULL;
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+/*
+ * NOTE: the suspend() method for an spi_master controller driver
+ * should verify that all its child devices are marked as suspended;
+ * suspend requests delivered through sysfs power/state files don't
+ * enforce such constraints.
+ */
+static int spi_suspend(struct device *dev, pm_message_t message)
+{
+ int value;
+ struct spi_driver *drv = to_spi_driver(dev->driver);
+
+ if (!drv->suspend)
+ return 0;
+
+ /* suspend will stop irqs and dma; no more i/o */
+ value = drv->suspend(to_spi_device(dev), message);
+ if (value == 0)
+ dev->power.power_state = message;
+ return value;
+}
+
+static int spi_resume(struct device *dev)
+{
+ int value;
+ struct spi_driver *drv = to_spi_driver(dev->driver);
+
+ if (!drv->resume)
+ return 0;
+
+ /* resume may restart the i/o queue */
+ value = drv->resume(to_spi_device(dev));
+ if (value == 0)
+ dev->power.power_state = PMSG_ON;
+ return value;
+}
+
+#else
+#define spi_suspend NULL
+#define spi_resume NULL
+#endif
+
+struct bus_type spi_bus_type = {
+ .name = "spi",
+ .dev_attrs = spi_dev_attrs,
+ .match = spi_match_device,
+ .uevent = spi_uevent,
+ .suspend = spi_suspend,
+ .resume = spi_resume,
+};
+EXPORT_SYMBOL_GPL(spi_bus_type);
+
+
+static int spi_drv_probe(struct device *dev)
+{
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+
+ return sdrv->probe(to_spi_device(dev));
+}
+
+static int spi_drv_remove(struct device *dev)
+{
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+
+ return sdrv->remove(to_spi_device(dev));
+}
+
+static void spi_drv_shutdown(struct device *dev)
+{
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+
+ sdrv->shutdown(to_spi_device(dev));
+}
+
+int spi_register_driver(struct spi_driver *sdrv)
+{
+ sdrv->driver.bus = &spi_bus_type;
+ if (sdrv->probe)
+ sdrv->driver.probe = spi_drv_probe;
+ if (sdrv->remove)
+ sdrv->driver.remove = spi_drv_remove;
+ if (sdrv->shutdown)
+ sdrv->driver.shutdown = spi_drv_shutdown;
+ return driver_register(&sdrv->driver);
+}
+EXPORT_SYMBOL_GPL(spi_register_driver);
+
+/*-------------------------------------------------------------------------*/
+
+/* SPI devices should normally not be created by SPI device drivers; that
+ * would make them board-specific. Similarly with SPI master drivers.
+ * Device registration normally goes into like arch/.../mach.../board-YYY.c
+ * with other readonly (flashable) information about mainboard devices.
+ */
+
+struct boardinfo {
+ struct list_head list;
+ unsigned n_board_info;
+ struct spi_board_info board_info[0];
+};
+
+static LIST_HEAD(board_list);
+static DECLARE_MUTEX(board_lock);
+
+
+/* On typical mainboards, this is purely internal; and it's not needed
+ * after board init creates the hard-wired devices. Some development
+ * platforms may not be able to use spi_register_board_info though, and
+ * this is exported so that for example a USB or parport based adapter
+ * driver could add devices (which it would learn about out-of-band).
+ */
+struct spi_device *__init_or_module
+spi_new_device(struct spi_master *master, struct spi_board_info *chip)
+{
+ struct spi_device *proxy;
+ struct device *dev = master->cdev.dev;
+ int status;
+
+ /* NOTE: caller did any chip->bus_num checks necessary */
+
+ if (!spi_master_get(master))
+ return NULL;
+
+ proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
+ if (!proxy) {
+ dev_err(dev, "can't alloc dev for cs%d\n",
+ chip->chip_select);
+ goto fail;
+ }
+ proxy->master = master;
+ proxy->chip_select = chip->chip_select;
+ proxy->max_speed_hz = chip->max_speed_hz;
+ proxy->irq = chip->irq;
+ proxy->modalias = chip->modalias;
+
+ snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
+ "%s.%u", master->cdev.class_id,
+ chip->chip_select);
+ proxy->dev.parent = dev;
+ proxy->dev.bus = &spi_bus_type;
+ proxy->dev.platform_data = (void *) chip->platform_data;
+ proxy->controller_data = chip->controller_data;
+ proxy->controller_state = NULL;
+ proxy->dev.release = spidev_release;
+
+ /* drivers may modify this default i/o setup */
+ status = master->setup(proxy);
+ if (status < 0) {
+ dev_dbg(dev, "can't %s %s, status %d\n",
+ "setup", proxy->dev.bus_id, status);
+ goto fail;
+ }
+
+ /* driver core catches callers that misbehave by defining
+ * devices that already exist.
+ */
+ status = device_register(&proxy->dev);
+ if (status < 0) {
+ dev_dbg(dev, "can't %s %s, status %d\n",
+ "add", proxy->dev.bus_id, status);
+ goto fail;
+ }
+ dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
+ return proxy;
+
+fail:
+ spi_master_put(master);
+ kfree(proxy);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(spi_new_device);
+
+/*
+ * Board-specific early init code calls this (probably during arch_initcall)
+ * with segments of the SPI device table. Any device nodes are created later,
+ * after the relevant parent SPI controller (bus_num) is defined. We keep
+ * this table of devices forever, so that reloading a controller driver will
+ * not make Linux forget about these hard-wired devices.
+ *
+ * Other code can also call this, e.g. a particular add-on board might provide
+ * SPI devices through its expansion connector, so code initializing that board
+ * would naturally declare its SPI devices.
+ *
+ * The board info passed can safely be __initdata ... but be careful of
+ * any embedded pointers (platform_data, etc), they're copied as-is.
+ */
+int __init
+spi_register_board_info(struct spi_board_info const *info, unsigned n)
+{
+ struct boardinfo *bi;
+
+ bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
+ if (!bi)
+ return -ENOMEM;
+ bi->n_board_info = n;
+ memcpy(bi->board_info, info, n * sizeof *info);
+
+ down(&board_lock);
+ list_add_tail(&bi->list, &board_list);
+ up(&board_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_register_board_info);
+
+/* FIXME someone should add support for a __setup("spi", ...) that
+ * creates board info from kernel command lines
+ */
+
+static void __init_or_module
+scan_boardinfo(struct spi_master *master)
+{
+ struct boardinfo *bi;
+ struct device *dev = master->cdev.dev;
+
+ down(&board_lock);
+ list_for_each_entry(bi, &board_list, list) {
+ struct spi_board_info *chip = bi->board_info;
+ unsigned n;
+
+ for (n = bi->n_board_info; n > 0; n--, chip++) {
+ if (chip->bus_num != master->bus_num)
+ continue;
+ /* some controllers only have one chip, so they
+ * might not use chipselects. otherwise, the
+ * chipselects are numbered 0..max.
+ */
+ if (chip->chip_select >= master->num_chipselect
+ && master->num_chipselect) {
+ dev_dbg(dev, "cs%d > max %d\n",
+ chip->chip_select,
+ master->num_chipselect);
+ continue;
+ }
+ (void) spi_new_device(master, chip);
+ }
+ }
+ up(&board_lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void spi_master_release(struct class_device *cdev)
+{
+ struct spi_master *master;
+
+ master = container_of(cdev, struct spi_master, cdev);
+ kfree(master);
+}
+
+static struct class spi_master_class = {
+ .name = "spi_master",
+ .owner = THIS_MODULE,
+ .release = spi_master_release,
+};
+
+
+/**
+ * spi_alloc_master - allocate SPI master controller
+ * @dev: the controller, possibly using the platform_bus
+ * @size: how much driver-private data to preallocate; the pointer to this
+ * memory is in the class_data field of the returned class_device,
+ * accessible with spi_master_get_devdata().
+ *
+ * This call is used only by SPI master controller drivers, which are the
+ * only ones directly touching chip registers. It's how they allocate
+ * an spi_master structure, prior to calling spi_add_master().
+ *
+ * This must be called from context that can sleep. It returns the SPI
+ * master structure on success, else NULL.
+ *
+ * The caller is responsible for assigning the bus number and initializing
+ * the master's methods before calling spi_add_master(); and (after errors
+ * adding the device) calling spi_master_put() to prevent a memory leak.
+ */
+struct spi_master * __init_or_module
+spi_alloc_master(struct device *dev, unsigned size)
+{
+ struct spi_master *master;
+
+ if (!dev)
+ return NULL;
+
+ master = kzalloc(size + sizeof *master, SLAB_KERNEL);
+ if (!master)
+ return NULL;
+
+ class_device_initialize(&master->cdev);
+ master->cdev.class = &spi_master_class;
+ master->cdev.dev = get_device(dev);
+ spi_master_set_devdata(master, &master[1]);
+
+ return master;
+}
+EXPORT_SYMBOL_GPL(spi_alloc_master);
+
+/**
+ * spi_register_master - register SPI master controller
+ * @master: initialized master, originally from spi_alloc_master()
+ *
+ * SPI master controllers connect to their drivers using some non-SPI bus,
+ * such as the platform bus. The final stage of probe() in that code
+ * includes calling spi_register_master() to hook up to this SPI bus glue.
+ *
+ * SPI controllers use board specific (often SOC specific) bus numbers,
+ * and board-specific addressing for SPI devices combines those numbers
+ * with chip select numbers. Since SPI does not directly support dynamic
+ * device identification, boards need configuration tables telling which
+ * chip is at which address.
+ *
+ * This must be called from context that can sleep. It returns zero on
+ * success, else a negative error code (dropping the master's refcount).
+ * After a successful return, the caller is responsible for calling
+ * spi_unregister_master().
+ */
+int __init_or_module
+spi_register_master(struct spi_master *master)
+{
+ static atomic_t dyn_bus_id = ATOMIC_INIT(0);
+ struct device *dev = master->cdev.dev;
+ int status = -ENODEV;
+ int dynamic = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ /* convention: dynamically assigned bus IDs count down from the max */
+ if (master->bus_num == 0) {
+ master->bus_num = atomic_dec_return(&dyn_bus_id);
+ dynamic = 1;
+ }
+
+ /* register the device, then userspace will see it.
+ * registration fails if the bus ID is in use.
+ */
+ snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+ "spi%u", master->bus_num);
+ status = class_device_add(&master->cdev);
+ if (status < 0)
+ goto done;
+ dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+ dynamic ? " (dynamic)" : "");
+
+ /* populate children from any spi device tables */
+ scan_boardinfo(master);
+ status = 0;
+done:
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_register_master);
+
+
+static int __unregister(struct device *dev, void *unused)
+{
+ /* note: before about 2.6.14-rc1 this would corrupt memory: */
+ spi_unregister_device(to_spi_device(dev));
+ return 0;
+}
+
+/**
+ * spi_unregister_master - unregister SPI master controller
+ * @master: the master being unregistered
+ *
+ * This call is used only by SPI master controller drivers, which are the
+ * only ones directly touching chip registers.
+ *
+ * This must be called from context that can sleep.
+ */
+void spi_unregister_master(struct spi_master *master)
+{
+ (void) device_for_each_child(master->cdev.dev, NULL, __unregister);
+ class_device_unregister(&master->cdev);
+ master->cdev.dev = NULL;
+}
+EXPORT_SYMBOL_GPL(spi_unregister_master);
+
+/**
+ * spi_busnum_to_master - look up master associated with bus_num
+ * @bus_num: the master's bus number
+ *
+ * This call may be used with devices that are registered after
+ * arch init time. It returns a refcounted pointer to the relevant
+ * spi_master (which the caller must release), or NULL if there is
+ * no such master registered.
+ */
+struct spi_master *spi_busnum_to_master(u16 bus_num)
+{
+ if (bus_num) {
+ char name[8];
+ struct kobject *bus;
+
+ snprintf(name, sizeof name, "spi%u", bus_num);
+ bus = kset_find_obj(&spi_master_class.subsys.kset, name);
+ if (bus)
+ return container_of(bus, struct spi_master, cdev.kobj);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(spi_busnum_to_master);
+
+
+/*-------------------------------------------------------------------------*/
+
+static void spi_complete(void *arg)
+{
+ complete(arg);
+}
+
+/**
+ * spi_sync - blocking/synchronous SPI data transfers
+ * @spi: device with which data will be exchanged
+ * @message: describes the data transfers
+ *
+ * This call may only be used from a context that may sleep. The sleep
+ * is non-interruptible, and has no timeout. Low-overhead controller
+ * drivers may DMA directly into and out of the message buffers.
+ *
+ * Note that the SPI device's chip select is active during the message,
+ * and then is normally disabled between messages. Drivers for some
+ * frequently-used devices may want to minimize costs of selecting a chip,
+ * by leaving it selected in anticipation that the next message will go
+ * to the same chip. (That may increase power usage.)
+ *
+ * Also, the caller is guaranteeing that the memory associated with the
+ * message will not be freed before this call returns.
+ *
+ * The return value is a negative error code if the message could not be
+ * submitted, else zero. When the value is zero, then message->status is
+ * also defined: it's the completion code for the transfer, either zero
+ * or a negative error code from the controller driver.
+ */
+int spi_sync(struct spi_device *spi, struct spi_message *message)
+{
+ DECLARE_COMPLETION(done);
+ int status;
+
+ message->complete = spi_complete;
+ message->context = &done;
+ status = spi_async(spi, message);
+ if (status == 0)
+ wait_for_completion(&done);
+ message->context = NULL;
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_sync);
+
+#define SPI_BUFSIZ (SMP_CACHE_BYTES)
+
+static u8 *buf;
+
+/**
+ * spi_write_then_read - SPI synchronous write followed by read
+ * @spi: device with which data will be exchanged
+ * @txbuf: data to be written (need not be dma-safe)
+ * @n_tx: size of txbuf, in bytes
+ * @rxbuf: buffer into which data will be read
+ * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
+ *
+ * This performs a half duplex MicroWire style transaction with the
+ * device, sending txbuf and then reading rxbuf. The return value
+ * is zero for success, else a negative errno status code.
+ * This call may only be used from a context that may sleep.
+ *
+ * Parameters to this routine are always copied using a small buffer;
+ * performance-sensitive or bulk transfer code should instead use
+ * spi_{async,sync}() calls with dma-safe buffers.
+ */
+int spi_write_then_read(struct spi_device *spi,
+ const u8 *txbuf, unsigned n_tx,
+ u8 *rxbuf, unsigned n_rx)
+{
+ static DECLARE_MUTEX(lock);
+
+ int status;
+ struct spi_message message;
+ struct spi_transfer x[2];
+ u8 *local_buf;
+
+ /* Use preallocated DMA-safe buffer. We can't avoid copying here,
+ * (as a pure convenience thing), but we can keep heap costs
+ * out of the hot path ...
+ */
+ if ((n_tx + n_rx) > SPI_BUFSIZ)
+ return -EINVAL;
+
+ spi_message_init(&message);
+ memset(x, 0, sizeof x);
+ if (n_tx) {
+ x[0].len = n_tx;
+ spi_message_add_tail(&x[0], &message);
+ }
+ if (n_rx) {
+ x[1].len = n_rx;
+ spi_message_add_tail(&x[1], &message);
+ }
+
+ /* ... unless someone else is using the pre-allocated buffer */
+ if (down_trylock(&lock)) {
+ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
+ if (!local_buf)
+ return -ENOMEM;
+ } else
+ local_buf = buf;
+
+ memcpy(local_buf, txbuf, n_tx);
+ x[0].tx_buf = local_buf;
+ x[1].rx_buf = local_buf + n_tx;
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0) {
+ memcpy(rxbuf, x[1].rx_buf, n_rx);
+ status = message.status;
+ }
+
+ if (x[0].tx_buf == buf)
+ up(&lock);
+ else
+ kfree(local_buf);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_write_then_read);
+
+/*-------------------------------------------------------------------------*/
+
+static int __init spi_init(void)
+{
+ int status;
+
+ buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);
+ if (!buf) {
+ status = -ENOMEM;
+ goto err0;
+ }
+
+ status = bus_register(&spi_bus_type);
+ if (status < 0)
+ goto err1;
+
+ status = class_register(&spi_master_class);
+ if (status < 0)
+ goto err2;
+ return 0;
+
+err2:
+ bus_unregister(&spi_bus_type);
+err1:
+ kfree(buf);
+ buf = NULL;
+err0:
+ return status;
+}
+
+/* board_info is normally registered in arch_initcall(),
+ * but even essential drivers wait till later
+ *
+ * REVISIT only boardinfo really needs static linking. the rest (device and
+ * driver registration) _could_ be dynamically linked (modular) ... costs
+ * include needing to have boardinfo data structures be much more public.
+ */
+subsys_initcall(spi_init);
+
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
new file mode 100644
index 000000000000..f037e5593269
--- /dev/null
+++ b/drivers/spi/spi_bitbang.c
@@ -0,0 +1,472 @@
+/*
+ * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
+ *
+ * This program is free software; you can redistribute 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/init.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support.
+ * Use this for GPIO or shift-register level hardware APIs.
+ *
+ * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
+ * to glue code. These bitbang setup() and cleanup() routines are always
+ * used, though maybe they're called from controller-aware code.
+ *
+ * chipselect() and friends may use use spi_device->controller_data and
+ * controller registers as appropriate.
+ *
+ *
+ * NOTE: SPI controller pins can often be used as GPIO pins instead,
+ * which means you could use a bitbang driver either to get hardware
+ * working quickly, or testing for differences that aren't speed related.
+ */
+
+struct spi_bitbang_cs {
+ unsigned nsecs; /* (clock cycle time)/2 */
+ u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
+ u32 word, u8 bits);
+ unsigned (*txrx_bufs)(struct spi_device *,
+ u32 (*txrx_word)(
+ struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned, struct spi_transfer *);
+};
+
+static unsigned bitbang_txrx_8(
+ struct spi_device *spi,
+ u32 (*txrx_word)(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned ns,
+ struct spi_transfer *t
+) {
+ unsigned bits = spi->bits_per_word;
+ unsigned count = t->len;
+ const u8 *tx = t->tx_buf;
+ u8 *rx = t->rx_buf;
+
+ while (likely(count > 0)) {
+ u8 word = 0;
+
+ if (tx)
+ word = *tx++;
+ word = txrx_word(spi, ns, word, bits);
+ if (rx)
+ *rx++ = word;
+ count -= 1;
+ }
+ return t->len - count;
+}
+
+static unsigned bitbang_txrx_16(
+ struct spi_device *spi,
+ u32 (*txrx_word)(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned ns,
+ struct spi_transfer *t
+) {
+ unsigned bits = spi->bits_per_word;
+ unsigned count = t->len;
+ const u16 *tx = t->tx_buf;
+ u16 *rx = t->rx_buf;
+
+ while (likely(count > 1)) {
+ u16 word = 0;
+
+ if (tx)
+ word = *tx++;
+ word = txrx_word(spi, ns, word, bits);
+ if (rx)
+ *rx++ = word;
+ count -= 2;
+ }
+ return t->len - count;
+}
+
+static unsigned bitbang_txrx_32(
+ struct spi_device *spi,
+ u32 (*txrx_word)(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned ns,
+ struct spi_transfer *t
+) {
+ unsigned bits = spi->bits_per_word;
+ unsigned count = t->len;
+ const u32 *tx = t->tx_buf;
+ u32 *rx = t->rx_buf;
+
+ while (likely(count > 3)) {
+ u32 word = 0;
+
+ if (tx)
+ word = *tx++;
+ word = txrx_word(spi, ns, word, bits);
+ if (rx)
+ *rx++ = word;
+ count -= 4;
+ }
+ return t->len - count;
+}
+
+/**
+ * spi_bitbang_setup - default setup for per-word I/O loops
+ */
+int spi_bitbang_setup(struct spi_device *spi)
+{
+ struct spi_bitbang_cs *cs = spi->controller_state;
+ struct spi_bitbang *bitbang;
+
+ if (!spi->max_speed_hz)
+ return -EINVAL;
+
+ if (!cs) {
+ cs = kzalloc(sizeof *cs, SLAB_KERNEL);
+ if (!cs)
+ return -ENOMEM;
+ spi->controller_state = cs;
+ }
+ bitbang = spi_master_get_devdata(spi->master);
+
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+ /* spi_transfer level calls that work per-word */
+ if (spi->bits_per_word <= 8)
+ cs->txrx_bufs = bitbang_txrx_8;
+ else if (spi->bits_per_word <= 16)
+ cs->txrx_bufs = bitbang_txrx_16;
+ else if (spi->bits_per_word <= 32)
+ cs->txrx_bufs = bitbang_txrx_32;
+ else
+ return -EINVAL;
+
+ /* per-word shift register access, in hardware or bitbanging */
+ cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
+ if (!cs->txrx_word)
+ return -EINVAL;
+
+ /* nsecs = (clock period)/2 */
+ cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
+ if (cs->nsecs > MAX_UDELAY_MS * 1000)
+ return -EINVAL;
+
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
+ __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
+ spi->bits_per_word, 2 * cs->nsecs);
+
+ /* NOTE we _need_ to call chipselect() early, ideally with adapter
+ * setup, unless the hardware defaults cooperate to avoid confusion
+ * between normal (active low) and inverted chipselects.
+ */
+
+ /* deselect chip (low or high) */
+ spin_lock(&bitbang->lock);
+ if (!bitbang->busy) {
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(cs->nsecs);
+ }
+ spin_unlock(&bitbang->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_setup);
+
+/**
+ * spi_bitbang_cleanup - default cleanup for per-word I/O loops
+ */
+void spi_bitbang_cleanup(const struct spi_device *spi)
+{
+ kfree(spi->controller_state);
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
+
+static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct spi_bitbang_cs *cs = spi->controller_state;
+ unsigned nsecs = cs->nsecs;
+
+ return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * SECOND PART ... simple transfer queue runner.
+ *
+ * This costs a task context per controller, running the queue by
+ * performing each transfer in sequence. Smarter hardware can queue
+ * several DMA transfers at once, and process several controller queues
+ * in parallel; this driver doesn't match such hardware very well.
+ *
+ * Drivers can provide word-at-a-time i/o primitives, or provide
+ * transfer-at-a-time ones to leverage dma or fifo hardware.
+ */
+static void bitbang_work(void *_bitbang)
+{
+ struct spi_bitbang *bitbang = _bitbang;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitbang->lock, flags);
+ bitbang->busy = 1;
+ while (!list_empty(&bitbang->queue)) {
+ struct spi_message *m;
+ struct spi_device *spi;
+ unsigned nsecs;
+ struct spi_transfer *t = NULL;
+ unsigned tmp;
+ unsigned cs_change;
+ int status;
+
+ m = container_of(bitbang->queue.next, struct spi_message,
+ queue);
+ list_del_init(&m->queue);
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+
+ /* FIXME this is made-up ... the correct value is known to
+ * word-at-a-time bitbang code, and presumably chipselect()
+ * should enforce these requirements too?
+ */
+ nsecs = 100;
+
+ spi = m->spi;
+ tmp = 0;
+ cs_change = 1;
+ status = 0;
+
+ list_for_each_entry (t, &m->transfers, transfer_list) {
+ if (bitbang->shutdown) {
+ status = -ESHUTDOWN;
+ break;
+ }
+
+ /* set up default clock polarity, and activate chip;
+ * this implicitly updates clock and spi modes as
+ * previously recorded for this device via setup().
+ * (and also deselects any other chip that might be
+ * selected ...)
+ */
+ if (cs_change) {
+ bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
+ ndelay(nsecs);
+ }
+ cs_change = t->cs_change;
+ if (!t->tx_buf && !t->rx_buf && t->len) {
+ status = -EINVAL;
+ break;
+ }
+
+ /* transfer data. the lower level code handles any
+ * new dma mappings it needs. our caller always gave
+ * us dma-safe buffers.
+ */
+ if (t->len) {
+ /* REVISIT dma API still needs a designated
+ * DMA_ADDR_INVALID; ~0 might be better.
+ */
+ if (!m->is_dma_mapped)
+ t->rx_dma = t->tx_dma = 0;
+ status = bitbang->txrx_bufs(spi, t);
+ }
+ if (status != t->len) {
+ if (status > 0)
+ status = -EMSGSIZE;
+ break;
+ }
+ m->actual_length += status;
+ status = 0;
+
+ /* protocol tweaks before next transfer */
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
+
+ if (!cs_change)
+ continue;
+ if (t->transfer_list.next == &m->transfers)
+ break;
+
+ /* sometimes a short mid-message deselect of the chip
+ * may be needed to terminate a mode or command
+ */
+ ndelay(nsecs);
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(nsecs);
+ }
+
+ m->status = status;
+ m->complete(m->context);
+
+ /* normally deactivate chipselect ... unless no error and
+ * cs_change has hinted that the next message will probably
+ * be for this chip too.
+ */
+ if (!(status == 0 && cs_change)) {
+ ndelay(nsecs);
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(nsecs);
+ }
+
+ spin_lock_irqsave(&bitbang->lock, flags);
+ }
+ bitbang->busy = 0;
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+}
+
+/**
+ * spi_bitbang_transfer - default submit to transfer queue
+ */
+int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
+{
+ struct spi_bitbang *bitbang;
+ unsigned long flags;
+
+ m->actual_length = 0;
+ m->status = -EINPROGRESS;
+
+ bitbang = spi_master_get_devdata(spi->master);
+ if (bitbang->shutdown)
+ return -ESHUTDOWN;
+
+ spin_lock_irqsave(&bitbang->lock, flags);
+ list_add_tail(&m->queue, &bitbang->queue);
+ queue_work(bitbang->workqueue, &bitbang->work);
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
+
+/*----------------------------------------------------------------------*/
+
+/**
+ * spi_bitbang_start - start up a polled/bitbanging SPI master driver
+ * @bitbang: driver handle
+ *
+ * Caller should have zero-initialized all parts of the structure, and then
+ * provided callbacks for chip selection and I/O loops. If the master has
+ * a transfer method, its final step should call spi_bitbang_transfer; or,
+ * that's the default if the transfer routine is not initialized. It should
+ * also set up the bus number and number of chipselects.
+ *
+ * For i/o loops, provide callbacks either per-word (for bitbanging, or for
+ * hardware that basically exposes a shift register) or per-spi_transfer
+ * (which takes better advantage of hardware like fifos or DMA engines).
+ *
+ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and
+ * spi_bitbang_cleanup to handle those spi master methods. Those methods are
+ * the defaults if the bitbang->txrx_bufs routine isn't initialized.
+ *
+ * This routine registers the spi_master, which will process requests in a
+ * dedicated task, keeping IRQs unblocked most of the time. To stop
+ * processing those requests, call spi_bitbang_stop().
+ */
+int spi_bitbang_start(struct spi_bitbang *bitbang)
+{
+ int status;
+
+ if (!bitbang->master || !bitbang->chipselect)
+ return -EINVAL;
+
+ INIT_WORK(&bitbang->work, bitbang_work, bitbang);
+ spin_lock_init(&bitbang->lock);
+ INIT_LIST_HEAD(&bitbang->queue);
+
+ if (!bitbang->master->transfer)
+ bitbang->master->transfer = spi_bitbang_transfer;
+ if (!bitbang->txrx_bufs) {
+ bitbang->use_dma = 0;
+ bitbang->txrx_bufs = spi_bitbang_bufs;
+ if (!bitbang->master->setup) {
+ bitbang->master->setup = spi_bitbang_setup;
+ bitbang->master->cleanup = spi_bitbang_cleanup;
+ }
+ } else if (!bitbang->master->setup)
+ return -EINVAL;
+
+ /* this task is the only thing to touch the SPI bits */
+ bitbang->busy = 0;
+ bitbang->workqueue = create_singlethread_workqueue(
+ bitbang->master->cdev.dev->bus_id);
+ if (bitbang->workqueue == NULL) {
+ status = -EBUSY;
+ goto err1;
+ }
+
+ /* driver may get busy before register() returns, especially
+ * if someone registered boardinfo for devices
+ */
+ status = spi_register_master(bitbang->master);
+ if (status < 0)
+ goto err2;
+
+ return status;
+
+err2:
+ destroy_workqueue(bitbang->workqueue);
+err1:
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_start);
+
+/**
+ * spi_bitbang_stop - stops the task providing spi communication
+ */
+int spi_bitbang_stop(struct spi_bitbang *bitbang)
+{
+ unsigned limit = 500;
+
+ spin_lock_irq(&bitbang->lock);
+ bitbang->shutdown = 0;
+ while (!list_empty(&bitbang->queue) && limit--) {
+ spin_unlock_irq(&bitbang->lock);
+
+ dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
+ msleep(10);
+
+ spin_lock_irq(&bitbang->lock);
+ }
+ spin_unlock_irq(&bitbang->lock);
+ if (!list_empty(&bitbang->queue)) {
+ dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
+ return -EBUSY;
+ }
+
+ destroy_workqueue(bitbang->workqueue);
+
+ spi_unregister_master(bitbang->master);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_stop);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
new file mode 100644
index 000000000000..79a3c59615ab
--- /dev/null
+++ b/drivers/spi/spi_butterfly.c
@@ -0,0 +1,423 @@
+/*
+ * spi_butterfly.c - parport-to-butterfly adapter
+ *
+ * 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.
+ *
+ * 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/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/parport.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/flash.h>
+
+#include <linux/mtd/partitions.h>
+
+
+/*
+ * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
+ * with a battery powered AVR microcontroller and lots of goodies. You
+ * can use GCC to develop firmware for this.
+ *
+ * See Documentation/spi/butterfly for information about how to build
+ * and use this custom parallel port cable.
+ */
+
+#undef HAVE_USI /* nyet */
+
+
+/* DATA output bits (pins 2..9 == D0..D7) */
+#define butterfly_nreset (1 << 1) /* pin 3 */
+
+#define spi_sck_bit (1 << 0) /* pin 2 */
+#define spi_mosi_bit (1 << 7) /* pin 9 */
+
+#define usi_sck_bit (1 << 3) /* pin 5 */
+#define usi_mosi_bit (1 << 4) /* pin 6 */
+
+#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */
+
+/* STATUS input bits */
+#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */
+
+#define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */
+
+/* CONTROL output bits */
+#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */
+/* USI uses no chipselect */
+
+
+
+static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
+{
+ return spi->controller_data;
+}
+
+static inline int is_usidev(struct spi_device *spi)
+{
+#ifdef HAVE_USI
+ return spi->chip_select != 1;
+#else
+ return 0;
+#endif
+}
+
+
+struct butterfly {
+ /* REVISIT ... for now, this must be first */
+ struct spi_bitbang bitbang;
+
+ struct parport *port;
+ struct pardevice *pd;
+
+ u8 lastbyte;
+
+ struct spi_device *dataflash;
+ struct spi_device *butterfly;
+ struct spi_board_info info[2];
+
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * these routines may be slower than necessary because they're hiding
+ * the fact that there are two different SPI busses on this cable: one
+ * to the DataFlash chip (or AVR SPI controller), the other to the
+ * AVR USI controller.
+ */
+
+static inline void
+setsck(struct spi_device *spi, int is_on)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+ u8 bit, byte = pp->lastbyte;
+
+ if (is_usidev(spi))
+ bit = usi_sck_bit;
+ else
+ bit = spi_sck_bit;
+
+ if (is_on)
+ byte |= bit;
+ else
+ byte &= ~bit;
+ parport_write_data(pp->port, byte);
+ pp->lastbyte = byte;
+}
+
+static inline void
+setmosi(struct spi_device *spi, int is_on)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+ u8 bit, byte = pp->lastbyte;
+
+ if (is_usidev(spi))
+ bit = usi_mosi_bit;
+ else
+ bit = spi_mosi_bit;
+
+ if (is_on)
+ byte |= bit;
+ else
+ byte &= ~bit;
+ parport_write_data(pp->port, byte);
+ pp->lastbyte = byte;
+}
+
+static inline int getmiso(struct spi_device *spi)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+ int value;
+ u8 bit;
+
+ if (is_usidev(spi))
+ bit = usi_miso_bit;
+ else
+ bit = spi_miso_bit;
+
+ /* only STATUS_BUSY is NOT negated */
+ value = !(parport_read_status(pp->port) & bit);
+ return (bit == PARPORT_STATUS_BUSY) ? value : !value;
+}
+
+static void butterfly_chipselect(struct spi_device *spi, int value)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+
+ /* set default clock polarity */
+ if (value)
+ setsck(spi, spi->mode & SPI_CPOL);
+
+ /* no chipselect on this USI link config */
+ if (is_usidev(spi))
+ return;
+
+ /* here, value == "activate or not" */
+
+ /* most PARPORT_CONTROL_* bits are negated */
+ if (spi_cs_bit == PARPORT_CONTROL_INIT)
+ value = !value;
+
+ /* here, value == "bit value to write in control register" */
+
+ parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
+}
+
+
+/* we only needed to implement one mode here, and choose SPI_MODE_0 */
+
+#define spidelay(X) do{}while(0)
+//#define spidelay ndelay
+
+#define EXPAND_BITBANG_TXRX
+#include <linux/spi/spi_bitbang.h>
+
+static u32
+butterfly_txrx_word_mode0(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* override default partitioning with cmdlinepart */
+static struct mtd_partition partitions[] = { {
+ /* JFFS2 wants partitions of 4*N blocks for this device ... */
+
+ /* sector 0 = 8 pages * 264 bytes/page (1 block)
+ * sector 1 = 248 pages * 264 bytes/page
+ */
+ .name = "bookkeeping", // 66 KB
+ .offset = 0,
+ .size = (8 + 248) * 264,
+// .mask_flags = MTD_WRITEABLE,
+}, {
+ /* sector 2 = 256 pages * 264 bytes/page
+ * sectors 3-5 = 512 pages * 264 bytes/page
+ */
+ .name = "filesystem", // 462 KB
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+} };
+
+static struct flash_platform_data flash = {
+ .name = "butterflash",
+ .parts = partitions,
+ .nr_parts = ARRAY_SIZE(partitions),
+};
+
+
+/* REVISIT remove this ugly global and its "only one" limitation */
+static struct butterfly *butterfly;
+
+static void butterfly_attach(struct parport *p)
+{
+ struct pardevice *pd;
+ int status;
+ struct butterfly *pp;
+ struct spi_master *master;
+ struct platform_device *pdev;
+
+ if (butterfly)
+ return;
+
+ /* REVISIT: this just _assumes_ a butterfly is there ... no probe,
+ * and no way to be selective about what it binds to.
+ */
+
+ /* FIXME where should master->cdev.dev come from?
+ * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc
+ * setting up a platform device like this is an ugly kluge...
+ */
+ pdev = platform_device_register_simple("butterfly", -1, NULL, 0);
+
+ master = spi_alloc_master(&pdev->dev, sizeof *pp);
+ if (!master) {
+ status = -ENOMEM;
+ goto done;
+ }
+ pp = spi_master_get_devdata(master);
+
+ /*
+ * SPI and bitbang hookup
+ *
+ * use default setup(), cleanup(), and transfer() methods; and
+ * only bother implementing mode 0. Start it later.
+ */
+ master->bus_num = 42;
+ master->num_chipselect = 2;
+
+ pp->bitbang.master = spi_master_get(master);
+ pp->bitbang.chipselect = butterfly_chipselect;
+ pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
+
+ /*
+ * parport hookup
+ */
+ pp->port = p;
+ pd = parport_register_device(p, "spi_butterfly",
+ NULL, NULL, NULL,
+ 0 /* FLAGS */, pp);
+ if (!pd) {
+ status = -ENOMEM;
+ goto clean0;
+ }
+ pp->pd = pd;
+
+ status = parport_claim(pd);
+ if (status < 0)
+ goto clean1;
+
+ /*
+ * Butterfly reset, powerup, run firmware
+ */
+ pr_debug("%s: powerup/reset Butterfly\n", p->name);
+
+ /* nCS for dataflash (this bit is inverted on output) */
+ parport_frob_control(pp->port, spi_cs_bit, 0);
+
+ /* stabilize power with chip in reset (nRESET), and
+ * both spi_sck_bit and usi_sck_bit clear (CPOL=0)
+ */
+ pp->lastbyte |= vcc_bits;
+ parport_write_data(pp->port, pp->lastbyte);
+ msleep(5);
+
+ /* take it out of reset; assume long reset delay */
+ pp->lastbyte |= butterfly_nreset;
+ parport_write_data(pp->port, pp->lastbyte);
+ msleep(100);
+
+
+ /*
+ * Start SPI ... for now, hide that we're two physical busses.
+ */
+ status = spi_bitbang_start(&pp->bitbang);
+ if (status < 0)
+ goto clean2;
+
+ /* Bus 1 lets us talk to at45db041b (firmware disables AVR)
+ * or AVR (firmware resets at45, acts as spi slave)
+ */
+ pp->info[0].max_speed_hz = 15 * 1000 * 1000;
+ strcpy(pp->info[0].modalias, "mtd_dataflash");
+ pp->info[0].platform_data = &flash;
+ pp->info[0].chip_select = 1;
+ pp->info[0].controller_data = pp;
+ pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
+ if (pp->dataflash)
+ pr_debug("%s: dataflash at %s\n", p->name,
+ pp->dataflash->dev.bus_id);
+
+#ifdef HAVE_USI
+ /* even more custom AVR firmware */
+ pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
+ strcpy(pp->info[1].modalias, "butterfly");
+ // pp->info[1].platform_data = ... TBD ... ;
+ pp->info[1].chip_select = 2,
+ pp->info[1].controller_data = pp;
+ pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]);
+ if (pp->butterfly)
+ pr_debug("%s: butterfly at %s\n", p->name,
+ pp->butterfly->dev.bus_id);
+
+ /* FIXME setup ACK for the IRQ line ... */
+#endif
+
+ // dev_info(_what?_, ...)
+ pr_info("%s: AVR Butterfly\n", p->name);
+ butterfly = pp;
+ return;
+
+clean2:
+ /* turn off VCC */
+ parport_write_data(pp->port, 0);
+
+ parport_release(pp->pd);
+clean1:
+ parport_unregister_device(pd);
+clean0:
+ (void) spi_master_put(pp->bitbang.master);
+done:
+ platform_device_unregister(pdev);
+ pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
+}
+
+static void butterfly_detach(struct parport *p)
+{
+ struct butterfly *pp;
+ struct platform_device *pdev;
+ int status;
+
+ /* FIXME this global is ugly ... but, how to quickly get from
+ * the parport to the "struct butterfly" associated with it?
+ * "old school" driver-internal device lists?
+ */
+ if (!butterfly || butterfly->port != p)
+ return;
+ pp = butterfly;
+ butterfly = NULL;
+
+#ifdef HAVE_USI
+ spi_unregister_device(pp->butterfly);
+ pp->butterfly = NULL;
+#endif
+ spi_unregister_device(pp->dataflash);
+ pp->dataflash = NULL;
+
+ status = spi_bitbang_stop(&pp->bitbang);
+
+ /* turn off VCC */
+ parport_write_data(pp->port, 0);
+ msleep(10);
+
+ parport_release(pp->pd);
+ parport_unregister_device(pp->pd);
+
+ pdev = to_platform_device(pp->bitbang.master->cdev.dev);
+
+ (void) spi_master_put(pp->bitbang.master);
+
+ platform_device_unregister(pdev);
+}
+
+static struct parport_driver butterfly_driver = {
+ .name = "spi_butterfly",
+ .attach = butterfly_attach,
+ .detach = butterfly_detach,
+};
+
+
+static int __init butterfly_init(void)
+{
+ return parport_register_driver(&butterfly_driver);
+}
+device_initcall(butterfly_init);
+
+static void __exit butterfly_exit(void)
+{
+ parport_unregister_driver(&butterfly_driver);
+}
+module_exit(butterfly_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index b28336148658..c1b47d74e206 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -532,9 +532,9 @@ static void speedtch_handle_int(struct urb *int_urb, struct pt_regs *regs)
int ret = int_urb->status;
/* The magic interrupt for "up state" */
- const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
+ static const unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
/* The magic interrupt for "down state" */
- const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
atm_dbg(usbatm, "%s entered\n", __func__);
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 9baa6296fc95..7af1883d4bf9 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -207,7 +207,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
** urbs **
************/
-static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
+static struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
{
struct urb *urb;
@@ -224,7 +224,7 @@ static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
return urb;
}
-static inline int usbatm_submit_urb(struct urb *urb)
+static int usbatm_submit_urb(struct urb *urb)
{
struct usbatm_channel *channel = urb->context;
int ret;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 248279e44c99..b9fd39fd1b5b 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -335,14 +335,9 @@ next_buffer:
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
- for (i = 0; i < buf->size && !acm->throttle; i++) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters,
- we drop them. */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- tty_insert_flip_char(tty, buf->base[i], 0);
- }
+ tty_buffer_request_room(tty, buf->size);
+ if (!acm->throttle)
+ tty_insert_flip_string(tty, buf->base, buf->size);
tty_flip_buffer_push(tty);
spin_lock(&acm->throttle_lock);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index c44bbedec817..3cf945cc5b9a 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -184,13 +184,13 @@ static void update_bus(struct dentry *bus)
bus->d_inode->i_gid = busgid;
bus->d_inode->i_mode = S_IFDIR | busmode;
- down(&bus->d_inode->i_sem);
+ mutex_lock(&bus->d_inode->i_mutex);
- list_for_each_entry(dev, &bus->d_subdirs, d_child)
+ list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child)
if (dev->d_inode)
update_dev(dev);
- up(&bus->d_inode->i_sem);
+ mutex_unlock(&bus->d_inode->i_mutex);
}
static void update_sb(struct super_block *sb)
@@ -201,9 +201,9 @@ static void update_sb(struct super_block *sb)
if (!root)
return;
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
- list_for_each_entry(bus, &root->d_subdirs, d_child) {
+ list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) {
if (bus->d_inode) {
switch (S_IFMT & bus->d_inode->i_mode) {
case S_IFDIR:
@@ -219,7 +219,7 @@ static void update_sb(struct super_block *sb)
}
}
- up(&root->d_inode->i_sem);
+ mutex_unlock(&root->d_inode->i_mutex);
}
static int remount(struct super_block *sb, int *flags, char *data)
@@ -319,7 +319,7 @@ static int usbfs_empty (struct dentry *dentry)
spin_lock(&dcache_lock);
list_for_each(list, &dentry->d_subdirs) {
- struct dentry *de = list_entry(list, struct dentry, d_child);
+ struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
if (usbfs_positive(de)) {
spin_unlock(&dcache_lock);
return 0;
@@ -333,10 +333,10 @@ static int usbfs_empty (struct dentry *dentry)
static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
dentry->d_inode->i_nlink--;
dput(dentry);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
d_delete(dentry);
return 0;
}
@@ -346,7 +346,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
int error = -ENOTEMPTY;
struct inode * inode = dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
dentry_unhash(dentry);
if (usbfs_empty(dentry)) {
dentry->d_inode->i_nlink -= 2;
@@ -355,7 +355,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
dir->i_nlink--;
error = 0;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (!error)
d_delete(dentry);
dput(dentry);
@@ -380,7 +380,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
{
loff_t retval = -EINVAL;
- down(&file->f_dentry->d_inode->i_sem);
+ mutex_lock(&file->f_dentry->d_inode->i_mutex);
switch(orig) {
case 0:
if (offset > 0) {
@@ -397,7 +397,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
default:
break;
}
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return retval;
}
@@ -480,7 +480,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
}
*dentry = NULL;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
@@ -489,7 +489,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
error = usbfs_create (parent->d_inode, *dentry, mode);
} else
error = PTR_ERR(dentry);
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
return error;
}
@@ -528,7 +528,7 @@ static void fs_remove_file (struct dentry *dentry)
if (!parent || !parent->d_inode)
return;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
if (usbfs_positive(dentry)) {
if (dentry->d_inode) {
if (S_ISDIR(dentry->d_inode->i_mode))
@@ -538,7 +538,7 @@ static void fs_remove_file (struct dentry *dentry)
dput(dentry);
}
}
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
}
/* --------------------------------------------------------------------- */
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8f402f85e1ca..afc84cfb61f9 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2534,9 +2534,6 @@ 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 0cea9782d7d4..de59c58896d6 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1891,7 +1891,7 @@ static int fsync_sub(struct lun *curlun)
return -EINVAL;
inode = filp->f_dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
current->flags |= PF_SYNCWRITE;
rc = filemap_fdatawrite(inode->i_mapping);
err = filp->f_op->fsync(filp, filp->f_dentry, 1);
@@ -1901,7 +1901,7 @@ static int fsync_sub(struct lun *curlun)
if (!rc)
rc = err;
current->flags &= ~PF_SYNCWRITE;
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
VLDBG(curlun, "fdatasync -> %d\n", rc);
return rc;
}
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 5c40980a5bd9..9a4edc5657aa 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1562,10 +1562,10 @@ restart:
spin_unlock_irq (&dev->lock);
/* break link to dcache */
- down (&parent->i_sem);
+ mutex_lock (&parent->i_mutex);
d_delete (dentry);
dput (dentry);
- up (&parent->i_sem);
+ mutex_unlock (&parent->i_mutex);
/* fds may still be open */
goto restart;
@@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs_driver = {
.driver = {
.name = (char *) shortname,
- // .shutdown = ...
- // .suspend = ...
- // .resume = ...
},
};
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 65e084a2c87e..ba9acd531024 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadget_driver = {
.disconnect = gs_disconnect,
.driver = {
.name = GS_SHORT_NAME,
- /* .shutdown = ... */
- /* .suspend = ... */
- /* .resume = ... */
},
};
@@ -1271,6 +1268,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
unsigned int len;
struct gs_port *port;
int ret;
+ struct tty_struct *tty;
/* TEMPORARY -- only port 0 is supported right now */
port = dev->dev_port[0];
@@ -1290,7 +1288,10 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
goto exit;
}
- if (port->port_tty == NULL) {
+
+ tty = port->port_tty;
+
+ if (tty == NULL) {
printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
port->port_num);
ret = -EIO;
@@ -1304,20 +1305,13 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
goto exit;
}
- len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count);
- if (len < size)
- size = len;
-
- if (size > 0) {
- memcpy(port->port_tty->flip.char_buf_ptr, packet, size);
- port->port_tty->flip.char_buf_ptr += size;
- port->port_tty->flip.count += size;
+ len = tty_buffer_request_room(tty, size);
+ if (len > 0) {
+ tty_insert_flip_string(tty, packet, len);
tty_flip_buffer_push(port->port_tty);
wake_up_interruptible(&port->port_tty->read_wait);
}
-
ret = 0;
-
exit:
spin_unlock(&port->port_lock);
return ret;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 6c58636e914b..2fc110d3ad5a 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_driver = {
.driver = {
.name = (char *) shortname,
.owner = THIS_MODULE,
- // .shutdown = ...
- // .suspend = ...
- // .resume = ...
},
};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ed1899d307db..be3fd9bce573 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -11,14 +11,14 @@ config USB_EHCI_HCD
The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
"high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
If your USB host controller supports USB 2.0, you will likely want to
- configure this Host Controller Driver. At this writing, the primary
- implementation of EHCI is a chip from NEC, widely available in add-on
- PCI cards, but implementations are in the works from other vendors
- including Intel and Philips. Motherboard support is appearing.
+ configure this Host Controller Driver. At the time of this writing,
+ the primary implementation of EHCI is a chip from NEC, widely available
+ in add-on PCI cards, but implementations are in the works from other
+ vendors including Intel and Philips. Motherboard support is appearing.
EHCI controllers are packaged with "companion" host controllers (OHCI
or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports
- will connect to EHCI if it the device is high speed, otherwise they
+ will connect to EHCI if the device is high speed, otherwise they
connect to a companion controller. If you configure EHCI, you should
probably configure the OHCI (for NEC and some other vendors) USB Host
Controller Driver or UHCI (for Via motherboards) Host Controller
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index d9cf3b327d96..77cd6ac07e3c 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -19,6 +19,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/signal.h>
#include <asm/mach-au1x00/au1000.h>
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 3959ccc88332..0020ed7a39d0 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -17,6 +17,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/signal.h>
#include <asm/hardware.h>
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index c9e29d808711..3785b3f7df1b 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -17,6 +17,7 @@
#include <linux/signal.h> /* SA_INTERRUPT */
#include <linux/jiffies.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -27,7 +28,6 @@
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include <asm/arch/usb.h>
-#include <asm/hardware/clock.h>
/* OMAP-1510 OHCI has its own MMU for DMA */
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 2ec6a78bd65e..b2a8dfa48870 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -15,6 +15,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/signal.h>
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 35cc9402adc0..372527a83593 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -20,9 +20,9 @@
*/
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/usb-control.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
@@ -363,7 +363,6 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
goto err1;
}
- clk_use(clk);
s3c2410_start_hc(dev, hcd);
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
@@ -384,7 +383,6 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
err2:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
- clk_unuse(clk);
clk_put(clk);
err1:
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 458f2acdeb0a..28538db9eaf3 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -674,7 +674,7 @@ struct vendor_product
/* These are taken from the msmUSB.inf file on the Windows driver CD */
-const static struct vendor_product mts_supported_products[] =
+static const struct vendor_product mts_supported_products[] =
{
{ "Phantom 336CX", mts_sup_unknown},
{ "Phantom 336CX", mts_sup_unknown},
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 509dd0a04c54..5246b35301de 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -37,6 +37,16 @@ config USB_HIDINPUT
If unsure, say Y.
+config USB_HIDINPUT_POWERBOOK
+ bool "Enable support for iBook/PowerBook special keys"
+ default n
+ depends on USB_HIDINPUT
+ help
+ Say Y here if you want support for the special keys (Fn, Numlock) on
+ Apple iBooks and PowerBooks.
+
+ If unsure, say N.
+
config HID_FF
bool "Force feedback support (EXPERIMENTAL)"
depends on USB_HIDINPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 1949b54f41f2..c222ed13deab 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -6,6 +6,7 @@
* 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)
+ * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
*
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
*
@@ -38,6 +39,11 @@
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID 0x05AC
+/* These names come from Info.plist in AppleUSBTrackpad.kext */
+#define GEYSER_ANSI_PRODUCT_ID 0x0214
+#define GEYSER_ISO_PRODUCT_ID 0x0215
+#define GEYSER_JIS_PRODUCT_ID 0x0216
+
#define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
@@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = {
{ ATP_DEVICE(0x020F) },
{ ATP_DEVICE(0x030A) },
{ ATP_DEVICE(0x030B) },
- { } /* Terminating entry */
+
+ /* PowerBooks Oct 2005 */
+ { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+
+ /* 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
@@ -108,6 +118,8 @@ struct atp {
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
/* accumulated sensors */
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+ int overflowwarn; /* overflow warning printed? */
+ int datalen; /* size of an USB urb transfer */
};
#define dbg_dump(msg, tab) \
@@ -124,7 +136,7 @@ struct atp {
if (debug) printk(format, ##a); \
} while (0)
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
MODULE_LICENSE("GPL");
@@ -132,6 +144,16 @@ static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
+/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
+static inline int atp_is_geyser_2(struct atp *dev)
+{
+ int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+ return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER_ISO_PRODUCT_ID) ||
+ (productId == GEYSER_JIS_PRODUCT_ID);
+}
+
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
int *z, int *fingers)
{
@@ -168,13 +190,20 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
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;
+ int retval, i, j;
struct atp *dev = urb->context;
switch (urb->status) {
case 0:
/* success */
break;
+ case -EOVERFLOW:
+ if(!dev->overflowwarn) {
+ printk("appletouch: OVERFLOW with data "
+ "length %d, actual length is %d\n",
+ dev->datalen, dev->urb->actual_length);
+ dev->overflowwarn = 1;
+ }
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
@@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
}
/* drop incomplete datasets */
- if (dev->urb->actual_length != ATP_DATASIZE) {
+ if (dev->urb->actual_length != dev->datalen) {
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];
+ if (atp_is_geyser_2(dev)) {
+ memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+ /*
+ * The values are laid out like this:
+ * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ...
+ * '-' is an unused value.
+ */
+
+ /* read X values */
+ for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+ dev->xy_cur[i] = dev->data[j];
+ dev->xy_cur[i + 1] = dev->data[j + 1];
+ }
+
+ /* read Y values */
+ for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+ dev->xy_cur[ATP_XSENSORS + i] = dev->data[j];
+ dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1];
+ }
+ } else {
+ 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);
@@ -216,16 +267,24 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
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");
+ /* 17" Powerbooks have extra X sensors */
+ for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+ if (!dev->xy_cur[i]) continue;
+
+ printk("appletouch: 17\" model detected.\n");
+ if(atp_is_geyser_2(dev))
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (20 - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ else
input_set_abs_params(dev->input, ABS_X, 0,
(ATP_XSENSORS - 1) *
ATP_XFACT - 1,
ATP_FUZZ, 0);
- break;
- }
+
+ break;
+ }
goto exit;
}
@@ -282,7 +341,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
}
- input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
+ input_report_key(dev->input, BTN_LEFT,
+ !!dev->data[dev->datalen - 1]);
input_sync(dev->input);
@@ -353,6 +413,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
dev->udev = udev;
dev->input = input_dev;
+ dev->overflowwarn = 0;
+ dev->datalen = (atp_is_geyser_2(dev)?64:81);
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) {
@@ -360,7 +422,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
goto err_free_devs;
}
- dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+ dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data) {
retval = -ENOMEM;
@@ -369,7 +431,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
usb_fill_int_urb(dev->urb, udev,
usb_rcvintpipe(udev, int_in_endpointAddr),
- dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+ dev->data, dev->datalen, atp_complete, dev, 1);
usb_make_path(udev, dev->phys, sizeof(dev->phys));
strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +447,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
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);
+ if (atp_is_geyser_2(dev)) {
+ /*
+ * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+ * later.
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+ } else {
+ /*
+ * 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);
@@ -427,7 +500,7 @@ static void atp_disconnect(struct usb_interface *iface)
usb_kill_urb(dev->urb);
input_unregister_device(dev->input);
usb_free_urb(dev->urb);
- usb_buffer_free(dev->udev, ATP_DATASIZE,
+ usb_buffer_free(dev->udev, dev->datalen,
dev->data, dev->urb->transfer_dma);
kfree(dev);
}
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 5f52979af1c7..a91e72c41415 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
+#define USB_VENDOR_ID_CHERRY 0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
+
/*
* Alphabetically sorted blacklist by quirk type.
*/
@@ -1580,6 +1583,16 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
+
+ { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+
{ 0, 0 }
};
@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
}
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+
+static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+ if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+ info("Fixing up Cherry Cymotion report descriptor");
+ rdesc[11] = rdesc[16] = 0xff;
+ rdesc[12] = rdesc[17] = 0x03;
+ }
+}
+
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return NULL;
}
+ if ((quirks & HID_QUIRK_CYMOTION))
+ hid_fixup_cymotion_descriptor(rdesc, rsize);
+
#ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index ceebab99eff2..702c48c2f81b 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -681,6 +681,21 @@ static char *keys[KEY_MAX + 1] = {
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
[KEY_DOCUMENTS] = "Documents",
+ [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
+ [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
+ [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
+ [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F",
+ [KEY_FN_S] = "Fn+S",
+ [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2",
+ [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4",
+ [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6",
+ [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8",
+ [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10",
+ [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12",
+ [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
+ [KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
+ [KEY_KBDILLUMUP] = "KbdIlluminationUp",
+ [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
};
static char *relatives[REL_MAX + 1] = {
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 192a03b28971..cb0d80f49252 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -73,6 +73,160 @@ static const struct {
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0)
+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+
+struct hidinput_key_translation {
+ u16 from;
+ u16 to;
+ u8 flags;
+};
+
+#define POWERBOOK_FLAG_FKEY 0x01
+
+static struct hidinput_key_translation powerbook_fn_keys[] = {
+ { KEY_BACKSPACE, KEY_DELETE },
+ { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
+ { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
+ { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
+ { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
+ { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
+ { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
+ { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
+ { KEY_UP, KEY_PAGEUP },
+ { KEY_DOWN, KEY_PAGEDOWN },
+ { KEY_LEFT, KEY_HOME },
+ { KEY_RIGHT, KEY_END },
+ { }
+};
+
+static struct hidinput_key_translation powerbook_numlock_keys[] = {
+ { KEY_J, KEY_KP1 },
+ { KEY_K, KEY_KP2 },
+ { KEY_L, KEY_KP3 },
+ { KEY_U, KEY_KP4 },
+ { KEY_I, KEY_KP5 },
+ { KEY_O, KEY_KP6 },
+ { KEY_7, KEY_KP7 },
+ { KEY_8, KEY_KP8 },
+ { KEY_9, KEY_KP9 },
+ { KEY_M, KEY_KP0 },
+ { KEY_DOT, KEY_KPDOT },
+ { KEY_SLASH, KEY_KPPLUS },
+ { KEY_SEMICOLON, KEY_KPMINUS },
+ { KEY_P, KEY_KPASTERISK },
+ { KEY_MINUS, KEY_KPEQUAL },
+ { KEY_0, KEY_KPSLASH },
+ { KEY_F6, KEY_NUMLOCK },
+ { KEY_KPENTER, KEY_KPENTER },
+ { KEY_BACKSPACE, KEY_BACKSPACE },
+ { }
+};
+
+static int usbhid_pb_fnmode = 1;
+module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
+MODULE_PARM_DESC(pb_fnmode,
+ "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
+
+static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
+{
+ struct hidinput_key_translation *trans;
+
+ /* Look for the translation */
+ for (trans = table; trans->from; trans++)
+ if (trans->from == from)
+ return trans;
+
+ return NULL;
+}
+
+static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+ struct hid_usage *usage, __s32 value)
+{
+ struct hidinput_key_translation *trans;
+
+ if (usage->code == KEY_FN) {
+ if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
+ else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
+
+ input_event(input, usage->type, usage->code, value);
+
+ return 1;
+ }
+
+ if (usbhid_pb_fnmode) {
+ int do_translate;
+
+ trans = find_translation(powerbook_fn_keys, usage->code);
+ if (trans) {
+ if (test_bit(usage->code, hid->pb_pressed_fn))
+ do_translate = 1;
+ else if (trans->flags & POWERBOOK_FLAG_FKEY)
+ do_translate =
+ (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
+ (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
+ else
+ do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
+
+ if (do_translate) {
+ if (value)
+ set_bit(usage->code, hid->pb_pressed_fn);
+ else
+ clear_bit(usage->code, hid->pb_pressed_fn);
+
+ input_event(input, usage->type, trans->to, value);
+
+ return 1;
+ }
+ }
+
+ if (test_bit(usage->code, hid->pb_pressed_numlock) ||
+ test_bit(LED_NUML, input->led)) {
+ trans = find_translation(powerbook_numlock_keys, usage->code);
+
+ if (trans) {
+ if (value)
+ set_bit(usage->code, hid->pb_pressed_numlock);
+ else
+ clear_bit(usage->code, hid->pb_pressed_numlock);
+
+ input_event(input, usage->type, trans->to, value);
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void hidinput_pb_setup(struct input_dev *input)
+{
+ struct hidinput_key_translation *trans;
+
+ set_bit(KEY_NUMLOCK, input->keybit);
+
+ /* Enable all needed keys */
+ for (trans = powerbook_fn_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+
+ for (trans = powerbook_numlock_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+}
+#else
+static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+ struct hid_usage *usage, __s32 value)
+{
+ return 0;
+}
+
+static inline void hidinput_pb_setup(struct input_dev *input)
+{
+}
+#endif
+
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage)
{
@@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_UP_SIMULATION:
switch (usage->hid & 0xffff) {
- case 0xba: map_abs(ABS_RUDDER); break;
+ case 0xba: map_abs(ABS_RUDDER); break;
case 0xbb: map_abs(ABS_THROTTLE); break;
+ case 0xc4: map_abs(ABS_GAS); break;
+ case 0xc5: map_abs(ABS_BRAKE); break;
+ case 0xc8: map_abs(ABS_WHEEL); break;
default: goto ignore;
}
break;
@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x226: map_key_clear(KEY_STOP); break;
case 0x227: map_key_clear(KEY_REFRESH); break;
case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
+ case 0x233: map_key_clear(KEY_SCROLLUP); break;
+ case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
case 0x238: map_rel(REL_HWHEEL); break;
case 0x279: map_key_clear(KEY_REDO); break;
case 0x289: map_key_clear(KEY_REPLY); break;
case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
case 0x28c: map_key_clear(KEY_SEND); break;
+
+ /* Reported on a Cherry Cymotion keyboard */
+ case 0x301: map_key_clear(KEY_PROG1); break;
+ case 0x302: map_key_clear(KEY_PROG2); break;
+ case 0x303: map_key_clear(KEY_PROG3); break;
+
default: goto ignore;
}
break;
@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) {
- case 0x003: map_key_clear(KEY_FN); break;
+ case 0x003:
+ /* The fn key on Apple PowerBooks */
+ map_key_clear(KEY_FN);
+ hidinput_pb_setup(input);
+ break;
+
default: goto ignore;
}
break;
@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
}
+ if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
+ return;
+
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
}
- if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
+ if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return;
input_event(input, usage->type, usage->code, value);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index ee48a2276104..8b0d4346ce9c 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -235,17 +235,20 @@ struct hid_item {
* HID device quirks.
*/
-#define HID_QUIRK_INVERT 0x001
-#define HID_QUIRK_NOTOUCH 0x002
-#define HID_QUIRK_IGNORE 0x004
-#define HID_QUIRK_NOGET 0x008
-#define HID_QUIRK_HIDDEV 0x010
-#define HID_QUIRK_BADPAD 0x020
-#define HID_QUIRK_MULTI_INPUT 0x040
-#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
+#define HID_QUIRK_INVERT 0x00000001
+#define HID_QUIRK_NOTOUCH 0x00000002
+#define HID_QUIRK_IGNORE 0x00000004
+#define HID_QUIRK_NOGET 0x00000008
+#define HID_QUIRK_HIDDEV 0x00000010
+#define HID_QUIRK_BADPAD 0x00000020
+#define HID_QUIRK_MULTI_INPUT 0x00000040
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
+#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400
+#define HID_QUIRK_CYMOTION 0x00000800
+#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
+#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
/*
* This is the global environment of the parser. This information is
@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */
void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */
int (*ff_event)(struct hid_device *hid, struct input_dev *input,
unsigned int type, unsigned int code, int value);
+
+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+ unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
+ unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
+#endif
};
#define HID_GLOBAL_STACK_SIZE 4
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index 19e015d171aa..d9d9f656b8c9 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev,
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 hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
struct input_dev *input_dev = hidinput->input;
private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index 48df4cfd5a42..d3e15df9e815 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE);
enum {
PENPARTNER = 0,
GRAPHIRE,
- G4,
+ WACOM_G4,
PL,
INTUOS,
INTUOS3,
@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
case 2: /* Mouse with wheel */
input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
- if (wacom->features->type == G4) {
+ if (wacom->features->type == WACOM_G4) {
rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
input_report_rel(dev, REL_WHEEL, rw);
} else
@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
id = CURSOR_DEVICE_ID;
input_report_key(dev, BTN_LEFT, data[1] & 0x01);
input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
- if (wacom->features->type == G4)
+ if (wacom->features->type == WACOM_G4)
input_report_abs(dev, ABS_DISTANCE, data[6]);
else
input_report_abs(dev, ABS_DISTANCE, data[7]);
@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
input_sync(dev);
/* send pad data */
- if (wacom->features->type == G4) {
+ if (wacom->features->type == WACOM_G4) {
/* fist time sending pad data */
if (wacom->tool[1] != BTN_TOOL_FINGER) {
wacom->id[1] = 0;
@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq },
- { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq },
- { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq },
+ { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq },
+ { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq },
{ "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
switch (wacom->features->type) {
- case G4:
+ case WACOM_G4:
input_dev->evbit[0] |= BIT(EV_MSC);
input_dev->mscbit[0] |= BIT(MSC_SERIAL);
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index 6a5700e9d428..25646804d5be 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/usb/media/dsbr100.c
@@ -127,6 +127,7 @@ static struct file_operations usb_dsbr100_fops = {
.open = usb_dsbr100_open,
.release = usb_dsbr100_close,
.ioctl = usb_dsbr100_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 3a0e8ce67ebe..8af665bbe330 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -4774,6 +4774,7 @@ static struct file_operations ov511_fops = {
.read = ov51x_v4l1_read,
.mmap = ov51x_v4l1_mmap,
.ioctl = ov51x_v4l1_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 09ca6128ac20..4f9b0dc6fd7b 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -154,6 +154,7 @@ static struct file_operations pwc_fops = {
.poll = pwc_video_poll,
.mmap = pwc_video_mmap,
.ioctl = pwc_video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device pwc_template = {
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index b2ae29af5940..2ba562285fda 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1193,6 +1193,7 @@ static struct file_operations se401_fops = {
.read = se401_read,
.mmap = se401_mmap,
.ioctl = se401_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device se401_template = {
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 774038b352cd..b497a6a0a206 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -1343,6 +1343,7 @@ static struct file_operations stv680_fops = {
.read = stv680_read,
.mmap = stv680_mmap,
.ioctl = stv680_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device stv680_template = {
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index 4bd113325ef9..63a72e550a1b 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -953,6 +953,7 @@ static struct file_operations usbvideo_fops = {
.read = usbvideo_v4l_read,
.mmap = usbvideo_v4l_mmap,
.ioctl = usbvideo_v4l_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static const struct video_device usbvideo_template = {
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 1c73155c8d77..5df144073871 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1236,6 +1236,7 @@ static struct file_operations vicam_fops = {
.read = vicam_read,
.mmap = vicam_mmap,
.ioctl = vicam_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index 3605a6f3067b..bff9434c8e55 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -3490,6 +3490,7 @@ static struct file_operations w9968cf_fops = {
.release = w9968cf_release,
.read = w9968cf_read,
.ioctl = w9968cf_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.mmap = w9968cf_mmap,
.llseek = no_llseek,
};
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 14f55fd26a64..be5dc80836c3 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -84,7 +84,7 @@ config USB_SERIAL_BELKIN
config USB_SERIAL_WHITEHEAT
tristate "USB ConnectTech WhiteHEAT Serial Driver"
- depends on USB_SERIAL && BROKEN_ON_SMP
+ depends on USB_SERIAL
help
Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
USB to serial converter device.
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 664139afcfa9..e9f9f4bafa17 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -37,11 +37,6 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr
return 0;
}
-struct bus_type usb_serial_bus_type = {
- .name = "usb-serial",
- .match = usb_serial_device_match,
-};
-
static int usb_serial_device_probe (struct device *dev)
{
struct usb_serial_driver *driver;
@@ -109,14 +104,18 @@ exit:
return retval;
}
+struct bus_type usb_serial_bus_type = {
+ .name = "usb-serial",
+ .match = usb_serial_device_match,
+ .probe = usb_serial_device_probe,
+ .remove = usb_serial_device_remove,
+};
+
int usb_serial_bus_register(struct usb_serial_driver *driver)
{
int retval;
driver->driver.bus = &usb_serial_bus_type;
- driver->driver.probe = usb_serial_device_probe;
- driver->driver.remove = usb_serial_device_remove;
-
retval = driver_register(&driver->driver);
return retval;
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6d18d4eaba35..2357b1d102d7 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -364,7 +364,6 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
short todo;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -381,14 +380,8 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
return;
}
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index af18355e94cc..68067fe117a4 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -357,7 +357,7 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
} while (retval != 5 && retval != ENODEV);
if (retval != 5) {
- err("%s - failed to retreive serial line settings - %d", __FUNCTION__, retval);
+ err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
return retval;
} else {
spin_lock_irqsave(&priv->lock, flags);
@@ -1263,12 +1263,10 @@ 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)) {
+ bytes = tty_buffer_request_room(tty, bytes);
for (; i < bytes ; ++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);
- }
tty_insert_flip_char(tty, data[i], tty_flag);
}
tty_flip_buffer_push(port->tty);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 8fc414bd5b24..b3f776a90c93 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -946,13 +946,10 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
spin_lock_irqsave( &priv->dp_port_lock, flags );
/* send any buffered chars from throttle time on to tty subsystem */
- len = min(priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count );
+
+ len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
if( len > 0 ) {
- memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len );
- memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len );
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
- tty->flip.count += len;
+ tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
tty_flip_buffer_push( tty );
}
@@ -1827,6 +1824,7 @@ static int digi_read_inb_callback( struct urb *urb )
int status = ((unsigned char *)urb->transfer_buffer)[2];
unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
int flag,throttled;
+ int i;
/* do not process callbacks on closed ports */
/* but do continue the read chain */
@@ -1885,20 +1883,18 @@ static int digi_read_inb_callback( struct urb *urb )
}
} else {
-
- len = min( len, TTY_FLIPBUF_SIZE - tty->flip.count );
-
+ len = tty_buffer_request_room(tty, len);
if( len > 0 ) {
- memcpy( tty->flip.char_buf_ptr, data, len );
- memset( tty->flip.flag_buf_ptr, flag, len );
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
- tty->flip.count += len;
+ /* Hot path */
+ if(flag == TTY_NORMAL)
+ tty_insert_flip_string(tty, data, len);
+ else {
+ for(i = 0; i < len; i++)
+ tty_insert_flip_char(tty, data[i], flag);
+ }
tty_flip_buffer_push( tty );
}
-
}
-
}
spin_unlock( &priv->dp_port_lock );
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 79a766e9ca23..63f7c78a1152 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -344,7 +344,6 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -359,19 +358,8 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* gb - 2000/11/13
- * If we insert too many characters we'll overflow the buffer.
- * This means we'll lose bytes - Decidedly bad.
- */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- tty_insert_flip_char(tty, data[i], 0);
- }
- /* gb - 2000/11/13
- * Goes straight through instead of scheduling - if tty->low_latency is set.
- */
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
bytes_in += urb->actual_length;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index eb863b3f2d79..10bc1bf23b35 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1610,24 +1610,11 @@ static void ftdi_process_read (void *param)
length = 0;
}
- /* have to make sure we don't overflow the buffer
- with tty_insert_flip_char's */
- if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- need_flip = 0;
-
- if (tty->flip.count != 0) {
- /* flip didn't work, this happens when ftdi_process_read() is
- * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
- dbg("%s - flip buffer push failed", __FUNCTION__);
- break;
- }
- }
if (priv->rx_flags & THROTTLED) {
dbg("%s - throttled", __FUNCTION__);
break;
}
- if (tty->ldisc.receive_room(tty)-tty->flip.count < length) {
+ if (tty_buffer_request_room(tty, length) < length) {
/* break out & wait for throttling/unthrottling to happen */
dbg("%s - receive room low", __FUNCTION__);
break;
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 452efce72714..d6f55e9dccae 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -275,23 +275,14 @@ static void send_to_tty(struct usb_serial_port *port,
char *data, unsigned int actual_length)
{
struct tty_struct *tty = port->tty;
- int i;
if (tty && actual_length) {
usb_serial_debug_data(debug, &port->dev,
__FUNCTION__, actual_length, data);
- for (i = 0; i < actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters,
- we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless
- tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, actual_length);
+ tty_insert_flip_string(tty, data, actual_length);
tty_flip_buffer_push(tty);
}
}
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4ddac620fc0c..476cda107f4f 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -254,7 +254,6 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
struct usb_serial *serial = port->serial;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -268,14 +267,8 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index faedbeb6ba49..3f29e6b0fd19 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1965,20 +1965,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
int cnt;
do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
- __FUNCTION__, length);
- return;
- }
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __FUNCTION__, length - cnt);
+ if(cnt == 0)
+ break;
}
- cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
- memcpy(tty->flip.char_buf_ptr, data, cnt);
- memset(tty->flip.flag_buf_ptr, 0, cnt);
- tty->flip.char_buf_ptr += cnt;
- tty->flip.flag_buf_ptr += cnt;
- tty->flip.count += cnt;
+ tty_insert_flip_string(tty, data, cnt);
data += cnt;
length -= cnt;
} while (length > 0);
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 2edf9cabad20..afc0f34b3a46 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1865,20 +1865,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
int cnt;
do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
- __FUNCTION__, length);
- return;
- }
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __FUNCTION__, length - cnt);
+ if(cnt == 0)
+ break;
}
- cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
- memcpy(tty->flip.char_buf_ptr, data, cnt);
- memset(tty->flip.flag_buf_ptr, 0, cnt);
- tty->flip.char_buf_ptr += cnt;
- tty->flip.flag_buf_ptr += cnt;
- tty->flip.count += cnt;
+ tty_insert_flip_string(tty, data, cnt);
data += cnt;
length -= cnt;
} while (length > 0);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 06d07cea0b70..9a5c97989562 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -711,7 +711,7 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int i, result;
+ int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -724,14 +724,8 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
bytes_in += urb->actual_length;
}
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 2dd191f5fe76..e760a70242c1 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -166,7 +166,6 @@ static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -180,14 +179,8 @@ static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 4e2f7dfb58b2..78335a5f7743 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -648,7 +648,6 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
urb->actual_length, data);
} else {
- int i;
int bytes_sent = ((__u8 *) data)[0] +
((unsigned int) ((__u8 *) data)[1] << 8);
tty = port->tty;
@@ -669,16 +668,8 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
bytes_sent = urb->actual_length - 2;
}
- for (i = 2; i < 2+bytes_sent; i++) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters,
- * we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless
- * tty->low_latency is set */
- tty_insert_flip_char(tty, ((__u8*) data)[i], 0);
- }
+ tty_buffer_request_room(tty, bytes_sent);
+ tty_insert_flip_string(tty, data + 2, bytes_sent);
tty_flip_buffer_push(tty);
/* again lockless, but debug info only */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index d9c21e275130..b8b213185d0f 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -365,7 +365,6 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
{
- int i;
int result;
struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
struct tty_struct *tty;
@@ -397,14 +396,8 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
*/
// END DEBUG
- for (i = 0; i < purb->actual_length; ++i) {
- // if we insert more than TTY_FLIPBUF_SIZE characters, we drop them.
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- // this doesn't actually push the data through unless tty->low_latency is set
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, purb->actual_length);
+ tty_insert_flip_string(tty, data, purb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 3fd2405304fd..52bdf6fe46f2 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -321,7 +321,7 @@ static int option_write(struct usb_serial_port *port,
static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
{
- int i, err;
+ int err;
int endpoint;
struct usb_serial_port *port;
struct tty_struct *tty;
@@ -338,11 +338,8 @@ static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
} else {
tty = port->tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- tty_flip_buffer_push(tty);
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
} else {
dbg("%s: empty read urb received", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index f03721056190..0eb883f44ada 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -43,8 +43,6 @@ static int debug;
#define PL2303_BUF_SIZE 1024
#define PL2303_TMP_BUF_SIZE 1024
-static DECLARE_MUTEX(pl2303_tmp_buf_sem);
-
struct pl2303_buf {
unsigned int buf_size;
char *buf_buf;
@@ -924,16 +922,12 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
+ tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
if (status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-
- for (i = 0; i < urb->actual_length; ++i) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
+ for (i = 0; i < urb->actual_length; ++i)
tty_insert_flip_char (tty, data[i], tty_flag);
- }
tty_flip_buffer_push (tty);
}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index abb830cb77bd..c18db3257073 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1280,24 +1280,18 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
int cnt;
do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length);
- return;
- }
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
+ if(cnt == 0)
+ break;
}
- cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
- memcpy(tty->flip.char_buf_ptr, data, cnt);
- memset(tty->flip.flag_buf_ptr, 0, cnt);
- tty->flip.char_buf_ptr += cnt;
- tty->flip.flag_buf_ptr += cnt;
- tty->flip.count += cnt;
+ tty_insert_flip_string(tty, data, cnt);
+ tty_flip_buffer_push(tty);
data += cnt;
length -= cnt;
} while (length > 0);
- tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 8bc8337c99c4..4dd6865d32b0 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -584,7 +584,7 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac
const struct usb_device_id *id;
struct usb_serial_driver *t;
- /* List trough know devices and see if the usb id matches */
+ /* Check if the usb id matches a known device */
list_for_each(p, &usb_serial_driver_list) {
t = list_entry(p, struct usb_serial_driver, driver_list);
id = usb_match_id(iface, t->id_table);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 49b1fbe61f25..bce3d55affd8 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -488,7 +488,6 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
unsigned long flags;
- int i;
int throttled;
int result;
@@ -503,14 +502,8 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
spin_lock_irqsave(&priv->lock, flags);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index a7c3c4734d83..557411c6e7c7 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -1434,7 +1434,9 @@ static void rx_data_softint(void *private)
urb = wrap->urb;
if (tty && urb->actual_length) {
- if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {
+ int len = tty_buffer_request_room(tty, urb->actual_length);
+ /* This stuff can go away now I suspect */
+ if (unlikely(len < urb->actual_length)) {
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urb_q);
spin_unlock_irqrestore(&info->lock, flags);
@@ -1442,11 +1444,8 @@ static void rx_data_softint(void *private)
schedule_work(&info->rx_work);
return;
}
-
- memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);
- tty->flip.char_buf_ptr += urb->actual_length;
- tty->flip.count += urb->actual_length;
- sent += urb->actual_length;
+ tty_insert_flip_string(tty, urb->transfer_buffer, len);
+ sent += len;
}
urb->dev = port->serial->dev;
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 3b0ddc55236b..78488bb41aeb 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -102,8 +102,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
-static int mc68x328fb_mmap(struct fb_info *info, struct file *file,
- struct vm_area_struct *vma);
+static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
static struct fb_ops mc68x328fb_ops = {
.fb_check_var = mc68x328fb_check_var,
@@ -398,8 +397,7 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
* Most drivers don't need their own mmap function
*/
-static int mc68x328fb_mmap(struct fb_info *info, struct file *file,
- struct vm_area_struct *vma)
+static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
#ifndef MMU
/* this is uClinux (no MMU) specific code */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc8e3bf5001b..3e153d313bb0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -993,12 +993,6 @@ config FB_ATY_GENERIC_LCD
Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
Rage XC, or Rage XL chipset.
-config FB_ATY_XL_INIT
- bool "Rage XL No-BIOS Init support"
- depends on FB_ATY_CT
- help
- Say Y here to support booting a Rage XL without BIOS support.
-
config FB_ATY_GX
bool "Mach64 GX support" if PCI
depends on FB_ATY
@@ -1151,7 +1145,7 @@ config FB_VOODOO1
config FB_CYBLA
tristate "Cyberblade/i1 support"
- depends on FB && PCI
+ depends on FB && PCI && X86_32 && !64BIT
select FB_CFB_IMAGEBLIT
select VIDEO_SELECT
---help---
@@ -1376,7 +1370,7 @@ config FB_PXA
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 vfb. If you want to compile it as a module,
+ module will be called pxafb. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
@@ -1409,7 +1403,7 @@ config FB_W100
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 vfb. If you want to compile it as a module,
+ module will be called w100fb. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 750cebb18306..b058273527bb 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -883,7 +883,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
* Note that we are entered with the kernel locked.
*/
static int
-acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+acornfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned long off, start;
u32 len;
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index a3c2c45e29e0..b2187175d03f 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -21,12 +21,11 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/list.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/clk.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
-
-#include <asm/hardware/amba_clcd.h>
#define to_clcd(info) container_of(info, struct clcd_fb, fb)
@@ -308,7 +307,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info)
return 0;
}
-static int clcdfb_mmap(struct fb_info *info, struct file *file,
+static int clcdfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct clcd_fb *fb = to_clcd(info);
@@ -346,10 +345,6 @@ static int clcdfb_register(struct clcd_fb *fb)
goto out;
}
- ret = clk_use(fb->clk);
- if (ret)
- goto free_clk;
-
fb->fb.fix.mmio_start = fb->dev->res.start;
fb->fb.fix.mmio_len = SZ_4K;
@@ -357,7 +352,7 @@ static int clcdfb_register(struct clcd_fb *fb)
if (!fb->regs) {
printk(KERN_ERR "CLCD: unable to remap registers\n");
ret = -ENOMEM;
- goto unuse_clk;
+ goto free_clk;
}
fb->fb.fbops = &clcdfb_ops;
@@ -427,8 +422,6 @@ static int clcdfb_register(struct clcd_fb *fb)
printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
iounmap(fb->regs);
- unuse_clk:
- clk_unuse(fb->clk);
free_clk:
clk_put(fb->clk);
out:
@@ -489,7 +482,6 @@ static int clcdfb_remove(struct amba_device *dev)
clcdfb_disable(fb);
unregister_framebuffer(&fb->fb);
iounmap(fb->regs);
- clk_unuse(fb->clk);
clk_put(fb->clk);
fb->board->remove(fb);
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index d549e215f3c5..3033c72dea20 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -590,6 +590,8 @@ static u_short maxfmode, chipset;
#define highw(x) ((u_long)(x)>>16 & 0xffff)
#define loww(x) ((u_long)(x) & 0xffff)
+#define custom amiga_custom
+
#define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
#define VBlankOff() custom.intena = IF_COPER
@@ -1129,9 +1131,7 @@ static void amifb_copyarea(struct fb_info *info,
const struct fb_copyarea *region);
static void amifb_imageblit(struct fb_info *info,
const struct fb_image *image);
-static int amifb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info);
+static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
/*
@@ -1164,8 +1164,8 @@ static void ami_update_display(void);
static void ami_init_display(void);
static void ami_do_blank(void);
static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data);
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data);
+static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
+static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
static int ami_get_cursorstate(struct fb_cursorstate *state);
static int ami_set_cursorstate(struct fb_cursorstate *state);
static void ami_set_sprite(void);
@@ -2170,15 +2170,15 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
* Amiga Frame Buffer Specific ioctls
*/
-static int amifb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int amifb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
union {
struct fb_fix_cursorinfo fix;
struct fb_var_cursorinfo var;
struct fb_cursorstate state;
} crsr;
+ void __user *argp = (void __user *)arg;
int i;
switch (cmd) {
@@ -2186,33 +2186,32 @@ static int amifb_ioctl(struct inode *inode, struct file *file,
i = ami_get_fix_cursorinfo(&crsr.fix);
if (i)
return i;
- return copy_to_user((void *)arg, &crsr.fix,
+ return copy_to_user(argp, &crsr.fix,
sizeof(crsr.fix)) ? -EFAULT : 0;
case FBIOGET_VCURSORINFO:
i = ami_get_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo *)arg)->data);
+ ((struct fb_var_cursorinfo __user *)arg)->data);
if (i)
return i;
- return copy_to_user((void *)arg, &crsr.var,
+ return copy_to_user(argp, &crsr.var,
sizeof(crsr.var)) ? -EFAULT : 0;
case FBIOPUT_VCURSORINFO:
- if (copy_from_user(&crsr.var, (void *)arg,
- sizeof(crsr.var)))
+ if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
return -EFAULT;
return ami_set_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo *)arg)->data);
+ ((struct fb_var_cursorinfo __user *)arg)->data);
case FBIOGET_CURSORSTATE:
i = ami_get_cursorstate(&crsr.state);
if (i)
return i;
- return copy_to_user((void *)arg, &crsr.state,
+ return copy_to_user(argp, &crsr.state,
sizeof(crsr.state)) ? -EFAULT : 0;
case FBIOPUT_CURSORSTATE:
- if (copy_from_user(&crsr.state, (void *)arg,
+ if (copy_from_user(&crsr.state, argp,
sizeof(crsr.state)))
return -EFAULT;
return ami_set_cursorstate(&crsr.state);
@@ -3325,7 +3324,7 @@ static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
return 0;
}
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
+static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
{
struct amifb_par *par = &currentpar;
register u_short *lspr, *sspr;
@@ -3347,14 +3346,14 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
var->yspot = par->crsr.spot_y;
if (size > var->height*var->width)
return -ENAMETOOLONG;
- if (!access_ok(VERIFY_WRITE, (void *)data, size))
+ if (!access_ok(VERIFY_WRITE, data, size))
return -EFAULT;
delta = 1<<par->crsr.fmode;
lspr = lofsprite + (delta<<1);
if (par->bplcon0 & BPC0_LACE)
sspr = shfsprite + (delta<<1);
else
- sspr = 0;
+ sspr = NULL;
for (height = (short)var->height-1; height >= 0; height--) {
bits = 0; words = delta; datawords = 0;
for (width = (short)var->width-1; width >= 0; width--) {
@@ -3400,7 +3399,7 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
return 0;
}
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
+static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
{
struct amifb_par *par = &currentpar;
register u_short *lspr, *sspr;
@@ -3427,7 +3426,7 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
return -EINVAL;
if (!var->height)
return -EINVAL;
- if (!access_ok(VERIFY_READ, (void *)data, var->width*var->height))
+ if (!access_ok(VERIFY_READ, data, var->width*var->height))
return -EFAULT;
delta = 1<<fmode;
lofsprite = shfsprite = (u_short *)spritememory;
@@ -3442,13 +3441,13 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
return -EINVAL;
memset(lspr, 0, (var->height+2)<<fmode<<2);
- sspr = 0;
+ sspr = NULL;
}
for (height = (short)var->height-1; height >= 0; height--) {
bits = 16; words = delta; datawords = 0;
for (width = (short)var->width-1; width >= 0; width--) {
unsigned long tdata = 0;
- get_user(tdata, (char *)data);
+ get_user(tdata, data);
data++;
#ifdef __mc68000__
asm volatile (
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 2784f0a9d693..df8e5667b348 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -366,7 +366,8 @@ static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
}
}
-void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void arcfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
{
struct arcfb_par *par = info->par;
@@ -376,7 +377,8 @@ void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
}
-void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void arcfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
{
struct arcfb_par *par = info->par;
@@ -386,7 +388,7 @@ void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
}
-void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct arcfb_par *par = info->par;
@@ -397,9 +399,8 @@ void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
image->height);
}
-static int arcfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int arcfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
struct arcfb_par *par = info->par;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index c64de59398f4..69f75547865d 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -549,7 +549,7 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
if (!request_mem_region(addr, size, "asiliantfb"))
return -EBUSY;
- p = framebuffer_alloc(sizeof(u32) * 256, &dp->dev);
+ p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev);
if (!p) {
release_mem_region(addr, size);
return -ENOMEM;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 15ec1295bc29..e69ab65f7843 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2571,8 +2571,7 @@ atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
}
static int
-atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, int con, struct fb_info *info)
+atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
#ifdef FBCMD_GET_CURRENTPAR
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
index 9dec96249ffb..18521397a6e3 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/aty/Makefile
@@ -5,7 +5,6 @@ obj-$(CONFIG_FB_RADEON) += radeonfb.o
atyfb-y := atyfb_base.o mach64_accel.o mach64_cursor.o
atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o
atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o
-atyfb-$(CONFIG_FB_ATY_XL_INIT) += xlinit.o
atyfb-objs := $(atyfb-y)
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index e686185a076d..bfc8a93b2c73 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -431,8 +431,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static int aty128fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *fb);
static int aty128fb_blank(int blank, struct fb_info *fb);
-static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info);
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
static int aty128fb_sync(struct fb_info *info);
/*
@@ -2108,8 +2107,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/* in param: u32* backlight value: 0 to 15 */
#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
-static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
struct aty128fb_par *par = info->par;
u32 value;
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index 09de173c1164..e9b7a64c1ac4 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -50,6 +50,7 @@ struct pll_info {
int sclk, mclk, mclk_pm, xclk;
int ref_div;
int ref_clk;
+ int ecp_max;
};
typedef struct {
@@ -354,6 +355,5 @@ static inline void wait_for_idle(struct atyfb_par *par)
extern void aty_reset_engine(const struct atyfb_par *par);
extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
-extern int atyfb_xl_init(struct fb_info *info);
extern void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par);
extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 3fefdb0cbf07..485be386a8ff 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -109,9 +109,18 @@
#define GUI_RESERVE (1 * PAGE_SIZE)
/* FIXME: remove the FAIL definition */
-#define FAIL(msg) do { printk(KERN_CRIT "atyfb: " msg "\n"); return -EINVAL; } while (0)
-#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0)
-
+#define FAIL(msg) do { \
+ if (!(var->activate & FB_ACTIVATE_TEST)) \
+ printk(KERN_CRIT "atyfb: " msg "\n"); \
+ return -EINVAL; \
+} while (0)
+#define FAIL_MAX(msg, x, _max_) do { \
+ if (x > _max_) { \
+ if (!(var->activate & FB_ACTIVATE_TEST)) \
+ printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
+ return -EINVAL; \
+ } \
+} while (0)
#ifdef DEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
#else
@@ -229,13 +238,12 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
static int atyfb_blank(int blank, struct fb_info *info);
-static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info);
+static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
#ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
+static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
#endif
static int atyfb_sync(struct fb_info *info);
@@ -340,6 +348,7 @@ static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
#define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
#define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
+/* FIXME what is this chip? */
#define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
/* make sets shorter */
@@ -359,58 +368,60 @@ static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
static struct {
u16 pci_id;
const char *name;
- int pll, mclk, xclk;
+ int pll, mclk, xclk, ecp_max;
u32 features;
} aty_chips[] __devinitdata = {
#ifdef CONFIG_FB_ATY_GX
/* Mach64 GX */
- { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
- { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, ATI_CHIP_88800CX },
+ { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
+ { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
#endif /* CONFIG_FB_ATY_GX */
#ifdef CONFIG_FB_ATY_CT
- { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, ATI_CHIP_264CT },
- { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, ATI_CHIP_264ET },
- { PCI_CHIP_MACH64VT, "ATI264VT? (Mach64 VT)", 170, 67, 67, ATI_CHIP_264VT },
- { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, ATI_CHIP_264GT },
- /* FIXME { ...ATI_264GU, maybe ATI_CHIP_264GTDVD }, */
- { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GTB)", 200, 67, 67, ATI_CHIP_264GTB },
- { PCI_CHIP_MACH64VU, "ATI264VTB (Mach64 VU)", 200, 67, 67, ATI_CHIP_264VT3 },
-
- { PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT },
- /* FIXME chipset maybe ATI_CHIP_264LTPRO ? */
- { PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
-
- { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 },
-
- { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
- { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
- { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
- { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
-
- { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, ATI_CHIP_264GTPRO },
- { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, ATI_CHIP_264GTPRO },
- { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
- { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO },
- { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, ATI_CHIP_264GTPRO },
-
- { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, ATI_CHIP_264LTPRO },
- { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, ATI_CHIP_264LTPRO },
- { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
- { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
- { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
-
- { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 235, 83, 63, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
- { PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
-
- { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
+ { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
+
+ /* FIXME what is this chip? */
+ { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
+
+ { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
+ { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
+
+ { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
+ { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
+
+ { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
+
+ { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
+
+ { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+ { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+ { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+ { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+
+ { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+ { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+ { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
+ { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+ { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+
+ { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
+ { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+ { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+ { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+ { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+
+ { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
+ { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
+
+ { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
#endif /* CONFIG_FB_ATY_CT */
};
@@ -431,6 +442,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
par->pll_limits.pll_max = aty_chips[i].pll;
par->pll_limits.mclk = aty_chips[i].mclk;
par->pll_limits.xclk = aty_chips[i].xclk;
+ par->pll_limits.ecp_max = aty_chips[i].ecp_max;
par->features = aty_chips[i].features;
chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
@@ -450,39 +462,63 @@ static int __devinit correct_chipset(struct atyfb_par *par)
#endif
#ifdef CONFIG_FB_ATY_CT
case PCI_CHIP_MACH64VT:
- rev &= 0xc7;
- if(rev == 0x00) {
- name = "ATI264VTA3 (Mach64 VT)";
- par->pll_limits.pll_max = 170;
- par->pll_limits.mclk = 67;
- par->pll_limits.xclk = 67;
- par->features = ATI_CHIP_264VT;
- } else if(rev == 0x40) {
- name = "ATI264VTA4 (Mach64 VT)";
+ switch (rev & 0x07) {
+ case 0x00:
+ switch (rev & 0xc0) {
+ case 0x00:
+ name = "ATI264VT (A3) (Mach64 VT)";
+ par->pll_limits.pll_max = 170;
+ par->pll_limits.mclk = 67;
+ par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VT;
+ break;
+ case 0x40:
+ name = "ATI264VT2 (A4) (Mach64 VT)";
+ par->pll_limits.pll_max = 200;
+ par->pll_limits.mclk = 67;
+ par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
+ break;
+ }
+ break;
+ case 0x01:
+ name = "ATI264VT3 (B1) (Mach64 VT)";
par->pll_limits.pll_max = 200;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
- par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
- } else {
- name = "ATI264VTB (Mach64 VT)";
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VTB;
+ break;
+ case 0x02:
+ name = "ATI264VT3 (B2) (Mach64 VT)";
par->pll_limits.pll_max = 200;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
- par->features = ATI_CHIP_264VTB;
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VT3;
+ break;
}
break;
case PCI_CHIP_MACH64GT:
- rev &= 0x07;
- if(rev == 0x01) {
+ switch (rev & 0x07) {
+ case 0x01:
+ name = "3D RAGE II (Mach64 GT)";
par->pll_limits.pll_max = 170;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 80;
par->features = ATI_CHIP_264GTB;
- } else if(rev == 0x02) {
+ break;
+ case 0x02:
+ name = "3D RAGE II+ (Mach64 GT)";
par->pll_limits.pll_max = 200;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 100;
par->features = ATI_CHIP_264GTB;
+ break;
}
break;
#endif
@@ -692,7 +728,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
(SHADOW_EN | SHADOW_RW_EN), par);
- DPRINTK("set secondary CRT to %ix%i %c%c\n",
+ DPRINTK("set shadow CRT to %ix%i %c%c\n",
((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
(crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
@@ -840,11 +876,14 @@ static int aty_var_to_crtc(const struct fb_info *info,
know if one is connected. So it's better to fail then.
*/
if (crtc->lcd_gen_cntl & CRT_ON) {
- PRINTKI("Disable lcd panel, because video mode does not fit.\n");
+ if (!(var->activate & FB_ACTIVATE_TEST))
+ PRINTKI("Disable LCD panel, because video mode does not fit.\n");
crtc->lcd_gen_cntl &= ~LCD_ON;
/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
} else {
- FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode.");
+ if (!(var->activate & FB_ACTIVATE_TEST))
+ PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
+ return -EINVAL;
}
}
}
@@ -858,9 +897,9 @@ static int aty_var_to_crtc(const struct fb_info *info,
vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
/* This is horror! When we simulate, say 640x480 on an 800x600
- lcd monitor, the CRTC should be programmed 800x600 values for
+ LCD monitor, the CRTC should be programmed 800x600 values for
the non visible part, but 640x480 for the visible part.
- This code has been tested on a laptop with it's 1400x1050 lcd
+ This code has been tested on a laptop with it's 1400x1050 LCD
monitor and a conventional monitor both switched on.
Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
works with little glitches also with DOUBLESCAN modes
@@ -955,16 +994,6 @@ static int aty_var_to_crtc(const struct fb_info *info,
vdisplay = yres;
if(vmode & FB_VMODE_DOUBLE)
vdisplay <<= 1;
- if(vmode & FB_VMODE_INTERLACED) {
- vdisplay >>= 1;
-
- /* The prefered mode for the lcd is not interlaced, so disable it if
- it was enabled. For doublescan there is no problem, because we can
- compensate for it in the hardware stretching (we stretch half as much)
- */
- vmode &= ~FB_VMODE_INTERLACED;
- /*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/
- }
crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
@@ -980,7 +1009,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
crtc->horz_stretching &=
~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
- if (xres < par->lcd_width) {
+ if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
do {
/*
* The horizontal blender misbehaves when HDisplay is less than a
@@ -1042,7 +1071,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
} while (0);
}
- if (vdisplay < par->lcd_height) {
+ if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
@@ -1065,9 +1094,8 @@ static int aty_var_to_crtc(const struct fb_info *info,
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
if (M64_HAS(MAGIC_FIFO)) {
- /* Not VTB/GTB */
- /* FIXME: magic FIFO values */
- crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH);
+ /* FIXME: display FIFO low watermark values */
+ crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
}
crtc->dp_pix_width = dp_pix_width;
crtc->dp_chain_mask = dp_chain_mask;
@@ -1184,7 +1212,8 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va
var->transp.length = 8;
break;
default:
- FAIL("Invalid pixel width");
+ PRINTKE("Invalid pixel width\n");
+ return -EINVAL;
}
/* output */
@@ -1241,7 +1270,8 @@ static int atyfb_set_par(struct fb_info *info)
pixclock = atyfb_get_pixclock(var, par);
if (pixclock == 0) {
- FAIL("Invalid pixclock");
+ PRINTKE("Invalid pixclock\n");
+ return -EINVAL;
} else {
if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
return err;
@@ -1446,7 +1476,9 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
pixclock = atyfb_get_pixclock(var, par);
if (pixclock == 0) {
- FAIL("Invalid pixclock");
+ if (!(var->activate & FB_ACTIVATE_TEST))
+ PRINTKE("Invalid pixclock\n");
+ return -EINVAL;
} else {
if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
return err;
@@ -1706,8 +1738,7 @@ struct atyclk {
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
#endif
-static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
#ifdef __sparc__
@@ -1812,7 +1843,7 @@ static int atyfb_sync(struct fb_info *info)
}
#ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
unsigned int size, page, map_size = 0;
@@ -2291,10 +2322,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
par->dac_ops = &aty_dac_ct;
par->pll_ops = &aty_pll_ct;
par->bus_type = PCI;
-#ifdef CONFIG_FB_ATY_XL_INIT
- if (IS_XL(par->pci_id))
- atyfb_xl_init(info);
-#endif
par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
ramname = aty_ct_ram[par->ram_type];
/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
@@ -2638,16 +2665,16 @@ static int __init store_video_par(char *video_str, unsigned char m64_num)
static int atyfb_blank(int blank, struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
- u8 gen_cntl;
+ u32 gen_cntl;
if (par->lock_blank || par->asleep)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank)
+ if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL)
set_backlight_enable(0);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
- if (par->lcd_table && blank &&
+ if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
pm &= ~PWR_BLON;
@@ -2655,31 +2682,31 @@ static int atyfb_blank(int blank, struct fb_info *info)
}
#endif
- gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
+ gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
switch (blank) {
case FB_BLANK_UNBLANK:
- gen_cntl &= ~(0x4c);
+ gen_cntl &= ~0x400004c;
break;
case FB_BLANK_NORMAL:
- gen_cntl |= 0x40;
+ gen_cntl |= 0x4000040;
break;
case FB_BLANK_VSYNC_SUSPEND:
- gen_cntl |= 0x8;
+ gen_cntl |= 0x4000048;
break;
case FB_BLANK_HSYNC_SUSPEND:
- gen_cntl |= 0x4;
+ gen_cntl |= 0x4000044;
break;
case FB_BLANK_POWERDOWN:
- gen_cntl |= 0x4c;
+ gen_cntl |= 0x400004c;
break;
}
- aty_st_8(CRTC_GEN_CNTL, gen_cntl, par);
+ aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && !blank)
+ if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL)
set_backlight_enable(1);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
- if (par->lcd_table && !blank &&
+ if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
pm |= PWR_BLON;
@@ -3157,15 +3184,15 @@ static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
/* We now need to determine the crtc parameters for the
- * lcd monitor. This is tricky, because they are not stored
+ * LCD monitor. This is tricky, because they are not stored
* individually in the BIOS. Instead, the BIOS contains a
* table of display modes that work for this monitor.
*
* The idea is that we search for a mode of the same dimensions
- * as the dimensions of the lcd monitor. Say our lcd monitor
+ * as the dimensions of the LCD monitor. Say our LCD monitor
* is 800x600 pixels, we search for a 800x600 monitor.
* The CRTC parameters we find here are the ones that we need
- * to use to simulate other resolutions on the lcd screen.
+ * to use to simulate other resolutions on the LCD screen.
*/
lcdmodeptr = (u16 *)(par->lcd_table + 64);
while (*lcdmodeptr != 0) {
@@ -3472,7 +3499,7 @@ err_release_mem:
static int __devinit atyfb_atari_probe(void)
{
- struct aty_par *par;
+ struct atyfb_par *par;
struct fb_info *info;
int m64_num;
u32 clock_r;
@@ -3692,9 +3719,7 @@ static int __init atyfb_init(void)
atyfb_setup(option);
#endif
-#ifdef CONFIG_PCI
pci_register_driver(&atyfb_driver);
-#endif
#ifdef CONFIG_ATARI
atyfb_atari_probe();
#endif
@@ -3703,9 +3728,7 @@ static int __init atyfb_init(void)
static void __exit atyfb_exit(void)
{
-#ifdef CONFIG_PCI
pci_unregister_driver(&atyfb_driver);
-#endif
}
module_init(atyfb_init);
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
index 9bdb2aab01aa..e7056934c6a8 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/aty/mach64_ct.c
@@ -206,9 +206,7 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll
{
u32 q;
struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef DEBUG
int pllvclk;
-#endif
/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;
@@ -223,13 +221,26 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll
pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
// pll->vclk_post_div <<= 6;
pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
-#ifdef DEBUG
pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
(par->ref_clk_per * pll->pll_ref_div);
+#ifdef DEBUG
printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
__FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real);
#endif
pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
+
+ /* Set ECP (scaler/overlay clock) divider */
+ if (par->pll_limits.ecp_max) {
+ int ecp = pllvclk / pll->vclk_post_div_real;
+ int ecp_div = 0;
+
+ while (ecp > par->pll_limits.ecp_max && ecp_div < 2) {
+ ecp >>= 1;
+ ecp_div++;
+ }
+ pll->pll_vclk_cntl |= ecp_div << 4;
+ }
+
return 0;
}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 156db84cb363..c9f0c5a07e6e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -864,8 +864,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
}
-static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct radeonfb_info *rinfo = info->par;
unsigned int tmp;
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index ea7c86306918..7f9838dceab5 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -423,7 +423,7 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
/*
* Probe display on both primary and secondary card's connector (if any)
* by various available techniques (i2c, OF device tree, BIOS, ...) and
- * try to retreive EDID. The algorithm here comes from XFree's radeon
+ * try to retrieve EDID. The algorithm here comes from XFree's radeon
* driver
*/
void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 097d668c4fe5..556895e99645 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
* BIOS does tho. Right now, all this PM stuff is pmac-only for that
* reason. --BenH
*/
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
@@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
#endif
}
-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */
+#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */
}
void radeonfb_pm_exit(struct radeonfb_info *rinfo)
{
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
if (rinfo->pm_mode != radeon_pm_none)
pmac_set_early_video_resume(NULL, NULL);
#endif
diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c
deleted file mode 100644
index a085cbf74ecb..000000000000
--- a/drivers/video/aty/xlinit.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * ATI Rage XL Initialization. Support for Xpert98 and Victoria
- * PCI cards.
- *
- * Copyright (C) 2002 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * stevel@mvista.com or source@mvista.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * 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.
- */
-#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/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <video/mach64.h>
-#include "atyfb.h"
-
-#define MPLL_GAIN 0xad
-#define VPLL_GAIN 0xd5
-
-enum {
- VICTORIA = 0,
- XPERT98,
- NUM_XL_CARDS
-};
-
-extern const struct aty_pll_ops aty_pll_ct;
-
-#define DEFAULT_CARD XPERT98
-static int xl_card = DEFAULT_CARD;
-
-static const struct xl_card_cfg_t {
- int ref_crystal; // 10^4 Hz
- int mem_type;
- int mem_size;
- u32 mem_cntl;
- u32 ext_mem_cntl;
- u32 mem_addr_config;
- u32 bus_cntl;
- u32 dac_cntl;
- u32 hw_debug;
- u32 custom_macro_cntl;
- u8 dll2_cntl;
- u8 pll_yclk_cntl;
-} card_cfg[NUM_XL_CARDS] = {
- // VICTORIA
- { 2700, SDRAM, 0x800000,
- 0x10757A3B, 0x64000C81, 0x00110202, 0x7b33A040,
- 0x82010102, 0x48803800, 0x005E0179,
- 0x50, 0x25
- },
- // XPERT98
- { 1432, WRAM, 0x800000,
- 0x00165A2B, 0xE0000CF1, 0x00200213, 0x7333A001,
- 0x8000000A, 0x48833800, 0x007F0779,
- 0x10, 0x19
- }
-};
-
-typedef struct {
- u8 lcd_reg;
- u32 val;
-} lcd_tbl_t;
-
-static const lcd_tbl_t lcd_tbl[] = {
- { 0x01, 0x000520C0 },
- { 0x08, 0x02000408 },
- { 0x03, 0x00000F00 },
- { 0x00, 0x00000000 },
- { 0x02, 0x00000000 },
- { 0x04, 0x00000000 },
- { 0x05, 0x00000000 },
- { 0x06, 0x00000000 },
- { 0x33, 0x00000000 },
- { 0x34, 0x00000000 },
- { 0x35, 0x00000000 },
- { 0x36, 0x00000000 },
- { 0x37, 0x00000000 }
-};
-
-static void reset_gui(struct atyfb_par *par)
-{
- aty_st_8(GEN_TEST_CNTL+1, 0x01, par);
- aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
- aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
- mdelay(5);
-}
-
-static void reset_sdram(struct atyfb_par *par)
-{
- u8 temp;
-
- temp = aty_ld_8(EXT_MEM_CNTL, par);
- temp |= 0x02;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_RESET = 1b
- temp |= 0x08;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 10b
- temp |= 0x0c;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 11b
- mdelay(5);
- temp &= 0xf3;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 00b
- temp &= 0xfd;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_REST = 0b
- mdelay(5);
-}
-
-static void init_dll(struct atyfb_par *par)
-{
- // enable DLL
- aty_st_pll_ct(PLL_GEN_CNTL,
- aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f,
- par);
-
- // reset DLL
- aty_st_pll_ct(DLL_CNTL, 0x82, par);
- aty_st_pll_ct(DLL_CNTL, 0xE2, par);
- mdelay(5);
- aty_st_pll_ct(DLL_CNTL, 0x82, par);
- mdelay(6);
-}
-
-static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll,
- int hsync_enb)
-{
- reset_gui(par);
- aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par);
- aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par);
-
- mdelay(15);
- init_dll(par);
- aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
- mdelay(5);
- aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
- mdelay(6);
- reset_sdram(par);
- aty_st_8(CRTC_GEN_CNTL+3,
- hsync_enb ? 0x00 : 0x04, par);
-
- aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par);
- aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
- aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
-}
-
-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 err;
- u32 temp;
-
- aty_st_8(CONFIG_STAT0, 0x85, par);
- mdelay(10);
-
- /*
- * The following needs to be set before the call
- * to var_to_pll() below. They'll be re-set again
- * to the same values in aty_init().
- */
- par->ref_clk_per = 100000000UL/card->ref_crystal;
- par->ram_type = card->mem_type;
- info->fix.smem_len = card->mem_size;
- if (xl_card == VICTORIA) {
- // the MCLK, XCLK are 120MHz on victoria card
- par->mclk_per = 1000000/120;
- par->xclk_per = 1000000/120;
- par->features &= ~M64F_MFB_FORCE_4;
- }
-
- /*
- * Calculate mclk and xclk dividers, etc. The passed
- * pixclock and bpp values don't matter yet, the vclk
- * isn't programmed until later.
- */
- if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
- return err;
-
- aty_st_pll_ct(LVDS_CNTL0, 0x00, par);
- aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par);
- aty_st_pll_ct(V2PLL_CNTL, 0x10, par);
- aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par);
- aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par);
- aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par);
- aty_st_pll_ct(VFC_CNTL, 0x1B, par);
- aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par);
- aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
- aty_st_pll_ct(SPLL_CNTL2, 0x03, par);
- aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par);
-
- reset_clocks(par, &pll.ct, 0);
- mdelay(10);
-
- aty_st_pll_ct(VCLK_POST_DIV, 0x03, par);
- aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par);
- aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par);
- aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par);
- aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par);
- aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
- aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par);
- aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par);
- aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
- aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par);
-
- aty_st_8(BUS_CNTL, 0x01, par);
- aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par);
-
- aty_st_le32(CRTC_GEN_CNTL, 0x04000200, par);
- aty_st_le16(CONFIG_STAT0, 0x0020, par);
- aty_st_le32(MEM_CNTL, 0x10151A33, par);
- aty_st_le32(EXT_MEM_CNTL, 0xE0000C01, par);
- aty_st_le16(CRTC_GEN_CNTL+2, 0x0000, par);
- aty_st_le32(DAC_CNTL, card->dac_cntl, par);
- aty_st_le16(GEN_TEST_CNTL, 0x0100, par);
- aty_st_le32(CUSTOM_MACRO_CNTL, 0x003C0171, par);
- aty_st_le32(MEM_BUF_CNTL, 0x00382848, par);
-
- aty_st_le32(HW_DEBUG, card->hw_debug, par);
- aty_st_le16(MEM_ADDR_CONFIG, 0x0000, par);
- aty_st_le16(GP_IO+2, 0x0000, par);
- aty_st_le16(GEN_TEST_CNTL, 0x0000, par);
- aty_st_le16(EXT_DAC_REGS+2, 0x0000, par);
- aty_st_le32(CRTC_INT_CNTL, 0x00000000, par);
- aty_st_le32(TIMER_CONFIG, 0x00000000, par);
- aty_st_le32(0xEC, 0x00000000, par);
- aty_st_le32(0xFC, 0x00000000, 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);
-
- aty_st_8(BUS_CNTL+1, 0xA0, par);
- mdelay(10);
-
- reset_clocks(par, &pll.ct, 1);
- mdelay(10);
-
- // something about power management
- aty_st_8(LCD_INDEX, 0x08, par);
- aty_st_8(LCD_DATA, 0x0A, par);
- aty_st_8(LCD_INDEX, 0x08, par);
- aty_st_8(LCD_DATA+3, 0x02, par);
- aty_st_8(LCD_INDEX, 0x08, par);
- aty_st_8(LCD_DATA, 0x0B, par);
- mdelay(2);
-
- // enable display requests, enable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
- // disable display
- aty_st_8(CRTC_GEN_CNTL, 0x40, par);
- // disable display requests, disable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
- mdelay(10);
-
- aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par);
-
- aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par);
- aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par);
- aty_st_le16(CUSTOM_MACRO_CNTL+2, card->custom_macro_cntl>>16, par);
- aty_st_8(CUSTOM_MACRO_CNTL+1,
- (card->custom_macro_cntl>>8) & 0xff, par);
-
- aty_st_le32(MEM_ADDR_CONFIG, card->mem_addr_config, par);
- aty_st_le32(MEM_CNTL, card->mem_cntl, par);
- aty_st_le32(EXT_MEM_CNTL, card->ext_mem_cntl, par);
-
- aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par);
-
- aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par);
- mdelay(15);
- aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
- mdelay(1);
-
- reset_clocks(par, &pll.ct, 0);
- mdelay(50);
- reset_clocks(par, &pll.ct, 0);
- mdelay(50);
-
- // enable extended register block
- aty_st_8(BUS_CNTL+3, 0x7B, par);
- mdelay(1);
- // disable extended register block
- aty_st_8(BUS_CNTL+3, 0x73, par);
-
- aty_st_8(CONFIG_STAT0, 0x80 | card->mem_type, par);
-
- // disable display requests, disable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
- // disable mapping registers in VGA aperture
- aty_st_8(CONFIG_CNTL, aty_ld_8(CONFIG_CNTL, par) & ~0x04, par);
- mdelay(50);
- // enable display requests, enable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
-
- // make GPIO's 14,15,16 all inputs
- aty_st_8(LCD_INDEX, 0x07, par);
- aty_st_8(LCD_DATA+3, 0x00, par);
-
- // enable the display
- aty_st_8(CRTC_GEN_CNTL, 0x00, par);
- mdelay(17);
- // reset the memory controller
- aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
- mdelay(15);
- aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
- mdelay(30);
-
- // enable extended register block
- aty_st_8(BUS_CNTL+3,
- (u8)(aty_ld_8(BUS_CNTL+3, par) | 0x08),
- par);
- // set FIFO size to 512 (PIO)
- aty_st_le32(GUI_CNTL,
- aty_ld_le32(GUI_CNTL, par) & ~0x3,
- par);
-
- // enable CRT and disable lcd
- aty_st_8(LCD_INDEX, 0x01, par);
- temp = aty_ld_le32(LCD_DATA, par);
- temp = (temp | 0x01) & ~0x02;
- aty_st_le32(LCD_DATA, temp, par);
- return 0;
-}
-
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a5129806172f..2406899f1207 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -379,7 +379,7 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
* 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)
+int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
{
struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
unsigned int len;
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 6a219b2c77e3..d0aaf450e8c7 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -20,6 +20,7 @@
#include <linux/backlight.h>
#include <asm/arch/sharpsl.h>
+#include <asm/hardware/sharpsl_pm.h>
#define CORGI_DEFAULT_INTENSITY 0x1f
#define CORGI_LIMIT_MASK 0x0b
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 9248fe1fbb1a..c029db4646f6 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -35,9 +35,8 @@
static int bw2_blank(int, struct fb_info *);
-static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int bw2_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
+static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -169,7 +168,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = {
{ .size = 0 }
};
-static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct bw2_par *par = (struct bw2_par *)info->par;
@@ -181,8 +180,7 @@ static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct bw2_par *par = (struct bw2_par *) info->par;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index a56147102abb..63b6c79c8a0a 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -31,9 +31,8 @@
static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
-static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int cg14_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -268,7 +267,7 @@ static int cg14_setcolreg(unsigned regno,
return 0;
}
-static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct cg14_par *par = (struct cg14_par *) info->par;
@@ -277,8 +276,7 @@ static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_str
par->iospace, vma);
}
-static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct cg14_par *par = (struct cg14_par *) info->par;
struct cg14_regs __iomem *regs = par->regs;
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 9fcd89608ed7..3de6e1b5ab2f 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -33,9 +33,8 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int cg3_blank(int, struct fb_info *);
-static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int cg3_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int cg3_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -230,7 +229,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = {
{ .size = 0 }
};
-static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct cg3_par *par = (struct cg3_par *)info->par;
@@ -240,8 +239,7 @@ static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct cg3_par *par = (struct cg3_par *) info->par;
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 050835e39aa3..7aab91ead681 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -36,9 +36,8 @@ static int cg6_blank(int, struct fb_info *);
static void cg6_imageblit(struct fb_info *, const struct fb_image *);
static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
static int cg6_sync(struct fb_info *);
-static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int cg6_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -524,7 +523,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = {
{ .size = 0 }
};
-static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct cg6_par *par = (struct cg6_par *)info->par;
@@ -534,8 +533,7 @@ static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct cg6_par *par = (struct cg6_par *) info->par;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index a5d09e159cd1..6ee449858a5c 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 && !SPARC && !M68K && !PARISC && !ARCH_VERSATILE
+ depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE
default y
help
Saying Y here will allow you to use Linux in text mode through a
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index e65fc3ef7630..eea422eb1ab5 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -234,14 +234,14 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void bit_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines, int fg, int bg)
+static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1;
char *src;
@@ -310,7 +310,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
@@ -323,10 +323,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3660e51b2612..041d06987861 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -209,13 +209,13 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
#endif
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
-static inline void fbcon_set_rotation(struct fb_info *info, struct display *p)
+static inline void fbcon_set_rotation(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
if (!(info->flags & FBINFO_MISC_TILEBLITTING) &&
- p->con_rotate < 4)
- ops->rotate = p->con_rotate;
+ ops->p->con_rotate < 4)
+ ops->rotate = ops->p->con_rotate;
else
ops->rotate = 0;
}
@@ -265,7 +265,7 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
fbcon_set_all_vcs(info);
}
#else
-static inline void fbcon_set_rotation(struct fb_info *info, struct display *p)
+static inline void fbcon_set_rotation(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
@@ -402,7 +402,7 @@ static void fb_flashcursor(void *private)
c = scr_readw((u16 *) vc->vc_pos);
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
CM_ERASE : CM_DRAW;
- ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1),
+ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
release_console_sem();
}
@@ -647,29 +647,27 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
}
#ifdef CONFIG_FB_TILEBLITTING
-static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
- struct display *p)
+static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
- ops->p = (p) ? p : &fb_display[vc->vc_num];
+ ops->p = &fb_display[vc->vc_num];
if ((info->flags & FBINFO_MISC_TILEBLITTING))
- fbcon_set_tileops(vc, info, p, ops);
+ fbcon_set_tileops(vc, info);
else {
- fbcon_set_rotation(info, ops->p);
+ fbcon_set_rotation(info);
fbcon_set_bitops(ops);
}
}
#else
-static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
- struct display *p)
+static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
info->flags &= ~FBINFO_MISC_TILEBLITTING;
- ops->p = (p) ? p : &fb_display[vc->vc_num];
- fbcon_set_rotation(info, ops->p);
+ ops->p = &fb_display[vc->vc_num];
+ fbcon_set_rotation(info);
fbcon_set_bitops(ops);
}
#endif /* CONFIG_MISC_TILEBLITTING */
@@ -689,15 +687,14 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
err = -ENODEV;
if (!err) {
- ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
if (!ops)
err = -ENOMEM;
}
if (!err) {
- memset(ops, 0, sizeof(struct fbcon_ops));
info->fbcon_par = ops;
- set_blitting_type(vc, info, NULL);
+ set_blitting_type(vc, info);
}
if (err) {
@@ -921,19 +918,18 @@ static const char *fbcon_startup(void)
return NULL;
}
- ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
if (!ops) {
module_put(owner);
return NULL;
}
- memset(ops, 0, sizeof(struct fbcon_ops));
ops->currcon = -1;
ops->graphics = 1;
ops->cur_rotate = -1;
info->fbcon_par = ops;
p->con_rotate = rotate;
- set_blitting_type(vc, info, NULL);
+ set_blitting_type(vc, info);
if (info->fix.type != FB_TYPE_TEXT) {
if (fbcon_softback_size) {
@@ -1093,7 +1089,7 @@ static void fbcon_init(struct vc_data *vc, int init)
ops = info->fbcon_par;
p->con_rotate = rotate;
- set_blitting_type(vc, info, NULL);
+ set_blitting_type(vc, info);
cols = vc->vc_cols;
rows = vc->vc_rows;
@@ -1110,7 +1106,7 @@ static void fbcon_init(struct vc_data *vc, int init)
*
* We need to do it in fbcon_init() to prevent screen corruption.
*/
- if (CON_IS_VISIBLE(vc)) {
+ if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
if (info->fbops->fb_set_par &&
!(ops->flags & FBCON_FLAGS_INIT))
info->fbops->fb_set_par(info);
@@ -1141,9 +1137,9 @@ static void fbcon_init(struct vc_data *vc, int init)
if (vc == svc && softback_buf)
fbcon_update_softback(vc);
- if (ops->rotate_font && ops->rotate_font(info, vc, p)) {
+ if (ops->rotate_font && ops->rotate_font(info, vc)) {
ops->rotate = FB_ROTATE_UR;
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
}
}
@@ -1243,7 +1239,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
- struct display *p = &fb_display[vc->vc_num];
int y;
int c = scr_readw((u16 *) vc->vc_pos);
@@ -1260,7 +1255,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
y = 0;
}
- ops->cursor(vc, info, p, mode, y, get_color(vc, info, c, 1),
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
@@ -1411,16 +1406,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct display *p = &fb_display[vc->vc_num];
- int redraw = 0;
p->yscroll += count;
+
if (p->yscroll > p->vrows - vc->vc_rows) {
p->yscroll -= p->vrows - vc->vc_rows;
- redraw = 1;
- }
-
- if (redraw)
fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
+ }
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
@@ -1462,16 +1454,13 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct display *p = &fb_display[vc->vc_num];
- int redraw = 0;
p->yscroll -= count;
+
if (p->yscroll < 0) {
p->yscroll += p->vrows - vc->vc_rows;
- redraw = 1;
- }
-
- if (redraw)
fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
+ }
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
@@ -1968,7 +1957,8 @@ static __inline__ void updatescrollmode(struct display *p,
divides(ypan, vc->vc_font.height) && vyres > yres;
int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
divides(ywrap, vc->vc_font.height) &&
- divides(vc->vc_font.height, vyres);
+ divides(vc->vc_font.height, vyres) &&
+ divides(vc->vc_font.height, yres);
int reading_fast = cap & FBINFO_READS_FAST;
int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED);
@@ -2107,16 +2097,19 @@ static int fbcon_switch(struct vc_data *vc)
info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
if (info->fbops->fb_set_par)
info->fbops->fb_set_par(info);
- fbcon_del_cursor_timer(old_info);
- fbcon_add_cursor_timer(info);
+
+ if (old_info != info) {
+ fbcon_del_cursor_timer(old_info);
+ fbcon_add_cursor_timer(info);
+ }
}
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
ops->cursor_reset = 1;
- if (ops->rotate_font && ops->rotate_font(info, vc, p)) {
+ if (ops->rotate_font && ops->rotate_font(info, vc)) {
ops->rotate = FB_ROTATE_UR;
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
}
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
@@ -2739,7 +2732,7 @@ static void fbcon_modechanged(struct fb_info *info)
return;
p = &fb_display[vc->vc_num];
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
if (CON_IS_VISIBLE(vc)) {
var_to_display(p, &info->var, info);
@@ -2781,7 +2774,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
continue;
p = &fb_display[vc->vc_num];
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
var_to_display(p, &info->var, info);
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
@@ -2806,6 +2799,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
fbcon_update_softback(vc);
}
}
+
+ ops->p = &fb_display[ops->currcon];
}
static int fbcon_mode_deleted(struct fb_info *info,
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 6892e7ff34de..c38c3d8e7a74 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -62,12 +62,10 @@ struct fbcon_ops {
int fg, int bg);
void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
int bottom_only);
- void (*cursor)(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg);
+ void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg);
int (*update_start)(struct fb_info *info);
- int (*rotate_font)(struct fb_info *info, struct vc_data *vc,
- struct display *p);
+ int (*rotate_font)(struct fb_info *info, struct vc_data *vc);
struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */
struct timer_list cursor_timer; /* Cursor timer */
struct fb_cursor cursor_state;
@@ -173,8 +171,7 @@ struct fbcon_ops {
#define SCROLL_PAN_REDRAW 0x005
#ifdef CONFIG_FB_TILEBLITTING
-extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
- struct display *p, struct fbcon_ops *ops);
+extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif
extern void fbcon_set_bitops(struct fbcon_ops *ops);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 4952b66ae206..990289a69b78 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -219,19 +219,18 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1, dx, dy;
char *src;
- u32 vyres = GETVYRES(p->scrollmode, info);
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
if (!ops->fontbuffer)
return;
@@ -303,7 +302,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
@@ -323,10 +322,10 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6d92b8456206..d44c5fa515fb 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -203,19 +203,18 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void cw_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1, dx, dy;
char *src;
- u32 vxres = GETVXRES(p->scrollmode, info);
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
if (!ops->fontbuffer)
return;
@@ -287,7 +286,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
@@ -307,10 +306,10 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c
index ec0dd8fe241c..2dc091fbd5c9 100644
--- a/drivers/video/console/fbcon_rotate.c
+++ b/drivers/video/console/fbcon_rotate.c
@@ -18,8 +18,7 @@
#include "fbcon.h"
#include "fbcon_rotate.h"
-static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc,
- struct display *p)
+static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
{
struct fbcon_ops *ops = info->fbcon_par;
int len, err = 0;
@@ -28,12 +27,12 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc,
u8 *dst;
if (vc->vc_font.data == ops->fontdata &&
- p->con_rotate == ops->cur_rotate)
+ ops->p->con_rotate == ops->cur_rotate)
goto finished;
src = ops->fontdata = vc->vc_font.data;
- ops->cur_rotate = p->con_rotate;
- len = (!p->userfont) ? 256 : FNTCHARCNT(src);
+ ops->cur_rotate = ops->p->con_rotate;
+ len = (!ops->p->userfont) ? 256 : FNTCHARCNT(src);
s_cellsize = ((vc->vc_font.width + 7)/8) *
vc->vc_font.height;
d_cellsize = s_cellsize;
diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h
index 1b8f92fdc6a8..75be5ce53dc5 100644
--- a/drivers/video/console/fbcon_rotate.h
+++ b/drivers/video/console/fbcon_rotate.h
@@ -11,8 +11,6 @@
#ifndef _FBCON_ROTATE_H
#define _FBCON_ROTATE_H
-#define FNTCHARCNT(fd) (((int *)(fd))[-3])
-
#define GETVYRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
(i)->var.yres : (i)->var.yres_virtual; })
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index 9dd059e8b645..f56ed068a5bc 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -249,20 +249,19 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void ud_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1, dx, dy;
char *src;
- u32 vyres = GETVYRES(p->scrollmode, info);
- u32 vxres = GETVXRES(p->scrollmode, info);
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
if (!ops->fontbuffer)
return;
@@ -334,7 +333,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
@@ -347,10 +346,10 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 8529bf08db28..3957fc7523e2 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -17,6 +17,8 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#include "fbcon.h"
+
int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
unsigned int scan_align = info->pixmap.scan_align - 1;
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
index cb25324a5635..153352ca9461 100644
--- a/drivers/video/console/tileblit.c
+++ b/drivers/video/console/tileblit.c
@@ -80,9 +80,8 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
return;
}
-static void tile_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_tilecursor cursor;
int use_sw = (vc->vc_cursor_type & 0x01);
@@ -130,10 +129,10 @@ static int tile_update_start(struct fb_info *info)
return err;
}
-void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
- struct display *p, struct fbcon_ops *ops)
+void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
{
struct fb_tilemap map;
+ struct fbcon_ops *ops = info->fbcon_par;
ops->bmove = tile_bmove;
ops->clear = tile_clear;
@@ -142,13 +141,13 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
ops->cursor = tile_cursor;
ops->update_start = tile_update_start;
- if (p) {
+ if (ops->p) {
map.width = vc->vc_font.width;
map.height = vc->vc_font.height;
map.depth = 1;
- map.length = (p->userfont) ?
- FNTCHARCNT(p->fontdata) : 256;
- map.data = p->fontdata;
+ map.length = (ops->p->userfont) ?
+ FNTCHARCNT(ops->p->fontdata) : 256;
+ map.data = ops->p->fontdata;
info->tileops->fb_settile(info, &map);
}
}
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 167de397e4b4..12d9329d1408 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -56,6 +56,8 @@
static DEFINE_SPINLOCK(vga_lock);
static int cursor_size_lastfrom;
static int cursor_size_lastto;
+static u32 vgacon_xres;
+static u32 vgacon_yres;
static struct vgastate state;
#define BLANK 0x0020
@@ -69,7 +71,7 @@ static struct vgastate state;
* appear.
*/
#undef TRIDENT_GLITCH
-
+#define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */
/*
* Interface used by the world
*/
@@ -325,6 +327,10 @@ static const char __init *vgacon_startup(void)
vga_scan_lines =
vga_video_font_height * vga_video_num_lines;
}
+
+ vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
+ vgacon_yres = vga_scan_lines;
+
return display_desc;
}
@@ -503,10 +509,18 @@ static int vgacon_doresize(struct vc_data *c,
{
unsigned long flags;
unsigned int scanlines = height * c->vc_font.height;
- u8 scanlines_lo, r7, vsync_end, mode;
+ u8 scanlines_lo, r7, vsync_end, mode, max_scan;
spin_lock_irqsave(&vga_lock, flags);
+ outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
+ max_scan = inb_p(vga_video_port_val);
+
+ if (max_scan & 0x80)
+ scanlines <<= 1;
+
+ vgacon_xres = width * VGA_FONTWIDTH;
+ vgacon_yres = height * c->vc_font.height;
outb_p(VGA_CRTC_MODE, vga_video_port_reg);
mode = inb_p(vga_video_port_val);
@@ -551,6 +565,10 @@ static int vgacon_doresize(struct vc_data *c,
static int vgacon_switch(struct vc_data *c)
{
+ int x = c->vc_cols * VGA_FONTWIDTH;
+ int y = c->vc_rows * c->vc_font.height;
+ int rows = ORIG_VIDEO_LINES * vga_default_font_height/
+ c->vc_font.height;
/*
* We need to save screen size here as it's the only way
* we can spot the screen has been resized and we need to
@@ -566,10 +584,11 @@ static int vgacon_switch(struct vc_data *c)
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
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)
+
+ if ((vgacon_xres != x || vgacon_yres != y) &&
+ (!(vga_video_num_columns % 2) &&
+ vga_video_num_columns <= ORIG_VIDEO_COLS &&
+ vga_video_num_lines <= rows))
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
@@ -993,7 +1012,8 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- if (font->width != 8 || (charcount != 256 && charcount != 512))
+ if (font->width != VGA_FONTWIDTH ||
+ (charcount != 256 && charcount != 512))
return -EINVAL;
rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
@@ -1010,7 +1030,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- font->width = 8;
+ font->width = VGA_FONTWIDTH;
font->height = c->vc_font.height;
font->charcount = vga_512_chars ? 512 : 256;
if (!font->data)
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 403d17377f8d..655301a8671c 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -128,17 +128,11 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int controlfb_blank(int blank_mode, struct fb_info *info);
-static int controlfb_mmap(struct fb_info *info, struct file *file,
+static int controlfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static int controlfb_set_par (struct fb_info *info);
static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
-/*
- * inititialization
- */
-int control_init(void);
-void control_setup(char *);
-
/******************** Prototypes for internal functions **********************/
static void set_control_clock(unsigned char *params);
@@ -286,7 +280,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
* for controlfb.
* Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
*/
-static int controlfb_mmap(struct fb_info *info, struct file *file,
+static int controlfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long off, start;
@@ -550,9 +544,46 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
/*
- * Called from fbmem.c for probing & initializing
+ * Parse user speficied options (`video=controlfb:')
*/
-int __init control_init(void)
+static void __init control_setup(char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "vmode:", 6)) {
+ int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX &&
+ control_mac_modes[vmode - 1].m[1] >= 0)
+ default_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ int depth = simple_strtoul(this_opt+6, NULL, 0);
+ switch (depth) {
+ case CMODE_8:
+ case CMODE_16:
+ case CMODE_32:
+ default_cmode = depth;
+ break;
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
+ }
+}
+
+static int __init control_init(void)
{
struct device_node *dp;
char *option = NULL;
@@ -651,15 +682,16 @@ static void __init find_vram_size(struct fb_info_control *p)
static int __init control_of_init(struct device_node *dp)
{
struct fb_info_control *p;
- unsigned long addr;
- int i;
+ struct resource fb_res, reg_res;
if (control_fb) {
printk(KERN_ERR "controlfb: only one control is supported\n");
return -ENXIO;
}
- if(dp->n_addrs != 2) {
- printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);
+
+ if (of_pci_address_to_resource(dp, 2, &fb_res) ||
+ of_pci_address_to_resource(dp, 1, &reg_res)) {
+ printk(KERN_ERR "can't get 2 addresses for control\n");
return -ENXIO;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -669,18 +701,12 @@ static int __init control_of_init(struct device_node *dp)
memset(p, 0, sizeof(*p));
/* Map in frame buffer and registers */
- for (i = 0; i < dp->n_addrs; ++i) {
- addr = dp->addrs[i].address;
- if (dp->addrs[i].size >= 0x800000) {
- p->fb_orig_base = addr;
- p->fb_orig_size = dp->addrs[i].size;
- /* use the big-endian aperture (??) */
- p->frame_buffer_phys = addr + 0x800000;
- } else {
- p->control_regs_phys = addr;
- p->control_regs_size = dp->addrs[i].size;
- }
- }
+ p->fb_orig_base = fb_res.start;
+ p->fb_orig_size = fb_res.end - fb_res.start + 1;
+ /* use the big-endian aperture (??) */
+ p->frame_buffer_phys = fb_res.start + 0x800000;
+ p->control_regs_phys = reg_res.start;
+ p->control_regs_size = reg_res.end - reg_res.start + 1;
if (!p->fb_orig_base ||
!request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
@@ -1059,43 +1085,3 @@ static void control_cleanup(void)
}
-/*
- * Parse user speficied options (`video=controlfb:')
- */
-void __init control_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!strncmp(this_opt, "vmode:", 6)) {
- int vmode = simple_strtoul(this_opt+6, NULL, 0);
- if (vmode > 0 && vmode <= VMODE_MAX &&
- control_mac_modes[vmode - 1].m[1] >= 0)
- default_vmode = vmode;
- } else if (!strncmp(this_opt, "cmode:", 6)) {
- int depth = simple_strtoul(this_opt+6, NULL, 0);
- switch (depth) {
- case CMODE_8:
- case CMODE_16:
- case CMODE_32:
- default_cmode = depth;
- break;
- case 8:
- default_cmode = CMODE_8;
- break;
- case 15:
- case 16:
- default_cmode = CMODE_16;
- break;
- case 24:
- case 32:
- default_cmode = CMODE_32;
- break;
- }
- }
- }
-}
-
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index a9300f930ef2..55a3514157ed 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -50,7 +50,6 @@
#include <linux/init.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 03fbe83d71a8..2b972461a030 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -7,11 +7,12 @@
* tridentfb.c by Jani Monoses
* see files above for further credits
*
- * TODO:
- *
*/
#define CYBLAFB_DEBUG 0
+#define CYBLAFB_KD_GRAPHICS_QUIRK 1
+
+#define CYBLAFB_PIXMAPSIZE 8192
#include <linux/config.h>
#include <linux/module.h>
@@ -22,7 +23,7 @@
#include <asm/types.h>
#include <video/cyblafb.h>
-#define VERSION "0.54"
+#define VERSION "0.62"
struct cyblafb_par {
u32 pseudo_pal[16];
@@ -32,7 +33,9 @@ struct cyblafb_par {
static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
.id = "CyBla",
.type = FB_TYPE_PACKED_PIXELS,
+ .xpanstep = 1,
.ypanstep = 1,
+ .ywrapstep = 1,
.visual = FB_VISUAL_PSEUDOCOLOR,
.accel = FB_ACCEL_NONE,
};
@@ -43,8 +46,9 @@ static int ref __devinitdata = 75;
static int fp __devinitdata;
static int crt __devinitdata;
static int memsize __devinitdata;
-static int vesafb __devinitdata;
+static int basestride;
+static int vesafb;
static int nativex;
static int center;
static int stretch;
@@ -52,26 +56,50 @@ static int pciwb = 1;
static int pcirb = 1;
static int pciwr = 1;
static int pcirr = 1;
+static int disabled;
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);
+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);
+
+//=========================================
+//
+// Well, we have to fix the upper layers.
+// Until this has been done, we work around
+// the bugs.
+//
+//=========================================
+
+#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG)
+ if (disabled) { \
+ printk("********\n");\
+ dump_stack();\
+ return val;\
+ }
+
+#elif CYBLAFB_KD_GRAPHICS_QUIRK
+#define KD_GRAPHICS_RETURN(val)\
+ if (disabled) {\
+ return val;\
+ }
+#else
+#define KD_GRAPHICS_RETURN(val)
+#endif
//=========================================
//
@@ -79,10 +107,10 @@ module_param(vesafb,int,0);
//
//=========================================
-#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)
+#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)
//======================================
//
@@ -90,47 +118,47 @@ module_param(vesafb,int,0);
//
//======================================
-static inline unsigned char read3X4(int reg)
+static inline u8 read3X4(u32 reg)
{
- out8(0x3D4,reg);
+ out8(0x3D4, reg);
return in8(0x3D5);
}
-static inline unsigned char read3C4(int reg)
+static inline u8 read3C4(u32 reg)
{
- out8(0x3C4,reg);
+ out8(0x3C4, reg);
return in8(0x3C5);
}
-static inline unsigned char read3CE(int reg)
+static inline u8 read3CE(u32 reg)
{
- out8(0x3CE,reg);
+ out8(0x3CE, reg);
return in8(0x3CF);
}
-static inline void write3X4(int reg,unsigned char val)
+static inline void write3X4(u32 reg, u8 val)
{
- out8(0x3D4,reg);
- out8(0x3D5,val);
+ out8(0x3D4, reg);
+ out8(0x3D5, val);
}
-static inline void write3C4(int reg,unsigned char val)
+static inline void write3C4(u32 reg, u8 val)
{
- out8(0x3C4,reg);
- out8(0x3C5,val);
+ out8(0x3C4, reg);
+ out8(0x3C5, val);
}
-static inline void write3CE(int reg,unsigned char val)
+static inline void write3CE(u32 reg, u8 val)
{
- out8(0x3CE,reg);
- out8(0x3CF,val);
+ out8(0x3CE, reg);
+ out8(0x3CF, val);
}
-static inline void write3C0(int reg,unsigned char val)
+static inline void write3C0(u32 reg, u8 val)
{
- in8(0x3DA); // read to reset index
- out8(0x3C0,reg);
- out8(0x3C0,val);
+ in8(0x3DA); // read to reset index
+ out8(0x3C0, reg);
+ out8(0x3C0, val);
}
//=================================================
@@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val)
//
//=================================================
-static inline void enable_mmio(void)
+static void enable_mmio(void)
{
- int tmp;
+ u8 tmp;
- outb(0x0B,0x3C4);
+ outb(0x0B, 0x3C4);
inb(0x3C5); // Set NEW mode
- outb(SR0E,0x3C4); // write enable a lot of extended ports
- outb(0x80,0x3C5);
+ 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(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(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
+ outb(CR39, 0x3D4);
+ outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio
}
//=================================================
//
// Set pixel clock VCLK1
-// - multipliers set elswhere
-// - freq in units of 0.01 MHz
+// - multipliers set elswhere
+// - freq in units of 0.01 MHz
+//
+// Hardware bug: SR18 >= 250 is broken for the
+// cyberblade/i1
//
//=================================================
static void set_vclk(struct cyblafb_par *par, int freq)
{
- u32 m,n,k;
- int f,fi,d,di;
- u8 lo=0,hi=0;
+ 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);
+ for (m = 0; m < 64; m++)
+ for (n = 0; n < 250; n++) {
+ 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)
+ write3C4(SR19, hi);
+ write3C4(SR18, lo);
+ if (verbosity > 0)
output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
- freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+ freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo);
}
//================================================
@@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq)
//
//================================================
-static void cyblafb_setup_GE(int pitch,int bpp)
+static void cyblafb_setup_GE(int pitch, int bpp)
{
- int base = (pitch>>3)<<20;
+ KD_GRAPHICS_RETURN();
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;
+ case 8:
+ basestride = ((pitch >> 3) << 20) | (0 << 29);
+ break;
+ case 15:
+ basestride = ((pitch >> 3) << 20) | (5 << 29);
+ break;
+ case 16:
+ basestride = ((pitch >> 3) << 20) | (1 << 29);
+ break;
+ case 24:
+ case 32:
+ basestride = ((pitch >> 3) << 20) | (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
+ write3X4(CR36, 0x90); // reset GE
+ write3X4(CR36, 0x80); // enable GE
+ out32(GE24, 1 << 7); // reset all GE pointers by toggling
+ out32(GE24, 0); // d7 of GE24
+ write3X4(CR2D, 0x00); // GE Timinigs, no delays
+ 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.
+// Cyberblade specific syncing
+//
+// A 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
+// First we try to sync ignoring that problem, as most of the
+// time that will succeed immediately and the enable_mmio()
+// would only degrade performance.
//
//=====================================================================
static int cyblafb_sync(struct fb_info *info)
{
- int status, i=100000;
- while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+ u32 status, i = 100000;
+
+ KD_GRAPHICS_RETURN(0);
+
+ while (((status = in32(GE20)) & 0xFe800000) && 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 = 1000000;
+ while (((status = in32(GE20)) & 0xFA800000) && i != 0)
i--;
if (i == 0) {
- output("GE Timeout, status: %x\n",status);
- if(status & 0x80000000)
+ output("GE Timeout, status: %x\n", status);
+ if (status & 0x80000000)
output("Bresenham Engine : Busy\n");
- if(status & 0x40000000)
+ if (status & 0x40000000)
output("Setup Engine : Busy\n");
- if(status & 0x20000000)
+ if (status & 0x20000000)
output("SP / DPE : Busy\n");
- if(status & 0x10000000)
+ if (status & 0x10000000)
output("Memory Interface : Busy\n");
- if(status & 0x08000000)
+ if (status & 0x08000000)
output("Com Lst Proc : Busy\n");
- if(status & 0x04000000)
+ if (status & 0x04000000)
output("Block Write : Busy\n");
- if(status & 0x02000000)
+ if (status & 0x02000000)
output("Command Buffer : Full\n");
- if(status & 0x01000000)
+ if (status & 0x01000000)
output("RESERVED : Busy\n");
- if(status & 0x00800000)
+ if (status & 0x00800000)
output("PCI Write Buffer : Busy\n");
cyblafb_setup_GE(info->var.xres,
info->var.bits_per_pixel);
@@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info)
//
//==============================
-static void cyblafb_fillrect(struct fb_info * info,
- const struct fb_fillrect *fr)
+static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr)
{
- int bpp = info->var.bits_per_pixel;
- int col;
+ u32 bpp = info->var.bits_per_pixel, col, desty, height;
+
+ KD_GRAPHICS_RETURN();
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;
+ 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));
-
+ desty = fr->dy;
+ height = fr->height;
+ while (height) {
+ out32(GEB8, basestride | ((desty * info->var.xres_virtual *
+ bpp) >> 6));
+ out32(GE60, col);
+ out32(GE48, fr->rop ? 0x66 : ROP_S);
+ out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+ out32(GE08, point(fr->dx, 0));
+ out32(GE0C, point(fr->dx + fr->width - 1,
+ height > 4096 ? 4095 : height - 1));
+ if (likely(height <= 4096))
+ return;
+ desty += 4096;
+ height -= 4096;
+ }
}
-//==============================
+//================================================
//
// Cyberblade specific copyarea
//
-//==============================
+// This function silently assumes that it never
+// will be called with width or height exceeding
+// 4096.
+//
+//================================================
-static void cyblafb_copyarea(struct fb_info *info,
- const struct fb_copyarea *ca)
+static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
{
- __u32 s1,s2,d1,d2;
- int direction;
+ u32 s1, s2, d1, d2, direction;
+
+ KD_GRAPHICS_RETURN();
+
+ s1 = point(ca->sx, 0);
+ s2 = point(ca->sx + ca->width - 1, ca->height - 1);
+ d1 = point(ca->dx, 0);
+ d2 = point(ca->dx + ca->width - 1, ca->height - 1);
- 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);
-
+ out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual *
+ info->var.bits_per_pixel) >> 6));
+ out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual *
+ info->var.bits_per_pixel) >> 6));
+ 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.
+// Accelerated for the most usual case, blitting 1 - bit deep
+// character images. Everything else is passed to the generic imageblit
+// unless it is so insane that it is better to printk an alert.
+//
+// Hardware bug: _Never_ blit across pixel column 2048, that will lock
+// the system. We split those blit requests into three blitting
+// operations.
//
//=======================================================================
static void cyblafb_imageblit(struct fb_info *info,
const struct fb_image *image)
{
-
u32 fgcol, bgcol;
+ u32 *pd = (u32 *) image->data;
+ u32 bpp = info->var.bits_per_pixel;
- 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);
+ KD_GRAPHICS_RETURN();
+
+ // Used only for drawing the penguine (image->depth > 1)
+ if (image->depth != 1) {
+ cfb_imageblit(info, image);
+ return;
+ }
+ // That should never happen, but it would be fatal
+ if (image->width == 0 || image->height == 0) {
+ output("imageblit: width/height 0 detected\n");
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];
+ 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;
+ case 8:
+ fgcol |= fgcol << 8;
+ bgcol |= bgcol << 8;
+ case 16:
+ fgcol |= fgcol << 16;
+ bgcol |= bgcol << 16;
+ 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));
+ out32(GEB8, basestride | ((image->dy * info->var.xres_virtual *
+ bpp) >> 6));
+ out32(GE60, fgcol);
+ out32(GE64, bgcol);
+
+ if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) {
+ u32 dds = ((image->width + 31) >> 5) * image->height;
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(image->dx, 0));
+ out32(GE0C, point(image->dx + image->width - 1,
+ image->height - 1));
+ while (dds--)
+ out32(GE9C, *pd++);
+ } else {
+ int i, j;
+ u32 ddstotal = (image->width + 31) >> 5;
+ u32 ddsleft = (2048 - image->dx + 31) >> 5;
+ u32 skipleft = ddstotal - ddsleft;
+
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(image->dx, 0));
+ out32(GE0C, point(2048 - 1, image->height - 1));
+ for (i = 0; i < image->height; i++) {
+ for (j = 0; j < ddsleft; j++)
+ out32(GE9C, *pd++);
+ pd += skipleft;
+ }
- 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;
+ if (image->dx % 32) {
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(2048, 0));
+ if (image->width > ddsleft << 5)
+ out32(GE0C, point(image->dx + (ddsleft << 5) -
+ 1, image->height - 1));
+ else
+ out32(GE0C, point(image->dx + image->width - 1,
+ image->height - 1));
+ pd = ((u32 *) image->data) + ddstotal - skipleft - 1;
+ for (i = 0; i < image->height; i++) {
+ out32(GE9C, swab32(swab32(*pd) << ((32 -
+ (image->dx & 31)) & 31)));
+ pd += ddstotal;
+ }
}
- 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;
+
+ if (skipleft) {
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(image->dx + (ddsleft << 5), 0));
+ out32(GE0C, point(image->dx + image->width - 1,
+ image->height - 1));
+ pd = (u32 *) image->data;
+ for (i = 0; i < image->height; i++) {
+ pd += ddsleft;
+ for (j = 0; j < skipleft; j++)
+ out32(GE9C, *pd++);
+ }
}
}
}
@@ -443,7 +526,6 @@ 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,
@@ -453,9 +535,9 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
// (This is what tridentfb does ... will be changed in the future)
//
//
- if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+ if (bpp % 8 != 0 || bpp < 8 || bpp > 32)
bpp = 8;
- if (bpp == 24 )
+ if (bpp == 24)
bpp = var->bits_per_pixel = 32;
//
@@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
//
- // xres != xres_virtual is broken, fail if such an
- // unusual mode is requested
+ // we do not allow vclk to exceed 230 MHz. If the requested
+ // vclk is too high, we default to 200 MHz
//
- if (var->xres != var->xres_virtual)
- return -EINVAL;
+ if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000)
+ var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000;
//
- // we do not allow vclk to exceed 230 MHz
+ // enforce (h|v)sync_len limits
//
- if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
- return -EINVAL;
+ var->hsync_len &= ~7;
+ if(var->hsync_len > 248)
+ var->hsync_len = 248;
+
+ var->vsync_len &= 15;
//
- // 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
+ // Enforce horizontal and vertical hardware limits.
+ // 1600x1200 is mentioned as a maximum, but higher resolutions could
+ // work with slow refresh, small margins and short sync.
//
- 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)
+ var->xres &= ~7;
+
+ if (((var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||
+ ((var->yres + var->upper_margin + var->lower_margin +
+ var->vsync_len) > 2047))
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:
+ if ((var->xres > 1600) || (var->yres > 1200))
+ output("Mode %dx%d exceeds documented limits.\n",
+ var->xres, var->yres);
+ //
+ // try to be smart about (x|y)res_virtual problems.
+ //
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (bpp == 8 || bpp == 16) {
+ if (var->xres_virtual > 4088)
+ var->xres_virtual = 4088;
+ } else {
+ if (var->xres_virtual > 2040)
+ var->xres_virtual = 2040;
+ }
+ var->xres_virtual &= ~7;
+ while (var->xres_virtual * var->yres_virtual * bpp / 8 >
+ info->fix.smem_len) {
+ if (var->yres_virtual > var->yres)
+ var->yres_virtual--;
+ else if (var->xres_virtual > var->xres)
+ var->xres_virtual -= 8;
+ else
return -EINVAL;
}
- return 0;
+ 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;
}
//=====================================================================
@@ -543,23 +653,25 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
// 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.
//
+// BUT:
+//
+// As of internal version 0.60 we do not use vga panning any longer.
+// Vga panning did not allow us the use of all available video memory
+// and thus prevented ywrap scrolling. We do use the "right view"
+// register now.
+//
+//
//=====================================================================
static int cyblafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- unsigned int offset;
+ KD_GRAPHICS_RETURN(0);
- 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));
-
+ out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *
+ var->xres_virtual)) * var->bits_per_pixel / 32));
return 0;
}
@@ -578,56 +690,96 @@ static void regdump(struct cyblafb_par *par)
return;
printk("\n");
- for(i=0; i<=0xff; i++) {
- outb(i,0x3d4);
- printk("CR%02x=%02x ",i,inb(0x3d5));
- if (i%16==15)
+ 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));
+ 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)
+ if (i % 16 == 15)
printk("\n");
}
- outb(0x30,0x3ce);
- outb(inb(0x3cf) & 0xbf,0x3cf);
+ 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)
+ 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)
+ 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)
+ 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
+ inb(0x3DA); // reset internal flag to 3c0 index
+ outb(0x20, 0x3C0); // enable attr
+
+ return;
+}
+
+//=======================================================================
+//
+// Save State
+//
+// This function is called while a switch to KD_TEXT is in progress,
+// before any of the other functions are called.
+//
+//=======================================================================
+static void cyblafb_save_state(struct fb_info *info)
+{
+ struct cyblafb_par *par = info->par;
+ if (verbosity > 0)
+ output("Switching to KD_TEXT\n");
+ disabled = 0;
+ regdump(par);
+ enable_mmio();
+ return;
+}
+
+//=======================================================================
+//
+// Restore State
+//
+// This function is called while a switch to KD_GRAPHICS is in progress,
+// We have to turn on vga style panning registers again because the
+// trident driver of X does not know about GE10.
+//
+//=======================================================================
+
+static void cyblafb_restore_state(struct fb_info *info)
+{
+ if (verbosity > 0)
+ output("Switching to KD_GRAPHICS\n");
+ out32(GE10, 0);
+ disabled = 1;
return;
}
@@ -640,32 +792,34 @@ static void regdump(struct cyblafb_par *par)
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;
+ 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;
+ KD_GRAPHICS_RETURN(0);
+
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);
+ 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;
+ 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);
+ preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);
vtotal = var->yres + var->upper_margin + var->lower_margin +
- var->vsync_len - 2;
+ var->vsync_len - 2;
vdispend = var->yres - 1;
vsyncstart = var->yres + var->lower_margin;
vblankstart = var->yres;
@@ -674,101 +828,99 @@ static int cyblafb_set_par(struct fb_info *info)
enable_mmio(); // necessary! ... check X ...
- write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+ write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
- write3CE(GR30,8);
+ write3CE(GR30, 8);
if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
// stretch or center ?
- out8(0x3C2,0xEB);
+ out8(0x3C2, 0xEB);
- write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+ 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);
+ 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);
+ 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);
+ 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_virtual * bpp) / (4 * 16)) & 0xFF);
+ write3X4(CR14, 0x40); // double word mode
+ write3X4(CR15, vblankstart & 0xFF);
+ write3X4(CR16, vblankend & 0xFF);
+ write3X4(CR17, 0xE3);
+ 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);
+ 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
+ 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);
+ 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);
+ write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *
+ 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
+ write3X4(CR2F, 0x92); // conservative, better signal quality
// CR30: reserved
// CR31: reserved
// CR32: reserved
@@ -777,96 +929,116 @@ static int cyblafb_set_par(struct fb_info *info)
// 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
+ 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
+ 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);
+ out8(0x3C4, 0x0b);
in8(0x3C5); // Set NEW mode
- write3C4(SR0D,0x00); // test ... check
+ write3C4(SR0D, 0x00); // test ... check
- set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
- info->var.pixclock); //SR18,SR19
+ 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,
+ 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); // vclk / 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
+ 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
+ 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); // 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) |
+ 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->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;
+ info->fix.line_length = info->var.xres_virtual * (bpp >> 3);
+ info->cmap.len = (bpp == 8) ? 256 : 16;
//
// init acceleration engine
//
- cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+ cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);
+
+ //
+ // Set/clear flags to allow proper scroll mode selection.
+ //
+ if (var->xres == var->xres_virtual)
+ info->flags &= ~FBINFO_HWACCEL_XPAN;
+ else
+ info->flags |= FBINFO_HWACCEL_XPAN;
+
+ if (var->yres == var->yres_virtual)
+ info->flags &= ~FBINFO_HWACCEL_YPAN;
+ else
+ info->flags |= FBINFO_HWACCEL_YPAN;
+
+ if (info->fix.smem_len !=
+ var->xres_virtual * var->yres_virtual * bpp / 8)
+ info->flags &= ~FBINFO_HWACCEL_YWRAP;
+ else
+ info->flags |= FBINFO_HWACCEL_YWRAP;
regdump(par);
@@ -885,27 +1057,27 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
{
int bpp = info->var.bits_per_pixel;
+ KD_GRAPHICS_RETURN(0);
+
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);
+ 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;
}
@@ -918,40 +1090,41 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int cyblafb_blank(int blank_mode, struct fb_info *info)
{
- unsigned char PMCont,DPMSCont;
+ unsigned char PMCont, DPMSCont;
+
+ KD_GRAPHICS_RETURN(0);
if (displaytype == DISPLAY_FP)
return 0;
- out8(0x83C8,0x04); // DPMS Control
+ 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
+ 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
+ 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
+ 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
+ case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off
PMCont |= 0x00;
DPMSCont |= 0x03;
break;
}
- write3CE(GR23,DPMSCont);
- out8(0x83C8,4);
- out8(0x83C6,PMCont);
+ write3CE(GR23, DPMSCont);
+ out8(0x83C8, 4);
+ out8(0x83C6, PMCont);
//
// let fbcon do a softblank for us
//
@@ -959,15 +1132,18 @@ static int cyblafb_blank(int blank_mode, struct fb_info *info)
}
static struct fb_ops cyblafb_ops __devinitdata = {
- .owner = THIS_MODULE,
+ .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_copyarea = cyblafb_copyarea,
.fb_imageblit = cyblafb_imageblit,
+ .fb_sync = cyblafb_sync,
+ .fb_restore_state = cyblafb_restore_state,
+ .fb_save_state = cyblafb_save_state,
};
//==========================================================================
@@ -986,74 +1162,89 @@ static struct fb_ops cyblafb_ops __devinitdata = {
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;
+ 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}
+ int xres; int vxres; 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, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, {
+ 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, {
+ 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, {
+ 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, {
+ 1280, 2048, 1024, 4096, 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;
+ 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;
+ 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;
+ 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;
+ | (cr27 & 0x40) << 4;
+ vblankend = cr16;
- modedb[0].yres = vdispend + 1;
- modedb[0].vsync_len = vsyncend;
+ 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;
+ 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;
+ tmp == 8 ? 32 : 8;
- fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+ 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 !
@@ -1062,10 +1253,10 @@ static int __devinit getstartupmode(struct fb_info *info)
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].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);
//
@@ -1073,36 +1264,39 @@ static int __devinit getstartupmode(struct fb_info *info)
// do not want to do it in another way!
//
- tryagain:
+ 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;
+ !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) {
+ 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
- ));
+ ((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;
+ if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32))
+ info->var.xres_virtual = modedb[i].vxres;
+ else
+ 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;
@@ -1114,33 +1308,32 @@ static int __devinit getstartupmode(struct fb_info *info)
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
+ 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){
+ 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;
+ // try 640x480 - 8@75 ...
+ if (i == 0) {
+ mode = "640x480";
+ bpp = 8;
+ ref = 75;
output("Detected mode failed check_var! "
- "Trying 640x480-8@75\n");
+ "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;
+ "Falling back to startup mode.\n", mode);
+ mode = NULL;
goto tryagain;
}
return 0;
-
}
//========================================================
@@ -1160,21 +1353,28 @@ static unsigned int __devinit get_memsize(void)
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);
+ case 0x03:
+ k = 1 * 1024 * 1024;
+ break;
+ case 0x07:
+ k = 2 * 1024 * 1024;
+ break;
+ case 0x0F:
+ k = 4 * 1024 * 1024;
+ break;
+ case 0x04:
+ k = 8 * 1024 * 1024;
+ break;
+ default:
+ k = 1 * 1024 * 1024;
+ 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);
+ output("framebuffer size = %d Kb\n", k / Kb);
return k;
}
@@ -1192,7 +1392,7 @@ static unsigned int __devinit get_displaytype(void)
return DISPLAY_FP;
if (crt)
return DISPLAY_CRT;
- return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+ return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
}
//=====================================
@@ -1203,7 +1403,7 @@ static unsigned int __devinit get_displaytype(void)
static int __devinit get_nativex(void)
{
- int x,y,tmp;
+ int x, y, tmp;
if (nativex)
return nativex;
@@ -1211,29 +1411,45 @@ static int __devinit get_nativex(void)
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;
+ 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);
+ 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)
+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);
-
+ info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev);
if (!info)
- goto errout_alloc;
+ goto errout_alloc_info;
+
+ info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ output("allocation of pixmap buffer failed!\n");
+ goto errout_alloc_pixmap;
+ }
+ info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4;
+ info->pixmap.buf_align = 4;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->pixmap.scan_align = 4;
par = info->par;
par->ops = cyblafb_ops;
@@ -1246,26 +1462,31 @@ static int __devinit cybla_pci_probe(struct pci_dev * 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");
+ if (!request_region(0x3c0, 0x20, "cyblafb")) {
+ output("region 0x3c0/0x20 already reserved\n");
+ vesafb |= 1;
+ }
//
// Graphics Engine Registers
//
- request_region(GEBase,0x100,"cyblafb");
+ if (!request_region(GEBase, 0x100, "cyblafb")) {
+ output("region %#x/0x100 already reserved\n", GEBase);
+ vesafb |= 2;
+ }
regdump(par);
enable_mmio();
// setup MMIO region
- info->fix.mmio_start = pci_resource_start(dev,1);
+ 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")) {
+ info->fix.mmio_len, "cyblafb")) {
output("request_mem_region failed for mmio region!\n");
goto errout_mmio_reqmem;
}
@@ -1276,18 +1497,17 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
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);
+ // is useful if both are loaded.
+ 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->fix.smem_len, "cyblafb")) {
+ output("region %#lx/%#x already reserved\n",
+ info->fix.smem_start, info->fix.smem_len);
+ vesafb |= 4;
}
info->screen_base = ioremap_nocache(info->fix.smem_start,
@@ -1300,31 +1520,30 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
displaytype = get_displaytype();
- if(displaytype == DISPLAY_FP)
+ 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->flags = FBINFO_DEFAULT
+ | FBINFO_HWACCEL_COPYAREA
+ | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_IMAGEBLIT
+ | FBINFO_READS_FAST
+// | FBINFO_PARTIAL_PAN_OK
+ | FBINFO_MISC_ALWAYS_SETPAR;
info->pseudo_palette = par->pseudo_pal;
- if(getstartupmode(info))
+ if (getstartupmode(info))
goto errout_findmode;
- fb_alloc_cmap(&info->cmap,256,0);
+ 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);
+ pci_set_drvdata(dev, info);
//
// normal exit and error paths
@@ -1332,23 +1551,24 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
return 0;
- errout_register:
- errout_findmode:
+ 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:
+ errout_smem_remap:
+ if (!(vesafb & 4))
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
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:
+ errout_mmio_remap:
+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ errout_mmio_reqmem:
+ if (!(vesafb & 1))
+ release_region(0x3c0, 32);
+ errout_enable:
+ kfree(info->pixmap.addr);
+ errout_alloc_pixmap:
framebuffer_release(info);
- errout_alloc:
- output("CyblaFB version %s aborting init.\n",VERSION);
+ errout_alloc_info:
+ output("CyblaFB version %s aborting init.\n", VERSION);
return -ENODEV;
}
@@ -1359,35 +1579,41 @@ static void __devexit cybla_pci_remove(struct pci_dev *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);
+ if (!(vesafb & 4))
+ 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);
+ if (!(vesafb & 2))
+ release_region(GEBase, 0x100);
+ if (!(vesafb & 1))
+ release_region(0x3c0, 32);
+ kfree(info->pixmap.addr);
framebuffer_release(info);
- output("CyblaFB version %s normal exit.\n",VERSION);
+ 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},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
-MODULE_DEVICE_TABLE(pci,cybla_devices);
+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)
+ .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 ...
+// video=cyblafb:1280x1024, bpp=16, ref=50 ...
//
// modprobe command line example:
//
@@ -1401,46 +1627,46 @@ static int __devinit cyblafb_init(void)
char *options = NULL;
char *opt;
- if (fb_get_options("cyblafb",&options))
+ 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))
+ 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))
+ 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))
+ 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))
+ 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 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
mode = opt;
}
#endif
- output("CyblaFB version %s initializing\n",VERSION);
+ output("CyblaFB version %s initializing\n", VERSION);
return pci_module_init(&cyblafb_pci_driver);
+ return pci_register_driver(&cyblafb_pci_driver);
}
static void __exit cyblafb_exit(void)
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index 0b6af00d197e..ac90883dc3aa 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -214,12 +214,11 @@ 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);
+ u8 *buf = kzalloc(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;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 10dfdf035264..d2dede6ed3e5 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -589,17 +589,19 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
return info->fbops->fb_read(file, buf, count, ppos);
total_size = info->screen_size;
+
if (total_size == 0)
total_size = info->fix.smem_len;
if (p >= total_size)
- return 0;
+ return 0;
+
if (count >= total_size)
- count = total_size;
+ count = total_size;
+
if (count + p > total_size)
count = total_size - p;
- cnt = 0;
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
if (!buffer)
@@ -636,6 +638,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
}
kfree(buffer);
+
return (err) ? err : cnt;
}
@@ -648,7 +651,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
struct fb_info *info = registered_fb[fbidx];
u32 *buffer, *src;
u32 __iomem *dst;
- int c, i, cnt = 0, err;
+ int c, i, cnt = 0, err = 0;
unsigned long total_size;
if (!info || !info->screen_base)
@@ -661,19 +664,19 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
return info->fbops->fb_write(file, buf, count, ppos);
total_size = info->screen_size;
+
if (total_size == 0)
total_size = info->fix.smem_len;
if (p > total_size)
- return -ENOSPC;
+ return 0;
+
if (count >= total_size)
- count = total_size;
- err = 0;
- if (count + p > total_size) {
- count = total_size - p;
- err = -ENOSPC;
- }
- cnt = 0;
+ count = total_size;
+
+ if (count + p > total_size)
+ count = total_size - p;
+
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
if (!buffer)
@@ -687,12 +690,15 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
while (count) {
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
src = buffer;
+
if (copy_from_user(src, buf, c)) {
err = -EFAULT;
break;
}
+
for (i = c >> 2; i--; )
fb_writel(*src++, dst++);
+
if (c & 3) {
u8 *src8 = (u8 *) src;
u8 __iomem *dst8 = (u8 __iomem *) dst;
@@ -702,11 +708,13 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
dst = (u32 __iomem *) dst8;
}
+
*ppos += c;
buf += c;
cnt += c;
count -= c;
}
+
kfree(buffer);
return (err) ? err : cnt;
@@ -949,7 +957,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
default:
if (fb->fb_ioctl == NULL)
return -EINVAL;
- return fb->fb_ioctl(inode, file, cmd, arg, info);
+ return fb->fb_ioctl(info, cmd, arg);
}
}
@@ -1099,7 +1107,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
default:
if (fb->fb_compat_ioctl)
- ret = fb->fb_compat_ioctl(file, cmd, arg, info);
+ ret = fb->fb_compat_ioctl(info, cmd, arg);
break;
}
unlock_kernel();
@@ -1127,7 +1135,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
if (fb->fb_mmap) {
int res;
lock_kernel();
- res = fb->fb_mmap(info, file, vma);
+ res = fb->fb_mmap(info, vma);
unlock_kernel();
return res;
}
@@ -1226,6 +1234,7 @@ fb_open(struct inode *inode, struct file *file)
return -ENODEV;
if (!try_module_get(info->fbops->owner))
return -ENODEV;
+ file->private_data = info;
if (info->fbops->fb_open) {
res = info->fbops->fb_open(info,1);
if (res)
@@ -1237,11 +1246,9 @@ fb_open(struct inode *inode, struct file *file)
static int
fb_release(struct inode *inode, struct file *file)
{
- int fbidx = iminor(inode);
- struct fb_info *info;
+ struct fb_info * const info = file->private_data;
lock_kernel();
- info = registered_fb[fbidx];
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
module_put(info->fbops->owner);
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index fc7965b66775..7c74e7325d95 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -317,26 +317,29 @@ static int edid_is_monitor_block(unsigned char *block)
static void calc_mode_timings(int xres, int yres, int refresh,
struct fb_videomode *mode)
{
- struct fb_var_screeninfo var;
- struct fb_info info;
+ struct fb_var_screeninfo *var;
- memset(&var, 0, sizeof(struct fb_var_screeninfo));
- var.xres = xres;
- var.yres = yres;
- fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
- refresh, &var, &info);
- mode->xres = xres;
- mode->yres = yres;
- mode->pixclock = var.pixclock;
- mode->refresh = refresh;
- mode->left_margin = var.left_margin;
- mode->right_margin = var.right_margin;
- mode->upper_margin = var.upper_margin;
- mode->lower_margin = var.lower_margin;
- mode->hsync_len = var.hsync_len;
- mode->vsync_len = var.vsync_len;
- mode->vmode = 0;
- mode->sync = 0;
+ var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+
+ if (var) {
+ var->xres = xres;
+ var->yres = yres;
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
+ refresh, var, NULL);
+ mode->xres = xres;
+ mode->yres = yres;
+ mode->pixclock = var->pixclock;
+ mode->refresh = refresh;
+ mode->left_margin = var->left_margin;
+ mode->right_margin = var->right_margin;
+ mode->upper_margin = var->upper_margin;
+ mode->lower_margin = var->lower_margin;
+ mode->hsync_len = var->hsync_len;
+ mode->vsync_len = var->vsync_len;
+ mode->vmode = 0;
+ mode->sync = 0;
+ kfree(var);
+ }
}
static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
@@ -525,10 +528,9 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
unsigned char *block;
int num = 0, i;
- mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+ mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
if (mode == NULL)
return NULL;
- memset(mode, 0, 50 * sizeof(struct fb_videomode));
if (edid == NULL || !edid_checksum(edid) ||
!edid_check_header(edid)) {
@@ -1105,15 +1107,21 @@ static void fb_timings_dclk(struct __fb_timings *timings)
*/
int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct __fb_timings timings;
+ struct __fb_timings *timings;
u32 interlace = 1, dscan = 1;
- u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
+ u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
+
+
+ timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
+
+ if (!timings)
+ return -ENOMEM;
/*
* If monspecs are invalid, use values that are enough
* for 640x480@60
*/
- if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+ if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
!info->monspecs.dclkmax ||
info->monspecs.hfmax < info->monspecs.hfmin ||
info->monspecs.vfmax < info->monspecs.vfmin ||
@@ -1130,65 +1138,66 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
dclkmax = info->monspecs.dclkmax;
}
- memset(&timings, 0, sizeof(struct __fb_timings));
- timings.hactive = var->xres;
- timings.vactive = var->yres;
+ timings->hactive = var->xres;
+ timings->vactive = var->yres;
if (var->vmode & FB_VMODE_INTERLACED) {
- timings.vactive /= 2;
+ timings->vactive /= 2;
interlace = 2;
}
if (var->vmode & FB_VMODE_DOUBLE) {
- timings.vactive *= 2;
+ timings->vactive *= 2;
dscan = 2;
}
switch (flags & ~FB_IGNOREMON) {
case FB_MAXTIMINGS: /* maximize refresh rate */
- timings.hfreq = hfmax;
- fb_timings_hfreq(&timings);
- if (timings.vfreq > vfmax) {
- timings.vfreq = vfmax;
- fb_timings_vfreq(&timings);
+ timings->hfreq = hfmax;
+ fb_timings_hfreq(timings);
+ if (timings->vfreq > vfmax) {
+ timings->vfreq = vfmax;
+ fb_timings_vfreq(timings);
}
- if (timings.dclk > dclkmax) {
- timings.dclk = dclkmax;
- fb_timings_dclk(&timings);
+ if (timings->dclk > dclkmax) {
+ timings->dclk = dclkmax;
+ fb_timings_dclk(timings);
}
break;
case FB_VSYNCTIMINGS: /* vrefresh driven */
- timings.vfreq = val;
- fb_timings_vfreq(&timings);
+ timings->vfreq = val;
+ fb_timings_vfreq(timings);
break;
case FB_HSYNCTIMINGS: /* hsync driven */
- timings.hfreq = val;
- fb_timings_hfreq(&timings);
+ timings->hfreq = val;
+ fb_timings_hfreq(timings);
break;
case FB_DCLKTIMINGS: /* pixelclock driven */
- timings.dclk = PICOS2KHZ(val) * 1000;
- fb_timings_dclk(&timings);
+ timings->dclk = PICOS2KHZ(val) * 1000;
+ fb_timings_dclk(timings);
break;
default:
- return -EINVAL;
+ err = -EINVAL;
}
- if (!(flags & FB_IGNOREMON) &&
- (timings.vfreq < vfmin || timings.vfreq > vfmax ||
- timings.hfreq < hfmin || timings.hfreq > hfmax ||
- timings.dclk < dclkmin || timings.dclk > dclkmax))
- return -EINVAL;
-
- var->pixclock = KHZ2PICOS(timings.dclk/1000);
- var->hsync_len = (timings.htotal * 8)/100;
- var->right_margin = (timings.hblank/2) - var->hsync_len;
- var->left_margin = timings.hblank - var->right_margin - var->hsync_len;
-
- var->vsync_len = (3 * interlace)/dscan;
- var->lower_margin = (1 * interlace)/dscan;
- var->upper_margin = (timings.vblank * interlace)/dscan -
- (var->vsync_len + var->lower_margin);
+ if (err || (!(flags & FB_IGNOREMON) &&
+ (timings->vfreq < vfmin || timings->vfreq > vfmax ||
+ timings->hfreq < hfmin || timings->hfreq > hfmax ||
+ timings->dclk < dclkmin || timings->dclk > dclkmax))) {
+ err = -EINVAL;
+ } else {
+ var->pixclock = KHZ2PICOS(timings->dclk/1000);
+ var->hsync_len = (timings->htotal * 8)/100;
+ var->right_margin = (timings->hblank/2) - var->hsync_len;
+ var->left_margin = timings->hblank - var->right_margin -
+ var->hsync_len;
+ var->vsync_len = (3 * interlace)/dscan;
+ var->lower_margin = (1 * interlace)/dscan;
+ var->upper_margin = (timings->vblank * interlace)/dscan -
+ (var->vsync_len + var->lower_margin);
+ }
- return 0;
+ kfree(timings);
+ return err;
}
#else
int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 08dac9580d15..6d26057337e2 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -43,10 +43,11 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
if (size)
fb_info_size += PADDING;
- p = kmalloc(fb_info_size + size, GFP_KERNEL);
+ p = kzalloc(fb_info_size + size, GFP_KERNEL);
+
if (!p)
return NULL;
- memset(p, 0, fb_info_size + size);
+
info = (struct fb_info *) p;
if (size)
@@ -106,8 +107,7 @@ static int mode_string(char *buf, unsigned int offset,
static ssize_t store_mode(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
char mstr[100];
struct fb_var_screeninfo var;
struct fb_modelist *modelist;
@@ -137,8 +137,7 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf,
static ssize_t show_mode(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
if (!fb_info->mode)
return 0;
@@ -149,8 +148,7 @@ static ssize_t show_mode(struct class_device *class_device, char *buf)
static ssize_t store_modes(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
LIST_HEAD(old_list);
int i = count / sizeof(struct fb_videomode);
@@ -174,8 +172,7 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf,
static ssize_t show_modes(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
unsigned int i;
struct list_head *pos;
struct fb_modelist *modelist;
@@ -193,8 +190,7 @@ static ssize_t show_modes(struct class_device *class_device, char *buf)
static ssize_t store_bpp(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_var_screeninfo var;
char ** last = NULL;
int err;
@@ -208,8 +204,7 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf,
static ssize_t show_bpp(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
}
@@ -280,8 +275,7 @@ static ssize_t show_con_rotate(struct class_device *class_device, char *buf)
static ssize_t store_virtual(struct class_device *class_device,
const char * buf, size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@@ -300,16 +294,14 @@ static ssize_t store_virtual(struct class_device *class_device,
static ssize_t show_virtual(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
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);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
}
@@ -320,7 +312,7 @@ static ssize_t show_stride(struct class_device *class_device, char *buf)
static ssize_t store_cmap(struct class_device *class_device, const char *buf,
size_t count)
{
- struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
int rc, i, start, length, transp = 0;
if ((count > PAGE_SIZE) || ((count % 16) != 0))
@@ -380,8 +372,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf,
static ssize_t show_cmap(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
unsigned int i;
if (!fb_info->cmap.red || !fb_info->cmap.blue ||
@@ -405,8 +396,7 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf)
static ssize_t store_blank(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
char *last = NULL;
int err;
@@ -422,41 +412,40 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf,
static ssize_t show_blank(struct class_device *class_device, char *buf)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t store_console(struct class_device *class_device,
const char * buf, size_t count)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t show_console(struct class_device *class_device, char *buf)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t store_cursor(struct class_device *class_device,
const char * buf, size_t count)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t show_cursor(struct class_device *class_device, char *buf)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t store_pan(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@@ -479,19 +468,40 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf,
static ssize_t show_pan(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
fb_info->var.xoffset);
}
static ssize_t show_name(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
}
+static ssize_t store_fbstate(struct class_device *class_device,
+ const char *buf, size_t count)
+{
+ struct fb_info *fb_info = class_get_devdata(class_device);
+ u32 state;
+ char *last = NULL;
+
+ state = simple_strtoul(buf, &last, 0);
+
+ acquire_console_sem();
+ fb_set_suspend(fb_info, (int)state);
+ release_console_sem();
+
+ return count;
+}
+
+static ssize_t show_fbstate(struct class_device *class_device, char *buf)
+{
+ struct fb_info *fb_info = class_get_devdata(class_device);
+ return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
+}
+
static struct class_device_attribute class_device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
@@ -507,6 +517,7 @@ static struct class_device_attribute class_device_attrs[] = {
__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
__ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate),
__ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all),
+ __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
};
int fb_init_class_device(struct fb_info *fb_info)
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index c4870d559afc..9c9b21d469a1 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -37,9 +37,8 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *);
static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
static int ffb_sync(struct fb_info *);
-static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int ffb_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
+static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -839,7 +838,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = {
{ .size = 0 }
};
-static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct ffb_par *par = (struct ffb_par *)info->par;
@@ -848,8 +847,7 @@ static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
0, vma);
}
-static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct ffb_par *par = (struct ffb_par *) info->par;
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index d744c51807b7..38d22729b129 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -979,7 +979,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return 0;
}
-static int gbefb_mmap(struct fb_info *info, struct file *file,
+static int gbefb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
@@ -1000,7 +1000,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file,
pgprot_fb(pgprot_val(vma->vm_page_prot));
vma->vm_flags |= VM_IO | VM_RESERVED;
- vma->vm_file = file;
/* look for the starting tile */
tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 8e8da7433994..20e69156d728 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -215,11 +215,11 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d
if (ret < 0)
return ret;
- ret = pci_request_region(dev, 1, "gx1fb (video)");
+ ret = pci_request_region(dev, 0, "gx1fb (video)");
if (ret < 0)
return ret;
- par->vid_regs = ioremap(pci_resource_start(dev, 1),
- pci_resource_len(dev, 1));
+ par->vid_regs = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0));
if (!par->vid_regs)
return -ENOMEM;
@@ -229,12 +229,9 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d
if (!par->dc_regs)
return -ENOMEM;
- 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_start = gx_base + 0x800000;
info->fix.smem_len = fb_len;
info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
if (!info->screen_base)
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index b37cea7d1094..4e39035cf335 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -42,6 +42,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/vga.h>
@@ -107,7 +108,7 @@ static DEFINE_SPINLOCK(hga_reg_lock);
/* Framebuffer driver structures */
-static struct fb_var_screeninfo hga_default_var = {
+static struct fb_var_screeninfo __initdata hga_default_var = {
.xres = 720,
.yres = 348,
.xres_virtual = 720,
@@ -121,7 +122,7 @@ static struct fb_var_screeninfo hga_default_var = {
.width = -1,
};
-static struct fb_fix_screeninfo hga_fix = {
+static struct fb_fix_screeninfo __initdata hga_fix = {
.id = "HGA",
.type = FB_TYPE_PACKED_PIXELS, /* (not sure) */
.visual = FB_VISUAL_MONO10,
@@ -131,8 +132,6 @@ static struct fb_fix_screeninfo hga_fix = {
.accel = FB_ACCEL_NONE
};
-static struct fb_info fb_info;
-
/* Don't assume that tty1 will be the initial current console. */
static int release_io_port = 0;
static int release_io_ports = 0;
@@ -549,10 +548,9 @@ static struct fb_ops hgafb_ops = {
* Initialization
*/
-static int __init hgafb_init(void)
+static int __init hgafb_probe(struct device *device)
{
- if (fb_get_options("hgafb", NULL))
- return -ENODEV;
+ struct fb_info *info;
if (! hga_card_detect()) {
printk(KERN_INFO "hgafb: HGA card not detected.\n");
@@ -564,41 +562,95 @@ static int __init hgafb_init(void)
printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
hga_type_name, hga_vram_len/1024);
+ info = framebuffer_alloc(0, NULL);
+ if (!info) {
+ iounmap(hga_vram);
+ return -ENOMEM;
+ }
+
hga_fix.smem_start = (unsigned long)hga_vram;
hga_fix.smem_len = hga_vram_len;
- fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
- fb_info.var = hga_default_var;
- fb_info.fix = hga_fix;
- fb_info.monspecs.hfmin = 0;
- fb_info.monspecs.hfmax = 0;
- fb_info.monspecs.vfmin = 10000;
- fb_info.monspecs.vfmax = 10000;
- fb_info.monspecs.dpms = 0;
- fb_info.fbops = &hgafb_ops;
- fb_info.screen_base = hga_vram;
-
- if (register_framebuffer(&fb_info) < 0) {
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+ info->var = hga_default_var;
+ info->fix = hga_fix;
+ info->monspecs.hfmin = 0;
+ info->monspecs.hfmax = 0;
+ info->monspecs.vfmin = 10000;
+ info->monspecs.vfmax = 10000;
+ info->monspecs.dpms = 0;
+ info->fbops = &hgafb_ops;
+ info->screen_base = hga_vram;
+
+ if (register_framebuffer(info) < 0) {
+ framebuffer_release(info);
iounmap(hga_vram);
return -EINVAL;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ info->node, info->fix.id);
+ dev_set_drvdata(device, info);
return 0;
}
-#ifdef MODULE
-static void __exit hgafb_exit(void)
+static int hgafb_remove(struct device *device)
{
+ struct fb_info *info = dev_get_drvdata(device);
+
hga_txt_mode();
hga_clear_screen();
- unregister_framebuffer(&fb_info);
+
+ if (info) {
+ unregister_framebuffer(info);
+ framebuffer_release(info);
+ }
+
iounmap(hga_vram);
- if (release_io_ports) release_region(0x3b0, 12);
- if (release_io_port) release_region(0x3bf, 1);
+
+ if (release_io_ports)
+ release_region(0x3b0, 12);
+
+ if (release_io_port)
+ release_region(0x3bf, 1);
+
+ return 0;
+}
+
+static struct device_driver hgafb_driver = {
+ .name = "hgafb",
+ .bus = &platform_bus_type,
+ .probe = hgafb_probe,
+ .remove = hgafb_remove,
+};
+
+static struct platform_device hgafb_device = {
+ .name = "hgafb",
+};
+
+static int __init hgafb_init(void)
+{
+ int ret;
+
+ if (fb_get_options("hgafb", NULL))
+ return -ENODEV;
+
+ ret = driver_register(&hgafb_driver);
+
+ if (!ret) {
+ ret = platform_device_register(&hgafb_device);
+ if (ret)
+ driver_unregister(&hgafb_driver);
+ }
+
+ return ret;
+}
+
+static void __exit hgafb_exit(void)
+{
+ platform_device_unregister(&hgafb_device);
+ driver_unregister(&hgafb_driver);
}
-#endif
/* -------------------------------------------------------------------------
*
@@ -613,7 +665,4 @@ MODULE_LICENSE("GPL");
module_param(nologo, bool, 0);
MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
module_init(hgafb_init);
-
-#ifdef MODULE
module_exit(hgafb_exit);
-#endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index c61bad0da20f..bd410e06db73 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -17,6 +17,7 @@
#include <linux/fb.h>
#include "i810.h"
#include "i810_regs.h"
+#include "i810_main.h"
#include "../edid.h"
#define I810_DDC 0x50
@@ -42,7 +43,7 @@
static void i810i2c_setscl(void *data, int state)
{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_i2c_chan *chan = data;
struct i810fb_par *par = chan->par;
u8 __iomem *mmio = par->mmio_start_virtual;
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
index 64cd1c827cf0..76764ea3486a 100644
--- a/drivers/video/i810/i810_accel.c
+++ b/drivers/video/i810/i810_accel.c
@@ -14,6 +14,7 @@
#include "i810_regs.h"
#include "i810.h"
+#include "i810_main.h"
static u32 i810fb_rop[] = {
COLOR_COPY_ROP, /* ROP_COPY */
@@ -57,7 +58,7 @@ static inline void i810_report_error(u8 __iomem *mmio)
*/
static inline int wait_for_space(struct fb_info *info, u32 space)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 head, count = WAIT_COUNT, tail;
u8 __iomem *mmio = par->mmio_start_virtual;
@@ -88,7 +89,7 @@ static inline int wait_for_space(struct fb_info *info, u32 space)
*/
static inline int wait_for_engine_idle(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
int count = WAIT_COUNT;
@@ -116,7 +117,7 @@ static inline int wait_for_engine_idle(struct fb_info *info)
*/
static inline u32 begin_iring(struct fb_info *info, u32 space)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (par->dev_flags & ALWAYS_SYNC)
wait_for_engine_idle(info);
@@ -161,7 +162,7 @@ static inline void source_copy_blit(int dwidth, int dheight, int dpitch,
int xdir, int src, int dest, int rop,
int blit_bpp, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 24 + IRING_PAD)) return;
@@ -195,7 +196,7 @@ static inline void color_blit(int width, int height, int pitch, int dest,
int rop, int what, int blit_bpp,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 24 + IRING_PAD)) return;
@@ -236,7 +237,7 @@ static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
int dest, const u32 *src, int bg,
int fg, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
@@ -254,7 +255,7 @@ static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
static inline void load_front(int offset, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 8 + IRING_PAD)) return;
@@ -296,7 +297,7 @@ static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 dx, dy, width, height, dest, rop = 0, color = 0;
if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -322,7 +323,7 @@ void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -361,7 +362,7 @@ void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 fg = 0, bg = 0, size, dst;
if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -397,7 +398,7 @@ void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
int i810fb_sync(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (!info->var.accel_flags || par->dev_flags & LOCKUP)
return 0;
@@ -407,7 +408,7 @@ int i810fb_sync(struct fb_info *info)
void i810fb_load_front(u32 offset, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
if (!info->var.accel_flags || par->dev_flags & LOCKUP)
@@ -427,7 +428,7 @@ void i810fb_load_front(u32 offset, struct fb_info *info)
*/
void i810fb_init_ringbuffer(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 tmp1, tmp2;
u8 __iomem *mmio = par->mmio_start_virtual;
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
index 64f087a4466b..9743d51e7f8c 100644
--- a/drivers/video/i810/i810_gtf.c
+++ b/drivers/video/i810/i810_gtf.c
@@ -14,6 +14,7 @@
#include "i810_regs.h"
#include "i810.h"
+#include "i810_main.h"
/*
* FIFO and Watermark tables - based almost wholly on i810_wmark.c in
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index c0c974b1afaa..266d0ab92663 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -42,20 +42,62 @@
#include <linux/pci_ids.h>
#include <linux/resource.h>
#include <linux/unistd.h>
+#include <linux/console.h>
#include <asm/io.h>
#include <asm/div64.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
#include <asm/page.h>
#include "i810_regs.h"
#include "i810.h"
#include "i810_main.h"
+/*
+ * voffset - framebuffer offset in MiB from aperture start address. In order for
+ * the driver to work with X, we must try to use memory holes left untouched by X. The
+ * following table lists where X's different surfaces start at.
+ *
+ * ---------------------------------------------
+ * : : 64 MiB : 32 MiB :
+ * ----------------------------------------------
+ * : FrontBuffer : 0 : 0 :
+ * : DepthBuffer : 48 : 16 :
+ * : BackBuffer : 56 : 24 :
+ * ----------------------------------------------
+ *
+ * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
+ * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
+ * work, allowing 7 + 1 MiB of Framebuffer memory.
+ * Note, the size of the hole may change depending on how much memory you allocate to X,
+ * and how the memory is split up between these surfaces.
+ *
+ * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
+ * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
+ *
+ * Experiment with v_offset to find out which works best for you.
+ */
+static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset __initdata = 0;
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int __devinit i810fb_init_pci (struct pci_dev *dev,
+ const struct pci_device_id *entry);
+static void __exit i810fb_remove_pci(struct pci_dev *dev);
+static int i810fb_resume(struct pci_dev *dev);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
+
+/* Chipset Specific Functions */
+static int i810fb_set_par (struct fb_info *info);
+static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
+ u8 *transp, struct fb_info *info);
+static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info);
+static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int i810fb_blank (int blank_mode, struct fb_info *info);
+
+/* Initialization */
+static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
+
/* PCI */
static const char *i810_pci_list[] __devinitdata = {
"Intel(R) 810 Framebuffer Device" ,
@@ -776,7 +818,7 @@ static void i810_load_cursor_image(int width, int height, u8 *data,
static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
u8 red, green, blue, trans, temp;
@@ -949,7 +991,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
static int i810_check_params(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
int line_length, vidmem, mode_valid = 0, retval = 0;
u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
/*
@@ -1043,7 +1085,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
*/
static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
@@ -1154,7 +1196,7 @@ static void decode_var(const struct fb_var_screeninfo *var,
static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
u8 *transp, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
u8 temp;
@@ -1193,7 +1235,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
static int i810fb_open(struct fb_info *info, int user)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 count = atomic_read(&par->use_count);
if (count == 0) {
@@ -1212,7 +1254,7 @@ static int i810fb_open(struct fb_info *info, int user)
static int i810fb_release(struct fb_info *info, int user)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 count;
count = atomic_read(&par->use_count);
@@ -1234,7 +1276,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
u8 temp;
int i;
@@ -1328,7 +1370,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int i810fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 total;
total = var->xoffset * par->depth +
@@ -1340,7 +1382,7 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var,
static int i810fb_blank (int blank_mode, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
int mode = 0, pwr, scr_off = 0;
@@ -1385,7 +1427,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info)
static int i810fb_set_par(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
decode_var(&info->var, par);
i810_load_regs(par);
@@ -1429,7 +1471,7 @@ static int i810fb_check_var(struct fb_var_screeninfo *var,
static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct i810fb_par *par = (struct i810fb_par *)info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
if (!par->dev_flags & LOCKUP)
@@ -1516,36 +1558,29 @@ static struct fb_ops i810fb_ops __devinitdata = {
static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- int blank = 0, prev_state = par->cur_state;
-
- if (state.event == prev_state)
- return 0;
+ struct i810fb_par *par = info->par;
par->cur_state = state.event;
- switch (state.event) {
- case 1:
- blank = VESA_VSYNC_SUSPEND;
- break;
- case 2:
- blank = VESA_HSYNC_SUSPEND;
- break;
- case 3:
- blank = VESA_POWERDOWN;
- break;
- default:
- return -EINVAL;
+ if (state.event == PM_EVENT_FREEZE) {
+ dev->dev.power.power_state = state;
+ return 0;
}
- info->fbops->fb_blank(blank, info);
- if (!prev_state) {
- agp_unbind_memory(par->i810_gtt.i810_fb_memory);
- agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
- pci_disable_device(dev);
- }
+ acquire_console_sem();
+ fb_set_suspend(info, 1);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ i810fb_blank(FB_BLANK_POWERDOWN, info);
+ agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+ agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
+
pci_save_state(dev);
+ pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
+ release_console_sem();
return 0;
}
@@ -1553,23 +1588,29 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
static int i810fb_resume(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
+ int cur_state = par->cur_state;
+
+ par->cur_state = PM_EVENT_ON;
- if (par->cur_state == 0)
+ if (cur_state == PM_EVENT_FREEZE) {
+ pci_set_power_state(dev, PCI_D0);
return 0;
+ }
- pci_restore_state(dev);
+ acquire_console_sem();
pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
pci_enable_device(dev);
+ pci_set_master(dev);
agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset);
agp_bind_memory(par->i810_gtt.i810_cursor_memory,
par->cursor_heap.offset);
-
+ i810fb_set_par(info);
+ fb_set_suspend (info, 0);
info->fbops->fb_blank(VESA_NO_BLANKING, info);
-
- par->cur_state = 0;
-
+ release_console_sem();
return 0;
}
/***********************************************************************
@@ -1610,7 +1651,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par)
static int __devinit i810_alloc_agp_mem(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
int size;
struct agp_bridge_data *bridge;
@@ -2074,7 +2115,7 @@ static void i810fb_release_resource(struct fb_info *info,
static void __exit i810fb_remove_pci(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
unregister_framebuffer(info);
i810fb_release_resource(info, par);
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 06072a6466f2..51d4f3d4116d 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -14,55 +14,6 @@
#ifndef __I810_MAIN_H__
#define __I810_MAIN_H__
-static int __devinit i810fb_init_pci (struct pci_dev *dev,
- const struct pci_device_id *entry);
-static void __exit i810fb_remove_pci(struct pci_dev *dev);
-static int i810fb_resume(struct pci_dev *dev);
-static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
-
-/*
- * voffset - framebuffer offset in MiB from aperture start address. In order for
- * the driver to work with X, we must try to use memory holes left untouched by X. The
- * following table lists where X's different surfaces start at.
- *
- * ---------------------------------------------
- * : : 64 MiB : 32 MiB :
- * ----------------------------------------------
- * : FrontBuffer : 0 : 0 :
- * : DepthBuffer : 48 : 16 :
- * : BackBuffer : 56 : 24 :
- * ----------------------------------------------
- *
- * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
- * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
- * work, allowing 7 + 1 MiB of Framebuffer memory.
- * Note, the size of the hole may change depending on how much memory you allocate to X,
- * and how the memory is split up between these surfaces.
- *
- * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
- * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
- *
- * Experiment with v_offset to find out which works best for you.
- */
-static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
-static u32 voffset __initdata = 0;
-
-static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-
-/* Chipset Specific Functions */
-static int i810fb_set_par (struct fb_info *info);
-static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
- u8 *transp, struct fb_info *info);
-static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info);
-static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
-static int i810fb_blank (int blank_mode, struct fb_info *info);
-
-/* Initialization */
-static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
-extern int __init agp_intel_init(void);
-
-
/* Video Timings */
extern void round_off_xres (u32 *xres);
extern void round_off_yres (u32 *xres, u32 *yres);
@@ -101,7 +52,7 @@ static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
/* Conditionals */
#ifdef CONFIG_X86
-inline void flush_cache(void)
+static inline void flush_cache(void)
{
asm volatile ("wbinvd":::"memory");
}
@@ -110,7 +61,9 @@ inline void flush_cache(void)
#endif
#ifdef CONFIG_MTRR
-#define KERNEL_HAS_MTRR 1
+
+#include <asm/mtrr.h>
+
static inline void __devinit set_mtrr(struct i810fb_par *par)
{
par->mtrr_reg = mtrr_add((u32) par->aperture.physical,
@@ -128,7 +81,6 @@ static inline void unset_mtrr(struct i810fb_par *par)
par->aperture.size);
}
#else
-#define KERNEL_HAS_MTRR 0
#define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
#define unset_mtrr(x) do { } while (0)
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index e326f44f652d..6b88050d21bf 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -219,7 +219,7 @@ static void iga_blank_border(struct iga_par *par)
}
#ifdef __sparc__
-static int igafb_mmap(struct fb_info *info, struct file *file,
+static int igafb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct iga_par *par = (struct iga_par *)info->par;
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7fbe24206b19..ad416ae47596 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -323,6 +323,7 @@ struct imstt_par {
unsigned long cmap_regs_phys;
__u8 *cmap_regs;
__u32 ramdac;
+ __u32 palette[16];
};
enum {
@@ -657,7 +658,7 @@ set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
static void
set_imstt_regvals (struct fb_info *info, u_int bpp)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
struct imstt_regvals *init = &par->init;
__u32 ctl, pitch, byteswap, scr;
@@ -749,7 +750,7 @@ set_imstt_regvals (struct fb_info *info, u_int bpp)
static inline void
set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 off = var->yoffset * (info->fix.line_length >> 3)
+ ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
write_reg_le32(par->dc_regs, SSR, off);
@@ -863,7 +864,7 @@ imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int
imsttfb_set_par(struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
return -EINVAL;
@@ -881,7 +882,7 @@ static int
imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
u_int bpp = info->var.bits_per_pixel;
if (regno > 255)
@@ -905,14 +906,17 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
if (regno < 16)
switch (bpp) {
case 16:
- ((u16 *)info->pseudo_palette)[regno] = (regno << (info->var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
+ par->palette[regno] =
+ (regno << (info->var.green.length ==
+ 5 ? 10 : 11)) | (regno << 5) | regno;
break;
case 24:
- ((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno;
+ par->palette[regno] =
+ (regno << 16) | (regno << 8) | regno;
break;
case 32: {
int i = (regno << 8) | regno;
- ((u32 *)info->pseudo_palette)[regno] = (i << 16) | i;
+ par->palette[regno] = (i << 16) |i;
break;
}
}
@@ -935,7 +939,7 @@ imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
static int
imsttfb_blank(int blank, struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 ctrl;
ctrl = read_reg_le32(par->dc_regs, STGCTL);
@@ -989,7 +993,7 @@ imsttfb_blank(int blank, struct fb_info *info)
static void
imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
bgc = rect->color;
@@ -1033,7 +1037,7 @@ imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
static void
imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
@@ -1195,7 +1199,7 @@ imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
static int
imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
u32 flags = cursor->set, fg, bg, xx, yy;
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
@@ -1263,10 +1267,9 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
#define FBIMSTT_GETIDXREG 0x545406
static int
-imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
void __user *argp = (void __user *)arg;
__u32 reg[2];
__u8 idx[2];
@@ -1350,7 +1353,7 @@ static struct fb_ops imsttfb_ops = {
static void __devinit
init_imstt(struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 i, tmp, *ip, *end;
tmp = read_reg_le32(par->dc_regs, PRC);
@@ -1413,7 +1416,7 @@ init_imstt(struct fb_info *info)
if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
|| !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
- kfree(info);
+ framebuffer_release(info);
return;
}
@@ -1449,7 +1452,7 @@ init_imstt(struct fb_info *info)
fb_alloc_cmap(&info->cmap, 0, 0);
if (register_framebuffer(info) < 0) {
- kfree(info);
+ framebuffer_release(info);
return;
}
@@ -1474,26 +1477,21 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_ERR "imsttfb: no OF node for pci device\n");
#endif /* CONFIG_PPC_OF */
- size = sizeof(struct fb_info) + sizeof(struct imstt_par) +
- sizeof(u32) * 16;
-
- info = kmalloc(size, GFP_KERNEL);
+ info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
if (!info) {
printk(KERN_ERR "imsttfb: Can't allocate memory\n");
return -ENOMEM;
}
- memset(info, 0, size);
-
- par = (struct imstt_par *) (info + 1);
+ par = info->par;
addr = pci_resource_start (pdev, 0);
size = pci_resource_len (pdev, 0);
if (!request_mem_region(addr, size, "imsttfb")) {
printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
- kfree(info);
+ framebuffer_release(info);
return -ENODEV;
}
@@ -1516,14 +1514,13 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
info->fix.smem_start = addr;
- info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000);
+ info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
+ 0x400000 : 0x800000);
info->fix.mmio_start = addr + 0x800000;
par->dc_regs = ioremap(addr + 0x800000, 0x1000);
par->cmap_regs_phys = addr + 0x840000;
par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
- info->par = par;
- info->pseudo_palette = (void *) (par + 1);
- info->device = &pdev->dev;
+ info->pseudo_palette = par->palette;
init_imstt(info);
pci_set_drvdata(pdev, info);
@@ -1534,7 +1531,7 @@ static void __devexit
imsttfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
int size = pci_resource_len(pdev, 0);
unregister_framebuffer(info);
@@ -1542,7 +1539,7 @@ imsttfb_remove(struct pci_dev *pdev)
iounmap(par->dc_regs);
iounmap(info->screen_base);
release_mem_region(info->fix.smem_start, size);
- kfree(info);
+ framebuffer_release(info);
}
#ifndef MODULE
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 5924cc225c95..1718baaeed2a 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -554,7 +554,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
inf = pdev->dev.platform_data;
if(!inf) {
- dev_err(dev,"No platform_data available\n");
+ dev_err(&pdev->dev,"No platform_data available\n");
return -ENOMEM;
}
@@ -579,7 +579,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
if (!inf->fixed_screen_cpu) {
ret = imxfb_map_video_memory(info);
if (ret) {
- dev_err(dev, "Failed to allocate video RAM: %d\n", ret);
+ dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto failed_map;
}
@@ -608,7 +608,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
imxfb_set_par(info);
ret = register_framebuffer(info);
if (ret < 0) {
- dev_err(dev, "failed to register framebuffer\n");
+ dev_err(&pdev->dev, "failed to register framebuffer\n");
goto failed_register;
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 0090544842f5..6b8bd3cdf9c0 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -157,9 +157,8 @@ static int intelfb_cursor(struct fb_info *info,
static int intelfb_sync(struct fb_info *info);
-static int intelfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info);
+static int intelfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg);
static int __devinit intelfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent);
@@ -1380,8 +1379,7 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
/* When/if we have our own ioctls. */
static int
-intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
int retval = 0;
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index 7e33cd307d47..ab5285a7f1d6 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/kyro/STG4000InitDevice.c
@@ -15,6 +15,7 @@
#include <linux/pci.h>
#include "STG4000Reg.h"
+#include "STG4000Interface.h"
/* SDRAM fixed settings */
#define SDRAM_CFG_0 0x49A1
diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/kyro/STG4000Interface.h
index e75b3b4a4aa1..b7c83d5dfb13 100644
--- a/drivers/video/kyro/STG4000Interface.h
+++ b/drivers/video/kyro/STG4000Interface.h
@@ -11,7 +11,8 @@
#ifndef _STG4000INTERFACE_H
#define _STG4000INTERFACE_H
-struct pci_dev;
+#include <linux/pci.h>
+#include <video/kyro.h>
/*
* Ramdac Setup
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c
index 2ae9bafacdd0..a8c9713413e6 100644
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ b/drivers/video/kyro/STG4000OverlayDevice.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include "STG4000Reg.h"
+#include "STG4000Interface.h"
/* HW Defines */
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 5eb4d5c177bd..477ad297de4e 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -73,8 +73,6 @@ static struct fb_var_screeninfo kyro_var __devinitdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct kyrofb_info *currentpar;
-
typedef struct {
STG4000REG __iomem *pSTGReg; /* Virtual address of PCI register region */
u32 ulNextFreeVidMem; /* Offset from start of vid mem to next free region */
@@ -309,7 +307,7 @@ enum {
/* Accessors */
static int kyro_dev_video_mode_set(struct fb_info *info)
{
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
/* Turn off display */
StopVTG(deviceInfo.pSTGReg);
@@ -402,7 +400,7 @@ static inline unsigned long get_line_length(int x, int bpp)
static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
@@ -478,7 +476,7 @@ static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int kyrofb_set_par(struct fb_info *info)
{
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
unsigned long lineclock;
unsigned long frameclock;
@@ -536,20 +534,22 @@ static int kyrofb_set_par(struct fb_info *info)
static int kyrofb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info)
{
+ struct kyrofb_info *par = info->par;
+
if (regno > 255)
return 1; /* Invalid register */
if (regno < 16) {
switch (info->var.bits_per_pixel) {
case 16:
- ((u16*)(info->pseudo_palette))[regno] =
+ par->palette[regno] =
(red & 0xf800) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
break;
case 32:
red >>= 8; green >>= 8; blue >>= 8; transp >>= 8;
- ((u32*)(info->pseudo_palette))[regno] =
+ par->palette[regno] =
(transp << 24) | (red << 16) | (green << 8) | blue;
break;
}
@@ -586,9 +586,8 @@ static int __init kyrofb_setup(char *options)
}
#endif
-static int kyrofb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int kyrofb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
overlay_create ol_create;
overlay_viewport_set ol_viewport_set;
@@ -675,6 +674,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct fb_info *info;
+ struct kyrofb_info *currentpar;
unsigned long size;
int err;
@@ -683,14 +683,11 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
return err;
}
- size = sizeof(struct fb_info) + sizeof(struct kyrofb_info) + 16 * sizeof(u32);
- info = kmalloc(size, GFP_KERNEL);
+ info = framebuffer_alloc(sizeof(struct kyrofb_info), &pdev->dev);
if (!info)
return -ENOMEM;
- memset(info, 0, size);
-
- currentpar = (struct kyrofb_info *)(info + 1);
+ currentpar = info->par;
kyro_fix.smem_start = pci_resource_start(pdev, 0);
kyro_fix.smem_len = pci_resource_len(pdev, 0);
@@ -716,8 +713,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
info->fbops = &kyrofb_ops;
info->fix = kyro_fix;
- info->par = currentpar;
- info->pseudo_palette = (void *)(currentpar + 1);
+ info->pseudo_palette = currentpar->palette;
info->flags = FBINFO_DEFAULT;
SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
@@ -741,7 +737,6 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
fb_memset(info->screen_base, 0, size);
- info->device = &pdev->dev;
if (register_framebuffer(info) < 0)
goto out_unmap;
@@ -757,7 +752,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
out_unmap:
iounmap(currentpar->regbase);
iounmap(info->screen_base);
- kfree(info);
+ framebuffer_release(info);
return -EINVAL;
}
@@ -765,7 +760,7 @@ out_unmap:
static void __devexit kyrofb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
/* Reset the board */
StopVTG(deviceInfo.pSTGReg);
@@ -789,7 +784,7 @@ static void __devexit kyrofb_remove(struct pci_dev *pdev)
unregister_framebuffer(info);
pci_set_drvdata(pdev, NULL);
- kfree(info);
+ framebuffer_release(info);
}
static int __init kyrofb_init(void)
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 494287f8f8bf..a23cfdb9d826 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -32,9 +32,8 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int leo_blank(int, struct fb_info *);
-static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int leo_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int leo_mmap(struct fb_info *, struct vm_area_struct *);
+static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -363,7 +362,7 @@ static struct sbus_mmap_map leo_mmap_map[] = {
{ .size = 0 }
};
-static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct leo_par *par = (struct leo_par *)info->par;
@@ -373,8 +372,7 @@ static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct leo_par *par = (struct leo_par *) info->par;
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index d0244c04af5a..4ef5cd19609d 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o
# How to generate logo's
-# Use logo-cfiles to retreive list of .c files to be built
+# Use logo-cfiles to retrieve list of .c files to be built
logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \
$(wildcard $(srctree)/$(src)/*$(1).$(2))))
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index cfc748e94272..e6cbd9de944a 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -609,18 +609,19 @@ void __init macfb_setup(char *options)
}
}
-void __init macfb_init(void)
+static int __init macfb_init(void)
{
int video_cmap_len, video_is_nubus = 0;
struct nubus_dev* ndev = NULL;
char *option = NULL;
+ int err;
if (fb_get_options("macfb", &option))
return -ENODEV;
macfb_setup(option);
if (!MACH_IS_MAC)
- return;
+ return -ENODEV;
/* There can only be one internal video controller anyway so
we're not too worried about this */
@@ -958,11 +959,11 @@ void __init macfb_init(void)
fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
- if (register_framebuffer(&fb_info) < 0)
- return;
-
- printk("fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ err = register_framebuffer(&fb_info);
+ if (!err)
+ printk("fb%d: %s frame buffer device\n",
+ fb_info.node, fb_info.fix.id);
+ return err;
}
module_init(macfb_init);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 1e74f4cca53b..4055ff6f5a81 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -865,9 +865,8 @@ static struct matrox_altout panellink_output = {
.name = "Panellink output",
};
-static int matroxfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int matroxfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
MINFO_FROM_INFO(info);
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index a8c47ad2cdb6..3a3e1804c56a 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -50,8 +50,6 @@
#include <asm/mtrr.h>
#endif
-#include "../console/fbcon.h"
-
#if defined(CONFIG_PPC_PMAC)
#include <asm/prom.h>
#include <asm/pci-bridge.h>
@@ -351,8 +349,6 @@ struct matrox_bios {
} output;
};
-extern struct display fb_display[];
-
struct matrox_switch;
struct matroxfb_driver;
struct matroxfb_dh_fb_info;
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index d52d7d825c41..27eb4bb4f89f 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -419,11 +419,10 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru
return 0;
}
-static int matroxfb_dh_ioctl(struct inode* inode,
- struct file* file,
+static int matroxfb_dh_ioctl(struct fb_info *info,
unsigned int cmd,
- unsigned long arg,
- struct fb_info* info) {
+ unsigned long arg)
+{
#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
MINFO_FROM(m2info->primary_dev);
@@ -457,7 +456,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
case MATROXFB_GET_OUTPUT_MODE:
case MATROXFB_GET_ALL_OUTPUTS:
{
- return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, &ACCESS_FBINFO(fbcon));
+ return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg);
}
case MATROXFB_SET_OUTPUT_CONNECTION:
{
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index 35008af7db75..c122d8743dd2 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -20,6 +20,8 @@
#include <asm/uaccess.h>
#include <asm/div64.h>
+#include "matroxfb_g450.h"
+
/* Definition of the various controls */
struct mctl {
struct v4l2_queryctrl desc;
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index a1f2c5e8fc88..6019710dc298 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -968,7 +968,7 @@ static inline int maven_compute_timming(struct maven_data* md,
return 0;
}
-static inline int maven_program_timming(struct maven_data* md,
+static int maven_program_timming(struct maven_data* md,
const struct mavenregs* m) {
struct i2c_client* c = md->client;
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index d9d3e9f6c08e..455a46ce840c 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -192,11 +192,8 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
unsigned int wd;
unsigned int divider;
int i;
- int fwidth;
struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
- fwidth = 8;
-
DBG(__FUNCTION__)
hw->SEQ[0] = 0x00;
@@ -235,10 +232,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
hw->ATTR[16] = 0x41;
hw->ATTR[17] = 0xFF;
hw->ATTR[18] = 0x0F;
- if (fwidth == 9)
- hw->ATTR[19] = 0x08;
- else
- hw->ATTR[19] = 0x00;
+ hw->ATTR[19] = 0x00;
hw->ATTR[20] = 0x00;
hd = m->HDisplay >> 3;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 8486e77872dc..747602aa5615 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -485,7 +485,7 @@ static void vgaHWRestore(const struct fb_info *info,
*/
static inline int neo2200_sync(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int waitcycles;
while (readl(&par->neo2200->bltStat) & 1)
@@ -525,7 +525,7 @@ static inline void neo2200_wait_fifo(struct fb_info *info,
static inline void neo2200_accel_init(struct fb_info *info,
struct fb_var_screeninfo *var)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
Neo2200 __iomem *neo2200 = par->neo2200;
u32 bltMod, pitch;
@@ -560,7 +560,7 @@ static inline void neo2200_accel_init(struct fb_info *info,
static int
neofb_open(struct fb_info *info, int user)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt) {
@@ -575,7 +575,7 @@ neofb_open(struct fb_info *info, int user)
static int
neofb_release(struct fb_info *info, int user)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt)
@@ -590,7 +590,7 @@ neofb_release(struct fb_info *info, int user)
static int
neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
unsigned int pixclock = var->pixclock;
struct xtimings timings;
int memlen, vramlen;
@@ -757,7 +757,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int neofb_set_par(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
struct xtimings timings;
unsigned char temp;
int i, clock_hi = 0;
@@ -853,7 +853,7 @@ static int neofb_set_par(struct fb_info *info)
/* If the user did not specify any display devices, then... */
if (par->PanelDispCntlReg1 == 0x00) {
/* Default to internal (i.e., LCD) only. */
- par->PanelDispCntlReg1 |= 0x02;
+ par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
}
/* If we are using a fixed mode, then tell the chip we are. */
@@ -1216,7 +1216,7 @@ static int neofb_set_par(struct fb_info *info)
static void neofb_update_start(struct fb_info *info,
struct fb_var_screeninfo *var)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
struct vgastate *state = &par->state;
int oldExtCRTDispAddr;
int Base;
@@ -1331,7 +1331,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
* wms...Enable VESA DPMS compatible powerdown mode
* run "setterm -powersave powerdown" to take advantage
*/
- struct neofb_par *par = (struct neofb_par *)info->par;
+ struct neofb_par *par = info->par;
int seqflags, lcdflags, dpmsflags, reg;
switch (blank_mode) {
@@ -1404,7 +1404,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
static void
neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
u_long dst, rop;
dst = rect->dx + rect->dy * info->var.xres_virtual;
@@ -1440,7 +1440,7 @@ static void
neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
u_long src, dst, bltCntl;
bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
@@ -1472,7 +1472,7 @@ neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
static void
neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int s_pitch = (image->width * image->depth + 7) >> 3;
int scan_align = info->pixmap.scan_align - 1;
int buf_align = info->pixmap.buf_align - 1;
@@ -1686,7 +1686,7 @@ static struct fb_videomode __devinitdata mode800x480 = {
static int __devinit neo_map_mmio(struct fb_info *info,
struct pci_dev *dev)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
DBG("neo_map_mmio");
@@ -1733,7 +1733,7 @@ static int __devinit neo_map_mmio(struct fb_info *info,
static void neo_unmap_mmio(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
DBG("neo_unmap_mmio");
@@ -1796,7 +1796,7 @@ static void neo_unmap_video(struct fb_info *info)
#ifdef CONFIG_MTRR
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
mtrr_del(par->mtrr, info->fix.smem_start,
info->fix.smem_len);
@@ -1811,7 +1811,7 @@ static void neo_unmap_video(struct fb_info *info)
static int __devinit neo_scan_monitor(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
unsigned char type, display;
int w;
@@ -1890,7 +1890,7 @@ static int __devinit neo_scan_monitor(struct fb_info *info)
static int __devinit neo_init_hw(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int videoRam = 896;
int maxClock = 65000;
int CursorMem = 1024;
@@ -2014,7 +2014,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
struct fb_info *info;
struct neofb_par *par;
- info = framebuffer_alloc(sizeof(struct neofb_par) + sizeof(u32) * 256, &dev->dev);
+ info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
if (!info)
return NULL;
@@ -2081,7 +2081,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
info->fix.accel = id->driver_data;
info->fbops = &neofb_ops;
- info->pseudo_palette = (void *) (par + 1);
+ info->pseudo_palette = par->palette;
return info;
}
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index b989358437b3..99c3a8e6a237 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -52,6 +52,7 @@
#include <linux/pci.h>
#include "nv_type.h"
#include "nv_local.h"
+#include "nv_proto.h"
void NVLockUnlock(struct nvidia_par *par, int Lock)
{
@@ -848,7 +849,7 @@ void NVCalcStateExt(struct nvidia_par *par,
int width,
int hDisplaySize, int height, int dotClock, int flags)
{
- int pixelDepth, VClk;
+ int pixelDepth, VClk = 0;
/*
* Save mode parameters.
*/
@@ -938,15 +939,24 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
if (par->Architecture == NV_ARCH_04) {
NV_WR32(par->PFB, 0x0200, state->config);
- } else if ((par->Chipset & 0xfff0) == 0x0090) {
- for (i = 0; i < 15; i++) {
- NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
- NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1);
- }
- } else {
+ } else if ((par->Architecture < NV_ARCH_40) ||
+ (par->Chipset & 0xfff0) == 0x0040) {
for (i = 0; i < 8; i++) {
NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
- NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+ NV_WR32(par->PFB, 0x0244 + (i * 0x10),
+ par->FbMapSize - 1);
+ }
+ } else {
+ int regions = 12;
+
+ if (((par->Chipset & 0xfff0) == 0x0090) ||
+ ((par->Chipset & 0xfff0) == 0x01D0) ||
+ ((par->Chipset & 0xfff0) == 0x0290))
+ regions = 15;
+ for(i = 0; i < regions; i++) {
+ NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+ NV_WR32(par->PFB, 0x0604 + (i * 0x10),
+ par->FbMapSize - 1);
}
}
@@ -1182,11 +1192,17 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
} else {
if (par->Architecture >= NV_ARCH_40) {
+ u32 tmp;
+
NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+ tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
+ for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
+ NV_WR32(par->PGRAPH, 0x5000, i);
+
if ((par->Chipset & 0xfff0) == 0x0040) {
NV_WR32(par->PGRAPH, 0x09b0,
0x83280fff);
@@ -1211,6 +1227,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
0xffff7fff);
break;
case 0x00C0:
+ case 0x0120:
NV_WR32(par->PGRAPH, 0x0828,
0x007596ff);
NV_WR32(par->PGRAPH, 0x082C,
@@ -1245,6 +1262,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
0x00100000);
break;
case 0x0090:
+ case 0x0290:
NV_WR32(par->PRAMDAC, 0x0608,
NV_RD32(par->PRAMDAC, 0x0608) |
0x00100000);
@@ -1310,14 +1328,44 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
}
}
- if ((par->Chipset & 0xfff0) == 0x0090) {
- for (i = 0; i < 60; i++)
- NV_WR32(par->PGRAPH, 0x0D00 + i,
- NV_RD32(par->PFB, 0x0600 + i));
+ if ((par->Architecture < NV_ARCH_40) ||
+ ((par->Chipset & 0xfff0) == 0x0040)) {
+ for (i = 0; i < 32; i++) {
+ NV_WR32(par->PGRAPH, 0x0900 + i*4,
+ NV_RD32(par->PFB, 0x0240 +i*4));
+ NV_WR32(par->PGRAPH, 0x6900 + i*4,
+ NV_RD32(par->PFB, 0x0240 +i*4));
+ }
} else {
- for (i = 0; i < 32; i++)
- NV_WR32(par->PGRAPH, 0x0900 + i,
- NV_RD32(par->PFB, 0x0240 + i));
+ if (((par->Chipset & 0xfff0) == 0x0090) ||
+ ((par->Chipset & 0xfff0) == 0x01D0) ||
+ ((par->Chipset & 0xfff0) == 0x0290)) {
+ for (i = 0; i < 60; i++) {
+ NV_WR32(par->PGRAPH,
+ 0x0D00 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ NV_WR32(par->PGRAPH,
+ 0x6900 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ }
+ } else {
+ for (i = 0; i < 48; i++) {
+ NV_WR32(par->PGRAPH,
+ 0x0900 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ if(((par->Chipset & 0xfff0)
+ != 0x0160) &&
+ ((par->Chipset & 0xfff0)
+ != 0x0220))
+ NV_WR32(par->PGRAPH,
+ 0x6900 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ }
+ }
}
if (par->Architecture >= NV_ARCH_40) {
@@ -1338,7 +1386,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PGRAPH, 0x0868,
par->FbMapSize - 1);
} else {
- if((par->Chipset & 0xfff0) == 0x0090) {
+ if ((par->Chipset & 0xfff0) == 0x0090 ||
+ (par->Chipset & 0xfff0) == 0x01D0 ||
+ (par->Chipset & 0xfff0) == 0x0290) {
NV_WR32(par->PGRAPH, 0x0DF0,
NV_RD32(par->PFB, 0x0200));
NV_WR32(par->PGRAPH, 0x0DF4,
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 12f2884d3f0b..bd9eca05e146 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -46,7 +46,7 @@ static void nvidia_gpio_setscl(void *data, int state)
static void nvidia_gpio_setsda(void *data, int state)
{
- struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_i2c_chan *chan = data;
struct nvidia_par *par = chan->par;
u32 val;
@@ -64,7 +64,7 @@ static void nvidia_gpio_setsda(void *data, int state)
static int nvidia_gpio_getscl(void *data)
{
- struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_i2c_chan *chan = data;
struct nvidia_par *par = chan->par;
u32 val = 0;
@@ -79,7 +79,7 @@ static int nvidia_gpio_getscl(void *data)
static int nvidia_gpio_getsda(void *data)
{
- struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_i2c_chan *chan = data;
struct nvidia_par *par = chan->par;
u32 val = 0;
@@ -136,13 +136,13 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
par->chan[2].par = par;
par->chan[0].ddc_base = 0x3e;
- nvidia_setup_i2c_bus(&par->chan[0], "BUS1");
+ nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0");
par->chan[1].ddc_base = 0x36;
- nvidia_setup_i2c_bus(&par->chan[1], "BUS2");
+ nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1");
par->chan[2].ddc_base = 0x50;
- nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
+ nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2");
}
void nvidia_delete_i2c_busses(struct nvidia_par *par)
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 3353103e8b0b..b149a690ee0f 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -4,7 +4,7 @@
#define __NV_PROTO_H__
/* in nv_setup.c */
-void NVCommonSetup(struct fb_info *info);
+int NVCommonSetup(struct fb_info *info);
void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
u8 NVReadCrtc(struct nvidia_par *par, u8 index);
void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 1f06a9f1bd0f..a18a9aebf05f 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -285,28 +285,34 @@ static void nv10GetConfig(struct nvidia_par *par)
par->CrystalFreqKHz = 27000;
}
- par->CursorStart = (par->RamAmountKBytes - 96) * 1024;
par->CURSOR = NULL; /* can't set this here */
par->MinVClockFreqKHz = 12000;
par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
}
-void NVCommonSetup(struct fb_info *info)
+int NVCommonSetup(struct fb_info *info)
{
struct nvidia_par *par = info->par;
- struct fb_var_screeninfo var;
+ struct fb_var_screeninfo *var;
u16 implementation = par->Chipset & 0x0ff0;
u8 *edidA = NULL, *edidB = NULL;
- struct fb_monspecs monitorA, monitorB;
+ struct fb_monspecs *monitorA, *monitorB;
struct fb_monspecs *monA = NULL, *monB = NULL;
int mobile = 0;
int tvA = 0;
int tvB = 0;
int FlatPanel = -1; /* really means the CRTC is slaved */
int Television = 0;
+ int err = 0;
- memset(&monitorA, 0, sizeof(struct fb_monspecs));
- memset(&monitorB, 0, sizeof(struct fb_monspecs));
+ var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+ monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+ monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+
+ if (!var || !monitorA || !monitorB) {
+ err = -ENOMEM;
+ goto done;
+ }
par->PRAMIN = par->REGS + (0x00710000 / 4);
par->PCRTC0 = par->REGS + (0x00600000 / 4);
@@ -382,6 +388,8 @@ void NVCommonSetup(struct fb_info *info)
case 0x0146:
case 0x0147:
case 0x0148:
+ case 0x0098:
+ case 0x0099:
mobile = 1;
break;
default:
@@ -406,9 +414,9 @@ void NVCommonSetup(struct fb_info *info)
par->CRTCnumber = 0;
if (nvidia_probe_i2c_connector(info, 1, &edidA))
nvidia_probe_of_connector(info, 1, &edidA);
- if (edidA && !fb_parse_edid(edidA, &var)) {
+ if (edidA && !fb_parse_edid(edidA, var)) {
printk("nvidiafb: EDID found from BUS1\n");
- monA = &monitorA;
+ monA = monitorA;
fb_edid_to_monspecs(edidA, monA);
FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
@@ -494,17 +502,17 @@ void NVCommonSetup(struct fb_info *info)
if (nvidia_probe_i2c_connector(info, 1, &edidA))
nvidia_probe_of_connector(info, 1, &edidA);
- if (edidA && !fb_parse_edid(edidA, &var)) {
+ if (edidA && !fb_parse_edid(edidA, var)) {
printk("nvidiafb: EDID found from BUS1\n");
- monA = &monitorA;
+ monA = monitorA;
fb_edid_to_monspecs(edidA, monA);
}
if (nvidia_probe_i2c_connector(info, 2, &edidB))
nvidia_probe_of_connector(info, 2, &edidB);
- if (edidB && !fb_parse_edid(edidB, &var)) {
+ if (edidB && !fb_parse_edid(edidB, var)) {
printk("nvidiafb: EDID found from BUS2\n");
- monB = &monitorB;
+ monB = monitorB;
fb_edid_to_monspecs(edidB, monB);
}
@@ -639,4 +647,9 @@ void NVCommonSetup(struct fb_info *info)
kfree(edidA);
kfree(edidB);
+done:
+ kfree(var);
+ kfree(monitorA);
+ kfree(monitorB);
+ return err;
}
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index bee09c6e48f6..dbcb8962e57d 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -284,6 +284,16 @@ 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_6200,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0252,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0313,
@@ -418,6 +428,7 @@ static int noaccel __devinitdata = 0;
static int noscale __devinitdata = 0;
static int paneltweak __devinitdata = 0;
static int vram __devinitdata = 0;
+static int bpp __devinitdata = 8;
#ifdef CONFIG_MTRR
static int nomtrr __devinitdata = 0;
#endif
@@ -485,7 +496,7 @@ static int nvidia_backlight_levels[] = {
static int nvidia_set_backlight_enable(int on, int level, void *data)
{
- struct nvidia_par *par = (struct nvidia_par *)data;
+ struct nvidia_par *par = data;
u32 tmp_pcrt, tmp_pmc, fpcontrol;
tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
@@ -1382,24 +1393,36 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
info->monspecs.modedb_len, &info->modelist);
fb_var_to_videomode(&modedb, &nvidiafb_default_var);
+ switch (bpp) {
+ case 0 ... 8:
+ bpp = 8;
+ break;
+ case 9 ... 16:
+ bpp = 16;
+ break;
+ default:
+ bpp = 32;
+ break;
+ }
+
if (specs->modedb != NULL) {
struct fb_videomode *modedb;
modedb = fb_find_best_display(specs, &info->modelist);
fb_videomode_to_var(&nvidiafb_default_var, modedb);
- nvidiafb_default_var.bits_per_pixel = 8;
+ nvidiafb_default_var.bits_per_pixel = bpp;
} 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);
+ specs->modedb_len, &modedb, bpp);
}
if (mode_option)
fb_find_mode(&nvidiafb_default_var, info, mode_option,
- specs->modedb, specs->modedb_len, &modedb, 8);
+ specs->modedb, specs->modedb_len, &modedb, bpp);
info->var = nvidiafb_default_var;
info->fix.visual = (info->var.bits_per_pixel == 8) ?
@@ -1448,11 +1471,34 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
return nvidiafb_check_var(&info->var, info);
}
-static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+static u32 __devinit nvidia_get_chipset(struct fb_info *info)
{
+ struct nvidia_par *par = info->par;
+ u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
+
+ printk("nvidiafb: PCI id - %x\n", id);
+ if ((id & 0xfff0) == 0x00f0) {
+ /* pci-e */
+ printk("nvidiafb: PCI-E card\n");
+ id = NV_RD32(par->REGS, 0x1800);
+
+ if ((id & 0x0000ffff) == 0x000010DE)
+ id = 0x10DE0000 | (id >> 16);
+ else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
+ id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
+ ((id >> 8) & 0x000000ff);
+ }
+
+ printk("nvidiafb: Actual id - %x\n", id);
+ return id;
+}
+
+static u32 __devinit nvidia_get_arch(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
u32 arch = 0;
- switch (pd->device & 0x0ff0) {
+ switch (par->Chipset & 0x0ff0) {
case 0x0100: /* GeForce 256 */
case 0x0110: /* GeForce2 MX */
case 0x0150: /* GeForce2 */
@@ -1485,6 +1531,8 @@ static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
case 0x0210:
case 0x0220:
case 0x0230:
+ case 0x0290:
+ case 0x0390:
arch = NV_ARCH_40;
break;
case 0x0020: /* TNT, TNT2 */
@@ -1513,7 +1561,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
if (!info)
goto err_out;
- par = (struct nvidia_par *)info->par;
+ par = info->par;
par->pci_dev = pd;
info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -1533,18 +1581,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
goto err_out_request;
}
- par->Architecture = nvidia_get_arch(pd);
-
- par->Chipset = (pd->vendor << 16) | pd->device;
- printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
-
- if (par->Architecture == 0) {
- printk(KERN_ERR PFX "unknown NV_ARCH\n");
- goto err_out_free_base0;
- }
-
- sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
-
par->FlatPanel = flatpanel;
if (flatpanel == 1)
printk(KERN_INFO PFX "flatpanel support enabled\n");
@@ -1570,7 +1606,19 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
goto err_out_free_base0;
}
- NVCommonSetup(info);
+ par->Chipset = nvidia_get_chipset(info);
+ printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
+ par->Architecture = nvidia_get_arch(info);
+
+ if (par->Architecture == 0) {
+ printk(KERN_ERR PFX "unknown NV_ARCH\n");
+ goto err_out_arch;
+ }
+
+ sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+ if (NVCommonSetup(info))
+ goto err_out_arch;
par->FbAddress = nvidiafb_fix.smem_start;
par->FbMapSize = par->RamAmountKBytes * 1024;
@@ -1581,10 +1629,15 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
if (par->FbMapSize > 64 * 1024 * 1024)
par->FbMapSize = 64 * 1024 * 1024;
- par->FbUsableSize = par->FbMapSize - (128 * 1024);
+ if(par->Architecture >= NV_ARCH_40)
+ par->FbUsableSize = par->FbMapSize - (560 * 1024);
+ else
+ par->FbUsableSize = par->FbMapSize - (128 * 1024);
par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
16 * 1024;
par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+ par->CursorStart = par->FbUsableSize + (32 * 1024);
+
info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
info->screen_size = par->FbUsableSize;
nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
@@ -1640,21 +1693,22 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
NVTRACE_LEAVE();
return 0;
- err_out_iounmap_fb:
+err_out_iounmap_fb:
iounmap(info->screen_base);
- err_out_free_base1:
+err_out_free_base1:
fb_destroy_modedb(info->monspecs.modedb);
nvidia_delete_i2c_busses(par);
+err_out_arch:
iounmap(par->REGS);
- err_out_free_base0:
+err_out_free_base0:
pci_release_regions(pd);
- err_out_request:
+err_out_request:
pci_disable_device(pd);
- err_out_enable:
+err_out_enable:
kfree(info->pixmap.addr);
- err_out_kfree:
+err_out_kfree:
framebuffer_release(info);
- err_out:
+err_out:
return -ENODEV;
}
@@ -1729,6 +1783,8 @@ static int __devinit nvidiafb_setup(char *options)
#endif
} else if (!strncmp(this_opt, "fpdither:", 9)) {
fpdither = simple_strtol(this_opt+9, NULL, 0);
+ } else if (!strncmp(this_opt, "bpp:", 4)) {
+ bpp = simple_strtoul(this_opt+4, NULL, 0);
} else
mode_option = this_opt;
}
@@ -1804,6 +1860,11 @@ module_param(vram, int, 0);
MODULE_PARM_DESC(vram,
"amount of framebuffer memory to remap in MiB"
"(default=0 - remap entire memory)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
+module_param(bpp, int, 0);
+MODULE_PARM_DESC(bpp, "pixel width in bits"
+ "(default=8)");
#ifdef CONFIG_MTRR
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 00d87f5bb7be..ad1434e3f227 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -223,6 +223,7 @@ static int offb_blank(int blank, struct fb_info *info)
int __init offb_init(void)
{
struct device_node *dp = NULL, *boot_disp = NULL;
+
#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
struct device_node *macos_display = NULL;
#endif
@@ -234,60 +235,54 @@ int __init offb_init(void)
if (boot_infos != 0) {
unsigned long addr =
(unsigned long) boot_infos->dispDeviceBase;
+ u32 *addrp;
+ u64 daddr, dsize;
+ unsigned int flags;
+
/* find the device node corresponding to the macos display */
while ((dp = of_find_node_by_type(dp, "display"))) {
int i;
- /*
- * Grrr... It looks like the MacOS ATI driver
- * munges the assigned-addresses property (but
- * the AAPL,address value is OK).
- */
- if (strncmp(dp->name, "ATY,", 4) == 0
- && dp->n_addrs == 1) {
- unsigned int *ap =
- (unsigned int *) get_property(dp,
- "AAPL,address",
- NULL);
- if (ap != NULL) {
- dp->addrs[0].address = *ap;
- dp->addrs[0].size = 0x01000000;
- }
- }
/*
- * The LTPro on the Lombard powerbook has no addresses
- * on the display nodes, they are on their parent.
+ * Look for an AAPL,address property first.
*/
- if (dp->n_addrs == 0
- && device_is_compatible(dp, "ATY,264LTPro")) {
- int na;
- unsigned int *ap = (unsigned int *)
- get_property(dp, "AAPL,address", &na);
- if (ap != 0)
- for (na /= sizeof(unsigned int);
- na > 0; --na, ++ap)
- if (*ap <= addr
- && addr <
- *ap + 0x1000000)
- goto foundit;
+ unsigned int na;
+ unsigned int *ap =
+ (unsigned int *)get_property(dp, "AAPL,address",
+ &na);
+ if (ap != 0) {
+ for (na /= sizeof(unsigned int); na > 0;
+ --na, ++ap)
+ if (*ap <= addr &&
+ addr < *ap + 0x1000000) {
+ macos_display = dp;
+ goto foundit;
+ }
}
/*
* See if the display address is in one of the address
* ranges for this display.
*/
- for (i = 0; i < dp->n_addrs; ++i) {
- if (dp->addrs[i].address <= addr
- && addr <
- dp->addrs[i].address +
- dp->addrs[i].size)
+ i = 0;
+ for (;;) {
+ addrp = of_get_address(dp, i++, &dsize, &flags);
+ if (addrp == NULL)
break;
+ if (!(flags & IORESOURCE_MEM))
+ continue;
+ daddr = of_translate_address(dp, addrp);
+ if (daddr == OF_BAD_ADDR)
+ continue;
+ if (daddr <= addr && addr < (daddr + dsize)) {
+ macos_display = dp;
+ goto foundit;
+ }
}
- if (i < dp->n_addrs) {
- foundit:
+ foundit:
+ if (macos_display) {
printk(KERN_INFO "MacOS display is %s\n",
dp->full_name);
- macos_display = dp;
break;
}
}
@@ -326,8 +321,10 @@ static void __init offb_init_nodriver(struct device_node *dp)
int *pp, i;
unsigned int len;
int width = 640, height = 480, depth = 8, pitch;
- unsigned int rsize, *up;
- unsigned long address = 0;
+ unsigned int flags, rsize, *up;
+ u64 address = OF_BAD_ADDR;
+ u32 *addrp;
+ u64 asize;
if ((pp = (int *) get_property(dp, "depth", &len)) != NULL
&& len == sizeof(int))
@@ -363,7 +360,7 @@ static void __init offb_init_nodriver(struct device_node *dp)
break;
}
if (pdev) {
- for (i = 0; i < 6 && address == 0; i++) {
+ for (i = 0; i < 6 && address == OF_BAD_ADDR; i++) {
if ((pci_resource_flags(pdev, i) &
IORESOURCE_MEM) &&
(pci_resource_len(pdev, i) >= rsize))
@@ -374,27 +371,33 @@ static void __init offb_init_nodriver(struct device_node *dp)
}
#endif /* CONFIG_PCI */
- if (address == 0 &&
- (up = (unsigned *) get_property(dp, "address", &len)) != NULL &&
- len == sizeof(unsigned))
- address = (u_long) * up;
- if (address == 0) {
- for (i = 0; i < dp->n_addrs; ++i)
- if (dp->addrs[i].size >=
- pitch * height * depth / 8)
- break;
- if (i >= dp->n_addrs) {
+ /* This one is dodgy, we may drop it ... */
+ if (address == OF_BAD_ADDR &&
+ (up = (unsigned *) get_property(dp, "address", &len)) != NULL &&
+ len == sizeof(unsigned int))
+ address = (u64) * up;
+
+ if (address == OF_BAD_ADDR) {
+ for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
+ != NULL; i++) {
+ if (!(flags & IORESOURCE_MEM))
+ continue;
+ if (asize >= pitch * height * depth / 8)
+ break;
+ }
+ if (addrp == NULL) {
printk(KERN_ERR
"no framebuffer address found for %s\n",
dp->full_name);
return;
}
-
- address = (u_long) dp->addrs[i].address;
-
-#ifdef CONFIG_PPC64
- address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset;
-#endif
+ address = of_translate_address(dp, addrp);
+ if (address == OF_BAD_ADDR) {
+ printk(KERN_ERR
+ "can't translate framebuffer address for %s\n",
+ dp->full_name);
+ return;
+ }
/* kludge for valkyrie */
if (strcmp(dp->name, "valkyrie") == 0)
@@ -459,7 +462,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
par->cmap_type = cmap_unknown;
if (depth == 8) {
- /* XXX kludge for ati */
+
+ /* Palette hacks disabled for now */
+#if 0
if (dp && !strncmp(name, "ATY,Rage128", 11)) {
unsigned long regbase = dp->addrs[2].address;
par->cmap_adr = ioremap(regbase, 0x1FFF);
@@ -490,6 +495,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
par->cmap_adr = ioremap(regbase + 0x6000, 0x1000);
par->cmap_type = cmap_gxt2000;
}
+#endif
fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_STATIC_PSEUDOCOLOR;
} else
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index b251e754e16c..0d1957505359 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -31,9 +31,8 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int p9100_blank(int, struct fb_info *);
-static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int p9100_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
+static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -222,7 +221,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = {
{ 0, 0, 0 }
};
-static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct p9100_par *par = (struct p9100_par *)info->par;
@@ -232,8 +231,8 @@ static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_st
vma);
}
-static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct p9100_par *par = (struct p9100_par *) info->par;
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index ca4082ae5a18..335e37465559 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -69,6 +69,8 @@ struct fb_info_platinum {
unsigned long total_vram;
int clktype;
int dactype;
+
+ struct resource rsrc_fb, rsrc_reg;
};
/*
@@ -97,9 +99,6 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
* Interface used by the world
*/
-int platinumfb_init(void);
-int platinumfb_setup(char*);
-
static struct fb_ops platinumfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = platinumfb_check_var,
@@ -138,13 +137,15 @@ static int platinumfb_set_par (struct fb_info *info)
init = platinum_reg_init[pinfo->vmode-1];
- if (pinfo->vmode == 13 && pinfo->cmode > 0)
- offset = 0x10;
+ if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8))
+ offset = 0x10;
+
info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
info->fix.visual = (pinfo->cmode == CMODE_8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
- info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) + offset;
+ info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
+ + offset;
printk("line_length: %x\n", info->fix.line_length);
return 0;
}
@@ -221,7 +222,9 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static inline int platinum_vram_reqd(int video_mode, int color_mode)
{
return vmode_attrs[video_mode-1].vres *
- (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 0x20) +0x1000;
+ (vmode_attrs[video_mode-1].hres * (1<<color_mode) +
+ ((video_mode == VMODE_832_624_75) &&
+ (color_mode > CMODE_8)) ? 0x10 : 0x20) + 0x1000;
}
#define STORE_D2(a, d) { \
@@ -481,7 +484,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
/*
* Parse user speficied options (`video=platinumfb:')
*/
-int __init platinumfb_setup(char *options)
+static int __init platinumfb_setup(char *options)
{
char *this_opt;
@@ -522,19 +525,15 @@ int __init platinumfb_setup(char *options)
#define invalidate_cache(addr)
#endif
-static int __devinit platinumfb_probe(struct of_device* odev, const struct of_device_id *match)
+static int __devinit platinumfb_probe(struct of_device* odev,
+ const struct of_device_id *match)
{
struct device_node *dp = odev->node;
struct fb_info *info;
struct fb_info_platinum *pinfo;
- unsigned long addr, size;
volatile __u8 *fbuffer;
- int i, bank0, bank1, bank2, bank3, rc;
+ int bank0, bank1, bank2, bank3, rc;
- if (dp->n_addrs != 2) {
- printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs);
- return -ENXIO;
- }
printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n");
info = framebuffer_alloc(sizeof(*pinfo), &odev->dev);
@@ -542,26 +541,39 @@ static int __devinit platinumfb_probe(struct of_device* odev, const struct of_de
return -ENOMEM;
pinfo = info->par;
- /* Map in frame buffer and registers */
- for (i = 0; i < dp->n_addrs; ++i) {
- addr = dp->addrs[i].address;
- size = dp->addrs[i].size;
- /* Let's assume we can request either all or nothing */
- if (!request_mem_region(addr, size, "platinumfb")) {
- framebuffer_release(info);
- return -ENXIO;
- }
- if (size >= 0x400000) {
- /* frame buffer - map only 4MB */
- pinfo->frame_buffer_phys = addr;
- pinfo->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
- pinfo->base_frame_buffer = pinfo->frame_buffer;
- } else {
- /* registers */
- pinfo->platinum_regs_phys = addr;
- pinfo->platinum_regs = ioremap(addr, size);
- }
+ if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) ||
+ of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) {
+ printk(KERN_ERR "platinumfb: Can't get resources\n");
+ framebuffer_release(info);
+ return -ENXIO;
}
+ if (!request_mem_region(pinfo->rsrc_reg.start,
+ pinfo->rsrc_reg.start -
+ pinfo->rsrc_reg.end + 1,
+ "platinumfb registers")) {
+ framebuffer_release(info);
+ return -ENXIO;
+ }
+ if (!request_mem_region(pinfo->rsrc_fb.start,
+ pinfo->rsrc_fb.start
+ - pinfo->rsrc_fb.end + 1,
+ "platinumfb framebuffer")) {
+ release_mem_region(pinfo->rsrc_reg.start,
+ pinfo->rsrc_reg.end -
+ pinfo->rsrc_reg.start + 1);
+ framebuffer_release(info);
+ return -ENXIO;
+ }
+
+ /* frame buffer - map only 4MB */
+ pinfo->frame_buffer_phys = pinfo->rsrc_fb.start;
+ pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000,
+ _PAGE_WRITETHRU);
+ pinfo->base_frame_buffer = pinfo->frame_buffer;
+
+ /* registers */
+ pinfo->platinum_regs_phys = pinfo->rsrc_reg.start;
+ pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000);
pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap");
@@ -624,18 +636,16 @@ static int __devexit platinumfb_remove(struct of_device* odev)
{
struct fb_info *info = dev_get_drvdata(&odev->dev);
struct fb_info_platinum *pinfo = info->par;
- struct device_node *dp = odev->node;
- unsigned long addr, size;
- int i;
unregister_framebuffer (info);
/* Unmap frame buffer and registers */
- for (i = 0; i < dp->n_addrs; ++i) {
- addr = dp->addrs[i].address;
- size = dp->addrs[i].size;
- release_mem_region(addr, size);
- }
+ release_mem_region(pinfo->rsrc_fb.start,
+ pinfo->rsrc_fb.end -
+ pinfo->rsrc_fb.start + 1);
+ release_mem_region(pinfo->rsrc_reg.start,
+ pinfo->rsrc_reg.end -
+ pinfo->rsrc_reg.start + 1);
iounmap(pinfo->frame_buffer);
iounmap(pinfo->platinum_regs);
release_mem_region(pinfo->cmap_regs_phys, 0x1000);
@@ -662,7 +672,7 @@ static struct of_platform_driver platinum_driver =
.remove = platinumfb_remove,
};
-int __init platinumfb_init(void)
+static int __init platinumfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -676,7 +686,7 @@ int __init platinumfb_init(void)
return 0;
}
-void __exit platinumfb_exit(void)
+static void __exit platinumfb_exit(void)
{
of_unregister_driver(&platinum_driver);
}
diff --git a/drivers/video/platinumfb.h b/drivers/video/platinumfb.h
index 2834fc1c344b..f6bd77cafd17 100644
--- a/drivers/video/platinumfb.h
+++ b/drivers/video/platinumfb.h
@@ -158,7 +158,9 @@ static struct platinum_regvals platinum_reg_init_14 = {
/* 832x624, 75Hz (13) */
static struct platinum_regvals platinum_reg_init_13 = {
0x70,
- { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */
+ { 864, 1680, 3344 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB,
+ * and we use 3344 instead of 3360 to fit in 2Mb
+ */
{ 0xff0, 4, 0, 0, 0, 0, 0x299, 0,
0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37,
0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52,
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 0277ce031e5e..5fe197943deb 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -91,6 +91,7 @@ struct pm2fb_par
u32 mem_config; /* MemConfig reg at probe */
u32 mem_control; /* MemControl reg at probe */
u32 boot_address; /* BootAddress reg at probe */
+ u32 palette[16];
};
/*
@@ -674,7 +675,7 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
*/
static int pm2fb_set_par(struct fb_info *info)
{
- struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *par = info->par;
u32 pixclock;
u32 width, height, depth;
u32 hsstart, hsend, hbend, htotal;
@@ -854,7 +855,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *par = info->par;
if (regno >= info->cmap.len) /* no. of hw registers */
return 1;
@@ -929,7 +930,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
case 16:
case 24:
case 32:
- ((u32*)(info->pseudo_palette))[regno] = v;
+ par->palette[regno] = v;
break;
}
return 0;
@@ -955,7 +956,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int pm2fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct pm2fb_par *p = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *p = info->par;
u32 base;
u32 depth;
u32 xres;
@@ -987,7 +988,7 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
*/
static int pm2fb_blank(int blank_mode, struct fb_info *info)
{
- struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *par = info->par;
u32 video = par->video;
DPRINTK("blank_mode %d\n", blank_mode);
@@ -1054,8 +1055,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
{
struct pm2fb_par *default_par;
struct fb_info *info;
- int size, err;
- int err_retval = -ENXIO;
+ int err, err_retval = -ENXIO;
err = pci_enable_device(pdev);
if ( err ) {
@@ -1063,11 +1063,10 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
return err;
}
- size = sizeof(struct pm2fb_par) + 256 * sizeof(u32);
- info = framebuffer_alloc(size, &pdev->dev);
+ info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
if ( !info )
return -ENOMEM;
- default_par = (struct pm2fb_par *) info->par;
+ default_par = info->par;
switch (pdev->device) {
case PCI_DEVICE_ID_TI_TVP4020:
@@ -1171,7 +1170,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
info->fbops = &pm2fb_ops;
info->fix = pm2fb_fix;
- info->pseudo_palette = (void *)(default_par + 1);
+ info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN;
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 2e11b601c488..0e78ddc81583 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -657,9 +657,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
static void pm3fb_detect(void);
static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
struct fb_info_gen *info);
-static int pm3fb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, int con,
- struct fb_info *info);
+static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
/* the struct that hold them together */
@@ -3438,9 +3436,7 @@ static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
return 0;
}
-static int pm3fb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, int con,
- struct fb_info *info)
+static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
u32 cm, i;
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 28d1fe5fe340..d92f352211ef 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -299,8 +299,7 @@ static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return -EINVAL;
}
-static int aafb_ioctl(struct inode *inode, struct file *file, u32 cmd,
- unsigned long arg, int con, struct fb_info *info)
+static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg)
{
/* TODO: Not yet implemented */
return -ENOIOCTLCMD;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 9fc10b9e6f57..53ad61f1038c 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -395,7 +395,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
return 0;
}
-static int pxafb_mmap(struct fb_info *info, struct file *file,
+static int pxafb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct pxafb_info *fbi = (struct pxafb_info *)info;
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 600318f708f2..db9fb9074dbc 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -1497,8 +1497,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
}
-static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
unsigned int tmp;
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9f96e9237d..6c19ab6afb01 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -630,7 +630,7 @@ static void riva_load_video_mode(struct fb_info *info)
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
struct riva_regs newmode;
NVTRACE_ENTER();
@@ -925,7 +925,7 @@ riva_set_rop_solid(struct riva_par *par, int rop)
static void riva_setup_accel(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
RIVA_FIFO_FREE(par->riva, Clip, 2);
NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
@@ -979,7 +979,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
#ifdef CONFIG_PMAC_BACKLIGHT
static int riva_set_backlight_enable(int on, int level, void *data)
{
- struct riva_par *par = (struct riva_par *)data;
+ struct riva_par *par = data;
U032 tmp_pcrt, tmp_pmc;
tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
@@ -1008,7 +1008,7 @@ static int riva_set_backlight_level(int level, void *data)
static int rivafb_open(struct fb_info *info, int user)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
NVTRACE_ENTER();
@@ -1034,7 +1034,7 @@ static int rivafb_open(struct fb_info *info, int user)
static int rivafb_release(struct fb_info *info, int user)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
NVTRACE_ENTER();
@@ -1057,7 +1057,7 @@ static int rivafb_release(struct fb_info *info, int user)
static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct fb_videomode *mode;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
int nom, den; /* translating from pixels->bytes */
int mode_valid = 0;
@@ -1166,7 +1166,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int rivafb_set_par(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
NVTRACE_ENTER();
/* vgaHWunlock() + riva unlock (0x7F) */
@@ -1205,43 +1205,19 @@ static int rivafb_set_par(struct fb_info *info)
static int rivafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
+ struct riva_par *par = info->par;
unsigned int base;
NVTRACE_ENTER();
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
- if (var->yoffset > (var->yres_virtual - var->yres))
- return -EINVAL;
-
- if (var->vmode & FB_VMODE_YWRAP) {
- if (var->yoffset < 0
- || var->yoffset >= info->var.yres_virtual
- || var->xoffset) return -EINVAL;
- } else {
- if (var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
- return -EINVAL;
- }
-
base = var->yoffset * info->fix.line_length + var->xoffset;
-
par->riva.SetStartAddress(&par->riva, base);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
-
- if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
- else
- info->var.vmode &= ~FB_VMODE_YWRAP;
NVTRACE_LEAVE();
return 0;
}
static int rivafb_blank(int blank, struct fb_info *info)
{
- struct riva_par *par= (struct riva_par *)info->par;
+ struct riva_par *par= info->par;
unsigned char tmp, vesa;
tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
@@ -1304,7 +1280,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
+ struct riva_par *par = info->par;
RIVA_HW_INST *chip = &par->riva;
int i;
@@ -1393,7 +1369,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
*/
static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
u_int color, rop = 0;
if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
@@ -1449,7 +1425,7 @@ static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
*/
static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
cfb_copyarea(info, region);
@@ -1495,7 +1471,7 @@ static inline void convert_bgcolor_16(u32 *col)
static void rivafb_imageblit(struct fb_info *info,
const struct fb_image *image)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
u32 fgx = 0, bgx = 0, width, tmp;
u8 *cdat = (u8 *) image->data;
volatile u32 __iomem *d;
@@ -1580,7 +1556,7 @@ static void rivafb_imageblit(struct fb_info *info,
*/
static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
u8 data[MAX_CURS * MAX_CURS/8];
int i, set = cursor->set;
u16 fg, bg;
@@ -1664,7 +1640,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
static int rivafb_sync(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
+ struct riva_par *par = info->par;
wait_for_idle(par);
return 0;
@@ -1696,7 +1672,7 @@ static struct fb_ops riva_fb_ops = {
static int __devinit riva_set_fbinfo(struct fb_info *info)
{
unsigned int cmap_len;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
NVTRACE_ENTER();
info->flags = FBINFO_DEFAULT
@@ -1733,7 +1709,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
#ifdef CONFIG_PPC_OF
static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
struct device_node *dp;
unsigned char *pedid = NULL;
unsigned char *disptype = NULL;
@@ -1767,7 +1743,7 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
static int __devinit riva_get_EDID_i2c(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
struct fb_var_screeninfo var;
int i;
@@ -1837,7 +1813,7 @@ static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
static void __devinit riva_get_edidinfo(struct fb_info *info)
{
struct fb_var_screeninfo *var = &rivafb_default_var;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
fb_edid_to_monspecs(par->EDID, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
@@ -1909,7 +1885,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
ret = -ENOMEM;
goto err_ret;
}
- default_par = (struct riva_par *) info->par;
+ default_par = info->par;
default_par->pdev = pd;
info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -2070,7 +2046,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
err_iounmap_screen_base:
#ifdef CONFIG_FB_RIVA_I2C
- riva_delete_i2c_busses((struct riva_par *) info->par);
+ riva_delete_i2c_busses(info->par);
#endif
iounmap(info->screen_base);
err_iounmap_pramin:
@@ -2093,7 +2069,7 @@ err_ret:
static void __exit rivafb_remove(struct pci_dev *pd)
{
struct fb_info *info = pci_get_drvdata(pd);
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
NVTRACE_ENTER();
if (!info)
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index 77151d8e0766..8b1967fc116a 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -30,7 +30,7 @@
static void riva_gpio_setscl(void* data, int state)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val;
@@ -48,7 +48,7 @@ static void riva_gpio_setscl(void* data, int state)
static void riva_gpio_setsda(void* data, int state)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val;
@@ -66,7 +66,7 @@ static void riva_gpio_setsda(void* data, int state)
static int riva_gpio_getscl(void* data)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val = 0;
@@ -81,7 +81,7 @@ static int riva_gpio_getscl(void* data)
static int riva_gpio_getsda(void* data)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val = 0;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ce6e749db3a7..d574dd3c9c8a 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -87,6 +87,7 @@
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -96,7 +97,6 @@
#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>
@@ -552,7 +552,7 @@ static inline void modify_gpio(void __iomem *reg,
* s3c2410fb_init_registers - Initialise all LCD-related registers
*/
-int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
{
unsigned long flags;
@@ -634,7 +634,7 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
static char driver_name[]="s3c2410fb";
-int __init s3c2410fb_probe(struct platform_device *pdev)
+static int __init s3c2410fb_probe(struct platform_device *pdev)
{
struct s3c2410fb_info *info;
struct fb_info *fbinfo;
@@ -667,8 +667,6 @@ int __init s3c2410fb_probe(struct platform_device *pdev)
info->fb = fbinfo;
platform_set_drvdata(pdev, fbinfo);
- s3c2410fb_init_registers(info);
-
dprintk("devinit\n");
strcpy(fbinfo->fix.id, driver_name);
@@ -701,8 +699,8 @@ int __init s3c2410fb_probe(struct platform_device *pdev)
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.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;
@@ -746,7 +744,6 @@ int __init s3c2410fb_probe(struct platform_device *pdev)
goto release_irq;
}
- clk_use(info->clk);
clk_enable(info->clk);
dprintk("got and enabled clock\n");
@@ -783,7 +780,6 @@ 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);
@@ -828,7 +824,6 @@ static int s3c2410fb_remove(struct platform_device *pdev)
if (info->clk) {
clk_disable(info->clk);
- clk_unuse(info->clk);
clk_put(info->clk);
info->clk = NULL;
}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 2ea1354e439f..8a893ce7040d 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -178,7 +178,6 @@
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/arch/assabet.h>
@@ -816,7 +815,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
return 0;
}
-static int sa1100fb_mmap(struct fb_info *info, struct file *file,
+static int sa1100fb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
@@ -1455,7 +1454,11 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
static int __init sa1100fb_probe(struct platform_device *pdev)
{
struct sa1100fb_info *fbi;
- int ret;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return -EINVAL;
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY;
@@ -1470,7 +1473,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
if (ret)
goto failed;
- ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
+ ret = request_irq(irq, sa1100fb_handle_irq, SA_INTERRUPT,
"LCD", fbi);
if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
@@ -1492,7 +1495,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
ret = register_framebuffer(&fbi->fb);
if (ret < 0)
- goto failed;
+ goto err_free_irq;
#ifdef CONFIG_CPU_FREQ
fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
@@ -1504,7 +1507,9 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
/* This driver cannot be unloaded at the moment */
return 0;
-failed:
+ err_free_irq:
+ free_irq(irq, fbi);
+ failed:
platform_set_drvdata(pdev, NULL);
kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 3c98457783c4..00719a91479f 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -49,7 +49,7 @@
static void savage4_gpio_setscl(void *data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
unsigned int r;
r = readl(chan->ioaddr + chan->reg);
@@ -63,7 +63,7 @@ static void savage4_gpio_setscl(void *data, int val)
static void savage4_gpio_setsda(void *data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
unsigned int r;
r = readl(chan->ioaddr + chan->reg);
@@ -77,21 +77,21 @@ static void savage4_gpio_setsda(void *data, int val)
static int savage4_gpio_getscl(void *data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
}
static int savage4_gpio_getsda(void *data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
}
static void prosavage_gpio_setscl(void* data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
u32 r;
SET_CR_IX(chan->ioaddr, chan->reg);
@@ -107,7 +107,7 @@ static void prosavage_gpio_setscl(void* data, int val)
static void prosavage_gpio_setsda(void* data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
unsigned int r;
SET_CR_IX(chan->ioaddr, chan->reg);
@@ -123,7 +123,7 @@ static void prosavage_gpio_setsda(void* data, int val)
static int prosavage_gpio_getscl(void* data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
SET_CR_IX(chan->ioaddr, chan->reg);
return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN));
@@ -131,7 +131,7 @@ static int prosavage_gpio_getscl(void* data)
static int prosavage_gpio_getsda(void* data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
SET_CR_IX(chan->ioaddr, chan->reg);
return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
@@ -140,10 +140,9 @@ static int prosavage_gpio_getsda(void* data)
static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
const char *name)
{
- int (*add_bus)(struct i2c_adapter *) = symbol_get(i2c_bit_add_bus);
int rc = 0;
- if (add_bus && chan->par) {
+ if (chan->par) {
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_HW_B_SAVAGE;
@@ -161,7 +160,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
chan->algo.setscl(chan, 1);
udelay(20);
- rc = add_bus(&chan->adapter);
+ rc = i2c_bit_add_bus(&chan->adapter);
if (rc == 0)
dev_dbg(&chan->par->pcidev->dev,
@@ -169,8 +168,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
else
dev_warn(&chan->par->pcidev->dev,
"Failed to register I2C bus %s.\n", name);
-
- symbol_put(i2c_bit_add_bus);
} else
chan->par = NULL;
@@ -179,7 +176,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
void savagefb_create_i2c_busses(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
par->chan.par = par;
switch(info->fix.accel) {
@@ -193,6 +190,7 @@ void savagefb_create_i2c_busses(struct fb_info *info)
par->chan.algo.getscl = prosavage_gpio_getscl;
break;
case FB_ACCEL_SAVAGE4:
+ case FB_ACCEL_SAVAGE2000:
par->chan.reg = 0xff20;
par->chan.ioaddr = par->mmio.vbase;
par->chan.algo.setsda = savage4_gpio_setsda;
@@ -209,14 +207,10 @@ void savagefb_create_i2c_busses(struct fb_info *info)
void savagefb_delete_i2c_busses(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
- int (*del_bus)(struct i2c_adapter *) =
- symbol_get(i2c_bit_del_bus);
+ struct savagefb_par *par = info->par;
- if (del_bus && par->chan.par) {
- del_bus(&par->chan.adapter);
- symbol_put(i2c_bit_del_bus);
- }
+ if (par->chan.par)
+ i2c_bit_del_bus(&par->chan.adapter);
par->chan.par = NULL;
}
@@ -224,8 +218,6 @@ void savagefb_delete_i2c_busses(struct fb_info *info)
static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
{
u8 start = 0x0;
- int (*transfer)(struct i2c_adapter *, struct i2c_msg *, int) =
- symbol_get(i2c_transfer);
struct i2c_msg msgs[] = {
{
.addr = SAVAGE_DDC,
@@ -239,21 +231,19 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
};
u8 *buf = NULL;
- if (transfer && chan->par) {
+ if (chan->par) {
buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
if (buf) {
msgs[1].buf = buf;
- if (transfer(&chan->adapter, msgs, 2) != 2) {
+ if (i2c_transfer(&chan->adapter, msgs, 2) != 2) {
dev_dbg(&chan->par->pcidev->dev,
"Unable to read EDID block.\n");
kfree(buf);
buf = NULL;
}
}
-
- symbol_put(i2c_transfer);
}
return buf;
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
index bac8ea3a0108..bbcc055d3bb7 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/savage/savagefb_accel.c
@@ -21,7 +21,7 @@ static u32 savagefb_rop[] = {
int savagefb_sync(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
par->SavageWaitIdle(par);
return 0;
@@ -29,7 +29,7 @@ int savagefb_sync(struct fb_info *info)
void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int sx = region->sx, dx = region->dx;
int sy = region->sy, dy = region->dy;
int cmd;
@@ -63,7 +63,7 @@ void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int cmd, color;
if (!rect->width || !rect->height)
@@ -90,7 +90,7 @@ void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int fg, bg, size, i, width;
int cmd;
u32 *src = (u32 *) image->data;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 09e2f2841901..ab727eaa7f43 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -686,7 +686,7 @@ static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode
static int savagefb_check_var (struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int memlen, vramlen, mode_valid = 0;
DBG("savagefb_check_var");
@@ -1025,7 +1025,7 @@ static int savagefb_setcolreg(unsigned regno,
unsigned transp,
struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
if (regno >= NR_PALETTE)
return -EINVAL;
@@ -1328,7 +1328,7 @@ static void savagefb_set_fix(struct fb_info *info)
#if defined(CONFIG_FB_SAVAGE_ACCEL)
static void savagefb_set_clip(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int cmd;
cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
@@ -1342,7 +1342,7 @@ static void savagefb_set_clip(struct fb_info *info)
static int savagefb_set_par (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
struct fb_var_screeninfo *var = &info->var;
int err;
@@ -1381,29 +1381,9 @@ static int savagefb_set_par (struct fb_info *info)
static int savagefb_pan_display (struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
- u_int y_bottom;
-
- y_bottom = var->yoffset;
-
- if (!(var->vmode & FB_VMODE_YWRAP))
- y_bottom += var->yres;
-
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
- if (y_bottom > info->var.yres_virtual)
- return -EINVAL;
+ struct savagefb_par *par = info->par;
savagefb_update_start (par, var);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
-
- if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
- else
- info->var.vmode &= ~FB_VMODE_YWRAP;
-
return 0;
}
@@ -1534,7 +1514,7 @@ static void savage_disable_mmio (struct savagefb_par *par)
static int __devinit savage_map_mmio (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
DBG ("savage_map_mmio");
if (S3_SAVAGE3D_SERIES (par->chip))
@@ -1567,7 +1547,7 @@ static int __devinit savage_map_mmio (struct fb_info *info)
static void __devinit savage_unmap_mmio (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
DBG ("savage_unmap_mmio");
savage_disable_mmio(par);
@@ -1581,7 +1561,7 @@ static void __devinit savage_unmap_mmio (struct fb_info *info)
static int __devinit savage_map_video (struct fb_info *info,
int video_len)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int resource;
DBG("savage_map_video");
@@ -1619,7 +1599,7 @@ static int __devinit savage_map_video (struct fb_info *info,
static void __devinit savage_unmap_video (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
DBG("savage_unmap_video");
@@ -1869,7 +1849,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
struct pci_dev *dev,
const struct pci_device_id *id)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int err = 0;
par->pcidev = dev;
@@ -2139,8 +2119,7 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
static void __devexit savagefb_remove (struct pci_dev *dev)
{
- struct fb_info *info =
- (struct fb_info *)pci_get_drvdata(dev);
+ struct fb_info *info = pci_get_drvdata(dev);
DBG("savagefb_remove");
@@ -2174,9 +2153,8 @@ static void __devexit savagefb_remove (struct pci_dev *dev)
static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
{
- struct fb_info *info =
- (struct fb_info *)pci_get_drvdata(dev);
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct savagefb_par *par = info->par;
DBG("savagefb_suspend");
@@ -2210,9 +2188,8 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
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;
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct savagefb_par *par = info->par;
int cur_state = par->pm_state;
DBG("savage_resume");
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 3a74a63dd4f2..a4d7cc51ce0b 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -199,8 +199,7 @@ struct fbcmap32 {
#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
-static int fbiogetputcmap(struct file *file, struct fb_info *info,
- unsigned int cmd, unsigned long arg)
+static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct fbcmap32 __user *argp = (void __user *)arg;
struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
@@ -216,10 +215,10 @@ static int fbiogetputcmap(struct file *file, struct fb_info *info,
ret |= put_user(compat_ptr(addr), &p->blue);
if (ret)
return -EFAULT;
- return info->fbops->fb_ioctl(file->f_dentry->d_inode, file,
+ return info->fbops->fb_ioctl(info,
(cmd == FBIOPUTCMAP32) ?
FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
- (unsigned long)p, info);
+ (unsigned long)p);
}
struct fbcursor32 {
@@ -236,8 +235,7 @@ struct fbcursor32 {
#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
-static int fbiogscursor(struct file *file, struct fb_info *info,
- unsigned long arg)
+static int fbiogscursor(struct fb_info *info, unsigned long arg)
{
struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
struct fbcursor32 __user *argp = (void __user *)arg;
@@ -260,12 +258,10 @@ static int fbiogscursor(struct file *file, struct fb_info *info,
ret |= put_user(compat_ptr(addr), &p->image);
if (ret)
return -EFAULT;
- return info->fbops->fb_ioctl(file->f_dentry->d_inode, file,
- FBIOSCURSOR, (unsigned long)p, info);
+ return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
}
-long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case FBIOGTYPE:
@@ -278,14 +274,13 @@ long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
case FBIOSCURPOS:
case FBIOGCURPOS:
case FBIOGCURMAX:
- return info->fbops->fb_ioctl(file->f_dentry->d_inode,
- file, cmd, arg, info);
+ return info->fbops->fb_ioctl(info, cmd, arg);
case FBIOPUTCMAP32:
- return fbiogetputcmap(file, info, cmd, arg);
+ return fbiogetputcmap(info, cmd, arg);
case FBIOGETCMAP32:
- return fbiogetputcmap(file, info, cmd, arg);
+ return fbiogetputcmap(info, cmd, arg);
case FBIOSCURSOR32:
- return fbiogscursor(file, info, arg);
+ return fbiogscursor(info, arg);
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
index b470e52ce9e2..492828c3fe8f 100644
--- a/drivers/video/sbuslib.h
+++ b/drivers/video/sbuslib.h
@@ -20,7 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
struct fb_info *info,
int type, int fb_depth, unsigned long fb_size);
-long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info);
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
#endif /* _SBUSLIB_H */
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 7054660767e4..2e6df1fcb2b9 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -115,7 +115,7 @@ static int sgivwfb_set_par(struct fb_info *info);
static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
-static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static struct fb_ops sgivwfb_ops = {
@@ -706,7 +706,7 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
return 0;
}
-static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
@@ -723,7 +723,6 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file,
if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
- vma->vm_file = file;
printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
offset, vma->vm_start);
return 0;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index dea1a46c67c4..8adf5bf91eee 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1743,13 +1743,14 @@ sisfb_blank(int blank, struct fb_info *info)
/* ----------- FBDev related routines for all series ---------- */
-static int
-sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- int con,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+#else
+static int sisfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ struct fb_info *info)
#endif
- struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
struct sis_memreq sismemreq;
@@ -1924,19 +1925,6 @@ sisfb_ioctl(struct inode *inode, struct file *file,
return 0;
}
-#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();
- return ret;
-}
-#endif
-
static int
sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
@@ -2007,7 +1995,7 @@ static struct fb_ops sisfb_ops = {
#endif
.fb_sync = fbcon_sis_sync,
#ifdef SIS_NEW_CONFIG_COMPAT
- .fb_compat_ioctl= sisfb_compat_ioctl,
+ .fb_compat_ioctl= sisfb_ioctl,
#endif
.fb_ioctl = sisfb_ioctl
};
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 445bcbba03ae..70b6df371b8e 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -727,9 +727,14 @@ static int sisfb_ioctl(struct inode *inode, struct file *file,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
+#else
static int sisfb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
struct fb_info *info);
+#endif
static int sisfb_set_par(struct fb_info *info);
static int sisfb_blank(int blank,
struct fb_info *info);
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a01e7ecc15ed..9b707771d757 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -115,7 +115,8 @@ static struct fb_fix_screeninfo xxxfb_fix __initdata = {
/*
* If your driver supports multiple boards or it supports multiple
* framebuffers, you should make these arrays, or allocate them
- * dynamically (using kmalloc()).
+ * dynamically using framebuffer_alloc() and free them with
+ * framebuffer_release().
*/
static struct fb_info info;
@@ -179,18 +180,31 @@ static int xxxfb_release(const struct fb_info *info, int user)
* intent to only test a mode and not actually set it. The stuff in
* modedb.c is a example of this. If the var passed in is slightly
* off by what the hardware can support then we alter the var PASSED in
- * to what we can do. If the hardware doesn't support mode change
- * a -EINVAL will be returned by the upper layers. You don't need to
- * implement this function then. If you hardware doesn't support
- * changing the resolution then this function is not needed. In this
- * case the driver woudl just provide a var that represents the static
- * state the screen is in.
+ * to what we can do.
+ *
+ * For values that are off, this function must round them _up_ to the
+ * next value that is supported by the hardware. If the value is
+ * greater than the highest value supported by the hardware, then this
+ * function must return -EINVAL.
+ *
+ * Exception to the above rule: Some drivers have a fixed mode, ie,
+ * the hardware is already set at boot up, and cannot be changed. In
+ * this case, it is more acceptable that this function just return
+ * a copy of the currently working var (info->var). Better is to not
+ * implement this function, as the upper layer will do the copying
+ * of the current var for you.
+ *
+ * Note: This is the only function where the contents of var can be
+ * freely adjusted after the driver has been registered. If you find
+ * that you have code outside of this function that alters the content
+ * of var, then you are doing something wrong. Note also that the
+ * contents of info->var must be left untouched at all times after
+ * driver registration.
*
* Returns negative errno on error, or zero on success.
*/
static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- const struct xxx_par *par = (const struct xxx_par *) info->par;
/* ... */
return 0;
}
@@ -204,14 +218,39 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
* fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
* fb_info since we are using that data. This means we depend on the
* data in var inside fb_info to be supported by the hardware.
- * xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ *
+ * This function is also used to recover/restore the hardware to a
+ * known working state.
+ *
+ * xxxfb_check_var is always called before xxxfb_set_par to ensure that
+ * the contents of var is always valid.
+ *
* Again if you can't change the resolution you don't need this function.
*
+ * However, even if your hardware does not support mode changing,
+ * a set_par might be needed to at least initialize the hardware to
+ * a known working state, especially if it came back from another
+ * process that also modifies the same hardware, such as X.
+ *
+ * If this is the case, a combination such as the following should work:
+ *
+ * static int xxxfb_check_var(struct fb_var_screeninfo *var,
+ * struct fb_info *info)
+ * {
+ * *var = info->var;
+ * return 0;
+ * }
+ *
+ * static int xxxfb_set_par(struct fb_info *info)
+ * {
+ * init your hardware here
+ * }
+ *
* Returns negative errno on error, or zero on success.
*/
static int xxxfb_set_par(struct fb_info *info)
{
- struct xxx_par *par = (struct xxx_par *) info->par;
+ struct xxx_par *par = info->par;
/* ... */
return 0;
}
@@ -258,70 +297,110 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of DAC
- * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+ * pseudo_palette[X] is programmed to (X << red.offset) |
+ * (X << green.offset) |
+ * (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
+ * color depth = SUM(var->{color}.length)
*
* Pseudocolor:
- * uses offset = 0 && length = DAC register width.
* var->{color}.offset is 0
- * var->{color}.length contains widht of DAC
- * cmap is not used
- * DAC[X] is programmed to (red, green, blue)
+ * var->{color}.length contains width of DAC or the number of unique
+ * colors available (color depth)
+ * pseudo_palette is not used
+ * RAMDAC[X] is programmed to (red, green, blue)
+ * color depth = var->{color}.length
+ *
+ * Static pseudocolor:
+ * same as Pseudocolor, but the RAMDAC is not programmed (read-only)
+ *
+ * Mono01/Mono10:
+ * Has only 2 values, black on white or white on black (fg on bg),
+ * var->{color}.offset is 0
+ * white = (1 << var->{color}.length) - 1, black = 0
+ * pseudo_palette is not used
+ * RAMDAC does not exist
+ * color depth is always 2
+ *
* Truecolor:
* does not use RAMDAC (usually has 3 of them).
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
- * cmap is programmed to (red << red.offset) | (green << green.offset) |
- * (blue << blue.offset) | (transp << transp.offset)
+ * pseudo_palette is programmed to (red << red.offset) |
+ * (green << green.offset) |
+ * (blue << blue.offset) |
+ * (transp << transp.offset)
* RAMDAC does not exist
+ * color depth = SUM(var->{color}.length})
+ *
+ * The color depth is used by fbcon for choosing the logo and also
+ * for color palette transformation if color depth < 4
+ *
+ * As can be seen from the above, the field bits_per_pixel is _NOT_
+ * a criteria for describing the color visual.
+ *
+ * A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor,
+ * and higher than that, true/directcolor. This is incorrect, one needs
+ * to look at the fix->visual.
+ *
+ * Another common mistake is using bits_per_pixel to calculate the color
+ * depth. The bits_per_pixel field does not directly translate to color
+ * depth. You have to compute for the color depth (using the color
+ * bitfields) and fix->visual as seen above.
+ */
+
+ /*
+ * This is the point where the color is converted to something that
+ * is acceptable by the hardware.
*/
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
- switch (info->fix.visual) {
- case FB_VISUAL_TRUECOLOR:
- case FB_VISUAL_PSEUDOCOLOR:
- red = CNVT_TOHW(red, info->var.red.length);
- green = CNVT_TOHW(green, info->var.green.length);
- blue = CNVT_TOHW(blue, info->var.blue.length);
- transp = CNVT_TOHW(transp, info->var.transp.length);
- break;
- case FB_VISUAL_DIRECTCOLOR:
- /* example here assumes 8 bit DAC. Might be different
- * for your hardware */
- red = CNVT_TOHW(red, 8);
- green = CNVT_TOHW(green, 8);
- blue = CNVT_TOHW(blue, 8);
- /* hey, there is bug in transp handling... */
- transp = CNVT_TOHW(transp, 8);
- break;
- }
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
#undef CNVT_TOHW
- /* Truecolor has hardware independent palette */
- if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
- u32 v;
-
- if (regno >= 16)
- return -EINVAL;
-
- v = (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset) |
- (transp << info->var.transp.offset);
-
- switch (info->var.bits_per_pixel) {
- case 8:
- /* Yes some hand held devices have this. */
- ((u8*)(info->pseudo_palette))[regno] = v;
- break;
- case 16:
- ((u16*)(info->pseudo_palette))[regno] = v;
- break;
- case 24:
- case 32:
- ((u32*)(info->pseudo_palette))[regno] = v;
- break;
- }
- return 0;
+ /*
+ * This is the point where the function feeds the color to the hardware
+ * palette after converting the colors to something acceptable by
+ * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and
+ * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette.
+ * If you have code that writes to the hardware CLUT, and it's not
+ * any of the above visuals, then you are doing something wrong.
+ */
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
+ info->fix.visual == FB_VISUAL_TRUECOLOR)
+ write_{red|green|blue|transp}_to_clut();
+
+ /* This is the point were you need to fill up the contents of
+ * info->pseudo_palette. This structure is used _only_ by fbcon, thus
+ * it only contains 16 entries to match the number of colors supported
+ * by the console. The pseudo_palette is used only if the visual is
+ * in directcolor or truecolor mode. With other visuals, the
+ * pseudo_palette is not used. (This might change in the future.)
+ *
+ * The contents of the pseudo_palette is in raw pixel format. Ie, each
+ * entry can be written directly to the framebuffer without any conversion.
+ * The pseudo_palette is (void *). However, if using the generic
+ * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette
+ * must be casted to (u32 *) _regardless_ of the bits per pixel. If the
+ * driver is using its own drawing functions, then it can use whatever
+ * size it wants.
+ */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ u32 v;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ v = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ ((u32*)(info->pseudo_palette))[regno] = v;
}
+
/* ... */
return 0;
}
@@ -340,6 +419,17 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int xxxfb_pan_display(struct fb_var_screeninfo *var,
const struct fb_info *info)
{
+ /*
+ * If your hardware does not support panning, _do_ _not_ implement this
+ * function. Creating a dummy function will just confuse user apps.
+ */
+
+ /*
+ * Note that even if this function is fully functional, a setting of
+ * 0 in both xpanstep and ypanstep means that this function will never
+ * get called.
+ */
+
/* ... */
return 0;
}
@@ -349,15 +439,20 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var,
* @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
+ * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
+ * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+ * e.g. a video mode which doesn't support it.
*
- * Returns negative errno on error, or zero on success.
+ * Implements VESA suspend and powerdown modes on hardware that supports
+ * disabling hsync/vsync:
+ *
+ * FB_BLANK_NORMAL = display is blanked, syncs are on.
+ * FB_BLANK_HSYNC_SUSPEND = hsync off
+ * FB_BLANK_VSYNC_SUSPEND = vsync off
+ * FB_BLANK_POWERDOWN = hsync and vsync off
+ *
+ * If implementing this function, at least support FB_BLANK_UNBLANK.
+ * Return !0 for any modes that are unimplemented.
*
*/
static int xxxfb_blank(int blank_mode, const struct fb_info *info)
@@ -454,6 +549,14 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image)
* @data: The actual data used to construct the image on the display.
* @cmap: The colormap used for color images.
*/
+
+/*
+ * The generic function, cfb_imageblit, expects that the bitmap scanlines are
+ * padded to the next byte. Most hardware accelerators may require padding to
+ * the next u16 or the next u32. If that is the case, the driver can specify
+ * this by setting info->pixmap.scan_align = 2 or 4. See a more
+ * comprehensive description of the pixmap below.
+ */
}
/**
@@ -517,6 +620,7 @@ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
*/
void xxxfb_rotate(struct fb_info *info, int angle)
{
+/* Will be deprecated */
}
/**
@@ -540,6 +644,9 @@ void xxxfb_poll(struct fb_info *info, poll_table *wait)
* so we can have consistent display output.
*
* @info: frame buffer structure that represents a single frame buffer
+ *
+ * If the driver has implemented its own hardware-based drawing function,
+ * implementing this function is highly recommended.
*/
void xxxfb_sync(struct fb_info *info)
{
@@ -549,20 +656,25 @@ void xxxfb_sync(struct fb_info *info)
* Initialization
*/
-int __init xxxfb_init(void)
+/* static int __init xxfb_probe (struct device *device) -- for platform devs */
+static int __init xxxfb_probe(struct pci_dev *dev,
+ const_struct pci_device_id *ent)
{
+ struct fb_info *info;
+ struct xxx_par *par;
+ struct device = &dev->dev; /* for pci drivers */
int cmap_len, retval;
/*
- * For kernel boot options (in 'video=xxxfb:<options>' format)
+ * Dynamically allocate info and par
*/
-#ifndef MODULE
- char *option = NULL;
+ info = framebuffer_alloc(sizeof(struct xxx_par), device);
- if (fb_get_options("xxxfb", &option))
- return -ENODEV;
- xxxfb_setup(option);
-#endif
+ if (!info) {
+ /* goto error path */
+ }
+
+ par = info->par;
/*
* Here we set the screen_base to the virtual memory address
@@ -570,18 +682,87 @@ int __init xxxfb_init(void)
* from the bus layer and then translate it to virtual memory
* space via ioremap. Consult ioport.h.
*/
- info.screen_base = framebuffer_virtual_memory;
- info.fbops = &xxxfb_ops;
- info.fix = xxxfb_fix;
- info.pseudo_palette = pseudo_palette;
-
+ info->screen_base = framebuffer_virtual_memory;
+ info->fbops = &xxxfb_ops;
+ info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be
+ * used, so mark it as __initdata
+ */
+ info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
+ * 16-member array
+ */
/*
* Set up flags to indicate what sort of acceleration your
* driver can provide (pan/wrap/copyarea/etc.) and whether it
* is a module -- see FBINFO_* in include/linux/fb.h
+ *
+ * If your hardware can support any of the hardware accelerated functions
+ * fbcon performance will improve if info->flags is set properly.
+ *
+ * FBINFO_HWACCEL_COPYAREA - hardware moves
+ * FBINFO_HWACCEL_FILLRECT - hardware fills
+ * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
+ * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
+ * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
+ * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
+ * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
+ * FBINFO_MISC_TILEBLITTING - hardware can do tile blits
+ *
+ * NOTE: These are for fbcon use only.
+ */
+ info->flags = FBINFO_DEFAULT;
+
+/********************* This stage is optional ******************************/
+ /*
+ * The struct pixmap is a scratch pad for the drawing functions. This
+ * is where the monochrome bitmap is constructed by the higher layers
+ * and then passed to the accelerator. For drivers that uses
+ * cfb_imageblit, you can skip this part. For those that have a more
+ * rigorous requirement, this stage is needed
+ */
+
+ /* PIXMAP_SIZE should be small enough to optimize drawing, but not
+ * large enough that memory is wasted. A safe size is
+ * (max_xres * max_font_height/8). max_xres is driver dependent,
+ * max_font_height is 32.
+ */
+ info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ /* goto error */
+ }
+
+ info->pixmap.size = PIXMAP_SIZE;
+
+ /*
+ * FB_PIXMAP_SYSTEM - memory is in system ram
+ * FB_PIXMAP_IO - memory is iomapped
+ * FB_PIXMAP_SYNC - if set, will call fb_sync() per access to pixmap,
+ * usually if FB_PIXMAP_IO is set.
+ *
+ * Currently, FB_PIXMAP_IO is unimplemented.
+ */
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+ /*
+ * scan_align is the number of padding for each scanline. It is in bytes.
+ * Thus for accelerators that need padding to the next u32, put 4 here.
+ */
+ info->pixmap.scan_align = 4;
+
+ /*
+ * buf_align is the amount to be padded for the buffer. For example,
+ * the i810fb needs a scan_align of 2 but expects it to be fed with
+ * dwords, so a buf_align = 4 is required.
*/
- info.flags = FBINFO_DEFAULT;
- info.par = current_par;
+ info->pixmap.buf_align = 4;
+
+ /* access_align is how many bits can be accessed from the framebuffer
+ * ie. some epson cards allow 16-bit access only. Most drivers will
+ * be safe with u32 here.
+ *
+ * NOTE: This field is currently unused.
+ */
+ info->pixmap.scan_align = 32
+/***************************** End optional stage ***************************/
/*
* This should give a reasonable default video mode. The following is
@@ -590,42 +771,145 @@ int __init xxxfb_init(void)
if (!mode_option)
mode_option = "640x480@60";
- retval = fb_find_mode(&info.var, &info, mode_option, NULL, 0, NULL, 8);
+ retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8);
if (!retval || retval == 4)
return -EINVAL;
/* This has to been done !!! */
- fb_alloc_cmap(&info.cmap, cmap_len, 0);
+ fb_alloc_cmap(info->cmap, cmap_len, 0);
/*
* The following is done in the case of having hardware with a static
* mode. If we are setting the mode ourselves we don't call this.
*/
- info.var = xxxfb_var;
-
- if (register_framebuffer(&info) < 0)
+ info->var = xxxfb_var;
+
+ /*
+ * For drivers that can...
+ */
+ xxxfb_check_var(&info->var, info);
+
+ /*
+ * Does a call to fb_set_par() before register_framebuffer needed? This
+ * will depend on you and the hardware. If you are sure that your driver
+ * is the only device in the system, a call to fb_set_par() is safe.
+ *
+ * Hardware in x86 systems has a VGA core. Calling set_par() at this
+ * point will corrupt the VGA console, so it might be safer to skip a
+ * call to set_par here and just allow fbcon to do it for you.
+ */
+ /* xxxfb_set_par(info); */
+
+ if (register_framebuffer(info) < 0)
return -EINVAL;
- printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
- info.fix.id);
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+ pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
return 0;
}
/*
* Cleanup
*/
+/* static void __exit xxxfb_remove(struct device *device) */
+static void __exit xxxfb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drv_data(dev);
+ /* or dev_get_drv_data(device); */
+
+ if (info) {
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info.cmap);
+ /* ... */
+ framebuffer_release(info);
+ }
+
+ return 0;
+}
-static void __exit xxxfb_cleanup(void)
+#if CONFIG_PCI
+/* For PCI drivers */
+static struct pci_driver xxxfb_driver = {
+ .name = "xxxfb",
+ .id_table = xxxfb_devices,
+ .probe = xxxfb_probe,
+ .remove = __devexit_p(xxxfb_remove),
+ .suspend = xxxfb_suspend, /* optional */
+ .resume = xxxfb_resume, /* optional */
+};
+
+static int __init xxxfb_init(void)
{
- /*
- * If your driver supports multiple boards, you should unregister and
- * clean up all instances.
- */
+ /*
+ * For kernel boot options (in 'video=xxxfb:<options>' format)
+ */
+#ifndef MODULE
+ char *option = NULL;
- unregister_framebuffer(info);
- fb_dealloc_cmap(&info.cmap);
- /* ... */
+ if (fb_get_options("xxxfb", &option))
+ return -ENODEV;
+ xxxfb_setup(option);
+#endif
+
+ return pci_register_driver(&xxxfb_driver);
+}
+
+static void __exit xxxfb_exit(void)
+{
+ pci_unregister_driver(&xxxfb_driver);
}
+#else
+#include <linux/platform_device.h>
+/* for platform devices */
+static struct device_driver xxxfb_driver = {
+ .name = "xxxfb",
+ .bus = &platform_bus_type,
+ .probe = xxxfb_probe,
+ .remove = xxxfb_remove,
+ .suspend = xxxfb_suspend, /* optional */
+ .resume = xxxfb_resume, /* optional */
+};
+
+static struct platform_device xxxfb_device = {
+ .name = "xxxfb",
+};
+
+static int __init xxxfb_init(void)
+{
+ int ret;
+ /*
+ * For kernel boot options (in 'video=xxxfb:<options>' format)
+ */
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("xxxfb", &option))
+ return -ENODEV;
+ xxxfb_setup(option);
+#endif
+ ret = driver_register(&xxxfb_driver);
+
+ if (!ret) {
+ ret = platform_device_register(&xxxfb_device);
+ if (ret)
+ driver_unregister(&xxxfb_driver);
+ }
+
+ return ret;
+}
+
+static void __exit xxxfb_exit(void)
+{
+ platform_device_unregister(&xxxfb_device);
+ driver_unregister(&xxxfb_driver);
+}
+#endif
+
+MODULE_LICENSE("GPL");
+module_init(xxxfb_init);
+module_exit(xxxfb_exit);
+
/*
* Setup
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index e0f14df840d9..99921df35474 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -382,7 +382,7 @@ static void sstfb_clear_screen(struct fb_info *info)
static int sstfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int hSyncOff = var->xres + var->right_margin + var->left_margin;
int vSyncOff = var->yres + var->lower_margin + var->upper_margin;
int vBackPorch = var->left_margin, yDim = var->yres;
@@ -542,7 +542,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
*/
static int sstfb_set_par(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
struct pci_dev *sst_dev = par->dev;
unsigned int freq;
@@ -748,13 +748,14 @@ static int sstfb_set_par(struct fb_info *info)
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
+ struct sstfb_par *par = info->par;
u32 col;
f_dddprintk("sstfb_setcolreg\n");
f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
regno, red, green, blue, transp);
- if (regno >= 16)
- return -EINVAL;
+ if (regno > 15)
+ return 0;
red >>= (16 - info->var.red.length);
green >>= (16 - info->var.green.length);
@@ -765,15 +766,14 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
| (blue << info->var.blue.offset)
| (transp << info->var.transp.offset);
- ((u32 *)info->pseudo_palette)[regno] = col;
+ par->palette[regno] = col;
return 0;
}
-static int sstfb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, struct fb_info *info )
+static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
struct pci_dev *sst_dev = par->dev;
u32 fbiinit0, tmp, val;
u_long p;
@@ -830,7 +830,7 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
#if 0
static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u32 stride = info->fix.line_length;
if (!IS_VOODOO2(par))
@@ -855,7 +855,7 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
*/
static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u32 stride = info->fix.line_length;
if (!IS_VOODOO2(par))
@@ -925,7 +925,7 @@ static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize)
static int __devinit sst_detect_att(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int i, mir, dir;
for (i=0; i<3; i++) {
@@ -950,7 +950,7 @@ static int __devinit sst_detect_att(struct fb_info *info)
static int __devinit sst_detect_ti(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int i, mir, dir;
for (i = 0; i<3; i++) {
@@ -986,7 +986,7 @@ static int __devinit sst_detect_ti(struct fb_info *info)
*/
static int __devinit sst_detect_ics(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int m_clk0_1, m_clk0_7, m_clk1_b;
int n_clk0_1, n_clk0_7, n_clk1_b;
int i;
@@ -1023,7 +1023,7 @@ static int __devinit sst_detect_ics(struct fb_info *info)
static int sst_set_pll_att_ti(struct fb_info *info,
const struct pll_timing *t, const int clock)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u8 cr0, cc;
/* enable indexed mode */
@@ -1077,7 +1077,7 @@ static int sst_set_pll_att_ti(struct fb_info *info,
static int sst_set_pll_ics(struct fb_info *info,
const struct pll_timing *t, const int clock)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u8 pll_ctrl;
sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
@@ -1114,7 +1114,7 @@ static int sst_set_pll_ics(struct fb_info *info,
static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u8 cr0;
sst_dac_write(DACREG_WMA, 0); /* backdoor */
@@ -1149,7 +1149,7 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
switch(bpp) {
case 16:
@@ -1308,7 +1308,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
static void __devexit sst_shutdown(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings;
int Fout;
@@ -1394,12 +1394,6 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
struct sst_spec *spec;
int err;
- struct all_info {
- struct fb_info info;
- struct sstfb_par par;
- u32 pseudo_palette[16];
- } *all;
-
/* Enable device in PCI config. */
if ((err=pci_enable_device(pdev))) {
eprintk("cannot enable device\n");
@@ -1407,14 +1401,13 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
}
/* Allocate the fb and par structures. */
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all)
+ info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
+ if (!info)
return -ENOMEM;
- memset(all, 0, sizeof(*all));
- pci_set_drvdata(pdev, all);
+
+ pci_set_drvdata(pdev, info);
- info = &all->info;
- par = info->par = &all->par;
+ par = info->par;
fix = &info->fix;
par->type = id->driver_data;
@@ -1471,7 +1464,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
info->flags = FBINFO_DEFAULT;
info->fbops = &sstfb_ops;
- info->pseudo_palette = &all->pseudo_palette;
+ info->pseudo_palette = par->palette;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_TRUECOLOR;
@@ -1527,7 +1520,7 @@ fail_mmio_remap:
fail_fb_mem:
release_mem_region(fix->mmio_start, info->fix.mmio_len);
fail_mmio_mem:
- kfree(info);
+ framebuffer_release(info);
return -ENXIO; /* no voodoo detected */
}
@@ -1537,7 +1530,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
struct fb_info *info;
info = pci_get_drvdata(pdev);
- par = (struct sstfb_par *) info->par;
+ par = info->par;
sst_shutdown(info);
unregister_framebuffer(info);
@@ -1545,7 +1538,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
iounmap(par->mmio_vbase);
release_mem_region(info->fix.smem_start, 0x400000);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
- kfree(info);
+ framebuffer_release(info);
}
@@ -1613,7 +1606,7 @@ static int sstfb_dump_regs(struct fb_info *info)
const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);
const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
struct pci_dev *dev = par->dev;
u32 pci_res[pci_s];
u32 sst_res[sst_s];
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index fbb17332afd7..56d71d6e9a72 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -3,7 +3,7 @@
* Low level Frame buffer driver for HP workstations with
* STI (standard text interface) video firmware.
*
- * Copyright (C) 2001-2004 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2005 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
*
* Based on:
@@ -73,16 +73,13 @@
#include "sticore.h"
/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
-#ifdef __LP64__
- #define REGION_BASE(fb_info, index) \
- (fb_info->sti->glob_cfg->region_ptrs[index] | 0xffffffff00000000)
-#else
- #define REGION_BASE(fb_info, index) \
- fb_info->sti->glob_cfg->region_ptrs[index]
-#endif
+#define REGION_BASE(fb_info, index) \
+ F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
#define NGLEDEVDEPROM_CRT_REGION 1
+#define NR_PALETTE 256
+
typedef struct {
__s32 video_config_reg;
__s32 misc_video_start;
@@ -112,7 +109,7 @@ struct stifb_info {
ngle_rom_t ngle_rom;
struct sti_struct *sti;
int deviceSpecificConfig;
- u32 pseudo_palette[256];
+ u32 pseudo_palette[16];
};
static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
@@ -352,10 +349,10 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
#define IS_888_DEVICE(fb) \
(!(IS_24_DEVICE(fb)))
-#define GET_FIFO_SLOTS(fb, cnt, numslots) \
-{ while (cnt < numslots) \
+#define GET_FIFO_SLOTS(fb, cnt, numslots) \
+{ while (cnt < numslots) \
cnt = READ_WORD(fb, REG_34); \
- cnt -= numslots; \
+ cnt -= numslots; \
}
#define IndexedDcd 0 /* Pixel data is indexed (pseudo) color */
@@ -995,7 +992,7 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
struct stifb_info *fb = (struct stifb_info *) info;
u32 color;
- if (regno >= 256) /* no. of hw registers */
+ if (regno >= NR_PALETTE)
return 1;
red >>= 8;
@@ -1005,8 +1002,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
DEBUG_OFF();
START_IMAGE_COLORMAP_ACCESS(fb);
-
- if (fb->info.var.grayscale) {
+
+ if (unlikely(fb->info.var.grayscale)) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
color = ((red * 77) +
(green * 151) +
@@ -1017,17 +1014,17 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
(blue));
}
- if (info->var.bits_per_pixel == 32) {
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- } else {
- ((u32 *)(info->pseudo_palette))[regno] = regno;
+ if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ struct fb_var_screeninfo *var = &fb->info.var;
+ if (regno < 16)
+ ((u32 *)fb->info.pseudo_palette)[regno] =
+ regno << var->red.offset |
+ regno << var->green.offset |
+ regno << var->blue.offset;
}
WRITE_IMAGE_COLOR(fb, regno, color);
-
+
if (fb->id == S9000_ID_HCRX) {
NgleLutBltCtl lutBltCtl;
@@ -1066,9 +1063,9 @@ stifb_blank(int blank_mode, struct fb_info *info)
case S9000_ID_HCRX:
HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
break;
- case S9000_ID_A1659A:; /* fall through */
- case S9000_ID_TIMBER:;
- case CRX24_OVERLAY_PLANES:;
+ case S9000_ID_A1659A: /* fall through */
+ case S9000_ID_TIMBER:
+ case CRX24_OVERLAY_PLANES:
default:
ENABLE_DISABLE_DISPLAY(fb, enable);
break;
@@ -1250,12 +1247,10 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
if ((fb->sti->regions_phys[0] & 0xfc000000) ==
(fb->sti->regions_phys[2] & 0xfc000000))
- sti_rom_address = fb->sti->regions_phys[0];
+ sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
else
- sti_rom_address = fb->sti->regions_phys[1];
-#ifdef __LP64__
- sti_rom_address |= 0xffffffff00000000;
-#endif
+ sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
+
fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
if (IS_24_DEVICE(fb)) {
if (bpp_pref == 8 || bpp_pref == 32)
@@ -1315,7 +1310,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
break;
case 32:
fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
var->blue.offset = 0;
var->green.offset = 8;
@@ -1337,7 +1332,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
info->pseudo_palette = &fb->pseudo_palette;
/* This has to been done !!! */
- fb_alloc_cmap(&info->cmap, 256, 0);
+ fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
stifb_init_display(fb);
if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
@@ -1488,7 +1483,3 @@ module_exit(stifb_cleanup);
MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
MODULE_LICENSE("GPL v2");
-
-MODULE_PARM(bpp, "i");
-MODULE_PARM_DESC(mem, "Bits per pixel (default: 8)");
-
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 2b27b4474001..95b918229d9b 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -33,9 +33,8 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int tcx_blank(int, struct fb_info *);
-static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int tcx_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int tcx_mmap(struct fb_info *, struct vm_area_struct *);
+static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long);
static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -302,7 +301,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = {
{ .size = 0 }
};
-static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct tcx_par *par = (struct tcx_par *)info->par;
@@ -312,8 +311,8 @@ static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct tcx_par *par = (struct tcx_par *) info->par;
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 9d53387e6a66..3e7baf4c9fa8 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -291,7 +291,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
static int banshee_wait_idle(struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
int i = 0;
banshee_make_room(par, 1);
@@ -364,7 +364,7 @@ static u32 do_calc_pll(int freq, int* freq_out)
static void do_write_regs(struct fb_info *info, struct banshee_reg* reg)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
int i;
banshee_wait_idle(info);
@@ -469,7 +469,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 lpitch;
if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
@@ -558,7 +558,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
static int tdfxfb_set_par(struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 hdispend, hsyncsta, hsyncend, htotal;
u32 hd, hs, he, ht, hbs, hbe;
u32 vd, vs, ve, vt, vbs, vbe;
@@ -780,7 +780,7 @@ static int tdfxfb_set_par(struct fb_info *info)
static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue,unsigned transp,struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 rgbcol;
if (regno >= info->cmap.len || regno > 255) return 1;
@@ -794,11 +794,15 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
break;
/* Truecolor has no hardware color palettes. */
case FB_VISUAL_TRUECOLOR:
- rgbcol = (CNVT_TOHW( red, info->var.red.length) << info->var.red.offset) |
- (CNVT_TOHW( green, info->var.green.length) << info->var.green.offset) |
- (CNVT_TOHW( blue, info->var.blue.length) << info->var.blue.offset) |
- (CNVT_TOHW( transp, info->var.transp.length) << info->var.transp.offset);
- ((u32*)(info->pseudo_palette))[regno] = rgbcol;
+ rgbcol = (CNVT_TOHW( red, info->var.red.length) <<
+ info->var.red.offset) |
+ (CNVT_TOHW( green, info->var.green.length) <<
+ info->var.green.offset) |
+ (CNVT_TOHW( blue, info->var.blue.length) <<
+ info->var.blue.offset) |
+ (CNVT_TOHW( transp, info->var.transp.length) <<
+ info->var.transp.offset);
+ par->palette[regno] = rgbcol;
break;
default:
DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
@@ -810,7 +814,7 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
static int tdfxfb_blank(int blank, struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 dacmode, state = 0, vgablank = 0;
dacmode = tdfx_inl(par, DACMODE);
@@ -855,7 +859,7 @@ static int tdfxfb_blank(int blank, struct fb_info *info)
static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 addr;
if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
@@ -878,7 +882,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
*/
static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
@@ -894,7 +898,7 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
tdfx_outl(par, COLORFORE, rect->color);
} else { /* FB_VISUAL_TRUECOLOR */
- tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]);
+ tdfx_outl(par, COLORFORE, par->palette[rect->color]);
}
tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
@@ -906,7 +910,7 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
*/
static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
@@ -938,7 +942,7 @@ static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area
static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
int size = image->height * ((image->width * image->depth + 7)>>3);
int fifo_free;
int i, stride = info->fix.line_length;
@@ -961,8 +965,10 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
break;
case FB_VISUAL_TRUECOLOR:
default:
- tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[image->fg_color]);
- tdfx_outl(par, COLORBACK, ((u32*)(info->pseudo_palette))[image->bg_color]);
+ tdfx_outl(par, COLORFORE,
+ par->palette[image->fg_color]);
+ tdfx_outl(par, COLORBACK,
+ par->palette[image->bg_color]);
}
#ifdef __BIG_ENDIAN
srcfmt = 0x400000 | BIT(20);
@@ -1007,7 +1013,7 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
#ifdef TDFX_HARDWARE_CURSOR
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
unsigned long flags;
/*
@@ -1157,18 +1163,17 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
{
struct tdfx_par *default_par;
struct fb_info *info;
- int size, err, lpitch;
+ int err, lpitch;
if ((err = pci_enable_device(pdev))) {
printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
return err;
}
- size = sizeof(struct tdfx_par)+256*sizeof(u32);
+ info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);
- info = framebuffer_alloc(size, &pdev->dev);
-
- if (!info) return -ENOMEM;
+ if (!info)
+ return -ENOMEM;
default_par = info->par;
@@ -1248,7 +1253,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
info->fbops = &tdfxfb_ops;
info->fix = tdfx_fix;
- info->pseudo_palette = (void *)(default_par + 1);
+ info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
#ifdef CONFIG_FB_3DFX_ACCEL
info->flags |= FBINFO_HWACCEL_FILLRECT |
@@ -1307,7 +1312,7 @@ out_err:
}
#ifndef MODULE
-void tdfxfb_setup(char *options)
+static void tdfxfb_setup(char *options)
{
char* this_opt;
@@ -1340,7 +1345,7 @@ void tdfxfb_setup(char *options)
static void __devexit tdfxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
unregister_framebuffer(info);
iounmap(par->regbase_virt);
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index ce97ec8eae97..2bdeb4baa952 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -342,19 +342,19 @@ int __init valkyriefb_init(void)
#else /* ppc (!CONFIG_MAC) */
{
struct device_node *dp;
+ struct resource r;
- dp = find_devices("valkyrie");
+ dp = of_find_node_by_name(NULL, "valkyrie");
if (dp == 0)
return 0;
- if (dp->n_addrs != 1) {
- printk(KERN_ERR "expecting 1 address for valkyrie (got %d)\n",
- dp->n_addrs);
+ if (of_address_to_resource(dp, 0, &r)) {
+ printk(KERN_ERR "can't find address for valkyrie\n");
return 0;
}
- frame_buffer_phys = dp->addrs[0].address;
- cmap_regs_phys = dp->addrs[0].address+0x304000;
+ frame_buffer_phys = r.start;
+ cmap_regs_phys = r.start + 0x304000;
flags = _PAGE_WRITETHRU;
}
#endif /* ppc (!CONFIG_MAC) */
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 3e58ddc2bc38..8982e540214c 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -57,7 +57,6 @@ static unsigned short *pmi_base = NULL;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static int depth;
-static int vga_compat;
/* --------------------------------------------------------------------- */
@@ -67,15 +66,6 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
#ifdef __i386__
int offset;
- if (!ypan)
- return -EINVAL;
- if (var->xoffset)
- return -EINVAL;
- if (var->yoffset > var->yres_virtual)
- return -EINVAL;
- if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
- return -EINVAL;
-
offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
__asm__ __volatile__(
@@ -90,37 +80,6 @@ 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)
{
@@ -205,7 +164,6 @@ 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,
@@ -459,9 +417,8 @@ static int __init vesafb_probe(struct platform_device *dev)
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 (!ypan)
+ info->fbops->fb_pan_display = NULL;
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
err = -ENOMEM;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index ffa1ad474226..53208cb58396 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -81,7 +81,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
-static int vfb_mmap(struct fb_info *info, struct file *file,
+static int vfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static struct fb_ops vfb_ops = {
@@ -368,7 +368,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
* Most drivers don't need their own mmap function
*/
-static int vfb_mmap(struct fb_info *info, struct file *file,
+static int vfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
return -EINVAL;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 226ae8a88482..f3f16fd9f231 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -705,15 +705,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int vga16fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- if (var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
- return -EINVAL;
-
vga16fb_pan_var(info, var);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index d9e01daee630..15179ec62339 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -356,10 +356,11 @@ int save_vga(struct vgastate *state)
{
struct regstate *saved;
- saved = kmalloc(sizeof(struct regstate), GFP_KERNEL);
+ saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
+
if (saved == NULL)
return 1;
- memset (saved, 0, sizeof(struct regstate));
+
state->vidstate = (void *)saved;
if (state->flags & VGA_SAVE_CMAP) {
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 9a1e00dd3e02..4baf61a22327 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -3,7 +3,7 @@ menu "Dallas's 1-wire bus"
config W1
tristate "Dallas's 1-wire support"
---help---
- Dallas's 1-wire bus is usefull to connect slow 1-pin devices
+ Dallas's 1-wire bus is useful to connect slow 1-pin devices
such as iButtons and thermal sensors.
If you want W1 support, you should say Y here.
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 1a409c2c320c..7aa2d3de6d37 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -45,7 +45,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
}
static ssize_t
-proc_bus_zorro_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
struct inode *ino = file->f_dentry->d_inode;
struct proc_dir_entry *dp = PDE(ino);
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index ccba227676f2..fcbee748c592 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &zorro_bus_type;
- drv->driver.probe = zorro_device_probe;
/* register with core */
count = driver_register(&drv->driver);
@@ -132,7 +131,8 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv)
struct bus_type zorro_bus_type = {
.name = "zorro",
- .match = zorro_bus_match
+ .match = zorro_bus_match,
+ .probe = zorro_device_probe,
};