aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acorn/block/mfmhd.c36
-rw-r--r--drivers/acorn/char/i2c.c1
-rw-r--r--drivers/acorn/char/pcf8583.c5
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/osl.c2
-rw-r--r--drivers/acpi/pci_irq.c7
-rw-r--r--drivers/acpi/processor_idle.c15
-rw-r--r--drivers/acpi/scan.c27
-rw-r--r--drivers/acpi/tables.c4
-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/firmware_class.c1
-rw-r--r--drivers/base/memory.c9
-rw-r--r--drivers/block/DAC960.c41
-rw-r--r--drivers/block/Kconfig2
-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.c42
-rw-r--r--drivers/block/floppy.c46
-rw-r--r--drivers/block/loop.c54
-rw-r--r--drivers/block/nbd.c125
-rw-r--r--drivers/block/paride/Kconfig5
-rw-r--r--drivers/block/paride/pd.c34
-rw-r--r--drivers/block/paride/pf.c50
-rw-r--r--drivers/block/pktcdvd.c12
-rw-r--r--drivers/block/ps2esdi.c25
-rw-r--r--drivers/block/rd.c4
-rw-r--r--drivers/block/swim3.c38
-rw-r--r--drivers/block/sx8.c51
-rw-r--r--drivers/block/ub.c2
-rw-r--r--drivers/block/umem.c43
-rw-r--r--drivers/block/viodasd.c78
-rw-r--r--drivers/block/xd.c31
-rw-r--r--drivers/bluetooth/hci_ldisc.c16
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/cdrom/cdu31a.c2
-rw-r--r--drivers/cdrom/cm206.c2
-rw-r--r--drivers/cdrom/viocd.c6
-rw-r--r--drivers/char/Kconfig31
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/sworks-agp.c1
-rw-r--r--drivers/char/amiserial.c55
-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.c42
-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.c67
-rw-r--r--drivers/char/hangcheck-timer.c2
-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.c71
-rw-r--r--drivers/char/ip2/i2lib.c2
-rw-r--r--drivers/char/ip2main.c26
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c6
-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/mmtimer.c90
-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.h9
-rw-r--r--drivers/char/rio/chan.h2
-rw-r--r--drivers/char/rio/cirrus.h178
-rw-r--r--drivers/char/rio/cmd.h5
-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/debug.h4
-rw-r--r--drivers/char/rio/defaults.h7
-rw-r--r--drivers/char/rio/eisa.h4
-rw-r--r--drivers/char/rio/enable.h4
-rw-r--r--drivers/char/rio/error.h3
-rw-r--r--drivers/char/rio/errors.h2
-rw-r--r--drivers/char/rio/formpkt.h151
-rw-r--r--drivers/char/rio/func.h51
-rw-r--r--drivers/char/rio/host.h93
-rw-r--r--drivers/char/rio/hosthw.h4
-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.h5
-rw-r--r--drivers/char/rio/ltt.h7
-rw-r--r--drivers/char/rio/lttwake.h5
-rw-r--r--drivers/char/rio/map.h27
-rw-r--r--drivers/char/rio/mca.h2
-rw-r--r--drivers/char/rio/mesg.h2
-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.h27
-rw-r--r--drivers/char/rio/port.h294
-rw-r--r--drivers/char/rio/proto.h132
-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.c1522
-rw-r--r--drivers/char/rio/rio_linux.h57
-rw-r--r--drivers/char/rio/rioboard.h204
-rw-r--r--drivers/char/rio/riocmd.c896
-rw-r--r--drivers/char/rio/rioctrl.c3119
-rw-r--r--drivers/char/rio/riodrvr.h128
-rw-r--r--drivers/char/rio/rioinfo.h30
-rw-r--r--drivers/char/rio/riointr.c1510
-rw-r--r--drivers/char/rio/rioioctl.h18
-rw-r--r--drivers/char/rio/rioparam.c563
-rw-r--r--drivers/char/rio/riopcicopy.c6
-rw-r--r--drivers/char/rio/rioroute.c1572
-rw-r--r--drivers/char/rio/riospace.h31
-rw-r--r--drivers/char/rio/riotable.c1019
-rw-r--r--drivers/char/rio/riotime.h4
-rw-r--r--drivers/char/rio/riotty.c1224
-rw-r--r--drivers/char/rio/riotypes.h71
-rw-r--r--drivers/char/rio/riowinif.h934
-rw-r--r--drivers/char/rio/riscos.h2
-rw-r--r--drivers/char/rio/rom.h22
-rw-r--r--drivers/char/rio/route.h61
-rw-r--r--drivers/char/rio/rtahw.h14
-rw-r--r--drivers/char/rio/rup.h39
-rw-r--r--drivers/char/rio/rupstat.h3
-rw-r--r--drivers/char/rio/sam.h13
-rw-r--r--drivers/char/rio/selftest.h48
-rw-r--r--drivers/char/rio/space.h2
-rw-r--r--drivers/char/rio/sysmap.h23
-rw-r--r--drivers/char/rio/timeouts.h7
-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.c47
-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.c37
-rw-r--r--drivers/char/sonypi.c381
-rw-r--r--drivers/char/specialix.c38
-rw-r--r--drivers/char/stallion.c65
-rw-r--r--drivers/char/sx.c19
-rw-r--r--drivers/char/synclink.c51
-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.c15
-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/Kconfig2
-rw-r--r--drivers/char/watchdog/cpu5wdt.c9
-rw-r--r--drivers/char/watchdog/mpc8xx_wdt.c20
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c4
-rw-r--r--drivers/char/watchdog/wdt977.c216
-rw-r--r--drivers/connector/cn_proc.c15
-rw-r--r--drivers/crypto/padlock-aes.c26
-rw-r--r--drivers/crypto/padlock.h2
-rw-r--r--drivers/firmware/efivars.c2
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/adm1021.c6
-rw-r--r--drivers/hwmon/adm1025.c10
-rw-r--r--drivers/hwmon/adm1026.c10
-rw-r--r--drivers/hwmon/adm1031.c6
-rw-r--r--drivers/hwmon/adm9240.c6
-rw-r--r--drivers/hwmon/asb100.c6
-rw-r--r--drivers/hwmon/atxp1.c6
-rw-r--r--drivers/hwmon/ds1621.c6
-rw-r--r--drivers/hwmon/fscher.c6
-rw-r--r--drivers/hwmon/fscpos.c6
-rw-r--r--drivers/hwmon/gl518sm.c6
-rw-r--r--drivers/hwmon/gl520sm.c6
-rw-r--r--drivers/hwmon/hwmon-vid.c69
-rw-r--r--drivers/hwmon/it87.c18
-rw-r--r--drivers/hwmon/lm63.c6
-rw-r--r--drivers/hwmon/lm75.c6
-rw-r--r--drivers/hwmon/lm77.c6
-rw-r--r--drivers/hwmon/lm78.c13
-rw-r--r--drivers/hwmon/lm80.c6
-rw-r--r--drivers/hwmon/lm83.c6
-rw-r--r--drivers/hwmon/lm85.c50
-rw-r--r--drivers/hwmon/lm87.c6
-rw-r--r--drivers/hwmon/lm90.c6
-rw-r--r--drivers/hwmon/lm92.c6
-rw-r--r--drivers/hwmon/max1619.c6
-rw-r--r--drivers/hwmon/pc87360.c7
-rw-r--r--drivers/hwmon/sis5595.c8
-rw-r--r--drivers/hwmon/smsc47b397.c8
-rw-r--r--drivers/hwmon/smsc47m1.c7
-rw-r--r--drivers/hwmon/via686a.c8
-rw-r--r--drivers/hwmon/vt8231.c862
-rw-r--r--drivers/hwmon/w83627ehf.c7
-rw-r--r--drivers/hwmon/w83627hf.c23
-rw-r--r--drivers/hwmon/w83781d.c13
-rw-r--r--drivers/hwmon/w83792d.c83
-rw-r--r--drivers/hwmon/w83l785ts.c6
-rw-r--r--drivers/i2c/busses/Kconfig24
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-i801.c6
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c1
-rw-r--r--drivers/i2c/busses/i2c-isa.c10
-rw-r--r--drivers/i2c/busses/i2c-keywest.c751
-rw-r--r--drivers/i2c/busses/i2c-keywest.h108
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c33
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c2
-rw-r--r--drivers/i2c/busses/i2c-parport.h12
-rw-r--r--drivers/i2c/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/ds1337.c43
-rw-r--r--drivers/i2c/chips/ds1374.c6
-rw-r--r--drivers/i2c/chips/eeprom.c6
-rw-r--r--drivers/i2c/chips/isp1301_omap.c6
-rw-r--r--drivers/i2c/chips/m41t00.c6
-rw-r--r--drivers/i2c/chips/max6875.c6
-rw-r--r--drivers/i2c/chips/pca9539.c6
-rw-r--r--drivers/i2c/chips/pcf8574.c6
-rw-r--r--drivers/i2c/chips/pcf8591.c6
-rw-r--r--drivers/i2c/chips/rtc8564.c43
-rw-r--r--drivers/i2c/chips/tps65010.c17
-rw-r--r--drivers/i2c/chips/x1205.c6
-rw-r--r--drivers/i2c/i2c-core.c70
-rw-r--r--drivers/i2c/i2c-dev.c63
-rw-r--r--drivers/ide/ide-cd.c16
-rw-r--r--drivers/ide/ide-disk.c149
-rw-r--r--drivers/ide/ide-floppy.c12
-rw-r--r--drivers/ide/ide-io.c20
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide.c21
-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/Kconfig23
-rw-r--r--drivers/ieee1394/Makefile2
-rw-r--r--drivers/ieee1394/amdtp.c1
-rw-r--r--drivers/ieee1394/csr1212.c21
-rw-r--r--drivers/ieee1394/csr1212.h2
-rw-r--r--drivers/ieee1394/dma.c73
-rw-r--r--drivers/ieee1394/dv1394.c14
-rw-r--r--drivers/ieee1394/eth1394.c20
-rw-r--r--drivers/ieee1394/highlevel.c18
-rw-r--r--drivers/ieee1394/hosts.c30
-rw-r--r--drivers/ieee1394/hosts.h162
-rw-r--r--drivers/ieee1394/ieee1394-ioctl.h8
-rw-r--r--drivers/ieee1394/ieee1394.h19
-rw-r--r--drivers/ieee1394/ieee1394_core.c827
-rw-r--r--drivers/ieee1394/ieee1394_core.h100
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c389
-rw-r--r--drivers/ieee1394/iso.c102
-rw-r--r--drivers/ieee1394/nodemgr.c50
-rw-r--r--drivers/ieee1394/nodemgr.h18
-rw-r--r--drivers/ieee1394/ohci1394.c43
-rw-r--r--drivers/ieee1394/ohci1394.h4
-rw-r--r--drivers/ieee1394/pcilynx.c2
-rw-r--r--drivers/ieee1394/raw1394.c79
-rw-r--r--drivers/ieee1394/sbp2.c1040
-rw-r--r--drivers/ieee1394/sbp2.h70
-rw-r--r--drivers/ieee1394/video1394.c107
-rw-r--r--drivers/infiniband/core/cm.c45
-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.c8
-rw-r--r--drivers/input/joystick/amijoy.c4
-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/mouse/amimouse.c6
-rw-r--r--drivers/input/serio/ambakmi.c15
-rw-r--r--drivers/input/serio/sa1111ps2.c1
-rw-r--r--drivers/input/serio/serport.c13
-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/hisax.h18
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.h18
-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.c254
-rw-r--r--drivers/macintosh/mediabay.c8
-rw-r--r--drivers/macintosh/smu.c50
-rw-r--r--drivers/macintosh/therm_adt746x.c45
-rw-r--r--drivers/macintosh/therm_pm72.c17
-rw-r--r--drivers/macintosh/therm_windtunnel.c6
-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.c63
-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.c114
-rw-r--r--drivers/md/dm-crypt.c5
-rw-r--r--drivers/md/dm-io.h3
-rw-r--r--drivers/md/dm-ioctl.c21
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-raid1.c13
-rw-r--r--drivers/md/dm-snap.c25
-rw-r--r--drivers/md/dm.c96
-rw-r--r--drivers/md/dm.h5
-rw-r--r--drivers/md/faulty.c9
-rw-r--r--drivers/md/kcopyd.c3
-rw-r--r--drivers/md/linear.c14
-rw-r--r--drivers/md/md.c926
-rw-r--r--drivers/md/multipath.c29
-rw-r--r--drivers/md/raid0.c32
-rw-r--r--drivers/md/raid1.c726
-rw-r--r--drivers/md/raid10.c544
-rw-r--r--drivers/md/raid5.c174
-rw-r--r--drivers/md/raid6main.c348
-rw-r--r--drivers/media/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/dst.c52
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c3
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c19
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig20
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c84
-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.c22
-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.c442
-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.c32
-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.c137
-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.c7
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h3
-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.h3
-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/Makefile10
-rw-r--r--drivers/media/video/adv7170.c13
-rw-r--r--drivers/media/video/adv7175.c13
-rw-r--r--drivers/media/video/arv.c1
-rw-r--r--drivers/media/video/bt819.c14
-rw-r--r--drivers/media/video/bt832.c78
-rw-r--r--drivers/media/video/bt856.c13
-rw-r--r--drivers/media/video/bttv-cards.c359
-rw-r--r--drivers/media/video/bttv-driver.c68
-rw-r--r--drivers/media/video/bttv-gpio.c21
-rw-r--r--drivers/media/video/bttv-i2c.c17
-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.h38
-rw-r--r--drivers/media/video/bttvp.h13
-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.c33
-rw-r--r--drivers/media/video/cpia_usb.c4
-rw-r--r--drivers/media/video/cs53l32a.c101
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c91
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c396
-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.h80
-rw-r--r--drivers/media/video/cx88/Kconfig25
-rw-r--r--drivers/media/video/cx88/Makefile4
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c848
-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.c70
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c218
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c15
-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.c10
-rw-r--r--drivers/media/video/cx88/cx88-video.c100
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c173
-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.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c170
-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.c13
-rw-r--r--drivers/media/video/ir-kbd-i2c.c21
-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.h102
-rw-r--r--drivers/media/video/mt20xx.c10
-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.c9
-rw-r--r--drivers/media/video/pms.c1
-rw-r--r--drivers/media/video/saa5246a.c16
-rw-r--r--drivers/media/video/saa5249.c19
-rw-r--r--drivers/media/video/saa6588.c17
-rw-r--r--drivers/media/video/saa7110.c13
-rw-r--r--drivers/media/video/saa7111.c13
-rw-r--r--drivers/media/video/saa7114.c13
-rw-r--r--drivers/media/video/saa7115.c331
-rw-r--r--drivers/media/video/saa711x.c15
-rw-r--r--drivers/media/video/saa7127.c93
-rw-r--r--drivers/media/video/saa7134/Kconfig2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c85
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c141
-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.c7
-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-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.c13
-rw-r--r--drivers/media/video/saa7191.c13
-rw-r--r--drivers/media/video/stradis.c1137
-rw-r--r--drivers/media/video/tda7432.c50
-rw-r--r--drivers/media/video/tda8290.c6
-rw-r--r--drivers/media/video/tda9840.c8
-rw-r--r--drivers/media/video/tda9875.c14
-rw-r--r--drivers/media/video/tda9887.c234
-rw-r--r--drivers/media/video/tea5767.c5
-rw-r--r--drivers/media/video/tea6415c.c8
-rw-r--r--drivers/media/video/tea6420.c11
-rw-r--r--drivers/media/video/tuner-3036.c9
-rw-r--r--drivers/media/video/tuner-core.c146
-rw-r--r--drivers/media/video/tuner-simple.c889
-rw-r--r--drivers/media/video/tvaudio.c185
-rw-r--r--drivers/media/video/tveeprom.c56
-rw-r--r--drivers/media/video/tvmixer.c26
-rw-r--r--drivers/media/video/tvp5150.c545
-rw-r--r--drivers/media/video/v4l1-compat.c35
-rw-r--r--drivers/media/video/v4l2-common.c219
-rw-r--r--drivers/media/video/video-buf.c9
-rw-r--r--drivers/media/video/videocodec.c11
-rw-r--r--drivers/media/video/videodev.c15
-rw-r--r--drivers/media/video/vino.c4
-rw-r--r--drivers/media/video/vpx3220.c14
-rw-r--r--drivers/media/video/w9966.c1
-rw-r--r--drivers/media/video/wm8775.c98
-rw-r--r--drivers/media/video/zoran_card.c3
-rw-r--r--drivers/media/video/zoran_driver.c18
-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/mptctl.c2
-rw-r--r--drivers/message/i2o/Kconfig12
-rw-r--r--drivers/message/i2o/README.ioctl2
-rw-r--r--drivers/message/i2o/bus-osm.c23
-rw-r--r--drivers/message/i2o/config-osm.c2
-rw-r--r--drivers/message/i2o/core.h20
-rw-r--r--drivers/message/i2o/device.c339
-rw-r--r--drivers/message/i2o/driver.c12
-rw-r--r--drivers/message/i2o/exec-osm.c114
-rw-r--r--drivers/message/i2o/i2o_block.c208
-rw-r--r--drivers/message/i2o/i2o_config.c196
-rw-r--r--drivers/message/i2o/i2o_lan.h38
-rw-r--r--drivers/message/i2o/i2o_proc.c2
-rw-r--r--drivers/message/i2o/i2o_scsi.c89
-rw-r--r--drivers/message/i2o/iop.c356
-rw-r--r--drivers/message/i2o/pci.c7
-rw-r--r--drivers/mfd/ucb1x00-core.c32
-rw-r--r--drivers/mfd/ucb1x00-ts.c1
-rw-r--r--drivers/mmc/mmc.c11
-rw-r--r--drivers/mmc/mmc_block.c223
-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/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/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/Kconfig23
-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/bonding/bond_alb.c4
-rw-r--r--drivers/net/bonding/bonding.h12
-rw-r--r--drivers/net/cs89x0.c140
-rw-r--r--drivers/net/cs89x0.h19
-rw-r--r--drivers/net/e100.c32
-rw-r--r--drivers/net/e1000/e1000_param.c10
-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.c2
-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/Kconfig2
-rw-r--r--drivers/net/phy/mdio_bus.c2
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/plip.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/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/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/sun3lance.c2
-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/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/Kconfig2
-rw-r--r--drivers/net/wireless/atmel.c227
-rw-r--r--drivers/net/wireless/ipw2100.c5
-rw-r--r--drivers/net/wireless/strip.c10
-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/Kconfig5
-rw-r--r--drivers/parport/daisy.c51
-rw-r--r--drivers/parport/ieee1284_ops.c62
-rw-r--r--drivers/parport/parport_pc.c36
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/parport/probe.c199
-rw-r--r--drivers/parport/share.c1
-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.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.c26
-rw-r--r--drivers/pci/remove.c3
-rw-r--r--drivers/pcmcia/ds.c37
-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/pnpbios/bioscalls.c45
-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/Makefile2
-rw-r--r--drivers/s390/block/Kconfig8
-rw-r--r--drivers/s390/block/dasd.c58
-rw-r--r--drivers/s390/block/dasd_diag.c11
-rw-r--r--drivers/s390/block/dasd_diag.h31
-rw-r--r--drivers/s390/block/dasd_eckd.c9
-rw-r--r--drivers/s390/block/dasd_fba.c6
-rw-r--r--drivers/s390/block/dasd_int.h4
-rw-r--r--drivers/s390/block/dasd_ioctl.c45
-rw-r--r--drivers/s390/block/dcssblk.c2
-rw-r--r--drivers/s390/block/xpram.c22
-rw-r--r--drivers/s390/char/con3215.c25
-rw-r--r--drivers/s390/char/fs3270.c20
-rw-r--r--drivers/s390/char/sclp_cpi.c2
-rw-r--r--drivers/s390/char/sclp_quiesce.c2
-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_block.c4
-rw-r--r--drivers/s390/char/tape_char.c20
-rw-r--r--drivers/s390/char/vmwatchdog.c2
-rw-r--r--drivers/s390/cio/blacklist.c234
-rw-r--r--drivers/s390/cio/blacklist.h2
-rw-r--r--drivers/s390/cio/ccwgroup.c6
-rw-r--r--drivers/s390/cio/chsc.c473
-rw-r--r--drivers/s390/cio/chsc.h13
-rw-r--r--drivers/s390/cio/cio.c168
-rw-r--r--drivers/s390/cio/cio.h11
-rw-r--r--drivers/s390/cio/cmf.c8
-rw-r--r--drivers/s390/cio/css.c297
-rw-r--r--drivers/s390/cio/css.h43
-rw-r--r--drivers/s390/cio/device.c47
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c29
-rw-r--r--drivers/s390/cio/device_id.c26
-rw-r--r--drivers/s390/cio/device_ops.c4
-rw-r--r--drivers/s390/cio/device_pgid.c56
-rw-r--r--drivers/s390/cio/device_status.c14
-rw-r--r--drivers/s390/cio/ioasm.h86
-rw-r--r--drivers/s390/cio/qdio.c713
-rw-r--r--drivers/s390/cio/qdio.h144
-rw-r--r--drivers/s390/cio/schid.h26
-rw-r--r--drivers/s390/crypto/z90common.h9
-rw-r--r--drivers/s390/crypto/z90crypt.h13
-rw-r--r--drivers/s390/crypto/z90hardware.c309
-rw-r--r--drivers/s390/crypto/z90main.c112
-rw-r--r--drivers/s390/net/Kconfig2
-rw-r--r--drivers/s390/net/claw.c6
-rw-r--r--drivers/s390/net/ctctty.c28
-rw-r--r--drivers/s390/net/cu3088.c3
-rw-r--r--drivers/s390/net/iucv.c10
-rw-r--r--drivers/s390/net/qeth_main.c21
-rw-r--r--drivers/s390/s390_rdev.c53
-rw-r--r--drivers/s390/s390mach.c66
-rw-r--r--drivers/s390/sysinfo.c2
-rw-r--r--drivers/scsi/Kconfig10
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/NCR53C9x.c5
-rw-r--r--drivers/scsi/aacraid/linit.c1
-rw-r--r--drivers/scsi/ahci.c1
-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.c5
-rw-r--r--drivers/scsi/blz1230.c4
-rw-r--r--drivers/scsi/blz2060.c4
-rw-r--r--drivers/scsi/ch.c1
-rw-r--r--drivers/scsi/cyberstorm.c4
-rw-r--r--drivers/scsi/cyberstormII.c4
-rw-r--r--drivers/scsi/fastlane.c4
-rw-r--r--drivers/scsi/hosts.c9
-rw-r--r--drivers/scsi/ide-scsi.c4
-rw-r--r--drivers/scsi/libata-core.c145
-rw-r--r--drivers/scsi/libata-scsi.c48
-rw-r--r--drivers/scsi/libata.h4
-rw-r--r--drivers/scsi/mac53c94.c22
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.h1
-rw-r--r--drivers/scsi/mesh.c3
-rw-r--r--drivers/scsi/oktagon_esp.c2
-rw-r--r--drivers/scsi/sata_mv.c1
-rw-r--r--drivers/scsi/sata_nv.c31
-rw-r--r--drivers/scsi/sata_promise.c1
-rw-r--r--drivers/scsi/sata_sil.c1
-rw-r--r--drivers/scsi/sata_sil24.c1
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c1
-rw-r--r--drivers/scsi/sata_sx4.c1
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c1
-rw-r--r--drivers/scsi/scsi.c109
-rw-r--r--drivers/scsi/scsi_lib.c86
-rw-r--r--drivers/scsi/scsi_priv.h1
-rw-r--r--drivers/scsi/scsi_sysfs.c31
-rw-r--r--drivers/scsi/sd.c106
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/wd33c93.c4
-rw-r--r--drivers/serial/21285.c9
-rw-r--r--drivers/serial/68328serial.c18
-rw-r--r--drivers/serial/68360serial.c54
-rw-r--r--drivers/serial/8250.c112
-rw-r--r--drivers/serial/8250.h6
-rw-r--r--drivers/serial/8250_pci.c124
-rw-r--r--drivers/serial/Kconfig69
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/amba-pl010.c13
-rw-r--r--drivers/serial/amba-pl011.c22
-rw-r--r--drivers/serial/at91_serial.c894
-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.c3
-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.c74
-rw-r--r--drivers/serial/mpsc.c6
-rw-r--r--drivers/serial/mux.c9
-rw-r--r--drivers/serial/pmac_zilog.c77
-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.c18
-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.c6
-rw-r--r--drivers/serial/sunsab.c38
-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/usb/atm/speedtch.c4
-rw-r--r--drivers/usb/class/cdc-acm.c11
-rw-r--r--drivers/usb/core/inode.c34
-rw-r--r--drivers/usb/gadget/file_storage.c4
-rw-r--r--drivers/usb/gadget/inode.c4
-rw-r--r--drivers/usb/gadget/serial.c19
-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/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.c5
-rw-r--r--drivers/usb/serial/Kconfig2
-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.c8
-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/Kconfig12
-rw-r--r--drivers/video/amba-clcd.c16
-rw-r--r--drivers/video/amifb.c36
-rw-r--r--drivers/video/arcfb.c8
-rw-r--r--drivers/video/asiliantfb.c2
-rw-r--r--drivers/video/aty/Makefile1
-rw-r--r--drivers/video/aty/atyfb.h2
-rw-r--r--drivers/video/aty/atyfb_base.c247
-rw-r--r--drivers/video/aty/mach64_ct.c17
-rw-r--r--drivers/video/aty/radeon_monitor.c2
-rw-r--r--drivers/video/aty/xlinit.c359
-rw-r--r--drivers/video/backlight/corgi_bl.c1
-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.c114
-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.c37
-rw-r--r--drivers/video/fbmon.c129
-rw-r--r--drivers/video/fbsysfs.c81
-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/imsttfb.c56
-rw-r--r--drivers/video/imxfb.c6
-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.c32
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/macfb.c15
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/matrox/matroxfb_g450.c2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c11
-rw-r--r--drivers/video/matrox/matroxfb_misc.c8
-rw-r--r--drivers/video/neofb.c36
-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/platinumfb.c98
-rw-r--r--drivers/video/platinumfb.h4
-rw-r--r--drivers/video/pm2fb.c21
-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.c15
-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/skeletonfb.c482
-rw-r--r--drivers/video/sstfb.c60
-rw-r--r--drivers/video/stifb.c65
-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/vga16fb.c8
-rw-r--r--drivers/video/vgastate.c5
-rw-r--r--drivers/w1/Kconfig2
-rw-r--r--drivers/zorro/proc.c2
1107 files changed, 47281 insertions, 33163 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index ea410b6b764..7fc3f0f08b2 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.
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 4b65f74d66b..ce074f6f336 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 c22bb9dca1e..c26c08b3682 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/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index e26f007a141..9b49f316ae9 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -257,9 +257,10 @@ pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver pcf8583_driver = {
- .name = "PCF8583",
+ .driver = {
+ .name = "PCF8583",
+ },
.id = I2C_DRIVERID_PCF8583,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = pcf8583_probe,
.detach_client = pcf8583_detach,
.command = pcf8583_command
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index fce21c25752..6d61945260a 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
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e3cd0b16031..20c9a37643c 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
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 09567c2edcf..e567c03b238 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_idle.c b/drivers/acpi/processor_idle.c
index 807b0df308f..cc049338e41 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -843,6 +843,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 +866,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;
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 0745d20afb8..3b26a710436 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/tables.c b/drivers/acpi/tables.c
index a2bf25b05e1..31d4f3ffc26 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/amba/Makefile b/drivers/amba/Makefile
new file mode 100644
index 00000000000..40fe74097be
--- /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 00000000000..889855d8d9f
--- /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 c57e20dcb0f..074abc81ec3 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 55959e4d1cb..f484747f255 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 fd8059920db..6b355bd7816 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 281d26784d2..07a7f97e1de 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/firmware_class.c b/drivers/base/firmware_class.c
index 5b3d5e9ddcb..3d384e3d34d 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>
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 7e1d077874d..d1a05224627 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>
@@ -49,12 +49,12 @@ static struct kset_uevent_ops memory_uevent_ops = {
static struct notifier_block *memory_chain;
-static int register_memory_notifier(struct notifier_block *nb)
+int register_memory_notifier(struct notifier_block *nb)
{
return notifier_chain_register(&memory_chain, nb);
}
-static void unregister_memory_notifier(struct notifier_block *nb)
+void unregister_memory_notifier(struct notifier_block *nb)
{
notifier_chain_unregister(&memory_chain, nb);
}
@@ -62,8 +62,7 @@ static void unregister_memory_notifier(struct notifier_block *nb)
/*
* register_memory - Setup a sysfs device for a memory block
*/
-static int
-register_memory(struct memory_block *memory, struct mem_section *section,
+int register_memory(struct memory_block *memory, struct mem_section *section,
struct node *root)
{
int error;
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 70eaa5c7ac0..6ede1f352c2 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,
};
@@ -3471,7 +3464,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
- end_that_request_last(Request);
+ end_that_request_last(Request, UpToDate);
if (Command->Completion) {
complete(Command->Completion);
@@ -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/Kconfig b/drivers/block/Kconfig
index c4b9d2adfc0..139cbba7618 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -117,7 +117,7 @@ config BLK_DEV_XD
config PARIDE
tristate "Parallel port IDE device support"
- depends on PARPORT
+ depends on PARPORT_PC
---help---
There are many external CD-ROM and disk devices that connect through
your computer's parallel port. Most of them are actually IDE devices
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 5d2d649f7e8..196c0ec9cd5 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 0acbfff8ad2..b6e29095621 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 0e97fcb9f3a..c05ee8bffd9 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 22bda05fc69..f8ce235ccfc 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 c3441b3f086..12d7b9bdfa9 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);
- 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 3b0858c8389..b24fc0553cc 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 2942d32280a..9e35de05d5c 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 cf1822a6361..862b9abac0a 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,
};
@@ -1036,7 +1038,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
complete_buffers(cmd->rq->bio, ok);
DBGPX(printk("Done with %p\n", cmd->rq););
- end_that_request_last(cmd->rq);
+ end_that_request_last(cmd->rq, ok ? 1 : -EIO);
}
/*
@@ -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 f7e765a1d31..374621a512e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -479,7 +479,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. */
@@ -2301,7 +2300,7 @@ static void floppy_end_request(struct request *req, int uptodate)
add_disk_randomness(req->rq_disk);
floppy_off((long)req->rq_disk->private_data);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
/* We're done with the request */
current_req = NULL;
@@ -3445,6 +3444,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 +3490,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 +3644,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 +3937,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 +3960,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 +4218,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 +4570,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 96c664af8d0..864729046e2 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -213,9 +213,9 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
struct address_space_operations *aops = mapping->a_ops;
pgoff_t index;
unsigned offset, bv_offs;
- int len, ret = 0;
+ int len, ret;
- down(&mapping->host->i_sem);
+ mutex_lock(&mapping->host->i_mutex);
index = pos >> PAGE_CACHE_SHIFT;
offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
bv_offs = bvec->bv_offset;
@@ -232,9 +232,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
page = grab_cache_page(mapping, index);
if (unlikely(!page))
goto fail;
- if (unlikely(aops->prepare_write(file, page, offset,
- offset + size)))
+ ret = aops->prepare_write(file, page, offset,
+ offset + size);
+ if (unlikely(ret)) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
goto unlock;
+ }
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
bvec->bv_page, bv_offs, size, IV);
if (unlikely(transfer_result)) {
@@ -251,9 +257,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
kunmap_atomic(kaddr, KM_USER0);
}
flush_dcache_page(page);
- if (unlikely(aops->commit_write(file, page, offset,
- offset + size)))
+ ret = aops->commit_write(file, page, offset,
+ offset + size);
+ if (unlikely(ret)) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
goto unlock;
+ }
if (unlikely(transfer_result))
goto unlock;
bv_offs += size;
@@ -264,8 +276,9 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
unlock_page(page);
page_cache_release(page);
}
+ ret = 0;
out:
- up(&mapping->host->i_sem);
+ mutex_unlock(&mapping->host->i_mutex);
return ret;
unlock:
unlock_page(page);
@@ -514,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;
@@ -580,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);
@@ -619,7 +629,7 @@ static int loop_thread(void *data)
break;
}
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
return 0;
}
@@ -830,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:
@@ -896,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;
@@ -1276,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 9e268ddedfb..6997d8e6bfb 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -54,11 +54,15 @@
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
#include <net/sock.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
+#include <asm/system.h>
#include <asm/types.h>
#include <linux/nbd.h>
@@ -136,7 +140,7 @@ static void nbd_end_request(struct request *req)
spin_lock_irqsave(q->queue_lock, flags);
if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
spin_unlock_irqrestore(q->queue_lock, flags);
}
@@ -170,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)
@@ -230,14 +233,6 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
request.len = htonl(size);
memcpy(request.handle, &req, sizeof(req));
- down(&lo->tx_lock);
-
- if (!sock || !lo->sock) {
- printk(KERN_ERR "%s: Attempted send on closed socket\n",
- lo->disk->disk_name);
- goto error_out;
- }
-
dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
lo->disk->disk_name, req,
nbdcmd_to_ascii(nbd_cmd(req)),
@@ -276,11 +271,9 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
}
}
}
- up(&lo->tx_lock);
return 0;
error_out:
- up(&lo->tx_lock);
return 1;
}
@@ -289,9 +282,14 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
struct request *req;
struct list_head *tmp;
struct request *xreq;
+ int err;
memcpy(&xreq, handle, sizeof(xreq));
+ err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
+ if (unlikely(err))
+ goto out;
+
spin_lock(&lo->queue_lock);
list_for_each(tmp, &lo->queue_head) {
req = list_entry(tmp, struct request, queuelist);
@@ -302,7 +300,11 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
return req;
}
spin_unlock(&lo->queue_lock);
- return NULL;
+
+ err = -ENOENT;
+
+out:
+ return ERR_PTR(err);
}
static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
@@ -331,7 +333,11 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
goto harderror;
}
req = nbd_find_request(lo, reply.handle);
- if (req == NULL) {
+ if (unlikely(IS_ERR(req))) {
+ result = PTR_ERR(req);
+ if (result != -ENOENT)
+ goto harderror;
+
printk(KERN_ERR "%s: Unexpected reply (%p)\n",
lo->disk->disk_name, reply.handle);
result = -EBADR;
@@ -395,19 +401,24 @@ static void nbd_clear_que(struct nbd_device *lo)
BUG_ON(lo->magic != LO_MAGIC);
- do {
- req = NULL;
- spin_lock(&lo->queue_lock);
- if (!list_empty(&lo->queue_head)) {
- req = list_entry(lo->queue_head.next, struct request, queuelist);
- list_del_init(&req->queuelist);
- }
- spin_unlock(&lo->queue_lock);
- if (req) {
- req->errors++;
- nbd_end_request(req);
- }
- } while (req);
+ /*
+ * Because we have set lo->sock to NULL under the tx_lock, all
+ * modifications to the list must have completed by now. For
+ * the same reason, the active_req must be NULL.
+ *
+ * As a consequence, we don't need to take the spin lock while
+ * purging the list here.
+ */
+ BUG_ON(lo->sock);
+ BUG_ON(lo->active_req);
+
+ while (!list_empty(&lo->queue_head)) {
+ req = list_entry(lo->queue_head.next, struct request,
+ queuelist);
+ list_del_init(&req->queuelist);
+ req->errors++;
+ nbd_end_request(req);
+ }
}
/*
@@ -435,11 +446,6 @@ static void do_nbd_request(request_queue_t * q)
BUG_ON(lo->magic != LO_MAGIC);
- if (!lo->file) {
- printk(KERN_ERR "%s: Request when not-ready\n",
- lo->disk->disk_name);
- goto error_out;
- }
nbd_cmd(req) = NBD_CMD_READ;
if (rq_data_dir(req) == WRITE) {
nbd_cmd(req) = NBD_CMD_WRITE;
@@ -453,32 +459,34 @@ static void do_nbd_request(request_queue_t * q)
req->errors = 0;
spin_unlock_irq(q->queue_lock);
- spin_lock(&lo->queue_lock);
-
- if (!lo->file) {
- spin_unlock(&lo->queue_lock);
- printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n",
- lo->disk->disk_name);
+ down(&lo->tx_lock);
+ if (unlikely(!lo->sock)) {
+ up(&lo->tx_lock);
+ printk(KERN_ERR "%s: Attempted send on closed socket\n",
+ lo->disk->disk_name);
req->errors++;
nbd_end_request(req);
spin_lock_irq(q->queue_lock);
continue;
}
- list_add(&req->queuelist, &lo->queue_head);
- spin_unlock(&lo->queue_lock);
+ lo->active_req = req;
if (nbd_send_req(lo, req) != 0) {
printk(KERN_ERR "%s: Request send failed\n",
lo->disk->disk_name);
- if (nbd_find_request(lo, (char *)&req) != NULL) {
- /* we still own req */
- req->errors++;
- nbd_end_request(req);
- } else /* we're racing with nbd_clear_que */
- printk(KERN_DEBUG "nbd: can't find req\n");
+ req->errors++;
+ nbd_end_request(req);
+ } else {
+ spin_lock(&lo->queue_lock);
+ list_add(&req->queuelist, &lo->queue_head);
+ spin_unlock(&lo->queue_lock);
}
+ lo->active_req = NULL;
+ up(&lo->tx_lock);
+ wake_up_all(&lo->active_wq);
+
spin_lock_irq(q->queue_lock);
continue;
@@ -529,17 +537,10 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
down(&lo->tx_lock);
lo->sock = NULL;
up(&lo->tx_lock);
- spin_lock(&lo->queue_lock);
file = lo->file;
lo->file = NULL;
- spin_unlock(&lo->queue_lock);
nbd_clear_que(lo);
- spin_lock(&lo->queue_lock);
- if (!list_empty(&lo->queue_head)) {
- printk(KERN_ERR "nbd: disconnect: some requests are in progress -> please try again.\n");
- error = -EBUSY;
- }
- spin_unlock(&lo->queue_lock);
+ BUG_ON(!list_empty(&lo->queue_head));
if (file)
fput(file);
return error;
@@ -598,24 +599,19 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
lo->sock = NULL;
}
up(&lo->tx_lock);
- spin_lock(&lo->queue_lock);
file = lo->file;
lo->file = NULL;
- spin_unlock(&lo->queue_lock);
nbd_clear_que(lo);
printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
if (file)
fput(file);
return lo->harderror;
case NBD_CLEAR_QUE:
- down(&lo->tx_lock);
- if (lo->sock) {
- up(&lo->tx_lock);
- return 0; /* probably should be error, but that would
- * break "nbd-client -d", so just return 0 */
- }
- up(&lo->tx_lock);
- nbd_clear_que(lo);
+ /*
+ * This is for compatibility only. The queue is always cleared
+ * by NBD_DO_IT or NBD_CLEAR_SOCK.
+ */
+ BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
return 0;
case NBD_PRINT_DEBUG:
printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
@@ -688,6 +684,7 @@ static int __init nbd_init(void)
spin_lock_init(&nbd_dev[i].queue_lock);
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
init_MUTEX(&nbd_dev[i].tx_lock);
+ init_waitqueue_head(&nbd_dev[i].active_wq);
nbd_dev[i].blksize = 1024;
nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
disk->major = NBD_MAJOR;
diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig
index 17ff4056125..c0d2854dd09 100644
--- a/drivers/block/paride/Kconfig
+++ b/drivers/block/paride/Kconfig
@@ -4,11 +4,12 @@
# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
# PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option
# controls the choices given to the user ...
+# PARIDE only supports PC style parports. Tough for USB or other parports...
config PARIDE_PARPORT
tristate
depends on PARIDE!=n
- default m if PARPORT=m
- default y if PARPORT!=m
+ default m if PARPORT_PC=m
+ default y if PARPORT_PC!=m
comment "Parallel IDE high-level drivers"
depends on PARIDE
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index fa49d62626b..62d2464c12f 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 e9746af29b9..852b564e903 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 c0233efabeb..51b7a5c5b77 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -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 29d1518be72..43415f69839 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -81,8 +81,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 +131,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 +1057,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/rd.c b/drivers/block/rd.c
index 68c60a5bcda..ffd6abd6d5a 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -154,7 +154,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page,
/*
* ->writepage to the the blockdev's mapping has to redirty the page so that the
- * VM doesn't go and steal it. We return WRITEPAGE_ACTIVATE so that the VM
+ * VM doesn't go and steal it. We return AOP_WRITEPAGE_ACTIVATE so that the VM
* won't try to (pointlessly) write the page again for a while.
*
* Really, these pages should not be on the LRU at all.
@@ -165,7 +165,7 @@ static int ramdisk_writepage(struct page *page, struct writeback_control *wbc)
make_page_uptodate(page);
SetPageDirty(page);
if (wbc->for_reclaim)
- return WRITEPAGE_ACTIVATE;
+ return AOP_WRITEPAGE_ACTIVATE;
unlock_page(page);
return 0;
}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index af7cb2bfd67..01f042f6f1c 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 1ded3b43345..2ae08b343b9 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 };
@@ -770,7 +751,7 @@ static inline void carm_end_request_queued(struct carm_host *host,
rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
assert(rc == 0);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
rc = carm_put_request(host, crq);
assert(rc == 0);
@@ -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/ub.c b/drivers/block/ub.c
index 10740a06508..a05fe5843e6 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -951,7 +951,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
static void ub_end_rq(struct request *rq, int uptodate)
{
end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
- end_that_request_last(rq);
+ end_that_request_last(rq, uptodate);
}
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 0f48301342d..a3614e6a68d 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 2d518aa2720..f63e07bd9f9 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,
};
/*
@@ -305,7 +279,7 @@ static void viodasd_end_request(struct request *req, int uptodate,
if (end_that_request_first(req, uptodate, num_sectors))
return;
add_disk_randomness(req->rq_disk);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
/*
@@ -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 68b6d7b154c..cbce7c5e944 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_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 573ff6c1be5..613673b12fa 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 15396034841..879bbc26ce9 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/cdu31a.c b/drivers/cdrom/cdu31a.c
index ac96de15d83..378e88d2075 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -1402,7 +1402,7 @@ static void do_cdu31a_request(request_queue_t * q)
if (!end_that_request_first(req, 1, nblock)) {
spin_lock_irq(q->queue_lock);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 1);
spin_unlock_irq(q->queue_lock);
}
continue;
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index 01f03517332..ce127f7ec0f 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 b5191780ecc..193446e6a08 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 84e68cdd451..d6fcd0a36f9 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
@@ -928,6 +936,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
@@ -985,7 +1002,7 @@ config HPET_MMAP
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86 || IA64 || PPC64 || ARCH_S390
+ depends on X86 || IA64 || PPC64 || S390
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 4aeae687e88..503dd901d40 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 3f8f7fa6b0f..268f78d926d 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 a124f8c5d06..667a21c72ed 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
@@ -265,8 +266,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 +284,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 +318,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 +326,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 +1089,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 +1113,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 +1194,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 +1285,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 +1300,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 +1369,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 00000000000..5d72f50de1a
--- /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 c7f818cd7b0..39c61a71176 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 e41060c7622..9d180c42816 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 efff0eec618..5485382cade 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 64d6237fdd0..9da0ddb892b 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 3dc3c9d79ae..54b561e6948 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 2b6453a9ffc..fabc930c67a 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 319bdea8de8..1db12dcb680 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 bd958d69a2a..f8425452694 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 cc97bb906dd..f4f9db6c7ed 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 4dff7554eb0..c4fa5a29582 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 bf0a740122b..403f44a1bf0 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 754b934715c..00000000000
--- 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 dd91ff6b474..e9e2db18952 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 9b0feba6b06..bcd4e604d3e 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 b48a595d54e..f9e45303498 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 abef2acf99f..8074771e348 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 b370aca718d..e84605fc54a 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 d51aeb4966f..695115d7038 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 d66dc55e29a..5b1d3a04458 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 3f452f763f0..6f943e3309e 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 60b6f8e8bf6..42d766359ca 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 6d344976191..68e43ddc16a 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 dba502373da..cc1b8908687 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 070cef6c2b4..dfe6ad2b6a6 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 c78f36aaa2f..a18b80d9192 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 dc94f191442..4fea32aed6d 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 acd821e8fe4..722658188f5 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 bc4bd49fb0c..bf9075b576b 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 f3aa0c37012..9140703da1b 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 23e027d2908..77412ddac00 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 0508240f4e3..8e2e6095c4b 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 17e457c73dc..c6c71b45f10 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 2218a946ec8..296248cdc76 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 4fa448ee846..a1381c61aa6 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 13176d136a9..ba87ff17ff6 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 70dc7f64b7b..c2a4bac1452 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 1713451a5cc..9f7ed0e0351 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 461728e6a58..6b0c5319350 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 24a9d4e86af..54a18eb2fc0 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 47f54b5ae95..2837e669183 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 7452753d4d0..db5a60450e6 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 5ddc0320241..5d835b006f5 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 1661e735140..e20450ae220 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 5c79e40eb88..94abffb2cca 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 1e2e367b8b8..9dd6d4116e4 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 27eb0e31bd3..87f8ca2b068 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 14479cc08a5..caeecc2c36d 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
@@ -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 3a1ac5f78b4..291dbf4c818 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 e5b73c00239..a0ed20e2522 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 342302d4674..915665c7fe7 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 1cd81a671a3..9c177a6b2a4 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 ee49670d816..b04ed1b562b 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 d92ccee3e54..498b19b1d64 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 fef4a2b84c1..0ccfd3618ff 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 231ac1438c6..7bc27516d42 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 6d10515795c..0d426deeefe 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 22d799cde41..aa6c0d1a82f 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 a4b0fa998a9..dd46cb85439 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 e87a5d59b99..ef2581d1614 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 8f273da76dd..30f7b382746 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 3cef10643a8..6f6d7d613ed 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 b1fddad83a9..e218e526950 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 da850b4f544..94f2b4728b6 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 a8529728fa6..6774d2fe345 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 c275cbb6e9c..baa4416032a 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 a582a3db4c7..84204ec1b04 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 d4b1766608b..593c0b8f650 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 00000000000..9d5e027dae0
--- /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 00000000000..f4036cd5d0e
--- /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 ebde9206115..47f0b5b2637 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 016665e0c69..3f012255d31 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 7d5daf43797..aad4f99f540 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 5c71e089246..9429736b3b9 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 d023add1929..56d7e3daea1 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 6bd6ac52ad1..c6a08e96285 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 3baddacdff2..33e0cb12e4c 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 4ac495f297f..70c897c8876 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 eb4eda34434..256590fcc22 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 7fab9fbdf42..300ac61b09e 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 8693835cb2d..e233cf280bc 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 407708a001e..765c5c108bf 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 9f53d2fcc36..e469f641c72 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -345,26 +345,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 +393,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 +403,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 +681,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 ||
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 66e53dd450f..40a67c86420 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -120,7 +120,7 @@ __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
#if defined(CONFIG_X86)
# define HAVE_MONOTONIC
# define TIMER_FREQ 1000000000ULL
-#elif defined(CONFIG_ARCH_S390)
+#elif defined(CONFIG_S390)
/* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */
# define TIMER_FREQ 0xFA240000ULL
#elif defined(CONFIG_IA64)
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f9217763467..1994a92d473 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 53dc77c760f..831eb4e8d9d 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 a22aa940e01..a9522189fc9 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 6f673d2de0b..b3bc2e37e61 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -1,4 +1,9 @@
/*
+ Added support for the AMD Geode LX RNG
+ (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
+
+ derived from
+
Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
@@ -95,6 +100,11 @@ static unsigned int via_data_present (void);
static u32 via_data_read (void);
#endif
+static int __init geode_init(struct pci_dev *dev);
+static void geode_cleanup(void);
+static unsigned int geode_data_present (void);
+static u32 geode_data_read (void);
+
struct rng_operations {
int (*init) (struct pci_dev *dev);
void (*cleanup) (void);
@@ -122,6 +132,7 @@ enum {
rng_hw_intel,
rng_hw_amd,
rng_hw_via,
+ rng_hw_geode,
};
static struct rng_operations rng_vendor_ops[] = {
@@ -139,6 +150,9 @@ static struct rng_operations rng_vendor_ops[] = {
/* rng_hw_via */
{ via_init, via_cleanup, via_data_present, via_data_read, 1 },
#endif
+
+ /* rng_hw_geode */
+ { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
};
/*
@@ -155,10 +169,14 @@ 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 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
+
{ 0, }, /* terminate list */
};
MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
@@ -460,6 +478,57 @@ static void via_cleanup(void)
}
#endif
+/***********************************************************************
+ *
+ * AMD Geode RNG operations
+ *
+ */
+
+static void __iomem *geode_rng_base = NULL;
+
+#define GEODE_RNG_DATA_REG 0x50
+#define GEODE_RNG_STATUS_REG 0x54
+
+static u32 geode_data_read(void)
+{
+ u32 val;
+
+ assert(geode_rng_base != NULL);
+ val = readl(geode_rng_base + GEODE_RNG_DATA_REG);
+ return val;
+}
+
+static unsigned int geode_data_present(void)
+{
+ u32 val;
+
+ assert(geode_rng_base != NULL);
+ val = readl(geode_rng_base + GEODE_RNG_STATUS_REG);
+ return val;
+}
+
+static void geode_cleanup(void)
+{
+ iounmap(geode_rng_base);
+ geode_rng_base = NULL;
+}
+
+static int geode_init(struct pci_dev *dev)
+{
+ unsigned long rng_base = pci_resource_start(dev, 0);
+
+ if (rng_base == 0)
+ return 1;
+
+ geode_rng_base = ioremap(rng_base, 0x58);
+
+ if (geode_rng_base == NULL) {
+ printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
/***********************************************************************
*
@@ -574,7 +643,7 @@ static int __init rng_init (void)
DPRINTK ("ENTER\n");
- /* Probe for Intel, AMD RNGs */
+ /* Probe for Intel, AMD, Geode RNGs */
for_each_pci_dev(pdev) {
ent = pci_match_id(rng_pci_tbl, pdev);
if (ent) {
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index ba85eb1b6ec..fc944d375be 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 d815d197dc3..56e93a5a1e2 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 1f56b4cf0f5..0097f06fa67 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
@@ -787,7 +788,6 @@ int ipmi_destroy_user(ipmi_user_t user)
int i;
unsigned long flags;
struct cmd_rcvr *rcvr;
- struct list_head *entry1, *entry2;
struct cmd_rcvr *rcvrs = NULL;
user->valid = 1;
@@ -812,8 +812,7 @@ int ipmi_destroy_user(ipmi_user_t user)
* synchronize_rcu()) then free everything in that list.
*/
down(&intf->cmd_rcvrs_lock);
- list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {
- rcvr = list_entry(entry1, struct cmd_rcvr, link);
+ list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
if (rcvr->user == user) {
list_del_rcu(&rcvr->link);
rcvr->next = rcvrs;
@@ -3297,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 e053eade036..49c09ae004b 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 beea450ee4b..c67ef3e47ad 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 1bbf507adda..e9ebabaf8cb 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 ce3bc0d45f1..28c5a3193b8 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 91dd669273e..29c41f4418c 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/mmtimer.c b/drivers/char/mmtimer.c
index 78c89a3e782..c92378121b4 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -1,11 +1,11 @@
/*
- * Intel Multimedia Timer device implementation for SGI SN platforms.
+ * Timer device implementation for SGI SN platforms.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 2001-2006 Silicon Graphics, Inc. All rights reserved.
*
* This driver exports an API that should be supportable by any HPET or IA-PC
* multimedia timer. The code below is currently specific to the SGI Altix
@@ -45,7 +45,7 @@ MODULE_LICENSE("GPL");
/* name of the device, usually in /dev */
#define MMTIMER_NAME "mmtimer"
#define MMTIMER_DESC "SGI Altix RTC Timer"
-#define MMTIMER_VERSION "2.0"
+#define MMTIMER_VERSION "2.1"
#define RTC_BITS 55 /* 55 bits for this implementation */
@@ -227,10 +227,7 @@ typedef struct mmtimer {
struct tasklet_struct tasklet;
} mmtimer_t;
-/*
- * Total number of comparators is comparators/node * MAX nodes/running kernel
- */
-static mmtimer_t timers[NUM_COMPARATORS*MAX_COMPACT_NODES];
+static mmtimer_t ** timers;
/**
* mmtimer_ioctl - ioctl interface for /dev/mmtimer
@@ -441,29 +438,29 @@ static irqreturn_t
mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
- mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) *
- NUM_COMPARATORS;
unsigned long expires = 0;
int result = IRQ_NONE;
+ unsigned indx = cpu_to_node(smp_processor_id());
/*
* Do this once for each comparison register
*/
for (i = 0; i < NUM_COMPARATORS; i++) {
+ mmtimer_t *base = timers[indx] + i;
/* Make sure this doesn't get reused before tasklet_sched */
- spin_lock(&base[i].lock);
- if (base[i].cpu == smp_processor_id()) {
- if (base[i].timer)
- expires = base[i].timer->it.mmtimer.expires;
+ spin_lock(&base->lock);
+ if (base->cpu == smp_processor_id()) {
+ if (base->timer)
+ expires = base->timer->it.mmtimer.expires;
/* expires test won't work with shared irqs */
if ((mmtimer_int_pending(i) > 0) ||
(expires && (expires < rtc_time()))) {
mmtimer_clr_int_pending(i);
- tasklet_schedule(&base[i].tasklet);
+ tasklet_schedule(&base->tasklet);
result = IRQ_HANDLED;
}
}
- spin_unlock(&base[i].lock);
+ spin_unlock(&base->lock);
expires = 0;
}
return result;
@@ -523,7 +520,7 @@ static int sgi_timer_del(struct k_itimer *timr)
{
int i = timr->it.mmtimer.clock;
cnodeid_t nodeid = timr->it.mmtimer.node;
- mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i;
+ mmtimer_t *t = timers[nodeid] + i;
unsigned long irqflags;
if (i != TIMER_OFF) {
@@ -609,11 +606,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
preempt_disable();
nodeid = cpu_to_node(smp_processor_id());
- base = timers + nodeid * NUM_COMPARATORS;
retry:
/* Don't use an allocated timer, or a deleted one that's pending */
for(i = 0; i< NUM_COMPARATORS; i++) {
- if (!base[i].timer && !base[i].tasklet.state) {
+ base = timers[nodeid] + i;
+ if (!base->timer && !base->tasklet.state) {
break;
}
}
@@ -623,14 +620,14 @@ retry:
return -EBUSY;
}
- spin_lock_irqsave(&base[i].lock, irqflags);
+ spin_lock_irqsave(&base->lock, irqflags);
- if (base[i].timer || base[i].tasklet.state != 0) {
- spin_unlock_irqrestore(&base[i].lock, irqflags);
+ if (base->timer || base->tasklet.state != 0) {
+ spin_unlock_irqrestore(&base->lock, irqflags);
goto retry;
}
- base[i].timer = timr;
- base[i].cpu = smp_processor_id();
+ base->timer = timr;
+ base->cpu = smp_processor_id();
timr->it.mmtimer.clock = i;
timr->it.mmtimer.node = nodeid;
@@ -645,11 +642,11 @@ retry:
}
} else {
timr->it.mmtimer.expires -= period;
- if (reschedule_periodic_timer(base+i))
+ if (reschedule_periodic_timer(base))
err = -EINVAL;
}
- spin_unlock_irqrestore(&base[i].lock, irqflags);
+ spin_unlock_irqrestore(&base->lock, irqflags);
preempt_enable();
@@ -675,6 +672,7 @@ static struct k_clock sgi_clock = {
static int __init mmtimer_init(void)
{
unsigned i;
+ cnodeid_t node, maxn = -1;
if (!ia64_platform_is("sn2"))
return -1;
@@ -691,14 +689,6 @@ static int __init mmtimer_init(void)
mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
2) / sn_rtc_cycles_per_second;
- for (i=0; i< NUM_COMPARATORS*MAX_COMPACT_NODES; i++) {
- spin_lock_init(&timers[i].lock);
- timers[i].timer = NULL;
- timers[i].cpu = 0;
- timers[i].i = i % NUM_COMPARATORS;
- tasklet_init(&timers[i].tasklet, mmtimer_tasklet, (unsigned long) (timers+i));
- }
-
if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, SA_PERCPU_IRQ, MMTIMER_NAME, NULL)) {
printk(KERN_WARNING "%s: unable to allocate interrupt.",
MMTIMER_NAME);
@@ -712,6 +702,40 @@ static int __init mmtimer_init(void)
return -1;
}
+ /* Get max numbered node, calculate slots needed */
+ for_each_online_node(node) {
+ maxn = node;
+ }
+ maxn++;
+
+ /* Allocate list of node ptrs to mmtimer_t's */
+ timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL);
+ if (timers == NULL) {
+ printk(KERN_ERR "%s: failed to allocate memory for device\n",
+ MMTIMER_NAME);
+ return -1;
+ }
+
+ /* Allocate mmtimer_t's for each online node */
+ for_each_online_node(node) {
+ timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
+ if (timers[node] == NULL) {
+ printk(KERN_ERR "%s: failed to allocate memory for device\n",
+ MMTIMER_NAME);
+ return -1;
+ }
+ for (i=0; i< NUM_COMPARATORS; i++) {
+ mmtimer_t * base = timers[node] + i;
+
+ spin_lock_init(&base->lock);
+ base->timer = NULL;
+ base->cpu = 0;
+ base->i = i;
+ tasklet_init(&base->tasklet, mmtimer_tasklet,
+ (unsigned long) (base));
+ }
+ }
+
sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 79e490ef2cf..f43c2e04ead 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 26448f17680..ea725a9964e 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 a133a62f3d5..9f54733f162 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 853c98cee64..c48de09d68f 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 c556f4d3ccd..ccad7ae9454 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 1af733d0732..3556ccd7757 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 cf45b100eff..8a8ca32822b 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 49f3997fd25..9b5a2c0e700 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 bdfdfd28594..86be04b241e 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 0b397e1c8f1..29c98020409 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 c329aeb7c87..602266e0c08 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
index bd4fc84ec6c..dd686d58fd6 100644
--- a/drivers/char/rio/brates.h
+++ b/drivers/char/rio/brates.h
@@ -97,11 +97,10 @@
#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 */
+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
index 5b306543328..af14311f9b6 100644
--- a/drivers/char/rio/chan.h
+++ b/drivers/char/rio/chan.h
@@ -21,7 +21,7 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_chan_h_sccs = "@(#)chan.h 1.1" ;
+static char *_rio_chan_h_sccs = "@(#)chan.h 1.1";
#endif
#endif
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
index cf056a990f1..217ff09f2fa 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
index c369edaea2b..797b62400c9 100644
--- a/drivers/char/rio/cmd.h
+++ b/drivers/char/rio/cmd.h
@@ -42,7 +42,7 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1" ;
+static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1";
#endif
#endif
@@ -52,7 +52,7 @@ static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1" ;
#define CMD_IGNORE_PKT ( (ushort) 0)
#define CMD_STATUS_REQ ( (ushort) 1)
-#define CMD_UNIT_STATUS_REQ ( (ushort) 2) /* Is this needed ??? */
+#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)
@@ -81,4 +81,3 @@ static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1" ;
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h
index 2b8efbdbee1..a9a8c45631d 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 46befd354f2..77cee8df68e 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 1712f6261dd..6853d03304a 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 62dba0e68b3..28a991bd4fe 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/debug.h b/drivers/char/rio/debug.h
index b6e0d093555..6ae95c00db4 100644
--- a/drivers/char/rio/debug.h
+++ b/drivers/char/rio/debug.h
@@ -33,7 +33,7 @@
#define DBPACKET(pkt, opt, str, chn) debug_packet((pkt), (opt), (str), (chn))
#else
#define DBPACKET(pkt, opt, str, c)
-#endif /* DCIRRUS */
+#endif /* DCIRRUS */
-#endif /* _debug_h_ */
+#endif /* _debug_h_ */
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h
index 2e7309e2762..5b600c32ac0 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
index 59371b0528b..c2abaf0eab0 100644
--- a/drivers/char/rio/eisa.h
+++ b/drivers/char/rio/eisa.h
@@ -60,7 +60,7 @@ static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2";
#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_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 */
@@ -101,4 +101,4 @@ static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2";
#define INBZ(z,x) inb(((z)<<12) | (x))
#define OUTBZ(z,x,y) outb((((z)<<12) | (x)), y)
-#endif /* __rio_eisa_h__ */
+#endif /* __rio_eisa_h__ */
diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h
index 8e9a419e15b..e06673fa48c 100644
--- a/drivers/char/rio/enable.h
+++ b/drivers/char/rio/enable.h
@@ -36,7 +36,7 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_enable_h_sccs = "@(#)enable.h 1.1" ;
+static char *_rio_enable_h_sccs = "@(#)enable.h 1.1";
#endif
#endif
@@ -46,5 +46,3 @@ static char *_rio_enable_h_sccs = "@(#)enable.h 1.1" ;
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/error.h b/drivers/char/rio/error.h
index 229438e355f..f20f0789db8 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 f920b9f3e2b..1d0d8914433 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
index a8b65ae0de9..3c7c91ace3e 100644
--- a/drivers/char/rio/formpkt.h
+++ b/drivers/char/rio/formpkt.h
@@ -41,114 +41,113 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1" ;
+static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1";
#endif
#endif
-typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1 ;
+typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1;
struct FORM_BOOT_PKT_1 {
- ushort pkt_number ;
- ushort pkt_total ;
- ushort boot_top ;
- } ;
+ ushort pkt_number;
+ ushort pkt_total;
+ ushort boot_top;
+};
-typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2 ;
+typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2;
struct FORM_BOOT_PKT_2 {
- ushort pkt_number ;
- char boot_data[10] ;
- } ;
+ 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_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_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 ;
+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 ;
+ 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] ;
- } ;
+ char cmd_code;
+ char pkt_number;
+ char total_in_sequence;
+ char route_data[9];
+};
-typedef struct FORM_ROUTE_REQ FORM_ROUTE_REQ ;
+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] ;
- } ;
+ char cmd_code;
+ char pkt_number;
+ char total_in_sequence;
+ char route_data[10];
+};
-typedef struct FORM_ERROR FORM_ERROR ;
+typedef struct FORM_ERROR FORM_ERROR;
struct FORM_ERROR {
- char cmd_code ;
- char error_code ;
+ char cmd_code;
+ char error_code;
- } ;
+};
-typedef struct FORM_STATUS FORM_STATUS ;
+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 ;
- } ;
+ 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 ;
+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 ;
- } ;
+ 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 ;
+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 ;
- } ;
+ 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 01987c6dc39..b4778410ec6 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 4c65963870a..f7dfcedf7d4 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
index f6f31ece6e3..6281fe47f4e 100644
--- a/drivers/char/rio/hosthw.h
+++ b/drivers/char/rio/hosthw.h
@@ -37,7 +37,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2" ;
+static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2";
#endif
#endif
@@ -53,5 +53,3 @@ static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2" ;
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
index 972250348f4..bfba5b0c033 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 d53843abe02..17a14c4a342 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 a4f7f1f5625..36aad4c9cb3 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
index bbac8fa18fe..b41764d7a22 100644
--- a/drivers/char/rio/lrt.h
+++ b/drivers/char/rio/lrt.h
@@ -36,7 +36,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1" ;
+static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1";
#endif
#endif
@@ -50,6 +50,3 @@ static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1" ;
/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h
index f27dcecf03c..ab04004d404 100644
--- a/drivers/char/rio/ltt.h
+++ b/drivers/char/rio/ltt.h
@@ -36,7 +36,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1" ;
+static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1";
#endif
#endif
@@ -45,11 +45,8 @@ static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1" ;
#else
#define LTT_STACK (ushort) 200
#endif
-
-/*********** end of file ***********/
-
-
+/*********** end of file ***********/
diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h
index fe17d0ee493..fdf0c1f250a 100644
--- a/drivers/char/rio/lttwake.h
+++ b/drivers/char/rio/lttwake.h
@@ -39,7 +39,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1" ;
+static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1";
#endif
#endif
@@ -48,6 +48,3 @@ static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1" ;
/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h
index 400645a1ff2..97fe287aab2 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
index 08a327e473a..d01e76be7a1 100644
--- a/drivers/char/rio/mca.h
+++ b/drivers/char/rio/mca.h
@@ -70,4 +70,4 @@ static char *_mca_h_sccs_ = "@(#)mca.h 1.2";
#define RIO_MCA_DEFAULT_MODE SLOW_LINKS
-#endif /* __rio_mca_h__ */
+#endif /* __rio_mca_h__ */
diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h
index 9cf6c0bacea..dd9be586ec6 100644
--- a/drivers/char/rio/mesg.h
+++ b/drivers/char/rio/mesg.h
@@ -38,4 +38,4 @@ static char *_mesg_h_sccs_ = "@(#)mesg.h 1.2";
#endif
-#endif /* __rio_mesg_h__ */
+#endif /* __rio_mesg_h__ */
diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h
index 2dc30b9aab3..de7e57180c9 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 46f99dfdac8..fe4e0056706 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 dc635bd2519..1eba9118079 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 e1483a0e30b..3baebf8513a 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 66bb2ff0f69..882fd429ac2 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
index d9b8e983e17..9616ee4c6cd 100644
--- a/drivers/char/rio/poll.h
+++ b/drivers/char/rio/poll.h
@@ -39,7 +39,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_poll_h_sccs = "@(#)poll.h 1.2" ;
+static char *_rio_poll_h_sccs = "@(#)poll.h 1.2";
#endif
#endif
@@ -54,23 +54,20 @@ static char *_rio_poll_h_sccs = "@(#)poll.h 1.2" ;
#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***** */
+#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 */
+#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 8506af06aa9..c99b1e70fdc 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
index ddff0ef84e3..f9a3376333e 100644
--- a/drivers/char/rio/proto.h
+++ b/drivers/char/rio/proto.h
@@ -23,15 +23,15 @@
/*
** boot.c
*/
-void init_boot( char *p, short stage);
+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);
+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
@@ -41,116 +41,116 @@ 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 );
+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 );
+void idle(Process * idle_p);
/*
** init.c
*/
void general_init(void);
-void mem_halt( int error);
+void mem_halt(int error);
/*
** linkinit.c
*/
-void initlink( u_short number, LPB *link);
-void runlink( LPB *link);
+void initlink(u_short number, LPB * link);
+void runlink(LPB * link);
/*
** list.c
*/
PKT *get_free_start(void);
-void put_free_start( PKT *pkt);
+void put_free_start(PKT * pkt);
#ifdef HOST
-int can_remove_transmit ( PKT **pkt, PKT *pointer );
+int can_remove_transmit(PKT ** pkt, PKT * pointer);
#endif
#ifdef RTA
-int spl7 ( void );
-int spl0 ( void );
-Q_BUF *get_free_q( void );
+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);
+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 );
+void lrt(Process * lrt_p, LPB * link);
#ifdef RTA
-void set_led_red ( LPB *link );
+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 );
+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 );
+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 );
+int consume_cpu(void);
#endif
/*
** lttwake.c
*/
#ifdef HOST
-void ltt_wakeup( Process *ltt_wakeup_p );
+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 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 );
+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);
+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);
+void tx_poll(Process * tx_poll_p);
/*
** process.c
*/
-int get_proc_space( Process **pd, int **pws, int wssize);
+int get_proc_space(Process ** pd, int **pws, int wssize);
/*
** readrom.c
@@ -160,85 +160,85 @@ void read_serial_number(char *buf);
/*
** rio.c
*/
-int main( void );
+int main(void);
/*
** route.c
*/
-void route_update ( PKT *pkt, LPB *link);
+void route_update(PKT * pkt, LPB * link);
/*
** rtainit.c
*/
#if defined(RTA)
void rta_init(ushort RtaType);
-#endif /* defined(RTA) */
+#endif /* defined(RTA) */
/*
** rupboot.c
*/
-void rup_boot( PKT *pkt, RUP *this_rup, LPB *link);
+void rup_boot(PKT * pkt, RUP * this_rup, LPB * link);
#ifdef RTA
-void kill_your_neighbour( int link_to_kill );
+void kill_your_neighbour(int link_to_kill);
#endif
/*
** rupcmd.c
*/
-void rup_command( PKT *pkt, struct RUP *this_rup, LPB *link);
+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 );
+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 );
+void rup_poll(PKT * pkt, RUP * this_rup, LPB * link);
/*
** ruppower.c
*/
-void rup_power( PKT *pkt, RUP *this_rup, LPB *link );
+void rup_power(PKT * pkt, RUP * this_rup, LPB * link);
/*
** ruprm.c
*/
-void rup_route_map( PKT *pkt, RUP *this_rup, LPB *link);
+void rup_route_map(PKT * pkt, RUP * this_rup, LPB * link);
/*
** rupstat.c
*/
-void rup_status( PKT *pkt, RUP *this_rup, LPB *link);
+void rup_status(PKT * pkt, RUP * this_rup, LPB * link);
/*
** rupsync.c
*/
-void rup_sync( PKT *pkt);
+void rup_sync(PKT * pkt);
/*
** rxpkt.c
*/
-ERROR rx_pkt( PKT_ptr_ptr pkt_address, LPB *link);
+ERROR rx_pkt(PKT_ptr_ptr pkt_address, LPB * link);
/*
** sendsts.c
*/
-void send_status( PKT *requesting_pkt, RUP *this_rup);
+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);
+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);
+ERROR tx_pkt(PKT * pkt, LPB * link);
+short send_sync(LPB * link);
-#endif /* _prototypes_h */
+#endif /* _prototypes_h */
diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h
index 848111ac938..69fc4bc3415 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 1fce02f8fcf..acd9e8e5307 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 13a9931958b..7f45e1ab533 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 d7d484024e2..8825bd61b7d 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
@@ -144,34 +140,51 @@ more than 512 ports.... */
*/
#define RIO_REPORT_FIFO
#define RIO_REPORT_OVERRUN
-#endif
+#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 +192,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 +225,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 +243,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 +262,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 +278,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 +301,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 +363,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 +489,106 @@ 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;
+ struct Port *PortP;
- func_enter();
+ func_enter();
- PortP = (struct Port *)ptr;
- PortP->gs.tty = NULL;
+ 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);
- }
+ 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
- func_exit();
+ func_exit();
}
@@ -595,16 +599,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();
-
- PortP = (struct Port *)ptr;
- PortP->gs.tty = NULL;
+ func_enter();
- func_exit ();
+ PortP = (struct Port *) ptr;
+ PortP->gs.tty = NULL;
+
+ func_exit();
}
@@ -612,146 +616,135 @@ 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;
+ int rc;
+ struct Port *PortP;
+ int ival;
- func_enter();
+ func_enter();
- PortP = (struct Port *)tty->driver_data;
+ PortP = (struct Port *) tty->driver_data;
- rc = 0;
- switch (cmd) {
+ rc = 0;
+ switch (cmd) {
#if 0
- case TIOCGSOFTCAR:
- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
- (unsigned int *) arg);
- break;
+ 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;
+ 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;
+ /*
+ * 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;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ func_exit();
+ return rc;
}
@@ -771,37 +764,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 +806,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 +885,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 +893,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));
+ }
+
+
+ func_exit();
+ return 0;
- free6:for (i--;i>=0;i--)
- kfree (p->RIOPortp[i]);
+ 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 +1008,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 +1021,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 +1333,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 1fba19d5b66..4ce77fb1fae 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 cc6ac6a98f6..822c071a693 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/riocmd.c b/drivers/char/rio/riocmd.c
index 533085ec6f1..b97dd9fdb6b 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,114 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
ushort subCommand;
unsigned long flags;
- func_enter ();
+ func_enter();
#ifdef CHECK
- CheckHost( Host );
- CheckHostP( HostP );
- CheckPacketP( PacketP );
+ CheckHost(Host);
+ CheckHostP(HostP);
+ CheckPacketP(PacketP);
#endif
/*
- ** 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 );
+ 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 );
+ 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 +501,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 +575,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 +589,29 @@ 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 );
+ 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 +620,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 +680,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 +689,246 @@ 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!
- */
+ ** 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);
+ 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 (!(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!
- */
+ ** Whammy! blat that pack!
+ */
#ifdef CHECK
- CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt));
+ 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));
+ 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 );
+ 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 );
+ 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 b4d1a23e27e..0b7700d2f04 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,264 @@ 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:
+ case RIO_DEBUG_MEM:
#ifdef DEBUG_MEM_SUPPORT
-RIO_DEBUG_CTRL, if (su)
- return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg);
- else
+ 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");
+ 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 +406,1244 @@ 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");
+ return RIONewTable(p);
- 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 :
+ 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");
- 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");
+ }
+ /*
+ ** 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");
#ifdef LOGGING
- RIOGetLog(arg);
- return 0;
+ RIOGetLog(arg);
+ return 0;
#else
- return -EINVAL;
+ 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);
+ 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;
- }
+ 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;
- 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 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;
+ 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->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 (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]);
#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);
+ 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;
+ 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;
- }
+ 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;
-
- case RIO_SET_CONFIG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
+ 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)&p->RIOConf, sizeof(struct Conf) )
- ==COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
+ 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;
}
- /*
- ** 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;
+ }
+ } 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_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;
+ 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;
+ /*
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ ** !! 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);
+ RIOSetupDataStructs(p);
#endif
- }
- RIOFoadWakeup(p);
- p->RIONumBootPkts = 0;
- p->RIOBooting = 0;
+ }
+ 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 );
+ 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));
+ bzero((caddr_t) & p->RIOPortp[0], RIO_PORTS * sizeof(struct Port));
#else
- printk ("HEEEEELP!\n");
+ printk("HEEEEELP!\n");
#endif
- for( loop=0; loop<RIO_PORTS; loop++ ) {
+ for (loop = 0; loop < RIO_PORTS; loop++) {
#if 0
- p->RIOPortp[loop]->TtyP = &p->channel[loop];
+ 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;
+ 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);
- 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);
+ /*
+ ** 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;
- 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;
{
@@ -1766,104 +1654,99 @@ uchar Cmd;
int port;
#ifdef CHECK
- CheckPortP( PortP );
+ 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 bc38ac5dfbd..663ee0914ed 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 e08421c9558..8de7966e603 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/riointr.c b/drivers/char/rio/riointr.c
index e42e7b50bf6..34d8787557a 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 c3d679733c9..14b83fae75c 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/rioparam.c b/drivers/char/rio/rioparam.c
index f10916326ec..4cc7f4942bf 100644
--- a/drivers/char/rio/rioparam.c
+++ b/drivers/char/rio/rioparam.c
@@ -157,46 +157,44 @@ 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 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;
@@ -207,9 +205,8 @@ int SleepFlag;
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");
+ } 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;
@@ -222,230 +219,222 @@ int SleepFlag;
}
/*
- ** 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");
+ ** 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 +442,195 @@ 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");
+ 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 & LOBLK)
+ rio_dprintk(RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\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");
+ 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 (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_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");
#endif
/*
- ** 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 +640,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 +656,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 +686,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 +712,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 +728,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 2ea99a60aa3..535afaa51ca 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 e9564c9fb37..0f4cd33ba64 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -93,625 +93,517 @@ 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;
+ 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");
+ RIOStackCheck("RIORouteRup");
#endif
#ifdef CHECK
- CheckPacketP(PacketP);
- CheckHostP(HostP);
- CheckRup(Rup);
- CheckHost(Host);
+ 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 )
- {
/*
- ** 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;
+ ushort dest_port = port + 8;
#if 0
- uint PktInt;
+ uint PktInt;
#endif
- WORD *TxPktP;
- PKT *Pkt;
+ 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,9 +615,8 @@ 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;
{
@@ -733,16 +624,16 @@ uint UnitId;
rio_spin_lock_irqsave(&HostP->HostLock, flags);
#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
+ 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 +644,83 @@ 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 );
+ 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 );
+ 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 +730,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 +738,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 +817,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 +851,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 +875,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 +936,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 32b09b0f23a..534f1f5b9f5 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 e45bc275907..42c3dffcbbb 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++;
+ }
+
+ 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;
+ }
- HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+ /*
+ ** 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;
- 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;
+ 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;
@@ -819,135 +755,127 @@ struct Map *HostMapP;
unsigned long flags;
#ifdef CHECK
- CheckHostP( HostP );
- CheckHostMapP( HostMapP );
+ 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];
+ 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 +883,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
index 66d52bc0549..35e01cd103d 100644
--- a/drivers/char/rio/riotime.h
+++ b/drivers/char/rio/riotime.h
@@ -40,7 +40,7 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1" ;
+static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1";
#endif
#endif
@@ -52,7 +52,7 @@ static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1" ;
/**************************************
* Convert a RIO tick (1/10th second)
* into transputer low priority ticks
- *************************************/
+ *************************************/
#define RioTimeToLow(time) (time*(100000 / 64))
#define RioLowToTime(time) ((time*64)/100000)
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index 78a321afdf4..5894a25b011 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -90,21 +90,19 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
#include "sam.h"
#if 0
-static void ttyseth_pv(struct Port *, struct ttystatics *,
- struct termios *sg, int);
+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 +115,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 +141,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 +203,131 @@ 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 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");
+ 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 ();
+ 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 );
+ if (repeat_this-- <= 0) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
pseterr(EINTR);
- func_exit ();
+ func_exit();
return -EIO;
}
- } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
- rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
+ } 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");
+ rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
pseterr(ENXIO);
- func_exit ();
+ func_exit();
return 0;
}
}
#else
/* 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");
+ rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
#endif
#if 0
- tp = PortP->TtyP; /* get tty struct */
+ tp = PortP->TtyP; /* get tty struct */
#endif
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 ();
+ 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 +338,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 +355,26 @@ 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 */
+ 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 */
+ RIODelay(PortP, HUNDRED_MS * 10);
+ RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); /* Config the port */
#endif
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 +391,109 @@ 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 (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL)
#if 0
- if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH))
+ 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;
- }
+ {
+ /*
+ ** 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,36 +502,35 @@ 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 */
+ 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);
@@ -553,48 +538,48 @@ riotclose(void *ptr)
/* 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 */
+
+ 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 +587,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 +635,8 @@ riotclose(void *ptr)
return -EIO;
}
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
goto close_end;
}
@@ -665,57 +649,56 @@ 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;
}
@@ -728,52 +711,50 @@ close_end:
** COOK_MEDIUM if the card can do all the processing necessary.
*/
#if 0
-static int
-RIOCookMode(struct ttystatics *tp)
+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)
- */
+ ** 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 );
+ 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 )
+ if (tp->tm.c_lflag & XCASE)
return COOK_WELL; /* Use line disc */
- if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) )
+ 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 */
+ if (tp->tm.c_oflag == OPOST) /* If only OPOST is set, do RAW */
return COOK_RAW;
/*
- ** So, we need to output process!
- */
+ ** 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 +769,31 @@ 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");
+ rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
#ifdef CHECK
- CheckPortP( PortP );
- if ( len < 1 || len > 2 )
- cprintf(("STUPID LENGTH %d\n",len));
+ CheckPortP(PortP);
+ if (len < 1 || len > 2)
+ cprintf(("STUPID LENGTH %d\n", len));
#endif
- 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 +803,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;
@@ -878,28 +857,26 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP,
** 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)
+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);
+ 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;
}
@@ -912,205 +889,195 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
PortP->Stat.IoctlCnt++;
#endif
- if ( PortP->State & RIO_DELETED ) {
+ if (PortP->State & RIO_DELETED) {
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return -EIO;
}
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return -EIO;
}
/*
- ** Count ioctls for port statistics reporting
- */
+ ** Count ioctls for port statistics reporting
+ */
if (PortP->statsGather)
PortP->ioctls++;
/*
- ** Specialix RIO Ioctl calls
- */
+ ** 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 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 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);
- }
+ 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);
- return 0;
+ 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 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;
- 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;
+ 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 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);
+ 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);
- return 0;
+ 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 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;
+ 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);
- return 0;
+ 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 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);
- }
+ 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 TCRIOIXANYON:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n");
- PortP->Config |= RIO_IXANY;
+ 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);
- return 0;
+ pseterr(EFAULT);
+ }
+ 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 TCRIOIXANYON:
+ rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXANYON\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 TCRIOIXANYOFF:
+ rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXANYOFF\n");
+ PortP->Config &= ~RIO_IXANY;
+ 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;
+ 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 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 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 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;
+ 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 */
@@ -1119,35 +1086,35 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
/* 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;
+ 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 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) {
+ switch (cmd) {
case TCSETAW:
case TCSETAF:
case TCSETA:
@@ -1171,29 +1138,29 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
#endif
case TIOCSETD:
case TIOCSETN:
- rio_dprintk (RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n");
+ 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.
- */
+ ** 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);
+ 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 );
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
pseterr(EIO);
return 0;
@@ -1202,10 +1169,10 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
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 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;
@@ -1214,13 +1181,12 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
tp->tm.c_line = PortP->StoredTty.line;
for (i = 0; i < NCC + 1; i++)
tp->tm.c_cc[i] = PortP->StoredTty.cc[i];
- }
- else {
+ } 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 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;
@@ -1232,44 +1198,41 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
}
}
- changed = (tp->tm.c_cflag != old_cflag) ||
- (tp->tm.c_iflag != old_iflag) ||
- (tp->tm.c_oflag != old_oflag);
+ 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);
+ 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)) {
+ ** 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);
+ wakeup((caddr_t) & tp->tm.c_canq);
}
#endif
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
pseterr(EIO);
return 0;
}
/*
- ** Re-configure if modes or cooking have changed
- */
+ ** 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_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 );
+ RIOClearUp(PortP);
pseterr(EIO);
return 0;
}
@@ -1280,36 +1243,32 @@ riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
/*
ttyseth -- set hardware dependent tty settings
*/
-void
-ttyseth(PortP, s, sg)
-struct Port * PortP;
-struct ttystatics * s;
+void ttyseth(PortP, s, sg)
+struct Port *PortP;
+struct ttystatics *s;
struct old_sgttyb *sg;
{
- struct old_sgttyb * tsg;
+ struct old_sgttyb *tsg;
struct termios *tp = &s->tm;
tsg = &s->sg;
- if (sg->sg_flags & (EVENP|ODDP)) {
+ 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 {
+ } else {
tp->c_cflag &= V_CS7;
tp->c_cflag &= PARENB;
tp->c_cflag &= PARODD;
}
- }
- else if (sg->sg_flags & ODDP) {
+ } else if (sg->sg_flags & ODDP) {
tp->c_cflag &= V_CS7;
tp->c_cflag &= PARENB;
tp->c_cflag &= PARODD;
- }
- else {
+ } else {
tp->c_cflag &= V_CS7;
tp->c_cflag &= PARENB;
}
@@ -1320,16 +1279,16 @@ struct old_sgttyb *sg;
* I will have to use separate sets of flags to store them in the
* Port structure.
*/
- if ( !sg->sg_ospeed )
+ if (!sg->sg_ospeed)
sg->sg_ospeed = sg->sg_ispeed;
else
sg->sg_ispeed = sg->sg_ospeed;
- if (sg->sg_ispeed > V_EXTB )
+ 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];
+ tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int) sg->sg_ispeed];
}
/*
@@ -1338,36 +1297,33 @@ struct old_sgttyb *sg;
sysv = 0 => (POSIX): struct termios *sg
sysv != 0 => (System V): struct termio *sg
*/
-static void
-ttyseth_pv(PortP, s, sg, sysv)
+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];
- }
+ 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 1c7c42c638f..9b67e2468be 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
index 18a4f147edc..f802d7593b8 100644
--- a/drivers/char/rio/riowinif.h
+++ b/drivers/char/rio/riowinif.h
@@ -40,7 +40,7 @@
*/
-#ifndef _riowinif_h /* If RIOWINDIF.H not already defined */
+#ifndef _riowinif_h /* If RIOWINDIF.H not already defined */
#define _riowinif_h 1
/*****************************************************************************
@@ -60,42 +60,41 @@
/* 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 */
+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;
@@ -184,45 +183,44 @@ typedef struct _PARM_MAP
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 */
+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 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 */
+#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 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 */
/*****************************************************************************
********************************** ***********************************
@@ -234,52 +232,51 @@ typedef struct _RUP
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 */
+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 */
+#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_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 */
+#define MAX_PHB 128 /* range 0-127 */
/*****************************************************************************
********************************** ***********************************
@@ -291,86 +288,85 @@ typedef struct _PHB
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 */
+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 */
+#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 */
/*****************************************************************************
******************************** *******************************
@@ -380,17 +376,16 @@ typedef struct _LPB
/* 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 */
+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 */
+#define FL_next 0x00 /* 0x00 offset of next list item */
+#define FL_prev 0x02 /* 0x02 offset of previous list item */
/*****************************************************************************
********************************** ***********************************
@@ -401,32 +396,31 @@ typedef struct _FREE_LIST
/* 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 */
+#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 */
+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 */
+#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
@@ -449,38 +443,38 @@ typedef struct _PKT
/* 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) */
+#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 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 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 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 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 */
+#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 */
@@ -488,24 +482,24 @@ typedef struct _PKT
#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 */
+#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 */
+#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 */
/*****************************************************************************
********************************** **********************************
@@ -518,89 +512,89 @@ typedef struct _PKT
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 */
+#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 */
+#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 */
+#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 */
+#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 */
+#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 */
+#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 */
/*****************************************************************************
********************************* *********************************
@@ -636,7 +630,7 @@ typedef struct _PKT
No parameters.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
/*****************************************************************************
********************************* *********************************
@@ -653,9 +647,9 @@ typedef struct _PKT
write flushing previously started by a pre-emptive WFLUSH packet. (in-band)
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
/*****************************************************************************
********************************* *********************************
@@ -669,8 +663,8 @@ typedef struct _PKT
packets of a port.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
#endif
/*****************************************************************************
@@ -685,8 +679,8 @@ typedef struct _PKT
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 */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
#endif
/*****************************************************************************
@@ -707,9 +701,9 @@ typedef struct _PKT
specified number of mS.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
-#define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */
+#define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */
/*****************************************************************************
********************************* *********************************
@@ -736,8 +730,8 @@ typedef struct _PKT
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 */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
#endif
/*****************************************************************************
@@ -753,8 +747,8 @@ typedef struct _PKT
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 */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
#endif
/*****************************************************************************
@@ -774,8 +768,8 @@ typedef struct _PKT
- Transparent Print Stop Sequence.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
#endif
/*****************************************************************************
@@ -789,14 +783,14 @@ typedef struct _PKT
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 */
+#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 */
+#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 */
+#define MBIS_RTS 0x01 /* RTS modem signal */
+#define MBIS_DTR 0x02 /* DTR modem signal */
/*****************************************************************************
********************************** **********************************
@@ -808,16 +802,16 @@ typedef struct _PKT
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 */
+#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 */
+#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 */
+#define MBIC_RTS 0x01 /* RTS modem signal */
+#define MBIC_DTR 0x02 /* DTR modem signal */
/*****************************************************************************
********************************** **********************************
@@ -829,15 +823,15 @@ typedef struct _PKT
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 */
+#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 */
+#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 */
+#define MSET_RTS 0x01 /* RTS modem signal */
+#define MSET_DTR 0x02 /* DTR modem signal */
/*****************************************************************************
********************************* *********************************
@@ -853,7 +847,7 @@ typedef struct _PKT
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 */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
/*****************************************************************************
********************************** **********************************
@@ -865,8 +859,8 @@ typedef struct _PKT
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 */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
/*****************************************************************************
********************************* ********************************
@@ -880,11 +874,11 @@ typedef struct _PKT
of the specified port's RTA address space.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#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 */
/*****************************************************************************
****************************** *****************************
@@ -898,11 +892,11 @@ typedef struct _PKT
of the CD1400 register specified in address.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#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 */
/*****************************************************************************
************************ **************************
@@ -916,33 +910,33 @@ typedef struct _PKT
packets, except MEMDUMP and READ_REGISTER.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#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 */
+#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 */
+#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 */
/*****************************************************************************
************************ **************************
@@ -956,35 +950,35 @@ typedef struct _PKT
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 */
+#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 */
+#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 */
+#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 */
+#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 */
+#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 */
/*****************************************************************************
******************** ********************
@@ -998,15 +992,15 @@ typedef struct _PKT
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 */
+#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 */
+#define PKT_Dump (PKT_Data+8) /* 32bytes of requested dump data */
/*****************************************************************************
***************** *****************
@@ -1020,14 +1014,14 @@ typedef struct _PKT
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 */
+#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 */
+#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 */
+#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
+#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
#endif
/*****************************************************************************
@@ -1041,9 +1035,9 @@ typedef struct _PKT
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 */
+#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
/*****************************************************************************
@@ -1059,10 +1053,10 @@ typedef struct _PKT
*/
#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_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
/*****************************************************************************
@@ -1077,7 +1071,7 @@ typedef struct _PKT
firmware code to load onto attached RTAs.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
/*****************************************************************************
@@ -1092,12 +1086,12 @@ typedef struct _PKT
to a BOOT_RUP - BOOT_REQUEST packet.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#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 */
/*****************************************************************************
************************ ***********************
@@ -1111,10 +1105,10 @@ typedef struct _PKT
RTA firmware has completed.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#define PKT_LinkNumber (PKT_Data+1) /* Link number RTA booted on */
+#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
/*****************************************************************************
************************ ***********************
@@ -1127,7 +1121,7 @@ typedef struct _PKT
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 */
+#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
/*****************************************************************************
*********************** ***********************
@@ -1141,9 +1135,9 @@ typedef struct _PKT
packet with the 70 bytes of the requested sequence.
*/
#if 0
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
+#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
#endif
-#define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */
+#define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */
/*****************************************************************************
**************************** ****************************
@@ -1157,10 +1151,10 @@ typedef struct _PKT
RTA to shut down and reboot.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 PKT_IfoadId1 (PKT_Data+2) /* IFOAD Id 1 */
+#define PKT_IfoadId2 (PKT_Data+3) /* IFOAD Id 2 */
#define IFOADID1 0xAD
#define IFOADID2 0xF0
@@ -1177,9 +1171,9 @@ typedef struct _PKT
RTA to flash its LEDs for a period of time.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
-#define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */
+#define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */
/*****************************************************************************
**************************** ***************************
@@ -1193,10 +1187,10 @@ typedef struct _PKT
RTA to shut down and flash it's LEDs.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 PKT_ZombieId1 (PKT_Data+2) /* ZOMBIE Id 1 */
+#define PKT_ZombieId2 (PKT_Data+3) /* ZOMBIE Id 2 */
#define ZOMBIEID1 0x52
#define ZOMBIEID2 0x21
@@ -1213,11 +1207,11 @@ typedef struct _PKT
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 */
+#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 PKT_UfoadId1 (PKT_Data+2) /* UFOAD Id 1 */
+#define PKT_UfoadId2 (PKT_Data+3) /* UFOAD Id 2 */
#define UFOADID1 0x1E
#define UFOADID2 0x0D
@@ -1234,11 +1228,11 @@ typedef struct _PKT
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 */
+#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 PKT_IwaitId1 (PKT_Data+2) /* IWAIT Id 1 */
+#define PKT_IwaitId2 (PKT_Data+3) /* IWAIT Id 2 */
#define IWAITID1 0xDE
#define IWAITID2 0xB1
@@ -1255,20 +1249,20 @@ typedef struct _PKT
RTA to a Driver to request an ID (RUP or unit number).
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#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 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 */
+#define MOD2 0x08 /* Set to indicate Rev2 module */
/*****************************************************************************
************************* *************************
@@ -1282,9 +1276,9 @@ typedef struct _PKT
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 */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
+#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
/*****************************************************************************
*********************** ***********************
@@ -1298,13 +1292,13 @@ typedef struct _PKT
packet to allocate the RTA's Id number (RUP number 1..16)
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#define PKT_Cmd (PKT_Data+0) /* Command code */
#endif
-#define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */
+#define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */
#if 0
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
+#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
#endif
-#define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */
+#define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */
/*****************************************************************************
*********************** ***********************
@@ -1318,18 +1312,18 @@ typedef struct _PKT
current link status.
*/
#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
+#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 */
+#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
index 7685cc1d9e7..60d66d0056a 100644
--- a/drivers/char/rio/riscos.h
+++ b/drivers/char/rio/riscos.h
@@ -60,4 +60,4 @@ static char *_riscos_h_sccs_ = "@(#)riscos.h 1.2";
#define RINDW(A) (*(ushort *)(A))
#define WINDW(A,V) (*(ushort *)(A)=(ushort)(V))
-#endif /* __rio_riscos_h__ */
+#endif /* __rio_riscos_h__ */
diff --git a/drivers/char/rio/rom.h b/drivers/char/rio/rom.h
index ee79b8e5b97..58a7843625f 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 c42dbb97171..769744e575a 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
index 06860118cbc..e6c2cdfd3a1 100644
--- a/drivers/char/rio/rtahw.h
+++ b/drivers/char/rio/rtahw.h
@@ -37,7 +37,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5" ;
+static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5";
#endif
#endif
@@ -58,12 +58,12 @@ static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5" ;
** 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 */
+ 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
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
index b9d2bc03d14..8d44fec91dd 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
index b4aafaff0d7..56d828c63d2 100644
--- a/drivers/char/rio/rupstat.h
+++ b/drivers/char/rio/rupstat.h
@@ -39,7 +39,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1" ;
+static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1";
#endif
#endif
@@ -48,4 +48,3 @@ static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1" ;
#define STATUS_TOPOLOGY 2
#endif
-
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h
index c1accb8cb62..31494054b21 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
index deae48722a2..7a3dba35232 100644
--- a/drivers/char/rio/selftest.h
+++ b/drivers/char/rio/selftest.h
@@ -38,36 +38,36 @@
** 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;
+ 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
+ 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
+ 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_ */
+#endif /* _selftests_h_ */
diff --git a/drivers/char/rio/space.h b/drivers/char/rio/space.h
index 72398d34205..1f12690f9d1 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
index fdc73139357..e1c6f1160df 100644
--- a/drivers/char/rio/sysmap.h
+++ b/drivers/char/rio/sysmap.h
@@ -37,27 +37,26 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1" ;
+static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1";
#endif
#endif
-#define SYSTEM_MAP_LEN 64 /* Len of System Map array */
+#define SYSTEM_MAP_LEN 64 /* Len of System Map array */
-typedef struct SYS_MAP SYS_MAP ;
-typedef struct SYS_MAP_LINK SYS_MAP_LINK ;
+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 */
- } ;
+ 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] ;
- } ;
+ 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
index 11b31330c90..a8b5be3ca9b 100644
--- a/drivers/char/rio/timeouts.h
+++ b/drivers/char/rio/timeouts.h
@@ -37,15 +37,14 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_defaults_h_sccs = "@(#)timeouts.h 1.3" ;
+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 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 255c40d463a..d15a11dc4f7 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 2cb9dd693fa..185b889e151 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 eddf86278ab..a126c7cabac 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 55a3a0188ed..050e70ee592 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>
@@ -107,15 +108,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 +355,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 +383,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 +421,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 d3bc731fbb2..0949dcef069 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 a7f099fb7df..7cac6d05d72 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 3df7a574267..2e308657f6f 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 51810f72f1a..93998f5baff 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 5b187c895c1..71093a9fc46 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 dda30e42ec7..80a5b840e22 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 c2deac968bd..f36342ae8e7 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
@@ -422,45 +422,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 +682,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 51a07370e63..f8dd8527c6a 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 0bbfce43031..0a574bdbce3 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>
@@ -665,7 +666,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 +677,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 +690,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 +711,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 +752,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();
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 95af2a94159..0e20780d4a2 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)
/*****************************************************************************/
@@ -901,7 +901,7 @@ 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);
@@ -913,14 +913,13 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
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;
@@ -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;
@@ -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);
@@ -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 3ad758a9a1d..64bf89cb574 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 62aa0e534a6..9f1b466c4f8 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1467,6 +1467,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 +1488,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 +1501,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 +1529,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 +7047,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 +7490,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 00000000000..07c9be6a6bb
--- /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 char 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 ee5a40be9f9..960adb256fb 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 145275ebdd7..5765f672e85 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 b3d411a756f..ac2a297ce37 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 12167c04fa4..bc56df8a347 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -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 */
@@ -741,7 +741,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 +750,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 +758,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 +768,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 +776,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 +784,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 2392e404e8d..ba4582d160f 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 a9be0e8eaea..5a3870477ef 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 159882ca69d..fd3a4beaa53 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 00000000000..aedf7a8e6da
--- /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 4b1eef51ec5..eb8b5be4e24 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 4d75c261f98..4e536038874 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 19ba83635dd..d9325281e48 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 9ac6d43437b..2267c7b8179 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 435b30748e2..bc1b4a15212 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 e91268e8683..f1d9cb7feae 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 344001b45af..a6544790af6 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -438,7 +438,7 @@ config INDYDOG
config ZVM_WATCHDOG
tristate "z/VM Watchdog Timer"
- depends on WATCHDOG && ARCH_S390
+ depends on WATCHDOG && S390
help
IBM s/390 and zSeries machines running under z/VM 5.1 or later
provide a virtual watchdog timer to their guest that cause a
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index e75045fe264..3e8410b5a65 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/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
index 56d62ba7c6c..b2fc71e2085 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 eb667daee19..9dc54736e4e 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/wdt977.c b/drivers/char/watchdog/wdt977.c
index 44d49dfacbb..3843900e94c 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 969d2b4aaec..4b4d7db1ff7 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/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 71407c578af..64819aa7cac 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 3cf2b7a1234..b78489bc298 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/firmware/efivars.c b/drivers/firmware/efivars.c
index bda5bce681b..343379f23a5 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/Kconfig b/drivers/hwmon/Kconfig
index db358cfa7cb..c5829591436 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -350,6 +350,18 @@ config SENSORS_VIA686A
This driver can also be built as a module. If so, the module
will be called via686a.
+config SENSORS_VT8231
+ tristate "VT8231"
+ depends on HWMON && I2C && PCI && EXPERIMENTAL
+ select HWMON_VID
+ select I2C_ISA
+ help
+ If you say yes here then you get support for the integrated sensors
+ in the VIA VT8231 device.
+
+ This driver can also be built as a module. If so, the module
+ will be called vt8231.
+
config SENSORS_W83781D
tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
depends on HWMON && I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index f7d6a2f61ee..06d4a1d1410 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
+obj-$(CONFIG_SENSORS_VT8231) += vt8231.o
obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 8102876c7c3..665612729cb 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -126,10 +126,10 @@ static int read_only;
/* This is the driver that will be inserted */
static struct i2c_driver adm1021_driver = {
- .owner = THIS_MODULE,
- .name = "adm1021",
+ .driver = {
+ .name = "adm1021",
+ },
.id = I2C_DRIVERID_ADM1021,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adm1021_attach_adapter,
.detach_client = adm1021_detach_client,
};
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 3ec12421694..9331c56d2ba 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -118,10 +118,10 @@ static struct adm1025_data *adm1025_update_device(struct device *dev);
*/
static struct i2c_driver adm1025_driver = {
- .owner = THIS_MODULE,
- .name = "adm1025",
+ .driver = {
+ .name = "adm1025",
+ },
.id = I2C_DRIVERID_ADM1025,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adm1025_attach_adapter,
.detach_client = adm1025_detach_client,
};
@@ -287,8 +287,6 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
struct adm1025_data *data = adm1025_update_device(dev);
return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
}
-/* in1_ref is deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-static DEVICE_ATTR(in1_ref, S_IRUGO, show_vid, NULL);
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
@@ -444,8 +442,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_alarms);
- /* in1_ref is deprecated, remove after 2005-11-11 */
- device_create_file(&new_client->dev, &dev_attr_in1_ref);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index e0f56549d1d..fefe6e74fd0 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -308,9 +308,9 @@ static void adm1026_init_client(struct i2c_client *client);
static struct i2c_driver adm1026_driver = {
- .owner = THIS_MODULE,
- .name = "adm1026",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "adm1026",
+ },
.attach_adapter = adm1026_attach_adapter,
.detach_client = adm1026_detach_client,
};
@@ -1227,8 +1227,6 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, c
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
}
-/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL);
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1673,8 +1671,6 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
- /* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
- device_create_file(&new_client->dev, &dev_attr_vid);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
device_create_file(&new_client->dev, &dev_attr_alarms);
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 7c545d5eee4..d0639796608 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -105,9 +105,9 @@ static struct adm1031_data *adm1031_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver adm1031_driver = {
- .owner = THIS_MODULE,
- .name = "adm1031",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "adm1031",
+ },
.attach_adapter = adm1031_attach_adapter,
.detach_client = adm1031_detach_client,
};
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 11dc95f8a17..5ddc22fea4a 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -137,10 +137,10 @@ static struct adm9240_data *adm9240_update_device(struct device *dev);
/* driver data */
static struct i2c_driver adm9240_driver = {
- .owner = THIS_MODULE,
- .name = "adm9240",
+ .driver = {
+ .name = "adm9240",
+ },
.id = I2C_DRIVERID_ADM9240,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adm9240_attach_adapter,
.detach_client = adm9240_detach_client,
};
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 52c469722a6..ae9de63cf2e 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -217,10 +217,10 @@ static struct asb100_data *asb100_update_device(struct device *dev);
static void asb100_init_client(struct i2c_client *client);
static struct i2c_driver asb100_driver = {
- .owner = THIS_MODULE,
- .name = "asb100",
+ .driver = {
+ .name = "asb100",
+ },
.id = I2C_DRIVERID_ASB100,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = asb100_attach_adapter,
.detach_client = asb100_detach_client,
};
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 53324f56404..b0c490073c8 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -50,9 +50,9 @@ static struct atxp1_data * atxp1_update_device(struct device *dev);
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
static struct i2c_driver atxp1_driver = {
- .owner = THIS_MODULE,
- .name = "atxp1",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "atxp1",
+ },
.attach_adapter = atxp1_attach_adapter,
.detach_client = atxp1_detach_client,
};
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 34f71b7c7f3..203f9c7abb2 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -89,10 +89,10 @@ static struct ds1621_data *ds1621_update_client(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver ds1621_driver = {
- .owner = THIS_MODULE,
- .name = "ds1621",
+ .driver = {
+ .name = "ds1621",
+ },
.id = I2C_DRIVERID_DS1621,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ds1621_attach_adapter,
.detach_client = ds1621_detach_client,
};
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index a02e1c34c75..25409181d1e 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -118,10 +118,10 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value);
*/
static struct i2c_driver fscher_driver = {
- .owner = THIS_MODULE,
- .name = "fscher",
+ .driver = {
+ .name = "fscher",
+ },
.id = I2C_DRIVERID_FSCHER,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = fscher_attach_adapter,
.detach_client = fscher_detach_client,
};
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 64e4edc64f8..6d0146b5702 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -100,10 +100,10 @@ static void reset_fan_alarm(struct i2c_client *client, int nr);
* Driver data (common to all clients)
*/
static struct i2c_driver fscpos_driver = {
- .owner = THIS_MODULE,
- .name = "fscpos",
+ .driver = {
+ .name = "fscpos",
+ },
.id = I2C_DRIVERID_FSCPOS,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = fscpos_attach_adapter,
.detach_client = fscpos_detach_client,
};
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 2f178dbe3d8..9e685e3a3bc 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -151,10 +151,10 @@ static struct gl518_data *gl518_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver gl518_driver = {
- .owner = THIS_MODULE,
- .name = "gl518sm",
+ .driver = {
+ .name = "gl518sm",
+ },
.id = I2C_DRIVERID_GL518,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = gl518_attach_adapter,
.detach_client = gl518_detach_client,
};
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index c39ba123942..baee60e44b5 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -109,10 +109,10 @@ static struct gl520_data *gl520_update_device(struct device *dev);
/* Driver data */
static struct i2c_driver gl520_driver = {
- .owner = THIS_MODULE,
- .name = "gl520sm",
+ .driver = {
+ .name = "gl520sm",
+ },
.id = I2C_DRIVERID_GL520,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = gl520_attach_adapter,
.detach_client = gl520_detach_client,
};
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 312769ad4da..e497274916c 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -49,20 +49,22 @@
. . . .
11110 = 0.800 V
11111 = 0.000 V (off)
+
+ The 17 specification is in fact Intel Mobile Voltage Positioning -
+ (IMVP-II). You can find more information in the datasheet of Max1718
+ http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
+
*/
/* vrm is the VRM/VRD document version multiplied by 10.
val is the 4-, 5- or 6-bit VID code.
Returned value is in mV to avoid floating point in the kernel. */
-int vid_from_reg(int val, int vrm)
+int vid_from_reg(int val, u8 vrm)
{
int vid;
switch(vrm) {
- case 0:
- return 0;
-
case 100: /* VRD 10.0 */
if((val & 0x1f) == 0x1f)
return 0;
@@ -91,10 +93,16 @@ int vid_from_reg(int val, int vrm)
case 84: /* VRM 8.4 */
val &= 0x0f;
/* fall through */
- default: /* VRM 8.2 */
+ case 82: /* VRM 8.2 */
return(val == 0x1f ? 0 :
val & 0x10 ? 5100 - (val) * 100 :
2050 - (val) * 50);
+ case 17: /* Intel IMVP-II */
+ return(val & 0x10 ? 975 - (val & 0xF) * 25 :
+ 1750 - val * 50);
+ default: /* report 0 for unknown */
+ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
+ return 0;
}
}
@@ -108,30 +116,36 @@ struct vrm_model {
u8 vendor;
u8 eff_family;
u8 eff_model;
- int vrm_type;
+ u8 eff_stepping;
+ u8 vrm_type;
};
#define ANY 0xFF
#ifdef CONFIG_X86
+/* the stepping parameter is highest acceptable stepping for current line */
+
static struct vrm_model vrm_models[] = {
- {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
- {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
- {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
- {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* Tualatin */
- {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
- {X86_VENDOR_INTEL, 0x7, ANY, 0}, /* Itanium */
- {X86_VENDOR_INTEL, 0xF, 0x0, 90}, /* P4 */
- {X86_VENDOR_INTEL, 0xF, 0x1, 90}, /* P4 Willamette */
- {X86_VENDOR_INTEL, 0xF, 0x2, 90}, /* P4 Northwood */
- {X86_VENDOR_INTEL, 0xF, 0x3, 100}, /* P4 Prescott */
- {X86_VENDOR_INTEL, 0xF, 0x4, 100}, /* P4 Prescott */
- {X86_VENDOR_INTEL, 0x10,ANY, 0}, /* Itanium 2 */
- {X86_VENDOR_UNKNOWN, ANY, ANY, 0} /* stop here */
+ {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
+ {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */
+ {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */
+ {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
+ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */
+ {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */
+ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */
+ {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */
+ {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */
+ {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */
+ {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */
+ {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */
+ {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */
+ {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */
+ {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */
+ {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */
};
-static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
{
int i = 0;
@@ -139,7 +153,8 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
if (vrm_models[i].vendor==vendor)
if ((vrm_models[i].eff_family==eff_family)
&& ((vrm_models[i].eff_model==eff_model) ||
- (vrm_models[i].eff_model==ANY)))
+ (vrm_models[i].eff_model==ANY)) &&
+ (eff_stepping <= vrm_models[i].eff_stepping))
return vrm_models[i].vrm_type;
i++;
}
@@ -147,12 +162,11 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
return 0;
}
-int vid_which_vrm(void)
+u8 vid_which_vrm(void)
{
struct cpuinfo_x86 *c = cpu_data;
u32 eax;
- u8 eff_family, eff_model;
- int vrm_ret;
+ u8 eff_family, eff_model, eff_stepping, vrm_ret;
if (c->x86 < 6) /* Any CPU with family lower than 6 */
return 0; /* doesn't have VID and/or CPUID */
@@ -160,20 +174,21 @@ int vid_which_vrm(void)
eax = cpuid_eax(1);
eff_family = ((eax & 0x00000F00)>>8);
eff_model = ((eax & 0x000000F0)>>4);
+ eff_stepping = eax & 0xF;
if (eff_family == 0xF) { /* use extended model & family */
eff_family += ((eax & 0x00F00000)>>20);
eff_model += ((eax & 0x000F0000)>>16)<<4;
}
- vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+ vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
if (vrm_ret == 0)
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
"x86 CPU\n");
return vrm_ret;
}
-/* and now something completely different for the non-x86 world */
+/* and now for something completely different for the non-x86 world */
#else
-int vid_which_vrm(void)
+u8 vid_which_vrm(void)
{
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
return 0;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index a61f5d00f10..0da7c9c508c 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -213,7 +213,7 @@ struct it87_data {
u8 sensor; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
- int vrm;
+ u8 vrm;
u32 alarms; /* Register encoding, combined */
u8 fan_main_ctrl; /* Register value */
u8 manual_pwm_ctl[3]; /* manual PWM value set by user */
@@ -234,17 +234,18 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data);
static struct i2c_driver it87_driver = {
- .owner = THIS_MODULE,
- .name = "it87",
+ .driver = {
+ .name = "it87",
+ },
.id = I2C_DRIVERID_IT87,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = it87_attach_adapter,
.detach_client = it87_detach_client,
};
static struct i2c_driver it87_isa_driver = {
- .owner = THIS_MODULE,
- .name = "it87-isa",
+ .driver = {
+ .name = "it87-isa",
+ },
.attach_adapter = it87_isa_attach_adapter,
.detach_client = it87_detach_client,
};
@@ -668,7 +669,7 @@ static ssize_t
show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf, "%ld\n", (long) data->vrm);
+ return sprintf(buf, "%u\n", data->vrm);
}
static ssize_t
store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -761,7 +762,8 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
+ if (!request_region(address, IT87_EXTENT,
+ it87_isa_driver.driver.name))
goto ERROR0;
/* For now, we presume we have a valid client. We create the
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 954ec249724..6b1aa7ef552 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -139,9 +139,9 @@ static void lm63_init_client(struct i2c_client *client);
*/
static struct i2c_driver lm63_driver = {
- .owner = THIS_MODULE,
- .name = "lm63",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "lm63",
+ },
.attach_adapter = lm63_attach_adapter,
.detach_client = lm63_detach_client,
};
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index d70f4c8fc1e..74ca2c8c61c 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -66,10 +66,10 @@ static struct lm75_data *lm75_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver lm75_driver = {
- .owner = THIS_MODULE,
- .name = "lm75",
+ .driver = {
+ .name = "lm75",
+ },
.id = I2C_DRIVERID_LM75,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm75_attach_adapter,
.detach_client = lm75_detach_client,
};
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 9380fda7dcd..a2f420d01fb 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -74,9 +74,9 @@ static struct lm77_data *lm77_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver lm77_driver = {
- .owner = THIS_MODULE,
- .name = "lm77",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "lm77",
+ },
.attach_adapter = lm77_attach_adapter,
.detach_client = lm77_detach_client,
};
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 78cdd506439..e404001e20d 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -164,17 +164,18 @@ static void lm78_init_client(struct i2c_client *client);
static struct i2c_driver lm78_driver = {
- .owner = THIS_MODULE,
- .name = "lm78",
+ .driver = {
+ .name = "lm78",
+ },
.id = I2C_DRIVERID_LM78,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm78_attach_adapter,
.detach_client = lm78_detach_client,
};
static struct i2c_driver lm78_isa_driver = {
- .owner = THIS_MODULE,
- .name = "lm78-isa",
+ .driver = {
+ .name = "lm78-isa",
+ },
.attach_adapter = lm78_isa_attach_adapter,
.detach_client = lm78_detach_client,
};
@@ -497,7 +498,7 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
if (!request_region(address, LM78_EXTENT,
- lm78_isa_driver.name)) {
+ lm78_isa_driver.driver.name)) {
err = -EBUSY;
goto ERROR0;
}
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index c359fdea211..c9a7cdea7bd 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -143,10 +143,10 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
*/
static struct i2c_driver lm80_driver = {
- .owner = THIS_MODULE,
- .name = "lm80",
+ .driver = {
+ .name = "lm80",
+ },
.id = I2C_DRIVERID_LM80,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm80_attach_adapter,
.detach_client = lm80_detach_client,
};
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 9a70611a9f6..26dfa9e216c 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -124,10 +124,10 @@ static struct lm83_data *lm83_update_device(struct device *dev);
*/
static struct i2c_driver lm83_driver = {
- .owner = THIS_MODULE,
- .name = "lm83",
+ .driver = {
+ .name = "lm83",
+ },
.id = I2C_DRIVERID_LM83,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm83_attach_adapter,
.detach_client = lm83_detach_client,
};
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index d1070ed2bee..7389a012754 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -380,10 +380,10 @@ static void lm85_init_client(struct i2c_client *client);
static struct i2c_driver lm85_driver = {
- .owner = THIS_MODULE,
- .name = "lm85",
+ .driver = {
+ .name = "lm85",
+ },
.id = I2C_DRIVERID_LM85,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm85_attach_adapter,
.detach_client = lm85_detach_client,
};
@@ -443,7 +443,17 @@ show_fan_offset(4);
static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+ int vid;
+
+ if (data->type == adt7463 && (data->vid & 0x80)) {
+ /* 6-pin VID (VRM 10) */
+ vid = vid_from_reg(data->vid & 0x3f, data->vrm);
+ } else {
+ /* 5-pin VID (VRM 9) */
+ vid = vid_from_reg(data->vid & 0x1f, data->vrm);
+ }
+
+ return sprintf(buf, "%d\n", vid);
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
@@ -1176,17 +1186,14 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
device_create_file(&new_client->dev, &dev_attr_in1_input);
device_create_file(&new_client->dev, &dev_attr_in2_input);
device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
device_create_file(&new_client->dev, &dev_attr_in0_min);
device_create_file(&new_client->dev, &dev_attr_in1_min);
device_create_file(&new_client->dev, &dev_attr_in2_min);
device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
device_create_file(&new_client->dev, &dev_attr_in0_max);
device_create_file(&new_client->dev, &dev_attr_in1_max);
device_create_file(&new_client->dev, &dev_attr_in2_max);
device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
device_create_file(&new_client->dev, &dev_attr_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp3_input);
@@ -1224,6 +1231,15 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit);
device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit);
+ /* The ADT7463 has an optional VRM 10 mode where pin 21 is used
+ as a sixth digital VID input rather than an analog input. */
+ data->vid = lm85_read_value(new_client, LM85_REG_VID);
+ if (!(kind == adt7463 && (data->vid & 0x80))) {
+ device_create_file(&new_client->dev, &dev_attr_in4_input);
+ device_create_file(&new_client->dev, &dev_attr_in4_min);
+ device_create_file(&new_client->dev, &dev_attr_in4_max);
+ }
+
return 0;
/* Error out and cleanup code */
@@ -1382,11 +1398,18 @@ static struct lm85_data *lm85_update_device(struct device *dev)
irrelevant. So it is left in 4*/
data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
- for (i = 0; i <= 4; ++i) {
+ data->vid = lm85_read_value(client, LM85_REG_VID);
+
+ for (i = 0; i <= 3; ++i) {
data->in[i] =
lm85_read_value(client, LM85_REG_IN(i));
}
+ if (!(data->type == adt7463 && (data->vid & 0x80))) {
+ data->in[4] = lm85_read_value(client,
+ LM85_REG_IN(4));
+ }
+
for (i = 0; i <= 3; ++i) {
data->fan[i] =
lm85_read_value(client, LM85_REG_FAN(i));
@@ -1450,13 +1473,20 @@ static struct lm85_data *lm85_update_device(struct device *dev)
/* Things that don't change often */
dev_dbg(&client->dev, "Reading config values\n");
- for (i = 0; i <= 4; ++i) {
+ for (i = 0; i <= 3; ++i) {
data->in_min[i] =
lm85_read_value(client, LM85_REG_IN_MIN(i));
data->in_max[i] =
lm85_read_value(client, LM85_REG_IN_MAX(i));
}
+ if (!(data->type == adt7463 && (data->vid & 0x80))) {
+ data->in_min[4] = lm85_read_value(client,
+ LM85_REG_IN_MIN(4));
+ data->in_max[4] = lm85_read_value(client,
+ LM85_REG_IN_MAX(4));
+ }
+
if ( data->type == emc6d100 ) {
for (i = 5; i <= 7; ++i) {
data->in_min[i] =
@@ -1478,8 +1508,6 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_TEMP_MAX(i));
}
- data->vid = lm85_read_value(client, LM85_REG_VID);
-
for (i = 0; i <= 2; ++i) {
int val ;
data->autofan[i].config =
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index eeec1817786..6ba34c302d8 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -161,10 +161,10 @@ static struct lm87_data *lm87_update_device(struct device *dev);
*/
static struct i2c_driver lm87_driver = {
- .owner = THIS_MODULE,
- .name = "lm87",
+ .driver = {
+ .name = "lm87",
+ },
.id = I2C_DRIVERID_LM87,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm87_attach_adapter,
.detach_client = lm87_detach_client,
};
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 83cf2e1b09f..5679464447c 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -186,10 +186,10 @@ static struct lm90_data *lm90_update_device(struct device *dev);
*/
static struct i2c_driver lm90_driver = {
- .owner = THIS_MODULE,
- .name = "lm90",
+ .driver = {
+ .name = "lm90",
+ },
.id = I2C_DRIVERID_LM90,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm90_attach_adapter,
.detach_client = lm90_detach_client,
};
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 7a4b3701ed1..b0c4cb730a7 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -410,10 +410,10 @@ static int lm92_detach_client(struct i2c_client *client)
*/
static struct i2c_driver lm92_driver = {
- .owner = THIS_MODULE,
- .name = "lm92",
+ .driver = {
+ .name = "lm92",
+ },
.id = I2C_DRIVERID_LM92,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm92_attach_adapter,
.detach_client = lm92_detach_client,
};
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 69e7e125683..3abe330b22c 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -90,9 +90,9 @@ static struct max1619_data *max1619_update_device(struct device *dev);
*/
static struct i2c_driver max1619_driver = {
- .owner = THIS_MODULE,
- .name = "max1619",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "max1619",
+ },
.attach_adapter = max1619_attach_adapter,
.detach_client = max1619_detach_client,
};
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 17f745a23d0..f161e88e3bb 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -236,8 +236,9 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
*/
static struct i2c_driver pc87360_driver = {
- .owner = THIS_MODULE,
- .name = "pc87360",
+ .driver = {
+ .name = "pc87360",
+ },
.attach_adapter = pc87360_detect,
.detach_client = pc87360_detach_client,
};
@@ -798,7 +799,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
for (i = 0; i < 3; i++) {
if (((data->address[i] = extra_isa[i]))
&& !request_region(extra_isa[i], PC87360_EXTENT,
- pc87360_driver.name)) {
+ pc87360_driver.driver.name)) {
dev_err(&new_client->dev, "Region 0x%x-0x%x already "
"in use!\n", extra_isa[i],
extra_isa[i]+PC87360_EXTENT-1);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 9c6cadec108..8be5189d9bd 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -198,8 +198,9 @@ static struct sis5595_data *sis5595_update_device(struct device *dev);
static void sis5595_init_client(struct i2c_client *client);
static struct i2c_driver sis5595_driver = {
- .owner = THIS_MODULE,
- .name = "sis5595",
+ .driver = {
+ .name = "sis5595",
+ },
.attach_adapter = sis5595_detect,
.detach_client = sis5595_detach_client,
};
@@ -484,7 +485,8 @@ static int sis5595_detect(struct i2c_adapter *adapter)
if (force_addr)
address = force_addr & ~(SIS5595_EXTENT - 1);
/* Reserve the ISA region */
- if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
+ if (!request_region(address, SIS5595_EXTENT,
+ sis5595_driver.driver.name)) {
err = -EBUSY;
goto exit;
}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 2a3e21b5b6b..8663bbbe97f 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -226,8 +226,9 @@ static int smsc47b397_detach_client(struct i2c_client *client)
static int smsc47b397_detect(struct i2c_adapter *adapter);
static struct i2c_driver smsc47b397_driver = {
- .owner = THIS_MODULE,
- .name = "smsc47b397",
+ .driver = {
+ .name = "smsc47b397",
+ },
.attach_adapter = smsc47b397_detect,
.detach_client = smsc47b397_detach_client,
};
@@ -238,7 +239,8 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
struct smsc47b397_data *data;
int err = 0;
- if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+ if (!request_region(address, SMSC_EXTENT,
+ smsc47b397_driver.driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n",
address);
return -EBUSY;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 5905c1af88f..d1e3ec0fe4d 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -126,8 +126,9 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static struct i2c_driver smsc47m1_driver = {
- .owner = THIS_MODULE,
- .name = "smsc47m1",
+ .driver = {
+ .name = "smsc47m1",
+ },
.attach_adapter = smsc47m1_detect,
.detach_client = smsc47m1_detach_client,
};
@@ -394,7 +395,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
int err = 0;
int fan1, fan2, pwm1, pwm2;
- if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
+ if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
return -EBUSY;
}
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 6f696f89717..cb01848729b 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -572,8 +572,9 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/* The driver. I choose to use type i2c_driver, as at is identical to both
smbus_driver and isa_driver, and clients could be of either kind */
static struct i2c_driver via686a_driver = {
- .owner = THIS_MODULE,
- .name = "via686a",
+ .driver = {
+ .name = "via686a",
+ },
.attach_adapter = via686a_detect,
.detach_client = via686a_detach_client,
};
@@ -615,7 +616,8 @@ static int via686a_detect(struct i2c_adapter *adapter)
}
/* Reserve the ISA region */
- if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
+ if (!request_region(address, VIA686A_EXTENT,
+ via686a_driver.driver.name)) {
dev_err(&adapter->dev, "region 0x%x already in use!\n",
address);
return -ENODEV;
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
new file mode 100644
index 00000000000..3eb08f004c0
--- /dev/null
+++ b/drivers/hwmon/vt8231.c
@@ -0,0 +1,862 @@
+/*
+ vt8231.c - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+
+ Copyright (c) 2005 Roger Lucas <roger@planbit.co.uk>
+ Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Aaron M. Marsh <amarsh@sdf.lonestar.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Supports VIA VT8231 South Bridge embedded sensors
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <asm/io.h>
+
+static int force_addr;
+module_param(force_addr, int, 0);
+MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors");
+
+/* Device address
+ Note that we can't determine the ISA address until we have initialized
+ our module */
+static unsigned short isa_address;
+
+#define VT8231_EXTENT 0x80
+#define VT8231_BASE_REG 0x70
+#define VT8231_ENABLE_REG 0x74
+
+/* The VT8231 registers
+
+ The reset value for the input channel configuration is used (Reg 0x4A=0x07)
+ which sets the selected inputs marked with '*' below if multiple options are
+ possible:
+
+ Voltage Mode Temperature Mode
+ Sensor Linux Id Linux Id VIA Id
+ -------- -------- -------- ------
+ CPU Diode N/A temp1 0
+ UIC1 in0 temp2 * 1
+ UIC2 in1 * temp3 2
+ UIC3 in2 * temp4 3
+ UIC4 in3 * temp5 4
+ UIC5 in4 * temp6 5
+ 3.3V in5 N/A
+
+ Note that the BIOS may set the configuration register to a different value
+ to match the motherboard configuration.
+*/
+
+/* fans numbered 0-1 */
+#define VT8231_REG_FAN_MIN(nr) (0x3b + (nr))
+#define VT8231_REG_FAN(nr) (0x29 + (nr))
+
+/* Voltage inputs numbered 0-5 */
+
+static const u8 regvolt[] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26 };
+static const u8 regvoltmax[] = { 0x3d, 0x2b, 0x2d, 0x2f, 0x31, 0x33 };
+static const u8 regvoltmin[] = { 0x3e, 0x2c, 0x2e, 0x30, 0x32, 0x34 };
+
+/* Temperatures are numbered 1-6 according to the Linux kernel specification.
+**
+** In the VIA datasheet, however, the temperatures are numbered from zero.
+** Since it is important that this driver can easily be compared to the VIA
+** datasheet, we will use the VIA numbering within this driver and map the
+** kernel sysfs device name to the VIA number in the sysfs callback.
+*/
+
+#define VT8231_REG_TEMP_LOW01 0x49
+#define VT8231_REG_TEMP_LOW25 0x4d
+
+static const u8 regtemp[] = { 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25 };
+static const u8 regtempmax[] = { 0x39, 0x3d, 0x2b, 0x2d, 0x2f, 0x31 };
+static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
+
+#define TEMP_FROM_REG(reg) (((253 * 4 - (reg)) * 550 + 105) / 210)
+#define TEMP_MAXMIN_FROM_REG(reg) (((253 - (reg)) * 2200 + 105) / 210)
+#define TEMP_MAXMIN_TO_REG(val) (253 - ((val) * 210 + 1100) / 2200)
+
+#define VT8231_REG_CONFIG 0x40
+#define VT8231_REG_ALARM1 0x41
+#define VT8231_REG_ALARM2 0x42
+#define VT8231_REG_FANDIV 0x47
+#define VT8231_REG_UCH_CONFIG 0x4a
+#define VT8231_REG_TEMP1_CONFIG 0x4b
+#define VT8231_REG_TEMP2_CONFIG 0x4c
+
+/* temps 0-5 as numbered in VIA datasheet - see later for mapping to Linux
+** numbering
+*/
+#define ISTEMP(i, ch_config) ((i) == 0 ? 1 : \
+ ((ch_config) >> ((i)+1)) & 0x01)
+/* voltages 0-5 */
+#define ISVOLT(i, ch_config) ((i) == 5 ? 1 : \
+ !(((ch_config) >> ((i)+2)) & 0x01))
+
+#define DIV_FROM_REG(val) (1 << (val))
+
+/* NB The values returned here are NOT temperatures. The calibration curves
+** for the thermistor curves are board-specific and must go in the
+** sensors.conf file. Temperature sensors are actually ten bits, but the
+** VIA datasheet only considers the 8 MSBs obtained from the regtemp[]
+** register. The temperature value returned should have a magnitude of 3,
+** so we use the VIA scaling as the "true" scaling and use the remaining 2
+** LSBs as fractional precision.
+**
+** All the on-chip hardware temperature comparisons for the alarms are only
+** 8-bits wide, and compare against the 8 MSBs of the temperature. The bits
+** in the registers VT8231_REG_TEMP_LOW01 and VT8231_REG_TEMP_LOW25 are
+** ignored.
+*/
+
+/******** FAN RPM CONVERSIONS ********
+** This chip saturates back at 0, not at 255 like many the other chips.
+** So, 0 means 0 RPM
+*/
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+ if (rpm == 0)
+ return 0;
+ return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255);
+}
+
+#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div)))
+
+struct vt8231_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ struct class_device *class_dev;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ u8 in[6]; /* Register value */
+ u8 in_max[6]; /* Register value */
+ u8 in_min[6]; /* Register value */
+ u16 temp[6]; /* Register value 10 bit, right aligned */
+ u8 temp_max[6]; /* Register value */
+ u8 temp_min[6]; /* Register value */
+ u8 fan[2]; /* Register value */
+ u8 fan_min[2]; /* Register value */
+ u8 fan_div[2]; /* Register encoding, shifted right */
+ u16 alarms; /* Register encoding */
+ u8 uch_config;
+};
+
+static struct pci_dev *s_bridge;
+static int vt8231_detect(struct i2c_adapter *adapter);
+static int vt8231_detach_client(struct i2c_client *client);
+static struct vt8231_data *vt8231_update_device(struct device *dev);
+static void vt8231_init_client(struct i2c_client *client);
+
+static inline int vt8231_read_value(struct i2c_client *client, u8 reg)
+{
+ return inb_p(client->addr + reg);
+}
+
+static inline void vt8231_write_value(struct i2c_client *client, u8 reg,
+ u8 value)
+{
+ outb_p(value, client->addr + reg);
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n", ((data->in[nr] - 3) * 10000) / 958);
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n", ((data->in_min[nr] - 3) * 10000) / 958);
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n", (((data->in_max[nr] - 3) * 10000) / 958));
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
+ vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
+ vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+/* Special case for input 5 as this has 3.3V scaling built into the chip */
+static ssize_t show_in5(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ (((data->in[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t show_in5_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ (((data->in_min[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ (((data->in_max[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
+ 0, 255);
+ vt8231_write_value(client, regvoltmin[5], data->in_min[5]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
+ 0, 255);
+ vt8231_write_value(client, regvoltmax[5], data->in_max[5]);
+ up(&data->update_lock);
+ return count;
+}
+
+#define define_voltage_sysfs(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, offset)
+
+define_voltage_sysfs(0);
+define_voltage_sysfs(1);
+define_voltage_sysfs(2);
+define_voltage_sysfs(3);
+define_voltage_sysfs(4);
+
+static DEVICE_ATTR(in5_input, S_IRUGO, show_in5, NULL);
+static DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, show_in5_min, set_in5_min);
+static DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, show_in5_max, set_in5_max);
+
+/* Temperatures */
+static ssize_t show_temp0(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp[0] * 250);
+}
+
+static ssize_t show_temp0_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_max[0] * 1000);
+}
+
+static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_min[0] * 1000);
+}
+
+static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
+ vt8231_write_value(client, regtempmax[0], data->temp_max[0]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
+ vt8231_write_value(client, regtempmin[0], data->temp_min[0]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_max[nr]));
+}
+
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_min[nr]));
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
+ vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
+ vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+/* Note that these map the Linux temperature sensor numbering (1-6) to the VIA
+** temperature sensor numbering (0-5)
+*/
+#define define_temperature_sysfs(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
+ show_temp_min, set_temp_min, offset - 1)
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
+static DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
+
+define_temperature_sysfs(2);
+define_temperature_sysfs(3);
+define_temperature_sysfs(4);
+define_temperature_sysfs(5);
+define_temperature_sysfs(6);
+
+#define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \
+ &sensor_dev_attr_temp##id##_min.dev_attr, \
+ &sensor_dev_attr_temp##id##_max.dev_attr }
+#define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \
+ &sensor_dev_attr_in##id##_min.dev_attr, \
+ &sensor_dev_attr_in##id##_max.dev_attr }
+
+struct str_device_attr_table {
+ struct device_attribute *input;
+ struct device_attribute *min;
+ struct device_attribute *max;
+};
+
+static struct str_device_attr_table cfg_info_temp[] = {
+ { &dev_attr_temp1_input, &dev_attr_temp1_min, &dev_attr_temp1_max },
+ CFG_INFO_TEMP(2),
+ CFG_INFO_TEMP(3),
+ CFG_INFO_TEMP(4),
+ CFG_INFO_TEMP(5),
+ CFG_INFO_TEMP(6)
+};
+
+static struct str_device_attr_table cfg_info_volt[] = {
+ CFG_INFO_VOLT(0),
+ CFG_INFO_VOLT(1),
+ CFG_INFO_VOLT(2),
+ CFG_INFO_VOLT(3),
+ CFG_INFO_VOLT(4),
+ { &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max }
+};
+
+/* Fans */
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+ DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+ vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int nr = sensor_attr->index;
+ int old = vt8231_read_value(client, VT8231_REG_FANDIV);
+ long min = FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr]));
+
+ down(&data->update_lock);
+ switch (val) {
+ case 1: data->fan_div[nr] = 0; break;
+ case 2: data->fan_div[nr] = 1; break;
+ case 4: data->fan_div[nr] = 2; break;
+ case 8: data->fan_div[nr] = 3; break;
+ default:
+ dev_err(&client->dev, "fan_div value %ld not supported."
+ "Choose one of 1, 2, 4 or 8!\n", val);
+ up(&data->update_lock);
+ return -EINVAL;
+ }
+
+ /* Correct the fan minimum speed */
+ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+ vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+
+ old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
+ vt8231_write_value(client, VT8231_REG_FANDIV, old);
+ up(&data->update_lock);
+ return count;
+}
+
+
+#define define_fan_sysfs(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, set_fan_div, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, offset - 1)
+
+define_fan_sysfs(1);
+define_fan_sysfs(2);
+
+/* Alarms */
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->alarms);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static struct i2c_driver vt8231_driver = {
+ .driver = {
+ .name = "vt8231",
+ },
+ .attach_adapter = vt8231_detect,
+ .detach_client = vt8231_detach_client,
+};
+
+static struct pci_device_id vt8231_pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
+
+static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id);
+
+static struct pci_driver vt8231_pci_driver = {
+ .name = "vt8231",
+ .id_table = vt8231_pci_ids,
+ .probe = vt8231_pci_probe,
+};
+
+int vt8231_detect(struct i2c_adapter *adapter)
+{
+ struct i2c_client *client;
+ struct vt8231_data *data;
+ int err = 0, i;
+ u16 val;
+
+ /* 8231 requires multiple of 256 */
+ if (force_addr) {
+ isa_address = force_addr & 0xFF00;
+ dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
+ isa_address);
+ if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge,
+ VT8231_BASE_REG, isa_address))
+ return -ENODEV;
+ }
+
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(s_bridge, VT8231_ENABLE_REG, &val))
+ return -ENODEV;
+
+ if (!(val & 0x0001)) {
+ dev_warn(&adapter->dev, "enabling sensors\n");
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, VT8231_ENABLE_REG,
+ val | 0x0001))
+ return -ENODEV;
+ }
+
+ /* Reserve the ISA region */
+ if (!request_region(isa_address, VT8231_EXTENT,
+ vt8231_pci_driver.name)) {
+ dev_err(&adapter->dev, "region 0x%x already in use!\n",
+ isa_address);
+ return -ENODEV;
+ }
+
+ if (!(data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit_release;
+ }
+
+ client = &data->client;
+ i2c_set_clientdata(client, data);
+ client->addr = isa_address;
+ client->adapter = adapter;
+ client->driver = &vt8231_driver;
+ client->dev.parent = &adapter->dev;
+
+ /* Fill in the remaining client fields and put into the global list */
+ strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
+
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(client)))
+ goto exit_free;
+
+ vt8231_init_client(client);
+
+ /* Register sysfs hooks */
+ data->class_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_detach;
+ }
+
+ /* Must update device information to find out the config field */
+ data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG);
+
+ for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) {
+ if (ISTEMP(i, data->uch_config)) {
+ device_create_file(&client->dev,
+ cfg_info_temp[i].input);
+ device_create_file(&client->dev, cfg_info_temp[i].max);
+ device_create_file(&client->dev, cfg_info_temp[i].min);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) {
+ if (ISVOLT(i, data->uch_config)) {
+ device_create_file(&client->dev,
+ cfg_info_volt[i].input);
+ device_create_file(&client->dev, cfg_info_volt[i].max);
+ device_create_file(&client->dev, cfg_info_volt[i].min);
+ }
+ }
+
+ device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+
+ device_create_file(&client->dev, &dev_attr_alarms);
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+exit_free:
+ kfree(data);
+exit_release:
+ release_region(isa_address, VT8231_EXTENT);
+ return err;
+}
+
+static int vt8231_detach_client(struct i2c_client *client)
+{
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int err;
+
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client))) {
+ return err;
+ }
+
+ release_region(client->addr, VT8231_EXTENT);
+ kfree(data);
+
+ return 0;
+}
+
+static void vt8231_init_client(struct i2c_client *client)
+{
+ vt8231_write_value(client, VT8231_REG_TEMP1_CONFIG, 0);
+ vt8231_write_value(client, VT8231_REG_TEMP2_CONFIG, 0);
+}
+
+static struct vt8231_data *vt8231_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int i;
+ u16 low;
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ for (i = 0; i < 6; i++) {
+ if (ISVOLT(i, data->uch_config)) {
+ data->in[i] = vt8231_read_value(client,
+ regvolt[i]);
+ data->in_min[i] = vt8231_read_value(client,
+ regvoltmin[i]);
+ data->in_max[i] = vt8231_read_value(client,
+ regvoltmax[i]);
+ }
+ }
+ for (i = 0; i < 2; i++) {
+ data->fan[i] = vt8231_read_value(client,
+ VT8231_REG_FAN(i));
+ data->fan_min[i] = vt8231_read_value(client,
+ VT8231_REG_FAN_MIN(i));
+ }
+
+ low = vt8231_read_value(client, VT8231_REG_TEMP_LOW01);
+ low = (low >> 6) | ((low & 0x30) >> 2)
+ | (vt8231_read_value(client, VT8231_REG_TEMP_LOW25) << 4);
+ for (i = 0; i < 6; i++) {
+ if (ISTEMP(i, data->uch_config)) {
+ data->temp[i] = (vt8231_read_value(client,
+ regtemp[i]) << 2)
+ | ((low >> (2 * i)) & 0x03);
+ data->temp_max[i] = vt8231_read_value(client,
+ regtempmax[i]);
+ data->temp_min[i] = vt8231_read_value(client,
+ regtempmin[i]);
+ }
+ }
+
+ i = vt8231_read_value(client, VT8231_REG_FANDIV);
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = i >> 6;
+ data->alarms = vt8231_read_value(client, VT8231_REG_ALARM1) |
+ (vt8231_read_value(client, VT8231_REG_ALARM2) << 8);
+
+ /* Set alarm flags correctly */
+ if (!data->fan[0] && data->fan_min[0]) {
+ data->alarms |= 0x40;
+ } else if (data->fan[0] && !data->fan_min[0]) {
+ data->alarms &= ~0x40;
+ }
+
+ if (!data->fan[1] && data->fan_min[1]) {
+ data->alarms |= 0x80;
+ } else if (data->fan[1] && !data->fan_min[1]) {
+ data->alarms &= ~0x80;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ u16 val;
+
+ if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG,
+ &val))
+ return -ENODEV;
+
+ isa_address = val & ~(VT8231_EXTENT - 1);
+ if (isa_address == 0 && force_addr == 0) {
+ dev_err(&dev->dev, "base address not set -\
+ upgrade BIOS or use force_addr=0xaddr\n");
+ return -ENODEV;
+ }
+
+ s_bridge = pci_dev_get(dev);
+
+ if (i2c_isa_add_driver(&vt8231_driver)) {
+ pci_dev_put(s_bridge);
+ s_bridge = NULL;
+ }
+
+ /* Always return failure here. This is to allow other drivers to bind
+ * to this pci device. We don't really want to have control over the
+ * pci device, we only wanted to read as few register values from it.
+ */
+ return -ENODEV;
+}
+
+static int __init sm_vt8231_init(void)
+{
+ return pci_register_driver(&vt8231_pci_driver);
+}
+
+static void __exit sm_vt8231_exit(void)
+{
+ pci_unregister_driver(&vt8231_pci_driver);
+ if (s_bridge != NULL) {
+ i2c_isa_del_driver(&vt8231_driver);
+ pci_dev_put(s_bridge);
+ s_bridge = NULL;
+ }
+}
+
+MODULE_AUTHOR("Roger Lucas <roger@planbit.co.uk>");
+MODULE_DESCRIPTION("VT8231 sensors");
+MODULE_LICENSE("GPL");
+
+module_init(sm_vt8231_init);
+module_exit(sm_vt8231_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index eee22a57e92..12d79f5e490 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -676,7 +676,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
int i, err = 0;
if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
- w83627ehf_driver.name)) {
+ w83627ehf_driver.driver.name)) {
err = -EBUSY;
goto exit;
}
@@ -785,8 +785,9 @@ static int w83627ehf_detach_client(struct i2c_client *client)
}
static struct i2c_driver w83627ehf_driver = {
- .owner = THIS_MODULE,
- .name = "w83627ehf",
+ .driver = {
+ .name = "w83627ehf",
+ },
.attach_adapter = w83627ehf_detect,
.detach_client = w83627ehf_detach_client,
};
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bbb3dcde146..7ea441d4da6 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -332,8 +332,9 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev);
static void w83627hf_init_client(struct i2c_client *client);
static struct i2c_driver w83627hf_driver = {
- .owner = THIS_MODULE,
- .name = "w83627hf",
+ .driver = {
+ .name = "w83627hf",
+ },
.attach_adapter = w83627hf_detect,
.detach_client = w83627hf_detach_client,
};
@@ -1009,7 +1010,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
address = force_addr & WINB_ALIGNMENT;
if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
- w83627hf_driver.name)) {
+ w83627hf_driver.driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -1122,11 +1123,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
if (kind != w83697hf)
device_create_file_temp(new_client, 3);
- if (kind != w83697hf)
+ if (kind != w83697hf && data->vid != 0xff) {
device_create_file_vid(new_client);
-
- if (kind != w83697hf)
device_create_file_vrm(new_client);
+ }
device_create_file_fan_div(new_client, 1);
device_create_file_fan_div(new_client, 2);
@@ -1232,7 +1232,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client)
/* Make sure the pins are configured for input
There must be at least five (VRM 9), and possibly 6 (VRM 10) */
- sel = superio_inb(W83627THF_GPIO5_IOSR);
+ sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
if ((sel & 0x1f) != 0x1f) {
dev_dbg(&client->dev, "GPIO5 not configured for VID "
"function\n");
@@ -1323,19 +1323,18 @@ static void w83627hf_init_client(struct i2c_client *client)
int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
} else if (w83627thf == data->type) {
- data->vid = w83627thf_read_gpio5(client) & 0x3f;
+ data->vid = w83627thf_read_gpio5(client);
}
/* Read VRM & OVT Config only once */
if (w83627thf == data->type || w83637hf == data->type) {
data->vrm_ovt =
w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
- data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
- } else {
- /* Convert VID to voltage based on default VRM */
- data->vrm = vid_which_vrm();
}
+ /* Convert VID to voltage based on VRM */
+ data->vrm = vid_which_vrm();
+
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
for (i = 1; i <= 3; i++) {
if (!(tmp & BIT_SCFG1[i - 1])) {
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index ffdb3a03e2b..557114872f3 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -269,17 +269,18 @@ static struct w83781d_data *w83781d_update_device(struct device *dev);
static void w83781d_init_client(struct i2c_client *client);
static struct i2c_driver w83781d_driver = {
- .owner = THIS_MODULE,
- .name = "w83781d",
+ .driver = {
+ .name = "w83781d",
+ },
.id = I2C_DRIVERID_W83781D,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = w83781d_attach_adapter,
.detach_client = w83781d_detach_client,
};
static struct i2c_driver w83781d_isa_driver = {
- .owner = THIS_MODULE,
- .name = "w83781d-isa",
+ .driver = {
+ .name = "w83781d-isa",
+ },
.attach_adapter = w83781d_isa_attach_adapter,
.detach_client = w83781d_detach_client,
};
@@ -1012,7 +1013,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa)
if (!request_region(address, W83781D_EXTENT,
- w83781d_isa_driver.name)) {
+ w83781d_isa_driver.driver.name)) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 1ba07263036..b176bf0c4c7 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -269,7 +269,6 @@ DIV_TO_REG(long val)
struct w83792d_data {
struct i2c_client client;
struct class_device *class_dev;
- struct semaphore lock;
enum chips type;
struct semaphore update_lock;
@@ -282,7 +281,7 @@ struct w83792d_data {
u8 in[9]; /* Register value */
u8 in_max[9]; /* Register value */
u8 in_min[9]; /* Register value */
- u8 low_bits[2]; /* Additional resolution to voltage in0-6 */
+ u16 low_bits; /* Additional resolution to voltage in6-0 */
u8 fan[7]; /* Register value */
u8 fan_min[7]; /* Register value */
u8 temp1[3]; /* current, over, thyst */
@@ -317,45 +316,17 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
static void w83792d_init_client(struct i2c_client *client);
static struct i2c_driver w83792d_driver = {
- .owner = THIS_MODULE,
- .name = "w83792d",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "w83792d",
+ },
.attach_adapter = w83792d_attach_adapter,
.detach_client = w83792d_detach_client,
};
-static long in_count_from_reg(int nr, struct w83792d_data *data)
+static inline long in_count_from_reg(int nr, struct w83792d_data *data)
{
- u16 vol_count = data->in[nr];
- u16 low_bits = 0;
- vol_count = (vol_count << 2);
- switch (nr)
- {
- case 0: /* vin0 */
- low_bits = (data->low_bits[0]) & 0x03;
- break;
- case 1: /* vin1 */
- low_bits = ((data->low_bits[0]) & 0x0c) >> 2;
- break;
- case 2: /* vin2 */
- low_bits = ((data->low_bits[0]) & 0x30) >> 4;
- break;
- case 3: /* vin3 */
- low_bits = ((data->low_bits[0]) & 0xc0) >> 6;
- break;
- case 4: /* vin4 */
- low_bits = (data->low_bits[1]) & 0x03;
- break;
- case 5: /* vin5 */
- low_bits = ((data->low_bits[1]) & 0x0c) >> 2;
- break;
- case 6: /* vin6 */
- low_bits = ((data->low_bits[1]) & 0x30) >> 4;
- default:
- break;
- }
- vol_count = vol_count | low_bits;
- return vol_count;
+ /* in7 and in8 do not have low bits, but the formula still works */
+ return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
}
/* following are the sysfs callback functions */
@@ -1192,7 +1163,6 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
- init_MUTEX(&data->lock);
new_client->adapter = adapter;
new_client->driver = &w83792d_driver;
new_client->flags = 0;
@@ -1243,7 +1213,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR1;
}
val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
- if (val1 == 0x7a && address >= 0x2c) {
+ if (val1 == 0x7a) {
kind = w83792d;
} else {
if (kind == 0)
@@ -1416,26 +1386,17 @@ w83792d_detach_client(struct i2c_client *client)
return 0;
}
-/* The SMBus locks itself, usually, but nothing may access the Winbond between
- bank switches. ISA access must always be locked explicitly!
- We ignore the W83792D BUSY flag at this moment - it could lead to deadlocks,
- would slow down the W83792D access and should not be necessary.
- There are some ugly typecasts here, but the good news is - they should
- nowhere else be necessary! */
-static int
-w83792d_read_value(struct i2c_client *client, u8 reg)
+/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+ but the driver only accesses registers in bank 0, so we don't have
+ to switch banks and lock access between switches. */
+static int w83792d_read_value(struct i2c_client *client, u8 reg)
{
- int res=0;
- res = i2c_smbus_read_byte_data(client, reg);
-
- return res;
+ return i2c_smbus_read_byte_data(client, reg);
}
-static int
-w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
{
- i2c_smbus_write_byte_data(client, reg, value);
- return 0;
+ return i2c_smbus_write_byte_data(client, reg, value);
}
static void
@@ -1492,10 +1453,10 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
data->in_min[i] = w83792d_read_value(client,
W83792D_REG_IN_MIN[i]);
}
- data->low_bits[0] = w83792d_read_value(client,
- W83792D_REG_LOW_BITS1);
- data->low_bits[1] = w83792d_read_value(client,
- W83792D_REG_LOW_BITS2);
+ data->low_bits = w83792d_read_value(client,
+ W83792D_REG_LOW_BITS1) +
+ (w83792d_read_value(client,
+ W83792D_REG_LOW_BITS2) << 8);
for (i = 0; i < 7; i++) {
/* Update the Fan measured value and limits */
data->fan[i] = w83792d_read_value(client,
@@ -1506,7 +1467,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
pwm_array_tmp[i] = w83792d_read_value(client,
W83792D_REG_PWM[i]);
data->pwm[i] = pwm_array_tmp[i] & 0x0f;
- data->pwm_mode[i] = (pwm_array_tmp[i] >> 7) & 0x01;
+ data->pwm_mode[i] = pwm_array_tmp[i] >> 7;
}
reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
@@ -1607,8 +1568,8 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
}
- dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits[0]);
- dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits[1]);
+ dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff);
+ dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8);
dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
for (i=0; i<7; i++) {
dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index f495b637866..f66c0cfdeda 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -92,10 +92,10 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
*/
static struct i2c_driver w83l785ts_driver = {
- .owner = THIS_MODULE,
- .name = "w83l785ts",
+ .driver = {
+ .name = "w83l785ts",
+ },
.id = I2C_DRIVERID_W83L785TS,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = w83l785ts_attach_adapter,
.detach_client = w83l785ts_detach_client,
};
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4010fe92e72..08d5b8fed2d 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 f1df00f66c6..b44831dff68 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-i801.c b/drivers/i2c/busses/i2c-i801.c
index ac3eafa8aac..1c752ddc10e 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -468,8 +468,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
return -1;
}
- if (hwpec)
- outb_p(1, SMBAUXCTL); /* enable hardware PEC */
+ outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */
if(block)
ret = i801_block_transaction(data, read_write, size, hwpec);
@@ -478,9 +477,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
ret = i801_transaction();
}
- if (hwpec)
- outb_p(0, SMBAUXCTL); /* disable hardware PEC */
-
if(block)
return ret;
if(ret)
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 1a587253d71..87fae937e66 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -725,6 +725,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
+ adap->class = I2C_CLASS_HWMON;
adap->algo = &iic_algo;
adap->client_register = NULL;
adap->client_unregister = NULL;
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 03672c9ca40..9f2ffef4d81 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -92,15 +92,13 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
int res;
/* Add the driver to the list of i2c drivers in the driver core */
- driver->driver.name = driver->name;
- driver->driver.owner = driver->owner;
driver->driver.bus = &i2c_bus_type;
driver->driver.probe = i2c_isa_device_probe;
driver->driver.remove = i2c_isa_device_remove;
res = driver_register(&driver->driver);
if (res)
return res;
- dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name);
+ dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
/* Now look for clients */
driver->attach_adapter(&isa_adapter);
@@ -124,14 +122,14 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
if ((res = driver->detach_client(client))) {
dev_err(&isa_adapter.dev, "Failed, driver "
"%s not unregistered!\n",
- driver->name);
+ driver->driver.name);
return res;
}
}
/* Get the driver off the core list */
driver_unregister(&driver->driver);
- dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name);
+ dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->driver.name);
return 0;
}
@@ -176,7 +174,7 @@ static void __exit i2c_isa_exit(void)
list_for_each_safe(item, _n, &isa_adapter.clients) {
client = list_entry(item, struct i2c_client, list);
dev_err(&isa_adapter.dev, "Driver %s still has an active "
- "ISA client at 0x%x\n", client->driver->name,
+ "ISA client at 0x%x\n", client->driver->driver.name,
client->addr);
}
if (client != NULL)
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
deleted file mode 100644
index d61f748278f..00000000000
--- 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 c5022e1ca6f..00000000000
--- 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-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 81031eb5105..22781d84f79 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -1,6 +1,4 @@
/*
- * drivers/i2c/busses/i2c-mv64xxx.c
- *
* Driver for the i2c controller on the Marvell line of host bridges for MIPS
* and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
*
@@ -65,7 +63,6 @@ enum {
MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA,
- MV64XXX_I2C_STATE_ABORTING,
};
/* Driver actions */
@@ -85,6 +82,7 @@ struct mv64xxx_i2c_data {
int irq;
u32 state;
u32 action;
+ u32 aborting;
u32 cntl_bits;
void __iomem *reg_base;
u32 reg_base_p;
@@ -122,12 +120,6 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
return;
}
- if (drv_data->state == MV64XXX_I2C_STATE_ABORTING) {
- drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
- drv_data->state = MV64XXX_I2C_STATE_IDLE;
- return;
- }
-
/* The status from the ctlr [mostly] tells us what to do next */
switch (status) {
/* Start condition interrupt */
@@ -148,14 +140,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
/* FALLTHRU */
case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */
- if (drv_data->bytes_left > 0) {
+ if ((drv_data->bytes_left == 0)
+ || (drv_data->aborting
+ && (drv_data->byte_posn != 0))) {
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ } else {
drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
drv_data->state =
MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;
drv_data->bytes_left--;
- } else {
- drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
- drv_data->state = MV64XXX_I2C_STATE_IDLE;
}
break;
@@ -184,7 +178,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
}
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
- if (drv_data->bytes_left == 1)
+ if ((drv_data->bytes_left == 1) || drv_data->aborting)
drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK;
break;
@@ -320,6 +314,7 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
drv_data->msg = msg;
drv_data->byte_posn = 0;
drv_data->bytes_left = msg->len;
+ drv_data->aborting = 0;
drv_data->rc = 0;
drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
@@ -359,17 +354,19 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
}
if (abort && drv_data->block) {
- drv_data->state = MV64XXX_I2C_STATE_ABORTING;
+ drv_data->aborting = 1;
spin_unlock_irqrestore(&drv_data->lock, flags);
time_left = wait_event_timeout(drv_data->waitq,
!drv_data->block,
msecs_to_jiffies(drv_data->adapter.timeout));
- if (time_left <= 0) {
+ if ((time_left <= 0) && drv_data->block) {
drv_data->state = MV64XXX_I2C_STATE_IDLE;
dev_err(&drv_data->adapter.dev,
- "mv64xxx: I2C bus locked\n");
+ "mv64xxx: I2C bus locked, block: %d, "
+ "time_left: %d\n", drv_data->block,
+ (int)time_left);
}
} else
spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -510,7 +507,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_kfree;
}
- strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
+ strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
I2C_NAME_SIZE);
init_waitqueue_head(&drv_data->waitq);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 4d18e6e5f15..2d80eb26f68 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -30,6 +30,7 @@
nForce3 Pro150 MCP 00D4
nForce3 250Gb MCP 00E4
nForce4 MCP 0052
+ nForce4 MCP-04 0034
This driver supports the 2 SMBuses that are included in the MCP of the
nForce2/3/4 chipsets.
@@ -257,6 +258,7 @@ static struct pci_device_id nforce2_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
{ 0 }
};
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index f63a5377928..d702e5e0388 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -80,6 +80,14 @@ static struct adapter_parm adapter_parm[] = {
.setscl = { 0x01, DATA, 1 },
.getsda = { 0x10, STAT, 1 },
},
+ /* type 6: Barco LPT->DVI (K5800236) adapter */
+ {
+ .setsda = { 0x02, DATA, 1 },
+ .setscl = { 0x01, DATA, 1 },
+ .getsda = { 0x20, STAT, 0 },
+ .getscl = { 0x40, STAT, 0 },
+ .init = { 0xfc, DATA, 0 },
+ },
};
static int type;
@@ -91,4 +99,6 @@ MODULE_PARM_DESC(type,
" 2 = Velleman K8000 adapter\n"
" 3 = ELV adapter\n"
" 4 = ADM1032 evaluation board\n"
- " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n");
+ " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"
+ " 6 = Barco LPT->DVI (K5800236) adapter\n"
+);
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
deleted file mode 100644
index bfefe7f7a53..00000000000
--- 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 00000000000..df786eb5529
--- /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 70f7ab829d3..86e2234faf8 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 58cfd3111ef..f7d40f8e5f5 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/ds1337.c b/drivers/i2c/chips/ds1337.c
index 02682fb794c..93d483b8b77 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -52,9 +52,9 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd,
* Driver data (common to all clients)
*/
static struct i2c_driver ds1337_driver = {
- .owner = THIS_MODULE,
- .name = "ds1337",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "ds1337",
+ },
.attach_adapter = ds1337_attach_adapter,
.detach_client = ds1337_detach_client,
.command = ds1337_command,
@@ -337,13 +337,38 @@ exit:
static void ds1337_init_client(struct i2c_client *client)
{
- s32 val;
+ u8 status, control;
- /* Ensure that device is set in 24-hour mode */
- val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
- if ((val >= 0) && (val & (1 << 6)))
- i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
- val & 0x3f);
+ /* On some boards, the RTC isn't configured by boot firmware.
+ * Handle that case by starting/configuring the RTC now.
+ */
+ status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+ control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+
+ if ((status & 0x80) || (control & 0x80)) {
+ /* RTC not running */
+ u8 buf[16];
+ struct i2c_msg msg[1];
+
+ dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
+
+ /* Initialize all, including STATUS and CONTROL to zero */
+ memset(buf, 0, sizeof(buf));
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = sizeof(buf);
+ msg[0].buf = &buf[0];
+
+ i2c_transfer(client->adapter, msg, 1);
+ } else {
+ /* Running: ensure that device is set in 24-hour mode */
+ s32 val;
+
+ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+ if ((val >= 0) && (val & (1 << 6)))
+ i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+ val & 0x3f);
+ }
}
static int ds1337_detach_client(struct i2c_client *client)
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index da488b735ab..0710b9da9d5 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -232,10 +232,10 @@ static int ds1374_detach(struct i2c_client *client)
}
static struct i2c_driver ds1374_driver = {
- .owner = THIS_MODULE,
- .name = DS1374_DRV_NAME,
+ .driver = {
+ .name = DS1374_DRV_NAME,
+ },
.id = I2C_DRIVERID_DS1374,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ds1374_attach,
.detach_client = ds1374_detach,
};
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 4baf573fa04..41116b7947f 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -68,10 +68,10 @@ static int eeprom_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver eeprom_driver = {
- .owner = THIS_MODULE,
- .name = "eeprom",
+ .driver = {
+ .name = "eeprom",
+ },
.id = I2C_DRIVERID_EEPROM,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = eeprom_attach_adapter,
.detach_client = eeprom_detach_client,
};
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index d2a100d7783..1251c7fc18d 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -1632,11 +1632,11 @@ static int isp1301_scan_bus(struct i2c_adapter *bus)
}
static struct i2c_driver isp1301_driver = {
- .owner = THIS_MODULE,
- .name = "isp1301_omap",
+ .driver = {
+ .name = "isp1301_omap",
+ },
.id = 1301, /* FIXME "official", i2c-ids.h */
.class = I2C_CLASS_HWMON,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = isp1301_scan_bus,
.detach_client = isp1301_detach_client,
};
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 3df309ae44a..2dc3d48375f 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -211,10 +211,10 @@ m41t00_detach(struct i2c_client *client)
}
static struct i2c_driver m41t00_driver = {
- .owner = THIS_MODULE,
- .name = M41T00_DRV_NAME,
+ .driver = {
+ .name = M41T00_DRV_NAME,
+ },
.id = I2C_DRIVERID_STM41T00,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = m41t00_attach,
.detach_client = m41t00_detach,
};
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index b376a006883..6d3ff584155 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -67,9 +67,9 @@ static int max6875_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver max6875_driver = {
- .owner = THIS_MODULE,
- .name = "max6875",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "max6875",
+ },
.attach_adapter = max6875_attach_adapter,
.detach_client = max6875_detach_client,
};
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 59a93034622..54b6e6a4bee 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -38,9 +38,9 @@ static int pca9539_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pca9539_driver = {
- .owner = THIS_MODULE,
- .name = "pca9539",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "pca9539",
+ },
.attach_adapter = pca9539_attach_adapter,
.detach_client = pca9539_detach_client,
};
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index c323c2de236..c3e6449c448 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -65,10 +65,10 @@ static void pcf8574_init_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8574_driver = {
- .owner = THIS_MODULE,
- .name = "pcf8574",
+ .driver = {
+ .name = "pcf8574",
+ },
.id = I2C_DRIVERID_PCF8574,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = pcf8574_attach_adapter,
.detach_client = pcf8574_detach_client,
};
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index ce420a67560..36cff09c678 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -88,10 +88,10 @@ static int pcf8591_read_channel(struct device *dev, int channel);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8591_driver = {
- .owner = THIS_MODULE,
- .name = "pcf8591",
+ .driver = {
+ .name = "pcf8591",
+ },
.id = I2C_DRIVERID_PCF8591,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = pcf8591_attach_adapter,
.detach_client = pcf8591_detach_client,
};
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 916cdc1af23..ceaa6b0bdfd 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -14,6 +14,7 @@
*/
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/bcd.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -52,9 +53,6 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
#define CTRL1(c) _rtc8564_ctrl1(c)
#define CTRL2(c) _rtc8564_ctrl2(c)
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-
static int debug;;
module_param(debug, int, S_IRUGO | S_IWUSR);
@@ -157,7 +155,6 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
i2c_set_clientdata(new_client, d);
- new_client->flags = I2C_CLIENT_ALLOW_USE;
new_client->addr = addr;
new_client->adapter = adap;
new_client->driver = &rtc8564_driver;
@@ -224,16 +221,16 @@ static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
return ret;
/* century stored in minute alarm reg */
- dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
- dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
- dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
- dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
- dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
+ dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
+ dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
+ dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
+ dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
+ dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
- dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
+ dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
- dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
- dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
+ dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
+ dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
_DBGRTCTM(2, *dt);
@@ -255,18 +252,18 @@ rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
buf[RTC8564_REG_CTRL2] = CTRL2(client);
- buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
- buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
- buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);
+ buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
+ buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
+ buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
if (datetoo) {
len += 5;
- buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
- buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
- buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
+ buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
+ buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
+ buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
/* century stored in minute alarm reg */
- buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
- buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
+ buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
+ buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
}
ret = rtc8564_write(client, 0, buf, len);
@@ -361,10 +358,10 @@ rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver rtc8564_driver = {
- .owner = THIS_MODULE,
- .name = "RTC8564",
+ .driver = {
+ .name = "RTC8564",
+ },
.id = I2C_DRIVERID_RTC8564,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = rtc8564_probe,
.detach_client = rtc8564_detach,
.command = rtc8564_command
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 280dd7a45db..1af3dfbb808 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);
@@ -637,9 +638,9 @@ static int __init tps65010_scan_bus(struct i2c_adapter *bus)
}
static struct i2c_driver tps65010_driver = {
- .owner = THIS_MODULE,
- .name = "tps65010",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "tps65010",
+ },
.attach_adapter = tps65010_scan_bus,
.detach_client = __exit_p(tps65010_detach_client),
};
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
index 7da366cdc18..245fffa92db 100644
--- a/drivers/i2c/chips/x1205.c
+++ b/drivers/i2c/chips/x1205.c
@@ -105,9 +105,9 @@ static int x1205_command(struct i2c_client *client, unsigned int cmd,
void *arg);
static struct i2c_driver x1205_driver = {
- .owner = THIS_MODULE,
- .name = "x1205",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "x1205",
+ },
.attach_adapter = &x1205_attach,
.detach_client = &x1205_detach,
};
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 82ea1b7ec91..52b77477df5 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -197,7 +197,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
/* inform drivers of new adapters */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
- if (driver->flags & I2C_DF_NOTIFY)
+ if (driver->attach_adapter)
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
}
@@ -235,7 +235,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
if (driver->detach_adapter)
if ((res = driver->detach_adapter(adap))) {
dev_err(&adap->dev, "detach_adapter failed "
- "for driver [%s]\n", driver->name);
+ "for driver [%s]\n",
+ driver->driver.name);
goto out_unlock;
}
}
@@ -245,10 +246,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
list_for_each_safe(item, _n, &adap->clients) {
client = list_entry(item, struct i2c_client, list);
- /* detaching devices is unconditional of the set notify
- * flag, as _all_ clients that reside on the adapter
- * must be deleted, as this would cause invalid states.
- */
if ((res=client->driver->detach_client(client))) {
dev_err(&adap->dev, "detach_client failed for client "
"[%s] at address 0x%02x\n", client->name,
@@ -286,7 +283,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
* chips.
*/
-int i2c_add_driver(struct i2c_driver *driver)
+int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
struct list_head *item;
struct i2c_adapter *adapter;
@@ -295,8 +292,7 @@ int i2c_add_driver(struct i2c_driver *driver)
down(&core_lists);
/* add the driver to the list of i2c drivers in the driver core */
- driver->driver.owner = driver->owner;
- driver->driver.name = driver->name;
+ driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
driver->driver.probe = i2c_device_probe;
driver->driver.remove = i2c_device_remove;
@@ -306,10 +302,10 @@ int i2c_add_driver(struct i2c_driver *driver)
goto out_unlock;
list_add_tail(&driver->list,&drivers);
- pr_debug("i2c-core: driver [%s] registered\n", driver->name);
+ pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
/* now look for instances of driver on our adapters */
- if (driver->flags & I2C_DF_NOTIFY) {
+ if (driver->attach_adapter) {
list_for_each(item,&adapters) {
adapter = list_entry(item, struct i2c_adapter, list);
driver->attach_adapter(adapter);
@@ -320,6 +316,7 @@ int i2c_add_driver(struct i2c_driver *driver)
up(&core_lists);
return res;
}
+EXPORT_SYMBOL(i2c_register_driver);
int i2c_del_driver(struct i2c_driver *driver)
{
@@ -334,17 +331,14 @@ int i2c_del_driver(struct i2c_driver *driver)
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
* afterwards.
- *
- * Removing clients does not depend on the notify flag, else
- * invalid operation might (will!) result, when using stale client
- * pointers.
*/
list_for_each(item1,&adapters) {
adap = list_entry(item1, struct i2c_adapter, list);
if (driver->detach_adapter) {
if ((res = driver->detach_adapter(adap))) {
dev_err(&adap->dev, "detach_adapter failed "
- "for driver [%s]\n", driver->name);
+ "for driver [%s]\n",
+ driver->driver.name);
goto out_unlock;
}
} else {
@@ -368,7 +362,7 @@ int i2c_del_driver(struct i2c_driver *driver)
driver_unregister(&driver->driver);
list_del(&driver->list);
- pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
+ pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
out_unlock:
up(&core_lists);
@@ -419,8 +413,7 @@ int i2c_attach_client(struct i2c_client *client)
}
}
- if (client->flags & I2C_CLIENT_ALLOW_USE)
- client->usage_count = 0;
+ client->usage_count = 0;
client->dev.parent = &client->adapter->dev;
client->dev.driver = &client->driver->driver;
@@ -443,8 +436,7 @@ int i2c_detach_client(struct i2c_client *client)
struct i2c_adapter *adapter = client->adapter;
int res = 0;
- if ((client->flags & I2C_CLIENT_ALLOW_USE)
- && (client->usage_count > 0)) {
+ if (client->usage_count > 0) {
dev_warn(&client->dev, "Client [%s] still busy, "
"can't detach\n", client->name);
return -EBUSY;
@@ -475,10 +467,10 @@ int i2c_detach_client(struct i2c_client *client)
static int i2c_inc_use_client(struct i2c_client *client)
{
- if (!try_module_get(client->driver->owner))
+ if (!try_module_get(client->driver->driver.owner))
return -ENODEV;
if (!try_module_get(client->adapter->owner)) {
- module_put(client->driver->owner);
+ module_put(client->driver->driver.owner);
return -ENODEV;
}
@@ -487,7 +479,7 @@ static int i2c_inc_use_client(struct i2c_client *client)
static void i2c_dec_use_client(struct i2c_client *client)
{
- module_put(client->driver->owner);
+ module_put(client->driver->driver.owner);
module_put(client->adapter->owner);
}
@@ -499,33 +491,20 @@ int i2c_use_client(struct i2c_client *client)
if (ret)
return ret;
- if (client->flags & I2C_CLIENT_ALLOW_USE) {
- if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
- client->usage_count++;
- else if (client->usage_count > 0)
- goto busy;
- else
- client->usage_count++;
- }
+ client->usage_count++;
return 0;
- busy:
- i2c_dec_use_client(client);
- return -EBUSY;
}
int i2c_release_client(struct i2c_client *client)
{
- if(client->flags & I2C_CLIENT_ALLOW_USE) {
- if(client->usage_count>0)
- client->usage_count--;
- else {
- pr_debug("i2c-core: %s used one too many times\n",
- __FUNCTION__);
- return -EPERM;
- }
+ if (!client->usage_count) {
+ pr_debug("i2c-core: %s used one too many times\n",
+ __FUNCTION__);
+ return -EPERM;
}
+ client->usage_count--;
i2c_dec_use_client(client);
return 0;
@@ -539,14 +518,14 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
down(&adap->clist_lock);
list_for_each(item,&adap->clients) {
client = list_entry(item, struct i2c_client, list);
- if (!try_module_get(client->driver->owner))
+ if (!try_module_get(client->driver->driver.owner))
continue;
if (NULL != client->driver->command) {
up(&adap->clist_lock);
client->driver->command(client,cmd,arg);
down(&adap->clist_lock);
}
- module_put(client->driver->owner);
+ module_put(client->driver->driver.owner);
}
up(&adap->clist_lock);
}
@@ -1147,7 +1126,6 @@ EXPORT_SYMBOL_GPL(i2c_bus_type);
EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
-EXPORT_SYMBOL(i2c_add_driver);
EXPORT_SYMBOL(i2c_del_driver);
EXPORT_SYMBOL(i2c_attach_client);
EXPORT_SYMBOL(i2c_detach_client);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 8af0bd1424d..ed7eed388ba 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -42,8 +42,7 @@ static struct i2c_client i2cdev_client_template;
struct i2c_dev {
int minor;
struct i2c_adapter *adap;
- struct class_device class_dev;
- struct completion released; /* FIXME, we need a class_device_unregister() */
+ struct class_device *class_dev;
};
#define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
@@ -105,7 +104,10 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
{
- struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
+ struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt));
+
+ if (!i2c_dev)
+ return -ENODEV;
return sprintf(buf, "%s\n", i2c_dev->adap->name);
}
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
@@ -408,21 +410,12 @@ static struct file_operations i2cdev_fops = {
.release = i2cdev_release,
};
-static void release_i2c_dev(struct class_device *dev)
-{
- struct i2c_dev *i2c_dev = to_i2c_dev(dev);
- complete(&i2c_dev->released);
-}
-
-static struct class i2c_dev_class = {
- .name = "i2c-dev",
- .release = &release_i2c_dev,
-};
+static struct class *i2c_dev_class;
static int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
- int retval;
+ struct device *dev;
i2c_dev = get_free_i2c_dev(adap);
if (IS_ERR(i2c_dev))
@@ -434,21 +427,20 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
/* register this i2c device with the driver core */
i2c_dev->adap = adap;
if (adap->dev.parent == &platform_bus)
- i2c_dev->class_dev.dev = &adap->dev;
+ dev = &adap->dev;
else
- i2c_dev->class_dev.dev = adap->dev.parent;
- i2c_dev->class_dev.class = &i2c_dev_class;
- i2c_dev->class_dev.devt = MKDEV(I2C_MAJOR, i2c_dev->minor);
- snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor);
- retval = class_device_register(&i2c_dev->class_dev);
- if (retval)
+ dev = adap->dev.parent;
+ i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
+ MKDEV(I2C_MAJOR, i2c_dev->minor),
+ dev, "i2c-%d", i2c_dev->minor);
+ if (!i2c_dev->class_dev)
goto error;
- class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
+ class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
return 0;
error:
return_i2c_dev(i2c_dev);
kfree(i2c_dev);
- return retval;
+ return -ENODEV;
}
static int i2cdev_detach_adapter(struct i2c_adapter *adap)
@@ -459,10 +451,8 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
if (!i2c_dev)
return -ENODEV;
- init_completion(&i2c_dev->released);
return_i2c_dev(i2c_dev);
- class_device_unregister(&i2c_dev->class_dev);
- wait_for_completion(&i2c_dev->released);
+ class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -474,21 +464,14 @@ static int i2cdev_detach_client(struct i2c_client *client)
return 0;
}
-static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
- void *arg)
-{
- return -1;
-}
-
static struct i2c_driver i2cdev_driver = {
- .owner = THIS_MODULE,
- .name = "dev_driver",
+ .driver = {
+ .name = "dev_driver",
+ },
.id = I2C_DRIVERID_I2CDEV,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter,
.detach_client = i2cdev_detach_client,
- .command = i2cdev_command,
};
static struct i2c_client i2cdev_client_template = {
@@ -507,8 +490,8 @@ static int __init i2c_dev_init(void)
if (res)
goto out;
- res = class_register(&i2c_dev_class);
- if (res)
+ i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
+ if (IS_ERR(i2c_dev_class))
goto out_unreg_chrdev;
res = i2c_add_driver(&i2cdev_driver);
@@ -518,7 +501,7 @@ static int __init i2c_dev_init(void)
return 0;
out_unreg_class:
- class_unregister(&i2c_dev_class);
+ class_destroy(i2c_dev_class);
out_unreg_chrdev:
unregister_chrdev(I2C_MAJOR, "i2c");
out:
@@ -529,7 +512,7 @@ out:
static void __exit i2c_dev_exit(void)
{
i2c_del_driver(&i2cdev_driver);
- class_unregister(&i2c_dev_class);
+ class_destroy(i2c_dev_class);
unregister_chrdev(I2C_MAJOR,"i2c");
}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 70aeb3a6012..9b2ebd219ad 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -614,7 +614,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
*/
spin_lock_irqsave(&ide_lock, flags);
end_that_request_chunk(failed, 0, failed->data_len);
- end_that_request_last(failed);
+ end_that_request_last(failed, 0);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -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;
@@ -1735,7 +1733,7 @@ end_request:
spin_lock_irqsave(&ide_lock, flags);
blkdev_dequeue_request(rq);
- end_that_request_last(rq);
+ end_that_request_last(rq, 1);
HWGROUP(drive)->rq = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
return ide_stopped;
@@ -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);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4e5767968d7..cab362ea033 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -681,50 +681,9 @@ static ide_proc_entry_t idedisk_proc[] = {
#endif /* CONFIG_PROC_FS */
-static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq)
+static void idedisk_prepare_flush(request_queue_t *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
- struct request *rq = flush_rq->end_io_data;
- int good_sectors = rq->hard_nr_sectors;
- int bad_sectors;
- sector_t sector;
-
- if (flush_rq->errors & ABRT_ERR) {
- printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
- blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE);
- blk_queue_issue_flush_fn(drive->queue, NULL);
- good_sectors = 0;
- } else if (flush_rq->errors) {
- good_sectors = 0;
- if (blk_barrier_preflush(rq)) {
- sector = ide_get_error_location(drive,flush_rq->buffer);
- if ((sector >= rq->hard_sector) &&
- (sector < rq->hard_sector + rq->hard_nr_sectors))
- good_sectors = sector - rq->hard_sector;
- }
- }
-
- if (flush_rq->errors)
- printk(KERN_ERR "%s: failed barrier write: "
- "sector=%Lx(good=%d/bad=%d)\n",
- drive->name, (unsigned long long)rq->sector,
- good_sectors,
- (int) (rq->hard_nr_sectors-good_sectors));
-
- bad_sectors = rq->hard_nr_sectors - good_sectors;
-
- if (good_sectors)
- __ide_end_request(drive, rq, 1, good_sectors);
- if (bad_sectors)
- __ide_end_request(drive, rq, 0, bad_sectors);
-}
-
-static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
-{
- ide_drive_t *drive = q->queuedata;
-
- if (!drive->wcache)
- return 0;
memset(rq->cmd, 0, sizeof(rq->cmd));
@@ -735,9 +694,8 @@ static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
rq->cmd[0] = WIN_FLUSH_CACHE;
- rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
+ rq->flags |= REQ_DRIVE_TASK;
rq->buffer = rq->cmd;
- return 1;
}
static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -794,27 +752,64 @@ static int set_nowerr(ide_drive_t *drive, int arg)
return 0;
}
+static void update_ordered(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ unsigned ordered = QUEUE_ORDERED_NONE;
+ prepare_flush_fn *prep_fn = NULL;
+ issue_flush_fn *issue_fn = NULL;
+
+ if (drive->wcache) {
+ unsigned long long capacity;
+ int barrier;
+ /*
+ * We must avoid issuing commands a drive does not
+ * understand or we may crash it. We check flush cache
+ * is supported. We also check we have the LBA48 flush
+ * cache if the drive capacity is too large. By this
+ * time we have trimmed the drive capacity if LBA48 is
+ * not available so we don't need to recheck that.
+ */
+ capacity = idedisk_capacity(drive);
+ barrier = ide_id_has_flush_cache(id) &&
+ (drive->addressing == 0 || capacity <= (1ULL << 28) ||
+ ide_id_has_flush_cache_ext(id));
+
+ printk(KERN_INFO "%s: cache flushes %ssupported\n",
+ drive->name, barrier ? "" : "not");
+
+ if (barrier) {
+ ordered = QUEUE_ORDERED_DRAIN_FLUSH;
+ prep_fn = idedisk_prepare_flush;
+ issue_fn = idedisk_issue_flush;
+ }
+ } else
+ ordered = QUEUE_ORDERED_DRAIN;
+
+ blk_queue_ordered(drive->queue, ordered, prep_fn);
+ blk_queue_issue_flush_fn(drive->queue, issue_fn);
+}
+
static int write_cache(ide_drive_t *drive, int arg)
{
ide_task_t args;
- int err;
+ int err = 1;
- if (!ide_id_has_flush_cache(drive->id))
- return 1;
-
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
+ if (ide_id_has_flush_cache(drive->id)) {
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ err = ide_raw_taskfile(drive, &args, NULL);
+ if (err == 0)
+ drive->wcache = arg;
+ }
- err = ide_raw_taskfile(drive, &args, NULL);
- if (err)
- return err;
+ update_ordered(drive);
- drive->wcache = arg;
- return 0;
+ return err;
}
static int do_idedisk_flushcache (ide_drive_t *drive)
@@ -888,7 +883,6 @@ static void idedisk_setup (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
unsigned long long capacity;
- int barrier;
idedisk_add_settings(drive);
@@ -992,31 +986,6 @@ static void idedisk_setup (ide_drive_t *drive)
drive->wcache = 1;
write_cache(drive, 1);
-
- /*
- * We must avoid issuing commands a drive does not understand
- * or we may crash it. We check flush cache is supported. We also
- * check we have the LBA48 flush cache if the drive capacity is
- * too large. By this time we have trimmed the drive capacity if
- * LBA48 is not available so we don't need to recheck that.
- */
- barrier = 0;
- if (ide_id_has_flush_cache(id))
- barrier = 1;
- if (drive->addressing == 1) {
- /* Can't issue the correct flush ? */
- if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id))
- barrier = 0;
- }
-
- printk(KERN_INFO "%s: cache flushes %ssupported\n",
- drive->name, barrier ? "" : "not ");
- if (barrier) {
- blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH);
- drive->queue->prepare_flush_fn = idedisk_prepare_flush;
- drive->queue->end_flush_fn = idedisk_end_flush;
- blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
- }
}
static void ide_cacheflush_p(ide_drive_t *drive)
@@ -1161,6 +1130,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)
{
@@ -1195,6 +1175,7 @@ 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
};
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index fba3fffc2d6..5945f551aaa 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2031,6 +2031,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,6 +2131,7 @@ 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
};
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ecfafcdafea..8d50df4526a 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);
+ end_that_request_last(rq, uptodate);
ret = 0;
}
+
return ret;
}
EXPORT_SYMBOL(__ide_end_request);
@@ -113,16 +110,17 @@ 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;
if (!nr_sectors)
nr_sectors = rq->hard_cur_sectors;
- if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors))
- ret = rq->nr_sectors != 0;
- else
- ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
+ ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
spin_unlock_irqrestore(&ide_lock, flags);
return ret;
@@ -247,7 +245,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
}
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
+ end_that_request_last(rq, 1);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -379,7 +377,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
rq->errors = err;
- end_that_request_last(rq);
+ end_that_request_last(rq, !rq->errors);
spin_unlock_irqrestore(&ide_lock, flags);
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 02167a5b751..e7425546b4b 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.c b/drivers/ide/ide.c
index 4b524f6b3ec..ec5a4cb173b 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)
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 242029c9c0c..6439dec6688 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 211641a5439..fe06ebb0e5b 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 ff2e217a8c8..0d3073f4eab 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 86fb1e0286d..c85b87cb59d 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 16b28357885..5013b1285e2 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/Kconfig b/drivers/ieee1394/Kconfig
index 25103a0ef9b..39142e2f804 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -169,27 +169,4 @@ config IEEE1394_RAWIO
To compile this driver as a module, say M here: the
module will be called raw1394.
-config IEEE1394_CMP
- tristate "IEC61883-1 Plug support"
- depends on IEEE1394
- help
- This option enables the Connection Management Procedures
- (IEC61883-1) driver, which implements input and output plugs.
-
- To compile this driver as a module, say M here: the
- module will be called cmp.
-
-config IEEE1394_AMDTP
- tristate "IEC61883-6 (Audio transmission) support"
- depends on IEEE1394 && IEEE1394_OHCI1394 && IEEE1394_CMP
- help
- This option enables the Audio & Music Data Transmission Protocol
- (IEC61883-6) driver, which implements audio transmission over
- IEEE1394.
-
- The userspace interface is documented in amdtp.h.
-
- To compile this driver as a module, say M here: the
- module will be called amdtp.
-
endmenu
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
index e8b4d48d376..6f53611fe25 100644
--- a/drivers/ieee1394/Makefile
+++ b/drivers/ieee1394/Makefile
@@ -14,8 +14,6 @@ obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
-obj-$(CONFIG_IEEE1394_AMDTP) += amdtp.o
-obj-$(CONFIG_IEEE1394_CMP) += cmp.o
quiet_cmd_oui2c = OUI2C $@
cmd_oui2c = $(CONFIG_SHELL) $(srctree)/$(src)/oui2c.sh < $< > $@
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index 75897509c40..17390d762cf 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -80,7 +80,6 @@
#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>
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 61ddd5d37ef..15773544234 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -1261,7 +1261,7 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
return CSR1212_EINVAL;
#endif
- cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ cr = CSR1212_MALLOC(sizeof(*cr));
if (!cr)
return CSR1212_ENOMEM;
@@ -1393,8 +1393,7 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
case CSR1212_KV_TYPE_LEAF:
if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
- if (!kv->value.leaf.data)
- {
+ if (!kv->value.leaf.data) {
ret = CSR1212_ENOMEM;
goto fail;
}
@@ -1462,7 +1461,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
cache->next = NULL;
csr->cache_tail = cache;
cache->filled_head =
- CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ CSR1212_MALLOC(sizeof(*cache->filled_head));
if (!cache->filled_head) {
return CSR1212_ENOMEM;
}
@@ -1484,7 +1483,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
/* Now seach read portions of the cache to see if it is there. */
for (cr = cache->filled_head; cr; cr = cr->next) {
if (cache_index < cr->offset_start) {
- newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ newcr = CSR1212_MALLOC(sizeof(*newcr));
if (!newcr)
return CSR1212_ENOMEM;
@@ -1508,7 +1507,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
if (!cr) {
cr = cache->filled_tail;
- newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ newcr = CSR1212_MALLOC(sizeof(*newcr));
if (!newcr)
return CSR1212_ENOMEM;
@@ -1611,15 +1610,17 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
csr->root_kv->valid = 0;
csr->root_kv->next = csr->root_kv;
csr->root_kv->prev = csr->root_kv;
- csr1212_get_keyval(csr, csr->root_kv);
+ ret = _csr1212_read_keyval(csr, csr->root_kv);
+ if (ret != CSR1212_SUCCESS)
+ return ret;
/* Scan through the Root directory finding all extended ROM regions
* and make cache regions for them */
for (dentry = csr->root_kv->value.directory.dentries_head;
dentry; dentry = dentry->next) {
- if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
- csr1212_get_keyval(csr, dentry->kv);
-
+ if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
+ !dentry->kv->valid) {
+ ret = _csr1212_read_keyval(csr, dentry->kv);
if (ret != CSR1212_SUCCESS)
return ret;
}
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index 28c5f4b726e..cecd5871f2d 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -646,7 +646,7 @@ static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t o
{
struct csr1212_csr_rom_cache *cache;
- cache = CSR1212_MALLOC(sizeof(struct csr1212_csr_rom_cache) + size);
+ cache = CSR1212_MALLOC(sizeof(*cache) + size);
if (!cache)
return NULL;
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index b79ddb43e74..9fb2769d9ab 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -23,7 +23,8 @@ void dma_prog_region_init(struct dma_prog_region *prog)
prog->bus_addr = 0;
}
-int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev)
+int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
+ struct pci_dev *dev)
{
/* round up to page size */
n_bytes = PAGE_ALIGN(n_bytes);
@@ -32,7 +33,8 @@ int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr);
if (!prog->kvirt) {
- printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
+ printk(KERN_ERR
+ "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
dma_prog_region_free(prog);
return -ENOMEM;
}
@@ -45,7 +47,8 @@ int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
void dma_prog_region_free(struct dma_prog_region *prog)
{
if (prog->kvirt) {
- pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT, prog->kvirt, prog->bus_addr);
+ pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT,
+ prog->kvirt, prog->bus_addr);
}
prog->kvirt = NULL;
@@ -65,7 +68,8 @@ void dma_region_init(struct dma_region *dma)
dma->sglist = NULL;
}
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction)
+int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
+ struct pci_dev *dev, int direction)
{
unsigned int i;
@@ -95,14 +99,16 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
/* fill scatter/gather list with pages */
for (i = 0; i < dma->n_pages; i++) {
- unsigned long va = (unsigned long) dma->kvirt + (i << PAGE_SHIFT);
+ unsigned long va =
+ (unsigned long)dma->kvirt + (i << PAGE_SHIFT);
dma->sglist[i].page = vmalloc_to_page((void *)va);
dma->sglist[i].length = PAGE_SIZE;
}
/* map sglist to the IOMMU */
- dma->n_dma_pages = pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
+ dma->n_dma_pages =
+ pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
if (dma->n_dma_pages == 0) {
printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
@@ -114,7 +120,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
return 0;
-err:
+ err:
dma_region_free(dma);
return -ENOMEM;
}
@@ -122,7 +128,8 @@ err:
void dma_region_free(struct dma_region *dma)
{
if (dma->n_dma_pages) {
- pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction);
+ pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages,
+ dma->direction);
dma->n_dma_pages = 0;
dma->dev = NULL;
}
@@ -137,7 +144,8 @@ void dma_region_free(struct dma_region *dma)
/* find the scatterlist index and remaining offset corresponding to a
given offset from the beginning of the buffer */
-static inline int dma_region_find(struct dma_region *dma, unsigned long offset, unsigned long *rem)
+static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
+ unsigned long *rem)
{
int i;
unsigned long off = offset;
@@ -156,15 +164,18 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
return i;
}
-dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
+dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
+ unsigned long offset)
{
unsigned long rem = 0;
- struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)];
+ struct scatterlist *sg =
+ &dma->sglist[dma_region_find(dma, offset, &rem)];
return sg_dma_address(sg) + rem;
}
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len)
+void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
+ unsigned long len)
{
int first, last;
unsigned long rem;
@@ -175,10 +186,12 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsig
first = dma_region_find(dma, offset, &rem);
last = dma_region_find(dma, offset + len - 1, &rem);
- pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+ pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
+ dma->direction);
}
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len)
+void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
+ unsigned long len)
{
int first, last;
unsigned long rem;
@@ -189,44 +202,47 @@ void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, un
first = dma_region_find(dma, offset, &rem);
last = dma_region_find(dma, offset + len - 1, &rem);
- pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+ pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
+ last - first + 1, dma->direction);
}
#ifdef CONFIG_MMU
/* nopage() handler for mmap access */
-static struct page*
-dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int *type)
+static struct page *dma_region_pagefault(struct vm_area_struct *area,
+ unsigned long address, int *type)
{
unsigned long offset;
unsigned long kernel_virt_addr;
struct page *ret = NOPAGE_SIGBUS;
- struct dma_region *dma = (struct dma_region*) area->vm_private_data;
+ struct dma_region *dma = (struct dma_region *)area->vm_private_data;
if (!dma->kvirt)
goto out;
- if ( (address < (unsigned long) area->vm_start) ||
- (address > (unsigned long) area->vm_start + (dma->n_pages << PAGE_SHIFT)) )
+ if ((address < (unsigned long)area->vm_start) ||
+ (address >
+ (unsigned long)area->vm_start + (dma->n_pages << PAGE_SHIFT)))
goto out;
if (type)
*type = VM_FAULT_MINOR;
offset = address - area->vm_start;
- kernel_virt_addr = (unsigned long) dma->kvirt + offset;
- ret = vmalloc_to_page((void*) kernel_virt_addr);
+ kernel_virt_addr = (unsigned long)dma->kvirt + offset;
+ ret = vmalloc_to_page((void *)kernel_virt_addr);
get_page(ret);
-out:
+ out:
return ret;
}
static struct vm_operations_struct dma_region_vm_ops = {
- .nopage = dma_region_pagefault,
+ .nopage = dma_region_pagefault,
};
-int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
+int dma_region_mmap(struct dma_region *dma, struct file *file,
+ struct vm_area_struct *vma)
{
unsigned long size;
@@ -250,11 +266,12 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_st
return 0;
}
-#else /* CONFIG_MMU */
+#else /* CONFIG_MMU */
-int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
+int dma_region_mmap(struct dma_region *dma, struct file *file,
+ struct vm_area_struct *vma)
{
return -EINVAL;
}
-#endif /* CONFIG_MMU */
+#endif /* CONFIG_MMU */
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index cbbbe14b884..efeaa944bd0 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>
@@ -123,15 +122,6 @@
#include "ohci1394.h"
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
-
/* DEBUG LEVELS:
0 - no debugging messages
1 - some debugging messages, but none during DMA frame transmission
@@ -2218,14 +2208,12 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
unsigned long flags;
int i;
- video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
+ video = kzalloc(sizeof(*video), GFP_KERNEL);
if (!video) {
printk(KERN_ERR "dv1394: cannot allocate video_card\n");
goto err;
}
- memset(video, 0, sizeof(struct video_card));
-
video->ohci = ohci;
/* lower 2 bits of id indicate which of four "plugs"
per host */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index c9e92d85c89..30fa0d43a43 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -88,9 +88,6 @@
printk(KERN_ERR "%s:%s[%d]: " fmt "\n", driver_name, __FUNCTION__, __LINE__, ## args)
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
-static char version[] __devinitdata =
- "$Rev: 1312 $ Ben Collins <bcollins@debian.org>";
-
struct fragment_info {
struct list_head list;
int offset;
@@ -355,12 +352,12 @@ static int eth1394_probe(struct device *dev)
if (!hi)
return -ENOENT;
- new_node = kmalloc(sizeof(struct eth1394_node_ref),
+ new_node = kmalloc(sizeof(*new_node),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!new_node)
return -ENOMEM;
- node_info = kmalloc(sizeof(struct eth1394_node_info),
+ node_info = kmalloc(sizeof(*node_info),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!node_info) {
kfree(new_node);
@@ -436,12 +433,12 @@ static int eth1394_update(struct unit_directory *ud)
node = eth1394_find_node(&priv->ip_node_list, ud);
if (!node) {
- node = kmalloc(sizeof(struct eth1394_node_ref),
+ node = kmalloc(sizeof(*node),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!node)
return -ENOMEM;
- node_info = kmalloc(sizeof(struct eth1394_node_info),
+ node_info = kmalloc(sizeof(*node_info),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!node_info) {
kfree(node);
@@ -566,7 +563,6 @@ static void ether1394_add_host (struct hpsb_host *host)
struct eth1394_host_info *hi = NULL;
struct net_device *dev = NULL;
struct eth1394_priv *priv;
- static int version_printed = 0;
u64 fifo_addr;
if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))
@@ -581,9 +577,6 @@ static void ether1394_add_host (struct hpsb_host *host)
if (fifo_addr == ~0ULL)
goto out;
- if (version_printed++ == 0)
- ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
-
/* We should really have our own alloc_hpsbdev() function in
* net_init.c instead of calling the one for ethernet then hijacking
* it for ourselves. That way we'd be a real networking device. */
@@ -1021,7 +1014,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len)
}
}
- new = kmalloc(sizeof(struct fragment_info), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
if (!new)
return -ENOMEM;
@@ -1040,7 +1033,7 @@ static inline int new_partial_datagram(struct net_device *dev,
{
struct partial_datagram *new;
- new = kmalloc(sizeof(struct partial_datagram), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
if (!new)
return -ENOMEM;
@@ -1768,7 +1761,6 @@ fail:
static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
strcpy (info->driver, driver_name);
- strcpy (info->version, "$Rev: 1312 $");
/* FIXME XXX provide sane businfo */
strcpy (info->bus_info, "ieee1394");
}
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 997e1bf6297..734b121a055 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -101,12 +101,10 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return NULL;
}
- hi = kmalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
+ hi = kzalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
if (!hi)
return NULL;
- memset(hi, 0, sizeof(*hi) + data_size);
-
if (data_size) {
data = hi->data = hi + 1;
hi->size = data_size;
@@ -326,11 +324,9 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
return retval;
}
- as = (struct hpsb_address_serve *)
- kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
- if (as == NULL) {
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
+ if (!as)
return retval;
- }
INIT_LIST_HEAD(&as->host_list);
INIT_LIST_HEAD(&as->hl_list);
@@ -383,11 +379,9 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return 0;
}
- as = (struct hpsb_address_serve *)
- kmalloc(sizeof(struct hpsb_address_serve), GFP_ATOMIC);
- if (as == NULL) {
- return 0;
- }
+ as = kmalloc(sizeof(*as), GFP_ATOMIC);
+ if (!as)
+ return 0;
INIT_LIST_HEAD(&as->host_list);
INIT_LIST_HEAD(&as->hl_list);
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index aeeaeb670d0..ba09741fc82 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -61,12 +61,12 @@ static void delayed_reset_bus(void * __reset_info)
static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
{
- return 0;
+ return 0;
}
static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
{
- return -1;
+ return -1;
}
static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
@@ -75,9 +75,9 @@ static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned
}
static struct hpsb_host_driver dummy_driver = {
- .transmit_packet = dummy_transmit_packet,
- .devctl = dummy_devctl,
- .isoctl = dummy_isoctl
+ .transmit_packet = dummy_transmit_packet,
+ .devctl = dummy_devctl,
+ .isoctl = dummy_isoctl
};
static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
@@ -110,13 +110,13 @@ static DECLARE_MUTEX(host_num_alloc);
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev)
{
- struct hpsb_host *h;
+ struct hpsb_host *h;
int i;
int hostnum = 0;
- h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
- if (!h) return NULL;
- memset(h, 0, sizeof(struct hpsb_host) + extra);
+ h = kzalloc(sizeof(*h) + extra, SLAB_KERNEL);
+ if (!h)
+ return NULL;
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
if (!h->csr.rom) {
@@ -125,7 +125,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
}
h->hostdata = h + 1;
- h->driver = drv;
+ h->driver = drv;
skb_queue_head_init(&h->pending_packet_queue);
INIT_LIST_HEAD(&h->addr_space);
@@ -145,8 +145,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
h->timeout.function = abort_timedouts;
h->timeout_interval = HZ / 20; // 50ms by default
- h->topology_map = h->csr.topology_map + 3;
- h->speed_map = (u8 *)(h->csr.speed_map + 2);
+ h->topology_map = h->csr.topology_map + 3;
+ h->speed_map = (u8 *)(h->csr.speed_map + 2);
down(&host_num_alloc);
@@ -186,14 +186,14 @@ int hpsb_add_host(struct hpsb_host *host)
void hpsb_remove_host(struct hpsb_host *host)
{
- host->is_shutdown = 1;
+ host->is_shutdown = 1;
cancel_delayed_work(&host->delayed_reset);
flush_scheduled_work();
- host->driver = &dummy_driver;
+ host->driver = &dummy_driver;
- highlevel_remove_host(host);
+ highlevel_remove_host(host);
hpsb_remove_extra_config_roms(host);
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index ae9b02cc013..07d188ca849 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -17,47 +17,47 @@ struct hpsb_packet;
struct hpsb_iso;
struct hpsb_host {
- struct list_head host_list;
+ struct list_head host_list;
- void *hostdata;
+ void *hostdata;
- atomic_t generation;
+ atomic_t generation;
struct sk_buff_head pending_packet_queue;
struct timer_list timeout;
unsigned long timeout_interval;
- unsigned char iso_listen_count[64];
+ unsigned char iso_listen_count[64];
- int node_count; /* number of identified nodes on this bus */
- int selfid_count; /* total number of SelfIDs received */
+ int node_count; /* number of identified nodes on this bus */
+ int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes that are actually active */
- nodeid_t node_id; /* node ID of this host */
- nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
- nodeid_t busmgr_id; /* ID of this bus' bus manager */
+ nodeid_t node_id; /* node ID of this host */
+ nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
+ nodeid_t busmgr_id; /* ID of this bus' bus manager */
- /* this nodes state */
- unsigned in_bus_reset:1;
- unsigned is_shutdown:1;
+ /* this nodes state */
+ unsigned in_bus_reset:1;
+ unsigned is_shutdown:1;
unsigned resume_packet_sent:1;
- /* this nodes' duties on the bus */
- unsigned is_root:1;
- unsigned is_cycmst:1;
- unsigned is_irm:1;
- unsigned is_busmgr:1;
+ /* this nodes' duties on the bus */
+ unsigned is_root:1;
+ unsigned is_cycmst:1;
+ unsigned is_irm:1;
+ unsigned is_busmgr:1;
- int reset_retries;
- quadlet_t *topology_map;
- u8 *speed_map;
- struct csr_control csr;
+ int reset_retries;
+ quadlet_t *topology_map;
+ u8 *speed_map;
+ struct csr_control csr;
/* Per node tlabel pool allocation */
struct hpsb_tlabel_pool tpool[64];
- struct hpsb_host_driver *driver;
+ struct hpsb_host_driver *driver;
struct pci_dev *pdev;
@@ -77,34 +77,34 @@ struct hpsb_host {
enum devctl_cmd {
- /* Host is requested to reset its bus and cancel all outstanding async
- * requests. If arg == 1, it shall also attempt to become root on the
- * bus. Return void. */
- RESET_BUS,
-
- /* Arg is void, return value is the hardware cycle counter value. */
- GET_CYCLE_COUNTER,
-
- /* Set the hardware cycle counter to the value in arg, return void.
- * FIXME - setting is probably not required. */
- SET_CYCLE_COUNTER,
-
- /* Configure hardware for new bus ID in arg, return void. */
- SET_BUS_ID,
-
- /* If arg true, start sending cycle start packets, stop if arg == 0.
- * Return void. */
- ACT_CYCLE_MASTER,
-
- /* Cancel all outstanding async requests without resetting the bus.
- * Return void. */
- CANCEL_REQUESTS,
-
- /* Start or stop receiving isochronous channel in arg. Return void.
- * This acts as an optimization hint, hosts are not required not to
- * listen on unrequested channels. */
- ISO_LISTEN_CHANNEL,
- ISO_UNLISTEN_CHANNEL
+ /* Host is requested to reset its bus and cancel all outstanding async
+ * requests. If arg == 1, it shall also attempt to become root on the
+ * bus. Return void. */
+ RESET_BUS,
+
+ /* Arg is void, return value is the hardware cycle counter value. */
+ GET_CYCLE_COUNTER,
+
+ /* Set the hardware cycle counter to the value in arg, return void.
+ * FIXME - setting is probably not required. */
+ SET_CYCLE_COUNTER,
+
+ /* Configure hardware for new bus ID in arg, return void. */
+ SET_BUS_ID,
+
+ /* If arg true, start sending cycle start packets, stop if arg == 0.
+ * Return void. */
+ ACT_CYCLE_MASTER,
+
+ /* Cancel all outstanding async requests without resetting the bus.
+ * Return void. */
+ CANCEL_REQUESTS,
+
+ /* Start or stop receiving isochronous channel in arg. Return void.
+ * This acts as an optimization hint, hosts are not required not to
+ * listen on unrequested channels. */
+ ISO_LISTEN_CHANNEL,
+ ISO_UNLISTEN_CHANNEL
};
enum isoctl_cmd {
@@ -135,13 +135,13 @@ enum isoctl_cmd {
};
enum reset_types {
- /* 166 microsecond reset -- only type of reset available on
- non-1394a capable controllers */
- LONG_RESET,
+ /* 166 microsecond reset -- only type of reset available on
+ non-1394a capable controllers */
+ LONG_RESET,
- /* Short (arbitrated) reset -- only available on 1394a capable
- controllers */
- SHORT_RESET,
+ /* Short (arbitrated) reset -- only available on 1394a capable
+ controllers */
+ SHORT_RESET,
/* Variants that set force_root before issueing the bus reset */
LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
@@ -159,22 +159,22 @@ struct hpsb_host_driver {
* reads to the ConfigROM on its own. */
void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom);
- /* This function shall implement packet transmission based on
- * packet->type. It shall CRC both parts of the packet (unless
- * packet->type == raw) and do byte-swapping as necessary or instruct
- * the hardware to do so. It can return immediately after the packet
- * was queued for sending. After sending, hpsb_sent_packet() has to be
- * called. Return 0 on success, negative errno on failure.
- * NOTE: The function must be callable in interrupt context.
- */
- int (*transmit_packet) (struct hpsb_host *host,
- struct hpsb_packet *packet);
-
- /* This function requests miscellanous services from the driver, see
- * above for command codes and expected actions. Return -1 for unknown
- * command, though that should never happen.
- */
- int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
+ /* This function shall implement packet transmission based on
+ * packet->type. It shall CRC both parts of the packet (unless
+ * packet->type == raw) and do byte-swapping as necessary or instruct
+ * the hardware to do so. It can return immediately after the packet
+ * was queued for sending. After sending, hpsb_sent_packet() has to be
+ * called. Return 0 on success, negative errno on failure.
+ * NOTE: The function must be callable in interrupt context.
+ */
+ int (*transmit_packet) (struct hpsb_host *host,
+ struct hpsb_packet *packet);
+
+ /* This function requests miscellanous services from the driver, see
+ * above for command codes and expected actions. Return -1 for unknown
+ * command, though that should never happen.
+ */
+ int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
/* ISO transmission/reception functions. Return 0 on success, -1
* (or -EXXX errno code) on failure. If the low-level driver does not
@@ -182,15 +182,15 @@ struct hpsb_host_driver {
*/
int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg);
- /* This function is mainly to redirect local CSR reads/locks to the iso
- * management registers (bus manager id, bandwidth available, channels
- * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus
- * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
- * as OHCI uses). data and compare are the new data and expected data
- * respectively, return value is the old value.
- */
- quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
- quadlet_t data, quadlet_t compare);
+ /* This function is mainly to redirect local CSR reads/locks to the iso
+ * management registers (bus manager id, bandwidth available, channels
+ * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus
+ * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
+ * as OHCI uses). data and compare are the new data and expected data
+ * respectively, return value is the old value.
+ */
+ quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
+ quadlet_t data, quadlet_t compare);
};
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
index f92b566363d..15670398634 100644
--- a/drivers/ieee1394/ieee1394-ioctl.h
+++ b/drivers/ieee1394/ieee1394-ioctl.h
@@ -7,14 +7,6 @@
#include <linux/ioctl.h>
#include <linux/types.h>
-
-/* AMDTP Gets 6 */
-#define AMDTP_IOC_CHANNEL _IOW('#', 0x00, struct amdtp_ioctl)
-#define AMDTP_IOC_PLUG _IOW('#', 0x01, struct amdtp_ioctl)
-#define AMDTP_IOC_PING _IOW('#', 0x02, struct amdtp_ioctl)
-#define AMDTP_IOC_ZAP _IO ('#', 0x03)
-
-
/* DV1394 Gets 10 */
/* Get the driver ready to transmit video. pass a struct dv1394_init* as
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
index b634a9bb365..936d776de00 100644
--- a/drivers/ieee1394/ieee1394.h
+++ b/drivers/ieee1394/ieee1394.h
@@ -62,6 +62,7 @@
extern const char *hpsb_speedto_str[];
+/* 1394a cable PHY packets */
#define SELFID_PWRCL_NO_POWER 0x0
#define SELFID_PWRCL_PROVIDE_15W 0x1
#define SELFID_PWRCL_PROVIDE_30W 0x2
@@ -76,8 +77,24 @@ extern const char *hpsb_speedto_str[];
#define SELFID_PORT_NCONN 0x1
#define SELFID_PORT_NONE 0x0
+#define PHYPACKET_LINKON 0x40000000
+#define PHYPACKET_PHYCONFIG_R 0x00800000
+#define PHYPACKET_PHYCONFIG_T 0x00400000
+#define EXTPHYPACKET_TYPE_PING 0x00000000
+#define EXTPHYPACKET_TYPE_REMOTEACCESS_BASE 0x00040000
+#define EXTPHYPACKET_TYPE_REMOTEACCESS_PAGED 0x00140000
+#define EXTPHYPACKET_TYPE_REMOTEREPLY_BASE 0x000C0000
+#define EXTPHYPACKET_TYPE_REMOTEREPLY_PAGED 0x001C0000
+#define EXTPHYPACKET_TYPE_REMOTECOMMAND 0x00200000
+#define EXTPHYPACKET_TYPE_REMOTECONFIRMATION 0x00280000
+#define EXTPHYPACKET_TYPE_RESUME 0x003C0000
-/* 1394a PHY bitmasks */
+#define EXTPHYPACKET_TYPEMASK 0xC0FC0000
+
+#define PHYPACKET_PORT_SHIFT 24
+#define PHYPACKET_GAPCOUNT_SHIFT 16
+
+/* 1394a PHY register map bitmasks */
#define PHY_00_PHYSICAL_ID 0xFC
#define PHY_00_R 0x02 /* Root */
#define PHY_00_PS 0x01 /* Power Status*/
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 32a1e016c85..25ef5a86f5f 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -179,34 +179,34 @@ void hpsb_free_packet(struct hpsb_packet *packet)
int hpsb_reset_bus(struct hpsb_host *host, int type)
{
- if (!host->in_bus_reset) {
- host->driver->devctl(host, RESET_BUS, type);
- return 0;
- } else {
- return 1;
- }
+ if (!host->in_bus_reset) {
+ host->driver->devctl(host, RESET_BUS, type);
+ return 0;
+ } else {
+ return 1;
+ }
}
int hpsb_bus_reset(struct hpsb_host *host)
{
- if (host->in_bus_reset) {
- HPSB_NOTICE("%s called while bus reset already in progress",
+ if (host->in_bus_reset) {
+ HPSB_NOTICE("%s called while bus reset already in progress",
__FUNCTION__);
- return 1;
- }
+ return 1;
+ }
- abort_requests(host);
- host->in_bus_reset = 1;
- host->irm_id = -1;
+ abort_requests(host);
+ host->in_bus_reset = 1;
+ host->irm_id = -1;
host->is_irm = 0;
- host->busmgr_id = -1;
+ host->busmgr_id = -1;
host->is_busmgr = 0;
host->is_cycmst = 0;
- host->node_count = 0;
- host->selfid_count = 0;
+ host->node_count = 0;
+ host->selfid_count = 0;
- return 0;
+ return 0;
}
@@ -216,150 +216,156 @@ int hpsb_bus_reset(struct hpsb_host *host)
*/
static int check_selfids(struct hpsb_host *host)
{
- int nodeid = -1;
- int rest_of_selfids = host->selfid_count;
- struct selfid *sid = (struct selfid *)host->topology_map;
- struct ext_selfid *esid;
- int esid_seq = 23;
+ int nodeid = -1;
+ int rest_of_selfids = host->selfid_count;
+ struct selfid *sid = (struct selfid *)host->topology_map;
+ struct ext_selfid *esid;
+ int esid_seq = 23;
host->nodes_active = 0;
- while (rest_of_selfids--) {
- if (!sid->extended) {
- nodeid++;
- esid_seq = 0;
+ while (rest_of_selfids--) {
+ if (!sid->extended) {
+ nodeid++;
+ esid_seq = 0;
- if (sid->phy_id != nodeid) {
- HPSB_INFO("SelfIDs failed monotony check with "
- "%d", sid->phy_id);
- return 0;
- }
+ if (sid->phy_id != nodeid) {
+ HPSB_INFO("SelfIDs failed monotony check with "
+ "%d", sid->phy_id);
+ return 0;
+ }
if (sid->link_active) {
host->nodes_active++;
if (sid->contender)
host->irm_id = LOCAL_BUS | sid->phy_id;
}
- } else {
- esid = (struct ext_selfid *)sid;
-
- if ((esid->phy_id != nodeid)
- || (esid->seq_nr != esid_seq)) {
- HPSB_INFO("SelfIDs failed monotony check with "
- "%d/%d", esid->phy_id, esid->seq_nr);
- return 0;
- }
- esid_seq++;
- }
- sid++;
- }
-
- esid = (struct ext_selfid *)(sid - 1);
- while (esid->extended) {
- if ((esid->porta == 0x2) || (esid->portb == 0x2)
- || (esid->portc == 0x2) || (esid->portd == 0x2)
- || (esid->porte == 0x2) || (esid->portf == 0x2)
- || (esid->portg == 0x2) || (esid->porth == 0x2)) {
+ } else {
+ esid = (struct ext_selfid *)sid;
+
+ if ((esid->phy_id != nodeid)
+ || (esid->seq_nr != esid_seq)) {
+ HPSB_INFO("SelfIDs failed monotony check with "
+ "%d/%d", esid->phy_id, esid->seq_nr);
+ return 0;
+ }
+ esid_seq++;
+ }
+ sid++;
+ }
+
+ esid = (struct ext_selfid *)(sid - 1);
+ while (esid->extended) {
+ if ((esid->porta == SELFID_PORT_PARENT) ||
+ (esid->portb == SELFID_PORT_PARENT) ||
+ (esid->portc == SELFID_PORT_PARENT) ||
+ (esid->portd == SELFID_PORT_PARENT) ||
+ (esid->porte == SELFID_PORT_PARENT) ||
+ (esid->portf == SELFID_PORT_PARENT) ||
+ (esid->portg == SELFID_PORT_PARENT) ||
+ (esid->porth == SELFID_PORT_PARENT)) {
HPSB_INFO("SelfIDs failed root check on "
"extended SelfID");
return 0;
- }
- esid--;
- }
+ }
+ esid--;
+ }
- sid = (struct selfid *)esid;
- if ((sid->port0 == 0x2) || (sid->port1 == 0x2) || (sid->port2 == 0x2)) {
+ sid = (struct selfid *)esid;
+ if ((sid->port0 == SELFID_PORT_PARENT) ||
+ (sid->port1 == SELFID_PORT_PARENT) ||
+ (sid->port2 == SELFID_PORT_PARENT)) {
HPSB_INFO("SelfIDs failed root check");
return 0;
- }
+ }
host->node_count = nodeid + 1;
- return 1;
+ return 1;
}
static void build_speed_map(struct hpsb_host *host, int nodecount)
{
u8 speedcap[nodecount];
u8 cldcnt[nodecount];
- u8 *map = host->speed_map;
- struct selfid *sid;
- struct ext_selfid *esid;
- int i, j, n;
-
- for (i = 0; i < (nodecount * 64); i += 64) {
- for (j = 0; j < nodecount; j++) {
- map[i+j] = IEEE1394_SPEED_MAX;
- }
- }
-
- for (i = 0; i < nodecount; i++) {
- cldcnt[i] = 0;
- }
-
- /* find direct children count and speed */
- for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
- n = nodecount - 1;
- (void *)sid >= (void *)host->topology_map; sid--) {
- if (sid->extended) {
- esid = (struct ext_selfid *)sid;
-
- if (esid->porta == 0x3) cldcnt[n]++;
- if (esid->portb == 0x3) cldcnt[n]++;
- if (esid->portc == 0x3) cldcnt[n]++;
- if (esid->portd == 0x3) cldcnt[n]++;
- if (esid->porte == 0x3) cldcnt[n]++;
- if (esid->portf == 0x3) cldcnt[n]++;
- if (esid->portg == 0x3) cldcnt[n]++;
- if (esid->porth == 0x3) cldcnt[n]++;
+ u8 *map = host->speed_map;
+ struct selfid *sid;
+ struct ext_selfid *esid;
+ int i, j, n;
+
+ for (i = 0; i < (nodecount * 64); i += 64) {
+ for (j = 0; j < nodecount; j++) {
+ map[i+j] = IEEE1394_SPEED_MAX;
+ }
+ }
+
+ for (i = 0; i < nodecount; i++) {
+ cldcnt[i] = 0;
+ }
+
+ /* find direct children count and speed */
+ for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
+ n = nodecount - 1;
+ (void *)sid >= (void *)host->topology_map; sid--) {
+ if (sid->extended) {
+ esid = (struct ext_selfid *)sid;
+
+ if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++;
} else {
- if (sid->port0 == 0x3) cldcnt[n]++;
- if (sid->port1 == 0x3) cldcnt[n]++;
- if (sid->port2 == 0x3) cldcnt[n]++;
-
- speedcap[n] = sid->speed;
- n--;
- }
- }
-
- /* set self mapping */
- for (i = 0; i < nodecount; i++) {
- map[64*i + i] = speedcap[i];
- }
-
- /* fix up direct children count to total children count;
- * also fix up speedcaps for sibling and parent communication */
- for (i = 1; i < nodecount; i++) {
- for (j = cldcnt[i], n = i - 1; j > 0; j--) {
- cldcnt[i] += cldcnt[n];
- speedcap[n] = min(speedcap[n], speedcap[i]);
- n -= cldcnt[n] + 1;
- }
- }
-
- for (n = 0; n < nodecount; n++) {
- for (i = n - cldcnt[n]; i <= n; i++) {
- for (j = 0; j < (n - cldcnt[n]); j++) {
- map[j*64 + i] = map[i*64 + j] =
- min(map[i*64 + j], speedcap[n]);
- }
- for (j = n + 1; j < nodecount; j++) {
- map[j*64 + i] = map[i*64 + j] =
- min(map[i*64 + j], speedcap[n]);
- }
- }
- }
+ if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
+
+ speedcap[n] = sid->speed;
+ n--;
+ }
+ }
+
+ /* set self mapping */
+ for (i = 0; i < nodecount; i++) {
+ map[64*i + i] = speedcap[i];
+ }
+
+ /* fix up direct children count to total children count;
+ * also fix up speedcaps for sibling and parent communication */
+ for (i = 1; i < nodecount; i++) {
+ for (j = cldcnt[i], n = i - 1; j > 0; j--) {
+ cldcnt[i] += cldcnt[n];
+ speedcap[n] = min(speedcap[n], speedcap[i]);
+ n -= cldcnt[n] + 1;
+ }
+ }
+
+ for (n = 0; n < nodecount; n++) {
+ for (i = n - cldcnt[n]; i <= n; i++) {
+ for (j = 0; j < (n - cldcnt[n]); j++) {
+ map[j*64 + i] = map[i*64 + j] =
+ min(map[i*64 + j], speedcap[n]);
+ }
+ for (j = n + 1; j < nodecount; j++) {
+ map[j*64 + i] = map[i*64 + j] =
+ min(map[i*64 + j], speedcap[n]);
+ }
+ }
+ }
}
void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
{
- if (host->in_bus_reset) {
- HPSB_VERBOSE("Including SelfID 0x%x", sid);
- host->topology_map[host->selfid_count++] = sid;
- } else {
- HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
+ if (host->in_bus_reset) {
+ HPSB_VERBOSE("Including SelfID 0x%x", sid);
+ host->topology_map[host->selfid_count++] = sid;
+ } else {
+ HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
sid, NODEID_TO_BUS(host->node_id));
- }
+ }
}
void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
@@ -367,50 +373,50 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
if (!host->in_bus_reset)
HPSB_NOTICE("SelfID completion called outside of bus reset!");
- host->node_id = LOCAL_BUS | phyid;
- host->is_root = isroot;
+ host->node_id = LOCAL_BUS | phyid;
+ host->is_root = isroot;
- if (!check_selfids(host)) {
- if (host->reset_retries++ < 20) {
- /* selfid stage did not complete without error */
- HPSB_NOTICE("Error in SelfID stage, resetting");
+ if (!check_selfids(host)) {
+ if (host->reset_retries++ < 20) {
+ /* selfid stage did not complete without error */
+ HPSB_NOTICE("Error in SelfID stage, resetting");
host->in_bus_reset = 0;
/* this should work from ohci1394 now... */
- hpsb_reset_bus(host, LONG_RESET);
- return;
- } else {
- HPSB_NOTICE("Stopping out-of-control reset loop");
- HPSB_NOTICE("Warning - topology map and speed map will not be valid");
+ hpsb_reset_bus(host, LONG_RESET);
+ return;
+ } else {
+ HPSB_NOTICE("Stopping out-of-control reset loop");
+ HPSB_NOTICE("Warning - topology map and speed map will not be valid");
host->reset_retries = 0;
- }
- } else {
+ }
+ } else {
host->reset_retries = 0;
- build_speed_map(host, host->node_count);
- }
+ build_speed_map(host, host->node_count);
+ }
HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
"... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
- /* irm_id is kept up to date by check_selfids() */
- if (host->irm_id == host->node_id) {
- host->is_irm = 1;
- } else {
- host->is_busmgr = 0;
- host->is_irm = 0;
- }
+ /* irm_id is kept up to date by check_selfids() */
+ if (host->irm_id == host->node_id) {
+ host->is_irm = 1;
+ } else {
+ host->is_busmgr = 0;
+ host->is_irm = 0;
+ }
- if (isroot) {
+ if (isroot) {
host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
host->is_cycmst = 1;
}
atomic_inc(&host->generation);
host->in_bus_reset = 0;
- highlevel_host_reset(host);
+ highlevel_host_reset(host);
}
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
- int ackcode)
+ int ackcode)
{
unsigned long flags;
@@ -457,6 +463,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
{
struct hpsb_packet *packet;
+ quadlet_t d = 0;
int retval = 0;
if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||
@@ -466,26 +473,16 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
return -EINVAL;
}
- packet = hpsb_alloc_packet(0);
- if (!packet)
- return -ENOMEM;
-
- packet->host = host;
- packet->header_size = 8;
- packet->data_size = 0;
- packet->expect_response = 0;
- packet->no_waiter = 0;
- packet->type = hpsb_raw;
- packet->header[0] = 0;
if (rootid != -1)
- packet->header[0] |= rootid << 24 | 1 << 23;
+ d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;
if (gapcnt != -1)
- packet->header[0] |= gapcnt << 16 | 1 << 22;
+ d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;
- packet->header[1] = ~packet->header[0];
+ packet = hpsb_make_phypacket(host, d);
+ if (!packet)
+ return -ENOMEM;
packet->generation = get_hpsb_generation(host);
-
retval = hpsb_send_packet_and_wait(packet);
hpsb_free_packet(packet);
@@ -510,13 +507,13 @@ int hpsb_send_packet(struct hpsb_packet *packet)
{
struct hpsb_host *host = packet->host;
- if (host->is_shutdown)
+ if (host->is_shutdown)
return -EINVAL;
if (host->in_bus_reset ||
(packet->generation != get_hpsb_generation(host)))
- return -EAGAIN;
+ return -EAGAIN;
- packet->state = hpsb_queued;
+ packet->state = hpsb_queued;
/* This just seems silly to me */
WARN_ON(packet->no_waiter && packet->expect_response);
@@ -530,42 +527,42 @@ int hpsb_send_packet(struct hpsb_packet *packet)
skb_queue_tail(&host->pending_packet_queue, packet->skb);
}
- if (packet->node_id == host->node_id) {
+ if (packet->node_id == host->node_id) {
/* it is a local request, so handle it locally */
- quadlet_t *data;
- size_t size = packet->data_size + packet->header_size;
+ quadlet_t *data;
+ size_t size = packet->data_size + packet->header_size;
- data = kmalloc(size, GFP_ATOMIC);
- if (!data) {
- HPSB_ERR("unable to allocate memory for concatenating header and data");
- return -ENOMEM;
- }
+ data = kmalloc(size, GFP_ATOMIC);
+ if (!data) {
+ HPSB_ERR("unable to allocate memory for concatenating header and data");
+ return -ENOMEM;
+ }
- memcpy(data, packet->header, packet->header_size);
+ memcpy(data, packet->header, packet->header_size);
- if (packet->data_size)
+ if (packet->data_size)
memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
- dump_packet("send packet local", packet->header, packet->header_size, -1);
+ dump_packet("send packet local", packet->header, packet->header_size, -1);
- hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
- hpsb_packet_received(host, data, size, 0);
+ hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
+ hpsb_packet_received(host, data, size, 0);
- kfree(data);
+ kfree(data);
- return 0;
- }
+ return 0;
+ }
- if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
- packet->speed_code =
- host->speed_map[NODEID_TO_NODE(host->node_id) * 64
- + NODEID_TO_NODE(packet->node_id)];
- }
+ if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
+ packet->speed_code =
+ host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+ + NODEID_TO_NODE(packet->node_id)];
+ }
- dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
+ dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
- return host->driver->transmit_packet(host, packet);
+ return host->driver->transmit_packet(host, packet);
}
/* We could just use complete() directly as the packet complete
@@ -593,81 +590,81 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
static void send_packet_nocare(struct hpsb_packet *packet)
{
- if (hpsb_send_packet(packet) < 0) {
- hpsb_free_packet(packet);
- }
+ if (hpsb_send_packet(packet) < 0) {
+ hpsb_free_packet(packet);
+ }
}
static void handle_packet_response(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size)
{
- struct hpsb_packet *packet = NULL;
+ struct hpsb_packet *packet = NULL;
struct sk_buff *skb;
- int tcode_match = 0;
- int tlabel;
- unsigned long flags;
+ int tcode_match = 0;
+ int tlabel;
+ unsigned long flags;
- tlabel = (data[0] >> 10) & 0x3f;
+ tlabel = (data[0] >> 10) & 0x3f;
spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
skb_queue_walk(&host->pending_packet_queue, skb) {
packet = (struct hpsb_packet *)skb->data;
- if ((packet->tlabel == tlabel)
- && (packet->node_id == (data[1] >> 16))){
- break;
- }
+ if ((packet->tlabel == tlabel)
+ && (packet->node_id == (data[1] >> 16))){
+ break;
+ }
packet = NULL;
- }
+ }
if (packet == NULL) {
- HPSB_DEBUG("unsolicited response packet received - no tlabel match");
- dump_packet("contents", data, 16, -1);
+ HPSB_DEBUG("unsolicited response packet received - no tlabel match");
+ dump_packet("contents", data, 16, -1);
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
- return;
- }
+ return;
+ }
- switch (packet->tcode) {
- case TCODE_WRITEQ:
- case TCODE_WRITEB:
- if (tcode != TCODE_WRITE_RESPONSE)
+ switch (packet->tcode) {
+ case TCODE_WRITEQ:
+ case TCODE_WRITEB:
+ if (tcode != TCODE_WRITE_RESPONSE)
break;
tcode_match = 1;
memcpy(packet->header, data, 12);
- break;
- case TCODE_READQ:
- if (tcode != TCODE_READQ_RESPONSE)
+ break;
+ case TCODE_READQ:
+ if (tcode != TCODE_READQ_RESPONSE)
break;
tcode_match = 1;
memcpy(packet->header, data, 16);
- break;
- case TCODE_READB:
- if (tcode != TCODE_READB_RESPONSE)
+ break;
+ case TCODE_READB:
+ if (tcode != TCODE_READB_RESPONSE)
break;
tcode_match = 1;
BUG_ON(packet->skb->len - sizeof(*packet) < size - 16);
memcpy(packet->header, data, 16);
memcpy(packet->data, data + 4, size - 16);
- break;
- case TCODE_LOCK_REQUEST:
- if (tcode != TCODE_LOCK_RESPONSE)
+ break;
+ case TCODE_LOCK_REQUEST:
+ if (tcode != TCODE_LOCK_RESPONSE)
break;
tcode_match = 1;
size = min((size - 16), (size_t)8);
BUG_ON(packet->skb->len - sizeof(*packet) < size);
memcpy(packet->header, data, 16);
memcpy(packet->data, data + 4, size);
- break;
- }
+ break;
+ }
- if (!tcode_match) {
+ if (!tcode_match) {
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
- HPSB_INFO("unsolicited response packet received - tcode mismatch");
- dump_packet("contents", data, 16, -1);
- return;
- }
+ HPSB_INFO("unsolicited response packet received - tcode mismatch");
+ dump_packet("contents", data, 16, -1);
+ return;
+ }
__skb_unlink(skb, &host->pending_packet_queue);
@@ -686,27 +683,27 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
quadlet_t *data, size_t dsize)
{
- struct hpsb_packet *p;
+ struct hpsb_packet *p;
- p = hpsb_alloc_packet(dsize);
- if (unlikely(p == NULL)) {
- /* FIXME - send data_error response */
- return NULL;
- }
+ p = hpsb_alloc_packet(dsize);
+ if (unlikely(p == NULL)) {
+ /* FIXME - send data_error response */
+ return NULL;
+ }
- p->type = hpsb_async;
- p->state = hpsb_unused;
- p->host = host;
- p->node_id = data[1] >> 16;
- p->tlabel = (data[0] >> 10) & 0x3f;
- p->no_waiter = 1;
+ p->type = hpsb_async;
+ p->state = hpsb_unused;
+ p->host = host;
+ p->node_id = data[1] >> 16;
+ p->tlabel = (data[0] >> 10) & 0x3f;
+ p->no_waiter = 1;
p->generation = get_hpsb_generation(host);
if (dsize % 4)
p->data[dsize / 4] = 0;
- return p;
+ return p;
}
#define PREP_ASYNC_HEAD_RCODE(tc) \
@@ -717,7 +714,7 @@ static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
packet->header[2] = 0
static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
- quadlet_t data)
+ quadlet_t data)
{
PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
packet->header[3] = data;
@@ -726,7 +723,7 @@ static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
}
static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
- int length)
+ int length)
{
if (rcode != RCODE_COMPLETE)
length = 0;
@@ -746,7 +743,7 @@ static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
}
static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,
- int length)
+ int length)
{
if (rcode != RCODE_COMPLETE)
length = 0;
@@ -758,184 +755,184 @@ static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extc
}
#define PREP_REPLY_PACKET(length) \
- packet = create_reply_packet(host, data, length); \
- if (packet == NULL) break
+ packet = create_reply_packet(host, data, length); \
+ if (packet == NULL) break
static void handle_incoming_packet(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size, int write_acked)
{
- struct hpsb_packet *packet;
- int length, rcode, extcode;
- quadlet_t buffer;
- nodeid_t source = data[1] >> 16;
- nodeid_t dest = data[0] >> 16;
- u16 flags = (u16) data[0];
- u64 addr;
-
- /* big FIXME - no error checking is done for an out of bounds length */
-
- switch (tcode) {
- case TCODE_WRITEQ:
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_write(host, source, dest, data+3,
+ struct hpsb_packet *packet;
+ int length, rcode, extcode;
+ quadlet_t buffer;
+ nodeid_t source = data[1] >> 16;
+ nodeid_t dest = data[0] >> 16;
+ u16 flags = (u16) data[0];
+ u64 addr;
+
+ /* big FIXME - no error checking is done for an out of bounds length */
+
+ switch (tcode) {
+ case TCODE_WRITEQ:
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_write(host, source, dest, data+3,
addr, 4, flags);
- if (!write_acked
- && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
- && (rcode >= 0)) {
- /* not a broadcast write, reply */
- PREP_REPLY_PACKET(0);
- fill_async_write_resp(packet, rcode);
- send_packet_nocare(packet);
- }
- break;
-
- case TCODE_WRITEB:
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_write(host, source, dest, data+4,
+ if (!write_acked
+ && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
+ && (rcode >= 0)) {
+ /* not a broadcast write, reply */
+ PREP_REPLY_PACKET(0);
+ fill_async_write_resp(packet, rcode);
+ send_packet_nocare(packet);
+ }
+ break;
+
+ case TCODE_WRITEB:
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_write(host, source, dest, data+4,
addr, data[3]>>16, flags);
- if (!write_acked
- && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
- && (rcode >= 0)) {
- /* not a broadcast write, reply */
- PREP_REPLY_PACKET(0);
- fill_async_write_resp(packet, rcode);
- send_packet_nocare(packet);
- }
- break;
-
- case TCODE_READQ:
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
-
- if (rcode >= 0) {
- PREP_REPLY_PACKET(0);
- fill_async_readquad_resp(packet, rcode, buffer);
- send_packet_nocare(packet);
- }
- break;
-
- case TCODE_READB:
- length = data[3] >> 16;
- PREP_REPLY_PACKET(length);
-
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_read(host, source, packet->data, addr,
- length, flags);
-
- if (rcode >= 0) {
- fill_async_readblock_resp(packet, rcode, length);
- send_packet_nocare(packet);
- } else {
- hpsb_free_packet(packet);
- }
- break;
-
- case TCODE_LOCK_REQUEST:
- length = data[3] >> 16;
- extcode = data[3] & 0xffff;
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-
- PREP_REPLY_PACKET(8);
-
- if ((extcode == 0) || (extcode >= 7)) {
- /* let switch default handle error */
- length = 0;
- }
-
- switch (length) {
- case 4:
- rcode = highlevel_lock(host, source, packet->data, addr,
- data[4], 0, extcode,flags);
- fill_async_lock_resp(packet, rcode, extcode, 4);
- break;
- case 8:
- if ((extcode != EXTCODE_FETCH_ADD)
- && (extcode != EXTCODE_LITTLE_ADD)) {
- rcode = highlevel_lock(host, source,
- packet->data, addr,
- data[5], data[4],
- extcode, flags);
- fill_async_lock_resp(packet, rcode, extcode, 4);
- } else {
- rcode = highlevel_lock64(host, source,
- (octlet_t *)packet->data, addr,
- *(octlet_t *)(data + 4), 0ULL,
- extcode, flags);
- fill_async_lock_resp(packet, rcode, extcode, 8);
- }
- break;
- case 16:
- rcode = highlevel_lock64(host, source,
- (octlet_t *)packet->data, addr,
- *(octlet_t *)(data + 6),
- *(octlet_t *)(data + 4),
- extcode, flags);
- fill_async_lock_resp(packet, rcode, extcode, 8);
- break;
- default:
- rcode = RCODE_TYPE_ERROR;
- fill_async_lock_resp(packet, rcode,
- extcode, 0);
- }
-
- if (rcode >= 0) {
- send_packet_nocare(packet);
- } else {
- hpsb_free_packet(packet);
- }
- break;
- }
+ if (!write_acked
+ && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
+ && (rcode >= 0)) {
+ /* not a broadcast write, reply */
+ PREP_REPLY_PACKET(0);
+ fill_async_write_resp(packet, rcode);
+ send_packet_nocare(packet);
+ }
+ break;
+
+ case TCODE_READQ:
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
+
+ if (rcode >= 0) {
+ PREP_REPLY_PACKET(0);
+ fill_async_readquad_resp(packet, rcode, buffer);
+ send_packet_nocare(packet);
+ }
+ break;
+
+ case TCODE_READB:
+ length = data[3] >> 16;
+ PREP_REPLY_PACKET(length);
+
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_read(host, source, packet->data, addr,
+ length, flags);
+
+ if (rcode >= 0) {
+ fill_async_readblock_resp(packet, rcode, length);
+ send_packet_nocare(packet);
+ } else {
+ hpsb_free_packet(packet);
+ }
+ break;
+
+ case TCODE_LOCK_REQUEST:
+ length = data[3] >> 16;
+ extcode = data[3] & 0xffff;
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+
+ PREP_REPLY_PACKET(8);
+
+ if ((extcode == 0) || (extcode >= 7)) {
+ /* let switch default handle error */
+ length = 0;
+ }
+
+ switch (length) {
+ case 4:
+ rcode = highlevel_lock(host, source, packet->data, addr,
+ data[4], 0, extcode,flags);
+ fill_async_lock_resp(packet, rcode, extcode, 4);
+ break;
+ case 8:
+ if ((extcode != EXTCODE_FETCH_ADD)
+ && (extcode != EXTCODE_LITTLE_ADD)) {
+ rcode = highlevel_lock(host, source,
+ packet->data, addr,
+ data[5], data[4],
+ extcode, flags);
+ fill_async_lock_resp(packet, rcode, extcode, 4);
+ } else {
+ rcode = highlevel_lock64(host, source,
+ (octlet_t *)packet->data, addr,
+ *(octlet_t *)(data + 4), 0ULL,
+ extcode, flags);
+ fill_async_lock_resp(packet, rcode, extcode, 8);
+ }
+ break;
+ case 16:
+ rcode = highlevel_lock64(host, source,
+ (octlet_t *)packet->data, addr,
+ *(octlet_t *)(data + 6),
+ *(octlet_t *)(data + 4),
+ extcode, flags);
+ fill_async_lock_resp(packet, rcode, extcode, 8);
+ break;
+ default:
+ rcode = RCODE_TYPE_ERROR;
+ fill_async_lock_resp(packet, rcode,
+ extcode, 0);
+ }
+
+ if (rcode >= 0) {
+ send_packet_nocare(packet);
+ } else {
+ hpsb_free_packet(packet);
+ }
+ break;
+ }
}
#undef PREP_REPLY_PACKET
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
- int write_acked)
+ int write_acked)
{
- int tcode;
-
- if (host->in_bus_reset) {
- HPSB_INFO("received packet during reset; ignoring");
- return;
- }
-
- dump_packet("received packet", data, size, -1);
-
- tcode = (data[0] >> 4) & 0xf;
-
- switch (tcode) {
- case TCODE_WRITE_RESPONSE:
- case TCODE_READQ_RESPONSE:
- case TCODE_READB_RESPONSE:
- case TCODE_LOCK_RESPONSE:
- handle_packet_response(host, tcode, data, size);
- break;
-
- case TCODE_WRITEQ:
- case TCODE_WRITEB:
- case TCODE_READQ:
- case TCODE_READB:
- case TCODE_LOCK_REQUEST:
- handle_incoming_packet(host, tcode, data, size, write_acked);
- break;
-
-
- case TCODE_ISO_DATA:
- highlevel_iso_receive(host, data, size);
- break;
-
- case TCODE_CYCLE_START:
- /* simply ignore this packet if it is passed on */
- break;
-
- default:
- HPSB_NOTICE("received packet with bogus transaction code %d",
- tcode);
- break;
- }
+ int tcode;
+
+ if (host->in_bus_reset) {
+ HPSB_INFO("received packet during reset; ignoring");
+ return;
+ }
+
+ dump_packet("received packet", data, size, -1);
+
+ tcode = (data[0] >> 4) & 0xf;
+
+ switch (tcode) {
+ case TCODE_WRITE_RESPONSE:
+ case TCODE_READQ_RESPONSE:
+ case TCODE_READB_RESPONSE:
+ case TCODE_LOCK_RESPONSE:
+ handle_packet_response(host, tcode, data, size);
+ break;
+
+ case TCODE_WRITEQ:
+ case TCODE_WRITEB:
+ case TCODE_READQ:
+ case TCODE_READB:
+ case TCODE_LOCK_REQUEST:
+ handle_incoming_packet(host, tcode, data, size, write_acked);
+ break;
+
+
+ case TCODE_ISO_DATA:
+ highlevel_iso_receive(host, data, size);
+ break;
+
+ case TCODE_CYCLE_START:
+ /* simply ignore this packet if it is passed on */
+ break;
+
+ default:
+ HPSB_NOTICE("received packet with bogus transaction code %d",
+ tcode);
+ break;
+ }
}
@@ -1030,10 +1027,10 @@ static int hpsbpkt_thread(void *__hi)
daemonize("khpsbpkt");
+ current->flags |= PF_NOFREEZE;
+
while (1) {
if (down_interruptible(&khpsbpkt_sig)) {
- if (try_to_freeze())
- continue;
printk("khpsbpkt: received unexpected signal?!\n" );
break;
}
@@ -1129,7 +1126,7 @@ static int __init ieee1394_init(void)
nodemgr implements functionality required of ieee1394a-2000
IRMs */
hpsb_disable_irm = 1;
-
+
return 0;
}
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 0b31429d0a6..b35466023f0 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -10,8 +10,8 @@
struct hpsb_packet {
- /* This struct is basically read-only for hosts with the exception of
- * the data buffer contents and xnext - see below. */
+ /* This struct is basically read-only for hosts with the exception of
+ * the data buffer contents and xnext - see below. */
/* This can be used for host driver internal linking.
*
@@ -21,47 +21,47 @@ struct hpsb_packet {
* driver_list when free'ing it. */
struct list_head driver_list;
- nodeid_t node_id;
+ nodeid_t node_id;
- /* Async and Iso types should be clear, raw means send-as-is, do not
- * CRC! Byte swapping shall still be done in this case. */
- enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+ /* Async and Iso types should be clear, raw means send-as-is, do not
+ * CRC! Byte swapping shall still be done in this case. */
+ enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
- /* Okay, this is core internal and a no care for hosts.
- * queued = queued for sending
- * pending = sent, waiting for response
- * complete = processing completed, successful or not
- */
- enum {
- hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
- } __attribute__((packed)) state;
+ /* Okay, this is core internal and a no care for hosts.
+ * queued = queued for sending
+ * pending = sent, waiting for response
+ * complete = processing completed, successful or not
+ */
+ enum {
+ hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
+ } __attribute__((packed)) state;
- /* These are core internal. */
- signed char tlabel;
+ /* These are core internal. */
+ signed char tlabel;
signed char ack_code;
unsigned char tcode;
- unsigned expect_response:1;
- unsigned no_waiter:1;
+ unsigned expect_response:1;
+ unsigned no_waiter:1;
- /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
- unsigned speed_code:2;
+ /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
+ unsigned speed_code:2;
- /*
- * *header and *data are guaranteed to be 32-bit DMAable and may be
- * overwritten to allow in-place byte swapping. Neither of these is
- * CRCed (the sizes also don't include CRC), but contain space for at
- * least one additional quadlet to allow in-place CRCing. The memory is
- * also guaranteed to be DMA mappable.
- */
- quadlet_t *header;
- quadlet_t *data;
- size_t header_size;
- size_t data_size;
+ /*
+ * *header and *data are guaranteed to be 32-bit DMAable and may be
+ * overwritten to allow in-place byte swapping. Neither of these is
+ * CRCed (the sizes also don't include CRC), but contain space for at
+ * least one additional quadlet to allow in-place CRCing. The memory is
+ * also guaranteed to be DMA mappable.
+ */
+ quadlet_t *header;
+ quadlet_t *data;
+ size_t header_size;
+ size_t data_size;
- struct hpsb_host *host;
- unsigned int generation;
+ struct hpsb_host *host;
+ unsigned int generation;
atomic_t refcnt;
@@ -73,10 +73,10 @@ struct hpsb_packet {
/* XXX This is just a hack at the moment */
struct sk_buff *skb;
- /* Store jiffies for implementing bus timeouts. */
- unsigned long sendtime;
+ /* Store jiffies for implementing bus timeouts. */
+ unsigned long sendtime;
- quadlet_t embedded_header[5];
+ quadlet_t embedded_header[5];
};
/* Set a task for when a packet completes */
@@ -102,7 +102,7 @@ void hpsb_free_packet(struct hpsb_packet *packet);
*/
static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
{
- return atomic_read(&host->generation);
+ return atomic_read(&host->generation);
}
/*
@@ -157,7 +157,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
* from within a transmit packet routine.
*/
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
- int ackcode);
+ int ackcode);
/*
* Hand over received packet to the core. The contents of data are expected to
@@ -171,7 +171,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
* packet type.
*/
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
- int write_acked);
+ int write_acked);
/*
@@ -197,20 +197,20 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
* Block 15 (240-255) reserved for drivers under development, etc.
*/
-#define IEEE1394_MAJOR 171
+#define IEEE1394_MAJOR 171
-#define IEEE1394_MINOR_BLOCK_RAW1394 0
-#define IEEE1394_MINOR_BLOCK_VIDEO1394 1
-#define IEEE1394_MINOR_BLOCK_DV1394 2
-#define IEEE1394_MINOR_BLOCK_AMDTP 3
+#define IEEE1394_MINOR_BLOCK_RAW1394 0
+#define IEEE1394_MINOR_BLOCK_VIDEO1394 1
+#define IEEE1394_MINOR_BLOCK_DV1394 2
+#define IEEE1394_MINOR_BLOCK_AMDTP 3
#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
-#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
-#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
-#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
-#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
-#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
+#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
+#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
+#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
+#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
+#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
+#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
/* return the index (within a minor number block) of a file */
static inline unsigned char ieee1394_file_to_instance(struct file *file)
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 0aa876360f9..3fe2f6c4a25 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -22,7 +22,7 @@
#include "ieee1394_core.h"
#include "highlevel.h"
#include "nodemgr.h"
-
+#include "ieee1394_transactions.h"
#define PREP_ASYNC_HEAD_ADDRESS(tc) \
packet->tcode = tc; \
@@ -31,80 +31,82 @@
packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
packet->header[2] = addr & 0xffffffff
-
static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
- packet->header_size = 12;
- packet->data_size = 0;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
+ packet->header_size = 12;
+ packet->data_size = 0;
+ packet->expect_response = 1;
}
-static void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length)
+static void fill_async_readblock(struct hpsb_packet *packet, u64 addr,
+ int length)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
- packet->header[3] = length << 16;
- packet->header_size = 16;
- packet->data_size = 0;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
+ packet->header[3] = length << 16;
+ packet->header_size = 16;
+ packet->data_size = 0;
+ packet->expect_response = 1;
}
-static void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data)
+static void fill_async_writequad(struct hpsb_packet *packet, u64 addr,
+ quadlet_t data)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
- packet->header[3] = data;
- packet->header_size = 16;
- packet->data_size = 0;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
+ packet->header[3] = data;
+ packet->header_size = 16;
+ packet->data_size = 0;
+ packet->expect_response = 1;
}
-static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length)
+static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr,
+ int length)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
- packet->header[3] = length << 16;
- packet->header_size = 16;
- packet->expect_response = 1;
- packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
+ packet->header[3] = length << 16;
+ packet->header_size = 16;
+ packet->expect_response = 1;
+ packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
}
static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
- int length)
+ int length)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
- packet->header[3] = (length << 16) | extcode;
- packet->header_size = 16;
- packet->data_size = length;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
+ packet->header[3] = (length << 16) | extcode;
+ packet->header_size = 16;
+ packet->data_size = length;
+ packet->expect_response = 1;
}
static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
- int tag, int sync)
+ int tag, int sync)
{
- packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_ISO_DATA << 4) | sync;
+ packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
+ | (TCODE_ISO_DATA << 4) | sync;
- packet->header_size = 4;
- packet->data_size = length;
- packet->type = hpsb_iso;
- packet->tcode = TCODE_ISO_DATA;
+ packet->header_size = 4;
+ packet->data_size = length;
+ packet->type = hpsb_iso;
+ packet->tcode = TCODE_ISO_DATA;
}
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
{
- packet->header[0] = data;
- packet->header[1] = ~data;
- packet->header_size = 8;
- packet->data_size = 0;
- packet->expect_response = 0;
- packet->type = hpsb_raw; /* No CRC added */
- packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */
+ packet->header[0] = data;
+ packet->header[1] = ~data;
+ packet->header_size = 8;
+ packet->data_size = 0;
+ packet->expect_response = 0;
+ packet->type = hpsb_raw; /* No CRC added */
+ packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */
}
static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
int channel, int tag, int sync)
{
packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_STREAM_DATA << 4) | sync;
+ | (TCODE_STREAM_DATA << 4) | sync;
packet->header_size = 4;
packet->data_size = length;
@@ -171,99 +173,96 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
*/
void hpsb_free_tlabel(struct hpsb_packet *packet)
{
- unsigned long flags;
+ unsigned long flags;
struct hpsb_tlabel_pool *tp;
tp = &packet->host->tpool[packet->node_id & NODE_MASK];
BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
- spin_lock_irqsave(&tp->lock, flags);
+ spin_lock_irqsave(&tp->lock, flags);
BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
- spin_unlock_irqrestore(&tp->lock, flags);
+ spin_unlock_irqrestore(&tp->lock, flags);
up(&tp->count);
}
-
-
int hpsb_packet_success(struct hpsb_packet *packet)
{
- switch (packet->ack_code) {
- case ACK_PENDING:
- switch ((packet->header[1] >> 12) & 0xf) {
- case RCODE_COMPLETE:
- return 0;
- case RCODE_CONFLICT_ERROR:
- return -EAGAIN;
- case RCODE_DATA_ERROR:
- return -EREMOTEIO;
- case RCODE_TYPE_ERROR:
- return -EACCES;
- case RCODE_ADDRESS_ERROR:
- return -EINVAL;
- default:
- HPSB_ERR("received reserved rcode %d from node %d",
- (packet->header[1] >> 12) & 0xf,
- packet->node_id);
- return -EAGAIN;
- }
- HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
-
- case ACK_BUSY_X:
- case ACK_BUSY_A:
- case ACK_BUSY_B:
- return -EBUSY;
-
- case ACK_TYPE_ERROR:
- return -EACCES;
-
- case ACK_COMPLETE:
- if (packet->tcode == TCODE_WRITEQ
- || packet->tcode == TCODE_WRITEB) {
- return 0;
- } else {
- HPSB_ERR("impossible ack_complete from node %d "
- "(tcode %d)", packet->node_id, packet->tcode);
- return -EAGAIN;
- }
-
-
- case ACK_DATA_ERROR:
- if (packet->tcode == TCODE_WRITEB
- || packet->tcode == TCODE_LOCK_REQUEST) {
- return -EAGAIN;
- } else {
- HPSB_ERR("impossible ack_data_error from node %d "
- "(tcode %d)", packet->node_id, packet->tcode);
- return -EAGAIN;
- }
-
- case ACK_ADDRESS_ERROR:
- return -EINVAL;
-
- case ACK_TARDY:
- case ACK_CONFLICT_ERROR:
- case ACKX_NONE:
- case ACKX_SEND_ERROR:
- case ACKX_ABORTED:
- case ACKX_TIMEOUT:
- /* error while sending */
- return -EAGAIN;
-
- default:
- HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
- packet->ack_code, packet->node_id, packet->tcode);
- return -EAGAIN;
- }
-
- HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
+ switch (packet->ack_code) {
+ case ACK_PENDING:
+ switch ((packet->header[1] >> 12) & 0xf) {
+ case RCODE_COMPLETE:
+ return 0;
+ case RCODE_CONFLICT_ERROR:
+ return -EAGAIN;
+ case RCODE_DATA_ERROR:
+ return -EREMOTEIO;
+ case RCODE_TYPE_ERROR:
+ return -EACCES;
+ case RCODE_ADDRESS_ERROR:
+ return -EINVAL;
+ default:
+ HPSB_ERR("received reserved rcode %d from node %d",
+ (packet->header[1] >> 12) & 0xf,
+ packet->node_id);
+ return -EAGAIN;
+ }
+ HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
+
+ case ACK_BUSY_X:
+ case ACK_BUSY_A:
+ case ACK_BUSY_B:
+ return -EBUSY;
+
+ case ACK_TYPE_ERROR:
+ return -EACCES;
+
+ case ACK_COMPLETE:
+ if (packet->tcode == TCODE_WRITEQ
+ || packet->tcode == TCODE_WRITEB) {
+ return 0;
+ } else {
+ HPSB_ERR("impossible ack_complete from node %d "
+ "(tcode %d)", packet->node_id, packet->tcode);
+ return -EAGAIN;
+ }
+
+ case ACK_DATA_ERROR:
+ if (packet->tcode == TCODE_WRITEB
+ || packet->tcode == TCODE_LOCK_REQUEST) {
+ return -EAGAIN;
+ } else {
+ HPSB_ERR("impossible ack_data_error from node %d "
+ "(tcode %d)", packet->node_id, packet->tcode);
+ return -EAGAIN;
+ }
+
+ case ACK_ADDRESS_ERROR:
+ return -EINVAL;
+
+ case ACK_TARDY:
+ case ACK_CONFLICT_ERROR:
+ case ACKX_NONE:
+ case ACKX_SEND_ERROR:
+ case ACKX_ABORTED:
+ case ACKX_TIMEOUT:
+ /* error while sending */
+ return -EAGAIN;
+
+ default:
+ HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
+ packet->ack_code, packet->node_id, packet->tcode);
+ return -EAGAIN;
+ }
+
+ HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
}
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, size_t length)
{
- struct hpsb_packet *packet;
+ struct hpsb_packet *packet;
if (length == 0)
return NULL;
@@ -288,8 +287,9 @@ struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
return packet;
}
-struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node,
- u64 addr, quadlet_t *buffer, size_t length)
+struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, nodeid_t node,
+ u64 addr, quadlet_t * buffer,
+ size_t length)
{
struct hpsb_packet *packet;
@@ -300,7 +300,7 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
if (!packet)
return NULL;
- if (length % 4) { /* zero padding bytes */
+ if (length % 4) { /* zero padding bytes */
packet->data[length >> 2] = 0;
}
packet->host = host;
@@ -322,8 +322,9 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
return packet;
}
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, int length,
- int channel, int tag, int sync)
+struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
+ int length, int channel, int tag,
+ int sync)
{
struct hpsb_packet *packet;
@@ -334,7 +335,7 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
if (!packet)
return NULL;
- if (length % 4) { /* zero padding bytes */
+ if (length % 4) { /* zero padding bytes */
packet->data[length >> 2] = 0;
}
packet->host = host;
@@ -352,14 +353,15 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
}
struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
- u64 addr, int extcode, quadlet_t *data,
- quadlet_t arg)
+ u64 addr, int extcode,
+ quadlet_t * data, quadlet_t arg)
{
struct hpsb_packet *p;
u32 length;
p = hpsb_alloc_packet(8);
- if (!p) return NULL;
+ if (!p)
+ return NULL;
p->host = host;
p->node_id = node;
@@ -388,15 +390,16 @@ struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
return p;
}
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
- u64 addr, int extcode, octlet_t *data,
- octlet_t arg)
+struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
+ nodeid_t node, u64 addr, int extcode,
+ octlet_t * data, octlet_t arg)
{
struct hpsb_packet *p;
u32 length;
p = hpsb_alloc_packet(16);
- if (!p) return NULL;
+ if (!p)
+ return NULL;
p->host = host;
p->node_id = node;
@@ -429,18 +432,18 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node
return p;
}
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
- quadlet_t data)
+struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
{
- struct hpsb_packet *p;
+ struct hpsb_packet *p;
- p = hpsb_alloc_packet(0);
- if (!p) return NULL;
+ p = hpsb_alloc_packet(0);
+ if (!p)
+ return NULL;
- p->host = host;
- fill_phy_packet(p, data);
+ p->host = host;
+ fill_phy_packet(p, data);
- return p;
+ return p;
}
struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
@@ -450,7 +453,8 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
struct hpsb_packet *p;
p = hpsb_alloc_packet(length);
- if (!p) return NULL;
+ if (!p)
+ return NULL;
p->host = host;
fill_iso_packet(p, length, channel, tag, sync);
@@ -466,47 +470,46 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
*/
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, quadlet_t *buffer, size_t length)
+ u64 addr, quadlet_t * buffer, size_t length)
{
- struct hpsb_packet *packet;
- int retval = 0;
+ struct hpsb_packet *packet;
+ int retval = 0;
- if (length == 0)
- return -EINVAL;
+ if (length == 0)
+ return -EINVAL;
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+ BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_readpacket(host, node, addr, length);
- if (!packet) {
- return -ENOMEM;
- }
+ if (!packet) {
+ return -ENOMEM;
+ }
packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
+ retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_read_fail;
- retval = hpsb_packet_success(packet);
+ retval = hpsb_packet_success(packet);
- if (retval == 0) {
- if (length == 4) {
- *buffer = packet->header[3];
- } else {
- memcpy(buffer, packet->data, length);
- }
- }
+ if (retval == 0) {
+ if (length == 4) {
+ *buffer = packet->header[3];
+ } else {
+ memcpy(buffer, packet->data, length);
+ }
+ }
-hpsb_read_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
+ hpsb_read_fail:
+ hpsb_free_tlabel(packet);
+ hpsb_free_packet(packet);
- return retval;
+ return retval;
}
-
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, quadlet_t *buffer, size_t length)
+ u64 addr, quadlet_t * buffer, size_t length)
{
struct hpsb_packet *packet;
int retval;
@@ -514,62 +517,61 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
if (length == 0)
return -EINVAL;
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+ BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
- packet = hpsb_make_writepacket (host, node, addr, buffer, length);
+ packet = hpsb_make_writepacket(host, node, addr, buffer, length);
if (!packet)
return -ENOMEM;
packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
+ retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_write_fail;
- retval = hpsb_packet_success(packet);
+ retval = hpsb_packet_success(packet);
-hpsb_write_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
+ hpsb_write_fail:
+ hpsb_free_tlabel(packet);
+ hpsb_free_packet(packet);
- return retval;
+ return retval;
}
#if 0
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
+ u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
{
- struct hpsb_packet *packet;
- int retval = 0;
+ struct hpsb_packet *packet;
+ int retval = 0;
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+ BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
- if (!packet)
- return -ENOMEM;
+ if (!packet)
+ return -ENOMEM;
packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
+ retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_lock_fail;
- retval = hpsb_packet_success(packet);
+ retval = hpsb_packet_success(packet);
- if (retval == 0) {
- *data = packet->data[0];
- }
+ if (retval == 0) {
+ *data = packet->data[0];
+ }
-hpsb_lock_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
+ hpsb_lock_fail:
+ hpsb_free_tlabel(packet);
+ hpsb_free_packet(packet);
- return retval;
+ return retval;
}
-
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
- quadlet_t *buffer, size_t length, u32 specifier_id,
+ quadlet_t * buffer, size_t length, u32 specifier_id,
unsigned int version)
{
struct hpsb_packet *packet;
@@ -586,7 +588,8 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
return -ENOMEM;
packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
- packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
+ packet->data[1] =
+ cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
memcpy(&(packet->data[2]), buffer, length - 8);
@@ -601,4 +604,4 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
return retval;
}
-#endif /* 0 */
+#endif /* 0 */
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index 615541b8b90..f26680ebef7 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -36,20 +36,22 @@ void hpsb_iso_shutdown(struct hpsb_iso *iso)
kfree(iso);
}
-static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type,
+static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
+ enum hpsb_iso_type type,
unsigned int data_buf_size,
unsigned int buf_packets,
- int channel,
- int dma_mode,
+ int channel, int dma_mode,
int irq_interval,
- void (*callback)(struct hpsb_iso*))
+ void (*callback) (struct hpsb_iso
+ *))
{
struct hpsb_iso *iso;
int dma_direction;
/* make sure driver supports the ISO API */
if (!host->driver->isoctl) {
- printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n",
+ printk(KERN_INFO
+ "ieee1394: host driver '%s' does not support the rawiso API\n",
host->driver->name);
return NULL;
}
@@ -59,12 +61,13 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
if (buf_packets < 2)
buf_packets = 2;
- if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
- dma_mode=HPSB_ISO_DMA_DEFAULT;
+ if ((dma_mode < HPSB_ISO_DMA_DEFAULT)
+ || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
+ dma_mode = HPSB_ISO_DMA_DEFAULT;
if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
- irq_interval = buf_packets / 4;
- if (irq_interval == 0) /* really interrupt for each packet*/
+ irq_interval = buf_packets / 4;
+ if (irq_interval == 0) /* really interrupt for each packet */
irq_interval = 1;
if (channel < -1 || channel >= 64)
@@ -76,7 +79,10 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
/* allocate and write the struct hpsb_iso */
- iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL);
+ iso =
+ kmalloc(sizeof(*iso) +
+ buf_packets * sizeof(struct hpsb_iso_packet_info),
+ GFP_KERNEL);
if (!iso)
return NULL;
@@ -111,17 +117,18 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
iso->prebuffer = 0;
/* allocate the packet buffer */
- if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
+ if (dma_region_alloc
+ (&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
goto err;
return iso;
-err:
+ err:
hpsb_iso_shutdown(iso);
return NULL;
}
-int hpsb_iso_n_ready(struct hpsb_iso* iso)
+int hpsb_iso_n_ready(struct hpsb_iso *iso)
{
unsigned long flags;
int val;
@@ -133,18 +140,19 @@ int hpsb_iso_n_ready(struct hpsb_iso* iso)
return val;
}
-
-struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
+struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int speed,
int irq_interval,
- void (*callback)(struct hpsb_iso*))
+ void (*callback) (struct hpsb_iso *))
{
struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
data_buf_size, buf_packets,
- channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback);
+ channel,
+ HPSB_ISO_DMA_DEFAULT,
+ irq_interval, callback);
if (!iso)
return NULL;
@@ -157,22 +165,23 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
iso->flags |= HPSB_ISO_DRIVER_INIT;
return iso;
-err:
+ err:
hpsb_iso_shutdown(iso);
return NULL;
}
-struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
+struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int dma_mode,
int irq_interval,
- void (*callback)(struct hpsb_iso*))
+ void (*callback) (struct hpsb_iso *))
{
struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
data_buf_size, buf_packets,
- channel, dma_mode, irq_interval, callback);
+ channel, dma_mode,
+ irq_interval, callback);
if (!iso)
return NULL;
@@ -183,7 +192,7 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
iso->flags |= HPSB_ISO_DRIVER_INIT;
return iso;
-err:
+ err:
hpsb_iso_shutdown(iso);
return NULL;
}
@@ -197,16 +206,17 @@ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
{
- if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
- return -EINVAL;
- return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
+ if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
+ return -EINVAL;
+ return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
}
int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
{
if (iso->type != HPSB_ISO_RECV || iso->channel != -1)
return -EINVAL;
- return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask);
+ return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK,
+ (unsigned long)&mask);
}
int hpsb_iso_recv_flush(struct hpsb_iso *iso)
@@ -283,7 +293,9 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
isoctl_args[2] = sync;
- retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]);
+ retval =
+ iso->host->driver->isoctl(iso, RECV_START,
+ (unsigned long)&isoctl_args[0]);
if (retval)
return retval;
@@ -296,7 +308,8 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
unsigned int offset, unsigned short len,
- unsigned int *out_offset, unsigned short *out_len)
+ unsigned int *out_offset,
+ unsigned short *out_len)
{
if (offset >= iso->buf_size)
return -EFAULT;
@@ -316,8 +329,8 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
return 0;
}
-
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy)
+int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
+ u8 tag, u8 sy)
{
struct hpsb_iso_packet_info *info;
unsigned long flags;
@@ -334,7 +347,8 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
info = &iso->infos[iso->first_packet];
/* check for bogus offset/length */
- if (hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len))
+ if (hpsb_iso_check_offset_len
+ (iso, offset, len, &info->offset, &info->len))
return -EFAULT;
info->tag = tag;
@@ -342,13 +356,13 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
spin_lock_irqsave(&iso->lock, flags);
- rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info);
+ rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info);
if (rv)
goto out;
/* increment cursors */
- iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
- iso->xmit_cycle = (iso->xmit_cycle+1) % 8000;
+ iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
+ iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000;
iso->n_ready_packets--;
if (iso->prebuffer != 0) {
@@ -359,7 +373,7 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
}
}
-out:
+ out:
spin_unlock_irqrestore(&iso->lock, flags);
return rv;
}
@@ -369,7 +383,9 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
if (iso->type != HPSB_ISO_XMIT)
return -EINVAL;
- return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets);
+ return wait_event_interruptible(iso->waitq,
+ hpsb_iso_n_ready(iso) ==
+ iso->buf_packets);
}
void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
@@ -396,7 +412,8 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
}
void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
- u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy)
+ u16 total_len, u16 cycle, u8 channel, u8 tag,
+ u8 sy)
{
unsigned long flags;
spin_lock_irqsave(&iso->lock, flags);
@@ -416,7 +433,7 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
info->tag = tag;
info->sy = sy;
- iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets;
+ iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
iso->n_ready_packets++;
}
@@ -435,20 +452,21 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
spin_lock_irqsave(&iso->lock, flags);
for (i = 0; i < n_packets; i++) {
rv = iso->host->driver->isoctl(iso, RECV_RELEASE,
- (unsigned long) &iso->infos[iso->first_packet]);
+ (unsigned long)&iso->infos[iso->
+ first_packet]);
if (rv)
break;
- iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
+ iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
iso->n_ready_packets--;
/* release memory from packets discarded when queue was full */
- if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */
+ if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */
if (iso->bytes_discarded != 0) {
struct hpsb_iso_packet_info inf;
inf.total_len = iso->bytes_discarded;
iso->host->driver->isoctl(iso, RECV_RELEASE,
- (unsigned long) &inf);
+ (unsigned long)&inf);
iso->bytes_discarded = 0;
}
}
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index f2453668acf..082c7fd239f 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -743,21 +743,20 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
unsigned int generation)
{
struct hpsb_host *host = hi->host;
- struct node_entry *ne;
-
- ne = kmalloc(sizeof(struct node_entry), GFP_KERNEL);
- if (!ne) return NULL;
+ struct node_entry *ne;
- memset(ne, 0, sizeof(struct node_entry));
+ ne = kzalloc(sizeof(*ne), GFP_KERNEL);
+ if (!ne)
+ return NULL;
ne->tpool = &host->tpool[nodeid & NODE_MASK];
- ne->host = host;
- ne->nodeid = nodeid;
+ ne->host = host;
+ ne->nodeid = nodeid;
ne->generation = generation;
ne->needs_probe = 1;
- ne->guid = guid;
+ ne->guid = guid;
ne->guid_vendor_id = (guid >> 40) & 0xffffff;
ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id);
ne->csr = csr;
@@ -787,7 +786,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
(host->node_id == nodeid) ? "Host" : "Node",
NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
- return ne;
+ return ne;
}
@@ -872,12 +871,10 @@ static struct unit_directory *nodemgr_process_unit_directory
struct csr1212_keyval *kv;
u8 last_key_id = 0;
- ud = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+ ud = kzalloc(sizeof(*ud), GFP_KERNEL);
if (!ud)
goto unit_directory_error;
- memset (ud, 0, sizeof(struct unit_directory));
-
ud->ne = ne;
ud->ignore_driver = ignore_drivers;
ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;
@@ -937,10 +934,10 @@ static struct unit_directory *nodemgr_process_unit_directory
/* Logical Unit Number */
if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
- ud_child = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+ ud_child = kmalloc(sizeof(*ud_child), GFP_KERNEL);
if (!ud_child)
goto unit_directory_error;
- memcpy(ud_child, ud, sizeof(struct unit_directory));
+ memcpy(ud_child, ud, sizeof(*ud_child));
nodemgr_register_device(ne, ud_child, &ne->device);
ud_child = NULL;
@@ -1200,7 +1197,7 @@ static void nodemgr_node_scan_one(struct host_info *hi,
struct csr1212_csr *csr;
struct nodemgr_csr_info *ci;
- ci = kmalloc(sizeof(struct nodemgr_csr_info), GFP_KERNEL);
+ ci = kmalloc(sizeof(*ci), GFP_KERNEL);
if (!ci)
return;
@@ -1410,14 +1407,28 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
struct hpsb_host *host = hi->host;
struct class *class = &nodemgr_ne_class;
struct class_device *cdev;
+ struct node_entry *ne;
/* Do some processing of the nodes we've probed. This pulls them
* into the sysfs layer if needed, and can result in processing of
* unit-directories, or just updating the node and it's
- * unit-directories. */
+ * unit-directories.
+ *
+ * Run updates before probes. Usually, updates are time-critical
+ * while probes are time-consuming. (Well, those probes need some
+ * improvement...) */
+
down_read(&class->subsys.rwsem);
- list_for_each_entry(cdev, &class->children, node)
- nodemgr_probe_ne(hi, container_of(cdev, struct node_entry, class_dev), generation);
+ list_for_each_entry(cdev, &class->children, node) {
+ ne = container_of(cdev, struct node_entry, class_dev);
+ if (!ne->needs_probe)
+ nodemgr_probe_ne(hi, ne, generation);
+ }
+ list_for_each_entry(cdev, &class->children, node) {
+ ne = container_of(cdev, struct node_entry, class_dev);
+ if (ne->needs_probe)
+ nodemgr_probe_ne(hi, ne, generation);
+ }
up_read(&class->subsys.rwsem);
@@ -1448,7 +1459,8 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host)
int ret = 1;
packet = hpsb_make_phypacket(host,
- 0x003c0000 | NODEID_TO_NODE(host->node_id) << 24);
+ EXTPHYPACKET_TYPE_RESUME |
+ NODEID_TO_NODE(host->node_id) << PHYPACKET_PORT_SHIFT);
if (packet) {
packet->no_waiter = 1;
packet->generation = get_hpsb_generation(host);
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 3a2f0c02fd0..0b26616e16c 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -151,24 +151,6 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
}
/*
- * Returns a node entry (which has its reference count incremented) or NULL if
- * the GUID in question is not known. Getting a valid entry does not mean that
- * the node with this GUID is currently accessible (might be powered down).
- */
-struct node_entry *hpsb_guid_get_entry(u64 guid);
-
-/* Same as above, but use the nodeid to get an node entry. This is not
- * fool-proof by itself, since the nodeid can change. */
-struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid);
-
-/*
- * If the entry refers to a local host, this function will return the pointer
- * to the hpsb_host structure. It will return NULL otherwise. Once you have
- * established it is a local host, you can use that knowledge from then on (the
- * GUID won't wander to an external node). */
-struct hpsb_host *hpsb_get_host_by_ne(struct node_entry *ne);
-
-/*
* This will fill in the given, pre-initialised hpsb_packet with the current
* information from the node entry (host, node ID, generation number). It will
* return false if the node owning the GUID is not accessible (and not modify the
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 4cf9b8f3e33..b6b96fa04d6 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -161,9 +161,6 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
#define PRINT(level, fmt, args...) \
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
-static char version[] __devinitdata =
- "$Rev: 1313 $ Ben Collins <bcollins@debian.org>";
-
/* Module Parameters */
static int phys_dma = 1;
module_param(phys_dma, int, 0644);
@@ -587,12 +584,13 @@ static void ohci_initialize(struct ti_ohci *ohci)
sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
#endif
PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
- "MMIO=[%lx-%lx] Max Packet=[%d]",
+ "MMIO=[%lx-%lx] Max Packet=[%d] IR/IT contexts=[%d/%d]",
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
pci_resource_start(ohci->dev, 0),
pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
- ohci->max_packet_size);
+ ohci->max_packet_size,
+ ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx);
/* Check all of our ports to make sure that if anything is
* connected, we enable that port. */
@@ -2960,28 +2958,23 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
d->ctrlClear = 0;
d->cmdPtr = 0;
- d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_ATOMIC);
- d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC);
+ d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC);
+ d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
if (d->buf_cpu == NULL || d->buf_bus == NULL) {
PRINT(KERN_ERR, "Failed to allocate dma buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
- memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*));
- memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t));
- d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*),
- GFP_ATOMIC);
- d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC);
+ d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC);
+ d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
PRINT(KERN_ERR, "Failed to allocate dma prg");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
- memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*));
- memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
@@ -3093,17 +3086,14 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
d->ctrlClear = 0;
d->cmdPtr = 0;
- d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*),
- GFP_KERNEL);
- d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
+ d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL);
+ d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
PRINT(KERN_ERR, "Failed to allocate at dma prg");
free_dma_trm_ctx(d);
return -ENOMEM;
}
- memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*));
- memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
len = sprintf(pool_name, "ohci1394_trm_prg");
sprintf(pool_name+len, "%d", num_allocs);
@@ -3201,8 +3191,6 @@ static struct hpsb_host_driver ohci1394_driver = {
.hw_csr_reg = ohci_hw_csr_reg,
};
-
-
/***********************************
* PCI Driver Interface functions *
***********************************/
@@ -3217,15 +3205,10 @@ do { \
static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- static int version_printed = 0;
-
struct hpsb_host *host;
struct ti_ohci *ohci; /* shortcut to currently handled device */
unsigned long ohci_base;
- if (version_printed++ == 0)
- PRINT_G(KERN_INFO, "%s", version);
-
if (pci_enable_device(dev))
FAIL(-ENXIO, "Failed to enable OHCI hardware");
pci_set_master(dev);
@@ -3369,13 +3352,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
/* Determine the number of available IR and IT contexts. */
ohci->nb_iso_rcv_ctx =
get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
- DBGMSG("%d iso receive contexts available",
- ohci->nb_iso_rcv_ctx);
-
ohci->nb_iso_xmit_ctx =
get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
- DBGMSG("%d iso transmit contexts available",
- ohci->nb_iso_xmit_ctx);
/* Set the usage bits for non-existent contexts so they can't
* be allocated */
@@ -3606,8 +3584,6 @@ static struct pci_driver ohci1394_pci_driver = {
.suspend = ohci1394_pci_suspend,
};
-
-
/***********************************
* OHCI1394 Video Interface *
***********************************/
@@ -3714,7 +3690,6 @@ EXPORT_SYMBOL(ohci1394_init_iso_tasklet);
EXPORT_SYMBOL(ohci1394_register_iso_tasklet);
EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet);
-
/***********************************
* General module initialization *
***********************************/
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index cc66c1cae25..7df0962144e 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -219,8 +219,8 @@ struct ti_ohci {
int self_id_errors;
- /* Tasklets for iso receive and transmit, used by video1394,
- * amdtp and dv1394 */
+ /* Tasklets for iso receive and transmit, used by video1394
+ * and dv1394 */
struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 6b1ab875333..e2edc41e1b6 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1435,7 +1435,7 @@ static int __devinit add_card(struct pci_dev *dev,
struct i2c_algo_bit_data i2c_adapter_data;
error = -ENOMEM;
- i2c_ad = kmalloc(sizeof(struct i2c_adapter), SLAB_KERNEL);
+ i2c_ad = kmalloc(sizeof(*i2c_ad), SLAB_KERNEL);
if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 24411e666b2..b0523563991 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -102,12 +102,9 @@ static struct pending_request *__alloc_pending_request(gfp_t flags)
{
struct pending_request *req;
- req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
- flags);
- if (req != NULL) {
- memset(req, 0, sizeof(struct pending_request));
+ req = kzalloc(sizeof(*req), flags);
+ if (req)
INIT_LIST_HEAD(&req->list);
- }
return req;
}
@@ -192,9 +189,9 @@ static void add_host(struct hpsb_host *host)
struct host_info *hi;
unsigned long flags;
- hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
+ hi = kmalloc(sizeof(*hi), GFP_KERNEL);
- if (hi != NULL) {
+ if (hi) {
INIT_LIST_HEAD(&hi->list);
hi->host = host;
INIT_LIST_HEAD(&hi->file_info_list);
@@ -315,8 +312,8 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
break;
if (!ibs) {
- ibs = kmalloc(sizeof(struct iso_block_store)
- + length, SLAB_ATOMIC);
+ ibs = kmalloc(sizeof(*ibs) + length,
+ SLAB_ATOMIC);
if (!ibs) {
kfree(req);
break;
@@ -376,8 +373,8 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
break;
if (!ibs) {
- ibs = kmalloc(sizeof(struct iso_block_store)
- + length, SLAB_ATOMIC);
+ ibs = kmalloc(sizeof(*ibs) + length,
+ SLAB_ATOMIC);
if (!ibs) {
kfree(req);
break;
@@ -502,10 +499,9 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
switch (req->req.type) {
case RAW1394_REQ_LIST_CARDS:
spin_lock_irqsave(&host_info_lock, flags);
- khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
- SLAB_ATOMIC);
+ khl = kmalloc(sizeof(*khl) * host_count, SLAB_ATOMIC);
- if (khl != NULL) {
+ if (khl) {
req->req.misc = host_count;
req->data = (quadlet_t *) khl;
@@ -517,7 +513,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
}
spin_unlock_irqrestore(&host_info_lock, flags);
- if (khl != NULL) {
+ if (khl) {
req->req.error = RAW1394_ERROR_NONE;
req->req.length = min(req->req.length,
(u32) (sizeof
@@ -1647,13 +1643,13 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
return (-EINVAL);
}
/* addr-list-entry for fileinfo */
- addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL);
+ addr = kmalloc(sizeof(*addr), SLAB_KERNEL);
if (!addr) {
req->req.length = 0;
return (-ENOMEM);
}
/* allocation of addr_space_buffer */
- addr->addr_space_buffer = (u8 *) vmalloc(req->req.length);
+ addr->addr_space_buffer = vmalloc(req->req.length);
if (!(addr->addr_space_buffer)) {
kfree(addr);
req->req.length = 0;
@@ -2122,8 +2118,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
return -ENOMEM;
}
- cache->filled_head =
- kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL);
+ cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL);
if (!cache->filled_head) {
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
@@ -2136,7 +2131,6 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
req->req.length)) {
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
- CSR1212_FREE(cache);
ret = -EFAULT;
} else {
cache->len = req->req.length;
@@ -2172,7 +2166,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
}
}
kfree(cache->filled_head);
- kfree(cache);
+ CSR1212_FREE(cache);
if (ret >= 0) {
/* we have to free the request, because we queue no response,
@@ -2488,8 +2482,8 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
/* ensure user-supplied buffer is accessible and big enough */
if (!access_ok(VERIFY_WRITE, upackets.infos,
- upackets.n_packets *
- sizeof(struct raw1394_iso_packet_info)))
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the packet_infos out */
@@ -2522,8 +2516,8 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
/* ensure user-supplied buffer is accessible and big enough */
if (!access_ok(VERIFY_READ, upackets.infos,
- upackets.n_packets *
- sizeof(struct raw1394_iso_packet_info)))
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the infos structs in and queue the packets */
@@ -2684,11 +2678,10 @@ static int raw1394_open(struct inode *inode, struct file *file)
{
struct file_info *fi;
- fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
- if (fi == NULL)
+ fi = kzalloc(sizeof(*fi), SLAB_KERNEL);
+ if (!fi)
return -ENOMEM;
- memset(fi, 0, sizeof(struct file_info));
fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
INIT_LIST_HEAD(&fi->list);
@@ -2748,8 +2741,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
list) {
entry = fi_hlp->addr_list.next;
while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry,
- struct
+ arm_addr = list_entry(entry, struct
arm_addr,
addr_list);
if (arm_addr->start ==
@@ -2912,16 +2904,17 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
- if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- NULL, RAW1394_DEVICE_NAME))) {
+ if (IS_ERR
+ (class_device_create
+ (hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+ RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
}
-
- devfs_mk_cdev(MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
+
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+ S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
@@ -2943,20 +2936,22 @@ static int __init init_raw1394(void)
goto out;
-out_dev:
+ out_dev:
devfs_remove(RAW1394_DEVICE_NAME);
class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-out_unreg:
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
-out:
+ out:
return ret;
}
static void __exit cleanup_raw1394(void)
{
class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index f7e18ccc5c0..18d7eda3885 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -80,9 +80,6 @@
#include "ieee1394_transactions.h"
#include "sbp2.h"
-static char version[] __devinitdata =
- "$Rev: 1306 $ Ben Collins <bcollins@debian.org>";
-
/*
* Module load parameter definitions
*/
@@ -151,18 +148,15 @@ static int force_inquiry_hack;
module_param(force_inquiry_hack, int, 0444);
MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
-
/*
* Export information about protocols/devices supported by this driver.
*/
static struct ieee1394_device_id sbp2_id_table[] = {
{
- .match_flags =IEEE1394_MATCH_SPECIFIER_ID |
- IEEE1394_MATCH_VERSION,
- .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
- .version = SBP2_SW_VERSION_ENTRY & 0xffffff
- },
- { }
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = SBP2_SW_VERSION_ENTRY & 0xffffff},
+ {}
};
MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
@@ -221,7 +215,6 @@ static u32 global_outstanding_dmas = 0;
#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
-
/*
* Globals
*/
@@ -254,8 +247,8 @@ static struct hpsb_address_ops sbp2_ops = {
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
static struct hpsb_address_ops sbp2_physdma_ops = {
- .read = sbp2_handle_physdma_read,
- .write = sbp2_handle_physdma_write,
+ .read = sbp2_handle_physdma_read,
+ .write = sbp2_handle_physdma_write,
};
#endif
@@ -287,7 +280,6 @@ static u32 sbp2_broken_inquiry_list[] = {
* General utility functions
**************************************/
-
#ifndef __BIG_ENDIAN
/*
* Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
@@ -324,7 +316,8 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
/*
* Debug packet dump routine. Length is in bytes.
*/
-static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32 dump_phys_addr)
+static void sbp2util_packet_dump(void *buffer, int length, char *dump_name,
+ u32 dump_phys_addr)
{
int i;
unsigned char *dump = buffer;
@@ -345,7 +338,7 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32
printk(" ");
if ((i & 0xf) == 0)
printk("\n ");
- printk("%02x ", (int) dump[i]);
+ printk("%02x ", (int)dump[i]);
}
printk("\n");
@@ -364,9 +357,9 @@ static int sbp2util_down_timeout(atomic_t *done, int timeout)
for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
if (msleep_interruptible(100)) /* 100ms */
- return(1);
+ return 1;
}
- return ((i > 0) ? 0:1);
+ return (i > 0) ? 0 : 1;
}
/* Free's an allocated packet */
@@ -380,21 +373,22 @@ static void sbp2_free_packet(struct hpsb_packet *packet)
* subaction and returns immediately. Can be used from interrupts.
*/
static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
- quadlet_t *buffer, size_t length)
+ quadlet_t *buffer, size_t length)
{
struct hpsb_packet *packet;
packet = hpsb_make_writepacket(ne->host, ne->nodeid,
addr, buffer, length);
- if (!packet)
- return -ENOMEM;
+ if (!packet)
+ return -ENOMEM;
- hpsb_set_packet_complete_task(packet, (void (*)(void*))sbp2_free_packet,
+ hpsb_set_packet_complete_task(packet,
+ (void (*)(void *))sbp2_free_packet,
packet);
hpsb_node_fill_packet(ne, packet);
- if (hpsb_send_packet(packet) < 0) {
+ if (hpsb_send_packet(packet) < 0) {
sbp2_free_packet(packet);
return -EIO;
}
@@ -417,22 +411,22 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
for (i = 0; i < orbs; i++) {
- command = (struct sbp2_command_info *)
- kmalloc(sizeof(struct sbp2_command_info), GFP_ATOMIC);
+ command = kzalloc(sizeof(*command), GFP_ATOMIC);
if (!command) {
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return(-ENOMEM);
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock,
+ flags);
+ return -ENOMEM;
}
- memset(command, '\0', sizeof(struct sbp2_command_info));
command->command_orb_dma =
- pci_map_single (hi->host->pdev, &command->command_orb,
- sizeof(struct sbp2_command_orb),
- PCI_DMA_BIDIRECTIONAL);
+ pci_map_single(hi->host->pdev, &command->command_orb,
+ sizeof(struct sbp2_command_orb),
+ PCI_DMA_BIDIRECTIONAL);
SBP2_DMA_ALLOC("single command orb DMA");
command->sge_dma =
- pci_map_single (hi->host->pdev, &command->scatter_gather_element,
- sizeof(command->scatter_gather_element),
- PCI_DMA_BIDIRECTIONAL);
+ pci_map_single(hi->host->pdev,
+ &command->scatter_gather_element,
+ sizeof(command->scatter_gather_element),
+ PCI_DMA_BIDIRECTIONAL);
SBP2_DMA_ALLOC("scatter_gather_element");
INIT_LIST_HEAD(&command->list);
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
@@ -488,7 +482,7 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
if (command->command_orb_dma == orb) {
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return (command);
+ return command;
}
}
}
@@ -496,7 +490,7 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);
- return(NULL);
+ return NULL;
}
/*
@@ -513,12 +507,12 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_
list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
if (command->Current_SCpnt == SCpnt) {
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return (command);
+ return command;
}
}
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return(NULL);
+ return NULL;
}
/*
@@ -545,7 +539,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return (command);
+ return command;
}
/* Free our DMA's */
@@ -587,7 +581,8 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
/*
* This function moves a command to the completed orb list.
*/
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
+ struct sbp2_command_info *command)
{
unsigned long flags;
@@ -606,8 +601,6 @@ static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_
return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
}
-
-
/*********************************************
* IEEE-1394 core driver stack related section
*********************************************/
@@ -627,14 +620,14 @@ static int sbp2_probe(struct device *dev)
if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
return -ENODEV;
- scsi_id = sbp2_alloc_device(ud);
+ scsi_id = sbp2_alloc_device(ud);
- if (!scsi_id)
- return -ENOMEM;
+ if (!scsi_id)
+ return -ENOMEM;
- sbp2_parse_unit_directory(scsi_id, ud);
+ sbp2_parse_unit_directory(scsi_id, ud);
- return sbp2_start_device(scsi_id);
+ return sbp2_start_device(scsi_id);
}
static int sbp2_remove(struct device *dev)
@@ -719,12 +712,11 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
SBP2_DEBUG("sbp2_alloc_device");
- scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+ scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
if (!scsi_id) {
SBP2_ERR("failed to create scsi_id");
goto failed_alloc;
}
- memset(scsi_id, 0, sizeof(*scsi_id));
scsi_id->ne = ud->ne;
scsi_id->ud = ud;
@@ -735,7 +727,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
INIT_LIST_HEAD(&scsi_id->scsi_list);
spin_lock_init(&scsi_id->sbp2_command_orb_lock);
- scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
+ scsi_id->sbp2_lun = 0;
ud->device.driver_data = scsi_id;
@@ -769,7 +761,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
/* Register our host with the SCSI stack. */
scsi_host = scsi_host_alloc(&scsi_driver_template,
- sizeof (unsigned long));
+ sizeof(unsigned long));
if (!scsi_host) {
SBP2_ERR("failed to register scsi host");
goto failed_alloc;
@@ -790,7 +782,6 @@ failed_alloc:
return NULL;
}
-
static void sbp2_host_reset(struct hpsb_host *host)
{
struct sbp2scsi_host_info *hi;
@@ -804,7 +795,6 @@ static void sbp2_host_reset(struct hpsb_host *host)
}
}
-
/*
* This function is where we first pull the node unique ids, and then
* allocate memory and register a SBP-2 device.
@@ -818,7 +808,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Login FIFO DMA */
scsi_id->login_response =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_login_response),
&scsi_id->login_response_dma);
if (!scsi_id->login_response)
goto alloc_fail;
@@ -826,7 +817,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Query logins ORB DMA */
scsi_id->query_logins_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_query_logins_orb),
&scsi_id->query_logins_orb_dma);
if (!scsi_id->query_logins_orb)
goto alloc_fail;
@@ -834,7 +826,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Query logins response DMA */
scsi_id->query_logins_response =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_query_logins_response),
&scsi_id->query_logins_response_dma);
if (!scsi_id->query_logins_response)
goto alloc_fail;
@@ -842,7 +835,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Reconnect ORB DMA */
scsi_id->reconnect_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_reconnect_orb),
&scsi_id->reconnect_orb_dma);
if (!scsi_id->reconnect_orb)
goto alloc_fail;
@@ -850,7 +844,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Logout ORB DMA */
scsi_id->logout_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_logout_orb),
&scsi_id->logout_orb_dma);
if (!scsi_id->logout_orb)
goto alloc_fail;
@@ -858,58 +853,11 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Login ORB DMA */
scsi_id->login_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_login_orb),
&scsi_id->login_orb_dma);
- if (!scsi_id->login_orb) {
-alloc_fail:
- if (scsi_id->query_logins_response) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_query_logins_response),
- scsi_id->query_logins_response,
- scsi_id->query_logins_response_dma);
- SBP2_DMA_FREE("query logins response DMA");
- }
-
- if (scsi_id->query_logins_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_query_logins_orb),
- scsi_id->query_logins_orb,
- scsi_id->query_logins_orb_dma);
- SBP2_DMA_FREE("query logins ORB DMA");
- }
-
- if (scsi_id->logout_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_logout_orb),
- scsi_id->logout_orb,
- scsi_id->logout_orb_dma);
- SBP2_DMA_FREE("logout ORB DMA");
- }
-
- if (scsi_id->reconnect_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_reconnect_orb),
- scsi_id->reconnect_orb,
- scsi_id->reconnect_orb_dma);
- SBP2_DMA_FREE("reconnect ORB DMA");
- }
-
- if (scsi_id->login_response) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_login_response),
- scsi_id->login_response,
- scsi_id->login_response_dma);
- SBP2_DMA_FREE("login FIFO DMA");
- }
-
- list_del(&scsi_id->scsi_list);
-
- kfree(scsi_id);
-
- SBP2_ERR ("Could not allocate memory for scsi_id");
-
- return -ENOMEM;
- }
+ if (!scsi_id->login_orb)
+ goto alloc_fail;
SBP2_DMA_ALLOC("consistent DMA region for login ORB");
SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
@@ -935,7 +883,7 @@ alloc_fail:
sbp2_remove_device(scsi_id);
return -EINTR;
}
-
+
/*
* Login to the sbp-2 device
*/
@@ -964,10 +912,17 @@ alloc_fail:
error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
if (error) {
SBP2_ERR("scsi_add_device failed");
+ sbp2_logout_device(scsi_id);
+ sbp2_remove_device(scsi_id);
return error;
}
return 0;
+
+alloc_fail:
+ SBP2_ERR("Could not allocate memory for scsi_id");
+ sbp2_remove_device(scsi_id);
+ return -ENOMEM;
}
/*
@@ -1054,51 +1009,44 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
* This function deals with physical dma write requests (for adapters that do not support
* physical dma in hardware). Mostly just here for debugging...
*/
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
- u64 addr, size_t length, u16 flags)
+static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid,
+ int destid, quadlet_t *data, u64 addr,
+ size_t length, u16 flags)
{
- /*
- * Manually put the data in the right place.
- */
- memcpy(bus_to_virt((u32)addr), data, length);
- sbp2util_packet_dump(data, length, "sbp2 phys dma write by device", (u32)addr);
- return(RCODE_COMPLETE);
+ /*
+ * Manually put the data in the right place.
+ */
+ memcpy(bus_to_virt((u32) addr), data, length);
+ sbp2util_packet_dump(data, length, "sbp2 phys dma write by device",
+ (u32) addr);
+ return RCODE_COMPLETE;
}
/*
* This function deals with physical dma read requests (for adapters that do not support
* physical dma in hardware). Mostly just here for debugging...
*/
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
- u64 addr, size_t length, u16 flags)
+static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
+ quadlet_t *data, u64 addr, size_t length,
+ u16 flags)
{
- /*
- * Grab data from memory and send a read response.
- */
- memcpy(data, bus_to_virt((u32)addr), length);
- sbp2util_packet_dump(data, length, "sbp2 phys dma read by device", (u32)addr);
- return(RCODE_COMPLETE);
+ /*
+ * Grab data from memory and send a read response.
+ */
+ memcpy(data, bus_to_virt((u32) addr), length);
+ sbp2util_packet_dump(data, length, "sbp2 phys dma read by device",
+ (u32) addr);
+ return RCODE_COMPLETE;
}
#endif
-
/**************************************
* SBP-2 protocol related section
**************************************/
/*
- * This function determines if we should convert scsi commands for a particular sbp2 device type
- */
-static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
-{
- return (((device_type == TYPE_DISK) ||
- (device_type == TYPE_RBC) ||
- (device_type == TYPE_ROM)) ? 1:0);
-}
-
-/*
* This function queries the device for the maximum concurrent logins it
* supports.
*/
@@ -1120,11 +1068,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
- if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
- scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
- SBP2_DEBUG("sbp2_query_logins: set lun to %d",
- ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
- }
+ scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
scsi_id->query_logins_orb->reserved_resp_length =
@@ -1161,12 +1105,12 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
- return(-EIO);
+ return -EIO;
}
if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
- return(-EIO);
+ return -EIO;
}
if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
@@ -1174,7 +1118,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
- return(-EIO);
+ return -EIO;
}
sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response));
@@ -1191,7 +1135,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
SBP2_DEBUG("Number of active logins: %d", active_logins);
if (active_logins >= max_logins) {
- return(-EIO);
+ return -EIO;
}
return 0;
@@ -1210,13 +1154,13 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
if (!scsi_id->login_orb) {
SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
- return(-EIO);
+ return -EIO;
}
if (!exclusive_login) {
if (sbp2_query_logins(scsi_id)) {
SBP2_INFO("Device does not support any more concurrent logins");
- return(-EIO);
+ return -EIO;
}
}
@@ -1233,12 +1177,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */
scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */
scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */
- /* Set the lun if we were able to pull it from the device's unit directory */
- if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
- scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
- SBP2_DEBUG("sbp2_query_logins: set lun to %d",
- ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
- }
+ scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
scsi_id->login_orb->passwd_resp_lengths =
@@ -1288,7 +1227,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
*/
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) {
SBP2_ERR("Error logging into SBP-2 device - login timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1296,7 +1235,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
SBP2_ERR("Error logging into SBP-2 device - login timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1307,7 +1246,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
SBP2_ERR("Error logging into SBP-2 device - login failed");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1331,7 +1270,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
SBP2_INFO("Logged into SBP-2 device");
- return(0);
+ return 0;
}
@@ -1385,8 +1324,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
atomic_set(&scsi_id->sbp2_login_complete, 0);
error = hpsb_node_write(scsi_id->ne,
- scsi_id->sbp2_management_agent_addr,
- data, 8);
+ scsi_id->sbp2_management_agent_addr, data, 8);
if (error)
return error;
@@ -1396,7 +1334,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
SBP2_INFO("Logged out of SBP-2 device");
- return(0);
+ return 0;
}
@@ -1456,8 +1394,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
atomic_set(&scsi_id->sbp2_login_complete, 0);
error = hpsb_node_write(scsi_id->ne,
- scsi_id->sbp2_management_agent_addr,
- data, 8);
+ scsi_id->sbp2_management_agent_addr, data, 8);
if (error)
return error;
@@ -1466,7 +1403,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
*/
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) {
SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1474,7 +1411,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1485,12 +1422,12 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
- return(-EIO);
+ return -EIO;
}
HPSB_DEBUG("Reconnected to SBP-2 device");
- return(0);
+ return 0;
}
@@ -1513,10 +1450,9 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
SBP2_ERR("sbp2_set_busy_timeout error");
}
- return(0);
+ return 0;
}
-
/*
* This function is called to parse sbp2 device's config rom unit
* directory. Used to determine things like sbp2 management agent offset,
@@ -1529,7 +1465,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
struct csr1212_dentry *dentry;
u64 management_agent_addr;
u32 command_set_spec_id, command_set, unit_characteristics,
- firmware_revision, workarounds;
+ firmware_revision, workarounds;
int i;
SBP2_DEBUG("sbp2_parse_unit_directory");
@@ -1547,13 +1483,14 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) {
/* Save off the management agent address */
management_agent_addr =
- CSR1212_REGISTER_SPACE_BASE +
- (kv->value.csr_offset << 2);
+ CSR1212_REGISTER_SPACE_BASE +
+ (kv->value.csr_offset << 2);
SBP2_DEBUG("sbp2_management_agent_addr = %x",
- (unsigned int) management_agent_addr);
+ (unsigned int)management_agent_addr);
} else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
- scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
+ scsi_id->sbp2_lun =
+ ORB_SET_LUN(kv->value.immediate);
}
break;
@@ -1561,14 +1498,14 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
/* Command spec organization */
command_set_spec_id = kv->value.immediate;
SBP2_DEBUG("sbp2_command_set_spec_id = %x",
- (unsigned int) command_set_spec_id);
+ (unsigned int)command_set_spec_id);
break;
case SBP2_COMMAND_SET_KEY:
/* Command set used by sbp2 device */
command_set = kv->value.immediate;
SBP2_DEBUG("sbp2_command_set = %x",
- (unsigned int) command_set);
+ (unsigned int)command_set);
break;
case SBP2_UNIT_CHARACTERISTICS_KEY:
@@ -1578,7 +1515,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
*/
unit_characteristics = kv->value.immediate;
SBP2_DEBUG("sbp2_unit_characteristics = %x",
- (unsigned int) unit_characteristics);
+ (unsigned int)unit_characteristics);
break;
case SBP2_FIRMWARE_REVISION_KEY:
@@ -1586,9 +1523,10 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
firmware_revision = kv->value.immediate;
if (force_inquiry_hack)
SBP2_INFO("sbp2_firmware_revision = %x",
- (unsigned int) firmware_revision);
- else SBP2_DEBUG("sbp2_firmware_revision = %x",
- (unsigned int) firmware_revision);
+ (unsigned int)firmware_revision);
+ else
+ SBP2_DEBUG("sbp2_firmware_revision = %x",
+ (unsigned int)firmware_revision);
break;
default:
@@ -1646,7 +1584,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
scsi_id->sbp2_firmware_revision = firmware_revision;
scsi_id->workarounds = workarounds;
if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
- scsi_id->sbp2_device_type_and_lun = ud->lun;
+ scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun);
}
}
@@ -1666,8 +1604,9 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
SBP2_DEBUG("sbp2_max_speed_and_size");
/* Initial setting comes from the hosts speed map */
- scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64
- + NODEID_TO_NODE(scsi_id->ne->nodeid)];
+ scsi_id->speed_code =
+ hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 +
+ NODEID_TO_NODE(scsi_id->ne->nodeid)];
/* Bump down our speed if the user requested it */
if (scsi_id->speed_code > max_speed) {
@@ -1678,15 +1617,16 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
/* Payload size is the lesser of what our speed supports and what
* our host supports. */
- scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
- (u8)(hi->host->csr.max_rec - 1));
+ scsi_id->max_payload_size =
+ min(sbp2_speedto_max_payload[scsi_id->speed_code],
+ (u8) (hi->host->csr.max_rec - 1));
HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
hpsb_speedto_str[scsi_id->speed_code],
- 1 << ((u32)scsi_id->max_payload_size + 2));
+ 1 << ((u32) scsi_id->max_payload_size + 2));
- return(0);
+ return 0;
}
/*
@@ -1721,30 +1661,187 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
*/
scsi_id->last_orb = NULL;
- return(0);
+ return 0;
+}
+
+static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ struct sbp2scsi_host_info *hi,
+ struct sbp2_command_info *command,
+ unsigned int scsi_use_sg,
+ struct scatterlist *sgpnt,
+ u32 orb_direction,
+ enum dma_data_direction dma_dir)
+{
+ command->dma_dir = dma_dir;
+ orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+ orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+ /* Special case if only one element (and less than 64KB in size) */
+ if ((scsi_use_sg == 1) &&
+ (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
+
+ SBP2_DEBUG("Only one s/g element");
+ command->dma_size = sgpnt[0].length;
+ command->dma_type = CMD_DMA_PAGE;
+ command->cmd_dma = pci_map_page(hi->host->pdev,
+ sgpnt[0].page,
+ sgpnt[0].offset,
+ command->dma_size,
+ command->dma_dir);
+ SBP2_DMA_ALLOC("single page scatter element");
+
+ orb->data_descriptor_lo = command->cmd_dma;
+ orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
+
+ } else {
+ struct sbp2_unrestricted_page_table *sg_element =
+ &command->scatter_gather_element[0];
+ u32 sg_count, sg_len;
+ dma_addr_t sg_addr;
+ int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,
+ dma_dir);
+
+ SBP2_DMA_ALLOC("scatter list");
+
+ command->dma_size = scsi_use_sg;
+ command->sge_buffer = sgpnt;
+
+ /* use page tables (s/g) */
+ orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+ orb->data_descriptor_lo = command->sge_dma;
+
+ /*
+ * Loop through and fill out our sbp-2 page tables
+ * (and split up anything too large)
+ */
+ for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
+ sg_len = sg_dma_len(sgpnt);
+ sg_addr = sg_dma_address(sgpnt);
+ while (sg_len) {
+ sg_element[sg_count].segment_base_lo = sg_addr;
+ if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+ sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+ sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+ } else {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+ sg_len = 0;
+ }
+ sg_count++;
+ }
+ }
+
+ /* Number of page table (s/g) elements */
+ orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+ sbp2util_packet_dump(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+ "sbp2 s/g list", command->sge_dma);
+
+ /* Byte swap page tables if necessary */
+ sbp2util_cpu_to_be32_buffer(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) *
+ sg_count);
+ }
+}
+
+static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
+ struct sbp2scsi_host_info *hi,
+ struct sbp2_command_info *command,
+ struct scatterlist *sgpnt,
+ u32 orb_direction,
+ unsigned int scsi_request_bufflen,
+ void *scsi_request_buffer,
+ enum dma_data_direction dma_dir)
+{
+ command->dma_dir = dma_dir;
+ command->dma_size = scsi_request_bufflen;
+ command->dma_type = CMD_DMA_SINGLE;
+ command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,
+ command->dma_size, command->dma_dir);
+ orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+ orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+ SBP2_DMA_ALLOC("single bulk");
+
+ /*
+ * Handle case where we get a command w/o s/g enabled (but
+ * check for transfers larger than 64K)
+ */
+ if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
+
+ orb->data_descriptor_lo = command->cmd_dma;
+ orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
+
+ } else {
+ struct sbp2_unrestricted_page_table *sg_element =
+ &command->scatter_gather_element[0];
+ u32 sg_count, sg_len;
+ dma_addr_t sg_addr;
+
+ /*
+ * Need to turn this into page tables, since the
+ * buffer is too large.
+ */
+ orb->data_descriptor_lo = command->sge_dma;
+
+ /* Use page tables (s/g) */
+ orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+
+ /*
+ * fill out our sbp-2 page tables (and split up
+ * the large buffer)
+ */
+ sg_count = 0;
+ sg_len = scsi_request_bufflen;
+ sg_addr = command->cmd_dma;
+ while (sg_len) {
+ sg_element[sg_count].segment_base_lo = sg_addr;
+ if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+ sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+ sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+ } else {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+ sg_len = 0;
+ }
+ sg_count++;
+ }
+
+ /* Number of page table (s/g) elements */
+ orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+ sbp2util_packet_dump(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+ "sbp2 s/g list", command->sge_dma);
+
+ /* Byte swap page tables if necessary */
+ sbp2util_cpu_to_be32_buffer(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) *
+ sg_count);
+ }
}
/*
* This function is called to create the actual command orb and s/g list
* out of the scsi command itself.
*/
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
- struct sbp2_command_info *command,
- unchar *scsi_cmd,
- unsigned int scsi_use_sg,
- unsigned int scsi_request_bufflen,
- void *scsi_request_buffer,
- enum dma_data_direction dma_dir)
-
+static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
+ struct sbp2_command_info *command,
+ unchar *scsi_cmd,
+ unsigned int scsi_use_sg,
+ unsigned int scsi_request_bufflen,
+ void *scsi_request_buffer,
+ enum dma_data_direction dma_dir)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- struct scatterlist *sgpnt = (struct scatterlist *) scsi_request_buffer;
+ struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
struct sbp2_command_orb *command_orb = &command->command_orb;
- struct sbp2_unrestricted_page_table *scatter_gather_element =
- &command->scatter_gather_element[0];
- u32 sg_count, sg_len, orb_direction;
- dma_addr_t sg_addr;
- int i;
+ u32 orb_direction;
/*
* Set-up our command ORB..
@@ -1758,222 +1855,42 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
command_orb->next_ORB_lo = 0x0;
command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size);
command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code);
- command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
+ command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
- /*
- * Get the direction of the transfer. If the direction is unknown, then use our
- * goofy table as a back-up.
- */
- switch (dma_dir) {
- case DMA_NONE:
- orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
- break;
- case DMA_TO_DEVICE:
- orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
- break;
- case DMA_FROM_DEVICE:
- orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
- break;
- case DMA_BIDIRECTIONAL:
- default:
- SBP2_ERR("SCSI data transfer direction not specified. "
- "Update the SBP2 direction table in sbp2.h if "
- "necessary for your application");
- __scsi_print_command(scsi_cmd);
- orb_direction = sbp2scsi_direction_table[*scsi_cmd];
- break;
+ if (dma_dir == DMA_NONE)
+ orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
+ else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)
+ orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
+ else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
+ orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
+ else {
+ SBP2_WARN("Falling back to DMA_NONE");
+ orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
}
- /*
- * Set-up our pagetable stuff... unfortunately, this has become
- * messier than I'd like. Need to clean this up a bit. ;-)
- */
+ /* Set-up our pagetable stuff */
if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-
SBP2_DEBUG("No data transfer");
-
- /*
- * Handle no data transfer
- */
command_orb->data_descriptor_hi = 0x0;
command_orb->data_descriptor_lo = 0x0;
command_orb->misc |= ORB_SET_DIRECTION(1);
-
} else if (scsi_use_sg) {
-
SBP2_DEBUG("Use scatter/gather");
-
- /*
- * Special case if only one element (and less than 64KB in size)
- */
- if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
-
- SBP2_DEBUG("Only one s/g element");
- command->dma_dir = dma_dir;
- command->dma_size = sgpnt[0].length;
- command->dma_type = CMD_DMA_PAGE;
- command->cmd_dma = pci_map_page(hi->host->pdev,
- sgpnt[0].page,
- sgpnt[0].offset,
- command->dma_size,
- command->dma_dir);
- SBP2_DMA_ALLOC("single page scatter element");
-
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->cmd_dma;
- command_orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
- } else {
- int count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, dma_dir);
- SBP2_DMA_ALLOC("scatter list");
-
- command->dma_size = scsi_use_sg;
- command->dma_dir = dma_dir;
- command->sge_buffer = sgpnt;
-
- /* use page tables (s/g) */
- command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->sge_dma;
-
- /*
- * Loop through and fill out our sbp-2 page tables
- * (and split up anything too large)
- */
- for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
- sg_len = sg_dma_len(sgpnt);
- sg_addr = sg_dma_address(sgpnt);
- while (sg_len) {
- scatter_gather_element[sg_count].segment_base_lo = sg_addr;
- if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
- sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
- sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
- } else {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
- sg_len = 0;
- }
- sg_count++;
- }
- }
-
- /* Number of page table (s/g) elements */
- command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
- sbp2util_packet_dump(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
- "sbp2 s/g list", command->sge_dma);
-
- /*
- * Byte swap page tables if necessary
- */
- sbp2util_cpu_to_be32_buffer(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) *
- sg_count);
-
- }
-
+ sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg,
+ sgpnt, orb_direction, dma_dir);
} else {
-
SBP2_DEBUG("No scatter/gather");
-
- command->dma_dir = dma_dir;
- command->dma_size = scsi_request_bufflen;
- command->dma_type = CMD_DMA_SINGLE;
- command->cmd_dma = pci_map_single (hi->host->pdev, scsi_request_buffer,
- command->dma_size,
- command->dma_dir);
- SBP2_DMA_ALLOC("single bulk");
-
- /*
- * Handle case where we get a command w/o s/g enabled (but
- * check for transfers larger than 64K)
- */
- if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->cmd_dma;
- command_orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
- /*
- * Sanity, in case our direction table is not
- * up-to-date
- */
- if (!scsi_request_bufflen) {
- command_orb->data_descriptor_hi = 0x0;
- command_orb->data_descriptor_lo = 0x0;
- command_orb->misc |= ORB_SET_DIRECTION(1);
- }
-
- } else {
- /*
- * Need to turn this into page tables, since the
- * buffer is too large.
- */
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->sge_dma;
-
- /* Use page tables (s/g) */
- command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
- /*
- * fill out our sbp-2 page tables (and split up
- * the large buffer)
- */
- sg_count = 0;
- sg_len = scsi_request_bufflen;
- sg_addr = command->cmd_dma;
- while (sg_len) {
- scatter_gather_element[sg_count].segment_base_lo = sg_addr;
- if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
- sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
- sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
- } else {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
- sg_len = 0;
- }
- sg_count++;
- }
-
- /* Number of page table (s/g) elements */
- command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
- sbp2util_packet_dump(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
- "sbp2 s/g list", command->sge_dma);
-
- /*
- * Byte swap page tables if necessary
- */
- sbp2util_cpu_to_be32_buffer(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) *
- sg_count);
-
- }
-
+ sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt,
+ orb_direction, scsi_request_bufflen,
+ scsi_request_buffer, dma_dir);
}
- /*
- * Byte swap command ORB if necessary
- */
+ /* Byte swap command ORB if necessary */
sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb));
- /*
- * Put our scsi command in the command ORB
- */
+ /* Put our scsi command in the command ORB */
memset(command_orb->cdb, 0, 12);
memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
-
- return(0);
}
/*
@@ -1989,7 +1906,7 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
outstanding_orb_incr;
SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
- command_orb, global_outstanding_command_orbs);
+ command_orb, global_outstanding_command_orbs);
pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,
sizeof(struct sbp2_command_orb),
@@ -2034,10 +1951,11 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
* both by the sbp2 device and us.
*/
scsi_id->last_orb->next_ORB_lo =
- cpu_to_be32(command->command_orb_dma);
+ cpu_to_be32(command->command_orb_dma);
/* Tells hardware that this pointer is valid */
scsi_id->last_orb->next_ORB_hi = 0x0;
- pci_dma_sync_single_for_device(hi->host->pdev, scsi_id->last_orb_dma,
+ pci_dma_sync_single_for_device(hi->host->pdev,
+ scsi_id->last_orb_dma,
sizeof(struct sbp2_command_orb),
PCI_DMA_BIDIRECTIONAL);
@@ -2051,14 +1969,14 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
SBP2_ERR("sbp2util_node_write_no_wait failed");
- return(-EIO);
+ return -EIO;
}
scsi_id->last_orb = command_orb;
scsi_id->last_orb_dma = command->command_orb_dma;
}
- return(0);
+ return 0;
}
/*
@@ -2085,7 +2003,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done);
if (!command) {
- return(-EIO);
+ return -EIO;
}
/*
@@ -2106,11 +2024,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg,
request_bufflen, SCpnt->request_buffer,
SCpnt->sc_data_direction);
- /*
- * Update our cdb if necessary (to handle sbp2 RBC command set
- * differences). This is where the command set hacks go! =)
- */
- sbp2_check_sbp2_command(scsi_id, command->command_orb.cdb);
sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb),
"sbp2 command orb", command->command_orb_dma);
@@ -2125,112 +2038,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
sbp2_link_orb_command(scsi_id, command);
- return(0);
-}
-
-
-/*
- * This function deals with command set differences between Linux scsi
- * command set and sbp2 RBC command set.
- */
-static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd)
-{
- unchar new_cmd[16];
- u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
-
- SBP2_DEBUG("sbp2_check_sbp2_command");
-
- switch (*cmd) {
-
- case READ_6:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert READ_6 to READ_10");
-
- /*
- * Need to turn read_6 into read_10
- */
- new_cmd[0] = 0x28;
- new_cmd[1] = (cmd[1] & 0xe0);
- new_cmd[2] = 0x0;
- new_cmd[3] = (cmd[1] & 0x1f);
- new_cmd[4] = cmd[2];
- new_cmd[5] = cmd[3];
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case WRITE_6:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
-
- /*
- * Need to turn write_6 into write_10
- */
- new_cmd[0] = 0x2a;
- new_cmd[1] = (cmd[1] & 0xe0);
- new_cmd[2] = 0x0;
- new_cmd[3] = (cmd[1] & 0x1f);
- new_cmd[4] = cmd[2];
- new_cmd[5] = cmd[3];
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case MODE_SENSE:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10");
-
- /*
- * Need to turn mode_sense_6 into mode_sense_10
- */
- new_cmd[0] = 0x5a;
- new_cmd[1] = cmd[1];
- new_cmd[2] = cmd[2];
- new_cmd[3] = 0x0;
- new_cmd[4] = 0x0;
- new_cmd[5] = 0x0;
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case MODE_SELECT:
-
- /*
- * TODO. Probably need to change mode select to 10 byte version
- */
-
- default:
- break;
- }
-
- return;
+ return 0;
}
/*
@@ -2260,80 +2068,40 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
sense_data[14] = sbp2_status[20];
sense_data[15] = sbp2_status[21];
- return(sbp2_status[8] & 0x3f); /* return scsi status */
+ return sbp2_status[8] & 0x3f; /* return scsi status */
}
/*
* This function is called after a command is completed, in order to do any necessary SBP-2
* response data translations for the SCSI stack
*/
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
+static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt)
{
u8 *scsi_buf = SCpnt->request_buffer;
- u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
SBP2_DEBUG("sbp2_check_sbp2_response");
switch (SCpnt->cmnd[0]) {
- case INQUIRY:
-
- /*
- * If scsi_id->sbp2_device_type_and_lun is uninitialized, then fill
- * this information in from the inquiry response data. Lun is set to zero.
- */
- if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
- SBP2_DEBUG("Creating sbp2_device_type_and_lun from scsi inquiry data");
- scsi_id->sbp2_device_type_and_lun = (scsi_buf[0] & 0x1f) << 16;
- }
-
- /*
- * Make sure data length is ok. Minimum length is 36 bytes
- */
- if (scsi_buf[4] == 0) {
- scsi_buf[4] = 36 - 5;
- }
-
- /*
- * Check for Simple Direct Access Device and change it to TYPE_DISK
- */
- if ((scsi_buf[0] & 0x1f) == TYPE_RBC) {
- SBP2_DEBUG("Changing TYPE_RBC to TYPE_DISK");
- scsi_buf[0] &= 0xe0;
- }
-
- /*
- * Fix ansi revision and response data format
- */
- scsi_buf[2] |= 2;
- scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-
- break;
-
- case MODE_SENSE:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Modify mode sense response (10 byte version)");
-
- scsi_buf[0] = scsi_buf[1]; /* Mode data length */
- scsi_buf[1] = scsi_buf[2]; /* Medium type */
- scsi_buf[2] = scsi_buf[3]; /* Device specific parameter */
- scsi_buf[3] = scsi_buf[7]; /* Block descriptor length */
- memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]);
- }
-
- break;
+ case INQUIRY:
+ /*
+ * Make sure data length is ok. Minimum length is 36 bytes
+ */
+ if (scsi_buf[4] == 0) {
+ scsi_buf[4] = 36 - 5;
+ }
- case MODE_SELECT:
+ /*
+ * Fix ansi revision and response data format
+ */
+ scsi_buf[2] |= 2;
+ scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
- /*
- * TODO. Probably need to change mode select to 10 byte version
- */
+ break;
- default:
- break;
+ default:
+ break;
}
return;
}
@@ -2358,14 +2126,14 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
if (!host) {
SBP2_ERR("host is NULL - this is bad!");
- return(RCODE_ADDRESS_ERROR);
+ return RCODE_ADDRESS_ERROR;
}
hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
if (!hi) {
SBP2_ERR("host info is NULL - this is bad!");
- return(RCODE_ADDRESS_ERROR);
+ return RCODE_ADDRESS_ERROR;
}
/*
@@ -2382,7 +2150,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
if (!scsi_id) {
SBP2_ERR("scsi_id is NULL - device is gone?");
- return(RCODE_ADDRESS_ERROR);
+ return RCODE_ADDRESS_ERROR;
}
/*
@@ -2480,10 +2248,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
SBP2_ORB_DEBUG("command orb completed");
}
- return(RCODE_COMPLETE);
+ return RCODE_COMPLETE;
}
-
/**************************************
* SCSI interface related section
**************************************/
@@ -2541,6 +2308,16 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
/*
+ * Bidirectional commands are not yet implemented,
+ * and unknown transfer direction not handled.
+ */
+ if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) {
+ SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+ result = DID_ERROR << 16;
+ goto done;
+ }
+
+ /*
* Try and send our SCSI command
*/
if (sbp2_send_command(scsi_id, SCpnt, done)) {
@@ -2616,55 +2393,56 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* complete the command, just let it get retried at the end of the
* bus reset.
*/
- if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+ if (!hpsb_node_entry_valid(scsi_id->ne)
+ && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
SBP2_ERR("Bus reset in progress - retry command later");
return;
}
-
+
/*
* Switch on scsi status
*/
switch (scsi_status) {
- case SBP2_SCSI_STATUS_GOOD:
- SCpnt->result = DID_OK;
- break;
+ case SBP2_SCSI_STATUS_GOOD:
+ SCpnt->result = DID_OK;
+ break;
- case SBP2_SCSI_STATUS_BUSY:
- SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
- SCpnt->result = DID_BUS_BUSY << 16;
- break;
+ case SBP2_SCSI_STATUS_BUSY:
+ SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
+ SCpnt->result = DID_BUS_BUSY << 16;
+ break;
- case SBP2_SCSI_STATUS_CHECK_CONDITION:
- SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
- SCpnt->result = CHECK_CONDITION << 1;
+ case SBP2_SCSI_STATUS_CHECK_CONDITION:
+ SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
+ SCpnt->result = CHECK_CONDITION << 1;
- /*
- * Debug stuff
- */
+ /*
+ * Debug stuff
+ */
#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
- scsi_print_command(SCpnt);
- scsi_print_sense("bh", SCpnt);
+ scsi_print_command(SCpnt);
+ scsi_print_sense("bh", SCpnt);
#endif
- break;
+ break;
- case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
- SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
- SCpnt->result = DID_NO_CONNECT << 16;
- scsi_print_command(SCpnt);
- break;
+ case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
+ SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
+ SCpnt->result = DID_NO_CONNECT << 16;
+ scsi_print_command(SCpnt);
+ break;
- case SBP2_SCSI_STATUS_CONDITION_MET:
- case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
- case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
- SBP2_ERR("Bad SCSI status = %x", scsi_status);
- SCpnt->result = DID_ERROR << 16;
- scsi_print_command(SCpnt);
- break;
+ case SBP2_SCSI_STATUS_CONDITION_MET:
+ case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
+ case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
+ SBP2_ERR("Bad SCSI status = %x", scsi_status);
+ SCpnt->result = DID_ERROR << 16;
+ scsi_print_command(SCpnt);
+ break;
- default:
- SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
- SCpnt->result = DID_ERROR << 16;
+ default:
+ SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
+ SCpnt->result = DID_ERROR << 16;
}
/*
@@ -2678,7 +2456,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* If a bus reset is in progress and there was an error, complete
* the command as busy so that it will get retried.
*/
- if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+ if (!hpsb_node_entry_valid(scsi_id->ne)
+ && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
SBP2_ERR("Completing command with busy (bus reset)");
SCpnt->result = DID_BUS_BUSY << 16;
}
@@ -2699,31 +2478,29 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Tell scsi stack that we're done with this command
*/
- done (SCpnt);
+ done(SCpnt);
}
-
static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
{
((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
return 0;
}
-
static int sbp2scsi_slave_configure(struct scsi_device *sdev)
{
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+ sdev->use_10_for_rw = 1;
+ sdev->use_10_for_ms = 1;
return 0;
}
-
static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
{
((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
return;
}
-
/*
* Called by scsi stack when something has really gone wrong. Usually
* called when a command has timed-out for some reason.
@@ -2769,7 +2546,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
}
- return(SUCCESS);
+ return SUCCESS;
}
/*
@@ -2779,28 +2556,20 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
- unsigned long flags;
SBP2_ERR("reset requested");
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
-
if (sbp2util_node_is_available(scsi_id)) {
SBP2_ERR("Generating sbp2 fetch agent reset");
sbp2_agent_reset(scsi_id, 0);
}
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
return SUCCESS;
}
-static const char *sbp2scsi_info (struct Scsi_Host *host)
-{
- return "SCSI emulation for IEEE-1394 SBP-2 Devices";
-}
-
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct scsi_device *sdev;
struct scsi_id_instance_data *scsi_id;
@@ -2812,10 +2581,7 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_att
if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0]))
return 0;
- if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED)
- lun = 0;
- else
- lun = ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+ lun = ORB_SET_LUN(scsi_id->sbp2_lun);
return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid,
scsi_id->ud->id, lun);
@@ -2837,12 +2603,9 @@ static struct scsi_host_template scsi_driver_template = {
.module = THIS_MODULE,
.name = "SBP-2 IEEE-1394",
.proc_name = SBP2_DEVICE_NAME,
- .info = sbp2scsi_info,
.queuecommand = sbp2scsi_queuecommand,
.eh_abort_handler = sbp2scsi_abort,
.eh_device_reset_handler = sbp2scsi_reset,
- .eh_bus_reset_handler = sbp2scsi_reset,
- .eh_host_reset_handler = sbp2scsi_reset,
.slave_alloc = sbp2scsi_slave_alloc,
.slave_configure = sbp2scsi_slave_configure,
.slave_destroy = sbp2scsi_slave_destroy,
@@ -2861,8 +2624,6 @@ static int sbp2_module_init(void)
SBP2_DEBUG("sbp2_module_init");
- printk(KERN_INFO "sbp2: %s\n", version);
-
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)");
@@ -2874,7 +2635,6 @@ static int sbp2_module_init(void)
/* Set max sectors (module load option). Default is 255 sectors. */
scsi_driver_template.max_sectors = max_sectors;
-
/* Register our high level driver with 1394 stack */
hpsb_register_highlevel(&sbp2_highlevel);
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index cd425be7484..900ea1d25e7 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -119,8 +119,8 @@ struct sbp2_query_logins_response {
struct sbp2_reconnect_orb {
u32 reserved1;
u32 reserved2;
- u32 reserved3;
- u32 reserved4;
+ u32 reserved3;
+ u32 reserved4;
u32 login_ID_misc;
u32 reserved5;
u32 status_FIFO_hi;
@@ -130,8 +130,8 @@ struct sbp2_reconnect_orb {
struct sbp2_logout_orb {
u32 reserved1;
u32 reserved2;
- u32 reserved3;
- u32 reserved4;
+ u32 reserved3;
+ u32 reserved4;
u32 login_ID_misc;
u32 reserved5;
u32 status_FIFO_hi;
@@ -188,7 +188,7 @@ struct sbp2_unrestricted_page_table {
struct sbp2_status_block {
u32 ORB_offset_hi_misc;
u32 ORB_offset_lo;
- u8 command_set_dependent[24];
+ u8 command_set_dependent[24];
};
/*
@@ -211,7 +211,7 @@ struct sbp2_status_block {
* specified for write posting, where the ohci controller will
* automatically send an ack_complete when the status is written by the
* sbp2 device... saving a split transaction. =)
- */
+ */
#define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL
#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe
#define SBP2_STATUS_FIFO_ADDRESS_LO 0x0
@@ -229,9 +229,6 @@ struct sbp2_status_block {
#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14
#define SBP2_FIRMWARE_REVISION_KEY 0x3c
-#define SBP2_DEVICE_TYPE(q) (((q) >> 16) & 0x1f)
-#define SBP2_DEVICE_LUN(q) ((q) & 0xffff)
-
#define SBP2_AGENT_STATE_OFFSET 0x00ULL
#define SBP2_AGENT_RESET_OFFSET 0x04ULL
#define SBP2_ORB_POINTER_OFFSET 0x08ULL
@@ -256,8 +253,6 @@ struct sbp2_status_block {
*/
#define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800
-#define SBP2_DEVICE_TYPE_LUN_UNINITIALIZED 0xffffffff
-
/*
* SCSI specific stuff
*/
@@ -265,45 +260,7 @@ struct sbp2_status_block {
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
-
-/*
- * SCSI direction table...
- * (now used as a back-up in case the direction passed down from above is "unknown")
- *
- * DIN = IN data direction
- * DOU = OUT data direction
- * DNO = No data transfer
- * DUN = Unknown data direction
- *
- * Opcode 0xec (Teac specific "opc execute") possibly should be DNO,
- * but we'll change it when somebody reports a problem with this.
- */
-#define DIN ORB_DIRECTION_READ_FROM_MEDIA
-#define DOU ORB_DIRECTION_WRITE_TO_MEDIA
-#define DNO ORB_DIRECTION_NO_DATA_TRANSFER
-#define DUN DIN
-
-static unchar sbp2scsi_direction_table[0x100] = {
- DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
- DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
- DIN,DUN,DIN,DIN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
- DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
- DOU,DOU,DIN,DIN,DIN,DNO,DIN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DNO,DUN,
- DUN,DIN,DIN,DNO,DNO,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DNO,DOU,DOU,DIN,DNO,DNO,DNO,DIN,DNO,DOU,DUN,DNO,DIN,DOU,DOU,
- DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DIN,DNO,DNO,DNO,DIN,DIN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
-};
-
-/* This should be safe */
-#define SBP2_MAX_CMDS 8
+#define SBP2_MAX_CMDS 8 /* This should be safe */
/* This is the two dma types we use for cmd_dma below */
enum cmd_dma_types {
@@ -338,10 +295,8 @@ struct sbp2_command_info {
#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1
#define SBP2_BREAKAGE_INQUIRY_HACK 0x2
-
struct sbp2scsi_host_info;
-
/*
* Information needed on a per scsi id basis (one for each sbp2 device)
*/
@@ -379,7 +334,7 @@ struct scsi_id_instance_data {
u32 sbp2_command_set_spec_id;
u32 sbp2_command_set;
u32 sbp2_unit_characteristics;
- u32 sbp2_device_type_and_lun;
+ u32 sbp2_lun;
u32 sbp2_firmware_revision;
/*
@@ -411,7 +366,6 @@ struct scsi_id_instance_data {
u32 workarounds;
};
-
/* Sbp2 host data structure (one per IEEE1394 host) */
struct sbp2scsi_host_info {
struct hpsb_host *host; /* IEEE1394 host */
@@ -456,20 +410,12 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, size_t length, u16 flags);
static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
- struct sbp2_command_info *command,
- unchar *scsi_cmd,
- unsigned int scsi_use_sg,
- unsigned int scsi_request_bufflen,
- void *scsi_request_buffer,
- enum dma_data_direction dma_dir);
static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command);
static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *));
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
-static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd);
static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt);
static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 23911da5015..39fb88309e8 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -19,12 +19,6 @@
*
* NOTES:
*
- * jds -- add private data to file to keep track of iso contexts associated
- * with each open -- so release won't kill all iso transfers.
- *
- * Damien Douxchamps: Fix failure when the number of DMA pages per frame is
- * one.
- *
* ioctl return codes:
* EFAULT is only for invalid address for the argp
* EINVAL for out of range values
@@ -34,12 +28,6 @@
* ENOTTY for unsupported ioctl request
*
*/
-
-/* Markus Tavenrath <speedygoo@speedygoo.de> :
- - fixed checks for valid buffer-numbers in video1394_icotl
- - changed the ways the dma prg's are used, now it's possible to use
- even a single dma buffer
-*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -60,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>
@@ -77,14 +64,6 @@
#define ISO_CHANNELS 64
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
struct it_dma_prg {
struct dma_cmd begin;
quadlet_t data[4];
@@ -206,14 +185,12 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
struct dma_iso_ctx *d;
int i;
- d = kmalloc(sizeof(struct dma_iso_ctx), GFP_KERNEL);
- if (d == NULL) {
+ d = kzalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
return NULL;
}
- memset(d, 0, sizeof *d);
-
d->ohci = ohci;
d->type = type;
d->channel = channel;
@@ -251,9 +228,8 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
}
d->ctx = d->iso_tasklet.context;
- d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region),
- GFP_KERNEL);
- if (d->prg_reg == NULL) {
+ d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL);
+ if (!d->prg_reg) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
free_dma_iso_ctx(d);
return NULL;
@@ -268,15 +244,14 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx;
d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx;
- d->ir_prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *),
+ d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg),
GFP_KERNEL);
- if (d->ir_prg == NULL) {
+ if (!d->ir_prg) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
free_dma_iso_ctx(d);
return NULL;
}
- memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *));
d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
d->left_size = (d->frame_size % PAGE_SIZE) ?
@@ -297,16 +272,15 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
- d->it_prg = kmalloc(d->num_desc * sizeof(struct it_dma_prg *),
+ d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg),
GFP_KERNEL);
- if (d->it_prg == NULL) {
+ if (!d->it_prg) {
PRINT(KERN_ERR, ohci->host->id,
"Failed to allocate dma it prg");
free_dma_iso_ctx(d);
return NULL;
}
- memset(d->it_prg, 0, d->num_desc*sizeof(struct it_dma_prg *));
d->packet_size = packet_size;
@@ -337,47 +311,24 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
}
}
- d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
- d->buffer_prg_assignment = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
- d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
- GFP_KERNEL);
- d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
- d->next_buffer = kmalloc(d->num_desc * sizeof(int),
- GFP_KERNEL);
-
- if (d->buffer_status == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_status");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->buffer_prg_assignment == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_prg_assignment");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->buffer_time == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->last_used_cmd == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate last_used_cmd");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->next_buffer == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate next_buffer");
+ d->buffer_status =
+ kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL);
+ d->buffer_prg_assignment =
+ kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL);
+ d->buffer_time =
+ kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL);
+ d->last_used_cmd =
+ kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL);
+ d->next_buffer =
+ kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL);
+
+ if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time ||
+ !d->last_used_cmd || !d->next_buffer) {
+ PRINT(KERN_ERR, ohci->host->id,
+ "Failed to allocate dma_iso_ctx member");
free_dma_iso_ctx(d);
return NULL;
}
- memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
- memset(d->buffer_prg_assignment, 0, d->num_desc * sizeof(unsigned int));
- memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
- memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
- memset(d->next_buffer, -1, d->num_desc * sizeof(int));
spin_lock_init(&d->lock);
@@ -539,7 +490,7 @@ static void wakeup_dma_ir_ctx(unsigned long l)
if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
reset_ir_status(d, i);
d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
- do_gettimeofday(&d->buffer_time[i]);
+ do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
}
}
@@ -1046,7 +997,6 @@ static int __video1394_ioctl(struct file *file,
/* set time of buffer */
v.filltime = d->buffer_time[v.buffer];
-// printk("Buffer %d time %d\n", v.buffer, (d->buffer_time[v.buffer]).tv_usec);
/*
* Look ahead to see how many more buffers have been received
@@ -1085,7 +1035,7 @@ static int __video1394_ioctl(struct file *file,
}
if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
- int buf_size = d->nb_cmd * sizeof(unsigned int);
+ int buf_size = d->nb_cmd * sizeof(*psizes);
struct video1394_queue_variable __user *p = argp;
unsigned int __user *qv;
@@ -1104,7 +1054,7 @@ static int __video1394_ioctl(struct file *file,
spin_lock_irqsave(&d->lock,flags);
- // last_buffer is last_prg
+ /* last_buffer is last_prg */
next_prg = (d->last_buffer + 1) % d->num_desc;
if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
PRINT(KERN_ERR, ohci->host->id,
@@ -1251,13 +1201,12 @@ static int video1394_open(struct inode *inode, struct file *file)
if (ohci == NULL)
return -EIO;
- ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL);
- if (ctx == NULL) {
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
return -ENOMEM;
}
- memset(ctx, 0, sizeof(struct file_ctx));
ctx->ohci = ohci;
INIT_LIST_HEAD(&ctx->context_list);
ctx->current_ctx = NULL;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 02110e00d14..c06b18102b6 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);
@@ -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 e169e798354..b2f3cb91d9b 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 1f1743c5c9a..5982d687a00 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 6e15787d1de..e95c4293a49 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 eb7f52537cc..c908de8db5a 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 7114e3fbab0..f7eecbc6af6 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 a57d021d435..407b6284d7d 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 81737bd6fae..96ea79b63df 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 4c15e112736..c857361be44 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 22fdc446f25..a14eed08a0f 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 9ed34587fc5..be1791be627 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 4a8adcef207..96f1a86bf04 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 497ff794ef6..a104ab041ea 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 34d68e5a72d..2eabb27804c 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 6f94b25f3ac..8b00d9a0f6f 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 2fc449da418..77bc6c746f4 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 d72fe95cba0..9fb985a016e 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 4cc7e2846df..484a7e6b7f8 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 7450550db73..fba608ed7df 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 f7d234295ef..e7e153d9c4c 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 9923a15a999..e0a5412b7e6 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 23885801b6d..86bcdd72a10 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 780009c7eaa..fd3f5c862a5 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 ed0c2ead8bc..98039da0caf 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 e829e10400e..faaf10e5fc7 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 d280b341a37..4ca175553f9 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 ee9fe226ae9..31207e66414 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 0270d1ec942..745979f33dc 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -154,11 +154,13 @@ 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))
-#elif defined(CONFIG_ARCH_S390)
+# 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)
# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 8558a99f663..ec55a29fc86 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/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 64672d49122..e301ee4ca26 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 6a15fe3bc52..83999d58312 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 1cd7657f7e4..1be963961c1 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/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index d13d4c8fe3c..c8b2cc9f184 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/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 9b1ab5e7a98..3df5eedf8f3 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/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 3f0df3330fb..ebd9976fc81 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/serport.c b/drivers/input/serio/serport.c
index 1bd88fca054..54a680cc704 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/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index b091d1a5412..d4c50512a1f 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 f6d5f530b86..49f453c53c6 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 11ae0fddea0..623adbb0d13 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 7b564c0dd99..0a37aded4b5 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 cccfabc1117..11e6f937c1e 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 4cc44a5dd1d..f31bba5b16f 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 8ac207f75e5..a296a846f29 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 c82105920d7..0ef560144be 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/hisax.h b/drivers/isdn/hisax/hisax.h
index 26c545fa223..1b85ce166af 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 bd8a22e4d6a..21fbcedf3a9 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/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4643df097bf..22759c01746 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 e27e9c3a81e..082735dbb41 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 8c404b4e248..f190a99604f 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 19f2fcf0ae4..b4b24335f71 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 a0ea44c3e8b..7d4a0ac28c0 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 71aeb912ec6..d56d400b6aa 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 cf6a6f2248a..314fc0830d9 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 228e1852a83..2a545ceb523 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
@@ -218,12 +225,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 +251,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 +368,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 +401,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 +411,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 +477,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);
+ }
}
}
@@ -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 b856bb67169..8dbf2852bae 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 e8378274d71..db2ae71d07e 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_adt746x.c b/drivers/macintosh/therm_adt746x.c
index f38696622eb..5ebfd1d138d 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -52,6 +52,7 @@ static char *sensor_location[3] = {NULL, NULL, NULL};
static int limit_adjust = 0;
static int fan_speed = -1;
+static int verbose = 0;
MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
@@ -66,6 +67,10 @@ module_param(fan_speed, int, 0644);
MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) "
"(default 64)");
+module_param(verbose, bool, 0);
+MODULE_PARM_DESC(verbose,"Verbose log operations "
+ "(default 0)");
+
struct thermostat {
struct i2c_client clt;
u8 temps[3];
@@ -149,13 +154,13 @@ detach_thermostat(struct i2c_adapter *adapter)
if (thread_therm != NULL) {
kthread_stop(thread_therm);
}
-
+
printk(KERN_INFO "adt746x: Putting max temperatures back from "
"%d, %d, %d to %d, %d, %d\n",
th->limits[0], th->limits[1], th->limits[2],
th->initial_limits[0], th->initial_limits[1],
th->initial_limits[2]);
-
+
for (i = 0; i < 3; i++)
write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
@@ -171,9 +176,9 @@ detach_thermostat(struct i2c_adapter *adapter)
}
static struct i2c_driver thermostat_driver = {
- .owner = THIS_MODULE,
- .name = "therm_adt746x",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "therm_adt746x",
+ },
.attach_adapter = attach_thermostat,
.detach_adapter = detach_thermostat,
};
@@ -212,12 +217,14 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
return;
if (th->last_speed[fan] != speed) {
- if (speed == -1)
- printk(KERN_DEBUG "adt746x: Setting speed to automatic "
- "for %s fan.\n", sensor_location[fan+1]);
- else
- printk(KERN_DEBUG "adt746x: Setting speed to %d "
- "for %s fan.\n", speed, sensor_location[fan+1]);
+ if (verbose) {
+ if (speed == -1)
+ printk(KERN_DEBUG "adt746x: Setting speed to automatic "
+ "for %s fan.\n", sensor_location[fan+1]);
+ else
+ printk(KERN_DEBUG "adt746x: Setting speed to %d "
+ "for %s fan.\n", speed, sensor_location[fan+1]);
+ }
} else
return;
@@ -298,10 +305,11 @@ static void update_fans_speed (struct thermostat *th)
if (new_speed > 255)
new_speed = 255;
- printk(KERN_DEBUG "adt746x: setting fans speed to %d "
- "(limit exceeded by %d on %s) \n",
- new_speed, var,
- sensor_location[fan_number+1]);
+ if (verbose)
+ printk(KERN_DEBUG "adt746x: Setting fans speed to %d "
+ "(limit exceeded by %d on %s) \n",
+ new_speed, var,
+ sensor_location[fan_number+1]);
write_both_fan_speed(th, new_speed);
th->last_var[fan_number] = var;
} else if (var < -2) {
@@ -309,8 +317,9 @@ static void update_fans_speed (struct thermostat *th)
* so cold (lastvar >= -1) */
if (i == 2 && lastvar < -1) {
if (th->last_speed[fan_number] != 0)
- printk(KERN_DEBUG "adt746x: Stopping "
- "fans.\n");
+ if (verbose)
+ printk(KERN_DEBUG "adt746x: Stopping "
+ "fans.\n");
write_both_fan_speed(th, 0);
}
}
@@ -406,7 +415,7 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
set_limit(th, i);
}
-
+
printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
" to %d, %d, %d\n",
th->initial_limits[0], th->initial_limits[1],
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 190878eef99..4f50ee5767a 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -283,9 +283,9 @@ static int therm_pm72_detach(struct i2c_adapter *adapter);
static struct i2c_driver therm_pm72_driver =
{
- .owner = THIS_MODULE,
- .name = "therm_pm72",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "therm_pm72",
+ },
.attach_adapter = therm_pm72_attach,
.detach_adapter = therm_pm72_detach,
};
@@ -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;
}
@@ -1988,18 +1988,13 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match)
{
- int rc;
-
state = state_detached;
/* Lookup the fans in the device tree */
fcu_lookup_fans(dev->node);
/* Add the driver */
- rc = i2c_add_driver(&therm_pm72_driver);
- if (rc < 0)
- return rc;
- return 0;
+ return i2c_add_driver(&therm_pm72_driver);
}
static int fcu_of_remove(struct of_device* dev)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 6aaa1df1a64..3d9dd2e166a 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -354,10 +354,10 @@ do_detach( struct i2c_client *client )
}
static struct i2c_driver g4fan_driver = {
- .owner = THIS_MODULE,
- .name = "therm_windtunnel",
+ .driver = {
+ .name = "therm_windtunnel",
+ },
.id = I2C_DRIVERID_G4FAN,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = do_attach,
.detach_client = do_detach,
};
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index d843a6c9c6d..2d9d7915040 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 e9a159ad302..2a2ffe06016 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 a1966975d58..0129fcc3b18 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 56404350856..6eb93e45fcd 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 6f80d76ac17..f08e52f2107 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 a0a41ad0f2b..906d3ecae6e 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"
@@ -47,9 +48,9 @@ static int wf_lm75_attach(struct i2c_adapter *adapter);
static int wf_lm75_detach(struct i2c_client *client);
static struct i2c_driver wf_lm75_driver = {
- .owner = THIS_MODULE,
- .name = "wf_lm75",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "wf_lm75",
+ },
.attach_adapter = wf_lm75_attach,
.detach_client = wf_lm75_detach,
};
@@ -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;
}
@@ -240,12 +206,7 @@ static int wf_lm75_detach(struct i2c_client *client)
static int __init wf_lm75_sensor_init(void)
{
- int rc;
-
- rc = i2c_add_driver(&wf_lm75_driver);
- if (rc < 0)
- return rc;
- return 0;
+ return i2c_add_driver(&wf_lm75_driver);
}
static void __exit wf_lm75_sensor_exit(void)
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index 80ddf9776bd..eb69a601e76 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 2c3158c81ff..4d811600bda 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 b558cc209d4..1a00d9c75a2 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 252d55df964..76a189ceb52 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -315,6 +315,8 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
if (bitmap->file == NULL)
return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+ flush_dcache_page(page); /* make sure visible to anyone reading the file */
+
if (wait)
lock_page(page);
else {
@@ -341,7 +343,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
/* add to list to be waited for by daemon */
struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
item->page = page;
- page_cache_get(page);
+ get_page(page);
spin_lock(&bitmap->write_lock);
list_add(&item->list, &bitmap->complete_pages);
spin_unlock(&bitmap->write_lock);
@@ -357,10 +359,10 @@ static struct page *read_page(struct file *file, unsigned long index,
struct inode *inode = file->f_mapping->host;
struct page *page = NULL;
loff_t isize = i_size_read(inode);
- unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+ unsigned long end_index = isize >> PAGE_SHIFT;
- PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
- (unsigned long long)index << PAGE_CACHE_SHIFT);
+ PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE,
+ (unsigned long long)index << PAGE_SHIFT);
page = read_cache_page(inode->i_mapping, index,
(filler_t *)inode->i_mapping->a_ops->readpage, file);
@@ -368,7 +370,7 @@ static struct page *read_page(struct file *file, unsigned long index,
goto out;
wait_on_page_locked(page);
if (!PageUptodate(page) || PageError(page)) {
- page_cache_release(page);
+ put_page(page);
page = ERR_PTR(-EIO);
goto out;
}
@@ -376,14 +378,14 @@ static struct page *read_page(struct file *file, unsigned long index,
if (index > end_index) /* we have read beyond EOF */
*bytes_read = 0;
else if (index == end_index) /* possible short read */
- *bytes_read = isize & ~PAGE_CACHE_MASK;
+ *bytes_read = isize & ~PAGE_MASK;
else
- *bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+ *bytes_read = PAGE_SIZE; /* got a full page */
out:
if (IS_ERR(page))
printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
- (int)PAGE_CACHE_SIZE,
- (unsigned long long)index << PAGE_CACHE_SHIFT,
+ (int)PAGE_SIZE,
+ (unsigned long long)index << PAGE_SHIFT,
PTR_ERR(page));
return page;
}
@@ -406,11 +408,11 @@ int bitmap_update_sb(struct bitmap *bitmap)
return 0;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
sb->events = cpu_to_le64(bitmap->mddev->events);
if (!bitmap->mddev->degraded)
sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
- kunmap(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
return write_page(bitmap, bitmap->sb_page, 1);
}
@@ -421,7 +423,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
if (!bitmap || !bitmap->sb_page)
return;
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic));
printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version));
@@ -440,7 +442,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
printk(KERN_DEBUG " sync size: %llu KB\n",
(unsigned long long)le64_to_cpu(sb->sync_size)/2);
printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
- kunmap(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
}
/* read the superblock from the bitmap file and initialize some bitmap fields */
@@ -466,7 +468,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
return err;
}
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
if (bytes_read < sizeof(*sb)) { /* short read */
printk(KERN_INFO "%s: bitmap file superblock truncated\n",
@@ -485,12 +487,12 @@ static int bitmap_read_sb(struct bitmap *bitmap)
else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
reason = "unrecognized superblock version";
- else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
- reason = "bitmap chunksize out of range (512B - 4MB)";
+ else if (chunksize < PAGE_SIZE)
+ reason = "bitmap chunksize too small";
else if ((1 << ffz(~chunksize)) != chunksize)
reason = "bitmap chunksize not a power of 2";
- else if (daemon_sleep < 1 || daemon_sleep > 15)
- reason = "daemon sleep period out of range (1-15s)";
+ else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT / HZ)
+ reason = "daemon sleep period out of range";
else if (write_behind > COUNTER_MAX)
reason = "write-behind limit out of range (0 - 16383)";
if (reason) {
@@ -535,7 +537,7 @@ success:
bitmap->events_cleared = bitmap->mddev->events;
err = 0;
out:
- kunmap(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
if (err)
bitmap_print_sb(bitmap);
return err;
@@ -558,9 +560,9 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
spin_unlock_irqrestore(&bitmap->lock, flags);
return;
}
- page_cache_get(bitmap->sb_page);
+ get_page(bitmap->sb_page);
spin_unlock_irqrestore(&bitmap->lock, flags);
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
switch (op) {
case MASK_SET: sb->state |= bits;
break;
@@ -568,8 +570,8 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
break;
default: BUG();
}
- kunmap(bitmap->sb_page);
- page_cache_release(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
+ put_page(bitmap->sb_page);
}
/*
@@ -622,12 +624,11 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
while (pages--)
if (map[pages]->index != 0) /* 0 is sb_page, release it below */
- page_cache_release(map[pages]);
+ put_page(map[pages]);
kfree(map);
kfree(attr);
- if (sb_page)
- page_cache_release(sb_page);
+ safe_put_page(sb_page);
}
static void bitmap_stop_daemon(struct bitmap *bitmap);
@@ -654,7 +655,7 @@ static void drain_write_queues(struct bitmap *bitmap)
while ((item = dequeue_page(bitmap))) {
/* don't bother to wait */
- page_cache_release(item->page);
+ put_page(item->page);
mempool_free(item, bitmap->write_pool);
}
@@ -763,7 +764,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
/* make sure the page stays cached until it gets written out */
if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
- page_cache_get(page);
+ get_page(page);
/* set the bit */
kaddr = kmap_atomic(page, KM_USER0);
@@ -854,6 +855,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
unsigned long bytes, offset, dummy;
int outofdate;
int ret = -ENOSPC;
+ void *paddr;
chunks = bitmap->chunks;
file = bitmap->file;
@@ -887,12 +889,10 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
if (!bitmap->filemap)
goto out;
- bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+ bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL);
if (!bitmap->filemap_attr)
goto out;
- memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
-
oldindex = ~0L;
for (i = 0; i < chunks; i++) {
@@ -901,8 +901,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
bit = file_page_offset(i);
if (index != oldindex) { /* this is a new page, read it in */
/* unmap the old page, we're done with it */
- if (oldpage != NULL)
- kunmap(oldpage);
if (index == 0) {
/*
* if we're here then the superblock page
@@ -925,30 +923,32 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
oldindex = index;
oldpage = page;
- kmap(page);
if (outofdate) {
/*
* if bitmap is out of date, dirty the
* whole page and write it out
*/
- memset(page_address(page) + offset, 0xff,
+ paddr = kmap_atomic(page, KM_USER0);
+ memset(paddr + offset, 0xff,
PAGE_SIZE - offset);
+ kunmap_atomic(paddr, KM_USER0);
ret = write_page(bitmap, page, 1);
if (ret) {
- kunmap(page);
/* release, page not in filemap yet */
- page_cache_release(page);
+ put_page(page);
goto out;
}
}
bitmap->filemap[bitmap->file_pages++] = page;
}
+ paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
- b = test_bit(bit, page_address(page));
+ b = test_bit(bit, paddr);
else
- b = ext2_test_bit(bit, page_address(page));
+ b = ext2_test_bit(bit, paddr);
+ kunmap_atomic(paddr, KM_USER0);
if (b) {
/* if the disk bit is set, set the memory bit */
bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
@@ -963,9 +963,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
ret = 0;
bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
- if (page) /* unmap the last page */
- kunmap(page);
-
if (bit_cnt) { /* Kick recovery if any bits were set */
set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
md_wakeup_thread(bitmap->mddev->thread);
@@ -1021,6 +1018,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
int err = 0;
int blocks;
int attr;
+ void *paddr;
if (bitmap == NULL)
return 0;
@@ -1043,7 +1041,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
/* skip this page unless it's marked as needing cleaning */
if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
if (attr & BITMAP_PAGE_NEEDWRITE) {
- page_cache_get(page);
+ get_page(page);
clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
}
spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1057,13 +1055,13 @@ int bitmap_daemon_work(struct bitmap *bitmap)
default:
bitmap_file_kick(bitmap);
}
- page_cache_release(page);
+ put_page(page);
}
continue;
}
/* grab the new page, sync and release the old */
- page_cache_get(page);
+ get_page(page);
if (lastpage != NULL) {
if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
@@ -1077,14 +1075,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
}
- kunmap(lastpage);
- page_cache_release(lastpage);
+ put_page(lastpage);
if (err)
bitmap_file_kick(bitmap);
} else
spin_unlock_irqrestore(&bitmap->lock, flags);
lastpage = page;
- kmap(page);
/*
printk("bitmap clean at page %lu\n", j);
*/
@@ -1107,10 +1103,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
-1);
/* clear the bit */
+ paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
- clear_bit(file_page_offset(j), page_address(page));
+ clear_bit(file_page_offset(j), paddr);
else
- ext2_clear_bit(file_page_offset(j), page_address(page));
+ ext2_clear_bit(file_page_offset(j), paddr);
+ kunmap_atomic(paddr, KM_USER0);
}
}
spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1118,7 +1116,6 @@ int bitmap_daemon_work(struct bitmap *bitmap)
/* now sync the final page */
if (lastpage != NULL) {
- kunmap(lastpage);
spin_lock_irqsave(&bitmap->lock, flags);
if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
@@ -1133,7 +1130,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
spin_unlock_irqrestore(&bitmap->lock, flags);
}
- page_cache_release(lastpage);
+ put_page(lastpage);
}
return err;
@@ -1184,7 +1181,7 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
PRINTK("finished page writeback: %p\n", page);
err = PageError(page);
- page_cache_release(page);
+ put_page(page);
if (err) {
printk(KERN_WARNING "%s: bitmap file writeback "
"failed (page %lu): %d\n",
@@ -1530,6 +1527,8 @@ void bitmap_destroy(mddev_t *mddev)
return;
mddev->bitmap = NULL; /* disconnect from the md device */
+ if (mddev->thread)
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
bitmap_free(bitmap);
}
@@ -1555,12 +1554,10 @@ int bitmap_create(mddev_t *mddev)
BUG_ON(file && mddev->bitmap_offset);
- bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+ bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
- memset(bitmap, 0, sizeof(*bitmap));
-
spin_lock_init(&bitmap->lock);
bitmap->mddev = mddev;
@@ -1601,12 +1598,11 @@ int bitmap_create(mddev_t *mddev)
#ifdef INJECT_FATAL_FAULT_1
bitmap->bp = NULL;
#else
- bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+ bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
#endif
err = -ENOMEM;
if (!bitmap->bp)
goto error;
- memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
bitmap->flags |= BITMAP_ACTIVE;
@@ -1636,6 +1632,8 @@ int bitmap_create(mddev_t *mddev)
if (IS_ERR(bitmap->writeback_daemon))
return PTR_ERR(bitmap->writeback_daemon);
+ mddev->thread->timeout = bitmap->daemon_sleep * HZ;
+
return bitmap_update_sb(bitmap);
error:
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index cf663105668..a601a427885 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -690,6 +690,8 @@ bad3:
bad2:
crypto_free_tfm(tfm);
bad1:
+ /* Must zero key material before freeing */
+ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
return -EINVAL;
}
@@ -706,6 +708,9 @@ static void crypt_dtr(struct dm_target *ti)
cc->iv_gen_ops->dtr(cc);
crypto_free_tfm(cc->tfm);
dm_put_device(ti, cc->dev);
+
+ /* Must zero key material before freeing */
+ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
}
diff --git a/drivers/md/dm-io.h b/drivers/md/dm-io.h
index 1a77f326570..f9035bfd1a9 100644
--- a/drivers/md/dm-io.h
+++ b/drivers/md/dm-io.h
@@ -9,9 +9,6 @@
#include "dm.h"
-/* FIXME make this configurable */
-#define DM_MAX_IO_REGIONS 8
-
struct io_region {
struct block_device *bdev;
sector_t sector;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 07d44e19536..561bda5011e 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -270,6 +270,7 @@ static int dm_hash_rename(const char *old, const char *new)
{
char *new_name, *old_name;
struct hash_cell *hc;
+ struct dm_table *table;
/*
* duplicate new.
@@ -317,6 +318,15 @@ static int dm_hash_rename(const char *old, const char *new)
/* rename the device node in devfs */
register_with_devfs(hc);
+ /*
+ * Wake up any dm event waiters.
+ */
+ table = dm_get_table(hc->md);
+ if (table) {
+ dm_table_event(table);
+ dm_table_put(table);
+ }
+
up_write(&_hash_lock);
kfree(old_name);
return 0;
@@ -683,14 +693,18 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
+ int do_lockfs = 1;
struct mapped_device *md;
md = find_device(param);
if (!md)
return -ENXIO;
+ if (param->flags & DM_SKIP_LOCKFS_FLAG)
+ do_lockfs = 0;
+
if (!dm_suspended(md))
- r = dm_suspend(md);
+ r = dm_suspend(md, do_lockfs);
if (!r)
r = __dev_status(md, param);
@@ -702,6 +716,7 @@ static int do_suspend(struct dm_ioctl *param)
static int do_resume(struct dm_ioctl *param)
{
int r = 0;
+ int do_lockfs = 1;
struct hash_cell *hc;
struct mapped_device *md;
struct dm_table *new_map;
@@ -727,8 +742,10 @@ static int do_resume(struct dm_ioctl *param)
/* Do we need to load a new map ? */
if (new_map) {
/* Suspend if it isn't already suspended */
+ if (param->flags & DM_SKIP_LOCKFS_FLAG)
+ do_lockfs = 0;
if (!dm_suspended(md))
- dm_suspend(md);
+ dm_suspend(md, do_lockfs);
r = dm_swap_table(md, new_map);
if (r) {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index a76349cb10a..efe4adf7853 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -573,7 +573,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
lc->sync_search);
lc->sync_search = *region + 1;
- if (*region == lc->region_count)
+ if (*region >= lc->region_count)
return 0;
} while (log_test_bit(lc->recovering_bits, *region));
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6b0fc167092..6cfa8d435d5 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -562,6 +562,8 @@ struct mirror_set {
region_t nr_regions;
int in_sync;
+ struct mirror *default_mirror; /* Default mirror */
+
unsigned int nr_mirrors;
struct mirror mirror[0];
};
@@ -611,7 +613,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
unsigned long flags = 0;
/* fill in the source */
- m = ms->mirror + DEFAULT_MIRROR;
+ m = ms->default_mirror;
from.bdev = m->dev->bdev;
from.sector = m->offset + region_to_sector(reg->rh, reg->key);
if (reg->key == (ms->nr_regions - 1)) {
@@ -627,7 +629,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
/* fill in the destinations */
for (i = 0, dest = to; i < ms->nr_mirrors; i++) {
- if (i == DEFAULT_MIRROR)
+ if (&ms->mirror[i] == ms->default_mirror)
continue;
m = ms->mirror + i;
@@ -682,7 +684,7 @@ static void do_recovery(struct mirror_set *ms)
static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector)
{
/* FIXME: add read balancing */
- return ms->mirror + DEFAULT_MIRROR;
+ return ms->default_mirror;
}
/*
@@ -709,7 +711,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
if (rh_in_sync(&ms->rh, region, 0))
m = choose_mirror(ms, bio->bi_sector);
else
- m = ms->mirror + DEFAULT_MIRROR;
+ m = ms->default_mirror;
map_bio(ms, m, bio);
generic_make_request(bio);
@@ -833,7 +835,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
rh_delay(&ms->rh, bio);
while ((bio = bio_list_pop(&nosync))) {
- map_bio(ms, ms->mirror + DEFAULT_MIRROR, bio);
+ map_bio(ms, ms->default_mirror, bio);
generic_make_request(bio);
}
}
@@ -900,6 +902,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
ms->nr_mirrors = nr_mirrors;
ms->nr_regions = dm_sector_div_up(ti->len, region_size);
ms->in_sync = 0;
+ ms->default_mirror = &ms->mirror[DEFAULT_MIRROR];
if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
ti->error = "dm-mirror: Error creating dirty region hash";
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index ab54f99b7c3..4b9dd8fb1e5 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -371,6 +371,20 @@ static inline ulong round_up(ulong n, ulong size)
return (n + size) & ~size;
}
+static void read_snapshot_metadata(struct dm_snapshot *s)
+{
+ if (s->have_metadata)
+ return;
+
+ if (s->store.read_metadata(&s->store)) {
+ down_write(&s->lock);
+ s->valid = 0;
+ up_write(&s->lock);
+ }
+
+ s->have_metadata = 1;
+}
+
/*
* Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
*/
@@ -848,16 +862,7 @@ static void snapshot_resume(struct dm_target *ti)
{
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
- if (s->have_metadata)
- return;
-
- if (s->store.read_metadata(&s->store)) {
- down_write(&s->lock);
- s->valid = 0;
- up_write(&s->lock);
- }
-
- s->have_metadata = 1;
+ read_snapshot_metadata(s);
}
static int snapshot_status(struct dm_target *ti, status_type_t type,
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 930b9fc2795..097d1e54009 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -55,6 +55,7 @@ union map_info *dm_get_mapinfo(struct bio *bio)
*/
#define DMF_BLOCK_IO 0
#define DMF_SUSPENDED 1
+#define DMF_FROZEN 2
struct mapped_device {
struct rw_semaphore io_lock;
@@ -97,7 +98,7 @@ struct mapped_device {
* freeze/thaw support require holding onto a super block
*/
struct super_block *frozen_sb;
- struct block_device *frozen_bdev;
+ struct block_device *suspended_bdev;
};
#define MIN_IOS 256
@@ -767,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;
@@ -836,9 +838,9 @@ static void __set_size(struct mapped_device *md, sector_t size)
{
set_capacity(md->disk, size);
- down(&md->frozen_bdev->bd_inode->i_sem);
- i_size_write(md->frozen_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
- up(&md->frozen_bdev->bd_inode->i_sem);
+ mutex_lock(&md->suspended_bdev->bd_inode->i_mutex);
+ i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
+ mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex);
}
static int __bind(struct mapped_device *md, struct dm_table *t)
@@ -902,10 +904,9 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result)
return create_aux(minor, 1, result);
}
-void *dm_get_mdptr(dev_t dev)
+static struct mapped_device *dm_find_md(dev_t dev)
{
struct mapped_device *md;
- void *mdptr = NULL;
unsigned minor = MINOR(dev);
if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
@@ -914,12 +915,32 @@ void *dm_get_mdptr(dev_t dev)
down(&_minor_lock);
md = idr_find(&_minor_idr, minor);
-
- if (md && (dm_disk(md)->first_minor == minor))
- mdptr = md->interface_ptr;
+ if (!md || (dm_disk(md)->first_minor != minor))
+ md = NULL;
up(&_minor_lock);
+ return md;
+}
+
+struct mapped_device *dm_get_md(dev_t dev)
+{
+ struct mapped_device *md = dm_find_md(dev);
+
+ if (md)
+ dm_get(md);
+
+ return md;
+}
+
+void *dm_get_mdptr(dev_t dev)
+{
+ struct mapped_device *md;
+ void *mdptr = NULL;
+
+ md = dm_find_md(dev);
+ if (md)
+ mdptr = md->interface_ptr;
return mdptr;
}
@@ -991,43 +1012,33 @@ out:
*/
static int lock_fs(struct mapped_device *md)
{
- int r = -ENOMEM;
-
- md->frozen_bdev = bdget_disk(md->disk, 0);
- if (!md->frozen_bdev) {
- DMWARN("bdget failed in lock_fs");
- goto out;
- }
+ int r;
WARN_ON(md->frozen_sb);
- md->frozen_sb = freeze_bdev(md->frozen_bdev);
+ md->frozen_sb = freeze_bdev(md->suspended_bdev);
if (IS_ERR(md->frozen_sb)) {
r = PTR_ERR(md->frozen_sb);
- goto out_bdput;
+ md->frozen_sb = NULL;
+ return r;
}
+ set_bit(DMF_FROZEN, &md->flags);
+
/* don't bdput right now, we don't want the bdev
- * to go away while it is locked. We'll bdput
- * in unlock_fs
+ * to go away while it is locked.
*/
return 0;
-
-out_bdput:
- bdput(md->frozen_bdev);
- md->frozen_sb = NULL;
- md->frozen_bdev = NULL;
-out:
- return r;
}
static void unlock_fs(struct mapped_device *md)
{
- thaw_bdev(md->frozen_bdev, md->frozen_sb);
- bdput(md->frozen_bdev);
+ if (!test_bit(DMF_FROZEN, &md->flags))
+ return;
+ thaw_bdev(md->suspended_bdev, md->frozen_sb);
md->frozen_sb = NULL;
- md->frozen_bdev = NULL;
+ clear_bit(DMF_FROZEN, &md->flags);
}
/*
@@ -1037,7 +1048,7 @@ static void unlock_fs(struct mapped_device *md)
* dm_bind_table, dm_suspend must be called to flush any in
* flight bios and ensure that any further io gets deferred.
*/
-int dm_suspend(struct mapped_device *md)
+int dm_suspend(struct mapped_device *md, int do_lockfs)
{
struct dm_table *map = NULL;
DECLARE_WAITQUEUE(wait, current);
@@ -1053,10 +1064,19 @@ int dm_suspend(struct mapped_device *md)
/* This does not get reverted if there's an error later. */
dm_table_presuspend_targets(map);
- /* Flush I/O to the device. */
- r = lock_fs(md);
- if (r)
+ md->suspended_bdev = bdget_disk(md->disk, 0);
+ if (!md->suspended_bdev) {
+ DMWARN("bdget failed in dm_suspend");
+ r = -ENOMEM;
goto out;
+ }
+
+ /* Flush I/O to the device. */
+ if (do_lockfs) {
+ r = lock_fs(md);
+ if (r)
+ goto out;
+ }
/*
* First we set the BLOCK_IO flag so no more ios will be mapped.
@@ -1105,6 +1125,11 @@ int dm_suspend(struct mapped_device *md)
r = 0;
out:
+ if (r && md->suspended_bdev) {
+ bdput(md->suspended_bdev);
+ md->suspended_bdev = NULL;
+ }
+
dm_table_put(map);
up(&md->suspend_lock);
return r;
@@ -1135,6 +1160,9 @@ int dm_resume(struct mapped_device *md)
unlock_fs(md);
+ bdput(md->suspended_bdev);
+ md->suspended_bdev = NULL;
+
clear_bit(DMF_SUSPENDED, &md->flags);
dm_table_unplug_all(map);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index e38c3fc1a1d..4eaf075da21 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -28,7 +28,7 @@
* in types.h.
*/
#ifdef CONFIG_LBD
-#define SECTOR_FORMAT "%Lu"
+#define SECTOR_FORMAT "%llu"
#else
#define SECTOR_FORMAT "%lu"
#endif
@@ -58,6 +58,7 @@ int dm_create(struct mapped_device **md);
int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
void dm_set_mdptr(struct mapped_device *md, void *ptr);
void *dm_get_mdptr(dev_t dev);
+struct mapped_device *dm_get_md(dev_t dev);
/*
* Reference counting for md.
@@ -68,7 +69,7 @@ void dm_put(struct mapped_device *md);
/*
* A device can still be used while suspended, but I/O is deferred.
*/
-int dm_suspend(struct mapped_device *md);
+int dm_suspend(struct mapped_device *md, int with_lockfs);
int dm_resume(struct mapped_device *md);
/*
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 0248f8e7eac..a7a5ab55433 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -316,9 +316,10 @@ static int stop(mddev_t *mddev)
return 0;
}
-static mdk_personality_t faulty_personality =
+static struct mdk_personality faulty_personality =
{
.name = "faulty",
+ .level = LEVEL_FAULTY,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -329,15 +330,17 @@ static mdk_personality_t faulty_personality =
static int __init raid_init(void)
{
- return register_md_personality(FAULTY, &faulty_personality);
+ return register_md_personality(&faulty_personality);
}
static void raid_exit(void)
{
- unregister_md_personality(FAULTY);
+ unregister_md_personality(&faulty_personality);
}
module_init(raid_init);
module_exit(raid_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-10"); /* faulty */
+MODULE_ALIAS("md-faulty");
+MODULE_ALIAS("md-level--5");
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index eb703648597..ca99979c868 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -561,11 +561,13 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
* Cancels a kcopyd job, eg. someone might be deactivating a
* mirror.
*/
+#if 0
int kcopyd_cancel(struct kcopyd_job *job, int block)
{
/* FIXME: finish */
return -1;
}
+#endif /* 0 */
/*-----------------------------------------------------------------
* Unit setup
@@ -684,4 +686,3 @@ void kcopyd_client_destroy(struct kcopyd_client *kc)
EXPORT_SYMBOL(kcopyd_client_create);
EXPORT_SYMBOL(kcopyd_client_destroy);
EXPORT_SYMBOL(kcopyd_copy);
-EXPORT_SYMBOL(kcopyd_cancel);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 946efef3a8f..777585458c8 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -121,11 +121,10 @@ static int linear_run (mddev_t *mddev)
sector_t curr_offset;
struct list_head *tmp;
- conf = kmalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
+ conf = kzalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
GFP_KERNEL);
if (!conf)
goto out;
- memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
mddev->private = conf;
cnt = 0;
@@ -352,9 +351,10 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
}
-static mdk_personality_t linear_personality=
+static struct mdk_personality linear_personality =
{
.name = "linear",
+ .level = LEVEL_LINEAR,
.owner = THIS_MODULE,
.make_request = linear_make_request,
.run = linear_run,
@@ -364,16 +364,18 @@ static mdk_personality_t linear_personality=
static int __init linear_init (void)
{
- return register_md_personality (LINEAR, &linear_personality);
+ return register_md_personality (&linear_personality);
}
static void linear_exit (void)
{
- unregister_md_personality (LINEAR);
+ unregister_md_personality (&linear_personality);
}
module_init(linear_init);
module_exit(linear_exit);
MODULE_LICENSE("GPL");
-MODULE_ALIAS("md-personality-1"); /* LINEAR */
+MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/
+MODULE_ALIAS("md-linear");
+MODULE_ALIAS("md-level--1");
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8175a2a222d..1778104e106 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -42,6 +42,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/buffer_head.h> /* for invalidate_bdev */
#include <linux/suspend.h>
+#include <linux/poll.h>
#include <linux/init.h>
@@ -67,7 +68,7 @@
static void autostart_arrays (int part);
#endif
-static mdk_personality_t *pers[MAX_PERSONALITY];
+static LIST_HEAD(pers_list);
static DEFINE_SPINLOCK(pers_lock);
/*
@@ -80,10 +81,22 @@ static DEFINE_SPINLOCK(pers_lock);
* idle IO detection.
*
* you can change it via /proc/sys/dev/raid/speed_limit_min and _max.
+ * or /sys/block/mdX/md/sync_speed_{min,max}
*/
static int sysctl_speed_limit_min = 1000;
static int sysctl_speed_limit_max = 200000;
+static inline int speed_min(mddev_t *mddev)
+{
+ return mddev->sync_speed_min ?
+ mddev->sync_speed_min : sysctl_speed_limit_min;
+}
+
+static inline int speed_max(mddev_t *mddev)
+{
+ return mddev->sync_speed_max ?
+ mddev->sync_speed_max : sysctl_speed_limit_max;
+}
static struct ctl_table_header *raid_table_header;
@@ -134,6 +147,24 @@ static struct block_device_operations md_fops;
static int start_readonly;
/*
+ * We have a system wide 'event count' that is incremented
+ * on any 'interesting' event, and readers of /proc/mdstat
+ * can use 'poll' or 'select' to find out when the event
+ * count increases.
+ *
+ * Events are:
+ * start array, stop array, error, add device, remove device,
+ * start build, activate spare
+ */
+static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
+static atomic_t md_event_count;
+static void md_new_event(mddev_t *mddev)
+{
+ atomic_inc(&md_event_count);
+ wake_up(&md_event_waiters);
+}
+
+/*
* Enables to iterate over all existing md arrays
* all_mddevs_lock protects this list.
*/
@@ -209,12 +240,10 @@ static mddev_t * mddev_find(dev_t unit)
}
spin_unlock(&all_mddevs_lock);
- new = (mddev_t *) kmalloc(sizeof(*new), GFP_KERNEL);
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
if (!new)
return NULL;
- memset(new, 0, sizeof(*new));
-
new->unit = unit;
if (MAJOR(unit) == MD_MAJOR)
new->md_minor = MINOR(unit);
@@ -262,7 +291,7 @@ static inline void mddev_unlock(mddev_t * mddev)
md_wakeup_thread(mddev->thread);
}
-mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
{
mdk_rdev_t * rdev;
struct list_head *tmp;
@@ -286,6 +315,18 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
return NULL;
}
+static struct mdk_personality *find_pers(int level, char *clevel)
+{
+ struct mdk_personality *pers;
+ list_for_each_entry(pers, &pers_list, list) {
+ if (level != LEVEL_NONE && pers->level == level)
+ return pers;
+ if (strcmp(pers->name, clevel)==0)
+ return pers;
+ }
+ return NULL;
+}
+
static inline sector_t calc_dev_sboffset(struct block_device *bdev)
{
sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -320,7 +361,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
static void free_disk_sb(mdk_rdev_t * rdev)
{
if (rdev->sb_page) {
- page_cache_release(rdev->sb_page);
+ put_page(rdev->sb_page);
rdev->sb_loaded = 0;
rdev->sb_page = NULL;
rdev->sb_offset = 0;
@@ -461,6 +502,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
bio_put(bio);
return ret;
}
+EXPORT_SYMBOL_GPL(sync_page_io);
static int read_disk_sb(mdk_rdev_t * rdev, int size)
{
@@ -665,6 +707,10 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
}
rdev->size = calc_dev_size(rdev, sb->chunk_size);
+ if (rdev->size < sb->size && sb->level > 1)
+ /* "this cannot possibly happen" ... */
+ ret = -EINVAL;
+
abort:
return ret;
}
@@ -688,6 +734,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->ctime = sb->ctime;
mddev->utime = sb->utime;
mddev->level = sb->level;
+ mddev->clevel[0] = 0;
mddev->layout = sb->layout;
mddev->raid_disks = sb->raid_disks;
mddev->size = sb->size;
@@ -714,9 +761,10 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+ && mddev->level != 10) {
/* FIXME use a better test */
- printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+ printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
return -EINVAL;
}
mddev->bitmap_offset = mddev->default_bitmap_offset;
@@ -968,6 +1016,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
}
rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
+ atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
@@ -1006,6 +1055,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev->size = le64_to_cpu(sb->data_size)/2;
if (le32_to_cpu(sb->chunksize))
rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1);
+
+ if (le32_to_cpu(sb->size) > rdev->size*2)
+ return -EINVAL;
return 0;
}
@@ -1023,6 +1075,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
mddev->level = le32_to_cpu(sb->level);
+ mddev->clevel[0] = 0;
mddev->layout = le32_to_cpu(sb->layout);
mddev->raid_disks = le32_to_cpu(sb->raid_disks);
mddev->size = le64_to_cpu(sb->size)/2;
@@ -1037,8 +1090,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
mddev->bitmap_file == NULL ) {
- if (mddev->level != 1) {
- printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+ && mddev->level != 10) {
+ printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
return -EINVAL;
}
mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
@@ -1105,6 +1159,8 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
else
sb->resync_offset = cpu_to_le64(0);
+ sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors);
+
if (mddev->bitmap && mddev->bitmap_file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
@@ -1182,11 +1238,20 @@ 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();
return -EINVAL;
}
+ /* make sure rdev->size exceeds mddev->size */
+ if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
+ if (mddev->pers)
+ /* Cannot change size, so fail */
+ return -ENOSPC;
+ else
+ mddev->size = rdev->size;
+ }
same_pdev = match_dev_unit(mddev, rdev);
if (same_pdev)
printk(KERN_WARNING
@@ -1213,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;
@@ -1496,6 +1563,26 @@ repeat:
}
+/* words written to sysfs files may, or my not, be \n terminated.
+ * We want to accept with case. For this we use cmd_match.
+ */
+static int cmd_match(const char *cmd, const char *str)
+{
+ /* See if cmd, written into a sysfs file, matches
+ * str. They must either be the same, or cmd can
+ * have a trailing newline
+ */
+ while (*cmd && *str && *cmd == *str) {
+ cmd++;
+ str++;
+ }
+ if (*cmd == '\n')
+ cmd++;
+ if (*str || *cmd)
+ return 0;
+ return 1;
+}
+
struct rdev_sysfs_entry {
struct attribute attr;
ssize_t (*show)(mdk_rdev_t *, char *);
@@ -1538,9 +1625,113 @@ super_show(mdk_rdev_t *rdev, char *page)
}
static struct rdev_sysfs_entry rdev_super = __ATTR_RO(super);
+static ssize_t
+errors_show(mdk_rdev_t *rdev, char *page)
+{
+ return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
+}
+
+static ssize_t
+errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+ if (*buf && (*e == 0 || *e == '\n')) {
+ atomic_set(&rdev->corrected_errors, n);
+ return len;
+ }
+ return -EINVAL;
+}
+static struct rdev_sysfs_entry rdev_errors =
+__ATTR(errors, 0644, errors_show, errors_store);
+
+static ssize_t
+slot_show(mdk_rdev_t *rdev, char *page)
+{
+ if (rdev->raid_disk < 0)
+ return sprintf(page, "none\n");
+ else
+ return sprintf(page, "%d\n", rdev->raid_disk);
+}
+
+static ssize_t
+slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ int slot = simple_strtoul(buf, &e, 10);
+ if (strncmp(buf, "none", 4)==0)
+ slot = -1;
+ else if (e==buf || (*e && *e!= '\n'))
+ return -EINVAL;
+ if (rdev->mddev->pers)
+ /* Cannot set slot in active array (yet) */
+ return -EBUSY;
+ if (slot >= rdev->mddev->raid_disks)
+ return -ENOSPC;
+ rdev->raid_disk = slot;
+ /* assume it is working */
+ rdev->flags = 0;
+ set_bit(In_sync, &rdev->flags);
+ return len;
+}
+
+
+static struct rdev_sysfs_entry rdev_slot =
+__ATTR(slot, 0644, slot_show, slot_store);
+
+static ssize_t
+offset_show(mdk_rdev_t *rdev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
+}
+
+static ssize_t
+offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long offset = simple_strtoull(buf, &e, 10);
+ if (e==buf || (*e && *e != '\n'))
+ return -EINVAL;
+ if (rdev->mddev->pers)
+ return -EBUSY;
+ rdev->data_offset = offset;
+ return len;
+}
+
+static struct rdev_sysfs_entry rdev_offset =
+__ATTR(offset, 0644, offset_show, offset_store);
+
+static ssize_t
+rdev_size_show(mdk_rdev_t *rdev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)rdev->size);
+}
+
+static ssize_t
+rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long size = simple_strtoull(buf, &e, 10);
+ if (e==buf || (*e && *e != '\n'))
+ return -EINVAL;
+ if (rdev->mddev->pers)
+ return -EBUSY;
+ rdev->size = size;
+ if (size < rdev->mddev->size || rdev->mddev->size == 0)
+ rdev->mddev->size = size;
+ return len;
+}
+
+static struct rdev_sysfs_entry rdev_size =
+__ATTR(size, 0644, rdev_size_show, rdev_size_store);
+
static struct attribute *rdev_default_attrs[] = {
&rdev_state.attr,
&rdev_super.attr,
+ &rdev_errors.attr,
+ &rdev_slot.attr,
+ &rdev_offset.attr,
+ &rdev_size.attr,
NULL,
};
static ssize_t
@@ -1598,12 +1789,11 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
mdk_rdev_t *rdev;
sector_t size;
- rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
printk(KERN_ERR "md: could not alloc mem for new device!\n");
return ERR_PTR(-ENOMEM);
}
- memset(rdev, 0, sizeof(*rdev));
if ((err = alloc_disk_sb(rdev)))
goto abort_free;
@@ -1621,6 +1811,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
rdev->data_offset = 0;
atomic_set(&rdev->nr_pending, 0);
atomic_set(&rdev->read_errors, 0);
+ atomic_set(&rdev->corrected_errors, 0);
size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
if (!size) {
@@ -1725,16 +1916,37 @@ static void analyze_sbs(mddev_t * mddev)
static ssize_t
level_show(mddev_t *mddev, char *page)
{
- mdk_personality_t *p = mddev->pers;
- if (p == NULL && mddev->raid_disks == 0)
- return 0;
- if (mddev->level >= 0)
- return sprintf(page, "raid%d\n", mddev->level);
- else
+ struct mdk_personality *p = mddev->pers;
+ if (p)
return sprintf(page, "%s\n", p->name);
+ else if (mddev->clevel[0])
+ return sprintf(page, "%s\n", mddev->clevel);
+ else if (mddev->level != LEVEL_NONE)
+ return sprintf(page, "%d\n", mddev->level);
+ else
+ return 0;
}
-static struct md_sysfs_entry md_level = __ATTR_RO(level);
+static ssize_t
+level_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int rv = len;
+ if (mddev->pers)
+ return -EBUSY;
+ if (len == 0)
+ return 0;
+ if (len >= sizeof(mddev->clevel))
+ return -ENOSPC;
+ strncpy(mddev->clevel, buf, len);
+ if (mddev->clevel[len-1] == '\n')
+ len--;
+ mddev->clevel[len] = 0;
+ mddev->level = LEVEL_NONE;
+ return rv;
+}
+
+static struct md_sysfs_entry md_level =
+__ATTR(level, 0644, level_show, level_store);
static ssize_t
raid_disks_show(mddev_t *mddev, char *page)
@@ -1744,7 +1956,197 @@ raid_disks_show(mddev_t *mddev, char *page)
return sprintf(page, "%d\n", mddev->raid_disks);
}
-static struct md_sysfs_entry md_raid_disks = __ATTR_RO(raid_disks);
+static int update_raid_disks(mddev_t *mddev, int raid_disks);
+
+static ssize_t
+raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* can only set raid_disks if array is not yet active */
+ char *e;
+ int rv = 0;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+
+ if (!*buf || (*e && *e != '\n'))
+ return -EINVAL;
+
+ if (mddev->pers)
+ rv = update_raid_disks(mddev, n);
+ else
+ mddev->raid_disks = n;
+ return rv ? rv : len;
+}
+static struct md_sysfs_entry md_raid_disks =
+__ATTR(raid_disks, 0644, raid_disks_show, raid_disks_store);
+
+static ssize_t
+chunk_size_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d\n", mddev->chunk_size);
+}
+
+static ssize_t
+chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* can only set chunk_size if array is not yet active */
+ char *e;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+
+ if (mddev->pers)
+ return -EBUSY;
+ if (!*buf || (*e && *e != '\n'))
+ return -EINVAL;
+
+ mddev->chunk_size = n;
+ return len;
+}
+static struct md_sysfs_entry md_chunk_size =
+__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
+
+static ssize_t
+null_show(mddev_t *mddev, char *page)
+{
+ return -EINVAL;
+}
+
+static ssize_t
+new_dev_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* buf must be %d:%d\n? giving major and minor numbers */
+ /* The new device is added to the array.
+ * If the array has a persistent superblock, we read the
+ * superblock to initialise info and check validity.
+ * Otherwise, only checking done is that in bind_rdev_to_array,
+ * which mainly checks size.
+ */
+ char *e;
+ int major = simple_strtoul(buf, &e, 10);
+ int minor;
+ dev_t dev;
+ mdk_rdev_t *rdev;
+ int err;
+
+ if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
+ return -EINVAL;
+ minor = simple_strtoul(e+1, &e, 10);
+ if (*e && *e != '\n')
+ return -EINVAL;
+ dev = MKDEV(major, minor);
+ if (major != MAJOR(dev) ||
+ minor != MINOR(dev))
+ return -EOVERFLOW;
+
+
+ if (mddev->persistent) {
+ rdev = md_import_device(dev, mddev->major_version,
+ mddev->minor_version);
+ if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
+ mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
+ mdk_rdev_t, same_set);
+ err = super_types[mddev->major_version]
+ .load_super(rdev, rdev0, mddev->minor_version);
+ if (err < 0)
+ goto out;
+ }
+ } else
+ rdev = md_import_device(dev, -1, -1);
+
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+ err = bind_rdev_to_array(rdev, mddev);
+ out:
+ if (err)
+ export_rdev(rdev);
+ return err ? err : len;
+}
+
+static struct md_sysfs_entry md_new_device =
+__ATTR(new_dev, 0200, null_show, new_dev_store);
+
+static ssize_t
+size_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
+}
+
+static int update_size(mddev_t *mddev, unsigned long size);
+
+static ssize_t
+size_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* If array is inactive, we can reduce the component size, but
+ * not increase it (except from 0).
+ * If array is active, we can try an on-line resize
+ */
+ char *e;
+ int err = 0;
+ unsigned long long size = simple_strtoull(buf, &e, 10);
+ if (!*buf || *buf == '\n' ||
+ (*e && *e != '\n'))
+ return -EINVAL;
+
+ if (mddev->pers) {
+ err = update_size(mddev, size);
+ md_update_sb(mddev);
+ } else {
+ if (mddev->size == 0 ||
+ mddev->size > size)
+ mddev->size = size;
+ else
+ err = -ENOSPC;
+ }
+ return err ? err : len;
+}
+
+static struct md_sysfs_entry md_size =
+__ATTR(component_size, 0644, size_show, size_store);
+
+
+/* Metdata version.
+ * This is either 'none' for arrays with externally managed metadata,
+ * or N.M for internally known formats
+ */
+static ssize_t
+metadata_show(mddev_t *mddev, char *page)
+{
+ if (mddev->persistent)
+ return sprintf(page, "%d.%d\n",
+ mddev->major_version, mddev->minor_version);
+ else
+ return sprintf(page, "none\n");
+}
+
+static ssize_t
+metadata_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int major, minor;
+ char *e;
+ if (!list_empty(&mddev->disks))
+ return -EBUSY;
+
+ if (cmd_match(buf, "none")) {
+ mddev->persistent = 0;
+ mddev->major_version = 0;
+ mddev->minor_version = 90;
+ return len;
+ }
+ major = simple_strtoul(buf, &e, 10);
+ if (e==buf || *e != '.')
+ return -EINVAL;
+ buf = e+1;
+ minor = simple_strtoul(buf, &e, 10);
+ if (e==buf || *e != '\n')
+ return -EINVAL;
+ if (major >= sizeof(super_types)/sizeof(super_types[0]) ||
+ super_types[major].name == NULL)
+ return -ENOENT;
+ mddev->major_version = major;
+ mddev->minor_version = minor;
+ mddev->persistent = 1;
+ return len;
+}
+
+static struct md_sysfs_entry md_metadata =
+__ATTR(metadata_version, 0644, metadata_show, metadata_store);
static ssize_t
action_show(mddev_t *mddev, char *page)
@@ -1771,31 +2173,27 @@ action_store(mddev_t *mddev, const char *page, size_t len)
if (!mddev->pers || !mddev->pers->sync_request)
return -EINVAL;
- if (strcmp(page, "idle")==0 || strcmp(page, "idle\n")==0) {
+ if (cmd_match(page, "idle")) {
if (mddev->sync_thread) {
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL;
mddev->recovery = 0;
}
- return len;
- }
-
- if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
- test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+ } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
return -EBUSY;
- if (strcmp(page, "resync")==0 || strcmp(page, "resync\n")==0 ||
- strcmp(page, "recover")==0 || strcmp(page, "recover\n")==0)
+ else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
else {
- if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0)
+ if (cmd_match(page, "check"))
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
- else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0)
+ else if (cmd_match(page, "repair"))
return -EINVAL;
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
}
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
return len;
}
@@ -1814,15 +2212,107 @@ md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
static struct md_sysfs_entry
md_mismatches = __ATTR_RO(mismatch_cnt);
+static ssize_t
+sync_min_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d (%s)\n", speed_min(mddev),
+ mddev->sync_speed_min ? "local": "system");
+}
+
+static ssize_t
+sync_min_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int min;
+ char *e;
+ if (strncmp(buf, "system", 6)==0) {
+ mddev->sync_speed_min = 0;
+ return len;
+ }
+ min = simple_strtoul(buf, &e, 10);
+ if (buf == e || (*e && *e != '\n') || min <= 0)
+ return -EINVAL;
+ mddev->sync_speed_min = min;
+ return len;
+}
+
+static struct md_sysfs_entry md_sync_min =
+__ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
+
+static ssize_t
+sync_max_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d (%s)\n", speed_max(mddev),
+ mddev->sync_speed_max ? "local": "system");
+}
+
+static ssize_t
+sync_max_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int max;
+ char *e;
+ if (strncmp(buf, "system", 6)==0) {
+ mddev->sync_speed_max = 0;
+ return len;
+ }
+ max = simple_strtoul(buf, &e, 10);
+ if (buf == e || (*e && *e != '\n') || max <= 0)
+ return -EINVAL;
+ mddev->sync_speed_max = max;
+ return len;
+}
+
+static struct md_sysfs_entry md_sync_max =
+__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
+
+
+static ssize_t
+sync_speed_show(mddev_t *mddev, char *page)
+{
+ unsigned long resync, dt, db;
+ resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+ dt = ((jiffies - mddev->resync_mark) / HZ);
+ if (!dt) dt++;
+ db = resync - (mddev->resync_mark_cnt);
+ return sprintf(page, "%ld\n", db/dt/2); /* K/sec */
+}
+
+static struct md_sysfs_entry
+md_sync_speed = __ATTR_RO(sync_speed);
+
+static ssize_t
+sync_completed_show(mddev_t *mddev, char *page)
+{
+ unsigned long max_blocks, resync;
+
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ max_blocks = mddev->resync_max_sectors;
+ else
+ max_blocks = mddev->size << 1;
+
+ resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+ return sprintf(page, "%lu / %lu\n", resync, max_blocks);
+}
+
+static struct md_sysfs_entry
+md_sync_completed = __ATTR_RO(sync_completed);
+
static struct attribute *md_default_attrs[] = {
&md_level.attr,
&md_raid_disks.attr,
+ &md_chunk_size.attr,
+ &md_size.attr,
+ &md_metadata.attr,
+ &md_new_device.attr,
NULL,
};
static struct attribute *md_redundancy_attrs[] = {
&md_scan_mode.attr,
&md_mismatches.attr,
+ &md_sync_min.attr,
+ &md_sync_max.attr,
+ &md_sync_speed.attr,
+ &md_sync_completed.attr,
NULL,
};
static struct attribute_group md_redundancy_group = {
@@ -1937,14 +2427,16 @@ static void md_safemode_timeout(unsigned long data)
md_wakeup_thread(mddev->thread);
}
+static int start_dirty_degraded;
static int do_md_run(mddev_t * mddev)
{
- int pnum, err;
+ int err;
int chunk_size;
struct list_head *tmp;
mdk_rdev_t *rdev;
struct gendisk *disk;
+ struct mdk_personality *pers;
char b[BDEVNAME_SIZE];
if (list_empty(&mddev->disks))
@@ -1961,20 +2453,8 @@ static int do_md_run(mddev_t * mddev)
analyze_sbs(mddev);
chunk_size = mddev->chunk_size;
- pnum = level_to_pers(mddev->level);
- if ((pnum != MULTIPATH) && (pnum != RAID1)) {
- if (!chunk_size) {
- /*
- * 'default chunksize' in the old md code used to
- * be PAGE_SIZE, baaad.
- * we abort here to be on the safe side. We don't
- * want to continue the bad practice.
- */
- printk(KERN_ERR
- "no chunksize specified, see 'man raidtab'\n");
- return -EINVAL;
- }
+ if (chunk_size) {
if (chunk_size > MAX_CHUNK_SIZE) {
printk(KERN_ERR "too big chunk_size: %d > %d\n",
chunk_size, MAX_CHUNK_SIZE);
@@ -2010,10 +2490,10 @@ static int do_md_run(mddev_t * mddev)
}
#ifdef CONFIG_KMOD
- if (!pers[pnum])
- {
- request_module("md-personality-%d", pnum);
- }
+ if (mddev->level != LEVEL_NONE)
+ request_module("md-level-%d", mddev->level);
+ else if (mddev->clevel[0])
+ request_module("md-%s", mddev->clevel);
#endif
/*
@@ -2035,30 +2515,39 @@ static int do_md_run(mddev_t * mddev)
return -ENOMEM;
spin_lock(&pers_lock);
- if (!pers[pnum] || !try_module_get(pers[pnum]->owner)) {
+ pers = find_pers(mddev->level, mddev->clevel);
+ if (!pers || !try_module_get(pers->owner)) {
spin_unlock(&pers_lock);
- printk(KERN_WARNING "md: personality %d is not loaded!\n",
- pnum);
+ if (mddev->level != LEVEL_NONE)
+ printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
+ mddev->level);
+ else
+ printk(KERN_WARNING "md: personality for level %s is not loaded!\n",
+ mddev->clevel);
return -EINVAL;
}
-
- mddev->pers = pers[pnum];
+ mddev->pers = pers;
spin_unlock(&pers_lock);
+ mddev->level = pers->level;
+ strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
mddev->recovery = 0;
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
mddev->barriers_work = 1;
+ mddev->ok_start_degraded = start_dirty_degraded;
if (start_readonly)
mddev->ro = 2; /* read-only, but switch on first write */
- /* before we start the array running, initialise the bitmap */
- err = bitmap_create(mddev);
- if (err)
- printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
- mdname(mddev), err);
- else
- err = mddev->pers->run(mddev);
+ err = mddev->pers->run(mddev);
+ if (!err && mddev->pers->sync_request) {
+ err = bitmap_create(mddev);
+ if (err) {
+ printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
+ mdname(mddev), err);
+ mddev->pers->stop(mddev);
+ }
+ }
if (err) {
printk(KERN_ERR "md: pers->run() failed ...\n");
module_put(mddev->pers->owner);
@@ -2104,6 +2593,7 @@ static int do_md_run(mddev_t * mddev)
mddev->queue->make_request_fn = mddev->pers->make_request;
mddev->changed = 1;
+ md_new_event(mddev);
return 0;
}
@@ -2231,6 +2721,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
printk(KERN_INFO "md: %s switched to read-only mode.\n",
mdname(mddev));
err = 0;
+ md_new_event(mddev);
out:
return err;
}
@@ -2668,12 +3159,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
if (info->state & (1<<MD_DISK_WRITEMOSTLY))
set_bit(WriteMostly, &rdev->flags);
- err = bind_rdev_to_array(rdev, mddev);
- if (err) {
- export_rdev(rdev);
- return err;
- }
-
if (!mddev->persistent) {
printk(KERN_INFO "md: nonpersistent superblock ...\n");
rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -2681,8 +3166,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
rdev->size = calc_dev_size(rdev, mddev->chunk_size);
- if (!mddev->size || (mddev->size > rdev->size))
- mddev->size = rdev->size;
+ err = bind_rdev_to_array(rdev, mddev);
+ if (err) {
+ export_rdev(rdev);
+ return err;
+ }
}
return 0;
@@ -2705,6 +3193,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
kick_rdev_from_array(rdev);
md_update_sb(mddev);
+ md_new_event(mddev);
return 0;
busy:
@@ -2753,15 +3242,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
size = calc_dev_size(rdev, mddev->chunk_size);
rdev->size = size;
- if (size < mddev->size) {
- printk(KERN_WARNING
- "%s: disk size %llu blocks < array size %llu\n",
- mdname(mddev), (unsigned long long)size,
- (unsigned long long)mddev->size);
- err = -ENOSPC;
- goto abort_export;
- }
-
if (test_bit(Faulty, &rdev->flags)) {
printk(KERN_WARNING
"md: can not hot-add faulty %s disk to %s!\n",
@@ -2771,7 +3251,9 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
}
clear_bit(In_sync, &rdev->flags);
rdev->desc_nr = -1;
- bind_rdev_to_array(rdev, mddev);
+ err = bind_rdev_to_array(rdev, mddev);
+ if (err)
+ goto abort_export;
/*
* The rest should better be atomic, we can have disk failures
@@ -2795,7 +3277,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
*/
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
-
+ md_new_event(mddev);
return 0;
abort_unbind_export:
@@ -2942,6 +3424,81 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
return 0;
}
+static int update_size(mddev_t *mddev, unsigned long size)
+{
+ mdk_rdev_t * rdev;
+ int rv;
+ struct list_head *tmp;
+
+ if (mddev->pers->resize == NULL)
+ return -EINVAL;
+ /* The "size" is the amount of each device that is used.
+ * This can only make sense for arrays with redundancy.
+ * linear and raid0 always use whatever space is available
+ * We can only consider changing the size if no resync
+ * or reconstruction is happening, and if the new size
+ * is acceptable. It must fit before the sb_offset or,
+ * if that is <data_offset, it must fit before the
+ * size of each device.
+ * If size is zero, we find the largest size that fits.
+ */
+ if (mddev->sync_thread)
+ return -EBUSY;
+ ITERATE_RDEV(mddev,rdev,tmp) {
+ sector_t avail;
+ int fit = (size == 0);
+ if (rdev->sb_offset > rdev->data_offset)
+ avail = (rdev->sb_offset*2) - rdev->data_offset;
+ else
+ avail = get_capacity(rdev->bdev->bd_disk)
+ - rdev->data_offset;
+ if (fit && (size == 0 || size > avail/2))
+ size = avail/2;
+ if (avail < ((sector_t)size << 1))
+ return -ENOSPC;
+ }
+ rv = mddev->pers->resize(mddev, (sector_t)size *2);
+ if (!rv) {
+ struct block_device *bdev;
+
+ bdev = bdget_disk(mddev->gendisk, 0);
+ if (bdev) {
+ mutex_lock(&bdev->bd_inode->i_mutex);
+ i_size_write(bdev->bd_inode, mddev->array_size << 10);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
+ bdput(bdev);
+ }
+ }
+ return rv;
+}
+
+static int update_raid_disks(mddev_t *mddev, int raid_disks)
+{
+ int rv;
+ /* change the number of raid disks */
+ if (mddev->pers->reshape == NULL)
+ return -EINVAL;
+ if (raid_disks <= 0 ||
+ raid_disks >= mddev->max_disks)
+ return -EINVAL;
+ if (mddev->sync_thread)
+ return -EBUSY;
+ rv = mddev->pers->reshape(mddev, raid_disks);
+ if (!rv) {
+ struct block_device *bdev;
+
+ bdev = bdget_disk(mddev->gendisk, 0);
+ if (bdev) {
+ mutex_lock(&bdev->bd_inode->i_mutex);
+ i_size_write(bdev->bd_inode, mddev->array_size << 10);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
+ bdput(bdev);
+ }
+ }
+ return rv;
+}
+
+
/*
* update_array_info is used to change the configuration of an
* on-line array.
@@ -2990,71 +3547,12 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
else
return mddev->pers->reconfig(mddev, info->layout, -1);
}
- if (mddev->size != info->size) {
- mdk_rdev_t * rdev;
- struct list_head *tmp;
- if (mddev->pers->resize == NULL)
- return -EINVAL;
- /* The "size" is the amount of each device that is used.
- * This can only make sense for arrays with redundancy.
- * linear and raid0 always use whatever space is available
- * We can only consider changing the size if no resync
- * or reconstruction is happening, and if the new size
- * is acceptable. It must fit before the sb_offset or,
- * if that is <data_offset, it must fit before the
- * size of each device.
- * If size is zero, we find the largest size that fits.
- */
- if (mddev->sync_thread)
- return -EBUSY;
- ITERATE_RDEV(mddev,rdev,tmp) {
- sector_t avail;
- int fit = (info->size == 0);
- if (rdev->sb_offset > rdev->data_offset)
- avail = (rdev->sb_offset*2) - rdev->data_offset;
- else
- avail = get_capacity(rdev->bdev->bd_disk)
- - rdev->data_offset;
- if (fit && (info->size == 0 || info->size > avail/2))
- info->size = avail/2;
- if (avail < ((sector_t)info->size << 1))
- return -ENOSPC;
- }
- rv = mddev->pers->resize(mddev, (sector_t)info->size *2);
- if (!rv) {
- struct block_device *bdev;
-
- bdev = bdget_disk(mddev->gendisk, 0);
- if (bdev) {
- down(&bdev->bd_inode->i_sem);
- i_size_write(bdev->bd_inode, mddev->array_size << 10);
- up(&bdev->bd_inode->i_sem);
- bdput(bdev);
- }
- }
- }
- if (mddev->raid_disks != info->raid_disks) {
- /* change the number of raid disks */
- if (mddev->pers->reshape == NULL)
- return -EINVAL;
- if (info->raid_disks <= 0 ||
- info->raid_disks >= mddev->max_disks)
- return -EINVAL;
- if (mddev->sync_thread)
- return -EBUSY;
- rv = mddev->pers->reshape(mddev, info->raid_disks);
- if (!rv) {
- struct block_device *bdev;
-
- bdev = bdget_disk(mddev->gendisk, 0);
- if (bdev) {
- down(&bdev->bd_inode->i_sem);
- i_size_write(bdev->bd_inode, mddev->array_size << 10);
- up(&bdev->bd_inode->i_sem);
- bdput(bdev);
- }
- }
- }
+ if (mddev->size != info->size)
+ rv = update_size(mddev, info->size);
+
+ if (mddev->raid_disks != info->raid_disks)
+ rv = update_raid_disks(mddev, info->raid_disks);
+
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
if (mddev->pers->quiesce == NULL)
return -EINVAL;
@@ -3103,12 +3601,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))
@@ -3270,24 +3777,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;
}
/*
@@ -3416,6 +3905,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,
};
@@ -3476,11 +3966,10 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
{
mdk_thread_t *thread;
- thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+ thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL);
if (!thread)
return NULL;
- memset(thread, 0, sizeof(mdk_thread_t));
init_waitqueue_head(&thread->wqueue);
thread->run = run;
@@ -3524,6 +4013,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
+ md_new_event(mddev);
}
/* seq_file implementation /proc/mdstat */
@@ -3664,24 +4154,29 @@ static void md_seq_stop(struct seq_file *seq, void *v)
mddev_put(mddev);
}
+struct mdstat_info {
+ int event;
+};
+
static int md_seq_show(struct seq_file *seq, void *v)
{
mddev_t *mddev = v;
sector_t size;
struct list_head *tmp2;
mdk_rdev_t *rdev;
- int i;
+ struct mdstat_info *mi = seq->private;
struct bitmap *bitmap;
if (v == (void*)1) {
+ struct mdk_personality *pers;
seq_printf(seq, "Personalities : ");
spin_lock(&pers_lock);
- for (i = 0; i < MAX_PERSONALITY; i++)
- if (pers[i])
- seq_printf(seq, "[%s] ", pers[i]->name);
+ list_for_each_entry(pers, &pers_list, list)
+ seq_printf(seq, "[%s] ", pers->name);
spin_unlock(&pers_lock);
seq_printf(seq, "\n");
+ mi->event = atomic_read(&md_event_count);
return 0;
}
if (v == (void*)2) {
@@ -3790,47 +4285,68 @@ static struct seq_operations md_seq_ops = {
static int md_seq_open(struct inode *inode, struct file *file)
{
int error;
+ struct mdstat_info *mi = kmalloc(sizeof(*mi), GFP_KERNEL);
+ if (mi == NULL)
+ return -ENOMEM;
error = seq_open(file, &md_seq_ops);
+ if (error)
+ kfree(mi);
+ else {
+ struct seq_file *p = file->private_data;
+ p->private = mi;
+ mi->event = atomic_read(&md_event_count);
+ }
return error;
}
+static int md_seq_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *m = file->private_data;
+ struct mdstat_info *mi = m->private;
+ m->private = NULL;
+ kfree(mi);
+ return seq_release(inode, file);
+}
+
+static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
+{
+ struct seq_file *m = filp->private_data;
+ struct mdstat_info *mi = m->private;
+ int mask;
+
+ poll_wait(filp, &md_event_waiters, wait);
+
+ /* always allow read */
+ mask = POLLIN | POLLRDNORM;
+
+ if (mi->event != atomic_read(&md_event_count))
+ mask |= POLLERR | POLLPRI;
+ return mask;
+}
+
static struct file_operations md_seq_fops = {
.open = md_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = md_seq_release,
+ .poll = mdstat_poll,
};
-int register_md_personality(int pnum, mdk_personality_t *p)
+int register_md_personality(struct mdk_personality *p)
{
- if (pnum >= MAX_PERSONALITY) {
- printk(KERN_ERR
- "md: tried to install personality %s as nr %d, but max is %lu\n",
- p->name, pnum, MAX_PERSONALITY-1);
- return -EINVAL;
- }
-
spin_lock(&pers_lock);
- if (pers[pnum]) {
- spin_unlock(&pers_lock);
- return -EBUSY;
- }
-
- pers[pnum] = p;
- printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum);
+ list_add_tail(&p->list, &pers_list);
+ printk(KERN_INFO "md: %s personality registered for level %d\n", p->name, p->level);
spin_unlock(&pers_lock);
return 0;
}
-int unregister_md_personality(int pnum)
+int unregister_md_personality(struct mdk_personality *p)
{
- if (pnum >= MAX_PERSONALITY)
- return -EINVAL;
-
- printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name);
+ printk(KERN_INFO "md: %s personality unregistered\n", p->name);
spin_lock(&pers_lock);
- pers[pnum] = NULL;
+ list_del_init(&p->list);
spin_unlock(&pers_lock);
return 0;
}
@@ -4012,10 +4528,10 @@ static void md_do_sync(mddev_t *mddev)
printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
- " %d KB/sec/disc.\n", sysctl_speed_limit_min);
+ " %d KB/sec/disc.\n", speed_min(mddev));
printk(KERN_INFO "md: using maximum available idle IO bandwidth "
"(but not more than %d KB/sec) for reconstruction.\n",
- sysctl_speed_limit_max);
+ speed_max(mddev));
is_mddev_idle(mddev); /* this also initializes IO event counters */
/* we don't use the checkpoint if there's a bitmap */
@@ -4056,7 +4572,7 @@ static void md_do_sync(mddev_t *mddev)
skipped = 0;
sectors = mddev->pers->sync_request(mddev, j, &skipped,
- currspeed < sysctl_speed_limit_min);
+ currspeed < speed_min(mddev));
if (sectors == 0) {
set_bit(MD_RECOVERY_ERR, &mddev->recovery);
goto out;
@@ -4069,7 +4585,11 @@ static void md_do_sync(mddev_t *mddev)
j += sectors;
if (j>1) mddev->curr_resync = j;
-
+ if (last_check == 0)
+ /* this is the earliers that rebuilt will be
+ * visible in /proc/mdstat
+ */
+ md_new_event(mddev);
if (last_check + window > io_sectors || j == max_sectors)
continue;
@@ -4117,8 +4637,8 @@ static void md_do_sync(mddev_t *mddev)
currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
/((jiffies-mddev->resync_mark)/HZ +1) +1;
- if (currspeed > sysctl_speed_limit_min) {
- if ((currspeed > sysctl_speed_limit_max) ||
+ if (currspeed > speed_min(mddev)) {
+ if ((currspeed > speed_max(mddev)) ||
!is_mddev_idle(mddev)) {
msleep(500);
goto repeat;
@@ -4255,6 +4775,7 @@ void md_check_recovery(mddev_t *mddev)
mddev->recovery = 0;
/* flag recovery needed just to double check */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_new_event(mddev);
goto unlock;
}
/* Clear some bits that don't mean anything, but
@@ -4292,6 +4813,7 @@ void md_check_recovery(mddev_t *mddev)
sprintf(nm, "rd%d", rdev->raid_disk);
sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
spares++;
+ md_new_event(mddev);
} else
break;
}
@@ -4324,9 +4846,9 @@ void md_check_recovery(mddev_t *mddev)
mdname(mddev));
/* leave the spares where they are, it shouldn't hurt */
mddev->recovery = 0;
- } else {
+ } else
md_wakeup_thread(mddev->sync_thread);
- }
+ md_new_event(mddev);
}
unlock:
mddev_unlock(mddev);
@@ -4503,12 +5025,14 @@ static int set_ro(const char *val, struct kernel_param *kp)
int num = simple_strtoul(val, &e, 10);
if (*val && (*e == '\0' || *e == '\n')) {
start_readonly = num;
- return 0;;
+ return 0;
}
return -EINVAL;
}
module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
+module_param(start_dirty_degraded, int, 0644);
+
EXPORT_SYMBOL(register_md_personality);
EXPORT_SYMBOL(unregister_md_personality);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 145cdc5ad00..96f7af4ae40 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -35,15 +35,10 @@
#define NR_RESERVED_BUFS 32
-static mdk_personality_t multipath_personality;
-
-
static void *mp_pool_alloc(gfp_t gfp_flags, void *data)
{
struct multipath_bh *mpb;
- mpb = kmalloc(sizeof(*mpb), gfp_flags);
- if (mpb)
- memset(mpb, 0, sizeof(*mpb));
+ mpb = kzalloc(sizeof(*mpb), gfp_flags);
return mpb;
}
@@ -308,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;
@@ -316,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
@@ -325,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);
@@ -444,7 +440,7 @@ static int multipath_run (mddev_t *mddev)
* should be freed in multipath_stop()]
*/
- conf = kmalloc(sizeof(multipath_conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
mddev->private = conf;
if (!conf) {
printk(KERN_ERR
@@ -452,9 +448,8 @@ static int multipath_run (mddev_t *mddev)
mdname(mddev));
goto out;
}
- memset(conf, 0, sizeof(*conf));
- conf->multipaths = kmalloc(sizeof(struct multipath_info)*mddev->raid_disks,
+ conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks,
GFP_KERNEL);
if (!conf->multipaths) {
printk(KERN_ERR
@@ -462,7 +457,6 @@ static int multipath_run (mddev_t *mddev)
mdname(mddev));
goto out_free_conf;
}
- memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks);
conf->working_disks = 0;
ITERATE_RDEV(mddev,rdev,tmp) {
@@ -557,9 +551,10 @@ static int multipath_stop (mddev_t *mddev)
return 0;
}
-static mdk_personality_t multipath_personality=
+static struct mdk_personality multipath_personality =
{
.name = "multipath",
+ .level = LEVEL_MULTIPATH,
.owner = THIS_MODULE,
.make_request = multipath_make_request,
.run = multipath_run,
@@ -572,15 +567,17 @@ static mdk_personality_t multipath_personality=
static int __init multipath_init (void)
{
- return register_md_personality (MULTIPATH, &multipath_personality);
+ return register_md_personality (&multipath_personality);
}
static void __exit multipath_exit (void)
{
- unregister_md_personality (MULTIPATH);
+ unregister_md_personality (&multipath_personality);
}
module_init(multipath_init);
module_exit(multipath_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-7"); /* MULTIPATH */
+MODULE_ALIAS("md-multipath");
+MODULE_ALIAS("md-level--4");
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index fece3277c2a..d03f99cf4b7 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -113,21 +113,16 @@ static int create_strip_zones (mddev_t *mddev)
}
printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
- conf->strip_zone = kmalloc(sizeof(struct strip_zone)*
+ conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
conf->nr_strip_zones, GFP_KERNEL);
if (!conf->strip_zone)
return 1;
- conf->devlist = kmalloc(sizeof(mdk_rdev_t*)*
+ conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
conf->nr_strip_zones*mddev->raid_disks,
GFP_KERNEL);
if (!conf->devlist)
return 1;
- memset(conf->strip_zone, 0,sizeof(struct strip_zone)*
- conf->nr_strip_zones);
- memset(conf->devlist, 0,
- sizeof(mdk_rdev_t*) * conf->nr_strip_zones * mddev->raid_disks);
-
/* The first zone must contain all devices, so here we check that
* there is a proper alignment of slots to devices and find them all
*/
@@ -280,7 +275,11 @@ static int raid0_run (mddev_t *mddev)
mdk_rdev_t *rdev;
struct list_head *tmp;
- printk("%s: setting max_sectors to %d, segment boundary to %d\n",
+ if (mddev->chunk_size == 0) {
+ printk(KERN_ERR "md/raid0: non-zero chunk size required.\n");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "%s: setting max_sectors to %d, segment boundary to %d\n",
mdname(mddev),
mddev->chunk_size >> 9,
(mddev->chunk_size>>1)-1);
@@ -307,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;
@@ -361,7 +357,7 @@ static int raid0_run (mddev_t *mddev)
* chunksize should be used in that case.
*/
{
- int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+ int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_SIZE;
if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
mddev->queue->backing_dev_info.ra_pages = 2* stripe;
}
@@ -440,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];
@@ -512,9 +505,10 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev)
return;
}
-static mdk_personality_t raid0_personality=
+static struct mdk_personality raid0_personality=
{
.name = "raid0",
+ .level = 0,
.owner = THIS_MODULE,
.make_request = raid0_make_request,
.run = raid0_run,
@@ -524,15 +518,17 @@ static mdk_personality_t raid0_personality=
static int __init raid0_init (void)
{
- return register_md_personality (RAID0, &raid0_personality);
+ return register_md_personality (&raid0_personality);
}
static void raid0_exit (void)
{
- unregister_md_personality (RAID0);
+ unregister_md_personality (&raid0_personality);
}
module_init(raid0_init);
module_exit(raid0_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-2"); /* RAID0 */
+MODULE_ALIAS("md-raid0");
+MODULE_ALIAS("md-level-0");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 229d7b20429..a06ff91f27e 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -47,10 +47,11 @@
*/
#define NR_RAID1_BIOS 256
-static mdk_personality_t raid1_personality;
static void unplug_slaves(mddev_t *mddev);
+static void allow_barrier(conf_t *conf);
+static void lower_barrier(conf_t *conf);
static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
{
@@ -59,10 +60,8 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
int size = offsetof(r1bio_t, bios[pi->raid_disks]);
/* allocate a r1bio with room for raid_disks entries in the bios array */
- r1_bio = kmalloc(size, gfp_flags);
- if (r1_bio)
- memset(r1_bio, 0, size);
- else
+ r1_bio = kzalloc(size, gfp_flags);
+ if (!r1_bio)
unplug_slaves(pi->mddev);
return r1_bio;
@@ -104,15 +103,30 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
}
/*
* Allocate RESYNC_PAGES data pages and attach them to
- * the first bio;
+ * the first bio.
+ * If this is a user-requested check/repair, allocate
+ * RESYNC_PAGES for each bio.
*/
- bio = r1_bio->bios[0];
- for (i = 0; i < RESYNC_PAGES; i++) {
- page = alloc_page(gfp_flags);
- if (unlikely(!page))
- goto out_free_pages;
-
- bio->bi_io_vec[i].bv_page = page;
+ if (test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery))
+ j = pi->raid_disks;
+ else
+ j = 1;
+ while(j--) {
+ bio = r1_bio->bios[j];
+ for (i = 0; i < RESYNC_PAGES; i++) {
+ page = alloc_page(gfp_flags);
+ if (unlikely(!page))
+ goto out_free_pages;
+
+ bio->bi_io_vec[i].bv_page = page;
+ }
+ }
+ /* If not user-requests, copy the page pointers to all bios */
+ if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) {
+ for (i=0; i<RESYNC_PAGES ; i++)
+ for (j=1; j<pi->raid_disks; j++)
+ r1_bio->bios[j]->bi_io_vec[i].bv_page =
+ r1_bio->bios[0]->bi_io_vec[i].bv_page;
}
r1_bio->master_bio = NULL;
@@ -120,8 +134,10 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
return r1_bio;
out_free_pages:
- for ( ; i > 0 ; i--)
- __free_page(bio->bi_io_vec[i-1].bv_page);
+ for (i=0; i < RESYNC_PAGES ; i++)
+ for (j=0 ; j < pi->raid_disks; j++)
+ safe_put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page);
+ j = -1;
out_free_bio:
while ( ++j < pi->raid_disks )
bio_put(r1_bio->bios[j]);
@@ -132,14 +148,16 @@ out_free_bio:
static void r1buf_pool_free(void *__r1_bio, void *data)
{
struct pool_info *pi = data;
- int i;
+ int i,j;
r1bio_t *r1bio = __r1_bio;
- struct bio *bio = r1bio->bios[0];
- for (i = 0; i < RESYNC_PAGES; i++) {
- __free_page(bio->bi_io_vec[i].bv_page);
- bio->bi_io_vec[i].bv_page = NULL;
- }
+ for (i = 0; i < RESYNC_PAGES; i++)
+ for (j = pi->raid_disks; j-- ;) {
+ if (j == 0 ||
+ r1bio->bios[j]->bi_io_vec[i].bv_page !=
+ r1bio->bios[0]->bi_io_vec[i].bv_page)
+ safe_put_page(r1bio->bios[j]->bi_io_vec[i].bv_page);
+ }
for (i=0 ; i < pi->raid_disks; i++)
bio_put(r1bio->bios[i]);
@@ -152,7 +170,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
for (i = 0; i < conf->raid_disks; i++) {
struct bio **bio = r1_bio->bios + i;
- if (*bio)
+ if (*bio && *bio != IO_BLOCKED)
bio_put(*bio);
*bio = NULL;
}
@@ -160,20 +178,13 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
static inline void free_r1bio(r1bio_t *r1_bio)
{
- unsigned long flags;
-
conf_t *conf = mddev_to_conf(r1_bio->mddev);
/*
* Wake up any possible resync thread that waits for the device
* to go idle.
*/
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ allow_barrier(conf);
put_all_bios(conf, r1_bio);
mempool_free(r1_bio, conf->r1bio_pool);
@@ -182,22 +193,17 @@ static inline void free_r1bio(r1bio_t *r1_bio)
static inline void put_buf(r1bio_t *r1_bio)
{
conf_t *conf = mddev_to_conf(r1_bio->mddev);
- unsigned long flags;
+ int i;
- mempool_free(r1_bio, conf->r1buf_pool);
+ for (i=0; i<conf->raid_disks; i++) {
+ struct bio *bio = r1_bio->bios[i];
+ if (bio->bi_end_io)
+ rdev_dec_pending(conf->mirrors[i].rdev, r1_bio->mddev);
+ }
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!conf->barrier)
- BUG();
- --conf->barrier;
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
+ mempool_free(r1_bio, conf->r1buf_pool);
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ lower_barrier(conf);
}
static void reschedule_retry(r1bio_t *r1_bio)
@@ -208,8 +214,10 @@ static void reschedule_retry(r1bio_t *r1_bio)
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&r1_bio->retry_list, &conf->retry_list);
+ conf->nr_queued ++;
spin_unlock_irqrestore(&conf->device_lock, flags);
+ wake_up(&conf->wait_barrier);
md_wakeup_thread(mddev->thread);
}
@@ -261,9 +269,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
- md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
- else
+ update_head_pos(mirror, r1_bio);
+
+ if (uptodate || conf->working_disks <= 1) {
/*
* Set R1BIO_Uptodate in our master bio, so that
* we will return a good error code for to the higher
@@ -273,16 +281,11 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
* user-side. So if something waits for IO, then it will
* wait for the 'master' bio.
*/
- set_bit(R1BIO_Uptodate, &r1_bio->state);
-
- update_head_pos(mirror, r1_bio);
+ if (uptodate)
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
- /*
- * we have only one bio on the read side
- */
- if (uptodate)
raid_end_bio_io(r1_bio);
- else {
+ } else {
/*
* oops, read error:
*/
@@ -378,7 +381,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
/* free extra copy of the data pages */
int i = bio->bi_vcnt;
while (i--)
- __free_page(bio->bi_io_vec[i].bv_page);
+ safe_put_page(bio->bi_io_vec[i].bv_page);
}
/* clear the bitmap if all writes complete successfully */
bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
@@ -433,11 +436,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
new_disk = 0;
for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
+ r1_bio->bios[new_disk] == IO_BLOCKED ||
!rdev || !test_bit(In_sync, &rdev->flags)
|| test_bit(WriteMostly, &rdev->flags);
rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) {
- if (rdev && test_bit(In_sync, &rdev->flags))
+ if (rdev && test_bit(In_sync, &rdev->flags) &&
+ r1_bio->bios[new_disk] != IO_BLOCKED)
wonly_disk = new_disk;
if (new_disk == conf->raid_disks - 1) {
@@ -451,11 +456,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* make sure the disk is operational */
for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
+ r1_bio->bios[new_disk] == IO_BLOCKED ||
!rdev || !test_bit(In_sync, &rdev->flags) ||
test_bit(WriteMostly, &rdev->flags);
rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) {
- if (rdev && test_bit(In_sync, &rdev->flags))
+ if (rdev && test_bit(In_sync, &rdev->flags) &&
+ r1_bio->bios[new_disk] != IO_BLOCKED)
wonly_disk = new_disk;
if (new_disk <= 0)
@@ -492,7 +499,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
rdev = rcu_dereference(conf->mirrors[disk].rdev);
- if (!rdev ||
+ if (!rdev || r1_bio->bios[disk] == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags) ||
test_bit(WriteMostly, &rdev->flags))
continue;
@@ -520,7 +527,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* cannot risk returning a device that failed
* before we inc'ed nr_pending
*/
- atomic_dec(&rdev->nr_pending);
+ rdev_dec_pending(rdev, conf->mddev);
goto retry;
}
conf->next_seq_sect = this_sector + sectors;
@@ -593,42 +600,119 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
return ret;
}
-/*
- * Throttle resync depth, so that we can both get proper overlapping of
- * requests, but are still able to handle normal requests quickly.
+/* Barriers....
+ * Sometimes we need to suspend IO while we do something else,
+ * either some resync/recovery, or reconfigure the array.
+ * To do this we raise a 'barrier'.
+ * The 'barrier' is a counter that can be raised multiple times
+ * to count how many activities are happening which preclude
+ * normal IO.
+ * We can only raise the barrier if there is no pending IO.
+ * i.e. if nr_pending == 0.
+ * We choose only to raise the barrier if no-one is waiting for the
+ * barrier to go down. This means that as soon as an IO request
+ * is ready, no other operations which require a barrier will start
+ * until the IO request has had a chance.
+ *
+ * So: regular IO calls 'wait_barrier'. When that returns there
+ * is no backgroup IO happening, It must arrange to call
+ * allow_barrier when it has finished its IO.
+ * backgroup IO calls must call raise_barrier. Once that returns
+ * there is no normal IO happeing. It must arrange to call
+ * lower_barrier when the particular background IO completes.
*/
#define RESYNC_DEPTH 32
-static void device_barrier(conf_t *conf, sector_t sect)
+static void raise_barrier(conf_t *conf)
{
spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
-
- if (!conf->barrier++) {
- wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
- if (conf->nr_pending)
- BUG();
+
+ /* Wait until no block IO is waiting */
+ wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+
+ /* block any new IO from starting */
+ conf->barrier++;
+
+ /* No wait for all pending IO to complete */
+ wait_event_lock_irq(conf->wait_barrier,
+ !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void lower_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->barrier--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void wait_barrier(conf_t *conf)
+{
+ spin_lock_irq(&conf->resync_lock);
+ if (conf->barrier) {
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+ conf->nr_waiting--;
}
- wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
- conf->next_resync = sect;
+ conf->nr_pending++;
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void allow_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->nr_pending--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void freeze_array(conf_t *conf)
+{
+ /* stop syncio and normal IO and wait for everything to
+ * go quite.
+ * We increment barrier and nr_waiting, and then
+ * wait until barrier+nr_pending match nr_queued+2
+ */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier++;
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier,
+ conf->barrier+conf->nr_pending == conf->nr_queued+2,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+ spin_unlock_irq(&conf->resync_lock);
+}
+static void unfreeze_array(conf_t *conf)
+{
+ /* reverse the effect of the freeze */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier--;
+ conf->nr_waiting--;
+ wake_up(&conf->wait_barrier);
spin_unlock_irq(&conf->resync_lock);
}
+
/* duplicate the data pages for behind I/O */
static struct page **alloc_behind_pages(struct bio *bio)
{
int i;
struct bio_vec *bvec;
- struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *),
+ struct page **pages = kzalloc(bio->bi_vcnt * sizeof(struct page *),
GFP_NOIO);
if (unlikely(!pages))
goto do_sync_io;
- memset(pages, 0, bio->bi_vcnt * sizeof(struct page *));
-
bio_for_each_segment(bvec, bio, i) {
pages[i] = alloc_page(GFP_NOIO);
if (unlikely(!pages[i]))
@@ -644,7 +728,7 @@ static struct page **alloc_behind_pages(struct bio *bio)
do_sync_io:
if (pages)
for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
- __free_page(pages[i]);
+ put_page(pages[i]);
kfree(pages);
PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
return NULL;
@@ -678,10 +762,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
*/
md_write_start(mddev, bio); /* wait on superblock update early */
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ wait_barrier(conf);
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -749,7 +830,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
!test_bit(Faulty, &rdev->flags)) {
atomic_inc(&rdev->nr_pending);
if (test_bit(Faulty, &rdev->flags)) {
- atomic_dec(&rdev->nr_pending);
+ rdev_dec_pending(rdev, mddev);
r1_bio->bios[i] = NULL;
} else
r1_bio->bios[i] = bio;
@@ -909,13 +990,8 @@ static void print_conf(conf_t *conf)
static void close_sync(conf_t *conf)
{
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier,
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
- spin_unlock_irq(&conf->resync_lock);
-
- if (conf->barrier) BUG();
- if (waitqueue_active(&conf->wait_idle)) BUG();
+ wait_barrier(conf);
+ allow_barrier(conf);
mempool_destroy(conf->r1buf_pool);
conf->r1buf_pool = NULL;
@@ -1015,28 +1091,27 @@ abort:
static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
{
- int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
- conf_t *conf = mddev_to_conf(r1_bio->mddev);
+ int i;
if (bio->bi_size)
return 1;
- if (r1_bio->bios[r1_bio->read_disk] != bio)
- BUG();
- update_head_pos(r1_bio->read_disk, r1_bio);
+ for (i=r1_bio->mddev->raid_disks; i--; )
+ if (r1_bio->bios[i] == bio)
+ break;
+ BUG_ON(i < 0);
+ update_head_pos(i, r1_bio);
/*
* we have read a block, now it needs to be re-written,
* or re-read if the read failed.
* We don't do much here, just schedule handling by raid1d
*/
- if (!uptodate) {
- md_error(r1_bio->mddev,
- conf->mirrors[r1_bio->read_disk].rdev);
- } else
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
set_bit(R1BIO_Uptodate, &r1_bio->state);
- rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
- reschedule_retry(r1_bio);
+
+ if (atomic_dec_and_test(&r1_bio->remaining))
+ reschedule_retry(r1_bio);
return 0;
}
@@ -1066,7 +1141,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
md_done_sync(mddev, r1_bio->sectors, uptodate);
put_buf(r1_bio);
}
- rdev_dec_pending(conf->mirrors[mirror].rdev, mddev);
return 0;
}
@@ -1079,34 +1153,173 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
bio = r1_bio->bios[r1_bio->read_disk];
-/*
- if (r1_bio->sector == 0) printk("First sync write startss\n");
-*/
- /*
- * schedule writes
- */
+
+ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ /* We have read all readable devices. If we haven't
+ * got the block, then there is no hope left.
+ * If we have, then we want to do a comparison
+ * and skip the write if everything is the same.
+ * If any blocks failed to read, then we need to
+ * attempt an over-write
+ */
+ int primary;
+ if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+ for (i=0; i<mddev->raid_disks; i++)
+ if (r1_bio->bios[i]->bi_end_io == end_sync_read)
+ md_error(mddev, conf->mirrors[i].rdev);
+
+ md_done_sync(mddev, r1_bio->sectors, 1);
+ put_buf(r1_bio);
+ return;
+ }
+ for (primary=0; primary<mddev->raid_disks; primary++)
+ if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
+ test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
+ r1_bio->bios[primary]->bi_end_io = NULL;
+ rdev_dec_pending(conf->mirrors[primary].rdev, mddev);
+ break;
+ }
+ r1_bio->read_disk = primary;
+ for (i=0; i<mddev->raid_disks; i++)
+ if (r1_bio->bios[i]->bi_end_io == end_sync_read &&
+ test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) {
+ int j;
+ int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
+ struct bio *pbio = r1_bio->bios[primary];
+ struct bio *sbio = r1_bio->bios[i];
+ for (j = vcnt; j-- ; )
+ if (memcmp(page_address(pbio->bi_io_vec[j].bv_page),
+ page_address(sbio->bi_io_vec[j].bv_page),
+ PAGE_SIZE))
+ break;
+ if (j >= 0)
+ mddev->resync_mismatches += r1_bio->sectors;
+ if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
+ sbio->bi_end_io = NULL;
+ rdev_dec_pending(conf->mirrors[i].rdev, mddev);
+ } else {
+ /* fixup the bio for reuse */
+ sbio->bi_vcnt = vcnt;
+ sbio->bi_size = r1_bio->sectors << 9;
+ sbio->bi_idx = 0;
+ sbio->bi_phys_segments = 0;
+ sbio->bi_hw_segments = 0;
+ sbio->bi_hw_front_size = 0;
+ sbio->bi_hw_back_size = 0;
+ sbio->bi_flags &= ~(BIO_POOL_MASK - 1);
+ sbio->bi_flags |= 1 << BIO_UPTODATE;
+ sbio->bi_next = NULL;
+ sbio->bi_sector = r1_bio->sector +
+ conf->mirrors[i].rdev->data_offset;
+ sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ }
+ }
+ }
if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
- /*
- * There is no point trying a read-for-reconstruct as
- * reconstruct is about to be aborted
+ /* ouch - failed to read all of that.
+ * Try some synchronous reads of other devices to get
+ * good data, much like with normal read errors. Only
+ * read into the pages we already have so they we don't
+ * need to re-issue the read request.
+ * We don't need to freeze the array, because being in an
+ * active sync request, there is no normal IO, and
+ * no overlapping syncs.
*/
- char b[BDEVNAME_SIZE];
- printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
- " for block %llu\n",
- bdevname(bio->bi_bdev,b),
- (unsigned long long)r1_bio->sector);
- md_done_sync(mddev, r1_bio->sectors, 0);
- put_buf(r1_bio);
- return;
+ sector_t sect = r1_bio->sector;
+ int sectors = r1_bio->sectors;
+ int idx = 0;
+
+ while(sectors) {
+ int s = sectors;
+ int d = r1_bio->read_disk;
+ int success = 0;
+ mdk_rdev_t *rdev;
+
+ if (s > (PAGE_SIZE>>9))
+ s = PAGE_SIZE >> 9;
+ do {
+ if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
+ rdev = conf->mirrors[d].rdev;
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ bio->bi_io_vec[idx].bv_page,
+ READ)) {
+ success = 1;
+ break;
+ }
+ }
+ d++;
+ if (d == conf->raid_disks)
+ d = 0;
+ } while (!success && d != r1_bio->read_disk);
+
+ if (success) {
+ int start = d;
+ /* write it back and re-read */
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
+ while (d != r1_bio->read_disk) {
+ if (d == 0)
+ d = conf->raid_disks;
+ d--;
+ if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+ continue;
+ rdev = conf->mirrors[d].rdev;
+ atomic_add(s, &rdev->corrected_errors);
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ bio->bi_io_vec[idx].bv_page,
+ WRITE) == 0)
+ md_error(mddev, rdev);
+ }
+ d = start;
+ while (d != r1_bio->read_disk) {
+ if (d == 0)
+ d = conf->raid_disks;
+ d--;
+ if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+ continue;
+ rdev = conf->mirrors[d].rdev;
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ bio->bi_io_vec[idx].bv_page,
+ READ) == 0)
+ md_error(mddev, rdev);
+ }
+ } else {
+ char b[BDEVNAME_SIZE];
+ /* Cannot read from anywhere, array is toast */
+ md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+ printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
+ " for block %llu\n",
+ bdevname(bio->bi_bdev,b),
+ (unsigned long long)r1_bio->sector);
+ md_done_sync(mddev, r1_bio->sectors, 0);
+ put_buf(r1_bio);
+ return;
+ }
+ sectors -= s;
+ sect += s;
+ idx ++;
+ }
}
+ /*
+ * schedule writes
+ */
atomic_set(&r1_bio->remaining, 1);
for (i = 0; i < disks ; i++) {
wbio = r1_bio->bios[i];
- if (wbio->bi_end_io != end_sync_write)
+ if (wbio->bi_end_io == NULL ||
+ (wbio->bi_end_io == end_sync_read &&
+ (i == r1_bio->read_disk ||
+ !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
continue;
- atomic_inc(&conf->mirrors[i].rdev->nr_pending);
+ wbio->bi_rw = WRITE;
+ wbio->bi_end_io = end_sync_write;
atomic_inc(&r1_bio->remaining);
md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
@@ -1167,6 +1380,7 @@ static void raid1d(mddev_t *mddev)
break;
r1_bio = list_entry(head->prev, r1bio_t, retry_list);
list_del(head->prev);
+ conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
mddev = r1_bio->mddev;
@@ -1206,6 +1420,86 @@ static void raid1d(mddev_t *mddev)
}
} else {
int disk;
+
+ /* we got a read error. Maybe the drive is bad. Maybe just
+ * the block and we can fix it.
+ * We freeze all other IO, and try reading the block from
+ * other devices. When we find one, we re-write
+ * and check it that fixes the read error.
+ * This is all done synchronously while the array is
+ * frozen
+ */
+ sector_t sect = r1_bio->sector;
+ int sectors = r1_bio->sectors;
+ freeze_array(conf);
+ if (mddev->ro == 0) while(sectors) {
+ int s = sectors;
+ int d = r1_bio->read_disk;
+ int success = 0;
+
+ if (s > (PAGE_SIZE>>9))
+ s = PAGE_SIZE >> 9;
+
+ do {
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags) &&
+ sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ conf->tmppage, READ))
+ success = 1;
+ else {
+ d++;
+ if (d == conf->raid_disks)
+ d = 0;
+ }
+ } while (!success && d != r1_bio->read_disk);
+
+ if (success) {
+ /* write it back and re-read */
+ int start = d;
+ while (d != r1_bio->read_disk) {
+ if (d==0)
+ d = conf->raid_disks;
+ d--;
+ rdev = conf->mirrors[d].rdev;
+ atomic_add(s, &rdev->corrected_errors);
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, WRITE) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ d = start;
+ while (d != r1_bio->read_disk) {
+ if (d==0)
+ d = conf->raid_disks;
+ d--;
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, READ) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ } else {
+ /* Cannot read from anywhere -- bye bye array */
+ md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+ break;
+ }
+ sectors -= s;
+ sect += s;
+ }
+
+ unfreeze_array(conf);
+
bio = r1_bio->bios[r1_bio->read_disk];
if ((disk=read_balance(conf, r1_bio)) == -1) {
printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
@@ -1214,7 +1508,8 @@ static void raid1d(mddev_t *mddev)
(unsigned long long)r1_bio->sector);
raid_end_bio_io(r1_bio);
} else {
- r1_bio->bios[r1_bio->read_disk] = NULL;
+ r1_bio->bios[r1_bio->read_disk] =
+ mddev->ro ? IO_BLOCKED : NULL;
r1_bio->read_disk = disk;
bio_put(bio);
bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
@@ -1269,14 +1564,13 @@ static int init_resync(conf_t *conf)
static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
conf_t *conf = mddev_to_conf(mddev);
- mirror_info_t *mirror;
r1bio_t *r1_bio;
struct bio *bio;
sector_t max_sector, nr_sectors;
- int disk;
+ int disk = -1;
int i;
- int wonly;
- int write_targets = 0;
+ int wonly = -1;
+ int write_targets = 0, read_targets = 0;
int sync_blocks;
int still_degraded = 0;
@@ -1317,55 +1611,35 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return sync_blocks;
}
/*
- * If there is non-resync activity waiting for us then
- * put in a delay to throttle resync.
+ * If there is non-resync activity waiting for a turn,
+ * and resync is going fast enough,
+ * then let it though before starting on this new sync request.
*/
- if (!go_faster && waitqueue_active(&conf->wait_resume))
+ if (!go_faster && conf->nr_waiting)
msleep_interruptible(1000);
- device_barrier(conf, sector_nr + RESYNC_SECTORS);
-
- /*
- * If reconstructing, and >1 working disc,
- * could dedicate one to rebuild and others to
- * service read requests ..
- */
- disk = conf->last_used;
- /* make sure disk is operational */
- wonly = disk;
- while (conf->mirrors[disk].rdev == NULL ||
- !test_bit(In_sync, &conf->mirrors[disk].rdev->flags) ||
- test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
- ) {
- if (conf->mirrors[disk].rdev &&
- test_bit(In_sync, &conf->mirrors[disk].rdev->flags))
- wonly = disk;
- if (disk <= 0)
- disk = conf->raid_disks;
- disk--;
- if (disk == conf->last_used) {
- disk = wonly;
- break;
- }
- }
- conf->last_used = disk;
- atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+ raise_barrier(conf);
- mirror = conf->mirrors + disk;
+ conf->next_resync = sector_nr;
r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
-
- spin_lock_irq(&conf->resync_lock);
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ rcu_read_lock();
+ /*
+ * If we get a correctably read error during resync or recovery,
+ * we might want to read from a different device. So we
+ * flag all drives that could conceivably be read from for READ,
+ * and any others (which will be non-In_sync devices) for WRITE.
+ * If a read fails, we try reading from something else for which READ
+ * is OK.
+ */
r1_bio->mddev = mddev;
r1_bio->sector = sector_nr;
r1_bio->state = 0;
set_bit(R1BIO_IsSync, &r1_bio->state);
- r1_bio->read_disk = disk;
for (i=0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev;
bio = r1_bio->bios[i];
/* take from bio_init */
@@ -1380,35 +1654,49 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
bio->bi_end_io = NULL;
bio->bi_private = NULL;
- if (i == disk) {
- bio->bi_rw = READ;
- bio->bi_end_io = end_sync_read;
- } else if (conf->mirrors[i].rdev == NULL ||
- test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+ rdev = rcu_dereference(conf->mirrors[i].rdev);
+ if (rdev == NULL ||
+ test_bit(Faulty, &rdev->flags)) {
still_degraded = 1;
continue;
- } else if (!test_bit(In_sync, &conf->mirrors[i].rdev->flags) ||
- sector_nr + RESYNC_SECTORS > mddev->recovery_cp ||
- test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ } else if (!test_bit(In_sync, &rdev->flags)) {
bio->bi_rw = WRITE;
bio->bi_end_io = end_sync_write;
write_targets ++;
- } else
- /* no need to read or write here */
- continue;
- bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
- bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ } else {
+ /* may need to read from here */
+ bio->bi_rw = READ;
+ bio->bi_end_io = end_sync_read;
+ if (test_bit(WriteMostly, &rdev->flags)) {
+ if (wonly < 0)
+ wonly = i;
+ } else {
+ if (disk < 0)
+ disk = i;
+ }
+ read_targets++;
+ }
+ atomic_inc(&rdev->nr_pending);
+ bio->bi_sector = sector_nr + rdev->data_offset;
+ bio->bi_bdev = rdev->bdev;
bio->bi_private = r1_bio;
}
+ rcu_read_unlock();
+ if (disk < 0)
+ disk = wonly;
+ r1_bio->read_disk = disk;
+
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && read_targets > 0)
+ /* extra read targets are also write targets */
+ write_targets += read_targets-1;
- if (write_targets == 0) {
+ if (write_targets == 0 || read_targets == 0) {
/* There is nowhere to write, so all non-sync
* drives must be failed - so we are finished
*/
sector_t rv = max_sector - sector_nr;
*skipped = 1;
put_buf(r1_bio);
- rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
return rv;
}
@@ -1436,10 +1724,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
for (i=0 ; i < conf->raid_disks; i++) {
bio = r1_bio->bios[i];
if (bio->bi_end_io) {
- page = r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page;
+ page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
if (bio_add_page(bio, page, len, 0) == 0) {
/* stop here */
- r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page = page;
+ bio->bi_io_vec[bio->bi_vcnt].bv_page = page;
while (i > 0) {
i--;
bio = r1_bio->bios[i];
@@ -1459,12 +1747,28 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sync_blocks -= (len>>9);
} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
bio_full:
- bio = r1_bio->bios[disk];
r1_bio->sectors = nr_sectors;
- md_sync_acct(mirror->rdev->bdev, nr_sectors);
+ /* For a user-requested sync, we read all readable devices and do a
+ * compare
+ */
+ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ atomic_set(&r1_bio->remaining, read_targets);
+ for (i=0; i<conf->raid_disks; i++) {
+ bio = r1_bio->bios[i];
+ if (bio->bi_end_io == end_sync_read) {
+ md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors);
+ generic_make_request(bio);
+ }
+ }
+ } else {
+ atomic_set(&r1_bio->remaining, 1);
+ bio = r1_bio->bios[r1_bio->read_disk];
+ md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev,
+ nr_sectors);
+ generic_make_request(bio);
- generic_make_request(bio);
+ }
return nr_sectors;
}
@@ -1487,18 +1791,19 @@ static int run(mddev_t *mddev)
* bookkeeping area. [whatever we allocate in run(),
* should be freed in stop()]
*/
- conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
mddev->private = conf;
if (!conf)
goto out_no_mem;
- memset(conf, 0, sizeof(*conf));
- conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+ conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
GFP_KERNEL);
if (!conf->mirrors)
goto out_no_mem;
- memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+ conf->tmppage = alloc_page(GFP_KERNEL);
+ if (!conf->tmppage)
+ goto out_no_mem;
conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL);
if (!conf->poolinfo)
@@ -1542,8 +1847,7 @@ static int run(mddev_t *mddev)
mddev->recovery_cp = MaxSector;
spin_lock_init(&conf->resync_lock);
- init_waitqueue_head(&conf->wait_idle);
- init_waitqueue_head(&conf->wait_resume);
+ init_waitqueue_head(&conf->wait_barrier);
bio_list_init(&conf->pending_bio_list);
bio_list_init(&conf->flushing_bio_list);
@@ -1583,7 +1887,6 @@ static int run(mddev_t *mddev)
mdname(mddev));
goto out_free_conf;
}
- if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
printk(KERN_INFO
"raid1: raid set %s active with %d out of %d mirrors\n",
@@ -1608,6 +1911,7 @@ out_free_conf:
if (conf->r1bio_pool)
mempool_destroy(conf->r1bio_pool);
kfree(conf->mirrors);
+ safe_put_page(conf->tmppage);
kfree(conf->poolinfo);
kfree(conf);
mddev->private = NULL;
@@ -1706,19 +2010,14 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
kfree(newpoolinfo);
return -ENOMEM;
}
- newmirrors = kmalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
+ newmirrors = kzalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
if (!newmirrors) {
kfree(newpoolinfo);
mempool_destroy(newpool);
return -ENOMEM;
}
- memset(newmirrors, 0, sizeof(struct mirror_info)*raid_disks);
- spin_lock_irq(&conf->resync_lock);
- conf->barrier++;
- wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, raid1_unplug(mddev->queue));
- spin_unlock_irq(&conf->resync_lock);
+ raise_barrier(conf);
/* ok, everything is stopped */
oldpool = conf->r1bio_pool;
@@ -1738,12 +2037,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
conf->raid_disks = mddev->raid_disks = raid_disks;
conf->last_used = 0; /* just make sure it is in-range */
- spin_lock_irq(&conf->resync_lock);
- conf->barrier--;
- spin_unlock_irq(&conf->resync_lock);
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
-
+ lower_barrier(conf);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
@@ -1758,33 +2052,19 @@ static void raid1_quiesce(mddev_t *mddev, int state)
switch(state) {
case 1:
- spin_lock_irq(&conf->resync_lock);
- conf->barrier++;
- wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, raid1_unplug(mddev->queue));
- spin_unlock_irq(&conf->resync_lock);
+ raise_barrier(conf);
break;
case 0:
- spin_lock_irq(&conf->resync_lock);
- conf->barrier--;
- spin_unlock_irq(&conf->resync_lock);
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
+ lower_barrier(conf);
break;
}
- if (mddev->thread) {
- if (mddev->bitmap)
- mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
- else
- mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
- md_wakeup_thread(mddev->thread);
- }
}
-static mdk_personality_t raid1_personality =
+static struct mdk_personality raid1_personality =
{
.name = "raid1",
+ .level = 1,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -1802,15 +2082,17 @@ static mdk_personality_t raid1_personality =
static int __init raid_init(void)
{
- return register_md_personality(RAID1, &raid1_personality);
+ return register_md_personality(&raid1_personality);
}
static void raid_exit(void)
{
- unregister_md_personality(RAID1);
+ unregister_md_personality(&raid1_personality);
}
module_init(raid_init);
module_exit(raid_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-3"); /* RAID1 */
+MODULE_ALIAS("md-raid1");
+MODULE_ALIAS("md-level-1");
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 713dc9c2c73..9e658e519a2 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -18,7 +18,9 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "dm-bio-list.h"
#include <linux/raid/raid10.h>
+#include <linux/raid/bitmap.h>
/*
* RAID10 provides a combination of RAID0 and RAID1 functionality.
@@ -47,6 +49,9 @@
static void unplug_slaves(mddev_t *mddev);
+static void allow_barrier(conf_t *conf);
+static void lower_barrier(conf_t *conf);
+
static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
{
conf_t *conf = data;
@@ -54,10 +59,8 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
int size = offsetof(struct r10bio_s, devs[conf->copies]);
/* allocate a r10bio with room for raid_disks entries in the bios array */
- r10_bio = kmalloc(size, gfp_flags);
- if (r10_bio)
- memset(r10_bio, 0, size);
- else
+ r10_bio = kzalloc(size, gfp_flags);
+ if (!r10_bio)
unplug_slaves(conf->mddev);
return r10_bio;
@@ -129,10 +132,10 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
out_free_pages:
for ( ; i > 0 ; i--)
- __free_page(bio->bi_io_vec[i-1].bv_page);
+ safe_put_page(bio->bi_io_vec[i-1].bv_page);
while (j--)
for (i = 0; i < RESYNC_PAGES ; i++)
- __free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
+ safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
j = -1;
out_free_bio:
while ( ++j < nalloc )
@@ -152,7 +155,7 @@ static void r10buf_pool_free(void *__r10_bio, void *data)
struct bio *bio = r10bio->devs[j].bio;
if (bio) {
for (i = 0; i < RESYNC_PAGES; i++) {
- __free_page(bio->bi_io_vec[i].bv_page);
+ safe_put_page(bio->bi_io_vec[i].bv_page);
bio->bi_io_vec[i].bv_page = NULL;
}
bio_put(bio);
@@ -167,7 +170,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
for (i = 0; i < conf->copies; i++) {
struct bio **bio = & r10_bio->devs[i].bio;
- if (*bio)
+ if (*bio && *bio != IO_BLOCKED)
bio_put(*bio);
*bio = NULL;
}
@@ -175,20 +178,13 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
static inline void free_r10bio(r10bio_t *r10_bio)
{
- unsigned long flags;
-
conf_t *conf = mddev_to_conf(r10_bio->mddev);
/*
* Wake up any possible resync thread that waits for the device
* to go idle.
*/
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ allow_barrier(conf);
put_all_bios(conf, r10_bio);
mempool_free(r10_bio, conf->r10bio_pool);
@@ -197,22 +193,10 @@ static inline void free_r10bio(r10bio_t *r10_bio)
static inline void put_buf(r10bio_t *r10_bio)
{
conf_t *conf = mddev_to_conf(r10_bio->mddev);
- unsigned long flags;
mempool_free(r10_bio, conf->r10buf_pool);
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!conf->barrier)
- BUG();
- --conf->barrier;
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
-
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ lower_barrier(conf);
}
static void reschedule_retry(r10bio_t *r10_bio)
@@ -223,6 +207,7 @@ static void reschedule_retry(r10bio_t *r10_bio)
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&r10_bio->retry_list, &conf->retry_list);
+ conf->nr_queued ++;
spin_unlock_irqrestore(&conf->device_lock, flags);
md_wakeup_thread(mddev->thread);
@@ -268,9 +253,9 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
- md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
- else
+ update_head_pos(slot, r10_bio);
+
+ if (uptodate) {
/*
* Set R10BIO_Uptodate in our master bio, so that
* we will return a good error code to the higher
@@ -281,15 +266,8 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int
* wait for the 'master' bio.
*/
set_bit(R10BIO_Uptodate, &r10_bio->state);
-
- update_head_pos(slot, r10_bio);
-
- /*
- * we have only one bio on the read side
- */
- if (uptodate)
raid_end_bio_io(r10_bio);
- else {
+ } else {
/*
* oops, read error:
*/
@@ -322,9 +300,11 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
+ if (!uptodate) {
md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
- else
+ /* an I/O failed, we can't clear the bitmap */
+ set_bit(R10BIO_Degraded, &r10_bio->state);
+ } else
/*
* Set R10BIO_Uptodate in our master bio, so that
* we will return a good error code for to the higher
@@ -344,6 +324,11 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in
* already.
*/
if (atomic_dec_and_test(&r10_bio->remaining)) {
+ /* clear the bitmap if all writes complete successfully */
+ bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
+ r10_bio->sectors,
+ !test_bit(R10BIO_Degraded, &r10_bio->state),
+ 0);
md_write_end(r10_bio->mddev);
raid_end_bio_io(r10_bio);
}
@@ -502,8 +487,9 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
rcu_read_lock();
/*
* Check if we can balance. We can balance on the whole
- * device if no resync is going on, or below the resync window.
- * We take the first readable disk when above the resync window.
+ * device if no resync is going on (recovery is ok), or below
+ * the resync window. We take the first readable disk when
+ * above the resync window.
*/
if (conf->mddev->recovery_cp < MaxSector
&& (this_sector + sectors >= conf->next_resync)) {
@@ -512,6 +498,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
disk = r10_bio->devs[slot].devnum;
while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
+ r10_bio->devs[slot].bio == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags)) {
slot++;
if (slot == conf->copies) {
@@ -529,6 +516,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
slot = 0;
disk = r10_bio->devs[slot].devnum;
while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
+ r10_bio->devs[slot].bio == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags)) {
slot ++;
if (slot == conf->copies) {
@@ -549,6 +537,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL ||
+ r10_bio->devs[nslot].bio == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags))
continue;
@@ -607,7 +596,10 @@ static void unplug_slaves(mddev_t *mddev)
static void raid10_unplug(request_queue_t *q)
{
+ mddev_t *mddev = q->queuedata;
+
unplug_slaves(q->queuedata);
+ md_wakeup_thread(mddev->thread);
}
static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -640,27 +632,107 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
return ret;
}
-/*
- * Throttle resync depth, so that we can both get proper overlapping of
- * requests, but are still able to handle normal requests quickly.
+/* Barriers....
+ * Sometimes we need to suspend IO while we do something else,
+ * either some resync/recovery, or reconfigure the array.
+ * To do this we raise a 'barrier'.
+ * The 'barrier' is a counter that can be raised multiple times
+ * to count how many activities are happening which preclude
+ * normal IO.
+ * We can only raise the barrier if there is no pending IO.
+ * i.e. if nr_pending == 0.
+ * We choose only to raise the barrier if no-one is waiting for the
+ * barrier to go down. This means that as soon as an IO request
+ * is ready, no other operations which require a barrier will start
+ * until the IO request has had a chance.
+ *
+ * So: regular IO calls 'wait_barrier'. When that returns there
+ * is no backgroup IO happening, It must arrange to call
+ * allow_barrier when it has finished its IO.
+ * backgroup IO calls must call raise_barrier. Once that returns
+ * there is no normal IO happeing. It must arrange to call
+ * lower_barrier when the particular background IO completes.
*/
#define RESYNC_DEPTH 32
-static void device_barrier(conf_t *conf, sector_t sect)
+static void raise_barrier(conf_t *conf, int force)
+{
+ BUG_ON(force && !conf->barrier);
+ spin_lock_irq(&conf->resync_lock);
+
+ /* Wait until no block IO is waiting (unless 'force') */
+ wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+
+ /* block any new IO from starting */
+ conf->barrier++;
+
+ /* No wait for all pending IO to complete */
+ wait_event_lock_irq(conf->wait_barrier,
+ !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void lower_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->barrier--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void wait_barrier(conf_t *conf)
{
spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
- conf->resync_lock, unplug_slaves(conf->mddev));
-
- if (!conf->barrier++) {
- wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, unplug_slaves(conf->mddev));
- if (conf->nr_pending)
- BUG();
+ if (conf->barrier) {
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+ conf->nr_waiting--;
}
- wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
- conf->resync_lock, unplug_slaves(conf->mddev));
- conf->next_resync = sect;
+ conf->nr_pending++;
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void allow_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->nr_pending--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void freeze_array(conf_t *conf)
+{
+ /* stop syncio and normal IO and wait for everything to
+ * go quiet.
+ * We increment barrier and nr_waiting, and then
+ * wait until barrier+nr_pending match nr_queued+2
+ */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier++;
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier,
+ conf->barrier+conf->nr_pending == conf->nr_queued+2,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void unfreeze_array(conf_t *conf)
+{
+ /* reverse the effect of the freeze */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier--;
+ conf->nr_waiting--;
+ wake_up(&conf->wait_barrier);
spin_unlock_irq(&conf->resync_lock);
}
@@ -674,6 +746,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
int i;
int chunk_sects = conf->chunk_mask + 1;
const int rw = bio_data_dir(bio);
+ struct bio_list bl;
+ unsigned long flags;
if (unlikely(bio_barrier(bio))) {
bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
@@ -719,10 +793,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
* thread has put up a bar for new requests.
* Continue immediately if no resync is active currently.
*/
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ wait_barrier(conf);
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -734,6 +805,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r10_bio->mddev = mddev;
r10_bio->sector = bio->bi_sector;
+ r10_bio->state = 0;
if (rw == READ) {
/*
@@ -778,13 +850,16 @@ static int make_request(request_queue_t *q, struct bio * bio)
!test_bit(Faulty, &rdev->flags)) {
atomic_inc(&rdev->nr_pending);
r10_bio->devs[i].bio = bio;
- } else
+ } else {
r10_bio->devs[i].bio = NULL;
+ set_bit(R10BIO_Degraded, &r10_bio->state);
+ }
}
rcu_read_unlock();
- atomic_set(&r10_bio->remaining, 1);
+ atomic_set(&r10_bio->remaining, 0);
+ bio_list_init(&bl);
for (i = 0; i < conf->copies; i++) {
struct bio *mbio;
int d = r10_bio->devs[i].devnum;
@@ -802,13 +877,14 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_private = r10_bio;
atomic_inc(&r10_bio->remaining);
- generic_make_request(mbio);
+ bio_list_add(&bl, mbio);
}
- if (atomic_dec_and_test(&r10_bio->remaining)) {
- md_write_end(mddev);
- raid_end_bio_io(r10_bio);
- }
+ bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0);
+ spin_lock_irqsave(&conf->device_lock, flags);
+ bio_list_merge(&conf->pending_bio_list, &bl);
+ blk_plug_device(mddev->queue);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
return 0;
}
@@ -897,13 +973,8 @@ static void print_conf(conf_t *conf)
static void close_sync(conf_t *conf)
{
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier,
- conf->resync_lock, unplug_slaves(conf->mddev));
- spin_unlock_irq(&conf->resync_lock);
-
- if (conf->barrier) BUG();
- if (waitqueue_active(&conf->wait_idle)) BUG();
+ wait_barrier(conf);
+ allow_barrier(conf);
mempool_destroy(conf->r10buf_pool);
conf->r10buf_pool = NULL;
@@ -971,7 +1042,12 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
if (!enough(conf))
return 0;
- for (mirror=0; mirror < mddev->raid_disks; mirror++)
+ if (rdev->saved_raid_disk >= 0 &&
+ conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+ mirror = rdev->saved_raid_disk;
+ else
+ mirror = 0;
+ for ( ; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
blk_queue_stack_limits(mddev->queue,
@@ -987,6 +1063,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
p->head_position = 0;
rdev->raid_disk = mirror;
found = 1;
+ if (rdev->saved_raid_disk != mirror)
+ conf->fullsync = 1;
rcu_assign_pointer(p->rdev, rdev);
break;
}
@@ -1027,7 +1105,6 @@ abort:
static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
{
- int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
conf_t *conf = mddev_to_conf(r10_bio->mddev);
int i,d;
@@ -1042,9 +1119,16 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
BUG();
update_head_pos(i, r10_bio);
d = r10_bio->devs[i].devnum;
- if (!uptodate)
- md_error(r10_bio->mddev,
- conf->mirrors[d].rdev);
+
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+ set_bit(R10BIO_Uptodate, &r10_bio->state);
+ else {
+ atomic_add(r10_bio->sectors,
+ &conf->mirrors[d].rdev->corrected_errors);
+ if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+ md_error(r10_bio->mddev,
+ conf->mirrors[d].rdev);
+ }
/* for reconstruct, we always reschedule after a read.
* for resync, only after all reads
@@ -1132,23 +1216,32 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
fbio = r10_bio->devs[i].bio;
/* now find blocks with errors */
- for (i=first+1 ; i < conf->copies ; i++) {
- int vcnt, j, d;
+ for (i=0 ; i < conf->copies ; i++) {
+ int j, d;
+ int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
- if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
- continue;
- /* We know that the bi_io_vec layout is the same for
- * both 'first' and 'i', so we just compare them.
- * All vec entries are PAGE_SIZE;
- */
tbio = r10_bio->devs[i].bio;
- vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
- for (j = 0; j < vcnt; j++)
- if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
- page_address(tbio->bi_io_vec[j].bv_page),
- PAGE_SIZE))
- break;
- if (j == vcnt)
+
+ if (tbio->bi_end_io != end_sync_read)
+ continue;
+ if (i == first)
+ continue;
+ if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) {
+ /* We know that the bi_io_vec layout is the same for
+ * both 'first' and 'i', so we just compare them.
+ * All vec entries are PAGE_SIZE;
+ */
+ for (j = 0; j < vcnt; j++)
+ if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
+ page_address(tbio->bi_io_vec[j].bv_page),
+ PAGE_SIZE))
+ break;
+ if (j == vcnt)
+ continue;
+ mddev->resync_mismatches += r10_bio->sectors;
+ }
+ if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+ /* Don't fix anything. */
continue;
/* Ok, we need to write this bio
* First we need to fixup bv_offset, bv_len and
@@ -1227,7 +1320,10 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
- generic_make_request(wbio);
+ if (test_bit(R10BIO_Uptodate, &r10_bio->state))
+ generic_make_request(wbio);
+ else
+ bio_endio(wbio, wbio->bi_size, -EIO);
}
@@ -1254,10 +1350,31 @@ static void raid10d(mddev_t *mddev)
for (;;) {
char b[BDEVNAME_SIZE];
spin_lock_irqsave(&conf->device_lock, flags);
+
+ if (conf->pending_bio_list.head) {
+ bio = bio_list_get(&conf->pending_bio_list);
+ blk_remove_plug(mddev->queue);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ /* flush any pending bitmap writes to disk before proceeding w/ I/O */
+ if (bitmap_unplug(mddev->bitmap) != 0)
+ printk("%s: bitmap file write failed!\n", mdname(mddev));
+
+ while (bio) { /* submit pending writes */
+ struct bio *next = bio->bi_next;
+ bio->bi_next = NULL;
+ generic_make_request(bio);
+ bio = next;
+ }
+ unplug = 1;
+
+ continue;
+ }
+
if (list_empty(head))
break;
r10_bio = list_entry(head->prev, r10bio_t, retry_list);
list_del(head->prev);
+ conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
mddev = r10_bio->mddev;
@@ -1270,8 +1387,96 @@ static void raid10d(mddev_t *mddev)
unplug = 1;
} else {
int mirror;
+ /* we got a read error. Maybe the drive is bad. Maybe just
+ * the block and we can fix it.
+ * We freeze all other IO, and try reading the block from
+ * other devices. When we find one, we re-write
+ * and check it that fixes the read error.
+ * This is all done synchronously while the array is
+ * frozen.
+ */
+ int sect = 0; /* Offset from r10_bio->sector */
+ int sectors = r10_bio->sectors;
+ freeze_array(conf);
+ if (mddev->ro == 0) while(sectors) {
+ int s = sectors;
+ int sl = r10_bio->read_slot;
+ int success = 0;
+
+ if (s > (PAGE_SIZE>>9))
+ s = PAGE_SIZE >> 9;
+
+ do {
+ int d = r10_bio->devs[sl].devnum;
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags) &&
+ sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9,
+ conf->tmppage, READ))
+ success = 1;
+ else {
+ sl++;
+ if (sl == conf->copies)
+ sl = 0;
+ }
+ } while (!success && sl != r10_bio->read_slot);
+
+ if (success) {
+ int start = sl;
+ /* write it back and re-read */
+ while (sl != r10_bio->read_slot) {
+ int d;
+ if (sl==0)
+ sl = conf->copies;
+ sl--;
+ d = r10_bio->devs[sl].devnum;
+ rdev = conf->mirrors[d].rdev;
+ atomic_add(s, &rdev->corrected_errors);
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, WRITE) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ sl = start;
+ while (sl != r10_bio->read_slot) {
+ int d;
+ if (sl==0)
+ sl = conf->copies;
+ sl--;
+ d = r10_bio->devs[sl].devnum;
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, READ) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ } else {
+ /* Cannot read from anywhere -- bye bye array */
+ md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
+ break;
+ }
+ sectors -= s;
+ sect += s;
+ }
+
+ unfreeze_array(conf);
+
bio = r10_bio->devs[r10_bio->read_slot].bio;
- r10_bio->devs[r10_bio->read_slot].bio = NULL;
+ r10_bio->devs[r10_bio->read_slot].bio =
+ mddev->ro ? IO_BLOCKED : NULL;
bio_put(bio);
mirror = read_balance(conf, r10_bio);
if (mirror == -1) {
@@ -1360,6 +1565,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sector_t max_sector, nr_sectors;
int disk;
int i;
+ int max_sync;
+ int sync_blocks;
sector_t sectors_skipped = 0;
int chunks_skipped = 0;
@@ -1373,6 +1580,29 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
max_sector = mddev->resync_max_sectors;
if (sector_nr >= max_sector) {
+ /* If we aborted, we need to abort the
+ * sync on the 'current' bitmap chucks (there can
+ * be several when recovering multiple devices).
+ * as we may have started syncing it but not finished.
+ * We can find the current address in
+ * mddev->curr_resync, but for recovery,
+ * we need to convert that to several
+ * virtual addresses.
+ */
+ if (mddev->curr_resync < max_sector) { /* aborted */
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else for (i=0; i<conf->raid_disks; i++) {
+ sector_t sect =
+ raid10_find_virt(conf, mddev->curr_resync, i);
+ bitmap_end_sync(mddev->bitmap, sect,
+ &sync_blocks, 1);
+ }
+ } else /* completed sync */
+ conf->fullsync = 0;
+
+ bitmap_close_sync(mddev->bitmap);
close_sync(conf);
*skipped = 1;
return sectors_skipped;
@@ -1395,9 +1625,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
* If there is non-resync activity waiting for us then
* put in a delay to throttle resync.
*/
- if (!go_faster && waitqueue_active(&conf->wait_resume))
+ if (!go_faster && conf->nr_waiting)
msleep_interruptible(1000);
- device_barrier(conf, sector_nr + RESYNC_SECTORS);
/* Again, very different code for resync and recovery.
* Both must result in an r10bio with a list of bios that
@@ -1414,6 +1643,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
* end_sync_write if we will want to write.
*/
+ max_sync = RESYNC_PAGES << (PAGE_SHIFT-9);
if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
/* recovery... the complicated one */
int i, j, k;
@@ -1422,14 +1652,29 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
for (i=0 ; i<conf->raid_disks; i++)
if (conf->mirrors[i].rdev &&
!test_bit(In_sync, &conf->mirrors[i].rdev->flags)) {
+ int still_degraded = 0;
/* want to reconstruct this device */
r10bio_t *rb2 = r10_bio;
+ sector_t sect = raid10_find_virt(conf, sector_nr, i);
+ int must_sync;
+ /* Unless we are doing a full sync, we only need
+ * to recover the block if it is set in the bitmap
+ */
+ must_sync = bitmap_start_sync(mddev->bitmap, sect,
+ &sync_blocks, 1);
+ if (sync_blocks < max_sync)
+ max_sync = sync_blocks;
+ if (!must_sync &&
+ !conf->fullsync) {
+ /* yep, skip the sync_blocks here, but don't assume
+ * that there will never be anything to do here
+ */
+ chunks_skipped = -1;
+ continue;
+ }
r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
- spin_lock_irq(&conf->resync_lock);
- conf->nr_pending++;
- if (rb2) conf->barrier++;
- spin_unlock_irq(&conf->resync_lock);
+ raise_barrier(conf, rb2 != NULL);
atomic_set(&r10_bio->remaining, 0);
r10_bio->master_bio = (struct bio*)rb2;
@@ -1437,8 +1682,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
atomic_inc(&rb2->remaining);
r10_bio->mddev = mddev;
set_bit(R10BIO_IsRecover, &r10_bio->state);
- r10_bio->sector = raid10_find_virt(conf, sector_nr, i);
+ r10_bio->sector = sect;
+
raid10_find_phys(conf, r10_bio);
+ /* Need to check if this section will still be
+ * degraded
+ */
+ for (j=0; j<conf->copies;j++) {
+ int d = r10_bio->devs[j].devnum;
+ if (conf->mirrors[d].rdev == NULL ||
+ test_bit(Faulty, &conf->mirrors[d].rdev->flags)) {
+ still_degraded = 1;
+ break;
+ }
+ }
+ must_sync = bitmap_start_sync(mddev->bitmap, sect,
+ &sync_blocks, still_degraded);
+
for (j=0; j<conf->copies;j++) {
int d = r10_bio->devs[j].devnum;
if (conf->mirrors[d].rdev &&
@@ -1498,14 +1758,22 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
} else {
/* resync. Schedule a read for every block at this virt offset */
int count = 0;
- r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
- spin_lock_irq(&conf->resync_lock);
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr,
+ &sync_blocks, mddev->degraded) &&
+ !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ /* We can skip this block */
+ *skipped = 1;
+ return sync_blocks + sectors_skipped;
+ }
+ if (sync_blocks < max_sync)
+ max_sync = sync_blocks;
+ r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
r10_bio->mddev = mddev;
atomic_set(&r10_bio->remaining, 0);
+ raise_barrier(conf, 0);
+ conf->next_resync = sector_nr;
r10_bio->master_bio = NULL;
r10_bio->sector = sector_nr;
@@ -1558,6 +1826,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
}
nr_sectors = 0;
+ if (sector_nr + max_sync < max_sector)
+ max_sector = sector_nr + max_sync;
do {
struct page *page;
int len = PAGE_SIZE;
@@ -1632,11 +1902,11 @@ static int run(mddev_t *mddev)
int nc, fc;
sector_t stride, size;
- if (mddev->level != 10) {
- printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n",
- mdname(mddev), mddev->level);
- goto out;
+ if (mddev->chunk_size == 0) {
+ printk(KERN_ERR "md/raid10: non-zero chunk size required.\n");
+ return -EINVAL;
}
+
nc = mddev->layout & 255;
fc = (mddev->layout >> 8) & 255;
if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
@@ -1650,22 +1920,24 @@ static int run(mddev_t *mddev)
* bookkeeping area. [whatever we allocate in run(),
* should be freed in stop()]
*/
- conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
mddev->private = conf;
if (!conf) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
goto out;
}
- memset(conf, 0, sizeof(*conf));
- conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+ conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
GFP_KERNEL);
if (!conf->mirrors) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
goto out_free_conf;
}
- memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+
+ conf->tmppage = alloc_page(GFP_KERNEL);
+ if (!conf->tmppage)
+ goto out_free_conf;
conf->near_copies = nc;
conf->far_copies = fc;
@@ -1713,8 +1985,7 @@ static int run(mddev_t *mddev)
INIT_LIST_HEAD(&conf->retry_list);
spin_lock_init(&conf->resync_lock);
- init_waitqueue_head(&conf->wait_idle);
- init_waitqueue_head(&conf->wait_resume);
+ init_waitqueue_head(&conf->wait_barrier);
/* need to check that every block has at least one working mirror */
if (!enough(conf)) {
@@ -1763,7 +2034,7 @@ static int run(mddev_t *mddev)
* maybe...
*/
{
- int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+ int stripe = conf->raid_disks * mddev->chunk_size / PAGE_SIZE;
stripe /= conf->near_copies;
if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
mddev->queue->backing_dev_info.ra_pages = 2* stripe;
@@ -1776,6 +2047,7 @@ static int run(mddev_t *mddev)
out_free_conf:
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
+ safe_put_page(conf->tmppage);
kfree(conf->mirrors);
kfree(conf);
mddev->private = NULL;
@@ -1798,10 +2070,31 @@ static int stop(mddev_t *mddev)
return 0;
}
+static void raid10_quiesce(mddev_t *mddev, int state)
+{
+ conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1:
+ raise_barrier(conf, 0);
+ break;
+ case 0:
+ lower_barrier(conf);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
-static mdk_personality_t raid10_personality =
+static struct mdk_personality raid10_personality =
{
.name = "raid10",
+ .level = 10,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -1812,19 +2105,22 @@ static mdk_personality_t raid10_personality =
.hot_remove_disk= raid10_remove_disk,
.spare_active = raid10_spare_active,
.sync_request = sync_request,
+ .quiesce = raid10_quiesce,
};
static int __init raid_init(void)
{
- return register_md_personality(RAID10, &raid10_personality);
+ return register_md_personality(&raid10_personality);
}
static void raid_exit(void)
{
- unregister_md_personality(RAID10);
+ unregister_md_personality(&raid10_personality);
}
module_init(raid_init);
module_exit(raid_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-9"); /* RAID10 */
+MODULE_ALIAS("md-raid10");
+MODULE_ALIAS("md-level-10");
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index fafc4bc045f..54f4a9847e3 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -35,12 +35,10 @@
#define STRIPE_SHIFT (PAGE_SHIFT - 9)
#define STRIPE_SECTORS (STRIPE_SIZE>>9)
#define IO_THRESHOLD 1
-#define HASH_PAGES 1
-#define HASH_PAGES_ORDER 0
-#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
+#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))
#define HASH_MASK (NR_HASH - 1)
-#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])
+#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
/* bio's attached to a stripe+device for I/O are linked together in bi_sector
* order without overlap. There may be several bio's per stripe+device, and
@@ -113,29 +111,21 @@ static void release_stripe(struct stripe_head *sh)
spin_unlock_irqrestore(&conf->device_lock, flags);
}
-static void remove_hash(struct stripe_head *sh)
+static inline void remove_hash(struct stripe_head *sh)
{
PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
- if (sh->hash_pprev) {
- if (sh->hash_next)
- sh->hash_next->hash_pprev = sh->hash_pprev;
- *sh->hash_pprev = sh->hash_next;
- sh->hash_pprev = NULL;
- }
+ hlist_del_init(&sh->hash);
}
-static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
{
- struct stripe_head **shp = &stripe_hash(conf, sh->sector);
+ struct hlist_head *hp = stripe_hash(conf, sh->sector);
PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
CHECK_DEVLOCK();
- if ((sh->hash_next = *shp) != NULL)
- (*shp)->hash_pprev = &sh->hash_next;
- *shp = sh;
- sh->hash_pprev = shp;
+ hlist_add_head(&sh->hash, hp);
}
@@ -167,7 +157,7 @@ static void shrink_buffers(struct stripe_head *sh, int num)
if (!p)
continue;
sh->dev[i].page = NULL;
- page_cache_release(p);
+ put_page(p);
}
}
@@ -228,10 +218,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i
static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
CHECK_DEVLOCK();
PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
- for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next)
+ hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
if (sh->sector == sector)
return sh;
PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
@@ -417,7 +408,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
set_bit(R5_UPTODATE, &sh->dev[i].flags);
#endif
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- printk("R5: read error corrected!!\n");
+ printk(KERN_INFO "raid5: read error corrected!!\n");
clear_bit(R5_ReadError, &sh->dev[i].flags);
clear_bit(R5_ReWrite, &sh->dev[i].flags);
}
@@ -428,13 +419,14 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
atomic_inc(&conf->disks[i].rdev->read_errors);
if (conf->mddev->degraded)
- printk("R5: read error not correctable.\n");
+ printk(KERN_WARNING "raid5: read error not correctable.\n");
else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
/* Oh, no!!! */
- printk("R5: read error NOT corrected!!\n");
+ printk(KERN_WARNING "raid5: read error NOT corrected!!\n");
else if (atomic_read(&conf->disks[i].rdev->read_errors)
> conf->max_nr_stripes)
- printk("raid5: Too many read errors, failing device.\n");
+ printk(KERN_WARNING
+ "raid5: Too many read errors, failing device.\n");
else
retry = 1;
if (retry)
@@ -604,7 +596,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
*dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks;
break;
default:
- printk("raid5: unsupported algorithm %d\n",
+ printk(KERN_ERR "raid5: unsupported algorithm %d\n",
conf->algorithm);
}
@@ -645,7 +637,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
i -= (sh->pd_idx + 1);
break;
default:
- printk("raid5: unsupported algorithm %d\n",
+ printk(KERN_ERR "raid5: unsupported algorithm %d\n",
conf->algorithm);
}
@@ -654,7 +646,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
- printk("compute_blocknr: map not correct\n");
+ printk(KERN_ERR "compute_blocknr: map not correct\n");
return 0;
}
return r_sector;
@@ -737,7 +729,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx)
if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
ptr[count++] = p;
else
- printk("compute_block() %d, stripe %llu, %d"
+ printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
" not present\n", dd_idx,
(unsigned long long)sh->sector, i);
@@ -960,11 +952,11 @@ static void handle_stripe(struct stripe_head *sh)
syncing = test_bit(STRIPE_SYNCING, &sh->state);
/* Now to look around and see what can be done */
+ rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
clear_bit(R5_Insync, &dev->flags);
- clear_bit(R5_Syncio, &dev->flags);
PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -1003,9 +995,9 @@ static void handle_stripe(struct stripe_head *sh)
non_overwrite++;
}
if (dev->written) written++;
- rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
+ rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
- /* The ReadError flag wil just be confusing now */
+ /* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
@@ -1016,6 +1008,7 @@ static void handle_stripe(struct stripe_head *sh)
} else
set_bit(R5_Insync, &dev->flags);
}
+ rcu_read_unlock();
PRINTK("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d\n",
locked, uptodate, to_read, to_write, failed, failed_num);
@@ -1027,10 +1020,13 @@ static void handle_stripe(struct stripe_head *sh)
int bitmap_end = 0;
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- mdk_rdev_t *rdev = conf->disks[i].rdev;
+ mdk_rdev_t *rdev;
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && test_bit(In_sync, &rdev->flags))
/* multiple read failures in one stripe */
md_error(conf->mddev, rdev);
+ rcu_read_unlock();
}
spin_lock_irq(&conf->device_lock);
@@ -1179,9 +1175,6 @@ static void handle_stripe(struct stripe_head *sh)
locked++;
PRINTK("Reading block %d (sync=%d)\n",
i, syncing);
- if (syncing)
- md_sync_acct(conf->disks[i].rdev->bdev,
- STRIPE_SECTORS);
}
}
}
@@ -1288,7 +1281,7 @@ static void handle_stripe(struct stripe_head *sh)
* is available
*/
if (syncing && locked == 0 &&
- !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 1) {
+ !test_bit(STRIPE_INSYNC, &sh->state)) {
set_bit(STRIPE_HANDLE, &sh->state);
if (failed == 0) {
char *pagea;
@@ -1306,27 +1299,25 @@ static void handle_stripe(struct stripe_head *sh)
if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
/* don't try to repair!! */
set_bit(STRIPE_INSYNC, &sh->state);
+ else {
+ compute_block(sh, sh->pd_idx);
+ uptodate++;
+ }
}
}
if (!test_bit(STRIPE_INSYNC, &sh->state)) {
+ /* either failed parity check, or recovery is happening */
if (failed==0)
failed_num = sh->pd_idx;
- /* should be able to compute the missing block and write it to spare */
- if (!test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)) {
- if (uptodate+1 != disks)
- BUG();
- compute_block(sh, failed_num);
- uptodate++;
- }
- if (uptodate != disks)
- BUG();
dev = &sh->dev[failed_num];
+ BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+ BUG_ON(uptodate != disks);
+
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantwrite, &dev->flags);
clear_bit(STRIPE_DEGRADED, &sh->state);
locked++;
set_bit(STRIPE_INSYNC, &sh->state);
- set_bit(R5_Syncio, &dev->flags);
}
}
if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
@@ -1392,7 +1383,7 @@ static void handle_stripe(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (test_bit(R5_Syncio, &sh->dev[i].flags))
+ if (syncing)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
@@ -1409,6 +1400,9 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_io_vec[0].bv_offset = 0;
bi->bi_size = STRIPE_SIZE;
bi->bi_next = NULL;
+ if (rw == WRITE &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+ atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
if (rw == 1)
@@ -1822,21 +1816,21 @@ static int run(mddev_t *mddev)
struct list_head *tmp;
if (mddev->level != 5 && mddev->level != 4) {
- printk("raid5: %s: raid level not set to 4/5 (%d)\n", mdname(mddev), mddev->level);
+ printk(KERN_ERR "raid5: %s: raid level not set to 4/5 (%d)\n",
+ mdname(mddev), mddev->level);
return -EIO;
}
- mddev->private = kmalloc (sizeof (raid5_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ mddev->private = kzalloc(sizeof (raid5_conf_t)
+ + mddev->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
- memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) );
+
conf->mddev = mddev;
- if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL)
+ if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
goto abort;
- memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
spin_lock_init(&conf->device_lock);
init_waitqueue_head(&conf->wait_for_stripe);
@@ -1903,10 +1897,17 @@ static int run(mddev_t *mddev)
if (mddev->degraded == 1 &&
mddev->recovery_cp != MaxSector) {
- printk(KERN_ERR
- "raid5: cannot start dirty degraded array for %s\n",
- mdname(mddev));
- goto abort;
+ if (mddev->ok_start_degraded)
+ printk(KERN_WARNING
+ "raid5: starting dirty degraded array: %s"
+ "- data corruption possible.\n",
+ mdname(mddev));
+ else {
+ printk(KERN_ERR
+ "raid5: cannot start dirty degraded array for %s\n",
+ mdname(mddev));
+ goto abort;
+ }
}
{
@@ -1948,7 +1949,7 @@ static int run(mddev_t *mddev)
*/
{
int stripe = (mddev->raid_disks-1) * mddev->chunk_size
- / PAGE_CACHE_SIZE;
+ / PAGE_SIZE;
if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
}
@@ -1956,9 +1957,6 @@ static int run(mddev_t *mddev)
/* Ok, everything is just fine now */
sysfs_create_group(&mddev->kobj, &raid5_attrs_group);
- if (mddev->bitmap)
- mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
@@ -1967,9 +1965,7 @@ static int run(mddev_t *mddev)
abort:
if (conf) {
print_raid5_conf(conf);
- if (conf->stripe_hashtbl)
- free_pages((unsigned long) conf->stripe_hashtbl,
- HASH_PAGES_ORDER);
+ kfree(conf->stripe_hashtbl);
kfree(conf);
}
mddev->private = NULL;
@@ -1986,7 +1982,7 @@ static int stop(mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
shrink_stripes(conf);
- free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+ kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
kfree(conf);
@@ -2014,12 +2010,12 @@ static void print_sh (struct stripe_head *sh)
static void printall (raid5_conf_t *conf)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
int i;
spin_lock_irq(&conf->device_lock);
for (i = 0; i < NR_HASH; i++) {
- sh = conf->stripe_hashtbl[i];
- for (; sh; sh = sh->hash_next) {
+ hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
if (sh->raid_conf != conf)
continue;
print_sh(sh);
@@ -2192,17 +2188,12 @@ static void raid5_quiesce(mddev_t *mddev, int state)
spin_unlock_irq(&conf->device_lock);
break;
}
- if (mddev->thread) {
- if (mddev->bitmap)
- mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
- else
- mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
- md_wakeup_thread(mddev->thread);
- }
}
-static mdk_personality_t raid5_personality=
+
+static struct mdk_personality raid5_personality =
{
.name = "raid5",
+ .level = 5,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -2217,17 +2208,42 @@ static mdk_personality_t raid5_personality=
.quiesce = raid5_quiesce,
};
-static int __init raid5_init (void)
+static struct mdk_personality raid4_personality =
{
- return register_md_personality (RAID5, &raid5_personality);
+ .name = "raid4",
+ .level = 4,
+ .owner = THIS_MODULE,
+ .make_request = make_request,
+ .run = run,
+ .stop = stop,
+ .status = status,
+ .error_handler = error,
+ .hot_add_disk = raid5_add_disk,
+ .hot_remove_disk= raid5_remove_disk,
+ .spare_active = raid5_spare_active,
+ .sync_request = sync_request,
+ .resize = raid5_resize,
+ .quiesce = raid5_quiesce,
+};
+
+static int __init raid5_init(void)
+{
+ register_md_personality(&raid5_personality);
+ register_md_personality(&raid4_personality);
+ return 0;
}
-static void raid5_exit (void)
+static void raid5_exit(void)
{
- unregister_md_personality (RAID5);
+ unregister_md_personality(&raid5_personality);
+ unregister_md_personality(&raid4_personality);
}
module_init(raid5_init);
module_exit(raid5_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-4"); /* RAID5 */
+MODULE_ALIAS("md-raid5");
+MODULE_ALIAS("md-raid4");
+MODULE_ALIAS("md-level-5");
+MODULE_ALIAS("md-level-4");
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 0000d162d19..8c823d686a6 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -40,12 +40,10 @@
#define STRIPE_SHIFT (PAGE_SHIFT - 9)
#define STRIPE_SECTORS (STRIPE_SIZE>>9)
#define IO_THRESHOLD 1
-#define HASH_PAGES 1
-#define HASH_PAGES_ORDER 0
-#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
+#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))
#define HASH_MASK (NR_HASH - 1)
-#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])
+#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
/* bio's attached to a stripe+device for I/O are linked together in bi_sector
* order without overlap. There may be several bio's per stripe+device, and
@@ -132,29 +130,21 @@ static void release_stripe(struct stripe_head *sh)
spin_unlock_irqrestore(&conf->device_lock, flags);
}
-static void remove_hash(struct stripe_head *sh)
+static inline void remove_hash(struct stripe_head *sh)
{
PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
- if (sh->hash_pprev) {
- if (sh->hash_next)
- sh->hash_next->hash_pprev = sh->hash_pprev;
- *sh->hash_pprev = sh->hash_next;
- sh->hash_pprev = NULL;
- }
+ hlist_del_init(&sh->hash);
}
-static __inline__ void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
{
- struct stripe_head **shp = &stripe_hash(conf, sh->sector);
+ struct hlist_head *hp = stripe_hash(conf, sh->sector);
PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
CHECK_DEVLOCK();
- if ((sh->hash_next = *shp) != NULL)
- (*shp)->hash_pprev = &sh->hash_next;
- *shp = sh;
- sh->hash_pprev = shp;
+ hlist_add_head(&sh->hash, hp);
}
@@ -186,7 +176,7 @@ static void shrink_buffers(struct stripe_head *sh, int num)
if (!p)
continue;
sh->dev[i].page = NULL;
- page_cache_release(p);
+ put_page(p);
}
}
@@ -247,10 +237,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i
static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
CHECK_DEVLOCK();
PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
- for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next)
+ hlist_for_each_entry (sh, hn, stripe_hash(conf, sector), hash)
if (sh->sector == sector)
return sh;
PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
@@ -367,8 +358,8 @@ static void shrink_stripes(raid6_conf_t *conf)
conf->slab_cache = NULL;
}
-static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done,
- int error)
+static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done,
+ int error)
{
struct stripe_head *sh = bi->bi_private;
raid6_conf_t *conf = sh->raid_conf;
@@ -420,9 +411,35 @@ static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done,
#else
set_bit(R5_UPTODATE, &sh->dev[i].flags);
#endif
+ if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+ printk(KERN_INFO "raid6: read error corrected!!\n");
+ clear_bit(R5_ReadError, &sh->dev[i].flags);
+ clear_bit(R5_ReWrite, &sh->dev[i].flags);
+ }
+ if (atomic_read(&conf->disks[i].rdev->read_errors))
+ atomic_set(&conf->disks[i].rdev->read_errors, 0);
} else {
- md_error(conf->mddev, conf->disks[i].rdev);
+ int retry = 0;
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
+ atomic_inc(&conf->disks[i].rdev->read_errors);
+ if (conf->mddev->degraded)
+ printk(KERN_WARNING "raid6: read error not correctable.\n");
+ else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
+ /* Oh, no!!! */
+ printk(KERN_WARNING "raid6: read error NOT corrected!!\n");
+ else if (atomic_read(&conf->disks[i].rdev->read_errors)
+ > conf->max_nr_stripes)
+ printk(KERN_WARNING
+ "raid6: Too many read errors, failing device.\n");
+ else
+ retry = 1;
+ if (retry)
+ set_bit(R5_ReadError, &sh->dev[i].flags);
+ else {
+ clear_bit(R5_ReadError, &sh->dev[i].flags);
+ clear_bit(R5_ReWrite, &sh->dev[i].flags);
+ md_error(conf->mddev, conf->disks[i].rdev);
+ }
}
rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
#if 0
@@ -805,7 +822,7 @@ static void compute_parity(struct stripe_head *sh, int method)
}
/* Compute one missing block */
-static void compute_block_1(struct stripe_head *sh, int dd_idx)
+static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
{
raid6_conf_t *conf = sh->raid_conf;
int i, count, disks = conf->raid_disks;
@@ -821,7 +838,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx)
compute_parity(sh, UPDATE_PARITY);
} else {
ptr[0] = page_address(sh->dev[dd_idx].page);
- memset(ptr[0], 0, STRIPE_SIZE);
+ if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
count = 1;
for (i = disks ; i--; ) {
if (i == dd_idx || i == qd_idx)
@@ -838,7 +855,8 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx)
}
if (count != 1)
xor_block(count, STRIPE_SIZE, ptr);
- set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+ if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+ else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
}
}
@@ -871,7 +889,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
return;
} else {
/* We're missing D+Q; recompute D from P */
- compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1);
+ compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
compute_parity(sh, UPDATE_PARITY); /* Is this necessary? */
return;
}
@@ -982,6 +1000,12 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
}
+static int page_is_zero(struct page *p)
+{
+ char *a = page_address(p);
+ return ((*(u32*)a) == 0 &&
+ memcmp(a, a+4, STRIPE_SIZE-4)==0);
+}
/*
* handle_stripe - do things to a stripe.
*
@@ -1000,7 +1024,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
*
*/
-static void handle_stripe(struct stripe_head *sh)
+static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
{
raid6_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks;
@@ -1027,11 +1051,11 @@ static void handle_stripe(struct stripe_head *sh)
syncing = test_bit(STRIPE_SYNCING, &sh->state);
/* Now to look around and see what can be done */
+ rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
clear_bit(R5_Insync, &dev->flags);
- clear_bit(R5_Syncio, &dev->flags);
PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -1070,14 +1094,21 @@ static void handle_stripe(struct stripe_head *sh)
non_overwrite++;
}
if (dev->written) written++;
- rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
+ rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ /* The ReadError flag will just be confusing now */
+ clear_bit(R5_ReadError, &dev->flags);
+ clear_bit(R5_ReWrite, &dev->flags);
+ }
+ if (!rdev || !test_bit(In_sync, &rdev->flags)
+ || test_bit(R5_ReadError, &dev->flags)) {
if ( failed < 2 )
failed_num[failed] = i;
failed++;
} else
set_bit(R5_Insync, &dev->flags);
}
+ rcu_read_unlock();
PRINTK("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d,%d\n",
locked, uptodate, to_read, to_write, failed,
@@ -1088,6 +1119,17 @@ static void handle_stripe(struct stripe_head *sh)
if (failed > 2 && to_read+to_write+written) {
for (i=disks; i--; ) {
int bitmap_end = 0;
+
+ if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+ mdk_rdev_t *rdev;
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[i].rdev);
+ if (rdev && test_bit(In_sync, &rdev->flags))
+ /* multiple read failures in one stripe */
+ md_error(conf->mddev, rdev);
+ rcu_read_unlock();
+ }
+
spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
@@ -1123,7 +1165,8 @@ static void handle_stripe(struct stripe_head *sh)
}
/* fail any reads if this device is non-operational */
- if (!test_bit(R5_Insync, &sh->dev[i].flags)) {
+ if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+ test_bit(R5_ReadError, &sh->dev[i].flags)) {
bi = sh->dev[i].toread;
sh->dev[i].toread = NULL;
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
@@ -1228,7 +1271,7 @@ static void handle_stripe(struct stripe_head *sh)
if (uptodate == disks-1) {
PRINTK("Computing stripe %llu block %d\n",
(unsigned long long)sh->sector, i);
- compute_block_1(sh, i);
+ compute_block_1(sh, i, 0);
uptodate++;
} else if ( uptodate == disks-2 && failed >= 2 ) {
/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
@@ -1259,9 +1302,6 @@ static void handle_stripe(struct stripe_head *sh)
locked++;
PRINTK("Reading block %d (sync=%d)\n",
i, syncing);
- if (syncing)
- md_sync_acct(conf->disks[i].rdev->bdev,
- STRIPE_SECTORS);
}
}
}
@@ -1323,7 +1363,7 @@ static void handle_stripe(struct stripe_head *sh)
/* We have failed blocks and need to compute them */
switch ( failed ) {
case 0: BUG();
- case 1: compute_block_1(sh, failed_num[0]); break;
+ case 1: compute_block_1(sh, failed_num[0], 0); break;
case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
default: BUG(); /* This request should have been failed? */
}
@@ -1338,12 +1378,10 @@ static void handle_stripe(struct stripe_head *sh)
(unsigned long long)sh->sector, i);
locked++;
set_bit(R5_Wantwrite, &sh->dev[i].flags);
-#if 0 /**** FIX: I don't understand the logic here... ****/
- if (!test_bit(R5_Insync, &sh->dev[i].flags)
- || ((i==pd_idx || i==qd_idx) && failed == 0)) /* FIX? */
- set_bit(STRIPE_INSYNC, &sh->state);
-#endif
}
+ /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+ set_bit(STRIPE_INSYNC, &sh->state);
+
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
atomic_dec(&conf->preread_active_stripes);
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -1356,84 +1394,119 @@ static void handle_stripe(struct stripe_head *sh)
* Any reads will already have been scheduled, so we just see if enough data
* is available
*/
- if (syncing && locked == 0 &&
- !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 2) {
- set_bit(STRIPE_HANDLE, &sh->state);
-#if 0 /* RAID-6: Don't support CHECK PARITY yet */
- if (failed == 0) {
- char *pagea;
- if (uptodate != disks)
- BUG();
- compute_parity(sh, CHECK_PARITY);
- uptodate--;
- pagea = page_address(sh->dev[pd_idx].page);
- if ((*(u32*)pagea) == 0 &&
- !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) {
- /* parity is correct (on disc, not in buffer any more) */
- set_bit(STRIPE_INSYNC, &sh->state);
- }
- }
-#endif
- if (!test_bit(STRIPE_INSYNC, &sh->state)) {
- int failed_needupdate[2];
- struct r5dev *adev, *bdev;
-
- if ( failed < 1 )
- failed_num[0] = pd_idx;
- if ( failed < 2 )
- failed_num[1] = (failed_num[0] == qd_idx) ? pd_idx : qd_idx;
+ if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
+ int update_p = 0, update_q = 0;
+ struct r5dev *dev;
- failed_needupdate[0] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[0]].flags);
- failed_needupdate[1] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[1]].flags);
+ set_bit(STRIPE_HANDLE, &sh->state);
- PRINTK("sync: failed=%d num=%d,%d fnu=%u%u\n",
- failed, failed_num[0], failed_num[1], failed_needupdate[0], failed_needupdate[1]);
+ BUG_ON(failed>2);
+ BUG_ON(uptodate < disks);
+ /* Want to check and possibly repair P and Q.
+ * However there could be one 'failed' device, in which
+ * case we can only check one of them, possibly using the
+ * other to generate missing data
+ */
-#if 0 /* RAID-6: This code seems to require that CHECK_PARITY destroys the uptodateness of the parity */
- /* should be able to compute the missing block(s) and write to spare */
- if ( failed_needupdate[0] ^ failed_needupdate[1] ) {
- if (uptodate+1 != disks)
- BUG();
- compute_block_1(sh, failed_needupdate[0] ? failed_num[0] : failed_num[1]);
- uptodate++;
- } else if ( failed_needupdate[0] & failed_needupdate[1] ) {
- if (uptodate+2 != disks)
- BUG();
- compute_block_2(sh, failed_num[0], failed_num[1]);
- uptodate += 2;
+ /* If !tmp_page, we cannot do the calculations,
+ * but as we have set STRIPE_HANDLE, we will soon be called
+ * by stripe_handle with a tmp_page - just wait until then.
+ */
+ if (tmp_page) {
+ if (failed == q_failed) {
+ /* The only possible failed device holds 'Q', so it makes
+ * sense to check P (If anything else were failed, we would
+ * have used P to recreate it).
+ */
+ compute_block_1(sh, pd_idx, 1);
+ if (!page_is_zero(sh->dev[pd_idx].page)) {
+ compute_block_1(sh,pd_idx,0);
+ update_p = 1;
+ }
+ }
+ if (!q_failed && failed < 2) {
+ /* q is not failed, and we didn't use it to generate
+ * anything, so it makes sense to check it
+ */
+ memcpy(page_address(tmp_page),
+ page_address(sh->dev[qd_idx].page),
+ STRIPE_SIZE);
+ compute_parity(sh, UPDATE_PARITY);
+ if (memcmp(page_address(tmp_page),
+ page_address(sh->dev[qd_idx].page),
+ STRIPE_SIZE)!= 0) {
+ clear_bit(STRIPE_INSYNC, &sh->state);
+ update_q = 1;
+ }
+ }
+ if (update_p || update_q) {
+ conf->mddev->resync_mismatches += STRIPE_SECTORS;
+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ /* don't try to repair!! */
+ update_p = update_q = 0;
}
-#else
- compute_block_2(sh, failed_num[0], failed_num[1]);
- uptodate += failed_needupdate[0] + failed_needupdate[1];
-#endif
- if (uptodate != disks)
- BUG();
+ /* now write out any block on a failed drive,
+ * or P or Q if they need it
+ */
- PRINTK("Marking for sync stripe %llu blocks %d,%d\n",
- (unsigned long long)sh->sector, failed_num[0], failed_num[1]);
+ if (failed == 2) {
+ dev = &sh->dev[failed_num[1]];
+ locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ if (failed >= 1) {
+ dev = &sh->dev[failed_num[0]];
+ locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
- /**** FIX: Should we really do both of these unconditionally? ****/
- adev = &sh->dev[failed_num[0]];
- locked += !test_bit(R5_LOCKED, &adev->flags);
- set_bit(R5_LOCKED, &adev->flags);
- set_bit(R5_Wantwrite, &adev->flags);
- bdev = &sh->dev[failed_num[1]];
- locked += !test_bit(R5_LOCKED, &bdev->flags);
- set_bit(R5_LOCKED, &bdev->flags);
+ if (update_p) {
+ dev = &sh->dev[pd_idx];
+ locked ++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ if (update_q) {
+ dev = &sh->dev[qd_idx];
+ locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
clear_bit(STRIPE_DEGRADED, &sh->state);
- set_bit(R5_Wantwrite, &bdev->flags);
set_bit(STRIPE_INSYNC, &sh->state);
- set_bit(R5_Syncio, &adev->flags);
- set_bit(R5_Syncio, &bdev->flags);
}
}
+
if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
md_done_sync(conf->mddev, STRIPE_SECTORS,1);
clear_bit(STRIPE_SYNCING, &sh->state);
}
+ /* If the failed drives are just a ReadError, then we might need
+ * to progress the repair/check process
+ */
+ if (failed <= 2 && ! conf->mddev->ro)
+ for (i=0; i<failed;i++) {
+ dev = &sh->dev[failed_num[i]];
+ if (test_bit(R5_ReadError, &dev->flags)
+ && !test_bit(R5_LOCKED, &dev->flags)
+ && test_bit(R5_UPTODATE, &dev->flags)
+ ) {
+ if (!test_bit(R5_ReWrite, &dev->flags)) {
+ set_bit(R5_Wantwrite, &dev->flags);
+ set_bit(R5_ReWrite, &dev->flags);
+ set_bit(R5_LOCKED, &dev->flags);
+ } else {
+ /* let's read it back */
+ set_bit(R5_Wantread, &dev->flags);
+ set_bit(R5_LOCKED, &dev->flags);
+ }
+ }
+ }
spin_unlock(&sh->lock);
while ((bi=return_bi)) {
@@ -1472,7 +1545,7 @@ static void handle_stripe(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (test_bit(R5_Syncio, &sh->dev[i].flags))
+ if (syncing)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
@@ -1489,6 +1562,9 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_io_vec[0].bv_offset = 0;
bi->bi_size = STRIPE_SIZE;
bi->bi_next = NULL;
+ if (rw == WRITE &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+ atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
if (rw == 1)
@@ -1664,7 +1740,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
}
finish_wait(&conf->wait_for_overlap, &w);
raid6_plug_device(conf);
- handle_stripe(sh);
+ handle_stripe(sh, NULL);
release_stripe(sh);
} else {
/* cannot get stripe for read-ahead, just give-up */
@@ -1728,6 +1804,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return rv;
}
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
!conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
/* we can skip this block, and probably more */
sync_blocks /= STRIPE_SECTORS;
@@ -1765,7 +1842,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
clear_bit(STRIPE_INSYNC, &sh->state);
spin_unlock(&sh->lock);
- handle_stripe(sh);
+ handle_stripe(sh, NULL);
release_stripe(sh);
return STRIPE_SECTORS;
@@ -1821,7 +1898,7 @@ static void raid6d (mddev_t *mddev)
spin_unlock_irq(&conf->device_lock);
handled++;
- handle_stripe(sh);
+ handle_stripe(sh, conf->spare_page);
release_stripe(sh);
spin_lock_irq(&conf->device_lock);
@@ -1848,17 +1925,19 @@ static int run(mddev_t *mddev)
return -EIO;
}
- mddev->private = kmalloc (sizeof (raid6_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ mddev->private = kzalloc(sizeof (raid6_conf_t)
+ + mddev->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
- memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) );
conf->mddev = mddev;
- if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL)
+ if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
+ goto abort;
+
+ conf->spare_page = alloc_page(GFP_KERNEL);
+ if (!conf->spare_page)
goto abort;
- memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
spin_lock_init(&conf->device_lock);
init_waitqueue_head(&conf->wait_for_stripe);
@@ -1929,13 +2008,18 @@ static int run(mddev_t *mddev)
goto abort;
}
-#if 0 /* FIX: For now */
if (mddev->degraded > 0 &&
mddev->recovery_cp != MaxSector) {
- printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev));
- goto abort;
+ if (mddev->ok_start_degraded)
+ printk(KERN_WARNING "raid6: starting dirty degraded array:%s"
+ "- data corruption possible.\n",
+ mdname(mddev));
+ else {
+ printk(KERN_ERR "raid6: cannot start dirty degraded array"
+ " for %s\n", mdname(mddev));
+ goto abort;
+ }
}
-#endif
{
mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6");
@@ -1977,7 +2061,7 @@ static int run(mddev_t *mddev)
*/
{
int stripe = (mddev->raid_disks-2) * mddev->chunk_size
- / PAGE_CACHE_SIZE;
+ / PAGE_SIZE;
if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
}
@@ -1985,18 +2069,14 @@ static int run(mddev_t *mddev)
/* Ok, everything is just fine now */
mddev->array_size = mddev->size * (mddev->raid_disks - 2);
- if (mddev->bitmap)
- mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
-
mddev->queue->unplug_fn = raid6_unplug_device;
mddev->queue->issue_flush_fn = raid6_issue_flush;
return 0;
abort:
if (conf) {
print_raid6_conf(conf);
- if (conf->stripe_hashtbl)
- free_pages((unsigned long) conf->stripe_hashtbl,
- HASH_PAGES_ORDER);
+ safe_put_page(conf->spare_page);
+ kfree(conf->stripe_hashtbl);
kfree(conf);
}
mddev->private = NULL;
@@ -2013,7 +2093,7 @@ static int stop (mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
shrink_stripes(conf);
- free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+ kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf);
mddev->private = NULL;
@@ -2040,12 +2120,13 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh)
static void printall (struct seq_file *seq, raid6_conf_t *conf)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
int i;
spin_lock_irq(&conf->device_lock);
for (i = 0; i < NR_HASH; i++) {
sh = conf->stripe_hashtbl[i];
- for (; sh; sh = sh->hash_next) {
+ hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
if (sh->raid_conf != conf)
continue;
print_sh(seq, sh);
@@ -2223,17 +2304,12 @@ static void raid6_quiesce(mddev_t *mddev, int state)
spin_unlock_irq(&conf->device_lock);
break;
}
- if (mddev->thread) {
- if (mddev->bitmap)
- mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
- else
- mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
- md_wakeup_thread(mddev->thread);
- }
}
-static mdk_personality_t raid6_personality=
+
+static struct mdk_personality raid6_personality =
{
.name = "raid6",
+ .level = 6,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -2248,7 +2324,7 @@ static mdk_personality_t raid6_personality=
.quiesce = raid6_quiesce,
};
-static int __init raid6_init (void)
+static int __init raid6_init(void)
{
int e;
@@ -2256,15 +2332,17 @@ static int __init raid6_init (void)
if ( e )
return e;
- return register_md_personality (RAID6, &raid6_personality);
+ return register_md_personality(&raid6_personality);
}
static void raid6_exit (void)
{
- unregister_md_personality (RAID6);
+ unregister_md_personality(&raid6_personality);
}
module_init(raid6_init);
module_exit(raid6_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-8"); /* RAID6 */
+MODULE_ALIAS("md-raid6");
+MODULE_ALIAS("md-level-6");
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 2899d34e5f7..04c1938b9c9 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 09ec964dec5..f8cf73ed49a 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 ec52dff8cb6..33bec8a6843 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 063986ec16b..468d3c95907 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 1d961023b83..7ebac7949df 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 21a9045b3ef..0b940e152b7 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 23cc6431e2b..3153f9513c6 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 123ed96f6fa..56ba5247067 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/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 8977c7a313d..3a2ff1cc24b 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 2239651969c..c650b4bf7f5 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 77977e9c013..f65f64b00ff 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.
@@ -794,10 +786,9 @@ static int dvb_bt8xx_probe(struct device *dev)
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 +803,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 +812,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;
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 7cf4c4a888e..6018fcdba1e 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 b996fb59b7e..c4b4c5b6b7c 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -60,7 +60,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk(level, args...) \
do { \
if ((debug & level)) { \
- printk("%s: %s(): ", __stringify(KBUILD_MODNAME), \
+ printk("%s: %s(): ", KBUILD_MODNAME, \
__FUNCTION__); \
printk(args); } \
} while (0)
@@ -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 a9a7b342104..12ee912a570 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 c6baac20f52..7adb50c1e8e 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 5956c35d34a..00347a75068 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 c49fd0bd718..772003fb182 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 95ea5095e07..771f32d889e 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 1e0840d02f1..70a6d14efda 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 86bba81e851..6711eb6a058 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 283c6e9339a..77ad2410f4d 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 fa476f662f8..6d256097277 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 a4aee866585..06b696e9acb 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -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;
@@ -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 0cc6e4a0e27..74ed5853f0f 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 54e2b29076b..90a69d343b7 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 d05fab01ccc..18d169836c9 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,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 135c2a81f58..087c9942785 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 52ac3e5adf5..dd5a1319588 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 450417a9e64..e6c55c9c941 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 0a94ec22aeb..cd21ddbfd05 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 6e2bac87344..130ea7f21f5 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 6f1f3042e21..005b0a7df35 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 7300489d3e2..a3460bf2d9f 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 5244e39770a..8535895819f 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 da970947dfc..9b254532af4 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 6be99e537e1..4a1b9e77e33 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 dd8e0b94edb..716f8bf528c 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 36b7048c02d..ee821974dc6 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 b4a1a98006c..dd568396e59 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 fac48fc7a4a..412039d8dba 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 104b5d016c7..b6d95e1c9c5 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 4a3e8c7eca2..a808d48e7bf 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 83f1de1e7e5..5242cca5db4 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 3835235b68d..028204956bb 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 8e269e1c1f9..db3a8b40031 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 a98760fe08a..615ec830e1c 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 8ceb9a33c7a..caaee893ca7 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 5de0e6d350b..0fc899f81c5 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 0c4db80ec33..d15d32c51dc 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 00000000000..d661c6f9cbe
--- /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 00000000000..0c922b5e926
--- /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 6b055360861..ae589adb1c0 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 c024fad1733..3b303dbb615 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 f857b869616..757075f007c 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 */
@@ -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 497d31dcf41..f682c09189b 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 cb5301865d0..4691ac54bc1 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 8d672283c93..ec4e641acc6 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 f0c610f2c2d..aaaec909ddf 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 52c416043a6..4f263e65ba1 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 aeafef46e3e..78d2b93d35b 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 a458a3bfff7..a16eeba0020 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 531f76246e5..7c3aed1f546 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 18715091aed..d6947759692 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 fc06cd6b46c..73829e647e5 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 e3b66578224..eb8a602198c 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 177d71d56b6..5bcd00f792e 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 9af3d71c89d..32c87b4c2f1 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 425cd19136f..21255cac979 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 dd02aff467f..c63e9a5084e 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 f02842be0d6..84f8f9f5286 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 bbebd1c4cac..1c5316e209e 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 fa5034a9ecf..5b2aadb8385 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 825ab1c38a4..a690730ac39 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 7dae91e5863..327a8089193 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -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 cce00ef293e..6ea30df2e82 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 0696a5a4f85..400facec740 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 87106e8bf35..cb377452b57 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -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 */
@@ -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 2a5e87ba105..84b83299b8b 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -167,7 +167,8 @@ enum av7110_encoder_command {
LoadVidCode,
SetMonitorType,
SetPanScanType,
- SetFreezeMode
+ SetFreezeMode,
+ SetWSSConfig
};
enum av7110_rec_play_state {
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index f5e59fc924a..9138132ad25 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 b5aea4129fa..94cf38c7e8a 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 9f51bae7194..1465c04e49a 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 017fcbccb8c..633e68c341c 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 fafe6407b3d..238c77b52f8 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 fdaa3318ad3..c7bb63c4d98 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -19,7 +19,7 @@ extern int budget_debug;
#endif
#define dprintk(level,args...) \
- do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0)
+ do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
struct budget_info {
char *name;
@@ -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 18aa22b5478..1f31e91195b 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 c6c1d41a2ef..914587d52b5 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 104df610dbe..5a13c4744f6 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 c334526af66..83611012ef3 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 8abc2189012..df831171e03 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 725af3af5b2..a5a46175fa0 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 c2ebe8754a9..dc292da2605 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 877c770558e..914deab4e04 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 5319a9c9a97..523be820f9c 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 9b0406318f2..f1b5ac81e9d 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 630cc786d0a..8e499b8f64c 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 6418f03b9ce..47173be97b9 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 e5e2021a731..36c9f5bf8cd 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 02d39a50d5e..c975ddd86cd 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 b2256d675b4..28a47c9e7a8 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 6f03ce4dd7b..0229f792a05 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 71971e9bb34..099ffb3b9c7 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 b03573c6840..fcfde2e4f19 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 b300bedf7c7..5a099a50d4d 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 f304f3c1476..8ac9a8ef909 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 4c6d6fb4903..d590e80c922 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 fc87efc5049..d82c8a30ba4 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 82060f9909d..dd24896906f 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -3,15 +3,19 @@
#
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
+
+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 1ca2b67aedf..4ce07ae62da 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -413,14 +413,12 @@ 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;
- client->flags = I2C_CLIENT_ALLOW_USE;
if ((client->addr == I2C_ADV7170 >> 1) ||
(client->addr == (I2C_ADV7170 >> 1) + 1)) {
dname = adv7170_name;
@@ -434,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;
@@ -498,11 +495,11 @@ adv7170_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_adv7170 = {
- .owner = THIS_MODULE,
- .name = "adv7170", /* name */
+ .driver = {
+ .name = "adv7170", /* name */
+ },
.id = I2C_DRIVERID_ADV7170,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adv7170_attach_adapter,
.detach_client = adv7170_detach_client,
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 173bca1e029..4e218f22b21 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -463,14 +463,12 @@ 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;
- client->flags = I2C_CLIENT_ALLOW_USE;
if ((client->addr == I2C_ADV7175 >> 1) ||
(client->addr == (I2C_ADV7175 >> 1) + 1)) {
dname = adv7175_name;
@@ -484,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;
@@ -548,11 +545,11 @@ adv7175_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_adv7175 = {
- .owner = THIS_MODULE,
- .name = "adv7175", /* name */
+ .driver = {
+ .name = "adv7175", /* name */
+ },
.id = I2C_DRIVERID_ADV7175,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adv7175_attach_adapter,
.detach_client = adv7175_detach_client,
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 881cdcb1875..7d5a068353f 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -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 3ee0afca76a..d6447791d0e 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -528,22 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
- 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;
@@ -623,11 +619,11 @@ bt819_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_bt819 = {
- .owner = THIS_MODULE,
- .name = "bt819",
+ .driver = {
+ .name = "bt819",
+ },
.id = I2C_DRIVERID_BT819,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = bt819_attach_adapter,
.detach_client = bt819_detach_client,
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index 3ca1d768bfd..07c78f1f7a4 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 = 0; /* 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;
@@ -230,10 +229,10 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c bt832 driver",
- .id = -1, /* FIXME */
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "bt832",
+ },
+ .id = 0, /* FIXME */
.attach_adapter = bt832_probe,
.detach_client = bt832_detach,
.command = bt832_command,
@@ -241,7 +240,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "bt832",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 8eb871d0e85..909b593530e 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -316,22 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
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);
@@ -405,11 +402,11 @@ bt856_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_bt856 = {
- .owner = THIS_MODULE,
- .name = "bt856",
+ .driver = {
+ .name = "bt856",
+ },
.id = I2C_DRIVERID_BT856,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = bt856_attach_adapter,
.detach_client = bt856_detach_client,
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 012be639aa1..65323e78d5f 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);
@@ -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 1ddf9ba613e..0e697034678 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -34,13 +34,14 @@
#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"
@@ -210,6 +211,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 +230,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 +247,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 +264,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 +281,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 +298,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 +315,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 +336,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);
@@ -1510,14 +1521,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) {
@@ -2206,22 +2209,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 +2560,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 +3110,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,
@@ -3229,6 +3220,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 +3693,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 +3730,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) {
@@ -3946,7 +3938,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 +4056,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 +4095,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 +4245,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 616a5b7e510..d64accc17b0 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -64,10 +64,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 +112,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 77619eb131f..748d630c7fe 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;
@@ -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,
@@ -300,7 +297,7 @@ static int attach_inform(struct i2c_client *client)
if (bttv_debug)
printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n",
- btv->c.nr,client->driver->name,client->addr,
+ btv->c.nr, client->driver->driver.name, client->addr,
client->name);
if (!client->driver->command)
return 0;
@@ -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 de1385e5d05..221b36e7f39 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 f4f58c60f15..72afdd64b88 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 93298f06e01..e370d74f2a1 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;
@@ -335,7 +366,6 @@ struct bttv_sub_driver {
struct device_driver drv;
char wanted[BUS_ID_SIZE];
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 +393,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 1e6a5632c3c..dd00c20ab95 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -73,6 +73,8 @@
#define UNSET (-1U)
+#define clamp(x, low, high) min (max (low, x), high)
+
/* ---------------------------------------------------------- */
struct bttv_tvnorm {
@@ -88,6 +90,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 +214,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 +274,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,7 +305,7 @@ struct bttv {
/* infrared remote */
int has_remote;
- struct bttv_input *remote;
+ struct bttv_ir *remote;
/* locking */
spinlock_t s_lock;
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 0065d0c240d..6bad93ef969 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 75442ec49f3..9976db4f6da 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 00000000000..297c32ab51e
--- /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 b7ec9bf4508..9f59541155d 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 ddf184f95d8..74cff626e04 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -170,16 +170,9 @@ static size_t cpia_read_nibble (struct parport *port,
/* Does the error line indicate end of data? */
if (((i /*& 1*/) == 0) &&
(parport_read_status(port) & PARPORT_STATUS_ERROR)) {
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
- DBG("%s: No more nibble data (%d bytes)\n",
- port->name, i/2);
-
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- break;
+ DBG("%s: No more nibble data (%d bytes)\n",
+ port->name, i/2);
+ goto end_of_data;
}
/* Event 7: Set nAutoFd low. */
@@ -227,18 +220,21 @@ static size_t cpia_read_nibble (struct parport *port,
byte = nibble;
}
- i /= 2; /* i is now in bytes */
-
if (i == len) {
/* Read the last nibble without checking data avail. */
- port = port->physport;
- if (parport_read_status (port) & PARPORT_STATUS_ERROR)
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+ end_of_data:
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ }
else
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
- return i;
+ return i/2;
}
/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
@@ -706,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 1439cb75287..03275c37c5d 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 780b352ec11..8739c64785e 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,20 +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->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define cs53l32a_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define cs53l32a_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
@@ -73,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;
}
@@ -146,23 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
- cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+ 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;
}
@@ -216,13 +205,13 @@ static int cs53l32a_detach(struct i2c_client *client)
/* i2c implementation */
static struct i2c_driver i2c_driver = {
- .name = "cs53l32a",
+ .driver = {
+ .name = "cs53l32a",
+ },
.id = I2C_DRIVERID_CS53L32A,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = cs53l32a_probe,
.detach_client = cs53l32a_detach,
.command = cs53l32a_command,
- .owner = THIS_MODULE,
};
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 740908f8027..cb9a7981e40 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 5b93723a176..1d75a42629d 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -45,9 +45,9 @@ static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
int cx25840_debug = 0;
-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,18 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "cx25840");
- cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1);
+ 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);
@@ -784,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);
@@ -802,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);
@@ -816,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;
}
@@ -844,15 +935,13 @@ static int cx25840_detach_client(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_cx25840 = {
- .name = "cx25840",
-
+ .driver = {
+ .name = "cx25840",
+ },
.id = I2C_DRIVERID_CX25840,
- .flags = I2C_DF_NOTIFY,
-
.attach_adapter = cx25840_attach_adapter,
.detach_client = cx25840_detach_client,
.command = cx25840_command,
- .owner = THIS_MODULE,
};
@@ -893,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) {
@@ -912,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;
@@ -938,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) {
@@ -963,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) {
@@ -980,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;
@@ -996,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;
@@ -1032,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) {
@@ -1041,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;
@@ -1051,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 df9d50a7554..e1a7823d82c 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 13ba4e15dde..04d879da7d6 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 4932ed1c9b1..fd22f30dcc1 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840.h
@@ -24,47 +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->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define cx25840_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define cx25840_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- 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;
};
/* ----------------------------------------------------------------------- */
@@ -83,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 85ba4106dc7..76fcb4e995c 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -29,6 +29,21 @@ 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
+ select SND_PCM_OSS
+ ---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 +53,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 +105,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 54401b02b7c..e4b2134fe56 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -4,7 +4,7 @@ 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
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -16,5 +16,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 00000000000..7695b521eb3
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -0,0 +1,848 @@
+/*
+ *
+ * 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 = 0;
+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 = 256,
+ .period_bytes_max = 2048,
+ .periods_min = 2,
+ .periods_max = 16,
+};
+
+/*
+ * 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=0;
+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,
+ SND_PCI_PM_CALLBACKS
+};
+
+/****************************************************************************
+ 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 74e57a53116..a502a4d6e4a 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 951709aa88b..ad2f565f522 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 bb6eb54e19c..194446f28c5 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -34,6 +34,7 @@
#include <linux/videodev2.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]");
@@ -76,60 +77,6 @@ static unsigned int cx88_devcount;
static LIST_HEAD(cx88_devlist);
static DECLARE_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 +238,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 +306,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 +318,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 +329,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 +795,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;
}
@@ -1104,11 +1050,10 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
up(&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);
@@ -1208,7 +1153,6 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
/* ------------------------------------------------------------------ */
-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 99ea955f598..e48aa3f6e50 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 9790d412f19..f720901e963 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);
@@ -94,7 +95,7 @@ static int attach_inform(struct i2c_client *client)
struct cx88_core *core = i2c_get_adapdata(client->adapter);
dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->name, client->addr, client->name);
+ client->driver->driver.name, client->addr, client->name);
if (!client->driver->command)
return 0;
@@ -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 461019dca90..da2ad5c4b55 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 35e6d0c2b87..c79cc1d2bf8 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 a1b120c8a9b..24118e43e73 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -132,14 +132,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 */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 24a48f8a48c..073494ceab0 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 00000000000..372cd29cedb
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -0,0 +1,173 @@
+/*
+
+ 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"
+
+
+/* ----------------------------------------------------------------------- */
+
+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 00000000000..b7a0a04d242
--- /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 77beafc5c32..e9fd55b57fa 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 da9481198c5..2831bdd1205 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 57779e63f35..58f7b4194a0 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 0cfe75416ec..dff3893f32f 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 7f5603054f0..0591a705b7a 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,
@@ -497,7 +496,6 @@ static struct i2c_adapter em28xx_adap_template = {
static struct i2c_client em28xx_client_template = {
.name = "em28xx internal",
- .flags = I2C_CLIENT_ALLOW_USE,
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 3a56120397a..3323dffe26a 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -32,6 +32,7 @@
#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 +107,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 +160,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,7 +186,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
.step = 0x1,
.default_value = 0x20,
.flags = 0,
- }
+ }
};
static struct usb_driver em28xx_usb_driver;
@@ -280,6 +287,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);
@@ -674,7 +683,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 +690,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 +749,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 +1021,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 +1056,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 +1269,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 +1646,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 +1861,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 +1931,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 5c7a41ce69f..33de9d846af 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 c9b00eafefd..e7bbeb11553 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 42a9414155c..0b6c2096ec6 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 deeef125eb9..7420b79e987 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;
@@ -451,10 +448,10 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd,
}
static struct i2c_driver i2c_driver_indycam = {
- .owner = THIS_MODULE,
- .name = "indycam",
+ .driver = {
+ .name = "indycam",
+ },
.id = I2C_DRIVERID_INDYCAM,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = indycam_probe,
.detach_client = indycam_detach,
.command = indycam_command,
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 740e543311a..58b0e698282 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -278,9 +278,10 @@ static int ir_detach(struct i2c_client *client);
static int ir_probe(struct i2c_adapter *adap);
static struct i2c_driver driver = {
- .name = "ir remote kbd driver",
+ .driver = {
+ .name = "ir-kbd-i2c",
+ },
.id = I2C_DRIVERID_INFRARED,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ir_probe,
.detach_client = ir_detach,
};
@@ -303,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";
@@ -377,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 3f2a882bc20..2869464aee0 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 00000000000..9b05a0ab776
--- /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 = 0; /* msp_debug output */
+int msp_once = 0; /* no continous stereo monitoring */
+int msp_amsound = 0; /* 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 = 0;
+
+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:
+ /* 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);
+
+ 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 00000000000..2072c3efebb
--- /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 d86f8e92e53..00000000000
--- 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->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->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->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define msp3400_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define msp3400_warn(fmt, arg...) do { \
- printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define msp3400_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- 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 = {
- .owner = THIS_MODULE,
- .name = "msp3400",
- .id = I2C_DRIVERID_MSP3400,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = msp_probe,
- .detach_client = msp_detach,
- .command = msp_command,
- .driver = {
- .suspend = msp_suspend,
- .resume = msp_resume,
- },
-};
-
-static struct i2c_client client_template =
-{
- .name = "(unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
- .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 2d9ff40f0b0..70a5ef8ba01 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -6,22 +6,28 @@
/* ---------------------------------------------------------------------- */
-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)
-
/* ioctl for MSP_SET_MATRIX will have to be registered */
#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
+/* 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
+
#define SCART_MASK 0
#define SCART_IN1 1
#define SCART_IN2 2
@@ -36,4 +42,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 2180018f06d..0bf1caac588 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
@@ -494,6 +497,13 @@ int microtune_init(struct i2c_client *c)
t->tv_freq = NULL;
t->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 d04793fb80f..8416ceff524 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 b3f4d266ced..c04130dab12 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 6eab458ab79..73b94f51a85 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 29bbdc05e3b..11f6be924d8 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 6c383d4b14f..5206e791392 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 3c8c48f338b..8e26ae338f3 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 2de34ebf067..e76b53d5909 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);
@@ -410,11 +409,11 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "ovcamchip",
+ .driver = {
+ .name = "ovcamchip",
+ },
.id = I2C_DRIVERID_OVCAMCHIP,
.class = I2C_CLASS_CAM_DIGITAL,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ovcamchip_attach,
.detach_client = ovcamchip_detach,
.command = ovcamchip_command,
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 2504207b2e3..9e644863948 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 b8054da31ff..2ce01020130 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);
@@ -151,25 +150,18 @@ static int saa5246a_detach(struct i2c_client *client)
return 0;
}
-static int saa5246a_command(struct i2c_client *device, unsigned int cmd,
- void *arg)
-{
- return -EINVAL;
-}
-
/*
* I2C interfaces
*/
static struct i2c_driver i2c_driver_videotext =
{
- .owner = THIS_MODULE,
- .name = IF_NAME, /* name */
+ .driver = {
+ .name = IF_NAME, /* name */
+ },
.id = I2C_DRIVERID_SAA5249, /* in i2c.h */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa5246a_probe,
.detach_client = saa5246a_detach,
- .command = saa5246a_command
};
static struct i2c_client client_template = {
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 7ffa2e9a9bf..5694eb58c3a 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);
@@ -226,23 +225,16 @@ static int saa5249_detach(struct i2c_client *client)
return 0;
}
-static int saa5249_command(struct i2c_client *device,
- unsigned int cmd, void *arg)
-{
- return -EINVAL;
-}
-
/* new I2C driver support */
static struct i2c_driver i2c_driver_videotext =
{
- .owner = THIS_MODULE,
- .name = IF_NAME, /* name */
+ .driver = {
+ .name = IF_NAME, /* name */
+ },
.id = I2C_DRIVERID_SAA5249, /* in i2c.h */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa5249_probe,
.detach_client = saa5249_detach,
- .command = saa5249_command
};
static struct i2c_client client_template = {
@@ -709,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 923322503e8..e70b17ef36e 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -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;
}
@@ -495,10 +485,10 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd,
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c saa6588 driver",
+ .driver = {
+ .name = "saa6588",
+ },
.id = -1, /* FIXME */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa6588_probe,
.detach_client = saa6588_detach,
.command = saa6588_command,
@@ -506,7 +496,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template = {
.name = "saa6588",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index e116bdbed31..7bb85a7b326 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -494,22 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
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;
@@ -587,11 +584,11 @@ saa7110_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7110 = {
- .owner = THIS_MODULE,
- .name = "saa7110",
+ .driver = {
+ .name = "saa7110",
+ },
.id = I2C_DRIVERID_SAA7110,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7110_attach_adapter,
.detach_client = saa7110_detach_client,
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index fe8a5e45396..8c06592b37f 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -511,22 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
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;
@@ -590,11 +587,11 @@ saa7111_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7111 = {
- .owner = THIS_MODULE,
- .name = "saa7111",
+ .driver = {
+ .name = "saa7111",
+ },
.id = I2C_DRIVERID_SAA7111A,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7111_attach_adapter,
.detach_client = saa7111_detach_client,
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index d9f50e2f7b9..fd0a4b4ef01 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -852,22 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
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;
@@ -1204,11 +1201,11 @@ saa7114_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7114 = {
- .owner = THIS_MODULE,
- .name = "saa7114",
+ .driver = {
+ .name = "saa7114",
+ },
.id = I2C_DRIVERID_SAA7114,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7114_attach_adapter,
.detach_client = saa7114_detach_client,
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index e717e30d818..048d000941c 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -39,30 +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->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define saa7115_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define saa7115_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
@@ -72,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;
};
/* ----------------------------------------------------------------------- */
@@ -468,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);
@@ -626,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;
}
@@ -671,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;
}
@@ -681,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;
}
@@ -691,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;
}
@@ -701,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;
@@ -742,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);
}
@@ -772,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;
}
@@ -800,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;
}
}
@@ -939,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))
@@ -965,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));
@@ -979,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);
}
}
@@ -991,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));
@@ -1005,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);
}
}
@@ -1088,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);
@@ -1102,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;
}
@@ -1126,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;
@@ -1147,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;
@@ -1164,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)) {
@@ -1178,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;
@@ -1263,48 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
- saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1);
+ 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;
}
@@ -1354,13 +1333,13 @@ static int saa7115_detach(struct i2c_client *client)
/* i2c implementation */
static struct i2c_driver i2c_driver_saa7115 = {
- .name = "saa7115",
+ .driver = {
+ .name = "saa7115",
+ },
.id = I2C_DRIVERID_SAA711X,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7115_probe,
.detach_client = saa7115_detach,
.command = saa7115_command,
- .owner = THIS_MODULE,
};
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 31f7b950b01..ae53063875f 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -487,21 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
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;
@@ -565,12 +562,10 @@ saa711x_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa711x = {
- .owner = THIS_MODULE,
- .name = "saa711x",
-
+ .driver = {
+ .name = "saa711x",
+ },
.id = I2C_DRIVERID_SAA711X,
- .flags = I2C_DF_NOTIFY,
-
.attach_adapter = saa711x_attach_adapter,
.detach_client = saa711x_detach_client,
.command = saa711x_command,
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index c36f014f1fd..992c71774f3 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -66,28 +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->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->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define saa7127_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define saa7127_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
@@ -334,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;
}
@@ -360,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;
}
@@ -372,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]);
@@ -395,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;
@@ -403,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;
@@ -421,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;
@@ -429,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;
@@ -446,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;
}
@@ -455,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;
}
@@ -467,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));
}
@@ -487,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;
}
@@ -542,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);
@@ -559,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;
@@ -631,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
@@ -711,18 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "saa7127");
- saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1);
+ 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.
@@ -731,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);
@@ -743,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);
@@ -768,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;
}
@@ -786,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;
}
@@ -819,13 +790,13 @@ static int saa7127_detach(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7127 = {
- .name = "saa7127",
+ .driver = {
+ .name = "saa7127",
+ },
.id = I2C_DRIVERID_SAA7127,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7127_probe,
.detach_client = saa7127_detach,
.command = saa7127_command,
- .owner = THIS_MODULE,
};
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 8a5c3e71b37..86671a43e76 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 a61d24f588f..0e0ba50946e 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;
}
@@ -597,10 +598,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c saa6752hs MPEG encoder",
+ .driver = {
+ .name = "saa6752hs",
+ },
.id = I2C_DRIVERID_SAA6752HS,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa6752hs_probe,
.detach_client = saa6752hs_detach,
.command = saa6752hs_command,
@@ -609,7 +610,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "saa6752hs",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index ade05f75fdb..a7a6ab9298a 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 672fb205959..275d06af69d 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,
@@ -2555,6 +2556,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 +2959,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 +3072,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 +3172,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 23d8747338e..3983a6524ca 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -95,77 +95,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;
@@ -211,7 +140,7 @@ static int pending_call(struct notifier_block *self, unsigned long state,
return NOTIFY_DONE;
}
-static int pending_registered;
+static int pending_registered=0;
static struct notifier_block pending_notifier = {
.notifier_call = pending_call,
};
@@ -610,11 +539,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 +580,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 +670,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 +803,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;
@@ -1156,7 +1118,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 +1135,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 e016480c346..399f9952596 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 575f3e835f9..bd4c389d4c3 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 df9dd36721e..6162550c413 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>
/* ----------------------------------------------------------- */
@@ -333,7 +334,7 @@ static int attach_inform(struct i2c_client *client)
struct tuner_setup tun_setup;
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
- client->driver->name, client->addr, client->name);
+ client->driver->driver.name, client->addr, client->name);
/* Am I an i2c remote control? */
@@ -343,7 +344,7 @@ static int attach_inform(struct i2c_client *client)
{
struct IR_i2c *ir = i2c_get_clientdata(client);
d1printk("%s i2c IR detected (%s).\n",
- client->driver->name,ir->phys);
+ client->driver->driver.name, ir->phys);
saa7134_set_i2c_ir(dev,ir);
break;
}
@@ -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 ab75ca5ac35..82d28cbf289 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 8badd2a9cb2..7448e386a80 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-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 45c852df13e..e97426bc85d 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 add49db1ad4..e70eae8d29b 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 f305ec802ea..756963f01bb 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 132aa7943c1..3ed0edb870a 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -408,22 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
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);
@@ -487,11 +484,11 @@ saa7185_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7185 = {
- .owner = THIS_MODULE,
- .name = "saa7185", /* name */
+ .driver = {
+ .name = "saa7185", /* name */
+ },
.id = I2C_DRIVERID_SAA7185B,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7185_attach_adapter,
.detach_client = saa7185_detach_client,
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index cbca896e8cf..746cadb8f1c 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;
@@ -788,10 +785,10 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd,
}
static struct i2c_driver i2c_driver_saa7191 = {
- .owner = THIS_MODULE,
- .name = "saa7191",
+ .driver = {
+ .name = "saa7191",
+ },
.id = I2C_DRIVERID_SAA7191,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7191_probe,
.detach_client = saa7191_detach,
.command = saa7191_command
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index d4497dbae05..54fc33011ff 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 d32737dd214..fc3d5824eff 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,21 +481,16 @@ 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;
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c tda7432 driver",
+ .driver = {
+ .name = "tda7432",
+ },
.id = I2C_DRIVERID_TDA7432,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tda7432_probe,
.detach_client = tda7432_detach,
.command = tda7432_command,
@@ -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 61d94ddaff4..2498b76df42 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;
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 1794686612c..ed4c04119cc 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -34,7 +34,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
#define SWITCH 0x00
#define LEVEL_ADJUST 0x02
@@ -221,10 +221,10 @@ static int detach(struct i2c_client *client)
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tda9840",
+ .driver = {
+ .name = "tda9840",
+ },
.id = I2C_DRIVERID_TDA9840,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = attach,
.detach_client = detach,
.command = command,
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index a5e37dc91f3..ef98c498225 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;
}
@@ -372,10 +366,10 @@ static int tda9875_command(struct i2c_client *client,
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c tda9875 driver",
+ .driver = {
+ .name = "tda9875",
+ },
.id = I2C_DRIVERID_TDA9875,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tda9875_probe,
.detach_client = tda9875_detach,
.command = tda9875_command,
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 2f2414e90e8..5815649bdc7 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:
@@ -819,14 +876,12 @@ static int tda9887_resume(struct device * dev)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c tda9887 driver",
.id = -1, /* FIXME */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tda9887_probe,
.detach_client = tda9887_detach,
.command = tda9887_command,
.driver = {
+ .name = "tda9887",
.suspend = tda9887_suspend,
.resume = tda9887_resume,
},
@@ -834,7 +889,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "tda9887",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index a9375ef05de..921fe72f23d 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;
+
/*****************************************************************************/
/******************************
@@ -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)
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index ee3688348b6..bb35844e384 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -36,7 +36,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
#define TEA6415C_NUM_INPUTS 8
#define TEA6415C_NUM_OUTPUTS 6
@@ -190,10 +190,10 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tea6415c",
+ .driver = {
+ .name = "tea6415c",
+ },
.id = I2C_DRIVERID_TEA6415C,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = attach,
.detach_client = detach,
.command = command,
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 17975c19da5..4dcba5a4fff 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -36,7 +36,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END };
@@ -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));
@@ -167,10 +166,10 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tea6420",
+ .driver = {
+ .name = "tea6420",
+ },
.id = I2C_DRIVERID_TEA6420,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = attach,
.detach_client = detach,
.command = command,
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 79203595b9c..c4a78e7a5a5 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -175,10 +175,10 @@ tuner_probe(struct i2c_adapter *adap)
static struct i2c_driver
i2c_driver_tuner =
{
- .owner = THIS_MODULE,
- .name = "sab3036",
+ .driver = {
+ .name = "sab3036",
+ },
.id = I2C_DRIVERID_SAB3036,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tuner_probe,
.detach_client = tuner_detach,
.command = tuner_command
@@ -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 e58abdfcaab..f30ef79d795 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);
@@ -206,7 +214,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
set_freq(c, t->freq);
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
- c->adapter->name, c->driver->name, c->addr << 1, type,
+ c->adapter->name, c->driver->driver.name, c->addr << 1, type,
t->mode_mask);
}
@@ -249,11 +257,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 +288,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 +306,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 +341,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->freq / 16000;
+ freq_fraction = (t->freq % 16000) * 100 / 16000;
+ } else {
+ freq = t->freq / 16;
+ freq_fraction = (t->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 +410,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];
@@ -478,7 +550,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 --- */
@@ -501,18 +575,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
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;
- }
- break;
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
return 0;
@@ -523,9 +585,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
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
kernel pointer here... */
@@ -708,10 +767,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
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;
}
@@ -742,21 +799,18 @@ static int tuner_resume(struct device *dev)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tuner",
.id = I2C_DRIVERID_TUNER,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tuner_probe,
.detach_client = tuner_detach,
.command = tuner_command,
.driver = {
- .suspend = tuner_suspend,
- .resume = tuner_resume,
- },
+ .name = "tuner",
+ .suspend = tuner_suspend,
+ .resume = tuner_resume,
+ },
};
static struct i2c_client client_template = {
.name = "(tuner unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index e0c9fdb9914..e5fb7436583 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,24 +79,20 @@
#define TUNER_PLL_LOCKED 0x40
#define TUNER_STEREO_MK3 0x04
+#define TUNER_MAX_RANGES 3
+
/* ---------------------------------------------------------------------- */
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;
+
+ int count;
+ struct {
+ unsigned short thresh;
+ unsigned char cb;
+ } ranges[TUNER_MAX_RANGES];
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 */
};
/*
@@ -102,158 +102,696 @@ struct tunertype
*/
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},
+ [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL (4002 FH5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
+ .name = "Philips PAL_I (FI1246 and compatibles)",
+ .count = 3,
+ .ranges = {
+ { 16 * 140.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
+ .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 451.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
+ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
+ .count = 3,
+ .ranges = {
+ { 16 * 168.25 /*MHz*/, 0xa7, },
+ { 16 * 447.25 /*MHz*/, 0x97, },
+ { 16 * 999.99 , 0x37, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_ABSENT] = { /* Tuner Absent */
+ .name = "NoTuner",
+ .count = 1,
+ .ranges = {
+ { 0, 0x00, },
+ },
+ .config = 0x00,
+ },
+ [TUNER_PHILIPS_PAL] = { /* Philips PAL */
+ .name = "Philips PAL_BG (FI1216 and compatibles)",
+ .count = 3,
+ .ranges = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 447.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4032 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4062 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0x02, },
+ { 16 * 450.00 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4036 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
+ .name = "Alps HSBH1",
+ .count = 3,
+ .ranges = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 385.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
/* 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},
+ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
+ .name = "Alps TSBE1",
+ .count = 3,
+ .ranges = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 385.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
+ .name = "Alps TSBB5",
+ .count = 3,
+ .ranges = {
+ { 16 * 133.25 /*MHz*/, 0x01, },
+ { 16 * 351.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBE5",
+ .count = 3,
+ .ranges = {
+ { 16 * 133.25 /*MHz*/, 0x01, },
+ { 16 * 351.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBC5",
+ .count = 3,
+ .ranges = {
+ { 16 * 133.25 /*MHz*/, 0x01, },
+ { 16 * 351.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4006FH5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
+ .name = "Alps TSCH6",
+ .count = 3,
+ .ranges = {
+ { 16 * 137.25 /*MHz*/, 0x14, },
+ { 16 * 385.25 /*MHz*/, 0x12, },
+ { 16 * 999.99 , 0x11, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK (4016 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 456.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
+ .name = "Philips NTSC_M (MK2)",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4066 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto (4006 FN5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
/* 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},
+ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4039 FR5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
+ .name = "Temic PAL/SECAM multi (4046 FM5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
+ .name = "Philips PAL_DK (FI1256 and compatibles)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216ME)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I+FM (TAPC-I001D)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I (TAPC-I701D)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC+FM (TPI8NSR01F)",
+ .count = 3,
+ .ranges = {
+ { 16 * 210.00 /*MHz*/, 0xa0, },
+ { 16 * 497.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG+FM (TPI8PSB01D)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG (TPI8PSB11D)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
/* 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,
+ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto + FM (4009 FN5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
+ .name = "SHARP NTSC_JP (2U5JF5540)",
+ .count = 3,
+ .ranges = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 317.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
+ .name = "Samsung PAL TCPM9091PD27",
+ .count = 3,
+ .ranges = {
+ { 16 * 169 /*MHz*/, 0xa0, },
+ { 16 * 464 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_MT2032] = { /* Microtune PAL|NTSC */
+ .name = "MT20xx universal",
/* 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},
+ [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4106 FH5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4136 FY5)",
+ .count = 3,
+ .ranges = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
+ .name = "LG PAL (newer TAPC series)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
+ .count = 3,
+ .ranges = {
+ { 16 * 158.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (newer TAPC series)",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
/* 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},
+ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
+ .name = "HITACHI V7-J180AT",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
+ .name = "Philips PAL_MK (FI1216 MK)",
+ .count = 3,
+ .ranges = {
+ { 16 * 140.25 /*MHz*/, 0x01, },
+ { 16 * 463.25 /*MHz*/, 0xc2, },
+ { 16 * 999.99 , 0xcf, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
+ .name = "Philips 1236D ATSC/NTSC dual in",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
+ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
+ .name = "Microtune 4049 FM5",
+ .count = 3,
+ .ranges = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
+ .name = "Panasonic VP27s/ENGE4324D",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0xce,
+ },
+ [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TAPE series)",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TNF_8831BGFF] = { /* Philips PAL */
+ .name = "Tenna TNF 8831 BGFF)",
+ .count = 3,
+ .ranges = {
+ { 16 * 161.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
+ .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
+ .count = 3,
+ .ranges = {
+ { 16 * 162.00 /*MHz*/, 0xa2, },
+ { 16 * 457.00 /*MHz*/, 0x94, },
+ { 16 * 999.99 , 0x31, },
+ },
+ .config = 0x8e,
+ },
/* 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,
+ [TUNER_TCL_2002N] = { /* TCL NTSC */
+ .name = "TCL 2002N",
+ .count = 3,
+ .ranges = {
+ { 16 * 172.00 /*MHz*/, 0x01, },
+ { 16 * 448.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
+ .name = "Thomson DTT 7610 (ATSC/NTSC)",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0x39, },
+ { 16 * 454.00 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+ .name = "Philips FQ1286",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x41, },
+ { 16 * 454.00 /*MHz*/, 0x42, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
+ .name = "tda8290+75",
/* 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},
+ [TUNER_TCL_2002MB] = { /* TCL PAL */
+ .name = "TCL 2002MB",
+ .count = 3,
+ .ranges = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0xce,
+ },
+ [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0xce,
+ },
+ [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
+ .name = "Philips FQ1236A MK4",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-5533MF",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
/* 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,
+ [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson DTT 761X (ATSC/NTSC)",
+ .count = 3,
+ .ranges = {
+ { 16 * 145.25 /*MHz*/, 0x39, },
+ { 16 * 415.25 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TENA_9533_DI] = { /* Philips PAL */
+ .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_TEA5767] = { /* Philips RADIO */
+ .name = "Philips TEA5767HN FM 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 },
+ [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips FMD1216ME MK3 Hybrid Tuner",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x51, },
+ { 16 * 442.00 /*MHz*/, 0x52, },
+ { 16 * 999.99 , 0x54, },
+ },
+ .config = 0x86,
+ },
+ [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
+ .name = "LG TDVS-H062F/TUA6034",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0x01 },
+ { 16 * 455.00 /*MHz*/, 0x02 },
+ { 16 * 999.99 , 0x04 },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+ .name = "Ymec TVF66T5-B/DFF",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TALN mini series)",
+ .count = 3,
+ .ranges = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 373.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+ },
+ .config = 0x8e,
+ },
+ [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
+ .name = "Philips TD1316 Hybrid Tuner",
+ .count = 3,
+ .ranges = {
+ { 16 * 160.00 /*MHz*/, 0xa1, },
+ { 16 * 442.00 /*MHz*/, 0xa2, },
+ { 16 * 999.99 , 0xa4, },
+ },
+ .config = 0xc8,
+ },
+ [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+ .name = "Philips TUV1236D ATSC/NTSC dual in",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0xce,
+ },
+ [TUNER_TNF_5335MF] = { /* Philips NTSC */
+ .name = "Tena TNF 5335 MF",
+ .count = 3,
+ .ranges = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+ },
+ .config = 0x8e,
+ },
};
unsigned const int tuner_count = ARRAY_SIZE(tuners);
@@ -305,20 +843,19 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
u16 div;
struct tunertype *tun;
unsigned char buffer[4];
- int rc;
+ int rc, IFPCoff, i;
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");
+ for (i = 0; i < tun->count; i++) {
+ if (freq > tun->ranges[i].thresh)
+ continue;
+ break;
}
-
+ config = tun->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) {
@@ -420,7 +957,37 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
* frequency in case (wanted frequency < current frequency).
*/
- div=freq + tun->IFPCoff;
+ /* 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 (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
buffer[0] = tun->config;
buffer[1] = config;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 5b20e8177ca..6d03b9b05c6 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;
+
+ 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;
+ }
- chip->norm = vc->norm;
+ 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,17 +1738,16 @@ 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 = {
- .owner = THIS_MODULE,
- .name = "generic i2c audio driver",
+ .driver = {
+ .name = "tvaudio",
+ },
.id = I2C_DRIVERID_TVAUDIO,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = chip_probe,
.detach_client = chip_detach,
.command = chip_command,
@@ -1714,7 +1756,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "(unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 5ac235365dd..5e71a354e87 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
@@ -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,14 +742,12 @@ 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;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name), "tveeprom");
i2c_attach_client(client);
@@ -779,10 +775,10 @@ tveeprom_detach_client (struct i2c_client *client)
}
static struct i2c_driver i2c_driver_tveeprom = {
- .owner = THIS_MODULE,
- .name = "tveeprom",
+ .driver = {
+ .name = "tveeprom",
+ },
.id = I2C_DRIVERID_TVEEPROM,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tveeprom_attach_adapter,
.detach_client = tveeprom_detach_client,
.command = tveeprom_command,
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 8318bd1aad0..9e86caeb96a 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -227,17 +227,11 @@ static int tvmixer_release(struct inode *inode, struct file *file)
}
static struct i2c_driver driver = {
-#ifdef I2C_PEC
- .owner = THIS_MODULE,
-#endif
- .name = "tv card mixer driver",
+ .driver = {
+ .name = "tvmixer",
+ },
.id = I2C_DRIVERID_TVMIXER,
-#ifdef I2C_DF_DUMMY
- .flags = I2C_DF_DUMMY,
-#else
- .flags = I2C_DF_NOTIFY,
.detach_adapter = tvmixer_adapters,
-#endif
.attach_adapter = tvmixer_adapters,
.detach_client = tvmixer_clients,
};
@@ -269,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 97431e26d22..e86b522938f 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 {
@@ -94,12 +100,14 @@ static inline int tvp5150_read(struct i2c_client *c, unsigned char addr)
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];
+};
+
+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;
+}
- tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_1, 0x0c);
- tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_2, 0x54);
+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_write(c, 0x27, 0x20); /* ?????????? */
+ tvp5150_dbg(1,"Set video std register to %d.\n",fmt);
+ tvp5150_write(c, TVP5150_VIDEO_STD, fmt);
- tvp5150_write(c, TVP5150_VIDEO_STD, 0x0); /* Auto switch */
+ return 0;
+}
+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);
+
+ 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;
@@ -714,19 +1045,18 @@ static struct i2c_driver driver;
static struct i2c_client client_template = {
.name = "(unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
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);
@@ -739,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;
@@ -763,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;
}
@@ -801,12 +1134,10 @@ static int tvp5150_detach_client(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tvp5150",
-
- /* FIXME */
- .id = I2C_DRIVERID_SAA7110,
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "tvp5150",
+ },
+ .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 4134549d11a..474a29bc176 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 597b8db35a1..5dbd7c1b362 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,174 @@ 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(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 +374,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 9a6bf287e26..9ef477523d2 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 839db622040..8f271de57fd 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 6de5b0094b8..d5be2598714 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -52,10 +52,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 +65,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
@@ -338,13 +336,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 "
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 71b28e9e085..c8fd8238904 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 137b58f2c66..d0a1e72ea8c 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -621,17 +621,14 @@ 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;
- client->flags = I2C_CLIENT_ALLOW_USE;
/* Check for manufacture ID and part number */
if (kind < 0) {
@@ -676,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;
@@ -722,11 +718,11 @@ vpx3220_attach_adapter (struct i2c_adapter *adapter)
*/
static struct i2c_driver vpx3220_i2c_driver = {
- .owner = THIS_MODULE,
- .name = "vpx3220",
+ .driver = {
+ .name = "vpx3220",
+ },
.id = I2C_DRIVERID_VPX3220,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = vpx3220_attach_adapter,
.detach_client = vpx3220_detach_client,
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index c318ba32fba..b7b0afffd21 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 a6936ad74fc..8cb64f8a8a9 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->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define wm8775_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- 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,18 +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;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "wm8775");
- wm8775_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL);
if (state == NULL) {
@@ -207,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;
}
@@ -233,15 +233,13 @@ static int wm8775_detach(struct i2c_client *client)
/* i2c implementation */
static struct i2c_driver i2c_driver = {
- .name = "wm8775",
-
- .id = I2C_DRIVERID_WM8775,
- .flags = I2C_DF_NOTIFY,
-
+ .driver = {
+ .name = "wm8775",
+ },
+ .id = I2C_DRIVERID_WM8775,
.attach_adapter = wm8775_probe,
- .detach_client = wm8775_detach,
- .command = wm8775_command,
- .owner = THIS_MODULE,
+ .detach_client = wm8775_detach,
+ .command = wm8775_command,
};
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 39a0d238900..ea3288661a3 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -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,
@@ -1061,7 +1061,6 @@ zr36057_init (struct zoran *zr)
kfree((void *)mem);
return -ENOMEM;
}
- memset((void *) mem, 0, mem_needed);
zr->stat_com = (u32 *) 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 07bde9acd67..485553be190 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -1311,7 +1311,7 @@ zoran_open (struct inode *inode,
res = -ENODEV;
goto open_unlock_and_return;
}
- if (!try_module_get(zr->decoder->driver->owner)) {
+ if (!try_module_get(zr->decoder->driver->driver.owner)) {
dprintk(1,
KERN_ERR
"%s: failed to grab ownership of i2c decoder\n",
@@ -1321,13 +1321,13 @@ zoran_open (struct inode *inode,
goto open_unlock_and_return;
}
if (zr->encoder &&
- !try_module_get(zr->encoder->driver->owner)) {
+ !try_module_get(zr->encoder->driver->driver.owner)) {
dprintk(1,
KERN_ERR
"%s: failed to grab ownership of i2c encoder\n",
ZR_DEVNAME(zr));
res = -EIO;
- module_put(zr->decoder->driver->owner);
+ module_put(zr->decoder->driver->driver.owner);
module_put(THIS_MODULE);
goto open_unlock_and_return;
}
@@ -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 =
@@ -1393,9 +1392,9 @@ zoran_open (struct inode *inode,
open_unlock_and_return:
/* if we grabbed locks, release them accordingly */
if (have_module_locks) {
- module_put(zr->decoder->driver->owner);
+ module_put(zr->decoder->driver->driver.owner);
if (zr->encoder) {
- module_put(zr->encoder->driver->owner);
+ module_put(zr->encoder->driver->driver.owner);
}
module_put(THIS_MODULE);
}
@@ -1461,9 +1460,9 @@ zoran_close (struct inode *inode,
kfree(fh);
/* release locks on the i2c modules */
- module_put(zr->decoder->driver->owner);
+ module_put(zr->decoder->driver->driver.owner);
if (zr->encoder) {
- module_put(zr->encoder->driver->owner);
+ module_put(zr->encoder->driver->driver.owner);
}
module_put(THIS_MODULE);
@@ -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 4ed898585c7..10130ef67ea 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 0144576a612..bd0cd28543c 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 129744a07ab..28fa31a5f15 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 07286816d7d..d4c633b8a7f 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/mptctl.c b/drivers/message/fusion/mptctl.c
index 959d2c5951b..7c340240a50 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -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)
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 43a942a29c2..fef67710388 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -24,6 +24,18 @@ config I2O
If unsure, say N.
+config I2O_LCT_NOTIFY_ON_CHANGES
+ bool "Enable LCT notification"
+ depends on I2O
+ default y
+ ---help---
+ Only say N here if you have a I2O controller from SUN. The SUN
+ firmware doesn't support LCT notification on changes. If this option
+ is enabled on such a controller the driver will hang up in a endless
+ loop. On all other controllers say Y.
+
+ If unsure, say Y.
+
config I2O_EXT_ADAPTEC
bool "Enable Adaptec extensions"
depends on I2O
diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl
index 73dd084c0e9..65c0c47aeb7 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/bus-osm.c b/drivers/message/i2o/bus-osm.c
index 151b228e1cb..ac06f10c54e 100644
--- a/drivers/message/i2o/bus-osm.c
+++ b/drivers/message/i2o/bus-osm.c
@@ -17,7 +17,7 @@
#include <linux/i2o.h>
#define OSM_NAME "bus-osm"
-#define OSM_VERSION "$Rev$"
+#define OSM_VERSION "1.317"
#define OSM_DESCRIPTION "I2O Bus Adapter OSM"
static struct i2o_driver i2o_bus_driver;
@@ -39,18 +39,18 @@ static struct i2o_class_id i2o_bus_class_id[] = {
*/
static int i2o_bus_scan(struct i2o_device *dev)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
return -ETIMEDOUT;
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.
+ tid);
- return i2o_msg_post_wait(dev->iop, m, 60);
+ return i2o_msg_post_wait(dev->iop, msg, 60);
};
/**
@@ -59,8 +59,9 @@ static int i2o_bus_scan(struct i2o_device *dev)
*
* Returns count.
*/
-static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf,
- size_t count)
+static ssize_t i2o_bus_store_scan(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2o_device *i2o_dev = to_i2o_device(d);
int rc;
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
index 10432f66520..3bba7aa82e5 100644
--- a/drivers/message/i2o/config-osm.c
+++ b/drivers/message/i2o/config-osm.c
@@ -22,7 +22,7 @@
#include <asm/uaccess.h>
#define OSM_NAME "config-osm"
-#define OSM_VERSION "1.248"
+#define OSM_VERSION "1.323"
#define OSM_DESCRIPTION "I2O Configuration OSM"
/* access mode user rw */
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 9eefedb1621..90628562851 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -14,8 +14,6 @@
*/
/* Exec-OSM */
-extern struct bus_type i2o_bus_type;
-
extern struct i2o_driver i2o_exec_driver;
extern int i2o_exec_lct_get(struct i2o_controller *);
@@ -23,6 +21,8 @@ extern int __init i2o_exec_init(void);
extern void __exit i2o_exec_exit(void);
/* driver */
+extern struct bus_type i2o_bus_type;
+
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
extern int __init i2o_driver_init(void);
@@ -33,19 +33,27 @@ extern int __init i2o_pci_init(void);
extern void __exit i2o_pci_exit(void);
/* device */
+extern struct device_attribute i2o_device_attrs[];
+
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
/* IOP */
extern struct i2o_controller *i2o_iop_alloc(void);
-extern void i2o_iop_free(struct i2o_controller *);
+
+/**
+ * i2o_iop_free - Free the i2o_controller struct
+ * @c: I2O controller to free
+ */
+static inline void i2o_iop_free(struct i2o_controller *c)
+{
+ i2o_pool_free(&c->in_msg);
+ kfree(c);
+}
extern int i2o_iop_add(struct i2o_controller *);
extern void i2o_iop_remove(struct i2o_controller *);
-/* config */
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
-
/* control registers relative to c->base */
#define I2O_IRQ_STATUS 0x30
#define I2O_IRQ_MASK 0x34
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 8eb50cdb8ae..ee183053fa2 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -35,18 +35,18 @@
static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
u32 type)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]);
- writel(type, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid);
+ msg->body[0] = cpu_to_le32(type);
- return i2o_msg_post_wait(dev->iop, m, 60);
+ return i2o_msg_post_wait(dev->iop, msg, 60);
}
/**
@@ -123,7 +123,6 @@ int i2o_device_claim_release(struct i2o_device *dev)
return rc;
}
-
/**
* i2o_device_release - release the memory for a I2O device
* @dev: I2O device which should be released
@@ -140,10 +139,10 @@ static void i2o_device_release(struct device *dev)
kfree(i2o_dev);
}
-
/**
- * i2o_device_class_show_class_id - Displays class id of I2O device
- * @cd: class device of which the class id should be displayed
+ * i2o_device_show_class_id - Displays class id of I2O device
+ * @dev: device of which the class id should be displayed
+ * @attr: pointer to device attribute
* @buf: buffer into which the class id should be printed
*
* Returns the number of bytes which are printed into the buffer.
@@ -159,15 +158,15 @@ static ssize_t i2o_device_show_class_id(struct device *dev,
}
/**
- * i2o_device_class_show_tid - Displays TID of I2O device
- * @cd: class device of which the TID should be displayed
- * @buf: buffer into which the class id should be printed
+ * i2o_device_show_tid - Displays TID of I2O device
+ * @dev: device of which the TID should be displayed
+ * @attr: pointer to device attribute
+ * @buf: buffer into which the TID should be printed
*
* Returns the number of bytes which are printed into the buffer.
*/
static ssize_t i2o_device_show_tid(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr, char *buf)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
@@ -175,6 +174,7 @@ static ssize_t i2o_device_show_tid(struct device *dev,
return strlen(buf) + 1;
}
+/* I2O device attributes */
struct device_attribute i2o_device_attrs[] = {
__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
@@ -193,12 +193,10 @@ static struct i2o_device *i2o_device_alloc(void)
{
struct i2o_device *dev;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
- memset(dev, 0, sizeof(*dev));
-
INIT_LIST_HEAD(&dev->list);
init_MUTEX(&dev->lock);
@@ -209,66 +207,6 @@ static struct i2o_device *i2o_device_alloc(void)
}
/**
- * i2o_setup_sysfs_links - Adds attributes to the I2O device
- * @cd: I2O class device which is added to the I2O device class
- *
- * This function get called when a I2O device is added to the class. It
- * creates the attributes for each device and creates user/parent symlink
- * if necessary.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev)
-{
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_device *tmp;
-
- /* create user entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && tmp != i2o_dev)
- sysfs_create_link(&i2o_dev->device.kobj,
- &tmp->device.kobj, "user");
-
- /* create user entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid &&
- tmp != i2o_dev)
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
-
- /* create parent entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && tmp != i2o_dev)
- sysfs_create_link(&i2o_dev->device.kobj,
- &tmp->device.kobj, "parent");
-
- /* create parent entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid &&
- tmp != i2o_dev)
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
-}
-
-static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
-{
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_device *tmp;
-
- sysfs_remove_link(&i2o_dev->device.kobj, "parent");
- sysfs_remove_link(&i2o_dev->device.kobj, "user");
-
- list_for_each_entry(tmp, &c->devices, list) {
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "parent");
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "user");
- }
-}
-
-
-
-/**
* i2o_device_add - allocate a new I2O device and add it to the IOP
* @iop: I2O controller where the device is on
* @entry: LCT entry of the I2O device
@@ -282,33 +220,57 @@ static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
static struct i2o_device *i2o_device_add(struct i2o_controller *c,
i2o_lct_entry * entry)
{
- struct i2o_device *dev;
+ struct i2o_device *i2o_dev, *tmp;
- dev = i2o_device_alloc();
- if (IS_ERR(dev)) {
+ i2o_dev = i2o_device_alloc();
+ if (IS_ERR(i2o_dev)) {
printk(KERN_ERR "i2o: unable to allocate i2o device\n");
- return dev;
+ return i2o_dev;
}
- dev->lct_data = *entry;
- dev->iop = c;
+ i2o_dev->lct_data = *entry;
- snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
- dev->lct_data.tid);
+ snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+ i2o_dev->lct_data.tid);
- dev->device.parent = &c->device;
+ i2o_dev->iop = c;
+ i2o_dev->device.parent = &c->device;
- device_register(&dev->device);
+ device_register(&i2o_dev->device);
- list_add_tail(&dev->list, &c->devices);
+ list_add_tail(&i2o_dev->list, &c->devices);
- i2o_setup_sysfs_links(dev);
+ /* create user entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+ if (tmp && (tmp != i2o_dev))
+ sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+ "user");
- i2o_driver_notify_device_add_all(dev);
+ /* create user entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ && (tmp != i2o_dev))
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
- pr_debug("i2o: device %s added\n", dev->device.bus_id);
+ /* create parent entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+ if (tmp && (tmp != i2o_dev))
+ sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+ "parent");
- return dev;
+ /* create parent entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ && (tmp != i2o_dev))
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+
+ i2o_driver_notify_device_add_all(i2o_dev);
+
+ pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id);
+
+ return i2o_dev;
}
/**
@@ -321,9 +283,22 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
*/
void i2o_device_remove(struct i2o_device *i2o_dev)
{
+ struct i2o_device *tmp;
+ struct i2o_controller *c = i2o_dev->iop;
+
i2o_driver_notify_device_remove_all(i2o_dev);
- i2o_remove_sysfs_links(i2o_dev);
+
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ }
list_del(&i2o_dev->list);
+
device_unregister(&i2o_dev->device);
}
@@ -341,56 +316,83 @@ int i2o_device_parse_lct(struct i2o_controller *c)
{
struct i2o_device *dev, *tmp;
i2o_lct *lct;
- int i;
- int max;
+ u32 *dlct = c->dlct.virt;
+ int max = 0, i = 0;
+ u16 table_size;
+ u32 buf;
down(&c->lct_lock);
kfree(c->lct);
- lct = c->dlct.virt;
+ buf = le32_to_cpu(*dlct++);
+ table_size = buf & 0xffff;
- c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL);
- if (!c->lct) {
+ lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
+ if (!lct) {
up(&c->lct_lock);
return -ENOMEM;
}
- if (lct->table_size * 4 > c->dlct.len) {
- memcpy(c->lct, c->dlct.virt, c->dlct.len);
- up(&c->lct_lock);
- return -EAGAIN;
- }
+ lct->lct_ver = buf >> 28;
+ lct->boot_tid = buf >> 16 & 0xfff;
+ lct->table_size = table_size;
+ lct->change_ind = le32_to_cpu(*dlct++);
+ lct->iop_flags = le32_to_cpu(*dlct++);
- memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
-
- lct = c->lct;
-
- max = (lct->table_size - 3) / 9;
+ table_size -= 3;
pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max,
lct->table_size);
- /* remove devices, which are not in the LCT anymore */
- list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+ while (table_size > 0) {
+ i2o_lct_entry *entry = &lct->lct_entry[max];
int found = 0;
- for (i = 0; i < max; i++) {
- if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+ buf = le32_to_cpu(*dlct++);
+ entry->entry_size = buf & 0xffff;
+ entry->tid = buf >> 16 & 0xfff;
+
+ entry->change_ind = le32_to_cpu(*dlct++);
+ entry->device_flags = le32_to_cpu(*dlct++);
+
+ buf = le32_to_cpu(*dlct++);
+ entry->class_id = buf & 0xfff;
+ entry->version = buf >> 12 & 0xf;
+ entry->vendor_id = buf >> 16;
+
+ entry->sub_class = le32_to_cpu(*dlct++);
+
+ buf = le32_to_cpu(*dlct++);
+ entry->user_tid = buf & 0xfff;
+ entry->parent_tid = buf >> 12 & 0xfff;
+ entry->bios_info = buf >> 24;
+
+ memcpy(&entry->identity_tag, dlct, 8);
+ dlct += 2;
+
+ entry->event_capabilities = le32_to_cpu(*dlct++);
+
+ /* add new devices, which are new in the LCT */
+ list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+ if (entry->tid == dev->lct_data.tid) {
found = 1;
break;
}
}
if (!found)
- i2o_device_remove(dev);
+ i2o_device_add(c, entry);
+
+ table_size -= 9;
+ max++;
}
- /* add new devices, which are new in the LCT */
- for (i = 0; i < max; i++) {
+ /* remove devices, which are not in the LCT anymore */
+ list_for_each_entry_safe(dev, tmp, &c->devices, list) {
int found = 0;
- list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+ for (i = 0; i < max; i++) {
if (lct->lct_entry[i].tid == dev->lct_data.tid) {
found = 1;
break;
@@ -398,14 +400,14 @@ int i2o_device_parse_lct(struct i2o_controller *c)
}
if (!found)
- i2o_device_add(c, &lct->lct_entry[i]);
+ i2o_device_remove(dev);
}
+
up(&c->lct_lock);
return 0;
}
-
/*
* Run time support routines
*/
@@ -419,13 +421,9 @@ int i2o_device_parse_lct(struct i2o_controller *c)
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
*/
int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
- int oplen, void *reslist, int reslen)
+ int oplen, void *reslist, int reslen)
{
- struct i2o_message __iomem *msg;
- u32 m;
- u32 *res32 = (u32 *) reslist;
- u32 *restmp = (u32 *) reslist;
- int len = 0;
+ struct i2o_message *msg;
int i = 0;
int rc;
struct i2o_dma res;
@@ -437,26 +435,27 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
return -ENOMEM;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY) {
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg)) {
i2o_dma_free(dev, &res);
- return -ETIMEDOUT;
+ return PTR_ERR(msg);
}
i = 0;
- writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid,
- &msg->u.head[1]);
- writel(0, &msg->body[i++]);
- writel(0x4C000000 | oplen, &msg->body[i++]); /* OperationList */
- memcpy_toio(&msg->body[i], oplist, oplen);
+ msg->u.head[1] =
+ cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid);
+ msg->body[i++] = cpu_to_le32(0x00000000);
+ msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */
+ memcpy(&msg->body[i], oplist, oplen);
i += (oplen / 4 + (oplen % 4 ? 1 : 0));
- writel(0xD0000000 | res.len, &msg->body[i++]); /* ResultList */
- writel(res.phys, &msg->body[i++]);
+ msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */
+ msg->body[i++] = cpu_to_le32(res.phys);
- writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
- SGL_OFFSET_5, &msg->u.head[0]);
+ msg->u.head[0] =
+ cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
+ SGL_OFFSET_5);
- rc = i2o_msg_post_wait_mem(c, m, 10, &res);
+ rc = i2o_msg_post_wait_mem(c, msg, 10, &res);
/* This only looks like a memory leak - don't "fix" it. */
if (rc == -ETIMEDOUT)
@@ -465,36 +464,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
memcpy(reslist, res.virt, res.len);
i2o_dma_free(dev, &res);
- /* Query failed */
- if (rc)
- return rc;
- /*
- * Calculate number of bytes of Result LIST
- * We need to loop through each Result BLOCK and grab the length
- */
- restmp = res32 + 1;
- len = 1;
- for (i = 0; i < (res32[0] & 0X0000FFFF); i++) {
- if (restmp[0] & 0x00FF0000) { /* BlockStatus != SUCCESS */
- printk(KERN_WARNING
- "%s - Error:\n ErrorInfoSize = 0x%02x, "
- "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
- (cmd ==
- I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" :
- "PARAMS_GET", res32[1] >> 24,
- (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF);
-
- /*
- * If this is the only request,than we return an error
- */
- if ((res32[0] & 0x0000FFFF) == 1) {
- return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */
- }
- }
- len += restmp[0] & 0x0000FFFF; /* Length of res BLOCK */
- restmp += restmp[0] & 0x0000FFFF; /* Skip to next BLOCK */
- }
- return (len << 2); /* bytes used by result list */
+ return rc;
}
/*
@@ -503,28 +473,25 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
void *buf, int buflen)
{
- u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
+ u32 opblk[] = { cpu_to_le32(0x00000001),
+ cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET),
+ cpu_to_le32((s16) field << 16 | 0x00000001)
+ };
u8 *resblk; /* 8 bytes for header */
- int size;
-
- if (field == -1) /* whole group */
- opblk[4] = -1;
+ int rc;
resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
if (!resblk)
return -ENOMEM;
- size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
- sizeof(opblk), resblk, buflen + 8);
+ rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+ sizeof(opblk), resblk, buflen + 8);
memcpy(buf, resblk + 8, buflen); /* cut off header */
kfree(resblk);
- if (size > buflen)
- return buflen;
-
- return size;
+ return rc;
}
/*
@@ -534,12 +501,12 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
* else return specific fields
* ibuf contains fieldindexes
*
- * if oper == I2O_PARAMS_LIST_GET, get from specific rows
- * if fieldcount == -1 return all fields
+ * if oper == I2O_PARAMS_LIST_GET, get from specific rows
+ * if fieldcount == -1 return all fields
* ibuf contains rowcount, keyvalues
- * else return specific fields
+ * else return specific fields
* fieldcount is # of fieldindexes
- * ibuf contains fieldindexes, rowcount, keyvalues
+ * ibuf contains fieldindexes, rowcount, keyvalues
*
* You could also use directly function i2o_issue_params().
*/
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 0fb9c4e2ad4..64130227574 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -61,12 +61,10 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)
};
/* I2O bus type */
-extern struct device_attribute i2o_device_attrs[];
-
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
- .dev_attrs = i2o_device_attrs,
+ .dev_attrs = i2o_device_attrs
};
/**
@@ -219,14 +217,14 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
/* cut of header from message size (in 32-bit words) */
size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
- evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
+ evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
if (!evt)
return -ENOMEM;
evt->size = size;
evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
evt->event_indicator = le32_to_cpu(msg->body[0]);
- memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
+ memcpy(&evt->data, &msg->body[1], size * 4);
list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
@@ -349,12 +347,10 @@ int __init i2o_driver_init(void)
osm_info("max drivers = %d\n", i2o_max_drivers);
i2o_drivers =
- kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+ kzalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
if (!i2o_drivers)
return -ENOMEM;
- memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
-
rc = bus_register(&i2o_bus_type);
if (rc < 0)
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 9c339a2505b..9bb9859f6df 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -33,7 +33,7 @@
#include <linux/workqueue.h>
#include <linux/string.h>
#include <linux/slab.h>
-#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */
+#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */
#include <asm/param.h> /* HZ */
#include "core.h"
@@ -75,11 +75,9 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
{
struct i2o_exec_wait *wait;
- wait = kmalloc(sizeof(*wait), GFP_KERNEL);
+ wait = kzalloc(sizeof(*wait), GFP_KERNEL);
if (!wait)
- return ERR_PTR(-ENOMEM);
-
- memset(wait, 0, sizeof(*wait));
+ return NULL;
INIT_LIST_HEAD(&wait->list);
@@ -114,13 +112,12 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
* Returns 0 on success, negative error code on timeout or positive error
* code from reply.
*/
-int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
- timeout, struct i2o_dma *dma)
+int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
+ unsigned long timeout, struct i2o_dma *dma)
{
DECLARE_WAIT_QUEUE_HEAD(wq);
struct i2o_exec_wait *wait;
static u32 tcntxt = 0x80000000;
- struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
int rc = 0;
wait = i2o_exec_wait_alloc();
@@ -138,15 +135,15 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
* We will only use transaction contexts >= 0x80000000 for POST WAIT,
* so we could find a POST WAIT reply easier in the reply handler.
*/
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
wait->tcntxt = tcntxt++;
- writel(wait->tcntxt, &msg->u.s.tcntxt);
+ msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
/*
* Post the message to the controller. At some point later it will
* return. If we time out before it returns then complete will be zero.
*/
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
if (!wait->complete) {
wait->wq = &wq;
@@ -266,13 +263,14 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
*
* Returns number of bytes printed into buffer.
*/
-static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t i2o_exec_show_vendor_id(struct device *d,
+ struct device_attribute *attr, char *buf)
{
struct i2o_device *dev = to_i2o_device(d);
u16 id;
- if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
- sprintf(buf, "0x%04x", id);
+ if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
+ sprintf(buf, "0x%04x", le16_to_cpu(id));
return strlen(buf) + 1;
}
@@ -286,13 +284,15 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute
*
* Returns number of bytes printed into buffer.
*/
-static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t i2o_exec_show_product_id(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
{
struct i2o_device *dev = to_i2o_device(d);
u16 id;
- if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
- sprintf(buf, "0x%04x", id);
+ if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
+ sprintf(buf, "0x%04x", le16_to_cpu(id));
return strlen(buf) + 1;
}
@@ -362,7 +362,9 @@ static void i2o_exec_lct_modified(struct i2o_controller *c)
if (i2o_device_parse_lct(c) != -EAGAIN)
change_ind = c->lct->change_ind + 1;
+#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES
i2o_exec_lct_notify(c, change_ind);
+#endif
};
/**
@@ -385,23 +387,22 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
u32 context;
if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
+ struct i2o_message __iomem *pmsg;
+ u32 pm;
+
/*
* If Fail bit is set we must take the transaction context of
* the preserved message to find the right request again.
*/
- struct i2o_message __iomem *pmsg;
- u32 pm;
pm = le32_to_cpu(msg->body[3]);
-
pmsg = i2o_msg_in_to_virt(c, pm);
+ context = readl(&pmsg->u.s.tcntxt);
i2o_report_status(KERN_INFO, "i2o_core", msg);
- context = readl(&pmsg->u.s.tcntxt);
-
/* Release the preserved msg */
- i2o_msg_nop(c, pm);
+ i2o_msg_nop_mfa(c, pm);
} else
context = le32_to_cpu(msg->u.s.tcntxt);
@@ -462,25 +463,26 @@ static void i2o_exec_event(struct i2o_event *evt)
*/
int i2o_exec_lct_get(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int i = 0;
int rc = -EAGAIN;
for (i = 1; i <= I2O_LCT_GET_TRIES; i++) {
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(0xffffffff, &msg->body[0]);
- writel(0x00000000, &msg->body[1]);
- writel(0xd0000000 | c->dlct.len, &msg->body[2]);
- writel(c->dlct.phys, &msg->body[3]);
-
- rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] =
+ cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->body[0] = cpu_to_le32(0xffffffff);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+ msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+ rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET);
if (rc < 0)
break;
@@ -506,29 +508,29 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
{
i2o_status_block *sb = c->status_block.virt;
struct device *dev;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
dev = &c->pdev->dev;
- if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL))
+ if (i2o_dma_realloc
+ (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
return -ENOMEM;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0, &msg->u.s.tcntxt); /* FIXME */
- writel(0xffffffff, &msg->body[0]);
- writel(change_ind, &msg->body[1]);
- writel(0xd0000000 | c->dlct.len, &msg->body[2]);
- writel(c->dlct.phys, &msg->body[3]);
-
- i2o_msg_post(c, m);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0xffffffff);
+ msg->body[1] = cpu_to_le32(change_ind);
+ msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+ msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+ i2o_msg_post(c, msg);
return 0;
};
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f283b5bafdd..b09fb630715 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -59,10 +59,12 @@
#include <linux/blkdev.h>
#include <linux/hdreg.h>
+#include <scsi/scsi.h>
+
#include "i2o_block.h"
#define OSM_NAME "block-osm"
-#define OSM_VERSION "1.287"
+#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O Block Device OSM"
static struct i2o_driver i2o_block_driver;
@@ -130,20 +132,20 @@ static int i2o_block_remove(struct device *dev)
*/
static int i2o_block_device_flush(struct i2o_device *dev)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(60 << 16, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(60 << 16);
osm_debug("Flushing...\n");
- return i2o_msg_post_wait(dev->iop, m, 60);
+ return i2o_msg_post_wait(dev->iop, msg, 60);
};
/**
@@ -181,21 +183,21 @@ static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,
*/
static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
{
- struct i2o_message __iomem *msg;
- u32 m;
-
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(-1, &msg->body[0]);
- writel(0, &msg->body[1]);
+ struct i2o_message *msg;
+
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(-1);
+ msg->body[1] = cpu_to_le32(0x00000000);
osm_debug("Mounting...\n");
- return i2o_msg_post_wait(dev->iop, m, 2);
+ return i2o_msg_post_wait(dev->iop, msg, 2);
};
/**
@@ -210,20 +212,20 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
*/
static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(-1, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(-1);
osm_debug("Locking...\n");
- return i2o_msg_post_wait(dev->iop, m, 2);
+ return i2o_msg_post_wait(dev->iop, msg, 2);
};
/**
@@ -238,20 +240,20 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
*/
static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(media_id, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(media_id);
osm_debug("Unlocking...\n");
- return i2o_msg_post_wait(dev->iop, m, 2);
+ return i2o_msg_post_wait(dev->iop, msg, 2);
};
/**
@@ -267,21 +269,21 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op)
{
struct i2o_device *i2o_dev = dev->i2o_dev;
struct i2o_controller *c = i2o_dev->iop;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int rc;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.
- tid, &msg->u.head[1]);
- writel(op << 24, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(op << 24);
osm_debug("Power...\n");
- rc = i2o_msg_post_wait(c, m, 60);
+ rc = i2o_msg_post_wait(c, msg, 60);
if (!rc)
dev->power = op;
@@ -331,7 +333,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)
*/
static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
struct i2o_block_request *ireq,
- u32 __iomem ** mptr)
+ u32 ** mptr)
{
int nents;
enum dma_data_direction direction;
@@ -466,7 +468,7 @@ static void i2o_block_end_request(struct request *req, int uptodate,
spin_lock_irqsave(q->queue_lock, flags);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
if (likely(dev)) {
dev->open_queue_depth--;
@@ -660,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
@@ -674,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 */
@@ -682,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:
@@ -745,10 +744,9 @@ static int i2o_block_transfer(struct request *req)
struct i2o_block_device *dev = req->rq_disk->private_data;
struct i2o_controller *c;
int tid = dev->i2o_dev->lct_data.tid;
- struct i2o_message __iomem *msg;
- u32 __iomem *mptr;
+ struct i2o_message *msg;
+ u32 *mptr;
struct i2o_block_request *ireq = req->special;
- u32 m;
u32 tcntxt;
u32 sgl_offset = SGL_OFFSET_8;
u32 ctl_flags = 0x00000000;
@@ -763,9 +761,9 @@ static int i2o_block_transfer(struct request *req)
c = dev->i2o_dev->iop;
- m = i2o_msg_get(c, &msg);
- if (m == I2O_QUEUE_EMPTY) {
- rc = -EBUSY;
+ msg = i2o_msg_get(c);
+ if (IS_ERR(msg)) {
+ rc = PTR_ERR(msg);
goto exit;
}
@@ -775,8 +773,8 @@ static int i2o_block_transfer(struct request *req)
goto nop_msg;
}
- writel(i2o_block_driver.context, &msg->u.s.icntxt);
- writel(tcntxt, &msg->u.s.tcntxt);
+ msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(tcntxt);
mptr = &msg->body[0];
@@ -834,11 +832,11 @@ static int i2o_block_transfer(struct request *req)
sgl_offset = SGL_OFFSET_12;
- writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
- &msg->u.head[1]);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid);
- writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
- writel(tid, mptr++);
+ *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
+ *mptr++ = cpu_to_le32(tid);
/*
* ENABLE_DISCONNECT
@@ -846,29 +844,31 @@ static int i2o_block_transfer(struct request *req)
* RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
*/
if (rq_data_dir(req) == READ) {
- cmd[0] = 0x28;
+ cmd[0] = READ_10;
scsi_flags = 0x60a0000a;
} else {
- cmd[0] = 0x2A;
+ cmd[0] = WRITE_10;
scsi_flags = 0xa0a0000a;
}
- writel(scsi_flags, mptr++);
+ *mptr++ = cpu_to_le32(scsi_flags);
*((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
*((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
- memcpy_toio(mptr, cmd, 10);
+ memcpy(mptr, cmd, 10);
mptr += 4;
- writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+ *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
} else
#endif
{
- writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
- writel(ctl_flags, mptr++);
- writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
- writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
- writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
+ msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
+ *mptr++ = cpu_to_le32(ctl_flags);
+ *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
+ *mptr++ =
+ cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT));
+ *mptr++ =
+ cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT));
}
if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
@@ -876,13 +876,13 @@ static int i2o_block_transfer(struct request *req)
goto context_remove;
}
- writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
- sgl_offset, &msg->u.head[0]);
+ msg->u.head[0] =
+ cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
list_add_tail(&ireq->queue, &dev->open_queue);
dev->open_queue_depth++;
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
@@ -890,7 +890,7 @@ static int i2o_block_transfer(struct request *req)
i2o_cntxt_list_remove(c, req);
nop_msg:
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
exit:
return rc;
@@ -959,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
};
@@ -978,13 +979,12 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
struct request_queue *queue;
int rc;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
osm_err("Insufficient memory to allocate I2O Block disk.\n");
rc = -ENOMEM;
goto exit;
}
- memset(dev, 0, sizeof(*dev));
INIT_LIST_HEAD(&dev->open_queue);
spin_lock_init(&dev->lock);
@@ -1049,8 +1049,8 @@ static int i2o_block_probe(struct device *dev)
int rc;
u64 size;
u32 blocksize;
- u32 flags, status;
u16 body_size = 4;
+ u16 power;
unsigned short max_sectors;
#ifdef CONFIG_I2O_EXT_ADAPTEC
@@ -1108,22 +1108,20 @@ static int i2o_block_probe(struct device *dev)
* Ask for the current media data. If that isn't supported
* then we ask for the device capacity data
*/
- if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
- i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
- blk_queue_hardsect_size(queue, blocksize);
+ if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
+ !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
+ blk_queue_hardsect_size(queue, le32_to_cpu(blocksize));
} else
osm_warn("unable to get blocksize of %s\n", gd->disk_name);
- if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
- i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
- set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
+ if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
+ !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
+ set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT);
} else
osm_warn("could not get size of %s\n", gd->disk_name);
- if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
- i2o_blk_dev->power = 0;
- i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
- i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
+ i2o_blk_dev->power = power;
i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 3c3a7abebb1..89daf67b764 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -36,12 +36,12 @@
#include <asm/uaccess.h>
-#include "core.h"
-
#define SG_TABLESIZE 30
-static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
- unsigned long arg);
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
+static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
static spinlock_t i2o_config_lock;
@@ -230,8 +230,7 @@ static int i2o_cfg_swdl(unsigned long arg)
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
unsigned char maxfrag = 0, curfrag = 1;
struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int status = 0, swlen = 0, fragsize = 8192;
struct i2o_controller *c;
@@ -257,31 +256,34 @@ static int i2o_cfg_swdl(unsigned long arg)
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
__copy_from_user(buffer.virt, kxfer.buf, fragsize);
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
- writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) |
- (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
- writel(0xD0000000 | fragsize, &msg->body[3]);
- writel(buffer.phys, &msg->body[4]);
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer.
+ sw_type) << 16) |
+ (((u32) maxfrag) << 8) | (((u32) curfrag)));
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
+ msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+ msg->body[4] = cpu_to_le32(buffer.phys);
osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+ status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
if (status != -ETIMEDOUT)
i2o_dma_free(&c->pdev->dev, &buffer);
@@ -302,8 +304,7 @@ static int i2o_cfg_swul(unsigned long arg)
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
unsigned char maxfrag = 0, curfrag = 1;
struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int status = 0, swlen = 0, fragsize = 8192;
struct i2o_controller *c;
int ret = 0;
@@ -330,30 +331,30 @@ static int i2o_cfg_swul(unsigned long arg)
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
- writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((u32) kxfer.flags << 24 | (u32) kxfer.
- sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag,
- &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
- writel(0xD0000000 | fragsize, &msg->body[3]);
- writel(buffer.phys, &msg->body[4]);
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.
+ sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag);
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
+ msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+ msg->body[4] = cpu_to_le32(buffer.phys);
osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+ status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
if (status != I2O_POST_WAIT_OK) {
if (status != -ETIMEDOUT)
@@ -380,8 +381,7 @@ static int i2o_cfg_swdel(unsigned long arg)
struct i2o_controller *c;
struct i2o_sw_xfer kxfer;
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int swlen;
int token;
@@ -395,21 +395,21 @@ static int i2o_cfg_swdel(unsigned long arg)
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16,
- &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
+ msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16);
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
- token = i2o_msg_post_wait(c, m, 10);
+ token = i2o_msg_post_wait(c, msg, 10);
if (token != I2O_POST_WAIT_OK) {
osm_info("swdel failed, DetailedStatus = %d\n", token);
@@ -423,25 +423,24 @@ static int i2o_cfg_validate(unsigned long arg)
{
int token;
int iop = (int)arg;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
struct i2o_controller *c;
c = i2o_find_iop(iop);
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
- token = i2o_msg_post_wait(c, m, 10);
+ token = i2o_msg_post_wait(c, msg, 10);
if (token != I2O_POST_WAIT_OK) {
osm_info("Can't validate configuration, ErrorStatus = %d\n",
@@ -454,8 +453,7 @@ static int i2o_cfg_validate(unsigned long arg)
static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
struct i2o_evt_id kdesc;
struct i2o_controller *c;
@@ -474,18 +472,19 @@ static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
if (!d)
return -ENODEV;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]);
- writel(kdesc.evt_mask, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 |
+ kdesc.tid);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data));
+ msg->body[0] = cpu_to_le32(kdesc.evt_mask);
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
}
@@ -537,7 +536,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
u32 sg_index = 0;
i2o_status_block *sb;
struct i2o_message *msg;
- u32 m;
unsigned int iop;
cmd = (struct i2o_cmd_passthru32 __user *)arg;
@@ -553,7 +551,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
return -ENXIO;
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
sb = c->status_block.virt;
@@ -585,19 +583,15 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
reply_size >>= 16;
reply_size <<= 2;
- reply = kmalloc(reply_size, GFP_KERNEL);
+ reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
return -ENOMEM;
}
- memset(reply, 0, reply_size);
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
- writel(i2o_config_driver.context, &msg->u.s.icntxt);
- writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
@@ -631,7 +625,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
goto cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
- p = &(sg_list[sg_index++]);
+ p = &(sg_list[sg_index]);
/* Allocate memory for the transfer */
if (i2o_dma_alloc
(&c->pdev->dev, p, sg_size,
@@ -642,6 +636,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
rcode = -ENOMEM;
goto sg_list_cleanup;
}
+ sg_index++;
/* Copy in the user's SG buffer if necessary */
if (sg[i].
flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
@@ -662,9 +657,11 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
- rcode = i2o_msg_post_wait(c, m, 60);
- if (rcode)
+ rcode = i2o_msg_post_wait(c, msg, 60);
+ if (rcode) {
+ reply[4] = ((u32) rcode) << 24;
goto sg_list_cleanup;
+ }
if (sg_offset) {
u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
@@ -714,6 +711,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
+ sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
@@ -731,7 +729,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
- sg_list_cleanup:
for (i = 0; i < sg_index; i++)
i2o_dma_free(&c->pdev->dev, &sg_list[i]);
@@ -780,8 +777,7 @@ static int i2o_cfg_passthru(unsigned long arg)
u32 i = 0;
void *p = NULL;
i2o_status_block *sb;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int iop;
if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
@@ -793,7 +789,7 @@ static int i2o_cfg_passthru(unsigned long arg)
return -ENXIO;
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
sb = c->status_block.virt;
@@ -820,19 +816,15 @@ static int i2o_cfg_passthru(unsigned long arg)
reply_size >>= 16;
reply_size <<= 2;
- reply = kmalloc(reply_size, GFP_KERNEL);
+ reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
return -ENOMEM;
}
- memset(reply, 0, reply_size);
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
- writel(i2o_config_driver.context, &msg->u.s.icntxt);
- writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
@@ -894,9 +886,11 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
- rcode = i2o_msg_post_wait(c, m, 60);
- if (rcode)
+ rcode = i2o_msg_post_wait(c, msg, 60);
+ if (rcode) {
+ reply[4] = ((u32) rcode) << 24;
goto sg_list_cleanup;
+ }
if (sg_offset) {
u32 msg[128];
@@ -946,6 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
+ sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
@@ -962,7 +957,6 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
- sg_list_cleanup:
for (i = 0; i < sg_index; i++)
kfree(sg_list[i]);
diff --git a/drivers/message/i2o/i2o_lan.h b/drivers/message/i2o/i2o_lan.h
index 561d63304d7..6502b817df5 100644
--- a/drivers/message/i2o/i2o_lan.h
+++ b/drivers/message/i2o/i2o_lan.h
@@ -103,14 +103,14 @@
#define I2O_LAN_DSC_SUSPENDED 0x11
struct i2o_packet_info {
- u32 offset : 24;
- u32 flags : 8;
- u32 len : 24;
- u32 status : 8;
+ u32 offset:24;
+ u32 flags:8;
+ u32 len:24;
+ u32 status:8;
};
struct i2o_bucket_descriptor {
- u32 context; /* FIXME: 64bit support */
+ u32 context; /* FIXME: 64bit support */
struct i2o_packet_info packet_info[1];
};
@@ -127,14 +127,14 @@ struct i2o_lan_local {
u8 unit;
struct i2o_device *i2o_dev;
- struct fddi_statistics stats; /* see also struct net_device_stats */
- unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
- atomic_t buckets_out; /* nbr of unused buckets on DDM */
- atomic_t tx_out; /* outstanding TXes */
- u8 tx_count; /* packets in one TX message frame */
- u16 tx_max_out; /* DDM's Tx queue len */
- u8 sgl_max; /* max SGLs in one message frame */
- u32 m; /* IOP address of the batch msg frame */
+ struct fddi_statistics stats; /* see also struct net_device_stats */
+ unsigned short (*type_trans) (struct sk_buff *, struct net_device *);
+ atomic_t buckets_out; /* nbr of unused buckets on DDM */
+ atomic_t tx_out; /* outstanding TXes */
+ u8 tx_count; /* packets in one TX message frame */
+ u16 tx_max_out; /* DDM's Tx queue len */
+ u8 sgl_max; /* max SGLs in one message frame */
+ u32 m; /* IOP address of the batch msg frame */
struct work_struct i2o_batch_send_task;
int send_active;
@@ -144,16 +144,16 @@ struct i2o_lan_local {
spinlock_t tx_lock;
- u32 max_size_mc_table; /* max number of multicast addresses */
+ u32 max_size_mc_table; /* max number of multicast addresses */
/* LAN OSM configurable parameters are here: */
- u16 max_buckets_out; /* max nbr of buckets to send to DDM */
- u16 bucket_thresh; /* send more when this many used */
+ u16 max_buckets_out; /* max nbr of buckets to send to DDM */
+ u16 bucket_thresh; /* send more when this many used */
u16 rx_copybreak;
- u8 tx_batch_mode; /* Set when using batch mode sends */
- u32 i2o_event_mask; /* To turn on interesting event flags */
+ u8 tx_batch_mode; /* Set when using batch mode sends */
+ u32 i2o_event_mask; /* To turn on interesting event flags */
};
-#endif /* _I2O_LAN_H */
+#endif /* _I2O_LAN_H */
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index d559a175836..2a0c42b8cda 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -28,7 +28,7 @@
*/
#define OSM_NAME "proc-osm"
-#define OSM_VERSION "1.145"
+#define OSM_VERSION "1.316"
#define OSM_DESCRIPTION "I2O ProcFS OSM"
#define I2O_MAX_MODULES 4
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 9f1744c3933..f9e5a23697a 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -70,7 +70,7 @@
#include <scsi/sg_request.h>
#define OSM_NAME "scsi-osm"
-#define OSM_VERSION "1.282"
+#define OSM_VERSION "1.316"
#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM"
static struct i2o_driver i2o_scsi_driver;
@@ -113,7 +113,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
list_for_each_entry(i2o_dev, &c->devices, list)
if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
- if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
&& (type == 0x01)) /* SCSI bus */
max_channel++;
}
@@ -146,7 +146,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
i = 0;
list_for_each_entry(i2o_dev, &c->devices, list)
if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
- if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
&& (type == 0x01)) /* only SCSI bus */
i2o_shost->channel[i++] = i2o_dev;
@@ -238,13 +238,15 @@ static int i2o_scsi_probe(struct device *dev)
u8 type;
struct i2o_device *d = i2o_shost->channel[0];
- if (i2o_parm_field_get(d, 0x0000, 0, &type, 1)
+ if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1)
&& (type == 0x01)) /* SCSI bus */
- if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
+ if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
channel = 0;
if (i2o_dev->lct_data.class_id ==
I2O_CLASS_RANDOM_BLOCK_STORAGE)
- lun = i2o_shost->lun++;
+ lun =
+ cpu_to_le64(i2o_shost->
+ lun++);
else
lun = 0;
}
@@ -253,10 +255,10 @@ static int i2o_scsi_probe(struct device *dev)
break;
case I2O_CLASS_SCSI_PERIPHERAL:
- if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0)
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4))
return -EFAULT;
- if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0)
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8))
return -EFAULT;
parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
@@ -281,20 +283,22 @@ static int i2o_scsi_probe(struct device *dev)
return -EFAULT;
}
- if (id >= scsi_host->max_id) {
- osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
- scsi_host->max_id);
+ if (le32_to_cpu(id) >= scsi_host->max_id) {
+ osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)",
+ le32_to_cpu(id), scsi_host->max_id);
return -EFAULT;
}
- if (lun >= scsi_host->max_lun) {
- osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
- (unsigned int)lun, scsi_host->max_lun);
+ if (le64_to_cpu(lun) >= scsi_host->max_lun) {
+ osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)",
+ (long unsigned int)le64_to_cpu(lun),
+ scsi_host->max_lun);
return -EFAULT;
}
scsi_dev =
- __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
+ __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id),
+ le64_to_cpu(lun), i2o_dev);
if (IS_ERR(scsi_dev)) {
osm_warn("can not add SCSI device %03x\n",
@@ -305,8 +309,9 @@ static int i2o_scsi_probe(struct device *dev)
sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
"scsi");
- osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
- i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+ osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n",
+ i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
+ (long unsigned int)le64_to_cpu(lun));
return 0;
};
@@ -510,8 +515,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
struct i2o_controller *c;
struct i2o_device *i2o_dev;
int tid;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
/*
* ENABLE_DISCONNECT
* SIMPLE_TAG
@@ -519,7 +523,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/
u32 scsi_flags = 0x20a00000;
u32 sgl_offset;
- u32 __iomem *mptr;
+ u32 *mptr;
u32 cmd = I2O_CMD_SCSI_EXEC << 24;
int rc = 0;
@@ -576,8 +580,8 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
* throw it back to the scsi layer
*/
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY) {
+ msg = i2o_msg_get(c);
+ if (IS_ERR(msg)) {
rc = SCSI_MLQUEUE_HOST_BUSY;
goto exit;
}
@@ -617,16 +621,16 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
if (sgl_offset == SGL_OFFSET_10)
sgl_offset = SGL_OFFSET_12;
cmd = I2O_CMD_PRIVATE << 24;
- writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
- writel(adpt_flags | tid, mptr++);
+ *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
+ *mptr++ = cpu_to_le32(adpt_flags | tid);
}
#endif
- writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
- writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
+ msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
+ msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context);
/* We want the SCSI control block back */
- writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt);
+ msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt));
/* LSI_920_PCI_QUIRK
*
@@ -649,15 +653,15 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
*/
- writel(scsi_flags | SCpnt->cmd_len, mptr++);
+ *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len);
/* Write SCSI command into the message - always 16 byte block */
- memcpy_toio(mptr, SCpnt->cmnd, 16);
+ memcpy(mptr, SCpnt->cmnd, 16);
mptr += 4;
if (sgl_offset != SGL_OFFSET_0) {
/* write size of data addressed by SGL */
- writel(SCpnt->request_bufflen, mptr++);
+ *mptr++ = cpu_to_le32(SCpnt->request_bufflen);
/* Now fill in the SGList and command */
if (SCpnt->use_sg) {
@@ -676,11 +680,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
/* Stick the headers on */
- writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,
- &msg->u.head[0]);
+ msg->u.head[0] =
+ cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
/* Queue the message */
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
osm_debug("Issued %ld\n", SCpnt->serial_number);
@@ -688,7 +692,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
nomem:
rc = -ENOMEM;
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
exit:
return rc;
@@ -709,8 +713,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
{
struct i2o_device *i2o_dev;
struct i2o_controller *c;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int tid;
int status = FAILED;
@@ -720,16 +723,16 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
c = i2o_dev->iop;
tid = i2o_dev->lct_data.tid;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
return SCSI_MLQUEUE_HOST_BUSY;
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid,
- &msg->u.head[1]);
- writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
+ msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
- if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT))
+ if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
status = SUCCESS;
return status;
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 4eb53258842..49216744693 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -32,7 +32,7 @@
#include "core.h"
#define OSM_NAME "i2o"
-#define OSM_VERSION "1.288"
+#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O subsystem"
/* global I2O controller list */
@@ -47,27 +47,6 @@ static struct i2o_dma i2o_systab;
static int i2o_hrt_get(struct i2o_controller *c);
/**
- * i2o_msg_nop - Returns a message which is not used
- * @c: I2O controller from which the message was created
- * @m: message which should be returned
- *
- * If you fetch a message via i2o_msg_get, and can't use it, you must
- * return the message with this function. Otherwise the message frame
- * is lost.
- */
-void i2o_msg_nop(struct i2o_controller *c, u32 m)
-{
- struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
-
- writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(0, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- i2o_msg_post(c, m);
-};
-
-/**
* i2o_msg_get_wait - obtain an I2O message from the IOP
* @c: I2O controller
* @msg: pointer to a I2O message pointer
@@ -81,22 +60,21 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m)
* address from the read port (see the i2o spec). If no message is
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/
-u32 i2o_msg_get_wait(struct i2o_controller *c,
- struct i2o_message __iomem ** msg, int wait)
+struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait)
{
unsigned long timeout = jiffies + wait * HZ;
- u32 m;
+ struct i2o_message *msg;
- while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
+ while (IS_ERR(msg = i2o_msg_get(c))) {
if (time_after(jiffies, timeout)) {
osm_debug("%s: Timeout waiting for message frame.\n",
c->name);
- return I2O_QUEUE_EMPTY;
+ return ERR_PTR(-ETIMEDOUT);
}
schedule_timeout_uninterruptible(1);
}
- return m;
+ return msg;
};
#if BITS_PER_LONG == 64
@@ -301,8 +279,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid)
*/
static int i2o_iop_quiesce(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
int rc;
@@ -313,16 +290,17 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
(sb->iop_state != ADAPTER_STATE_OPERATIONAL))
return 0;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
/* Long timeout needed for quiesce if lots of devices */
- if ((rc = i2o_msg_post_wait(c, m, 240)))
+ if ((rc = i2o_msg_post_wait(c, msg, 240)))
osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
else
osm_debug("%s: Quiesced.\n", c->name);
@@ -342,8 +320,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
*/
static int i2o_iop_enable(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
int rc;
@@ -353,16 +330,17 @@ static int i2o_iop_enable(struct i2o_controller *c)
if (sb->iop_state != ADAPTER_STATE_READY)
return -EINVAL;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
/* How long of a timeout do we need? */
- if ((rc = i2o_msg_post_wait(c, m, 240)))
+ if ((rc = i2o_msg_post_wait(c, msg, 240)))
osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
else
osm_debug("%s: Enabled.\n", c->name);
@@ -413,22 +391,22 @@ static inline void i2o_iop_enable_all(void)
*/
static int i2o_iop_clear(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int rc;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
- if ((rc = i2o_msg_post_wait(c, m, 30)))
+ if ((rc = i2o_msg_post_wait(c, msg, 30)))
osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
else
osm_debug("%s: Cleared.\n", c->name);
@@ -446,13 +424,13 @@ static int i2o_iop_clear(struct i2o_controller *c)
* Clear and (re)initialize IOP's outbound queue and post the message
* frames to the IOP.
*
- * Returns 0 on success or a negative errno code on failure.
+ * Returns 0 on success or negative error code on failure.
*/
static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
{
- volatile u8 *status = c->status.virt;
u32 m;
- struct i2o_message __iomem *msg;
+ volatile u8 *status = c->status.virt;
+ struct i2o_message *msg;
ulong timeout;
int i;
@@ -460,23 +438,24 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
memset(c->status.virt, 0, 4);
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0x00000000, &msg->u.s.tcntxt);
- writel(PAGE_SIZE, &msg->body[0]);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(PAGE_SIZE);
/* Outbound msg frame size in words and Initcode */
- writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
- writel(0xd0000004, &msg->body[2]);
- writel(i2o_dma_low(c->status.phys), &msg->body[3]);
- writel(i2o_dma_high(c->status.phys), &msg->body[4]);
+ msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80);
+ msg->body[2] = cpu_to_le32(0xd0000004);
+ msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys));
+ msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys));
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
while (*status <= I2O_CMD_IN_PROGRESS) {
@@ -511,34 +490,34 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
static int i2o_iop_reset(struct i2o_controller *c)
{
volatile u8 *status = c->status.virt;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned long timeout;
i2o_status_block *sb = c->status_block.virt;
int rc = 0;
osm_debug("%s: Resetting controller\n", c->name);
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
memset(c->status_block.virt, 0, 8);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context
- writel(0, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(i2o_dma_low(c->status.phys), &msg->body[2]);
- writel(i2o_dma_high(c->status.phys), &msg->body[3]);
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0x00000000);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys));
+ msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys));
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
/* Wait for a reply */
timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
@@ -567,18 +546,15 @@ static int i2o_iop_reset(struct i2o_controller *c)
osm_debug("%s: Reset in progress, waiting for reboot...\n",
c->name);
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
- while (m == I2O_QUEUE_EMPTY) {
+ while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) {
if (time_after(jiffies, timeout)) {
osm_err("%s: IOP reset timeout.\n", c->name);
- rc = -ETIMEDOUT;
+ rc = PTR_ERR(msg);
goto exit;
}
schedule_timeout_uninterruptible(1);
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
}
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
/* from here all quiesce commands are safe */
c->no_quiesce = 0;
@@ -686,8 +662,7 @@ static int i2o_iop_activate(struct i2o_controller *c)
*/
static int i2o_iop_systab_set(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
struct device *dev = &c->pdev->dev;
struct resource *root;
@@ -735,41 +710,38 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
}
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len,
PCI_DMA_TODEVICE);
if (!i2o_systab.phys) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
- writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
/*
* Provide three SGL-elements:
* System table (SysTab), Private memory space declaration and
* Private i/o space declaration
- *
- * FIXME: is this still true?
- * Nasty one here. We can't use dma_alloc_coherent to send the
- * same table to everyone. We have to go remap it for them all
*/
- writel(c->unit + 2, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(0x54000000 | i2o_systab.len, &msg->body[2]);
- writel(i2o_systab.phys, &msg->body[3]);
- writel(0x54000000 | sb->current_mem_size, &msg->body[4]);
- writel(sb->current_mem_base, &msg->body[5]);
- writel(0xd4000000 | sb->current_io_size, &msg->body[6]);
- writel(sb->current_io_base, &msg->body[6]);
+ msg->body[0] = cpu_to_le32(c->unit + 2);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len);
+ msg->body[3] = cpu_to_le32(i2o_systab.phys);
+ msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size);
+ msg->body[5] = cpu_to_le32(sb->current_mem_base);
+ msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size);
+ msg->body[6] = cpu_to_le32(sb->current_io_base);
- rc = i2o_msg_post_wait(c, m, 120);
+ rc = i2o_msg_post_wait(c, msg, 120);
dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len,
PCI_DMA_TODEVICE);
@@ -780,8 +752,6 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
else
osm_debug("%s: SysTab set.\n", c->name);
- i2o_status_get(c); // Entered READY state
-
return rc;
}
@@ -791,7 +761,7 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
*
* Send the system table and enable the I2O controller.
*
- * Returns 0 on success or negativer error code on failure.
+ * Returns 0 on success or negative error code on failure.
*/
static int i2o_iop_online(struct i2o_controller *c)
{
@@ -830,7 +800,6 @@ void i2o_iop_remove(struct i2o_controller *c)
list_for_each_entry_safe(dev, tmp, &c->devices, list)
i2o_device_remove(dev);
- class_device_unregister(c->classdev);
device_del(&c->device);
/* Ask the IOP to switch to RESET state */
@@ -869,12 +838,11 @@ static int i2o_systab_build(void)
i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *
sizeof(struct i2o_sys_tbl_entry);
- systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
+ systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL);
if (!systab) {
osm_err("unable to allocate memory for System Table\n");
return -ENOMEM;
}
- memset(systab, 0, i2o_systab.len);
systab->version = I2OVERSION;
systab->change_ind = change_ind + 1;
@@ -952,30 +920,30 @@ static int i2o_parse_hrt(struct i2o_controller *c)
*/
int i2o_status_get(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
volatile u8 *status_block;
unsigned long timeout;
status_block = (u8 *) c->status_block.virt;
memset(c->status_block.virt, 0, sizeof(i2o_status_block));
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context
- writel(0, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(i2o_dma_low(c->status_block.phys), &msg->body[2]);
- writel(i2o_dma_high(c->status_block.phys), &msg->body[3]);
- writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0x00000000);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys));
+ msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys));
+ msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
/* Wait for a reply */
timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
@@ -1002,7 +970,7 @@ int i2o_status_get(struct i2o_controller *c)
* The HRT contains information about possible hidden devices but is
* mostly useless to us.
*
- * Returns 0 on success or negativer error code on failure.
+ * Returns 0 on success or negative error code on failure.
*/
static int i2o_hrt_get(struct i2o_controller *c)
{
@@ -1013,20 +981,20 @@ static int i2o_hrt_get(struct i2o_controller *c)
struct device *dev = &c->pdev->dev;
for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]);
- writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(0xd0000000 | c->hrt.len, &msg->body[0]);
- writel(c->hrt.phys, &msg->body[1]);
+ msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len);
+ msg->body[1] = cpu_to_le32(c->hrt.phys);
- rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
+ rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt);
if (rc < 0) {
osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
@@ -1051,15 +1019,6 @@ static int i2o_hrt_get(struct i2o_controller *c)
}
/**
- * i2o_iop_free - Free the i2o_controller struct
- * @c: I2O controller to free
- */
-void i2o_iop_free(struct i2o_controller *c)
-{
- kfree(c);
-};
-
-/**
* i2o_iop_release - release the memory for a I2O controller
* @dev: I2O controller which should be released
*
@@ -1073,14 +1032,11 @@ static void i2o_iop_release(struct device *dev)
i2o_iop_free(c);
};
-/* I2O controller class */
-static struct class *i2o_controller_class;
-
/**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
*
* Allocate the necessary memory for a i2o_controller struct and
- * initialize the lists.
+ * initialize the lists and message mempool.
*
* Returns a pointer to the I2O controller or a negative error code on
* failure.
@@ -1089,20 +1045,29 @@ struct i2o_controller *i2o_iop_alloc(void)
{
static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */
struct i2o_controller *c;
+ char poolname[32];
- c = kmalloc(sizeof(*c), GFP_KERNEL);
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c) {
osm_err("i2o: Insufficient memory to allocate a I2O controller."
"\n");
return ERR_PTR(-ENOMEM);
}
- memset(c, 0, sizeof(*c));
+
+ c->unit = unit++;
+ sprintf(c->name, "iop%d", c->unit);
+
+ snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
+ if (i2o_pool_alloc
+ (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
+ I2O_MSG_INPOOL_MIN)) {
+ kfree(c);
+ return ERR_PTR(-ENOMEM);
+ };
INIT_LIST_HEAD(&c->devices);
spin_lock_init(&c->lock);
init_MUTEX(&c->lct_lock);
- c->unit = unit++;
- sprintf(c->name, "iop%d", c->unit);
device_initialize(&c->device);
@@ -1137,36 +1102,29 @@ int i2o_iop_add(struct i2o_controller *c)
goto iop_reset;
}
- c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
- &c->device, "iop%d", c->unit);
- if (IS_ERR(c->classdev)) {
- osm_err("%s: could not add controller class\n", c->name);
- goto device_del;
- }
-
osm_info("%s: Activating I2O controller...\n", c->name);
osm_info("%s: This may take a few minutes if there are many devices\n",
c->name);
if ((rc = i2o_iop_activate(c))) {
osm_err("%s: could not activate controller\n", c->name);
- goto class_del;
+ goto device_del;
}
osm_debug("%s: building sys table...\n", c->name);
if ((rc = i2o_systab_build()))
- goto class_del;
+ goto device_del;
osm_debug("%s: online controller...\n", c->name);
if ((rc = i2o_iop_online(c)))
- goto class_del;
+ goto device_del;
osm_debug("%s: getting LCT...\n", c->name);
if ((rc = i2o_exec_lct_get(c)))
- goto class_del;
+ goto device_del;
list_add(&c->list, &i2o_controllers);
@@ -1176,9 +1134,6 @@ int i2o_iop_add(struct i2o_controller *c)
return 0;
- class_del:
- class_device_unregister(c->classdev);
-
device_del:
device_del(&c->device);
@@ -1199,28 +1154,27 @@ int i2o_iop_add(struct i2o_controller *c)
* is waited for, or expected. If you do not want further notifications,
* call the i2o_event_register again with a evt_mask of 0.
*
- * Returns 0 on success or -ETIMEDOUT if no message could be fetched for
- * sending the request.
+ * Returns 0 on success or negative error code on failure.
*/
int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,
int tcntxt, u32 evt_mask)
{
struct i2o_controller *c = dev->iop;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data.
- tid, &msg->u.head[1]);
- writel(drv->context, &msg->u.s.icntxt);
- writel(tcntxt, &msg->u.s.tcntxt);
- writel(evt_mask, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->u.s.icntxt = cpu_to_le32(drv->context);
+ msg->u.s.tcntxt = cpu_to_le32(tcntxt);
+ msg->body[0] = cpu_to_le32(evt_mask);
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
};
@@ -1239,14 +1193,8 @@ static int __init i2o_iop_init(void)
printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
- i2o_controller_class = class_create(THIS_MODULE, "i2o_controller");
- if (IS_ERR(i2o_controller_class)) {
- osm_err("can't register class i2o_controller\n");
- goto exit;
- }
-
if ((rc = i2o_driver_init()))
- goto class_exit;
+ goto exit;
if ((rc = i2o_exec_init()))
goto driver_exit;
@@ -1262,9 +1210,6 @@ static int __init i2o_iop_init(void)
driver_exit:
i2o_driver_exit();
- class_exit:
- class_destroy(i2o_controller_class);
-
exit:
return rc;
}
@@ -1279,7 +1224,6 @@ static void __exit i2o_iop_exit(void)
i2o_pci_exit();
i2o_exec_exit();
i2o_driver_exit();
- class_destroy(i2o_controller_class);
};
module_init(i2o_iop_init);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index ee7075fa1ec..c5b656cdea7 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -339,7 +339,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
pci_name(pdev));
c->pdev = pdev;
- c->device.parent = get_device(&pdev->dev);
+ c->device.parent = &pdev->dev;
/* Cards that fall apart if you hit them with large I/O loads... */
if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -410,8 +410,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if ((rc = i2o_iop_add(c)))
goto uninstall;
- get_device(&c->device);
-
if (i960)
pci_write_config_word(i960, 0x42, 0x03ff);
@@ -424,7 +422,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
i2o_pci_free(c);
free_controller:
- put_device(c->device.parent);
i2o_iop_free(c);
disable:
@@ -454,7 +451,6 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev)
printk(KERN_INFO "%s: Controller removed.\n", c->name);
- put_device(c->device.parent);
put_device(&c->device);
};
@@ -483,4 +479,5 @@ void __exit i2o_pci_exit(void)
{
pci_unregister_driver(&i2o_pci_driver);
};
+
MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index e335d54c465..aff83f96680 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 551061c2ead..79fd062ccb3 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/mmc/mmc.c b/drivers/mmc/mmc.c
index eb41391e06e..bfca5c176e8 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 abcf19116d7..9b7c37e0e57 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);
@@ -263,7 +251,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
*/
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 1);
}
spin_unlock_irq(&md->lock);
} while (ret);
@@ -289,7 +277,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
spin_unlock_irq(&md->lock);
return 0;
@@ -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);
@@ -419,7 +464,7 @@ static int mmc_blk_probe(struct mmc_card *card)
printk(KERN_INFO "%s: %s %s %luKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- get_capacity(md->disk) >> 1, mmc_blk_readonly(card)?"(ro)":"");
+ get_capacity(md->disk) >> 1, md->read_only ? "(ro)" : "");
mmc_set_drvdata(card, md);
add_disk(md->disk);
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 166c9b0ad04..634ef53e85a 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 4589bbd6819..6d7eadc9a67 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 c7eb7c26908..f2575762536 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/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b9b77cf39a1..7abd7fee0dd 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 2f7e254912f..ab71f172eb7 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 265b079fe93..00000000000
--- 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 339cb1218ea..7f3ff500b68 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 9c5945d6df8..201e1362da1 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/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 3a5841c9d95..4129c03dfd9 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 d209214b131..5b55599739f 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 32541cbb010..9cf1ce718ec 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 45c077d0f06..af06a80f44d 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 20ce212638f..a3e00a4635a 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 5c5eebdb691..dcc98afa65d 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 c10f009ce9b..53b5b071df0 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 d2102a27d30..adfba44dac5 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 e2fa29b612c..5c15f3e9ea0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -27,6 +27,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 +142,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 +857,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 +1387,7 @@ config FORCEDETH
config CS89x0
tristate "CS89x0 support"
- depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105
+ depends on NET_PCI && (ISA || 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 +1397,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 +1804,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.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b74a7cb5bae..00e72b12fb9 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 8a0af5453e2..7952dc6d77e 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 470364deded..625184b65e3 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 b0d706834d8..bc263edf06a 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 877891a29aa..53e3afc1b7b 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 4f1f4e31bda..00000000000
--- 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 1cc53abc3a3..f1d5b1027ff 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 942a2819576..6a93b666eb7 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/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 854ddfb90da..f2a63186ae0 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 015c7f1d1bc..3dd78d048c3 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/cs89x0.c b/drivers/net/cs89x0.c
index a6078ad9b65..e2cfde7e31e 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -100,7 +100,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
@@ -175,7 +175,7 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0};
#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 +338,86 @@ out:
}
#endif
+#if defined(CONFIG_ARCH_IXDP2X01)
+static int
+readword(unsigned long base_addr, int portno)
+{
+ return (u16)__raw_readl(base_addr + (portno << 1));
+}
+
+static void
+writeword(unsigned long base_addr, int portno, int value)
+{
+ __raw_writel((u16)value, base_addr + (portno << 1));
+}
+#else
+#if defined(CONFIG_ARCH_PNX010X)
static int
-readreg(struct net_device *dev, int portno)
+readword(unsigned long base_addr, int portno)
{
- outw(portno, dev->base_addr + ADD_PORT);
- return inw(dev->base_addr + DATA_PORT);
+ return inw(base_addr + (portno << 1));
}
static void
-writereg(struct net_device *dev, int portno, int value)
+writeword(unsigned long base_addr, int portno, int value)
+{
+ outw(value, base_addr + (portno << 1));
+}
+#else
+static int
+readword(unsigned long base_addr, int portno)
{
- outw(portno, dev->base_addr + ADD_PORT);
- outw(value, dev->base_addr + DATA_PORT);
+ return inw(base_addr + portno);
+}
+
+static void
+writeword(unsigned long base_addr, int portno, int value)
+{
+ outw(value, base_addr + portno);
+}
+#endif
+#endif
+
+static void
+readwords(unsigned long base_addr, int portno, void *buf, int length)
+{
+ u8 *buf8 = (u8 *)buf;
+
+ do {
+ u32 tmp32;
+
+ tmp32 = readword(base_addr, portno);
+ *buf8++ = (u8)tmp32;
+ *buf8++ = (u8)(tmp32 >> 8);
+ } while (--length);
+}
+
+static void
+writewords(unsigned long base_addr, int portno, void *buf, int length)
+{
+ u8 *buf8 = (u8 *)buf;
+
+ do {
+ u32 tmp32;
+
+ tmp32 = *buf8++;
+ tmp32 |= (*buf8++) << 8;
+ writeword(base_addr, portno, tmp32);
+ } while (--length);
}
static int
-readword(struct net_device *dev, int portno)
+readreg(struct net_device *dev, int 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, int regno, int 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 +512,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 +547,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 +559,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 +780,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_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X)
i = cs8900_irq_map[0];
#else
/* Translate the IRQ using the IRQ mapping table. */
@@ -790,7 +846,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:
@@ -970,11 +1026,11 @@ void __init reset_chip(struct net_device *dev)
#ifndef 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 +1160,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 +1171,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 +1256,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 +1287,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105)
+#if !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 +1372,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 +1513,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 +1528,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 +1568,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 +1662,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 +1682,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 +1957,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 decea264f12..bd954aaa636 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 22cd0455670..23de22631c6 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -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>
@@ -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)
@@ -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);
@@ -2562,6 +2587,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
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 38695d5b463..ccbbe5ad8e0 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -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 */
@@ -641,8 +641,12 @@ 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;
}
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index f5a4dd7d856..e5c5cd2a271 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 50f8e23bb9e..6b0ab1eac3f 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 c39344adecc..3682ec61e8a 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 146f9513aea..0c18dbd67d3 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 94a91da84fb..cb9d66ac3ab 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 04a462c2a5b..74e52fcbf80 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 10d34cb1919..51ef181b136 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 90999867a32..102c1f0b90d 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 3e9accf137e..dc5e9d59dee 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 0abf5dd08b4..74e167e7dea 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 59cf841b14a..cf9fb3698a6 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 e92c17f6931..55c7ed60839 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 08703d6f934..d8410634bca 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 644edbff4f9..c2dae6092c4 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 1da8a66f91e..591c5864ffb 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 00000000000..1b699259b4e
--- /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 d54156f11e6..7a081346f07 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 e7a8b7f7f5d..72cbfdc9cfc 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 3d016a498e1..6070195b87b 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 b8d112348ba..101750bf210 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 f0b8bc3637e..f69fb4cec76 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 a49f910c835..00000000000
--- 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 df22b8b532e..ea7c9464d46 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 c5b76746e72..8d225921ae7 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 c65054364bc..e3904d6bfec 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 741aecc655d..a82a4ba8de4 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 77eadf84cb2..f0f04be989d 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 1d75ca0bb93..d1d714faa6c 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 309d254842c..646e89fc356 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 d8c99f038fa..06cb460361a 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 3cb9b3fe0cf..22c3a37bba5 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>
*
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 0de8fdd2aa8..94f782d51f0 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 6d62ada85de..e6df375a1d4 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 a1ac4bd1696..a7bb54df75a 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 049c34b3706..593d8adee89 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/Kconfig b/drivers/net/phy/Kconfig
index c782a632980..fa39b944bc4 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -6,7 +6,7 @@ menu "PHY device support"
config PHYLIB
tristate "PHY Device support and infrastructure"
- depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
+ depends on NET_ETHERNET && (BROKEN || !S390)
help
Ethernet controllers are usually attached to PHY
devices. This option provides infrastructure for
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 02940c0fef6..459443b572c 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 b8686e47f89..1474b7c5ac0 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/plip.c b/drivers/net/plip.c
index 1bd22cd40c7..87ee3271b17 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -98,7 +98,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/delay.h>
-#include <linux/lp.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -106,7 +105,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
#include <linux/skbuff.h>
#include <linux/if_plip.h>
#include <linux/workqueue.h>
-#include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/parport.h>
#include <linux/bitops.h>
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 400f652282d..aa6540b3946 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 4d51c0c8023..33cb8254e79 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 14a76f7cf90..2e1bed153c3 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/sis190.c b/drivers/net/sis190.c
index 478791e09bf..b420182eec4 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 0fddf61047b..07c1b4c8699 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 9a76ac180b1..a5f2b1ee075 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 58e1a5be913..a386172107e 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/slip.c b/drivers/net/slip.c
index 404ea4297e3..b2e18d28850 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 ba8593ac3f8..3db30cd0625 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 28bf2e69eb5..7ec08127c9d 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 5c2824be4ee..e0efd1964e7 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/sun3lance.c b/drivers/net/sun3lance.c
index 5c8fcd40ef4..01bdb233405 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/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 125ed00e95a..c67c91251d0 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 1a431633625..98398166680 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 82c6b757d30..c2d5907dc8e 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/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 52f26b9c69d..931cbdf6d79 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 036adc4f8ba..22e794071cf 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 bdf672c4818..9c3ccc66914 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 b03feae459f..7caa8dc88a5 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 24f7967aab6..c1a6e69f790 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -243,7 +243,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/atmel.c b/drivers/net/wireless/atmel.c
index e4729ddf29f..f0ccfef6644 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)
@@ -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/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 44cd3fcd157..cf05661fb1b 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -7153,7 +7153,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 +7184,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;
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index d25264ba0c0..18baacfc5a2 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/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 531b0731314..b2e8e49c865 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 026f671ea55..78193e4bbdb 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 166bca79013..b80318f0342 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 5ab75334c57..216d1d85932 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 6362bf99eff..3d94d86c1c9 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 3a1b4826e5c..e13aafa70bf 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 a8c20396ffb..2b3ba1dcf33 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 5e495dcbc58..cbae8c8963f 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 95bd07b8b61..3627a2d7f79 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 273a7417972..42a3c54e8e6 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 ff75e9296df..54b2b7f20b9 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 725a14119f2..f605dea5722 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
@@ -77,7 +77,7 @@ config PARPORT_PC_SUPERIO
config PARPORT_PC_PCMCIA
tristate "Support for PCMCIA management for PC-style ports"
- depends on PARPORT!=n && (PCMCIA!=n && PARPORT_PC=m && PARPORT_PC || PARPORT_PC=y && PCMCIA)
+ depends on PCMCIA && PARPORT_PC
help
Say Y here if you need PCMCIA support for your PC-style parallel
ports. If unsure, say N.
@@ -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/daisy.c b/drivers/parport/daisy.c
index 075c7eb5c85..9ee67321b63 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -144,9 +144,9 @@ again:
add_dev (numdevs++, port, -1);
/* Find out the legacy device's IEEE 1284 device ID. */
- deviceid = kmalloc (1000, GFP_KERNEL);
+ deviceid = kmalloc (1024, GFP_KERNEL);
if (deviceid) {
- if (parport_device_id (numdevs - 1, deviceid, 1000) > 2)
+ if (parport_device_id (numdevs - 1, deviceid, 1024) > 2)
detected++;
kfree (deviceid);
@@ -252,7 +252,7 @@ struct pardevice *parport_open (int devnum, const char *name,
selected = port->daisy;
parport_release (dev);
- if (selected != port->daisy) {
+ if (selected != daisy) {
/* No corresponding device. */
parport_unregister_device (dev);
return NULL;
@@ -344,9 +344,9 @@ static int cpp_daisy (struct parport *port, int cmd)
PARPORT_CONTROL_STROBE,
PARPORT_CONTROL_STROBE);
udelay (1);
+ s = parport_read_status (port);
parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
udelay (1);
- s = parport_read_status (port);
parport_write_data (port, 0xff); udelay (2);
return s;
@@ -395,15 +395,15 @@ int parport_daisy_select (struct parport *port, int daisy, int mode)
case IEEE1284_MODE_EPP:
case IEEE1284_MODE_EPPSL:
case IEEE1284_MODE_EPPSWE:
- return (cpp_daisy (port, 0x20 + daisy) &
- PARPORT_STATUS_ERROR);
+ return !(cpp_daisy (port, 0x20 + daisy) &
+ PARPORT_STATUS_ERROR);
// For these modes we should switch to ECP mode:
case IEEE1284_MODE_ECP:
case IEEE1284_MODE_ECPRLE:
case IEEE1284_MODE_ECPSWE:
- return (cpp_daisy (port, 0xd0 + daisy) &
- PARPORT_STATUS_ERROR);
+ return !(cpp_daisy (port, 0xd0 + daisy) &
+ PARPORT_STATUS_ERROR);
// Nothing was told for BECP in Daisy chain specification.
// May be it's wise to use ECP?
@@ -413,8 +413,8 @@ int parport_daisy_select (struct parport *port, int daisy, int mode)
case IEEE1284_MODE_BYTE:
case IEEE1284_MODE_COMPAT:
default:
- return (cpp_daisy (port, 0xe0 + daisy) &
- PARPORT_STATUS_ERROR);
+ return !(cpp_daisy (port, 0xe0 + daisy) &
+ PARPORT_STATUS_ERROR);
}
}
@@ -436,7 +436,7 @@ static int select_port (struct parport *port)
static int assign_addrs (struct parport *port)
{
- unsigned char s, last_dev;
+ unsigned char s;
unsigned char daisy;
int thisdev = numdevs;
int detected;
@@ -472,10 +472,13 @@ static int assign_addrs (struct parport *port)
}
parport_write_data (port, 0x78); udelay (2);
- last_dev = 0; /* We've just been speaking to a device, so we
- know there must be at least _one_ out there. */
+ s = parport_read_status (port);
- for (daisy = 0; daisy < 4; daisy++) {
+ for (daisy = 0;
+ (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT))
+ == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)
+ && daisy < 4;
+ ++daisy) {
parport_write_data (port, daisy);
udelay (2);
parport_frob_control (port,
@@ -485,14 +488,18 @@ static int assign_addrs (struct parport *port)
parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
udelay (1);
- if (last_dev)
- /* No more devices. */
- break;
+ add_dev (numdevs++, port, daisy);
- last_dev = !(parport_read_status (port)
- & PARPORT_STATUS_BUSY);
+ /* See if this device thought it was the last in the
+ * chain. */
+ if (!(s & PARPORT_STATUS_BUSY))
+ break;
- add_dev (numdevs++, port, daisy);
+ /* We are seeing pass through status now. We see
+ last_dev from next device or if last_dev does not
+ work status lines from some non-daisy chain
+ device. */
+ s = parport_read_status (port);
}
parport_write_data (port, 0xff); udelay (2);
@@ -501,11 +508,11 @@ static int assign_addrs (struct parport *port)
detected);
/* Ask the new devices to introduce themselves. */
- deviceid = kmalloc (1000, GFP_KERNEL);
+ deviceid = kmalloc (1024, GFP_KERNEL);
if (!deviceid) return 0;
for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
- parport_device_id (thisdev, deviceid, 1000);
+ parport_device_id (thisdev, deviceid, 1024);
kfree (deviceid);
return detected;
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index ce1e2aad8b1..d6c77658231 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -165,17 +165,7 @@ size_t parport_ieee1284_read_nibble (struct parport *port,
/* Does the error line indicate end of data? */
if (((i & 1) == 0) &&
(parport_read_status(port) & PARPORT_STATUS_ERROR)) {
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
- DPRINTK (KERN_DEBUG
- "%s: No more nibble data (%d bytes)\n",
- port->name, i/2);
-
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- break;
+ goto end_of_data;
}
/* Event 7: Set nAutoFd low. */
@@ -225,18 +215,25 @@ size_t parport_ieee1284_read_nibble (struct parport *port,
byte = nibble;
}
- i /= 2; /* i is now in bytes */
-
if (i == len) {
/* Read the last nibble without checking data avail. */
- port = port->physport;
- if (parport_read_status (port) & PARPORT_STATUS_ERROR)
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+ end_of_data:
+ DPRINTK (KERN_DEBUG
+ "%s: No more nibble data (%d bytes)\n",
+ port->name, i/2);
+
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ }
else
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
- return i;
+ return i/2;
#endif /* IEEE1284 support */
}
@@ -256,17 +253,7 @@ size_t parport_ieee1284_read_byte (struct parport *port,
/* Data available? */
if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
- DPRINTK (KERN_DEBUG
- "%s: No more byte data (%Zd bytes)\n",
- port->name, count);
-
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- break;
+ goto end_of_data;
}
/* Event 14: Place data bus in high impedance state. */
@@ -318,11 +305,20 @@ size_t parport_ieee1284_read_byte (struct parport *port,
if (count == len) {
/* Read the last byte without checking data avail. */
- port = port->physport;
- if (parport_read_status (port) & PARPORT_STATUS_ERROR)
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+ end_of_data:
+ DPRINTK (KERN_DEBUG
+ "%s: No more byte data (%Zd bytes)\n",
+ port->name, count);
+
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ }
else
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
return count;
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index c6493ad7c0c..9302b8fd746 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1169,7 +1169,7 @@ dump_parport_state ("fwd idle", port);
/* GCC is not inlining extern inline function later overwriten to non-inline,
so we use outlined_ variants here. */
-static struct parport_operations parport_pc_ops =
+static const struct parport_operations parport_pc_ops =
{
.write_data = parport_pc_write_data,
.read_data = parport_pc_read_data,
@@ -1211,10 +1211,11 @@ static struct parport_operations parport_pc_ops =
static void __devinit show_parconfig_smsc37c669(int io, int key)
{
int cr1,cr4,cra,cr23,cr26,cr27,i=0;
- static const char *modes[]={ "SPP and Bidirectional (PS/2)",
- "EPP and SPP",
- "ECP",
- "ECP and EPP" };
+ static const char *const modes[]={
+ "SPP and Bidirectional (PS/2)",
+ "EPP and SPP",
+ "ECP",
+ "ECP and EPP" };
outb(key,io);
outb(key,io);
@@ -1288,7 +1289,7 @@ static void __devinit show_parconfig_smsc37c669(int io, int key)
static void __devinit show_parconfig_winbond(int io, int key)
{
int cr30,cr60,cr61,cr70,cr74,crf0,i=0;
- static const char *modes[] = {
+ static const char *const modes[] = {
"Standard (SPP) and Bidirectional(PS/2)", /* 0 */
"EPP-1.9 and SPP",
"ECP",
@@ -1297,7 +1298,9 @@ static void __devinit show_parconfig_winbond(int io, int key)
"EPP-1.7 and SPP", /* 5 */
"undefined!",
"ECP and EPP-1.7" };
- static char *irqtypes[] = { "pulsed low, high-Z", "follows nACK" };
+ static char *const irqtypes[] = {
+ "pulsed low, high-Z",
+ "follows nACK" };
/* The registers are called compatible-PnP because the
register layout is modelled after ISA-PnP, the access
@@ -2368,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);
@@ -2377,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 */
@@ -2396,7 +2399,8 @@ EXPORT_SYMBOL (parport_pc_unregister_port);
/* ITE support maintained by Rich Liu <richliu@poorman.org> */
static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
- int autodma, struct parport_pc_via_data *via)
+ int autodma,
+ const struct parport_pc_via_data *via)
{
short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
struct resource *base_res;
@@ -2524,7 +2528,8 @@ static struct parport_pc_via_data via_8231_data __devinitdata = {
};
static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq,
- int autodma, struct parport_pc_via_data *via)
+ int autodma,
+ const struct parport_pc_via_data *via)
{
u8 tmp, tmp2, siofunc;
u8 ppcontrol = 0;
@@ -2694,8 +2699,9 @@ enum parport_pc_sio_types {
/* each element directly indexed from enum list, above */
static struct parport_pc_superio {
- int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, struct parport_pc_via_data *via);
- struct parport_pc_via_data *via;
+ int (*probe) (struct pci_dev *pdev, int autoirq, int autodma,
+ const struct parport_pc_via_data *via);
+ const struct parport_pc_via_data *via;
} parport_pc_superio_info[] __devinitdata = {
{ sio_via_probe, &via_686a_data, },
{ sio_via_probe, &via_8231_data, },
@@ -2828,7 +2834,7 @@ static struct parport_pc_pci {
/* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
};
-static struct pci_device_id parport_pc_pci_tbl[] = {
+static const struct pci_device_id parport_pc_pci_tbl[] = {
/* Super-IO onboard chips */
{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
{ 0x1106, 0x8231, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_8231 },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index d3dad0aac7c..76dd077e318 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/parport/probe.c b/drivers/parport/probe.c
index 4b48b31ec23..b62aee8de3c 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -11,9 +11,9 @@
#include <linux/string.h>
#include <asm/uaccess.h>
-static struct {
- char *token;
- char *descr;
+static const struct {
+ const char *token;
+ const char *descr;
} classes[] = {
{ "", "Legacy device" },
{ "PRINTER", "Printer" },
@@ -128,8 +128,131 @@ static void parse_data(struct parport *port, int device, char *str)
kfree(txt);
}
+/* Read up to count-1 bytes of device id. Terminate buffer with
+ * '\0'. Buffer begins with two Device ID length bytes as given by
+ * device. */
+static ssize_t parport_read_device_id (struct parport *port, char *buffer,
+ size_t count)
+{
+ unsigned char length[2];
+ unsigned lelen, belen;
+ size_t idlens[4];
+ unsigned numidlens;
+ unsigned current_idlen;
+ ssize_t retval;
+ size_t len;
+
+ /* First two bytes are MSB,LSB of inclusive length. */
+ retval = parport_read (port, length, 2);
+
+ if (retval < 0)
+ return retval;
+ if (retval != 2)
+ return -EIO;
+
+ if (count < 2)
+ return 0;
+ memcpy(buffer, length, 2);
+ len = 2;
+
+ /* Some devices wrongly send LE length, and some send it two
+ * bytes short. Construct a sorted array of lengths to try. */
+ belen = (length[0] << 8) + length[1];
+ lelen = (length[1] << 8) + length[0];
+ idlens[0] = min(belen, lelen);
+ idlens[1] = idlens[0]+2;
+ if (belen != lelen) {
+ int off = 2;
+ /* Don't try lenghts of 0x100 and 0x200 as 1 and 2 */
+ if (idlens[0] <= 2)
+ off = 0;
+ idlens[off] = max(belen, lelen);
+ idlens[off+1] = idlens[off]+2;
+ numidlens = off+2;
+ }
+ else {
+ /* Some devices don't truly implement Device ID, but
+ * just return constant nibble forever. This catches
+ * also those cases. */
+ if (idlens[0] == 0 || idlens[0] > 0xFFF) {
+ printk (KERN_DEBUG "%s: reported broken Device ID"
+ " length of %#zX bytes\n",
+ port->name, idlens[0]);
+ return -EIO;
+ }
+ numidlens = 2;
+ }
+
+ /* Try to respect the given ID length despite all the bugs in
+ * the ID length. Read according to shortest possible ID
+ * first. */
+ for (current_idlen = 0; current_idlen < numidlens; ++current_idlen) {
+ size_t idlen = idlens[current_idlen];
+ if (idlen+1 >= count)
+ break;
+
+ retval = parport_read (port, buffer+len, idlen-len);
+
+ if (retval < 0)
+ return retval;
+ len += retval;
+
+ if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
+ if (belen != len) {
+ printk (KERN_DEBUG "%s: Device ID was %d bytes"
+ " while device told it would be %d"
+ " bytes\n",
+ port->name, len, belen);
+ }
+ goto done;
+ }
+
+ /* This might end reading the Device ID too
+ * soon. Hopefully the needed fields were already in
+ * the first 256 bytes or so that we must have read so
+ * far. */
+ if (buffer[len-1] == ';') {
+ printk (KERN_DEBUG "%s: Device ID reading stopped"
+ " before device told data not available. "
+ "Current idlen %d of %d, len bytes %02X %02X\n",
+ port->name, current_idlen, numidlens,
+ length[0], length[1]);
+ goto done;
+ }
+ }
+ if (current_idlen < numidlens) {
+ /* Buffer not large enough, read to end of buffer. */
+ size_t idlen, len2;
+ if (len+1 < count) {
+ retval = parport_read (port, buffer+len, count-len-1);
+ if (retval < 0)
+ return retval;
+ len += retval;
+ }
+ /* Read the whole ID since some devices would not
+ * otherwise give back the Device ID from beginning
+ * next time when asked. */
+ idlen = idlens[current_idlen];
+ len2 = len;
+ while(len2 < idlen && retval > 0) {
+ char tmp[4];
+ retval = parport_read (port, tmp,
+ min(sizeof tmp, idlen-len2));
+ if (retval < 0)
+ return retval;
+ len2 += retval;
+ }
+ }
+ /* In addition, there are broken devices out there that don't
+ even finish off with a semi-colon. We do not need to care
+ about those at this time. */
+ done:
+ buffer[len] = '\0';
+ return len;
+}
+
/* Get Std 1284 Device ID. */
-ssize_t parport_device_id (int devnum, char *buffer, size_t len)
+ssize_t parport_device_id (int devnum, char *buffer, size_t count)
{
ssize_t retval = -ENXIO;
struct pardevice *dev = parport_open (devnum, "Device ID probe",
@@ -139,76 +262,20 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
parport_claim_or_block (dev);
- /* Negotiate to compatibility mode, and then to device ID mode.
- * (This is in case we are already in device ID mode.) */
+ /* Negotiate to compatibility mode, and then to device ID
+ * mode. (This so that we start form beginning of device ID if
+ * already in device ID mode.) */
parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
retval = parport_negotiate (dev->port,
IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
if (!retval) {
- int idlen;
- unsigned char length[2];
-
- /* First two bytes are MSB,LSB of inclusive length. */
- retval = parport_read (dev->port, length, 2);
-
- if (retval != 2) goto end_id;
-
- idlen = (length[0] << 8) + length[1] - 2;
- /*
- * Check if the caller-allocated buffer is large enough
- * otherwise bail out or there will be an at least off by one.
- */
- if (idlen + 1 < len)
- len = idlen;
- else {
- retval = -EINVAL;
- goto out;
- }
- retval = parport_read (dev->port, buffer, len);
-
- if (retval != len)
- printk (KERN_DEBUG "%s: only read %Zd of %Zd ID bytes\n",
- dev->port->name, retval,
- len);
-
- /* Some printer manufacturers mistakenly believe that
- the length field is supposed to be _exclusive_.
- In addition, there are broken devices out there
- that don't even finish off with a semi-colon. */
- if (buffer[len - 1] != ';') {
- ssize_t diff;
- diff = parport_read (dev->port, buffer + len, 2);
- retval += diff;
-
- if (diff)
- printk (KERN_DEBUG
- "%s: device reported incorrect "
- "length field (%d, should be %Zd)\n",
- dev->port->name, idlen, retval);
- else {
- /* One semi-colon short of a device ID. */
- buffer[len++] = ';';
- printk (KERN_DEBUG "%s: faking semi-colon\n",
- dev->port->name);
-
- /* If we get here, I don't think we
- need to worry about the possible
- standard violation of having read
- more than we were told to. The
- device is non-compliant anyhow. */
- }
- }
-
- end_id:
- buffer[len] = '\0';
+ retval = parport_read_device_id (dev->port, buffer, count);
parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
+ if (retval > 2)
+ parse_data (dev->port, dev->daisy, buffer+2);
}
- if (retval > 2)
- parse_data (dev->port, dev->daisy, buffer);
-
-out:
parport_release (dev);
parport_close (dev);
return retval;
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 9cb3ab156b0..ea62bed6bc8 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -1002,6 +1002,7 @@ EXPORT_SYMBOL(parport_register_driver);
EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
+EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number);
EXPORT_SYMBOL(parport_find_base);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 8e21f6ab89a..509a5b3ae99 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 092491e25ef..cb88404c89f 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 9aed8efe6a1..b3659ffccac 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 10a5a7674a8..771ed34b181 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 4c11048ad51..bbfeed767ff 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 b1ba429e0a2..155133fe5c1 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 6a61b9f286e..0aac6a61337 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 8df70486034..4fb569018a2 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 0b8b26beb16..77e530321de 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 647673a7d22..4017fb03a0b 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 ae244e21862..2bdb30f68bf 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 cc03609f45d..7d93dbaf628 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 4b35097b3d9..396b54b0c84 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 08ad26a0cae..ce0e9b6ce83 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 63628e01dd4..a2b3f0010ce 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 58619359ad0..25ccb0e4759 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 9987a6fd65b..b4226ff3a85 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 38009bc0fd5..19e1a5e1e30 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.c b/drivers/pci/pci.c
index 8e287a828d5..d2a633efa10 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 294849d2459..a6dfee2f6d2 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 467a4ceccf1..e4e5f1e8d81 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 fce2cb2112d..adfad4fd6a1 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 9eb465727fc..92a88576083 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 f28ebdd3958..605f0df0bfb 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1342,6 +1342,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 27a294b6965..1a6bf9de166 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 0252582b91c..621ec459d27 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -920,6 +920,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 +976,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 +991,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),
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 5d957dfe23d..fda06941e73 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 b5fdeec20b1..fd364736895 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 7a7744662d5..5ab1cdef7c4 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 24c547ef512..0574efd7828 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 1b277d2c1c9..57f38dba0a4 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 113726f7cf9..7d77c74120c 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/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 6b7583f497d..a1f0b0ba2bf 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -31,15 +31,6 @@ static struct {
} pnp_bios_callpoint;
-/* The PnP BIOS entries in the GDT */
-#define PNP_GDT (GDT_ENTRY_PNPBIOS_BASE * 8)
-
-#define PNP_CS32 (PNP_GDT+0x00) /* segment for calling fn */
-#define PNP_CS16 (PNP_GDT+0x08) /* code segment for BIOS */
-#define PNP_DS (PNP_GDT+0x10) /* data segment for BIOS */
-#define PNP_TS1 (PNP_GDT+0x18) /* transfer data segment */
-#define PNP_TS2 (PNP_GDT+0x20) /* another data segment */
-
/*
* These are some opcodes for a "static asmlinkage"
* As this code is *not* executed inside the linux kernel segment, but in a
@@ -67,16 +58,11 @@ __asm__(
".previous \n"
);
-#define Q_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \
-set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
-} while(0)
-
#define Q2_SET_SEL(cpu, selname, address, size) \
do { \
-set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \
-set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
+struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \
+set_base(gdt[(selname) >> 3], (u32)(address)); \
+set_limit(gdt[(selname) >> 3], size); \
} while(0)
static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
@@ -115,8 +101,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
return PNP_FUNCTION_NOT_SUPPORTED;
cpu = get_cpu();
- save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8];
- per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc;
+ save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8];
+ get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc;
/* On some boxes IRQ's during PnP BIOS calls are deadly. */
spin_lock_irqsave(&pnp_bios_lock, flags);
@@ -158,7 +144,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
);
spin_unlock_irqrestore(&pnp_bios_lock, flags);
- per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40;
+ get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
put_cpu();
/* If we get here and this is set then the PnP BIOS faulted on us. */
@@ -290,12 +276,15 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
{
u16 status;
+ u16 tmp_nodenum;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot && pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
+ tmp_nodenum = *nodenum;
status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
- nodenum, sizeof(char), data, 65536);
+ &tmp_nodenum, sizeof(tmp_nodenum), data, 65536);
+ *nodenum = tmp_nodenum;
return status;
}
@@ -535,10 +524,12 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header)
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
- for(i=0; i < NR_CPUS; i++)
- {
- Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
- Q_SET_SEL(i, PNP_CS16, header->fields.pm16cseg, 64 * 1024);
- Q_SET_SEL(i, PNP_DS, header->fields.pm16dseg, 64 * 1024);
- }
+ for (i = 0; i < NR_CPUS; i++) {
+ struct desc_struct *gdt = get_cpu_gdt_table(i);
+ if (!gdt)
+ continue;
+ set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc);
+ set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg));
+ set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg));
+ }
}
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 4f7ed4bd3be..94e30fe4b8f 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 30a11436e24..bef9316e95d 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 3ca1011ceaa..5e382470faa 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/Makefile b/drivers/s390/Makefile
index c99a2fe92fb..9803c9352d7 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -2,7 +2,7 @@
# Makefile for the S/390 specific device drivers
#
-obj-y += s390mach.o sysinfo.o
+obj-y += s390mach.o sysinfo.o s390_rdev.o
obj-y += cio/ block/ char/ crypto/ net/ scsi/
drivers-y += drivers/s390/built-in.o
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6e7d7b06421..6f50cc9323d 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -1,11 +1,11 @@
-if ARCH_S390
+if S390
comment "S/390 block device drivers"
- depends on ARCH_S390
+ depends on S390
config BLK_DEV_XPRAM
tristate "XPRAM disk support"
- depends on ARCH_S390
+ depends on S390
help
Select this option if you want to use your expanded storage on S/390
or zSeries as a disk. This is useful as a _fast_ swap device if you
@@ -49,7 +49,7 @@ config DASD_FBA
config DASD_DIAG
tristate "Support for DIAG access to Disks"
- depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL)
+ depends on DASD && ( 64BIT = 'n' || EXPERIMENTAL)
help
Select this option if you want to use Diagnose250 command to access
Disks under VM. If you are not running under VM or unsure what it is,
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 7008d32433b..9c25654b1e7 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.167 $
+ * $Revision: 1.172 $
*/
#include <linux/config.h>
@@ -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>
@@ -604,7 +605,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
void
dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
{
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
struct ccw1 *ccw;
/* Clear any idals used for the request. */
@@ -1035,7 +1036,7 @@ dasd_end_request(struct request *req, int uptodate)
if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
BUG();
add_disk_randomness(req->rq_disk);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
/*
@@ -1224,6 +1225,12 @@ __dasd_start_head(struct dasd_device * device)
if (list_empty(&device->ccw_queue))
return;
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
+ /* check FAILFAST */
+ if (device->stopped & ~DASD_STOPPED_PENDING &&
+ test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
+ cqr->status = DASD_CQR_FAILED;
+ dasd_schedule_bh(device);
+ }
if ((cqr->status == DASD_CQR_QUEUED) &&
(!device->stopped)) {
/* try to start the first I/O that can be started */
@@ -1323,7 +1330,7 @@ void
dasd_schedule_bh(struct dasd_device * device)
{
/* Protect against rescheduling. */
- if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled))
+ if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0)
return;
dasd_get_device(device);
tasklet_hi_schedule(&device->tasklet);
@@ -1717,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,
};
@@ -1750,8 +1780,10 @@ dasd_exit(void)
* SECTION: common functions for ccw_driver use
*/
-/* initial attempt at a probe function. this can be simplified once
- * the other detection code is gone */
+/*
+ * Initial attempt at a probe function. this can be simplified once
+ * the other detection code is gone.
+ */
int
dasd_generic_probe (struct ccw_device *cdev,
struct dasd_discipline *discipline)
@@ -1770,8 +1802,10 @@ dasd_generic_probe (struct ccw_device *cdev,
return ret;
}
-/* this will one day be called from a global not_oper handler.
- * It is also used by driver_unregister during module unload */
+/*
+ * This will one day be called from a global not_oper handler.
+ * It is also used by driver_unregister during module unload.
+ */
void
dasd_generic_remove (struct ccw_device *cdev)
{
@@ -1798,9 +1832,11 @@ dasd_generic_remove (struct ccw_device *cdev)
dasd_delete_device(device);
}
-/* activate a device. This is called from dasd_{eckd,fba}_probe() when either
+/*
+ * Activate a device. This is called from dasd_{eckd,fba}_probe() when either
* the device is detected for the first time and is supposed to be used
- * or the user has started activation through sysfs */
+ * or the user has started activation through sysfs.
+ */
int
dasd_generic_set_online (struct ccw_device *cdev,
struct dasd_discipline *discipline)
@@ -1917,7 +1953,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
if (cqr->status == DASD_CQR_IN_IO)
cqr->status = DASD_CQR_FAILED;
device->stopped |= DASD_STOPPED_DC_EIO;
- dasd_schedule_bh(device);
} else {
list_for_each_entry(cqr, &device->ccw_queue, list)
if (cqr->status == DASD_CQR_IN_IO) {
@@ -1927,6 +1962,7 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
device->stopped |= DASD_STOPPED_DC_WAIT;
dasd_set_timer(device, 0);
}
+ dasd_schedule_bh(device);
ret = 1;
break;
case CIO_OPER:
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index ab8754e566b..ba80fdea7eb 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.51 $
+ * $Revision: 1.53 $
*/
#include <linux/config.h>
@@ -25,6 +25,7 @@
#include <asm/io.h>
#include <asm/s390_ext.h>
#include <asm/todclk.h>
+#include <asm/vtoc.h>
#include "dasd_int.h"
#include "dasd_diag.h"
@@ -74,7 +75,7 @@ dia250(void *iob, int cmd)
int rc;
__asm__ __volatile__(
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
" lghi %0,3\n"
" lgr 0,%3\n"
" diag 0,%2,0x250\n"
@@ -329,7 +330,7 @@ dasd_diag_check_device(struct dasd_device *device)
struct dasd_diag_private *private;
struct dasd_diag_characteristics *rdc_data;
struct dasd_diag_bio bio;
- struct dasd_diag_cms_label *label;
+ struct vtoc_cms_label *label;
blocknum_t end_block;
unsigned int sb, bsize;
int rc;
@@ -380,7 +381,7 @@ dasd_diag_check_device(struct dasd_device *device)
mdsk_term_io(device);
/* figure out blocksize of device */
- label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
+ label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);
if (label == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"No memory to allocate initialization request");
@@ -548,6 +549,8 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
}
cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
+ if (req->flags & REQ_FAILFAST)
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = DIAG_TIMEOUT;
cqr->status = DASD_CQR_FILLED;
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index df31484d73a..a4f80bd735f 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.8 $
+ * $Revision: 1.9 $
*/
#define MDSK_WRITE_REQ 0x01
@@ -44,29 +44,8 @@ struct dasd_diag_characteristics {
u8 rdev_features;
} __attribute__ ((packed, aligned(4)));
-struct dasd_diag_cms_label {
- u8 label_id[4];
- u8 vol_id[6];
- u16 version_id;
- u32 block_size;
- u32 origin_ptr;
- u32 usable_count;
- u32 formatted_count;
- u32 block_count;
- u32 used_count;
- u32 fst_size;
- u32 fst_count;
- u8 format_date[6];
- u8 reserved1[2];
- u32 disk_offset;
- u32 map_block;
- u32 hblk_disp;
- u32 user_disp;
- u8 reserved2[4];
- u8 segment_name[8];
-} __attribute__ ((packed));
-
-#ifdef CONFIG_ARCH_S390X
+
+#ifdef CONFIG_64BIT
#define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT
typedef u64 blocknum_t;
@@ -107,7 +86,7 @@ struct dasd_diag_rw_io {
struct dasd_diag_bio *bio_list;
u8 spare4[8];
} __attribute__ ((packed, aligned(8)));
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define DASD_DIAG_FLAGA_DEFAULT 0x0
typedef u32 blocknum_t;
@@ -146,4 +125,4 @@ struct dasd_diag_rw_io {
u32 interrupt_params;
u8 spare3[20];
} __attribute__ ((packed, aligned(8)));
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 811060e10c0..96eb4825858 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.71 $
+ * $Revision: 1.74 $
*/
#include <linux/config.h>
@@ -1041,7 +1041,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
/* Eckd can only do full blocks. */
return ERR_PTR(-EINVAL);
count += bv->bv_len >> (device->s2b_shift + 9);
-#if defined(CONFIG_ARCH_S390X)
+#if defined(CONFIG_64BIT)
if (idal_is_needed (page_address(bv->bv_page),
bv->bv_len))
cidaw += bv->bv_len >> (device->s2b_shift + 9);
@@ -1136,6 +1136,8 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
recid++;
}
}
+ if (req->flags & REQ_FAILFAST)
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
cqr->lpm = private->path_data.ppm;
@@ -1252,6 +1254,7 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
@@ -1296,6 +1299,7 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
@@ -1339,6 +1343,7 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 28cb4613b7f..8ec75dc08e2 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -4,7 +4,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.40 $
+ * $Revision: 1.41 $
*/
#include <linux/config.h>
@@ -271,7 +271,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
/* Fba can only do full blocks. */
return ERR_PTR(-EINVAL);
count += bv->bv_len >> (device->s2b_shift + 9);
-#if defined(CONFIG_ARCH_S390X)
+#if defined(CONFIG_64BIT)
if (idal_is_needed (page_address(bv->bv_page),
bv->bv_len))
cidaw += bv->bv_len / blksize;
@@ -352,6 +352,8 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
recid++;
}
}
+ if (req->flags & REQ_FAILFAST)
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
cqr->retries = 32;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 9fab04f3056..e4b401500b0 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.65 $
+ * $Revision: 1.68 $
*/
#ifndef DASD_INT_H
@@ -208,6 +208,7 @@ struct dasd_ccw_req {
/* per dasd_ccw_req flags */
#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
+#define DASD_CQR_FLAGS_FAILFAST 1 /* FAILFAST */
/* Signature for error recovery functions. */
typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
@@ -526,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 789595b3fa0..9396fcacb8f 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.47 $
+ * $Revision: 1.50 $
*
* i/o controls for the dasd driver.
*/
@@ -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)
{
@@ -352,6 +364,9 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
if (device == NULL)
return -ENODEV;
+ if (dasd_profile_level == DASD_PROFILE_OFF)
+ return -EIO;
+
if (copy_to_user((long __user *) args, (long *) &device->profile,
sizeof (struct dasd_profile_info_t)))
return -EFAULT;
@@ -483,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[] =
@@ -525,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/dcssblk.c b/drivers/s390/block/dcssblk.c
index 4fde4118899..2e727f49ad1 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -15,7 +15,7 @@
#include <asm/io.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
-#include <asm/ccwdev.h> // for s390_root_dev_(un)register()
+#include <asm/s390_rdev.h>
//#define DCSSBLK_DEBUG /* Debug messages on/off */
#define DCSSBLK_NAME "dcssblk"
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index d428c909b8a..54ecd548c31 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -160,7 +160,7 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,1b\n"
@@ -208,7 +208,7 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,1b\n"
@@ -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 75419cf9d35..1f060914cfa 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 735a7fcdeff..5f6fa4c6784 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_cpi.c b/drivers/s390/char/sclp_cpi.c
index 5a6cef2dfa1..80f7f31310e 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -204,7 +204,7 @@ cpi_module_init(void)
printk(KERN_WARNING "cpi: no control program identification "
"support\n");
sclp_unregister(&sclp_cpi_event);
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
}
req = cpi_prepare_req();
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 83f75774df6..56fa6916889 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -32,7 +32,7 @@ do_load_quiesce_psw(void * __unused)
psw_t quiesce_psw;
int cpu;
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+ if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
signal_processor(smp_processor_id(), sigp_stop);
/* Wait for all other cpus to enter stopped state */
for_each_online_cpu(cpu) {
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index a20d7c89341..6cbf067f1a8 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 06bd85824d7..9e02625c82c 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_block.c b/drivers/s390/char/tape_block.c
index 1efc9f21229..5ced2725d6c 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -65,7 +65,7 @@ static void
tapeblock_trigger_requeue(struct tape_device *device)
{
/* Protect against rescheduling. */
- if (atomic_compare_and_swap(0, 1, &device->blk_data.requeue_scheduled))
+ if (atomic_cmpxchg(&device->blk_data.requeue_scheduled, 0, 1) != 0)
return;
schedule_work(&device->blk_data.requeue_task);
}
@@ -78,7 +78,7 @@ tapeblock_end_request(struct request *req, int uptodate)
{
if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
BUG();
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
static void
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 86262a13f7c..5ce7ca38ace 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/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 5473c23fcb5..5acc0ace3d7 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -66,7 +66,7 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout,
__cmdl = len;
err = 0;
asm volatile (
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
"diag %2,%4,0x288\n"
"1: \n"
".section .fixup,\"ax\"\n"
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index a1c52a68219..daf21e03b21 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.35 $
+ * $Revision: 1.39 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -15,6 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/ctype.h>
#include <linux/device.h>
@@ -34,10 +35,10 @@
* These can be single devices or ranges of devices
*/
-/* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
+/* 65536 bits for each set to indicate if a devno is blacklisted or not */
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \
(8*sizeof(long)))
-static unsigned long bl_dev[__BL_DEV_WORDS];
+static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS];
typedef enum {add, free} range_action;
/*
@@ -45,21 +46,23 @@ typedef enum {add, free} range_action;
* (Un-)blacklist the devices from-to
*/
static inline void
-blacklist_range (range_action action, unsigned int from, unsigned int to)
+blacklist_range (range_action action, unsigned int from, unsigned int to,
+ unsigned int ssid)
{
if (!to)
to = from;
- if (from > to || to > __MAX_SUBCHANNELS) {
+ if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
printk (KERN_WARNING "Invalid blacklist range "
- "0x%04x to 0x%04x, skipping\n", from, to);
+ "0.%x.%04x to 0.%x.%04x, skipping\n",
+ ssid, from, ssid, to);
return;
}
for (; from <= to; from++) {
if (action == add)
- set_bit (from, bl_dev);
+ set_bit (from, bl_dev[ssid]);
else
- clear_bit (from, bl_dev);
+ clear_bit (from, bl_dev[ssid]);
}
}
@@ -69,7 +72,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to)
* Shamelessly grabbed from dasd_devmap.c.
*/
static inline int
-blacklist_busid(char **str, int *id0, int *id1, int *devno)
+blacklist_busid(char **str, int *id0, int *ssid, int *devno)
{
int val, old_style;
char *sav;
@@ -86,7 +89,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
goto confused;
val = simple_strtoul(*str, str, 16);
if (old_style || (*str)[0] != '.') {
- *id0 = *id1 = 0;
+ *id0 = *ssid = 0;
if (val < 0 || val > 0xffff)
goto confused;
*devno = val;
@@ -105,7 +108,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
val = simple_strtoul(*str, str, 16);
if (val < 0 || val > 0xff || (*str)++[0] != '.')
goto confused;
- *id1 = val;
+ *ssid = val;
if (!isxdigit((*str)[0])) /* We require at least one hex digit */
goto confused;
val = simple_strtoul(*str, str, 16);
@@ -125,7 +128,7 @@ confused:
static inline int
blacklist_parse_parameters (char *str, range_action action)
{
- unsigned int from, to, from_id0, to_id0, from_id1, to_id1;
+ unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
while (*str != 0 && *str != '\n') {
range_action ra = action;
@@ -142,23 +145,25 @@ blacklist_parse_parameters (char *str, range_action action)
*/
if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
- from = 0;
- to = __MAX_SUBCHANNELS;
+ int j;
+
str += 3;
+ for (j=0; j <= __MAX_SSID; j++)
+ blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
} else {
int rc;
rc = blacklist_busid(&str, &from_id0,
- &from_id1, &from);
+ &from_ssid, &from);
if (rc)
continue;
to = from;
to_id0 = from_id0;
- to_id1 = from_id1;
+ to_ssid = from_ssid;
if (*str == '-') {
str++;
rc = blacklist_busid(&str, &to_id0,
- &to_id1, &to);
+ &to_ssid, &to);
if (rc)
continue;
}
@@ -168,18 +173,19 @@ blacklist_parse_parameters (char *str, range_action action)
strsep(&str, ",\n"));
continue;
}
- if ((from_id0 != to_id0) || (from_id1 != to_id1)) {
+ if ((from_id0 != to_id0) ||
+ (from_ssid != to_ssid)) {
printk(KERN_WARNING "invalid cio_ignore range "
"%x.%x.%04x-%x.%x.%04x\n",
- from_id0, from_id1, from,
- to_id0, to_id1, to);
+ from_id0, from_ssid, from,
+ to_id0, to_ssid, to);
continue;
}
+ pr_debug("blacklist_setup: adding range "
+ "from %x.%x.%04x to %x.%x.%04x\n",
+ from_id0, from_ssid, from, to_id0, to_ssid, to);
+ blacklist_range (ra, from, to, to_ssid);
}
- /* FIXME: ignoring id0 and id1 here. */
- pr_debug("blacklist_setup: adding range "
- "from 0.0.%04x to 0.0.%04x\n", from, to);
- blacklist_range (ra, from, to);
}
return 1;
}
@@ -213,12 +219,33 @@ __setup ("cio_ignore=", blacklist_setup);
* Used by validate_subchannel()
*/
int
-is_blacklisted (int devno)
+is_blacklisted (int ssid, int devno)
{
- return test_bit (devno, bl_dev);
+ return test_bit (devno, bl_dev[ssid]);
}
#ifdef CONFIG_PROC_FS
+static int
+__s390_redo_validation(struct subchannel_id schid, void *data)
+{
+ int ret;
+ struct subchannel *sch;
+
+ sch = get_subchannel_by_schid(schid);
+ if (sch) {
+ /* Already known. */
+ put_device(&sch->dev);
+ return 0;
+ }
+ ret = css_probe_device(schid);
+ if (ret == -ENXIO)
+ return ret; /* We're through. */
+ if (ret == -ENOMEM)
+ /* Stop validation for now. Bad, but no need for a panic. */
+ return ret;
+ return 0;
+}
+
/*
* Function: s390_redo_validation
* Look for no longer blacklisted devices
@@ -226,29 +253,9 @@ is_blacklisted (int devno)
static inline void
s390_redo_validation (void)
{
- unsigned int irq;
-
CIO_TRACE_EVENT (0, "redoval");
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- int ret;
- struct subchannel *sch;
-
- sch = get_subchannel_by_schid(irq);
- if (sch) {
- /* Already known. */
- put_device(&sch->dev);
- continue;
- }
- ret = css_probe_device(irq);
- if (ret == -ENXIO)
- break; /* We're through. */
- if (ret == -ENOMEM)
- /*
- * Stop validation for now. Bad, but no need for a
- * panic.
- */
- break;
- }
+
+ for_each_subchannel(__s390_redo_validation, NULL);
}
/*
@@ -278,41 +285,90 @@ blacklist_parse_proc_parameters (char *buf)
s390_redo_validation ();
}
-/* FIXME: These should be real bus ids and not home-grown ones! */
-static int cio_ignore_read (char *page, char **start, off_t off,
- int count, int *eof, void *data)
+/* Iterator struct for all devices. */
+struct ccwdev_iter {
+ int devno;
+ int ssid;
+ int in_range;
+};
+
+static void *
+cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
{
- const unsigned int entry_size = 18; /* "0.0.ABCD-0.0.EFGH\n" */
- long devno;
- int len;
-
- len = 0;
- for (devno = off; /* abuse the page variable
- * as counter, see fs/proc/generic.c */
- devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
- if (!test_bit(devno, bl_dev))
- continue;
- len += sprintf(page + len, "0.0.%04lx", devno);
- if (test_bit(devno + 1, bl_dev)) { /* print range */
- while (++devno < __MAX_SUBCHANNELS)
- if (!test_bit(devno, bl_dev))
- break;
- len += sprintf(page + len, "-0.0.%04lx", --devno);
- }
- len += sprintf(page + len, "\n");
- }
+ struct ccwdev_iter *iter;
+
+ if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+ return NULL;
+ iter = kzalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
+ if (!iter)
+ return ERR_PTR(-ENOMEM);
+ iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
+ iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
+ return iter;
+}
+
+static void
+cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
+{
+ if (!IS_ERR(it))
+ kfree(it);
+}
+
+static void *
+cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
+{
+ struct ccwdev_iter *iter;
+
+ if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+ return NULL;
+ iter = it;
+ if (iter->devno == __MAX_SUBCHANNEL) {
+ iter->devno = 0;
+ iter->ssid++;
+ if (iter->ssid > __MAX_SSID)
+ return NULL;
+ } else
+ iter->devno++;
+ (*offset)++;
+ return iter;
+}
- if (devno < __MAX_SUBCHANNELS)
- *eof = 1;
- *start = (char *) (devno - off); /* number of checked entries */
- return len;
+static int
+cio_ignore_proc_seq_show(struct seq_file *s, void *it)
+{
+ struct ccwdev_iter *iter;
+
+ iter = it;
+ if (!is_blacklisted(iter->ssid, iter->devno))
+ /* Not blacklisted, nothing to output. */
+ return 0;
+ if (!iter->in_range) {
+ /* First device in range. */
+ if ((iter->devno == __MAX_SUBCHANNEL) ||
+ !is_blacklisted(iter->ssid, iter->devno + 1))
+ /* Singular device. */
+ return seq_printf(s, "0.%x.%04x\n",
+ iter->ssid, iter->devno);
+ iter->in_range = 1;
+ return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno);
+ }
+ if ((iter->devno == __MAX_SUBCHANNEL) ||
+ !is_blacklisted(iter->ssid, iter->devno + 1)) {
+ /* Last device in range. */
+ iter->in_range = 0;
+ return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
+ }
+ return 0;
}
-static int cio_ignore_write(struct file *file, const char __user *user_buf,
- unsigned long user_len, void *data)
+static ssize_t
+cio_ignore_write(struct file *file, const char __user *user_buf,
+ size_t user_len, loff_t *offset)
{
char *buf;
+ if (*offset)
+ return -EINVAL;
if (user_len > 65536)
user_len = 65536;
buf = vmalloc (user_len + 1); /* maybe better use the stack? */
@@ -330,6 +386,27 @@ static int cio_ignore_write(struct file *file, const char __user *user_buf,
return user_len;
}
+static struct seq_operations cio_ignore_proc_seq_ops = {
+ .start = cio_ignore_proc_seq_start,
+ .stop = cio_ignore_proc_seq_stop,
+ .next = cio_ignore_proc_seq_next,
+ .show = cio_ignore_proc_seq_show,
+};
+
+static int
+cio_ignore_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &cio_ignore_proc_seq_ops);
+}
+
+static struct file_operations cio_ignore_proc_fops = {
+ .open = cio_ignore_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+ .write = cio_ignore_write,
+};
+
static int
cio_ignore_proc_init (void)
{
@@ -340,8 +417,7 @@ cio_ignore_proc_init (void)
if (!entry)
return 0;
- entry->read_proc = cio_ignore_read;
- entry->write_proc = cio_ignore_write;
+ entry->proc_fops = &cio_ignore_proc_fops;
return 1;
}
diff --git a/drivers/s390/cio/blacklist.h b/drivers/s390/cio/blacklist.h
index fb42cafbe57..95e25c1df92 100644
--- a/drivers/s390/cio/blacklist.h
+++ b/drivers/s390/cio/blacklist.h
@@ -1,6 +1,6 @@
#ifndef S390_BLACKLIST_H
#define S390_BLACKLIST_H
-extern int is_blacklisted (int devno);
+extern int is_blacklisted (int ssid, int devno);
#endif
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index be9d2d65c22..e849289d4f3 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
- * $Revision: 1.32 $
+ * $Revision: 1.33 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -263,7 +263,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev)
struct ccwgroup_driver *gdrv;
int ret;
- if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
return -EAGAIN;
if (gdev->state == CCWGROUP_ONLINE) {
ret = 0;
@@ -289,7 +289,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
struct ccwgroup_driver *gdrv;
int ret;
- if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
return -EAGAIN;
if (gdev->state == CCWGROUP_OFFLINE) {
ret = 0;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index fa3c23b80e3..7270808c02d 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.120 $
+ * $Revision: 1.126 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -24,8 +24,6 @@
#include "ioasm.h"
#include "chsc.h"
-static struct channel_path *chps[NR_CHPIDS];
-
static void *sei_page;
static int new_channel_path(int chpid);
@@ -33,13 +31,13 @@ static int new_channel_path(int chpid);
static inline void
set_chp_logically_online(int chp, int onoff)
{
- chps[chp]->state = onoff;
+ css[0]->chps[chp]->state = onoff;
}
static int
get_chp_status(int chp)
{
- return (chps[chp] ? chps[chp]->state : -ENODEV);
+ return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV);
}
void
@@ -77,7 +75,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
struct {
struct chsc_header request;
- u16 reserved1;
+ u16 reserved1a:10;
+ u16 ssid:2;
+ u16 reserved1b:4;
u16 f_sch; /* first subchannel */
u16 reserved2;
u16 l_sch; /* last subchannel */
@@ -104,8 +104,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
.code = 0x0004,
};
- ssd_area->f_sch = sch->irq;
- ssd_area->l_sch = sch->irq;
+ ssd_area->ssid = sch->schid.ssid;
+ ssd_area->f_sch = sch->schid.sch_no;
+ ssd_area->l_sch = sch->schid.sch_no;
ccode = chsc(ssd_area);
if (ccode > 0) {
@@ -147,7 +148,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
*/
if (ssd_area->st > 3) { /* uhm, that looks strange... */
CIO_CRW_EVENT(0, "Strange subchannel type %d"
- " for sch %04x\n", ssd_area->st, sch->irq);
+ " for sch 0.%x.%04x\n", ssd_area->st,
+ sch->schid.ssid, sch->schid.sch_no);
/*
* There may have been a new subchannel type defined in the
* time since this code was written; since we don't know which
@@ -156,8 +158,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
return 0;
} else {
const char *type[4] = {"I/O", "chsc", "message", "ADM"};
- CIO_CRW_EVENT(6, "ssd: sch %04x is %s subchannel\n",
- sch->irq, type[ssd_area->st]);
+ CIO_CRW_EVENT(6, "ssd: sch 0.%x.%04x is %s subchannel\n",
+ sch->schid.ssid, sch->schid.sch_no,
+ type[ssd_area->st]);
sch->ssd_info.valid = 1;
sch->ssd_info.type = ssd_area->st;
@@ -218,13 +221,13 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
int j;
int mask;
struct subchannel *sch;
- __u8 *chpid;
+ struct channel_path *chpid;
struct schib schib;
sch = to_subchannel(dev);
chpid = data;
for (j = 0; j < 8; j++)
- if (sch->schib.pmcw.chpid[j] == *chpid)
+ if (sch->schib.pmcw.chpid[j] == chpid->id)
break;
if (j >= 8)
return 0;
@@ -232,7 +235,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
mask = 0x80 >> j;
spin_lock(&sch->lock);
- stsch(sch->irq, &schib);
+ stsch(sch->schid, &schib);
if (!schib.pmcw.dnv)
goto out_unreg;
memcpy(&sch->schib, &schib, sizeof(struct schib));
@@ -284,7 +287,7 @@ out_unlock:
out_unreg:
spin_unlock(&sch->lock);
sch->lpm = 0;
- if (css_enqueue_subchannel_slow(sch->irq)) {
+ if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
@@ -295,23 +298,30 @@ static inline void
s390_set_chpid_offline( __u8 chpid)
{
char dbf_txt[15];
+ struct device *dev;
sprintf(dbf_txt, "chpr%x", chpid);
CIO_TRACE_EVENT(2, dbf_txt);
if (get_chp_status(chpid) <= 0)
return;
-
- bus_for_each_dev(&css_bus_type, NULL, &chpid,
+ dev = get_device(&css[0]->chps[chpid]->dev);
+ bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev),
s390_subchannel_remove_chpid);
if (need_rescan || css_slow_subchannels_exist())
queue_work(slow_path_wq, &slow_path_work);
+ put_device(dev);
}
+struct res_acc_data {
+ struct channel_path *chp;
+ u32 fla_mask;
+ u16 fla;
+};
+
static int
-s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
- struct subchannel *sch)
+s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch)
{
int found;
int chp;
@@ -323,8 +333,9 @@ s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
* check if chpid is in information updated by ssd
*/
if (sch->ssd_info.valid &&
- sch->ssd_info.chpid[chp] == chpid &&
- (sch->ssd_info.fla[chp] & fla_mask) == fla) {
+ sch->ssd_info.chpid[chp] == res_data->chp->id &&
+ (sch->ssd_info.fla[chp] & res_data->fla_mask)
+ == res_data->fla) {
found = 1;
break;
}
@@ -337,24 +348,87 @@ s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
* new path information and eventually check for logically
* offline chpids.
*/
- ccode = stsch(sch->irq, &sch->schib);
+ ccode = stsch(sch->schid, &sch->schib);
if (ccode > 0)
return 0;
return 0x80 >> chp;
}
+static inline int
+s390_process_res_acc_new_sch(struct subchannel_id schid)
+{
+ struct schib schib;
+ int ret;
+ /*
+ * We don't know the device yet, but since a path
+ * may be available now to the device we'll have
+ * to do recognition again.
+ * Since we don't have any idea about which chpid
+ * that beast may be on we'll have to do a stsch
+ * on all devices, grr...
+ */
+ if (stsch_err(schid, &schib))
+ /* We're through */
+ return need_rescan ? -EAGAIN : -ENXIO;
+
+ /* Put it on the slow path. */
+ ret = css_enqueue_subchannel_slow(schid);
+ if (ret) {
+ css_clear_subchannel_slow_list();
+ need_rescan = 1;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
static int
-s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
+__s390_process_res_acc(struct subchannel_id schid, void *data)
{
+ int chp_mask, old_lpm;
+ struct res_acc_data *res_data;
struct subchannel *sch;
- int irq, rc;
+
+ res_data = (struct res_acc_data *)data;
+ sch = get_subchannel_by_schid(schid);
+ if (!sch)
+ /* Check if a subchannel is newly available. */
+ return s390_process_res_acc_new_sch(schid);
+
+ spin_lock_irq(&sch->lock);
+
+ chp_mask = s390_process_res_acc_sch(res_data, sch);
+
+ if (chp_mask == 0) {
+ spin_unlock_irq(&sch->lock);
+ return 0;
+ }
+ old_lpm = sch->lpm;
+ sch->lpm = ((sch->schib.pmcw.pim &
+ sch->schib.pmcw.pam &
+ sch->schib.pmcw.pom)
+ | chp_mask) & sch->opm;
+ if (!old_lpm && sch->lpm)
+ device_trigger_reprobe(sch);
+ else if (sch->driver && sch->driver->verify)
+ sch->driver->verify(&sch->dev);
+
+ spin_unlock_irq(&sch->lock);
+ put_device(&sch->dev);
+ return (res_data->fla_mask == 0xffff) ? -ENODEV : 0;
+}
+
+
+static int
+s390_process_res_acc (struct res_acc_data *res_data)
+{
+ int rc;
char dbf_txt[15];
- sprintf(dbf_txt, "accpr%x", chpid);
+ sprintf(dbf_txt, "accpr%x", res_data->chp->id);
CIO_TRACE_EVENT( 2, dbf_txt);
- if (fla != 0) {
- sprintf(dbf_txt, "fla%x", fla);
+ if (res_data->fla != 0) {
+ sprintf(dbf_txt, "fla%x", res_data->fla);
CIO_TRACE_EVENT( 2, dbf_txt);
}
@@ -365,70 +439,11 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
* The more information we have (info), the less scanning
* will we have to do.
*/
-
- if (!get_chp_status(chpid))
- return 0; /* no need to do the rest */
-
- rc = 0;
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- int chp_mask, old_lpm;
-
- sch = get_subchannel_by_schid(irq);
- if (!sch) {
- struct schib schib;
- int ret;
- /*
- * We don't know the device yet, but since a path
- * may be available now to the device we'll have
- * to do recognition again.
- * Since we don't have any idea about which chpid
- * that beast may be on we'll have to do a stsch
- * on all devices, grr...
- */
- if (stsch(irq, &schib)) {
- /* We're through */
- if (need_rescan)
- rc = -EAGAIN;
- break;
- }
- if (need_rescan) {
- rc = -EAGAIN;
- continue;
- }
- /* Put it on the slow path. */
- ret = css_enqueue_subchannel_slow(irq);
- if (ret) {
- css_clear_subchannel_slow_list();
- need_rescan = 1;
- }
- rc = -EAGAIN;
- continue;
- }
-
- spin_lock_irq(&sch->lock);
-
- chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch);
-
- if (chp_mask == 0) {
-
- spin_unlock_irq(&sch->lock);
- continue;
- }
- old_lpm = sch->lpm;
- sch->lpm = ((sch->schib.pmcw.pim &
- sch->schib.pmcw.pam &
- sch->schib.pmcw.pom)
- | chp_mask) & sch->opm;
- if (!old_lpm && sch->lpm)
- device_trigger_reprobe(sch);
- else if (sch->driver && sch->driver->verify)
- sch->driver->verify(&sch->dev);
-
- spin_unlock_irq(&sch->lock);
- put_device(&sch->dev);
- if (fla_mask == 0xffff)
- break;
- }
+ rc = for_each_subchannel(__s390_process_res_acc, res_data);
+ if (css_slow_subchannels_exist())
+ rc = -EAGAIN;
+ else if (rc != -EAGAIN)
+ rc = 0;
return rc;
}
@@ -466,6 +481,7 @@ int
chsc_process_crw(void)
{
int chpid, ret;
+ struct res_acc_data res_data;
struct {
struct chsc_header request;
u32 reserved1;
@@ -499,8 +515,9 @@ chsc_process_crw(void)
ret = 0;
do {
int ccode, status;
+ struct device *dev;
memset(sei_area, 0, sizeof(*sei_area));
-
+ memset(&res_data, 0, sizeof(struct res_acc_data));
sei_area->request = (struct chsc_header) {
.length = 0x0010,
.code = 0x000e,
@@ -573,26 +590,25 @@ chsc_process_crw(void)
if (status < 0)
new_channel_path(sei_area->rsid);
else if (!status)
- return 0;
- if ((sei_area->vf & 0x80) == 0) {
- pr_debug("chpid: %x\n", sei_area->rsid);
- ret = s390_process_res_acc(sei_area->rsid,
- 0, 0);
- } else if ((sei_area->vf & 0xc0) == 0x80) {
- pr_debug("chpid: %x link addr: %x\n",
- sei_area->rsid, sei_area->fla);
- ret = s390_process_res_acc(sei_area->rsid,
- sei_area->fla,
- 0xff00);
- } else if ((sei_area->vf & 0xc0) == 0xc0) {
- pr_debug("chpid: %x full link addr: %x\n",
- sei_area->rsid, sei_area->fla);
- ret = s390_process_res_acc(sei_area->rsid,
- sei_area->fla,
- 0xffff);
+ break;
+ dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
+ res_data.chp = to_channelpath(dev);
+ pr_debug("chpid: %x", sei_area->rsid);
+ if ((sei_area->vf & 0xc0) != 0) {
+ res_data.fla = sei_area->fla;
+ if ((sei_area->vf & 0xc0) == 0xc0) {
+ pr_debug(" full link addr: %x",
+ sei_area->fla);
+ res_data.fla_mask = 0xffff;
+ } else {
+ pr_debug(" link addr: %x",
+ sei_area->fla);
+ res_data.fla_mask = 0xff00;
+ }
}
- pr_debug("\n");
-
+ ret = s390_process_res_acc(&res_data);
+ pr_debug("\n\n");
+ put_device(dev);
break;
default: /* other stuff */
@@ -604,12 +620,72 @@ chsc_process_crw(void)
return ret;
}
+static inline int
+__chp_add_new_sch(struct subchannel_id schid)
+{
+ struct schib schib;
+ int ret;
+
+ if (stsch(schid, &schib))
+ /* We're through */
+ return need_rescan ? -EAGAIN : -ENXIO;
+
+ /* Put it on the slow path. */
+ ret = css_enqueue_subchannel_slow(schid);
+ if (ret) {
+ css_clear_subchannel_slow_list();
+ need_rescan = 1;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+
static int
-chp_add(int chpid)
+__chp_add(struct subchannel_id schid, void *data)
{
+ int i;
+ struct channel_path *chp;
struct subchannel *sch;
- int irq, ret, rc;
+
+ chp = (struct channel_path *)data;
+ sch = get_subchannel_by_schid(schid);
+ if (!sch)
+ /* Check if the subchannel is now available. */
+ return __chp_add_new_sch(schid);
+ spin_lock(&sch->lock);
+ for (i=0; i<8; i++)
+ if (sch->schib.pmcw.chpid[i] == chp->id) {
+ if (stsch(sch->schid, &sch->schib) != 0) {
+ /* Endgame. */
+ spin_unlock(&sch->lock);
+ return -ENXIO;
+ }
+ break;
+ }
+ if (i==8) {
+ spin_unlock(&sch->lock);
+ return 0;
+ }
+ sch->lpm = ((sch->schib.pmcw.pim &
+ sch->schib.pmcw.pam &
+ sch->schib.pmcw.pom)
+ | 0x80 >> i) & sch->opm;
+
+ if (sch->driver && sch->driver->verify)
+ sch->driver->verify(&sch->dev);
+
+ spin_unlock(&sch->lock);
+ put_device(&sch->dev);
+ return 0;
+}
+
+static int
+chp_add(int chpid)
+{
+ int rc;
char dbf_txt[15];
+ struct device *dev;
if (!get_chp_status(chpid))
return 0; /* no need to do the rest */
@@ -617,59 +693,13 @@ chp_add(int chpid)
sprintf(dbf_txt, "cadd%x", chpid);
CIO_TRACE_EVENT(2, dbf_txt);
- rc = 0;
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- int i;
-
- sch = get_subchannel_by_schid(irq);
- if (!sch) {
- struct schib schib;
-
- if (stsch(irq, &schib)) {
- /* We're through */
- if (need_rescan)
- rc = -EAGAIN;
- break;
- }
- if (need_rescan) {
- rc = -EAGAIN;
- continue;
- }
- /* Put it on the slow path. */
- ret = css_enqueue_subchannel_slow(irq);
- if (ret) {
- css_clear_subchannel_slow_list();
- need_rescan = 1;
- }
- rc = -EAGAIN;
- continue;
- }
-
- spin_lock(&sch->lock);
- for (i=0; i<8; i++)
- if (sch->schib.pmcw.chpid[i] == chpid) {
- if (stsch(sch->irq, &sch->schib) != 0) {
- /* Endgame. */
- spin_unlock(&sch->lock);
- return rc;
- }
- break;
- }
- if (i==8) {
- spin_unlock(&sch->lock);
- return rc;
- }
- sch->lpm = ((sch->schib.pmcw.pim &
- sch->schib.pmcw.pam &
- sch->schib.pmcw.pom)
- | 0x80 >> i) & sch->opm;
-
- if (sch->driver && sch->driver->verify)
- sch->driver->verify(&sch->dev);
-
- spin_unlock(&sch->lock);
- put_device(&sch->dev);
- }
+ dev = get_device(&css[0]->chps[chpid]->dev);
+ rc = for_each_subchannel(__chp_add, to_channelpath(dev));
+ if (css_slow_subchannels_exist())
+ rc = -EAGAIN;
+ if (rc != -EAGAIN)
+ rc = 0;
+ put_device(dev);
return rc;
}
@@ -702,7 +732,7 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
if (!device_is_online(sch))
/* cio could be doing I/O. */
return 0;
- cc = stsch(sch->irq, &sch->schib);
+ cc = stsch(sch->schid, &sch->schib);
if (cc)
return 0;
if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
@@ -743,7 +773,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
* just varied off path. Then kill it.
*/
if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
- if (css_enqueue_subchannel_slow(sch->irq)) {
+ if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
@@ -781,6 +811,29 @@ s390_subchannel_vary_chpid_on(struct device *dev, void *data)
return 0;
}
+static int
+__s390_vary_chpid_on(struct subchannel_id schid, void *data)
+{
+ struct schib schib;
+ struct subchannel *sch;
+
+ sch = get_subchannel_by_schid(schid);
+ if (sch) {
+ put_device(&sch->dev);
+ return 0;
+ }
+ if (stsch_err(schid, &schib))
+ /* We're through */
+ return -ENXIO;
+ /* Put it on the slow path. */
+ if (css_enqueue_subchannel_slow(schid)) {
+ css_clear_subchannel_slow_list();
+ need_rescan = 1;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
/*
* Function: s390_vary_chpid
* Varies the specified chpid online or offline
@@ -789,8 +842,7 @@ static int
s390_vary_chpid( __u8 chpid, int on)
{
char dbf_text[15];
- int status, irq, ret;
- struct subchannel *sch;
+ int status;
sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid);
CIO_TRACE_EVENT( 2, dbf_text);
@@ -815,30 +867,9 @@ s390_vary_chpid( __u8 chpid, int on)
bus_for_each_dev(&css_bus_type, NULL, &chpid, on ?
s390_subchannel_vary_chpid_on :
s390_subchannel_vary_chpid_off);
- if (!on)
- goto out;
- /* Scan for new devices on varied on path. */
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- struct schib schib;
-
- if (need_rescan)
- break;
- sch = get_subchannel_by_schid(irq);
- if (sch) {
- put_device(&sch->dev);
- continue;
- }
- if (stsch(irq, &schib))
- /* We're through */
- break;
- /* Put it on the slow path. */
- ret = css_enqueue_subchannel_slow(irq);
- if (ret) {
- css_clear_subchannel_slow_list();
- need_rescan = 1;
- }
- }
-out:
+ if (on)
+ /* Scan for new devices on varied on path. */
+ for_each_subchannel(__s390_vary_chpid_on, NULL);
if (need_rescan || css_slow_subchannels_exist())
queue_work(slow_path_wq, &slow_path_work);
return 0;
@@ -995,7 +1026,7 @@ new_channel_path(int chpid)
chp->id = chpid;
chp->state = 1;
chp->dev = (struct device) {
- .parent = &css_bus_device,
+ .parent = &css[0]->device,
.release = chp_release,
};
snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
@@ -1017,7 +1048,7 @@ new_channel_path(int chpid)
device_unregister(&chp->dev);
goto out_free;
} else
- chps[chpid] = chp;
+ css[0]->chps[chpid] = chp;
return ret;
out_free:
kfree(chp);
@@ -1030,7 +1061,7 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
struct channel_path *chp;
struct channel_path_desc *desc;
- chp = chps[sch->schib.pmcw.chpid[chp_no]];
+ chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]];
if (!chp)
return NULL;
desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
@@ -1051,6 +1082,54 @@ chsc_alloc_sei_area(void)
return (sei_page ? 0 : -ENOMEM);
}
+int __init
+chsc_enable_facility(int operation_code)
+{
+ int ret;
+ struct {
+ struct chsc_header request;
+ u8 reserved1:4;
+ u8 format:4;
+ u8 reserved2;
+ u16 operation_code;
+ u32 reserved3;
+ u32 reserved4;
+ u32 operation_data_area[252];
+ struct chsc_header response;
+ u32 reserved5:4;
+ u32 format2:4;
+ u32 reserved6:24;
+ } *sda_area;
+
+ sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
+ if (!sda_area)
+ return -ENOMEM;
+ sda_area->request = (struct chsc_header) {
+ .length = 0x0400,
+ .code = 0x0031,
+ };
+ sda_area->operation_code = operation_code;
+
+ ret = chsc(sda_area);
+ if (ret > 0) {
+ ret = (ret == 3) ? -ENODEV : -EBUSY;
+ goto out;
+ }
+ switch (sda_area->response.code) {
+ case 0x0003: /* invalid request block */
+ case 0x0007:
+ ret = -EINVAL;
+ break;
+ case 0x0004: /* command not provided */
+ case 0x0101: /* facility not provided */
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ out:
+ free_page((unsigned long)sda_area);
+ return ret;
+}
+
subsys_initcall(chsc_alloc_sei_area);
struct css_general_char css_general_characteristics;
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index be20da49d14..44e4b4bb1c5 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -1,12 +1,12 @@
#ifndef S390_CHSC_H
#define S390_CHSC_H
-#define NR_CHPIDS 256
-
#define CHSC_SEI_ACC_CHPID 1
#define CHSC_SEI_ACC_LINKADDR 2
#define CHSC_SEI_ACC_FULLLINKADDR 3
+#define CHSC_SDA_OC_MSS 0x2
+
struct chsc_header {
u16 length;
u16 code;
@@ -43,7 +43,9 @@ struct css_general_char {
u32 ext_mb : 1; /* bit 48 */
u32 : 7;
u32 aif_tdd : 1; /* bit 56 */
- u32 : 10;
+ u32 : 1;
+ u32 qebsm : 1; /* bit 58 */
+ u32 : 8;
u32 aif_osa : 1; /* bit 67 */
u32 : 28;
}__attribute__((packed));
@@ -63,4 +65,9 @@ extern int chsc_determine_css_characteristics(void);
extern int css_characteristics_avail;
extern void *chsc_get_chp_desc(struct subchannel*, int);
+
+extern int chsc_enable_facility(int);
+
+#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
+
#endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 185bc73c3ec..7376bc87206 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.135 $
+ * $Revision: 1.138 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -135,7 +135,7 @@ cio_tpi(void)
return 0;
irb = (struct irb *) __LC_IRB;
/* Store interrupt response block to lowcore. */
- if (tsch (tpi_info->irq, irb) != 0)
+ if (tsch (tpi_info->schid, irb) != 0)
/* Not status pending or not operational. */
return 1;
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
@@ -163,10 +163,11 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
else
sch->lpm = 0;
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
- "subchannel %04x!\n", sch->irq);
+ "subchannel 0.%x.%04x!\n", sch->schid.ssid,
+ sch->schid.sch_no);
sprintf(dbf_text, "no%s", sch->dev.bus_id);
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -194,7 +195,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
sch->orb.spnd = sch->options.suspend;
sch->orb.ssic = sch->options.suspend && sch->options.inter;
sch->orb.lpm = (lpm != 0) ? (lpm & sch->opm) : sch->lpm;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
/*
* for 64 bit we always support 64 bit IDAWs with 4k page size only
*/
@@ -204,7 +205,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
sch->orb.key = key >> 4;
/* issue "Start Subchannel" */
sch->orb.cpa = (__u32) __pa (cpa);
- ccode = ssch (sch->irq, &sch->orb);
+ ccode = ssch (sch->schid, &sch->orb);
/* process condition code */
sprintf (dbf_txt, "ccode:%d", ccode);
@@ -243,7 +244,7 @@ cio_resume (struct subchannel *sch)
CIO_TRACE_EVENT (4, "resIO");
CIO_TRACE_EVENT (4, sch->dev.bus_id);
- ccode = rsch (sch->irq);
+ ccode = rsch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (4, dbf_txt);
@@ -283,7 +284,7 @@ cio_halt(struct subchannel *sch)
/*
* Issue "Halt subchannel" and process condition code
*/
- ccode = hsch (sch->irq);
+ ccode = hsch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (2, dbf_txt);
@@ -318,7 +319,7 @@ cio_clear(struct subchannel *sch)
/*
* Issue "Clear subchannel" and process condition code
*/
- ccode = csch (sch->irq);
+ ccode = csch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (2, dbf_txt);
@@ -351,7 +352,7 @@ cio_cancel (struct subchannel *sch)
CIO_TRACE_EVENT (2, "cancelIO");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
- ccode = xsch (sch->irq);
+ ccode = xsch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (2, dbf_txt);
@@ -359,7 +360,7 @@ cio_cancel (struct subchannel *sch)
switch (ccode) {
case 0: /* success */
/* Update information in scsw. */
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
return 0;
case 1: /* status pending */
return -EBUSY;
@@ -381,7 +382,7 @@ cio_modify (struct subchannel *sch)
ret = 0;
for (retry = 0; retry < 5; retry++) {
- ccode = msch_err (sch->irq, &sch->schib);
+ ccode = msch_err (sch->schid, &sch->schib);
if (ccode < 0) /* -EIO if msch gets a program check. */
return ccode;
switch (ccode) {
@@ -414,7 +415,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
CIO_TRACE_EVENT (2, "ensch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
- ccode = stsch (sch->irq, &sch->schib);
+ ccode = stsch (sch->schid, &sch->schib);
if (ccode)
return -ENODEV;
@@ -432,13 +433,13 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
*/
sch->schib.pmcw.csense = 0;
if (ret == 0) {
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
if (sch->schib.pmcw.ena)
break;
}
if (ret == -EBUSY) {
struct irb irb;
- if (tsch(sch->irq, &irb) != 0)
+ if (tsch(sch->schid, &irb) != 0)
break;
}
}
@@ -461,7 +462,7 @@ cio_disable_subchannel (struct subchannel *sch)
CIO_TRACE_EVENT (2, "dissch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
- ccode = stsch (sch->irq, &sch->schib);
+ ccode = stsch (sch->schid, &sch->schib);
if (ccode == 3) /* Not operational. */
return -ENODEV;
@@ -485,7 +486,7 @@ cio_disable_subchannel (struct subchannel *sch)
*/
break;
if (ret == 0) {
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
if (!sch->schib.pmcw.ena)
break;
}
@@ -508,12 +509,12 @@ cio_disable_subchannel (struct subchannel *sch)
* -ENODEV for subchannels with invalid device number or blacklisted devices
*/
int
-cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
+cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
{
char dbf_txt[15];
int ccode;
- sprintf (dbf_txt, "valsch%x", irq);
+ sprintf (dbf_txt, "valsch%x", schid.sch_no);
CIO_TRACE_EVENT (4, dbf_txt);
/* Nuke all fields. */
@@ -522,17 +523,20 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
spin_lock_init(&sch->lock);
/* Set a name for the subchannel */
- snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", irq);
+ snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
+ schid.sch_no);
/*
* The first subchannel that is not-operational (ccode==3)
* indicates that there aren't any more devices available.
+ * If stsch gets an exception, it means the current subchannel set
+ * is not valid.
*/
- sch->irq = irq;
- ccode = stsch (irq, &sch->schib);
+ ccode = stsch_err (schid, &sch->schib);
if (ccode)
- return -ENXIO;
+ return (ccode == 3) ? -ENXIO : ccode;
+ sch->schid = schid;
/* Copy subchannel type from path management control word. */
sch->st = sch->schib.pmcw.st;
@@ -541,9 +545,9 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
*/
if (sch->st != 0) {
CIO_DEBUG(KERN_INFO, 0,
- "Subchannel %04X reports "
+ "Subchannel 0.%x.%04x reports "
"non-I/O subchannel type %04X\n",
- sch->irq, sch->st);
+ sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */
return sch->st;
}
@@ -554,26 +558,29 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
return -ENODEV;
/* Devno is valid. */
- if (is_blacklisted (sch->schib.pmcw.dev)) {
+ if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
/*
* This device must not be known to Linux. So we simply
* say that there is no device and return ENODEV.
*/
CIO_MSG_EVENT(0, "Blacklisted device detected "
- "at devno %04X\n", sch->schib.pmcw.dev);
+ "at devno %04X, subchannel set %x\n",
+ sch->schib.pmcw.dev, sch->schid.ssid);
return -ENODEV;
}
sch->opm = 0xff;
- chsc_validate_chpids(sch);
+ if (!cio_is_console(sch->schid))
+ chsc_validate_chpids(sch);
sch->lpm = sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom &
sch->opm;
CIO_DEBUG(KERN_INFO, 0,
- "Detected device %04X on subchannel %04X"
+ "Detected device %04x on subchannel 0.%x.%04X"
" - PIM = %02X, PAM = %02X, POM = %02X\n",
- sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim,
+ sch->schib.pmcw.dev, sch->schid.ssid,
+ sch->schid.sch_no, sch->schib.pmcw.pim,
sch->schib.pmcw.pam, sch->schib.pmcw.pom);
/*
@@ -632,7 +639,7 @@ do_IRQ (struct pt_regs *regs)
if (sch)
spin_lock(&sch->lock);
/* Store interrupt response block to lowcore. */
- if (tsch (tpi_info->irq, irb) == 0 && sch) {
+ if (tsch (tpi_info->schid, irb) == 0 && sch) {
/* Keep subchannel information word up to date. */
memcpy (&sch->schib.scsw, &irb->scsw,
sizeof (irb->scsw));
@@ -691,28 +698,36 @@ wait_cons_dev (void)
}
static int
-cio_console_irq(void)
+cio_test_for_console(struct subchannel_id schid, void *data)
{
- int irq;
+ if (stsch_err(schid, &console_subchannel.schib) != 0)
+ return -ENXIO;
+ if (console_subchannel.schib.pmcw.dnv &&
+ console_subchannel.schib.pmcw.dev ==
+ console_devno) {
+ console_irq = schid.sch_no;
+ return 1; /* found */
+ }
+ return 0;
+}
+
+
+static int
+cio_get_console_sch_no(void)
+{
+ struct subchannel_id schid;
+ init_subchannel_id(&schid);
if (console_irq != -1) {
/* VM provided us with the irq number of the console. */
- if (stsch(console_irq, &console_subchannel.schib) != 0 ||
+ schid.sch_no = console_irq;
+ if (stsch(schid, &console_subchannel.schib) != 0 ||
!console_subchannel.schib.pmcw.dnv)
return -1;
console_devno = console_subchannel.schib.pmcw.dev;
} else if (console_devno != -1) {
/* At least the console device number is known. */
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- if (stsch(irq, &console_subchannel.schib) != 0)
- break;
- if (console_subchannel.schib.pmcw.dnv &&
- console_subchannel.schib.pmcw.dev ==
- console_devno) {
- console_irq = irq;
- break;
- }
- }
+ for_each_subchannel(cio_test_for_console, NULL);
if (console_irq == -1)
return -1;
} else {
@@ -728,17 +743,20 @@ cio_console_irq(void)
struct subchannel *
cio_probe_console(void)
{
- int irq, ret;
+ int sch_no, ret;
+ struct subchannel_id schid;
if (xchg(&console_subchannel_in_use, 1) != 0)
return ERR_PTR(-EBUSY);
- irq = cio_console_irq();
- if (irq == -1) {
+ sch_no = cio_get_console_sch_no();
+ if (sch_no == -1) {
console_subchannel_in_use = 0;
return ERR_PTR(-ENODEV);
}
memset(&console_subchannel, 0, sizeof(struct subchannel));
- ret = cio_validate_subchannel(&console_subchannel, irq);
+ init_subchannel_id(&schid);
+ schid.sch_no = sch_no;
+ ret = cio_validate_subchannel(&console_subchannel, schid);
if (ret) {
console_subchannel_in_use = 0;
return ERR_PTR(-ENODEV);
@@ -770,11 +788,11 @@ cio_release_console(void)
/* Bah... hack to catch console special sausages. */
int
-cio_is_console(int irq)
+cio_is_console(struct subchannel_id schid)
{
if (!console_subchannel_in_use)
return 0;
- return (irq == console_subchannel.irq);
+ return schid_equal(&schid, &console_subchannel.schid);
}
struct subchannel *
@@ -787,7 +805,7 @@ cio_get_console_subchannel(void)
#endif
static inline int
-__disable_subchannel_easy(unsigned int schid, struct schib *schib)
+__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
{
int retry, cc;
@@ -805,7 +823,7 @@ __disable_subchannel_easy(unsigned int schid, struct schib *schib)
}
static inline int
-__clear_subchannel_easy(unsigned int schid)
+__clear_subchannel_easy(struct subchannel_id schid)
{
int retry;
@@ -815,8 +833,8 @@ __clear_subchannel_easy(unsigned int schid)
struct tpi_info ti;
if (tpi(&ti)) {
- tsch(ti.irq, (struct irb *)__LC_IRB);
- if (ti.irq == schid)
+ tsch(ti.schid, (struct irb *)__LC_IRB);
+ if (schid_equal(&ti.schid, &schid))
return 0;
}
udelay(100);
@@ -825,31 +843,33 @@ __clear_subchannel_easy(unsigned int schid)
}
extern void do_reipl(unsigned long devno);
+static int
+__shutdown_subchannel_easy(struct subchannel_id schid, void *data)
+{
+ struct schib schib;
+
+ if (stsch_err(schid, &schib))
+ return -ENXIO;
+ if (!schib.pmcw.ena)
+ return 0;
+ switch(__disable_subchannel_easy(schid, &schib)) {
+ case 0:
+ case -ENODEV:
+ break;
+ default: /* -EBUSY */
+ if (__clear_subchannel_easy(schid))
+ break; /* give up... */
+ stsch(schid, &schib);
+ __disable_subchannel_easy(schid, &schib);
+ }
+ return 0;
+}
-/* Clear all subchannels. */
void
clear_all_subchannels(void)
{
- unsigned int schid;
-
local_irq_disable();
- for (schid=0;schid<=highest_subchannel;schid++) {
- struct schib schib;
- if (stsch(schid, &schib))
- break; /* break out of the loop */
- if (!schib.pmcw.ena)
- continue;
- switch(__disable_subchannel_easy(schid, &schib)) {
- case 0:
- case -ENODEV:
- break;
- default: /* -EBUSY */
- if (__clear_subchannel_easy(schid))
- break; /* give up... jump out of switch */
- stsch(schid, &schib);
- __disable_subchannel_easy(schid, &schib);
- }
- }
+ for_each_subchannel(__shutdown_subchannel_easy, NULL);
}
/* Make sure all subchannels are quiet before we re-ipl an lpar. */
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index c50a9da420a..0ca987344e0 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -1,6 +1,8 @@
#ifndef S390_CIO_H
#define S390_CIO_H
+#include "schid.h"
+
/*
* where we put the ssd info
*/
@@ -83,7 +85,7 @@ struct orb {
/* subchannel data structure used by I/O subroutines */
struct subchannel {
- unsigned int irq; /* aka. subchannel number */
+ struct subchannel_id schid;
spinlock_t lock; /* subchannel lock */
enum {
@@ -114,7 +116,7 @@ struct subchannel {
#define to_subchannel(n) container_of(n, struct subchannel, dev)
-extern int cio_validate_subchannel (struct subchannel *, unsigned int);
+extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
extern int cio_enable_subchannel (struct subchannel *, unsigned int);
extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *);
@@ -127,14 +129,15 @@ extern int cio_cancel (struct subchannel *);
extern int cio_set_options (struct subchannel *, int);
extern int cio_get_options (struct subchannel *);
extern int cio_modify (struct subchannel *);
+
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
extern struct subchannel *cio_probe_console(void);
extern void cio_release_console(void);
-extern int cio_is_console(int irq);
+extern int cio_is_console(struct subchannel_id);
extern struct subchannel *cio_get_console_subchannel(void);
#else
-#define cio_is_console(irq) 0
+#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
#endif
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index b978f7fe832..0b03714e696 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $)
*
* Linux on zSeries Channel Measurement Facility support
*
@@ -178,7 +178,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
/* msch can silently fail, so do it again if necessary */
for (retry = 0; retry < 3; retry++) {
/* prepare schib */
- stsch(sch->irq, schib);
+ stsch(sch->schid, schib);
schib->pmcw.mme = mme;
schib->pmcw.mbfc = mbfc;
/* address can be either a block address or a block index */
@@ -188,7 +188,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
schib->pmcw.mbi = address;
/* try to submit it */
- switch(ret = msch_err(sch->irq, schib)) {
+ switch(ret = msch_err(sch->schid, schib)) {
case 0:
break;
case 1:
@@ -202,7 +202,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
ret = -EINVAL;
break;
}
- stsch(sch->irq, schib); /* restore the schib */
+ stsch(sch->schid, schib); /* restore the schib */
if (ret)
break;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 555119cacc2..e565193650c 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
- * $Revision: 1.85 $
+ * $Revision: 1.93 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -21,19 +21,35 @@
#include "ioasm.h"
#include "chsc.h"
-unsigned int highest_subchannel;
int need_rescan = 0;
int css_init_done = 0;
+static int max_ssid = 0;
+
+struct channel_subsystem *css[__MAX_CSSID + 1];
-struct pgid global_pgid;
int css_characteristics_avail = 0;
-struct device css_bus_device = {
- .bus_id = "css0",
-};
+inline int
+for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
+{
+ struct subchannel_id schid;
+ int ret;
+
+ init_subchannel_id(&schid);
+ ret = -ENODEV;
+ do {
+ do {
+ ret = fn(schid, data);
+ if (ret)
+ break;
+ } while (schid.sch_no++ < __MAX_SUBCHANNEL);
+ schid.sch_no = 0;
+ } while (schid.ssid++ < max_ssid);
+ return ret;
+}
static struct subchannel *
-css_alloc_subchannel(int irq)
+css_alloc_subchannel(struct subchannel_id schid)
{
struct subchannel *sch;
int ret;
@@ -41,13 +57,11 @@ css_alloc_subchannel(int irq)
sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
if (sch == NULL)
return ERR_PTR(-ENOMEM);
- ret = cio_validate_subchannel (sch, irq);
+ ret = cio_validate_subchannel (sch, schid);
if (ret < 0) {
kfree(sch);
return ERR_PTR(ret);
}
- if (irq > highest_subchannel)
- highest_subchannel = irq;
if (sch->st != SUBCHANNEL_TYPE_IO) {
/* For now we ignore all non-io subchannels. */
@@ -87,7 +101,7 @@ css_subchannel_release(struct device *dev)
struct subchannel *sch;
sch = to_subchannel(dev);
- if (!cio_is_console(sch->irq))
+ if (!cio_is_console(sch->schid))
kfree(sch);
}
@@ -99,7 +113,7 @@ css_register_subchannel(struct subchannel *sch)
int ret;
/* Initialize the subchannel structure */
- sch->dev.parent = &css_bus_device;
+ sch->dev.parent = &css[0]->device;
sch->dev.bus = &css_bus_type;
sch->dev.release = &css_subchannel_release;
@@ -114,12 +128,12 @@ css_register_subchannel(struct subchannel *sch)
}
int
-css_probe_device(int irq)
+css_probe_device(struct subchannel_id schid)
{
int ret;
struct subchannel *sch;
- sch = css_alloc_subchannel(irq);
+ sch = css_alloc_subchannel(schid);
if (IS_ERR(sch))
return PTR_ERR(sch);
ret = css_register_subchannel(sch);
@@ -132,26 +146,26 @@ static int
check_subchannel(struct device * dev, void * data)
{
struct subchannel *sch;
- int irq = (unsigned long)data;
+ struct subchannel_id *schid = data;
sch = to_subchannel(dev);
- return (sch->irq == irq);
+ return schid_equal(&sch->schid, schid);
}
struct subchannel *
-get_subchannel_by_schid(int irq)
+get_subchannel_by_schid(struct subchannel_id schid)
{
struct device *dev;
dev = bus_find_device(&css_bus_type, NULL,
- (void *)(unsigned long)irq, check_subchannel);
+ (void *)&schid, check_subchannel);
return dev ? to_subchannel(dev) : NULL;
}
static inline int
-css_get_subchannel_status(struct subchannel *sch, int schid)
+css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid)
{
struct schib schib;
int cc;
@@ -170,13 +184,13 @@ css_get_subchannel_status(struct subchannel *sch, int schid)
}
static int
-css_evaluate_subchannel(int irq, int slow)
+css_evaluate_subchannel(struct subchannel_id schid, int slow)
{
int event, ret, disc;
struct subchannel *sch;
unsigned long flags;
- sch = get_subchannel_by_schid(irq);
+ sch = get_subchannel_by_schid(schid);
disc = sch ? device_is_disconnected(sch) : 0;
if (disc && slow) {
if (sch)
@@ -194,9 +208,10 @@ css_evaluate_subchannel(int irq, int slow)
put_device(&sch->dev);
return -EAGAIN; /* Will be done on the slow path. */
}
- event = css_get_subchannel_status(sch, irq);
- CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n",
- irq, event, sch?(disc?"disconnected":"normal"):"unknown",
+ event = css_get_subchannel_status(sch, schid);
+ CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
+ schid.ssid, schid.sch_no, event,
+ sch?(disc?"disconnected":"normal"):"unknown",
slow?"slow":"fast");
switch (event) {
case CIO_NO_PATH:
@@ -253,7 +268,7 @@ css_evaluate_subchannel(int irq, int slow)
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
put_device(&sch->dev);
- ret = css_probe_device(irq);
+ ret = css_probe_device(schid);
} else {
/*
* We can't immediately deregister the disconnected
@@ -272,7 +287,7 @@ css_evaluate_subchannel(int irq, int slow)
device_trigger_reprobe(sch);
spin_unlock_irqrestore(&sch->lock, flags);
}
- ret = sch ? 0 : css_probe_device(irq);
+ ret = sch ? 0 : css_probe_device(schid);
break;
default:
BUG();
@@ -281,28 +296,15 @@ css_evaluate_subchannel(int irq, int slow)
return ret;
}
-static void
-css_rescan_devices(void)
+static int
+css_rescan_devices(struct subchannel_id schid, void *data)
{
- int irq, ret;
-
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- ret = css_evaluate_subchannel(irq, 1);
- /* No more memory. It doesn't make sense to continue. No
- * panic because this can happen in midflight and just
- * because we can't use a new device is no reason to crash
- * the system. */
- if (ret == -ENOMEM)
- break;
- /* -ENXIO indicates that there are no more subchannels. */
- if (ret == -ENXIO)
- break;
- }
+ return css_evaluate_subchannel(schid, 1);
}
struct slow_subchannel {
struct list_head slow_list;
- unsigned long schid;
+ struct subchannel_id schid;
};
static LIST_HEAD(slow_subchannels_head);
@@ -315,7 +317,7 @@ css_trigger_slow_path(void)
if (need_rescan) {
need_rescan = 0;
- css_rescan_devices();
+ for_each_subchannel(css_rescan_devices, NULL);
return;
}
@@ -354,23 +356,31 @@ css_reiterate_subchannels(void)
* Called from the machine check handler for subchannel report words.
*/
int
-css_process_crw(int irq)
+css_process_crw(int rsid1, int rsid2)
{
int ret;
+ struct subchannel_id mchk_schid;
- CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
+ CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
+ rsid1, rsid2);
if (need_rescan)
/* We need to iterate all subchannels anyway. */
return -EAGAIN;
+
+ init_subchannel_id(&mchk_schid);
+ mchk_schid.sch_no = rsid1;
+ if (rsid2 != 0)
+ mchk_schid.ssid = (rsid2 >> 8) & 3;
+
/*
* Since we are always presented with IPI in the CRW, we have to
* use stsch() to find out if the subchannel in question has come
* or gone.
*/
- ret = css_evaluate_subchannel(irq, 0);
+ ret = css_evaluate_subchannel(mchk_schid, 0);
if (ret == -EAGAIN) {
- if (css_enqueue_subchannel_slow(irq)) {
+ if (css_enqueue_subchannel_slow(mchk_schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
@@ -378,22 +388,83 @@ css_process_crw(int irq)
return ret;
}
-static void __init
-css_generate_pgid(void)
+static int __init
+__init_channel_subsystem(struct subchannel_id schid, void *data)
{
- /* Let's build our path group ID here. */
- if (css_characteristics_avail && css_general_characteristics.mcss)
- global_pgid.cpu_addr = 0x8000;
+ struct subchannel *sch;
+ int ret;
+
+ if (cio_is_console(schid))
+ sch = cio_get_console_subchannel();
else {
+ sch = css_alloc_subchannel(schid);
+ if (IS_ERR(sch))
+ ret = PTR_ERR(sch);
+ else
+ ret = 0;
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOMEM:
+ panic("Out of memory in init_channel_subsystem\n");
+ /* -ENXIO: no more subchannels. */
+ case -ENXIO:
+ return ret;
+ default:
+ return 0;
+ }
+ }
+ /*
+ * We register ALL valid subchannels in ioinfo, even those
+ * that have been present before init_channel_subsystem.
+ * These subchannels can't have been registered yet (kmalloc
+ * not working) so we do it now. This is true e.g. for the
+ * console subchannel.
+ */
+ css_register_subchannel(sch);
+ return 0;
+}
+
+static void __init
+css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
+{
+ if (css_characteristics_avail && css_general_characteristics.mcss) {
+ css->global_pgid.pgid_high.ext_cssid.version = 0x80;
+ css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
+ } else {
#ifdef CONFIG_SMP
- global_pgid.cpu_addr = hard_smp_processor_id();
+ css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id();
#else
- global_pgid.cpu_addr = 0;
+ css->global_pgid.pgid_high.cpu_addr = 0;
#endif
}
- global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
- global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
- global_pgid.tod_high = (__u32) (get_clock() >> 32);
+ css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
+ css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
+ css->global_pgid.tod_high = tod_high;
+
+}
+
+static void
+channel_subsystem_release(struct device *dev)
+{
+ struct channel_subsystem *css;
+
+ css = to_css(dev);
+ kfree(css);
+}
+
+static inline void __init
+setup_css(int nr)
+{
+ u32 tod_high;
+
+ memset(css[nr], 0, sizeof(struct channel_subsystem));
+ css[nr]->valid = 1;
+ css[nr]->cssid = nr;
+ sprintf(css[nr]->device.bus_id, "css%x", nr);
+ css[nr]->device.release = channel_subsystem_release;
+ tod_high = (u32) (get_clock() >> 32);
+ css_generate_pgid(css[nr], tod_high);
}
/*
@@ -404,53 +475,50 @@ css_generate_pgid(void)
static int __init
init_channel_subsystem (void)
{
- int ret, irq;
+ int ret, i;
if (chsc_determine_css_characteristics() == 0)
css_characteristics_avail = 1;
- css_generate_pgid();
-
if ((ret = bus_register(&css_bus_type)))
goto out;
- if ((ret = device_register (&css_bus_device)))
- goto out_bus;
+ /* Try to enable MSS. */
+ ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
+ switch (ret) {
+ case 0: /* Success. */
+ max_ssid = __MAX_SSID;
+ break;
+ case -ENOMEM:
+ goto out_bus;
+ default:
+ max_ssid = 0;
+ }
+ /* Setup css structure. */
+ for (i = 0; i <= __MAX_CSSID; i++) {
+ css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
+ if (!css[i]) {
+ ret = -ENOMEM;
+ goto out_unregister;
+ }
+ setup_css(i);
+ ret = device_register(&css[i]->device);
+ if (ret)
+ goto out_free;
+ }
css_init_done = 1;
ctl_set_bit(6, 28);
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- struct subchannel *sch;
-
- if (cio_is_console(irq))
- sch = cio_get_console_subchannel();
- else {
- sch = css_alloc_subchannel(irq);
- if (IS_ERR(sch))
- ret = PTR_ERR(sch);
- else
- ret = 0;
- if (ret == -ENOMEM)
- panic("Out of memory in "
- "init_channel_subsystem\n");
- /* -ENXIO: no more subchannels. */
- if (ret == -ENXIO)
- break;
- if (ret)
- continue;
- }
- /*
- * We register ALL valid subchannels in ioinfo, even those
- * that have been present before init_channel_subsystem.
- * These subchannels can't have been registered yet (kmalloc
- * not working) so we do it now. This is true e.g. for the
- * console subchannel.
- */
- css_register_subchannel(sch);
- }
+ for_each_subchannel(__init_channel_subsystem, NULL);
return 0;
-
+out_free:
+ kfree(css[i]);
+out_unregister:
+ while (i > 0) {
+ i--;
+ device_unregister(&css[i]->device);
+ }
out_bus:
bus_unregister(&css_bus_type);
out:
@@ -481,47 +549,8 @@ struct bus_type css_bus_type = {
subsys_initcall(init_channel_subsystem);
-/*
- * Register root devices for some drivers. The release function must not be
- * in the device drivers, so we do it here.
- */
-static void
-s390_root_dev_release(struct device *dev)
-{
- kfree(dev);
-}
-
-struct device *
-s390_root_dev_register(const char *name)
-{
- struct device *dev;
- int ret;
-
- if (!strlen(name))
- return ERR_PTR(-EINVAL);
- dev = kmalloc(sizeof(struct device), GFP_KERNEL);
- if (!dev)
- return ERR_PTR(-ENOMEM);
- memset(dev, 0, sizeof(struct device));
- strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
- dev->release = s390_root_dev_release;
- ret = device_register(dev);
- if (ret) {
- kfree(dev);
- return ERR_PTR(ret);
- }
- return dev;
-}
-
-void
-s390_root_dev_unregister(struct device *dev)
-{
- if (dev)
- device_unregister(dev);
-}
-
int
-css_enqueue_subchannel_slow(unsigned long schid)
+css_enqueue_subchannel_slow(struct subchannel_id schid)
{
struct slow_subchannel *new_slow_sch;
unsigned long flags;
@@ -564,6 +593,4 @@ css_slow_subchannels_exist(void)
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(css_bus_type);
-EXPORT_SYMBOL(s390_root_dev_register);
-EXPORT_SYMBOL(s390_root_dev_unregister);
EXPORT_SYMBOL_GPL(css_characteristics_avail);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 2004a6c4938..251ebd7a7d3 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -6,6 +6,8 @@
#include <asm/cio.h>
+#include "schid.h"
+
/*
* path grouping stuff
*/
@@ -33,19 +35,25 @@ struct path_state {
__u8 resvd : 3; /* reserved */
} __attribute__ ((packed));
+struct extended_cssid {
+ u8 version;
+ u8 cssid;
+} __attribute__ ((packed));
+
struct pgid {
union {
__u8 fc; /* SPID function code */
struct path_state ps; /* SNID path state */
} inf;
- __u32 cpu_addr : 16; /* CPU address */
+ union {
+ __u32 cpu_addr : 16; /* CPU address */
+ struct extended_cssid ext_cssid;
+ } pgid_high;
__u32 cpu_id : 24; /* CPU identification */
__u32 cpu_model : 16; /* CPU model */
__u32 tod_high; /* high word TOD clock */
} __attribute__ ((packed));
-extern struct pgid global_pgid;
-
#define MAX_CIWS 8
/*
@@ -68,7 +76,8 @@ struct ccw_device_private {
atomic_t onoff;
unsigned long registered;
__u16 devno; /* device number */
- __u16 irq; /* subchannel number */
+ __u16 sch_no; /* subchannel number */
+ __u8 ssid; /* subchannel set id */
__u8 imask; /* lpm mask for SNID/SID/SPGID */
int iretry; /* retry counter SNID/SID/SPGID */
struct {
@@ -121,15 +130,27 @@ struct css_driver {
extern struct bus_type css_bus_type;
extern struct css_driver io_subchannel_driver;
-int css_probe_device(int irq);
-extern struct subchannel * get_subchannel_by_schid(int irq);
-extern unsigned int highest_subchannel;
+extern int css_probe_device(struct subchannel_id);
+extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
-
-#define __MAX_SUBCHANNELS 65536
+extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
+
+#define __MAX_SUBCHANNEL 65535
+#define __MAX_SSID 3
+#define __MAX_CHPID 255
+#define __MAX_CSSID 0
+
+struct channel_subsystem {
+ u8 cssid;
+ int valid;
+ struct channel_path *chps[__MAX_CHPID];
+ struct device device;
+ struct pgid global_pgid;
+};
+#define to_css(dev) container_of(dev, struct channel_subsystem, device)
extern struct bus_type css_bus_type;
-extern struct device css_bus_device;
+extern struct channel_subsystem *css[];
/* Some helper functions for disconnected state. */
int device_is_disconnected(struct subchannel *);
@@ -144,7 +165,7 @@ void device_set_waiting(struct subchannel *);
void device_kill_pending_timer(struct subchannel *);
/* Helper functions to build lists for the slow path. */
-int css_enqueue_subchannel_slow(unsigned long schid);
+extern int css_enqueue_subchannel_slow(struct subchannel_id schid);
void css_walk_subchannel_slow_list(void (*fn)(unsigned long));
void css_clear_subchannel_slow_list(void);
int css_slow_subchannels_exist(void);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 85908cacc3b..fa3e4c0a253 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
- * $Revision: 1.131 $
+ * $Revision: 1.137 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -374,7 +374,7 @@ online_store (struct device *dev, struct device_attribute *attr, const char *buf
int i, force, ret;
char *tmp;
- if (atomic_compare_and_swap(0, 1, &cdev->private->onoff))
+ if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
return -EAGAIN;
if (cdev->drv && !try_module_get(cdev->drv->owner)) {
@@ -535,7 +535,8 @@ ccw_device_register(struct ccw_device *cdev)
}
struct match_data {
- unsigned int devno;
+ unsigned int devno;
+ unsigned int ssid;
struct ccw_device * sibling;
};
@@ -548,6 +549,7 @@ match_devno(struct device * dev, void * data)
cdev = to_ccwdev(dev);
if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
(cdev->private->devno == d->devno) &&
+ (cdev->private->ssid == d->ssid) &&
(cdev != d->sibling)) {
cdev->private->state = DEV_STATE_NOT_OPER;
return 1;
@@ -556,11 +558,13 @@ match_devno(struct device * dev, void * data)
}
static struct ccw_device *
-get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
+get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
+ struct ccw_device *sibling)
{
struct device *dev;
struct match_data data = {
- .devno = devno,
+ .devno = devno,
+ .ssid = ssid,
.sibling = sibling,
};
@@ -616,13 +620,13 @@ ccw_device_do_unreg_rereg(void *data)
need_rename = 1;
other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev,
- cdev);
+ sch->schid.ssid, cdev);
if (other_cdev) {
struct subchannel *other_sch;
other_sch = to_subchannel(other_cdev->dev.parent);
if (get_device(&other_sch->dev)) {
- stsch(other_sch->irq, &other_sch->schib);
+ stsch(other_sch->schid, &other_sch->schib);
if (other_sch->schib.pmcw.dnv) {
other_sch->schib.pmcw.intparm = 0;
cio_modify(other_sch);
@@ -639,8 +643,8 @@ ccw_device_do_unreg_rereg(void *data)
if (test_and_clear_bit(1, &cdev->private->registered))
device_del(&cdev->dev);
if (need_rename)
- snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
- sch->schib.pmcw.dev);
+ snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
+ sch->schid.ssid, sch->schib.pmcw.dev);
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_add_changed, (void *)cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -769,18 +773,20 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
sch->dev.driver_data = cdev;
sch->driver = &io_subchannel_driver;
cdev->ccwlock = &sch->lock;
+
/* Init private data. */
priv = cdev->private;
priv->devno = sch->schib.pmcw.dev;
- priv->irq = sch->irq;
+ priv->ssid = sch->schid.ssid;
+ priv->sch_no = sch->schid.sch_no;
priv->state = DEV_STATE_NOT_OPER;
INIT_LIST_HEAD(&priv->cmb_list);
init_waitqueue_head(&priv->wait_q);
init_timer(&priv->timer);
/* Set an initial name for the device. */
- snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
- sch->schib.pmcw.dev);
+ snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
+ sch->schid.ssid, sch->schib.pmcw.dev);
/* Increase counter of devices currently in recognition. */
atomic_inc(&ccw_device_init_count);
@@ -951,7 +957,7 @@ io_subchannel_shutdown(struct device *dev)
sch = to_subchannel(dev);
cdev = dev->driver_data;
- if (cio_is_console(sch->irq))
+ if (cio_is_console(sch->schid))
return;
if (!sch->schib.pmcw.ena)
/* Nothing to do. */
@@ -986,10 +992,6 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
cdev->dev = (struct device) {
.parent = &sch->dev,
};
- /* Initialize the subchannel structure */
- sch->dev.parent = &css_bus_device;
- sch->dev.bus = &css_bus_type;
-
rc = io_subchannel_recog(cdev, sch);
if (rc)
return rc;
@@ -1146,6 +1148,16 @@ ccw_driver_unregister (struct ccw_driver *cdriver)
driver_unregister(&cdriver->driver);
}
+/* Helper func for qdio. */
+struct subchannel_id
+ccw_device_get_subchannel_id(struct ccw_device *cdev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(cdev->dev.parent);
+ return sch->schid;
+}
+
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccw_device_set_online);
EXPORT_SYMBOL(ccw_device_set_offline);
@@ -1155,3 +1167,4 @@ EXPORT_SYMBOL(get_ccwdev_by_busid);
EXPORT_SYMBOL(ccw_bus_type);
EXPORT_SYMBOL(ccw_device_work);
EXPORT_SYMBOL(ccw_device_notify_work);
+EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index a3aa056d724..11587ebb728 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -110,6 +110,7 @@ int ccw_device_stlck(struct ccw_device *);
/* qdio needs this. */
void ccw_device_set_timeout(struct ccw_device *, int);
+extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
void retry_set_schib(struct ccw_device *cdev);
#endif
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index c1c89f4fd4e..23d12b65e5f 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -133,7 +133,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
int ret;
sch = to_subchannel(cdev->dev.parent);
- ret = stsch(sch->irq, &sch->schib);
+ ret = stsch(sch->schid, &sch->schib);
if (ret || !sch->schib.pmcw.dnv)
return -ENODEV;
if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0)
@@ -231,7 +231,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
* through ssch() and the path information is up to date.
*/
old_lpm = sch->lpm;
- stsch(sch->irq, &sch->schib);
+ stsch(sch->schid, &sch->schib);
sch->lpm = sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom &
@@ -257,8 +257,9 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
switch (state) {
case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : unknown device %04x on subchannel %04x\n",
- cdev->private->devno, sch->irq);
+ "SenseID : unknown device %04x on subchannel "
+ "0.%x.%04x\n", cdev->private->devno,
+ sch->schid.ssid, sch->schid.sch_no);
break;
case DEV_STATE_OFFLINE:
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
@@ -282,16 +283,18 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
return;
}
/* Issue device info message. */
- CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: "
+ CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
"CU Type/Mod = %04X/%02X, Dev Type/Mod = "
- "%04X/%02X\n", cdev->private->devno,
+ "%04X/%02X\n",
+ cdev->private->ssid, cdev->private->devno,
cdev->id.cu_type, cdev->id.cu_model,
cdev->id.dev_type, cdev->id.dev_model);
break;
case DEV_STATE_BOXED:
CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : boxed device %04x on subchannel %04x\n",
- cdev->private->devno, sch->irq);
+ "SenseID : boxed device %04x on subchannel "
+ "0.%x.%04x\n", cdev->private->devno,
+ sch->schid.ssid, sch->schid.sch_no);
break;
}
cdev->private->state = state;
@@ -359,7 +362,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED)
CIO_DEBUG(KERN_WARNING, 2,
"Boxed device %04x on subchannel %04x\n",
- cdev->private->devno, sch->irq);
+ cdev->private->devno, sch->schid.sch_no);
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
@@ -592,7 +595,7 @@ ccw_device_offline(struct ccw_device *cdev)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- if (stsch(sch->irq, &sch->schib) || !sch->schib.pmcw.dnv)
+ if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE) {
if (sch->schib.scsw.actl != 0)
@@ -711,7 +714,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
* Since we might not just be coming from an interrupt from the
* subchannel we have to update the schib.
*/
- stsch(sch->irq, &sch->schib);
+ stsch(sch->schid, &sch->schib);
if (sch->schib.scsw.actl != 0 ||
(cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
@@ -923,7 +926,7 @@ ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event)
/* Iff device is idle, reset timeout. */
sch = to_subchannel(cdev->dev.parent);
- if (!stsch(sch->irq, &sch->schib))
+ if (!stsch(sch->schid, &sch->schib))
if (sch->schib.scsw.actl == 0)
ccw_device_set_timeout(cdev, 0);
/* Call the handler. */
@@ -1035,7 +1038,7 @@ device_trigger_reprobe(struct subchannel *sch)
return;
/* Update some values. */
- if (stsch(sch->irq, &sch->schib))
+ if (stsch(sch->schid, &sch->schib))
return;
/*
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 0e68fb511dc..04ceba343db 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,7 @@
/*
* diag210 is used under VM to get information about a virtual device
*/
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
int
diag210(struct diag210 * addr)
{
@@ -256,16 +256,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
* sense id information. So, for intervention required,
* we use the "whack it until it talks" strategy...
*/
- CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x "
- "reports cmd reject\n",
- cdev->private->devno, sch->irq);
+ CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
+ "0.%x.%04x reports cmd reject\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no);
return -EOPNOTSUPP;
}
if (irb->esw.esw0.erw.cons) {
- CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, "
+ CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, "
"lpum %02X, cnt %02d, sns :"
" %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->devno,
+ cdev->private->ssid, cdev->private->devno,
irb->esw.esw0.sublog.lpum,
irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
@@ -277,16 +278,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
if (irb->scsw.cc == 3) {
if ((sch->orb.lpm &
sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
- CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on"
- " subchannel %04x is 'not operational'\n",
- sch->orb.lpm, cdev->private->devno,
- sch->irq);
+ CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
+ "on subchannel 0.%x.%04x is "
+ "'not operational'\n", sch->orb.lpm,
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no);
return -EACCES;
}
/* Hmm, whatever happened, try again. */
CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
- "subchannel %04x returns status %02X%02X\n",
- cdev->private->devno, sch->irq,
+ "subchannel 0.%x.%04x returns status %02X%02X\n",
+ cdev->private->devno, sch->schid.ssid, sch->schid.sch_no,
irb->scsw.dstat, irb->scsw.cstat);
return -EAGAIN;
}
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 85a3026e690..143b6c25a4e 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.57 $
+ * $Revision: 1.58 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -570,7 +570,7 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
int
_ccw_device_get_subchannel_number(struct ccw_device *cdev)
{
- return cdev->private->irq;
+ return cdev->private->sch_no;
}
int
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 0adac8a6733..052832d03d3 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -22,6 +22,7 @@
#include "cio_debug.h"
#include "css.h"
#include "device.h"
+#include "ioasm.h"
/*
* Start Sense Path Group ID helper function. Used in ccw_device_recog
@@ -56,10 +57,10 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
if (ret != -EACCES)
return ret;
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not "
+ "0.%x.%04x, lpm %02X, became 'not "
"operational'\n",
- cdev->private->devno, sch->irq,
- cdev->private->imask);
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
}
cdev->private->imask >>= 1;
@@ -105,10 +106,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
return -EOPNOTSUPP;
}
if (irb->esw.esw0.erw.cons) {
- CIO_MSG_EVENT(2, "SNID - device %04x, unit check, "
+ CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
"lpum %02X, cnt %02d, sns : "
"%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->devno,
+ cdev->private->ssid, cdev->private->devno,
irb->esw.esw0.sublog.lpum,
irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
@@ -118,15 +119,17 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
return -EAGAIN;
}
if (irb->scsw.cc == 3) {
- CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->irq, sch->orb.lpm);
+ CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
+ " lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, sch->orb.lpm);
return -EACCES;
}
if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
- CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x "
+ CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
"is reserved by someone else\n",
- cdev->private->devno, sch->irq);
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no);
return -EUSERS;
}
return 0;
@@ -162,7 +165,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
case 0: /* Sense Path Group ID successful. */
if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
- memcpy(&cdev->private->pgid, &global_pgid,
+ memcpy(&cdev->private->pgid, &css[0]->global_pgid,
sizeof(struct pgid));
ccw_device_sense_pgid_done(cdev, 0);
break;
@@ -235,8 +238,9 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
sch->lpm &= ~cdev->private->imask;
sch->vpm &= ~cdev->private->imask;
CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->irq, cdev->private->imask);
+ "0.%x.%04x, lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
return ret;
}
@@ -258,8 +262,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
if (irb->ecw[0] & SNS0_CMD_REJECT)
return -EOPNOTSUPP;
/* Hmm, whatever happened, try again. */
- CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, "
+ CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
+ "cnt %02d, "
"sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
+ cdev->private->ssid,
cdev->private->devno, irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
irb->ecw[2], irb->ecw[3],
@@ -268,10 +274,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
return -EAGAIN;
}
if (irb->scsw.cc == 3) {
- CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->irq,
- cdev->private->imask);
+ CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
+ " lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
return -EACCES;
}
return 0;
@@ -364,8 +370,22 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
void
ccw_device_verify_start(struct ccw_device *cdev)
{
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
cdev->private->flags.pgid_single = 0;
cdev->private->iretry = 5;
+ /*
+ * Update sch->lpm with current values to catch paths becoming
+ * available again.
+ */
+ if (stsch(sch->schid, &sch->schib)) {
+ ccw_device_verify_done(cdev, -ENODEV);
+ return;
+ }
+ sch->lpm = sch->schib.pmcw.pim &
+ sch->schib.pmcw.pam &
+ sch->schib.pmcw.pom &
+ sch->opm;
__ccw_device_verify_start(cdev);
}
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 12a24d4331a..db09c209098 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -36,15 +36,16 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
"received"
- " ... device %04X on subchannel %04X, dev_stat "
+ " ... device %04x on subchannel 0.%x.%04x, dev_stat "
": %02X sch_stat : %02X\n",
- cdev->private->devno, cdev->private->irq,
+ cdev->private->devno, cdev->private->ssid,
+ cdev->private->sch_no,
irb->scsw.dstat, irb->scsw.cstat);
if (irb->scsw.cc != 3) {
char dbf_text[15];
- sprintf(dbf_text, "chk%x", cdev->private->irq);
+ sprintf(dbf_text, "chk%x", cdev->private->sch_no);
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, irb, sizeof (struct irb));
}
@@ -59,10 +60,11 @@ ccw_device_path_notoper(struct ccw_device *cdev)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
- CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are "
- "not operational \n", __FUNCTION__, sch->irq,
+ CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
+ "not operational \n", __FUNCTION__,
+ sch->schid.ssid, sch->schid.sch_no,
sch->schib.pmcw.pnom);
sch->lpm &= ~sch->schib.pmcw.pnom;
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 45480a2bc4c..95a9462f9a9 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -1,12 +1,13 @@
#ifndef S390_CIO_IOASM_H
#define S390_CIO_IOASM_H
+#include "schid.h"
+
/*
* TPI info structure
*/
struct tpi_info {
- __u32 reserved1 : 16; /* reserved 0x00000001 */
- __u32 irq : 16; /* aka. subchannel number */
+ struct subchannel_id schid;
__u32 intparm; /* interruption parameter */
__u32 adapter_IO : 1;
__u32 reserved2 : 1;
@@ -21,7 +22,8 @@ struct tpi_info {
* Some S390 specific IO instructions as inline
*/
-static inline int stsch(int irq, volatile struct schib *addr)
+static inline int stsch(struct subchannel_id schid,
+ volatile struct schib *addr)
{
int ccode;
@@ -31,12 +33,42 @@ static inline int stsch(int irq, volatile struct schib *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
+ : "cc", "1" );
+ return ccode;
+}
+
+static inline int stsch_err(struct subchannel_id schid,
+ volatile struct schib *addr)
+{
+ int ccode;
+
+ __asm__ __volatile__(
+ " lhi %0,%3\n"
+ " lr 1,%1\n"
+ " stsch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+#ifdef CONFIG_64BIT
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,1b\n"
+ ".previous"
+#else
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,1b\n"
+ ".previous"
+#endif
+ : "=&d" (ccode)
+ : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int msch(int irq, volatile struct schib *addr)
+static inline int msch(struct subchannel_id schid,
+ volatile struct schib *addr)
{
int ccode;
@@ -46,12 +78,13 @@ static inline int msch(int irq, volatile struct schib *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int msch_err(int irq, volatile struct schib *addr)
+static inline int msch_err(struct subchannel_id schid,
+ volatile struct schib *addr)
{
int ccode;
@@ -62,7 +95,7 @@ static inline int msch_err(int irq, volatile struct schib *addr)
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
".section __ex_table,\"a\"\n"
" .align 8\n"
" .quad 0b,1b\n"
@@ -74,12 +107,13 @@ static inline int msch_err(int irq, volatile struct schib *addr)
".previous"
#endif
: "=&d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr), "K" (-EIO)
+ : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int tsch(int irq, volatile struct irb *addr)
+static inline int tsch(struct subchannel_id schid,
+ volatile struct irb *addr)
{
int ccode;
@@ -89,7 +123,7 @@ static inline int tsch(int irq, volatile struct irb *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
@@ -103,12 +137,13 @@ static inline int tpi( volatile struct tpi_info *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "a" (addr)
+ : "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int ssch(int irq, volatile struct orb *addr)
+static inline int ssch(struct subchannel_id schid,
+ volatile struct orb *addr)
{
int ccode;
@@ -118,12 +153,12 @@ static inline int ssch(int irq, volatile struct orb *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int rsch(int irq)
+static inline int rsch(struct subchannel_id schid)
{
int ccode;
@@ -133,12 +168,12 @@ static inline int rsch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
-static inline int csch(int irq)
+static inline int csch(struct subchannel_id schid)
{
int ccode;
@@ -148,12 +183,12 @@ static inline int csch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
-static inline int hsch(int irq)
+static inline int hsch(struct subchannel_id schid)
{
int ccode;
@@ -163,12 +198,12 @@ static inline int hsch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
-static inline int xsch(int irq)
+static inline int xsch(struct subchannel_id schid)
{
int ccode;
@@ -178,21 +213,22 @@ static inline int xsch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
static inline int chsc(void *chsc_area)
{
+ typedef struct { char _[4096]; } addr_type;
int cc;
__asm__ __volatile__ (
- ".insn rre,0xb25f0000,%1,0 \n\t"
+ ".insn rre,0xb25f0000,%2,0 \n\t"
"ipm %0 \n\t"
"srl %0,28 \n\t"
- : "=d" (cc)
- : "d" (chsc_area)
+ : "=d" (cc), "=m" (*(addr_type *) chsc_area)
+ : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
: "cc" );
return cc;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index eb39218b925..30a836ffc31 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.108 $"
+#define VERSION_QDIO_C "$Revision: 1.114 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -76,6 +76,7 @@ static struct qdio_perf_stats perf_stats;
#endif /* QDIO_PERFORMANCE_STATS */
static int hydra_thinints;
+static int is_passthrough = 0;
static int omit_svs;
static int indicator_used[INDICATORS_PER_CACHELINE];
@@ -136,12 +137,126 @@ qdio_release_q(struct qdio_q *q)
atomic_dec(&q->use_count);
}
-static volatile inline void
-qdio_set_slsb(volatile char *slsb, unsigned char value)
+/*check ccq */
+static inline int
+qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
+{
+ char dbf_text[15];
+
+ if (ccq == 0 || ccq == 32 || ccq == 96)
+ return 0;
+ if (ccq == 97)
+ return 1;
+ /*notify devices immediately*/
+ sprintf(dbf_text,"%d", ccq);
+ QDIO_DBF_TEXT2(1,trace,dbf_text);
+ return -EIO;
+}
+/* EQBS: extract buffer states */
+static inline int
+qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
+ unsigned int *start, unsigned int *cnt)
+{
+ struct qdio_irq *irq;
+ unsigned int tmp_cnt, q_no, ccq;
+ int rc ;
+ char dbf_text[15];
+
+ ccq = 0;
+ tmp_cnt = *cnt;
+ irq = (struct qdio_irq*)q->irq_ptr;
+ q_no = q->q_no;
+ if(!q->is_input_q)
+ q_no += irq->no_input_qs;
+ ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
+ rc = qdio_check_ccq(q, ccq);
+ if (rc < 0) {
+ QDIO_DBF_TEXT2(1,trace,"eqberr");
+ sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
+ QDIO_DBF_TEXT2(1,trace,dbf_text);
+ q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
+ QDIO_STATUS_LOOK_FOR_ERROR,
+ 0, 0, 0, -1, -1, q->int_parm);
+ return 0;
+ }
+ return (tmp_cnt - *cnt);
+}
+
+/* SQBS: set buffer states */
+static inline int
+qdio_do_sqbs(struct qdio_q *q, unsigned char state,
+ unsigned int *start, unsigned int *cnt)
{
- xchg((char*)slsb,value);
+ struct qdio_irq *irq;
+ unsigned int tmp_cnt, q_no, ccq;
+ int rc;
+ char dbf_text[15];
+
+ ccq = 0;
+ tmp_cnt = *cnt;
+ irq = (struct qdio_irq*)q->irq_ptr;
+ q_no = q->q_no;
+ if(!q->is_input_q)
+ q_no += irq->no_input_qs;
+ ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
+ rc = qdio_check_ccq(q, ccq);
+ if (rc < 0) {
+ QDIO_DBF_TEXT3(1,trace,"sqberr");
+ sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
+ QDIO_STATUS_LOOK_FOR_ERROR,
+ 0, 0, 0, -1, -1, q->int_parm);
+ return 0;
+ }
+ return (tmp_cnt - *cnt);
}
+static inline int
+qdio_set_slsb(struct qdio_q *q, unsigned int *bufno,
+ unsigned char state, unsigned int *count)
+{
+ volatile char *slsb;
+ struct qdio_irq *irq;
+
+ irq = (struct qdio_irq*)q->irq_ptr;
+ if (!irq->is_qebsm) {
+ slsb = (char *)&q->slsb.acc.val[(*bufno)];
+ xchg(slsb, state);
+ return 1;
+ }
+ return qdio_do_sqbs(q, state, bufno, count);
+}
+
+#ifdef CONFIG_QDIO_DEBUG
+static inline void
+qdio_trace_slsb(struct qdio_q *q)
+{
+ if (q->queue_type==QDIO_TRACE_QTYPE) {
+ if (q->is_input_q)
+ QDIO_DBF_HEX2(0,slsb_in,&q->slsb,
+ QDIO_MAX_BUFFERS_PER_Q);
+ else
+ QDIO_DBF_HEX2(0,slsb_out,&q->slsb,
+ QDIO_MAX_BUFFERS_PER_Q);
+ }
+}
+#endif
+
+static inline int
+set_slsb(struct qdio_q *q, unsigned int *bufno,
+ unsigned char state, unsigned int *count)
+{
+ int rc;
+#ifdef CONFIG_QDIO_DEBUG
+ qdio_trace_slsb(q);
+#endif
+ rc = qdio_set_slsb(q, bufno, state, count);
+#ifdef CONFIG_QDIO_DEBUG
+ qdio_trace_slsb(q);
+#endif
+ return rc;
+}
static inline int
qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
unsigned int gpr3)
@@ -155,7 +270,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
perf_stats.siga_syncs++;
#endif /* QDIO_PERFORMANCE_STATS */
- cc = do_siga_sync(q->irq, gpr2, gpr3);
+ cc = do_siga_sync(q->schid, gpr2, gpr3);
if (cc)
QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
@@ -170,6 +285,23 @@ qdio_siga_sync_q(struct qdio_q *q)
return qdio_siga_sync(q, q->mask, 0);
}
+static int
+__do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
+{
+ struct qdio_irq *irq;
+ unsigned int fc = 0;
+ unsigned long schid;
+
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if (!irq->is_qebsm)
+ schid = *((u32 *)&q->schid);
+ else {
+ schid = irq->sch_token;
+ fc |= 0x80;
+ }
+ return do_siga_output(schid, q->mask, busy_bit, fc);
+}
+
/*
* returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
* an access exception
@@ -189,7 +321,7 @@ qdio_siga_output(struct qdio_q *q)
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
for (;;) {
- cc = do_siga_output(q->irq, q->mask, &busy_bit);
+ cc = __do_siga_output(q, &busy_bit);
//QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit);
if ((cc==2) && (busy_bit) && (q->is_iqdio_q)) {
if (!start_time)
@@ -221,7 +353,7 @@ qdio_siga_input(struct qdio_q *q)
perf_stats.siga_ins++;
#endif /* QDIO_PERFORMANCE_STATS */
- cc = do_siga_input(q->irq, q->mask);
+ cc = do_siga_input(q->schid, q->mask);
if (cc)
QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
@@ -230,7 +362,7 @@ qdio_siga_input(struct qdio_q *q)
}
/* locked by the locks in qdio_activate and qdio_cleanup */
-static __u32 volatile *
+static __u32 *
qdio_get_indicator(void)
{
int i;
@@ -258,7 +390,7 @@ qdio_put_indicator(__u32 *addr)
atomic_dec(&spare_indicator_usecount);
}
-static inline volatile void
+static inline void
tiqdio_clear_summary_bit(__u32 *location)
{
QDIO_DBF_TEXT5(0,trace,"clrsummb");
@@ -267,7 +399,7 @@ tiqdio_clear_summary_bit(__u32 *location)
xchg(location,0);
}
-static inline volatile void
+static inline void
tiqdio_set_summary_bit(__u32 *location)
{
QDIO_DBF_TEXT5(0,trace,"setsummb");
@@ -336,7 +468,9 @@ static inline int
qdio_stop_polling(struct qdio_q *q)
{
#ifdef QDIO_USE_PROCESSING_STATE
- int gsf;
+ unsigned int tmp, gsf, count = 1;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
if (!atomic_swap(&q->polling,0))
return 1;
@@ -348,17 +482,22 @@ qdio_stop_polling(struct qdio_q *q)
if (!q->is_input_q)
return 1;
- gsf=GET_SAVED_FRONTIER(q);
- set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)&
- (QDIO_MAX_BUFFERS_PER_Q-1)],
- SLSB_P_INPUT_NOT_INIT);
+ tmp = gsf = GET_SAVED_FRONTIER(q);
+ tmp = ((tmp + QDIO_MAX_BUFFERS_PER_Q-1) & (QDIO_MAX_BUFFERS_PER_Q-1) );
+ set_slsb(q, &tmp, SLSB_P_INPUT_NOT_INIT, &count);
+
/*
* we don't issue this SYNC_MEMORY, as we trust Rick T and
* moreover will not use the PROCESSING state under VM, so
* q->polling was 0 anyway
*/
/*SYNC_MEMORY;*/
- if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED)
+ if (irq->is_qebsm) {
+ count = 1;
+ qdio_do_eqbs(q, &state, &gsf, &count);
+ } else
+ state = q->slsb.acc.val[gsf];
+ if (state != SLSB_P_INPUT_PRIMED)
return 1;
/*
* set our summary bit again, as otherwise there is a
@@ -431,18 +570,136 @@ tiqdio_clear_global_summary(void)
/************************* OUTBOUND ROUTINES *******************************/
+static int
+qdio_qebsm_get_outbound_buffer_frontier(struct qdio_q *q)
+{
+ struct qdio_irq *irq;
+ unsigned char state;
+ unsigned int cnt, count, ftc;
+
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if ((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis))
+ SYNC_MEMORY;
+
+ ftc = q->first_to_check;
+ count = qdio_min(atomic_read(&q->number_of_buffers_used),
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+ if (count == 0)
+ return q->first_to_check;
+ cnt = qdio_do_eqbs(q, &state, &ftc, &count);
+ if (cnt == 0)
+ return q->first_to_check;
+ switch (state) {
+ case SLSB_P_OUTPUT_ERROR:
+ QDIO_DBF_TEXT3(0,trace,"outperr");
+ atomic_sub(cnt , &q->number_of_buffers_used);
+ if (q->qdio_error)
+ q->error_status_flags |=
+ QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+ q->qdio_error = SLSB_P_OUTPUT_ERROR;
+ q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+ q->first_to_check = ftc;
+ break;
+ case SLSB_P_OUTPUT_EMPTY:
+ QDIO_DBF_TEXT5(0,trace,"outpempt");
+ atomic_sub(cnt, &q->number_of_buffers_used);
+ q->first_to_check = ftc;
+ break;
+ case SLSB_CU_OUTPUT_PRIMED:
+ /* all buffers primed */
+ QDIO_DBF_TEXT5(0,trace,"outpprim");
+ break;
+ default:
+ break;
+ }
+ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
+ return q->first_to_check;
+}
+
+static int
+qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q)
+{
+ struct qdio_irq *irq;
+ unsigned char state;
+ int tmp, ftc, count, cnt;
+ char dbf_text[15];
+
+
+ irq = (struct qdio_irq *) q->irq_ptr;
+ ftc = q->first_to_check;
+ count = qdio_min(atomic_read(&q->number_of_buffers_used),
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+ if (count == 0)
+ return q->first_to_check;
+ cnt = qdio_do_eqbs(q, &state, &ftc, &count);
+ if (cnt == 0)
+ return q->first_to_check;
+ switch (state) {
+ case SLSB_P_INPUT_ERROR :
+#ifdef CONFIG_QDIO_DEBUG
+ QDIO_DBF_TEXT3(1,trace,"inperr");
+ sprintf(dbf_text,"%2x,%2x",ftc,count);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
+ if (q->qdio_error)
+ q->error_status_flags |=
+ QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+ q->qdio_error = SLSB_P_INPUT_ERROR;
+ q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+ atomic_sub(cnt, &q->number_of_buffers_used);
+ q->first_to_check = ftc;
+ break;
+ case SLSB_P_INPUT_PRIMED :
+ QDIO_DBF_TEXT3(0,trace,"inptprim");
+ sprintf(dbf_text,"%2x,%2x",ftc,count);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ tmp = 0;
+ ftc = q->first_to_check;
+#ifdef QDIO_USE_PROCESSING_STATE
+ if (cnt > 1) {
+ cnt -= 1;
+ tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt);
+ if (!tmp)
+ break;
+ }
+ cnt = 1;
+ tmp += set_slsb(q, &ftc,
+ SLSB_P_INPUT_PROCESSING, &cnt);
+ atomic_set(&q->polling, 1);
+#else
+ tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt);
+#endif
+ atomic_sub(tmp, &q->number_of_buffers_used);
+ q->first_to_check = ftc;
+ break;
+ case SLSB_CU_INPUT_EMPTY:
+ case SLSB_P_INPUT_NOT_INIT:
+ case SLSB_P_INPUT_PROCESSING:
+ QDIO_DBF_TEXT5(0,trace,"inpnipro");
+ break;
+ default:
+ break;
+ }
+ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
+ return q->first_to_check;
+}
static inline int
qdio_get_outbound_buffer_frontier(struct qdio_q *q)
{
- int f,f_mod_no;
- volatile char *slsb;
- int first_not_to_check;
+ struct qdio_irq *irq;
+ volatile char *slsb;
+ unsigned int count = 1;
+ int first_not_to_check, f, f_mod_no;
char dbf_text[15];
QDIO_DBF_TEXT4(0,trace,"getobfro");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if (irq->is_qebsm)
+ return qdio_qebsm_get_outbound_buffer_frontier(q);
+
slsb=&q->slsb.acc.val[0];
f_mod_no=f=q->first_to_check;
/*
@@ -484,7 +741,7 @@ check_next:
QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
/* kind of process the buffer */
- set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_OUTPUT_NOT_INIT, &count);
/*
* we increment the frontier, as this buffer
@@ -597,48 +854,48 @@ qdio_kick_outbound_q(struct qdio_q *q)
result=qdio_siga_output(q);
- switch (result) {
- case 0:
- /* went smooth this time, reset timestamp */
+ switch (result) {
+ case 0:
+ /* went smooth this time, reset timestamp */
#ifdef CONFIG_QDIO_DEBUG
- QDIO_DBF_TEXT3(0,trace,"cc2reslv");
- sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
- atomic_read(&q->busy_siga_counter));
- QDIO_DBF_TEXT3(0,trace,dbf_text);
+ QDIO_DBF_TEXT3(0,trace,"cc2reslv");
+ sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no,
+ atomic_read(&q->busy_siga_counter));
+ QDIO_DBF_TEXT3(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
- q->timing.busy_start=0;
+ q->timing.busy_start=0;
+ break;
+ case (2|QDIO_SIGA_ERROR_B_BIT_SET):
+ /* cc=2 and busy bit: */
+ atomic_inc(&q->busy_siga_counter);
+
+ /* if the last siga was successful, save
+ * timestamp here */
+ if (!q->timing.busy_start)
+ q->timing.busy_start=NOW;
+
+ /* if we're in time, don't touch error_status_flags
+ * and siga_error */
+ if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
+ qdio_mark_q(q);
break;
- case (2|QDIO_SIGA_ERROR_B_BIT_SET):
- /* cc=2 and busy bit: */
- atomic_inc(&q->busy_siga_counter);
-
- /* if the last siga was successful, save
- * timestamp here */
- if (!q->timing.busy_start)
- q->timing.busy_start=NOW;
-
- /* if we're in time, don't touch error_status_flags
- * and siga_error */
- if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
- qdio_mark_q(q);
- break;
- }
- QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
+ }
+ QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
#ifdef CONFIG_QDIO_DEBUG
- sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
- atomic_read(&q->busy_siga_counter));
- QDIO_DBF_TEXT3(0,trace,dbf_text);
+ sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no,
+ atomic_read(&q->busy_siga_counter));
+ QDIO_DBF_TEXT3(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
- /* else fallthrough and report error */
- default:
- /* for plain cc=1, 2 or 3: */
- if (q->siga_error)
- q->error_status_flags|=
- QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+ /* else fallthrough and report error */
+ default:
+ /* for plain cc=1, 2 or 3: */
+ if (q->siga_error)
q->error_status_flags|=
- QDIO_STATUS_LOOK_FOR_ERROR;
- q->siga_error=result;
- }
+ QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+ q->error_status_flags|=
+ QDIO_STATUS_LOOK_FOR_ERROR;
+ q->siga_error=result;
+ }
}
static inline void
@@ -743,8 +1000,10 @@ qdio_outbound_processing(struct qdio_q *q)
static inline int
qdio_get_inbound_buffer_frontier(struct qdio_q *q)
{
+ struct qdio_irq *irq;
int f,f_mod_no;
volatile char *slsb;
+ unsigned int count = 1;
int first_not_to_check;
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
@@ -756,6 +1015,10 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q)
QDIO_DBF_TEXT4(0,trace,"getibfro");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if (irq->is_qebsm)
+ return qdio_qebsm_get_inbound_buffer_frontier(q);
+
slsb=&q->slsb.acc.val[0];
f_mod_no=f=q->first_to_check;
/*
@@ -792,19 +1055,19 @@ check_next:
* kill VM in terms of CP overhead
*/
if (q->siga_sync) {
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
} else {
/* set the previous buffer to NOT_INIT. The current
* buffer will be set to PROCESSING at the end of
* this function to avoid further interrupts. */
if (last_position>=0)
- set_slsb(&slsb[last_position],
- SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &last_position,
+ SLSB_P_INPUT_NOT_INIT, &count);
atomic_set(&q->polling,1);
last_position=f_mod_no;
}
#else /* QDIO_USE_PROCESSING_STATE */
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
#endif /* QDIO_USE_PROCESSING_STATE */
/*
* not needed, as the inbound queue will be synced on the next
@@ -829,7 +1092,7 @@ check_next:
QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
/* kind of process the buffer */
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
if (q->qdio_error)
q->error_status_flags|=
@@ -857,7 +1120,7 @@ out:
#ifdef QDIO_USE_PROCESSING_STATE
if (last_position>=0)
- set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING);
+ set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count);
#endif /* QDIO_USE_PROCESSING_STATE */
QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
@@ -902,6 +1165,10 @@ static inline int
tiqdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
+ unsigned int start_buf, count;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
#endif
@@ -927,8 +1194,13 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!q->siga_sync)
/* we'll check for more primed buffers in qeth_stop_polling */
return 0;
-
- if (q->slsb.acc.val[q->first_to_check]!=SLSB_P_INPUT_PRIMED)
+ if (irq->is_qebsm) {
+ count = 1;
+ start_buf = q->first_to_check;
+ qdio_do_eqbs(q, &state, &start_buf, &count);
+ } else
+ state = q->slsb.acc.val[q->first_to_check];
+ if (state != SLSB_P_INPUT_PRIMED)
/*
* nothing more to do, if next buffer is not PRIMED.
* note that we did a SYNC_MEMORY before, that there
@@ -955,6 +1227,10 @@ static inline int
qdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
+ unsigned int start_buf, count;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
#endif
@@ -973,8 +1249,13 @@ qdio_is_inbound_q_done(struct qdio_q *q)
QDIO_DBF_TEXT4(0,trace,dbf_text);
return 1;
}
-
- if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) {
+ if (irq->is_qebsm) {
+ count = 1;
+ start_buf = q->first_to_check;
+ qdio_do_eqbs(q, &state, &start_buf, &count);
+ } else
+ state = q->slsb.acc.val[q->first_to_check];
+ if (state == SLSB_P_INPUT_PRIMED) {
/* we got something to do */
QDIO_DBF_TEXT4(0,trace,"inqisntA");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -1456,7 +1737,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
void *ptr;
int available;
- sprintf(dbf_text,"qfqs%4x",cdev->private->irq);
+ sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
for (i=0;i<no_input_qs;i++) {
q=irq_ptr->input_qs[i];
@@ -1476,7 +1757,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->queue_type=q_format;
q->int_parm=int_parm;
- q->irq=irq_ptr->irq;
+ q->schid = irq_ptr->schid;
q->irq_ptr = irq_ptr;
q->cdev = cdev;
q->mask=1<<(31-i);
@@ -1523,11 +1804,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
/* fill in slsb */
- for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
- set_slsb(&q->slsb.acc.val[j],
- SLSB_P_INPUT_NOT_INIT);
-/* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/
- }
+ if (!irq_ptr->is_qebsm) {
+ unsigned int count = 1;
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+ set_slsb(q, &j, SLSB_P_INPUT_NOT_INIT, &count);
+ }
}
for (i=0;i<no_output_qs;i++) {
@@ -1549,7 +1830,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->queue_type=q_format;
q->int_parm=int_parm;
q->is_input_q=0;
- q->irq=irq_ptr->irq;
+ q->schid = irq_ptr->schid;
q->cdev = cdev;
q->irq_ptr = irq_ptr;
q->mask=1<<(31-i);
@@ -1584,11 +1865,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
/* fill in slsb */
- for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
- set_slsb(&q->slsb.acc.val[j],
- SLSB_P_OUTPUT_NOT_INIT);
-/* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/
- }
+ if (!irq_ptr->is_qebsm) {
+ unsigned int count = 1;
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+ set_slsb(q, &j, SLSB_P_OUTPUT_NOT_INIT, &count);
+ }
}
}
@@ -1656,7 +1937,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
char dbf_text[15];
QDIO_DBF_TEXT5(0,trace,"newstate");
- sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state);
+ sprintf(dbf_text,"%4x%4x",irq_ptr->schid.sch_no,state);
QDIO_DBF_TEXT5(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
@@ -1669,12 +1950,12 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
}
static inline void
-qdio_irq_check_sense(int irq, struct irb *irb)
+qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb)
{
char dbf_text[15];
if (irb->esw.esw0.erw.cons) {
- sprintf(dbf_text,"sens%4x",irq);
+ sprintf(dbf_text,"sens%4x",schid.sch_no);
QDIO_DBF_TEXT2(1,trace,dbf_text);
QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN);
@@ -1785,21 +2066,22 @@ qdio_timeout_handler(struct ccw_device *cdev)
switch (irq_ptr->state) {
case QDIO_IRQ_STATE_INACTIVE:
- QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n",
- irq_ptr->irq);
+ QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1,setup,"eq:timeo");
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
break;
case QDIO_IRQ_STATE_CLEANUP:
- QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n",
- irq_ptr->irq);
+ QDIO_PRINT_INFO("Did not get interrupt on cleanup, "
+ "irq=0.%x.%x.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
break;
case QDIO_IRQ_STATE_ESTABLISHED:
case QDIO_IRQ_STATE_ACTIVE:
/* I/O has been terminated by common I/O layer. */
- QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n",
- irq_ptr->irq);
+ QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1, trace, "cio:term");
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
if (get_device(&cdev->dev)) {
@@ -1862,7 +2144,7 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
}
- qdio_irq_check_sense(irq_ptr->irq, irb);
+ qdio_irq_check_sense(irq_ptr->schid, irb);
#ifdef CONFIG_QDIO_DEBUG
sprintf(dbf_text, "state:%d", irq_ptr->state);
@@ -1905,7 +2187,7 @@ int
qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
unsigned int queue_number)
{
- int cc;
+ int cc = 0;
struct qdio_q *q;
struct qdio_irq *irq_ptr;
void *ptr;
@@ -1918,7 +2200,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
return -ENODEV;
#ifdef CONFIG_QDIO_DEBUG
- *((int*)(&dbf_text[4])) = irq_ptr->irq;
+ *((int*)(&dbf_text[4])) = irq_ptr->schid.sch_no;
QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
*((int*)(&dbf_text[0]))=flags;
*((int*)(&dbf_text[4]))=queue_number;
@@ -1929,12 +2211,14 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
q=irq_ptr->input_qs[queue_number];
if (!q)
return -EINVAL;
- cc = do_siga_sync(q->irq, 0, q->mask);
+ if (!(irq_ptr->is_qebsm))
+ cc = do_siga_sync(q->schid, 0, q->mask);
} else if (flags&QDIO_FLAG_SYNC_OUTPUT) {
q=irq_ptr->output_qs[queue_number];
if (!q)
return -EINVAL;
- cc = do_siga_sync(q->irq, q->mask, 0);
+ if (!(irq_ptr->is_qebsm))
+ cc = do_siga_sync(q->schid, q->mask, 0);
} else
return -EINVAL;
@@ -1945,15 +2229,54 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
return cc;
}
-static unsigned char
-qdio_check_siga_needs(int sch)
+static inline void
+qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+ unsigned long token)
+{
+ struct qdio_q *q;
+ int i;
+ unsigned int count, start_buf;
+ char dbf_text[15];
+
+ /*check if QEBSM is disabled */
+ if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) {
+ irq_ptr->is_qebsm = 0;
+ irq_ptr->sch_token = 0;
+ irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+ QDIO_DBF_TEXT0(0,setup,"noV=V");
+ return;
+ }
+ irq_ptr->sch_token = token;
+ /*input queue*/
+ for (i = 0; i < irq_ptr->no_input_qs;i++) {
+ q = irq_ptr->input_qs[i];
+ count = QDIO_MAX_BUFFERS_PER_Q;
+ start_buf = 0;
+ set_slsb(q, &start_buf, SLSB_P_INPUT_NOT_INIT, &count);
+ }
+ sprintf(dbf_text,"V=V:%2x",irq_ptr->is_qebsm);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
+ sprintf(dbf_text,"%8lx",irq_ptr->sch_token);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
+ /*output queue*/
+ for (i = 0; i < irq_ptr->no_output_qs; i++) {
+ q = irq_ptr->output_qs[i];
+ count = QDIO_MAX_BUFFERS_PER_Q;
+ start_buf = 0;
+ set_slsb(q, &start_buf, SLSB_P_OUTPUT_NOT_INIT, &count);
+ }
+}
+
+static void
+qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
{
int result;
unsigned char qdioac;
-
struct {
struct chsc_header request;
- u16 reserved1;
+ u16 reserved1:10;
+ u16 ssid:2;
+ u16 fmt:4;
u16 first_sch;
u16 reserved2;
u16 last_sch;
@@ -1964,67 +2287,83 @@ qdio_check_siga_needs(int sch)
u8 reserved5;
u16 sch;
u8 qfmt;
- u8 reserved6;
- u8 qdioac;
+ u8 parm;
+ u8 qdioac1;
u8 sch_class;
u8 reserved7;
u8 icnt;
u8 reserved8;
u8 ocnt;
+ u8 reserved9;
+ u8 mbccnt;
+ u16 qdioac2;
+ u64 sch_token;
} *ssqd_area;
+ QDIO_DBF_TEXT0(0,setup,"getssqd");
+ qdioac = 0;
ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!ssqd_area) {
QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
- "SIGAs for sch x%x.\n", sch);
- return CHSC_FLAG_SIGA_INPUT_NECESSARY ||
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
+ irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
+ CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+ CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
+ irq_ptr->sch_token = 0;
+ irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+ return;
}
+
ssqd_area->request = (struct chsc_header) {
.length = 0x0010,
.code = 0x0024,
};
-
- ssqd_area->first_sch = sch;
- ssqd_area->last_sch = sch;
-
- result=chsc(ssqd_area);
+ ssqd_area->first_sch = irq_ptr->schid.sch_no;
+ ssqd_area->last_sch = irq_ptr->schid.sch_no;
+ ssqd_area->ssid = irq_ptr->schid.ssid;
+ result = chsc(ssqd_area);
if (result) {
QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
- "SIGAs for sch x%x.\n",
- result,sch);
+ "SIGAs for sch 0.%x.%x.\n", result,
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
goto out;
}
if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
QDIO_PRINT_WARN("response upon checking SIGA needs " \
- "is 0x%x. Using all SIGAs for sch x%x.\n",
- ssqd_area->response.code, sch);
+ "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
+ ssqd_area->response.code,
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
goto out;
}
if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
!(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
- (ssqd_area->sch != sch)) {
- QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \
- "using all SIGAs.\n",sch);
+ (ssqd_area->sch != irq_ptr->schid.sch_no)) {
+ QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
+ "using all SIGAs.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
+ irq_ptr->is_qebsm = 0;
goto out;
}
-
- qdioac = ssqd_area->qdioac;
+ qdioac = ssqd_area->qdioac1;
out:
+ qdio_check_subchannel_qebsm(irq_ptr, qdioac,
+ ssqd_area->sch_token);
free_page ((unsigned long) ssqd_area);
- return qdioac;
+ irq_ptr->qdioac = qdioac;
}
static unsigned int
@@ -2055,6 +2394,13 @@ tiqdio_check_chsc_availability(void)
sprintf(dbf_text,"hydrati%1x", hydra_thinints);
QDIO_DBF_TEXT0(0,setup,dbf_text);
+#ifdef CONFIG_64BIT
+ /* Check for QEBSM support in general (bit 58). */
+ is_passthrough = css_general_characteristics.qebsm;
+#endif
+ sprintf(dbf_text,"cssQBS:%1x", is_passthrough);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
+
/* Check for aif time delay disablement fac (bit 56). If installed,
* omit svs even under lpar (good point by rick again) */
omit_svs = css_general_characteristics.aif_tdd;
@@ -2091,7 +2437,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
/* set to 0x10000000 to enable
* time delay disablement facility */
u32 reserved5;
- u32 subsystem_id;
+ struct subchannel_id schid;
u32 reserved6[1004];
struct chsc_header response;
u32 reserved7;
@@ -2113,7 +2459,8 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!scssc_area) {
QDIO_PRINT_WARN("No memory for setting indicators on " \
- "subchannel x%x.\n", irq_ptr->irq);
+ "subchannel 0.%x.%x.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
return -ENOMEM;
}
scssc_area->request = (struct chsc_header) {
@@ -2127,7 +2474,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
scssc_area->ks = QDIO_STORAGE_KEY;
scssc_area->kc = QDIO_STORAGE_KEY;
scssc_area->isc = TIQDIO_THININT_ISC;
- scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;
+ scssc_area->schid = irq_ptr->schid;
/* enables the time delay disablement facility. Don't care
* whether it is really there (i.e. we haven't checked for
* it) */
@@ -2137,12 +2484,11 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
QDIO_PRINT_WARN("Time delay disablement facility " \
"not available\n");
-
-
result = chsc(scssc_area);
if (result) {
- QDIO_PRINT_WARN("could not set indicators on irq x%x, " \
- "cc=%i.\n",irq_ptr->irq,result);
+ QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \
+ "cc=%i.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result);
result = -EIO;
goto out;
}
@@ -2198,7 +2544,8 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!scsscf_area) {
QDIO_PRINT_WARN("No memory for setting delay target on " \
- "subchannel x%x.\n", irq_ptr->irq);
+ "subchannel 0.%x.%x.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
return -ENOMEM;
}
scsscf_area->request = (struct chsc_header) {
@@ -2210,8 +2557,10 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
result=chsc(scsscf_area);
if (result) {
- QDIO_PRINT_WARN("could not set delay target on irq x%x, " \
- "cc=%i. Continuing.\n",irq_ptr->irq,result);
+ QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \
+ "cc=%i. Continuing.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ result);
result = -EIO;
goto out;
}
@@ -2245,7 +2594,7 @@ qdio_cleanup(struct ccw_device *cdev, int how)
if (!irq_ptr)
return -ENODEV;
- sprintf(dbf_text,"qcln%4x",irq_ptr->irq);
+ sprintf(dbf_text,"qcln%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2272,7 +2621,7 @@ qdio_shutdown(struct ccw_device *cdev, int how)
down(&irq_ptr->setting_up_sema);
- sprintf(dbf_text,"qsqs%4x",irq_ptr->irq);
+ sprintf(dbf_text,"qsqs%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2378,7 +2727,7 @@ qdio_free(struct ccw_device *cdev)
down(&irq_ptr->setting_up_sema);
- sprintf(dbf_text,"qfqs%4x",irq_ptr->irq);
+ sprintf(dbf_text,"qfqs%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2526,13 +2875,14 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
irq_ptr = cdev->private->qdio_data;
if (cstat || (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
- sprintf(dbf_text,"ick1%4x",irq_ptr->irq);
+ sprintf(dbf_text,"ick1%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1,trace,dbf_text);
QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
QDIO_PRINT_ERR("received check condition on establish " \
- "queues on irq 0x%x (cs=x%x, ds=x%x).\n",
- irq_ptr->irq,cstat,dstat);
+ "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ cstat,dstat);
qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR);
}
@@ -2540,9 +2890,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
QDIO_DBF_TEXT2(1,setup,"eq:no de");
QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
- QDIO_PRINT_ERR("establish queues on irq %04x: didn't get "
+ QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get "
"device end: dstat=%02x, cstat=%02x\n",
- irq_ptr->irq, dstat, cstat);
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ dstat, cstat);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
return 1;
}
@@ -2551,10 +2902,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
QDIO_DBF_TEXT2(1,setup,"eq:badio");
QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
- QDIO_PRINT_ERR("establish queues on irq %04x: got "
+ QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got "
"the following devstat: dstat=%02x, "
- "cstat=%02x\n",
- irq_ptr->irq, dstat, cstat);
+ "cstat=%02x\n", irq_ptr->schid.ssid,
+ irq_ptr->schid.sch_no, dstat, cstat);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
return 1;
}
@@ -2569,7 +2920,7 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
irq_ptr = cdev->private->qdio_data;
- sprintf(dbf_text,"qehi%4x",cdev->private->irq);
+ sprintf(dbf_text,"qehi%4x",cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2588,7 +2939,7 @@ qdio_initialize(struct qdio_initialize *init_data)
int rc;
char dbf_text[15];
- sprintf(dbf_text,"qini%4x",init_data->cdev->private->irq);
+ sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2609,7 +2960,7 @@ qdio_allocate(struct qdio_initialize *init_data)
struct qdio_irq *irq_ptr;
char dbf_text[15];
- sprintf(dbf_text,"qalc%4x",init_data->cdev->private->irq);
+ sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -2682,7 +3033,7 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
irq_ptr->int_parm=init_data->int_parm;
- irq_ptr->irq = init_data->cdev->private->irq;
+ irq_ptr->schid = ccw_device_get_subchannel_id(init_data->cdev);
irq_ptr->no_input_qs=init_data->no_input_qs;
irq_ptr->no_output_qs=init_data->no_output_qs;
@@ -2698,11 +3049,12 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
QDIO_DBF_TEXT2(0,setup,dbf_text);
if (irq_ptr->is_thinint_irq) {
- irq_ptr->dev_st_chg_ind=qdio_get_indicator();
+ irq_ptr->dev_st_chg_ind = qdio_get_indicator();
QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
if (!irq_ptr->dev_st_chg_ind) {
QDIO_PRINT_WARN("no indicator location available " \
- "for irq 0x%x\n",irq_ptr->irq);
+ "for irq 0.%x.%x\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdio_release_irq_memory(irq_ptr);
return -ENOBUFS;
}
@@ -2747,6 +3099,10 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
irq_ptr->qdr->qkey=QDIO_STORAGE_KEY;
/* fill in qib */
+ irq_ptr->is_qebsm = is_passthrough;
+ if (irq_ptr->is_qebsm)
+ irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM;
+
irq_ptr->qib.qfmt=init_data->q_format;
if (init_data->no_input_qs)
irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib);
@@ -2829,7 +3185,7 @@ qdio_establish(struct qdio_initialize *init_data)
tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
}
- sprintf(dbf_text,"qest%4x",cdev->private->irq);
+ sprintf(dbf_text,"qest%4x",cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2855,9 +3211,10 @@ qdio_establish(struct qdio_initialize *init_data)
sprintf(dbf_text,"eq:io%4x",result);
QDIO_DBF_TEXT2(1,setup,dbf_text);
}
- QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \
- "returned %i, next try returned %i\n",
- irq_ptr->irq,result,result2);
+ QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \
+ "returned %i, next try returned %i\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ result, result2);
result=result2;
if (result)
ccw_device_set_timeout(cdev, 0);
@@ -2884,7 +3241,7 @@ qdio_establish(struct qdio_initialize *init_data)
return -EIO;
}
- irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
+ qdio_get_ssqd_information(irq_ptr);
/* if this gets set once, we're running under VM and can omit SVSes */
if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
omit_svs=1;
@@ -2930,7 +3287,7 @@ qdio_activate(struct ccw_device *cdev, int flags)
goto out;
}
- sprintf(dbf_text,"qact%4x", irq_ptr->irq);
+ sprintf(dbf_text,"qact%4x", irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(0,setup,dbf_text);
QDIO_DBF_TEXT2(0,trace,dbf_text);
@@ -2955,9 +3312,10 @@ qdio_activate(struct ccw_device *cdev, int flags)
sprintf(dbf_text,"aq:io%4x",result);
QDIO_DBF_TEXT2(1,setup,dbf_text);
}
- QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \
- "returned %i, next try returned %i\n",
- irq_ptr->irq,result,result2);
+ QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \
+ "returned %i, next try returned %i\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ result, result2);
result=result2;
}
@@ -3015,30 +3373,40 @@ static inline void
qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+ qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
+ if (irq->is_qebsm) {
+ while (count)
+ set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+ return;
+ }
for (;;) {
- set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_INPUT_EMPTY);
+ set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
count--;
if (!count) break;
- qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+ qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
}
-
- /* not necessary, as the queues are synced during the SIGA read */
- /*SYNC_MEMORY;*/
}
static inline void
qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
+ qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
+ if (irq->is_qebsm) {
+ while (count)
+ set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+ return;
+ }
+
for (;;) {
- set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_OUTPUT_PRIMED);
+ set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
count--;
if (!count) break;
- qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+ qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
}
-
- /* SIGA write will sync the queues */
- /*SYNC_MEMORY;*/
}
static inline void
@@ -3083,6 +3451,9 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
struct qdio_buffer *buffers)
{
int used_elements;
+ unsigned int cnt, start_buf;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
/* This is the outbound handling of queues */
#ifdef QDIO_PERFORMANCE_STATS
@@ -3115,9 +3486,15 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
* SYNC_MEMORY :-/ ), we try to
* fast-requeue buffers
*/
- if (q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
- &(QDIO_MAX_BUFFERS_PER_Q-1)]!=
- SLSB_CU_OUTPUT_PRIMED) {
+ if (irq->is_qebsm) {
+ cnt = 1;
+ start_buf = ((qidx+QDIO_MAX_BUFFERS_PER_Q-1) &
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+ qdio_do_eqbs(q, &state, &start_buf, &cnt);
+ } else
+ state = q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
+ &(QDIO_MAX_BUFFERS_PER_Q-1) ];
+ if (state != SLSB_CU_OUTPUT_PRIMED) {
qdio_kick_outbound_q(q);
} else {
QDIO_DBF_TEXT3(0,trace, "fast-req");
@@ -3150,7 +3527,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags,
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[20];
- sprintf(dbf_text,"doQD%04x",cdev->private->irq);
+ sprintf(dbf_text,"doQD%04x",cdev->private->sch_no);
QDIO_DBF_TEXT3(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 328e31cc685..fa385e761fe 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -3,14 +3,15 @@
#include <asm/page.h>
-#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
+#include "schid.h"
+
+#define VERSION_CIO_QDIO_H "$Revision: 1.40 $"
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_VERBOSE_LEVEL 9
#else /* CONFIG_QDIO_DEBUG */
#define QDIO_VERBOSE_LEVEL 5
#endif /* CONFIG_QDIO_DEBUG */
-
#define QDIO_USE_PROCESSING_STATE
#ifdef CONFIG_QDIO_PERF_STATS
@@ -265,12 +266,64 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
/*
* Some instructions as assembly
*/
+
+static inline int
+do_sqbs(unsigned long sch, unsigned char state, int queue,
+ unsigned int *start, unsigned int *count)
+{
+#ifdef CONFIG_64BIT
+ register unsigned long _ccq asm ("0") = *count;
+ register unsigned long _sch asm ("1") = sch;
+ unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+
+ asm volatile (
+ " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
+ : "+d" (_ccq), "+d" (_queuestart)
+ : "d" ((unsigned long)state), "d" (_sch)
+ : "memory", "cc"
+ );
+ *count = _ccq & 0xff;
+ *start = _queuestart & 0xff;
+
+ return (_ccq >> 32) & 0xff;
+#else
+ return 0;
+#endif
+}
+
+static inline int
+do_eqbs(unsigned long sch, unsigned char *state, int queue,
+ unsigned int *start, unsigned int *count)
+{
+#ifdef CONFIG_64BIT
+ register unsigned long _ccq asm ("0") = *count;
+ register unsigned long _sch asm ("1") = sch;
+ unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+ unsigned long _state = 0;
+
+ asm volatile (
+ " .insn rrf,0xB99c0000,%1,%2,0,0 \n\t"
+ : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+ : "d" (_sch)
+ : "memory", "cc"
+ );
+ *count = _ccq & 0xff;
+ *start = _queuestart & 0xff;
+ *state = _state & 0xff;
+
+ return (_ccq >> 32) & 0xff;
+#else
+ return 0;
+#endif
+}
+
+
static inline int
-do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
+do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
{
int cc;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 0,2 \n\t"
"lr 1,%1 \n\t"
@@ -280,10 +333,10 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask1), "d" (mask2)
+ : "d" (schid), "d" (mask1), "d" (mask2)
: "cc", "0", "1", "2", "3"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
"lghi 0,2 \n\t"
"llgfr 1,%1 \n\t"
@@ -293,19 +346,19 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask1), "d" (mask2)
+ : "d" (schid), "d" (mask1), "d" (mask2)
: "cc", "0", "1", "2", "3"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return cc;
}
static inline int
-do_siga_input(unsigned int irq, unsigned int mask)
+do_siga_input(struct subchannel_id schid, unsigned int mask)
{
int cc;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 0,1 \n\t"
"lr 1,%1 \n\t"
@@ -314,10 +367,10 @@ do_siga_input(unsigned int irq, unsigned int mask)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask)
+ : "d" (schid), "d" (mask)
: "cc", "0", "1", "2", "memory"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
"lghi 0,1 \n\t"
"llgfr 1,%1 \n\t"
@@ -326,21 +379,22 @@ do_siga_input(unsigned int irq, unsigned int mask)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask)
+ : "d" (schid), "d" (mask)
: "cc", "0", "1", "2", "memory"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return cc;
}
static inline int
-do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
+do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
+ unsigned int fc)
{
int cc;
__u32 busy_bit;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 0,0 \n\t"
"lr 1,%2 \n\t"
@@ -366,14 +420,14 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
".long 0b,2b \n\t"
".previous \n\t"
: "=d" (cc), "=d" (busy_bit)
- : "d" (0x10000|irq), "d" (mask),
+ : "d" (schid), "d" (mask),
"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
: "cc", "0", "1", "2", "memory"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
- "lghi 0,0 \n\t"
- "llgfr 1,%2 \n\t"
+ "llgfr 0,%5 \n\t"
+ "lgr 1,%2 \n\t"
"llgfr 2,%3 \n\t"
"siga 0 \n\t"
"0:"
@@ -391,11 +445,11 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
".quad 0b,1b \n\t"
".previous \n\t"
: "=d" (cc), "=d" (busy_bit)
- : "d" (0x10000|irq), "d" (mask),
- "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
+ : "d" (schid), "d" (mask),
+ "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
: "cc", "0", "1", "2", "memory"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
(*bb) = busy_bit;
return cc;
@@ -407,21 +461,21 @@ do_clear_global_summary(void)
unsigned long time;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 1,3 \n\t"
".insn rre,0xb2650000,2,0 \n\t"
"lr %0,3 \n\t"
: "=d" (time) : : "cc", "1", "2", "3"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
"lghi 1,3 \n\t"
".insn rre,0xb2650000,2,0 \n\t"
"lgr %0,3 \n\t"
: "=d" (time) : : "cc", "1", "2", "3"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return time;
}
@@ -488,42 +542,21 @@ struct qdio_perf_stats {
#define MY_MODULE_STRING(x) #x
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
#define QDIO_GET_ADDR(x) ((__u32)(unsigned long)x)
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define QDIO_GET_ADDR(x) ((__u32)(long)x)
-#endif /* CONFIG_ARCH_S390X */
-
-#ifdef CONFIG_QDIO_DEBUG
-#define set_slsb(x,y) \
- if(q->queue_type==QDIO_TRACE_QTYPE) { \
- if(q->is_input_q) { \
- QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } else { \
- QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } \
- } \
- qdio_set_slsb(x,y); \
- if(q->queue_type==QDIO_TRACE_QTYPE) { \
- if(q->is_input_q) { \
- QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } else { \
- QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } \
- }
-#else /* CONFIG_QDIO_DEBUG */
-#define set_slsb(x,y) qdio_set_slsb(x,y)
-#endif /* CONFIG_QDIO_DEBUG */
+#endif /* CONFIG_64BIT */
struct qdio_q {
volatile struct slsb slsb;
char unused[QDIO_MAX_BUFFERS_PER_Q];
- __u32 * volatile dev_st_chg_ind;
+ __u32 * dev_st_chg_ind;
int is_input_q;
- int irq;
+ struct subchannel_id schid;
struct ccw_device *cdev;
unsigned int is_iqdio_q;
@@ -568,6 +601,7 @@ struct qdio_q {
struct tasklet_struct tasklet;
#endif /* QDIO_USE_TIMERS_FOR_POLLING */
+
enum qdio_irq_states state;
/* used to store the error condition during a data transfer */
@@ -617,13 +651,17 @@ struct qdio_irq {
__u32 * volatile dev_st_chg_ind;
unsigned long int_parm;
- int irq;
+ struct subchannel_id schid;
unsigned int is_iqdio_irq;
unsigned int is_thinint_irq;
unsigned int hydra_gives_outbound_pcis;
unsigned int sync_done_on_outb_pcis;
+ /* QEBSM facility */
+ unsigned int is_qebsm;
+ unsigned long sch_token;
+
enum qdio_irq_states state;
unsigned int no_input_qs;
diff --git a/drivers/s390/cio/schid.h b/drivers/s390/cio/schid.h
new file mode 100644
index 00000000000..54328fec5ad
--- /dev/null
+++ b/drivers/s390/cio/schid.h
@@ -0,0 +1,26 @@
+#ifndef S390_SCHID_H
+#define S390_SCHID_H
+
+struct subchannel_id {
+ __u32 reserved:13;
+ __u32 ssid:2;
+ __u32 one:1;
+ __u32 sch_no:16;
+} __attribute__ ((packed,aligned(4)));
+
+
+/* Helper function for sane state of pre-allocated subchannel_id. */
+static inline void
+init_subchannel_id(struct subchannel_id *schid)
+{
+ memset(schid, 0, sizeof(struct subchannel_id));
+ schid->one = 1;
+}
+
+static inline int
+schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)
+{
+ return !memcmp(schid1, schid2, sizeof(struct subchannel_id));
+}
+
+#endif /* S390_SCHID_H */
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index e319e78b5ea..f87c785f203 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -1,9 +1,9 @@
/*
* linux/drivers/s390/crypto/z90common.h
*
- * z90crypt 1.3.2
+ * z90crypt 1.3.3
*
- * Copyright (C) 2001, 2004 IBM Corporation
+ * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
@@ -91,12 +91,13 @@ enum hdstat {
#define TSQ_FATAL_ERROR 34
#define RSQ_FATAL_ERROR 35
-#define Z90CRYPT_NUM_TYPES 5
+#define Z90CRYPT_NUM_TYPES 6
#define PCICA 0
#define PCICC 1
#define PCIXCC_MCL2 2
#define PCIXCC_MCL3 3
#define CEX2C 4
+#define CEX2A 5
#define NILDEV -1
#define ANYDEV -1
#define PCIXCC_UNK -2
@@ -105,7 +106,7 @@ enum hdevice_type {
PCICC_HW = 3,
PCICA_HW = 4,
PCIXCC_HW = 5,
- OTHER_HW = 6,
+ CEX2A_HW = 6,
CEX2C_HW = 7
};
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 0a3bb5a10dd..3a18443fdfa 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -1,9 +1,9 @@
/*
* linux/drivers/s390/crypto/z90crypt.h
*
- * z90crypt 1.3.2
+ * z90crypt 1.3.3
*
- * Copyright (C) 2001, 2004 IBM Corporation
+ * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
@@ -29,11 +29,11 @@
#include <linux/ioctl.h>
-#define VERSION_Z90CRYPT_H "$Revision: 1.11 $"
+#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
#define z90crypt_VERSION 1
#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
-#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support
+#define z90crypt_VARIANT 3 // 3 = CEX2A support
/**
* struct ica_rsa_modexpo
@@ -122,6 +122,9 @@ struct ica_rsa_modexpo_crt {
* Z90STAT_CEX2CCOUNT
* Return an integer count of all CEX2Cs.
*
+ * Z90STAT_CEX2ACOUNT
+ * Return an integer count of all CEX2As.
+ *
* Z90STAT_REQUESTQ_COUNT
* Return an integer count of the number of entries waiting to be
* sent to a device.
@@ -144,6 +147,7 @@ struct ica_rsa_modexpo_crt {
* 0x03: PCIXCC_MCL2
* 0x04: PCIXCC_MCL3
* 0x05: CEX2C
+ * 0x06: CEX2A
* 0x0d: device is disabled via the proc filesystem
*
* Z90STAT_QDEPTH_MASK
@@ -199,6 +203,7 @@ struct ica_rsa_modexpo_crt {
#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
+#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index c215e088973..d7f7494a0cb 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -1,9 +1,9 @@
/*
* linux/drivers/s390/crypto/z90hardware.c
*
- * z90crypt 1.3.2
+ * z90crypt 1.3.3
*
- * Copyright (C) 2001, 2004 IBM Corporation
+ * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
@@ -648,6 +648,87 @@ static struct cca_public_sec static_cca_pub_sec = {
#define RESPONSE_CPRB_SIZE 0x000006B8
#define RESPONSE_CPRBX_SIZE 0x00000724
+struct type50_hdr {
+ u8 reserved1;
+ u8 msg_type_code;
+ u16 msg_len;
+ u8 reserved2;
+ u8 ignored;
+ u16 reserved3;
+};
+
+#define TYPE50_TYPE_CODE 0x50
+
+#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg))
+#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg))
+#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg))
+#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg))
+
+#define TYPE50_MEB1_FMT 0x0001
+#define TYPE50_MEB2_FMT 0x0002
+#define TYPE50_CRB1_FMT 0x0011
+#define TYPE50_CRB2_FMT 0x0012
+
+struct type50_meb1_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 exponent[128];
+ u8 modulus[128];
+ u8 message[128];
+};
+
+struct type50_meb2_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 exponent[256];
+ u8 modulus[256];
+ u8 message[256];
+};
+
+struct type50_crb1_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 p[64];
+ u8 q[64];
+ u8 dp[64];
+ u8 dq[64];
+ u8 u[64];
+ u8 message[128];
+};
+
+struct type50_crb2_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 p[128];
+ u8 q[128];
+ u8 dp[128];
+ u8 dq[128];
+ u8 u[128];
+ u8 message[256];
+};
+
+union type50_msg {
+ struct type50_meb1_msg meb1;
+ struct type50_meb2_msg meb2;
+ struct type50_crb1_msg crb1;
+ struct type50_crb2_msg crb2;
+};
+
+struct type80_hdr {
+ u8 reserved1;
+ u8 type;
+ u16 len;
+ u8 code;
+ u8 reserved2[3];
+ u8 reserved3[8];
+};
+
+#define TYPE80_RSP_CODE 0x80
+
struct error_hdr {
unsigned char reserved1;
unsigned char type;
@@ -657,6 +738,7 @@ struct error_hdr {
};
#define TYPE82_RSP_CODE 0x82
+#define TYPE88_RSP_CODE 0x88
#define REP82_ERROR_MACHINE_FAILURE 0x10
#define REP82_ERROR_PREEMPT_FAILURE 0x12
@@ -679,6 +761,22 @@ struct error_hdr {
#define REP82_ERROR_PACKET_TRUNCATED 0xA0
#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
+#define REP88_ERROR_MODULE_FAILURE 0x10
+#define REP88_ERROR_MODULE_TIMEOUT 0x11
+#define REP88_ERROR_MODULE_NOTINIT 0x13
+#define REP88_ERROR_MODULE_NOTAVAIL 0x14
+#define REP88_ERROR_MODULE_DISABLED 0x15
+#define REP88_ERROR_MODULE_IN_DIAGN 0x17
+#define REP88_ERROR_FASTPATH_DISABLD 0x19
+#define REP88_ERROR_MESSAGE_TYPE 0x20
+#define REP88_ERROR_MESSAGE_MALFORMD 0x22
+#define REP88_ERROR_MESSAGE_LENGTH 0x23
+#define REP88_ERROR_RESERVED_FIELD 0x24
+#define REP88_ERROR_KEY_TYPE 0x34
+#define REP88_ERROR_INVALID_KEY 0x82
+#define REP88_ERROR_OPERAND 0x84
+#define REP88_ERROR_OPERAND_EVEN_MOD 0x85
+
#define CALLER_HEADER 12
static inline int
@@ -687,7 +785,7 @@ testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" llgfr 0,%4 \n"
" slgr 1,1 \n"
" lgr 2,1 \n"
@@ -757,7 +855,7 @@ resetq(int q_nr, struct ap_status_word *stat_p)
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" llgfr 0,%2 \n"
" lghi 1,1 \n"
" sll 1,24 \n"
@@ -823,7 +921,7 @@ sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat)
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" lgr 6,%3 \n"
" llgfr 7,%2 \n"
" llgt 0,0(6) \n"
@@ -902,7 +1000,7 @@ rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id,
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" llgfr 0,%2 \n"
" lgr 3,%4 \n"
" lgr 6,%3 \n"
@@ -1029,10 +1127,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
stat = HD_ONLINE;
*q_depth = t_depth + 1;
switch (t_dev_type) {
- case OTHER_HW:
- stat = HD_NOT_THERE;
- *dev_type = NILDEV;
- break;
case PCICA_HW:
*dev_type = PCICA;
break;
@@ -1045,6 +1139,9 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
case CEX2C_HW:
*dev_type = CEX2C;
break;
+ case CEX2A_HW:
+ *dev_type = CEX2A;
+ break;
default:
*dev_type = NILDEV;
break;
@@ -2029,6 +2126,177 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
return 0;
}
+static int
+ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p,
+ union type50_msg *z90cMsg_p)
+{
+ int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len;
+ unsigned char *mod_tgt, *exp_tgt, *inp_tgt;
+ union type50_msg *tmp_type50_msg;
+
+ mod_len = icaMex_p->inputdatalength;
+
+ msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) +
+ CALLER_HEADER;
+
+ memset(z90cMsg_p, 0, msg_size);
+
+ tmp_type50_msg = (union type50_msg *)
+ ((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+ tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE;
+
+ if (mod_len <= 128) {
+ tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN;
+ tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT;
+ mod_tgt = tmp_type50_msg->meb1.modulus;
+ mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus);
+ exp_tgt = tmp_type50_msg->meb1.exponent;
+ exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent);
+ inp_tgt = tmp_type50_msg->meb1.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->meb1.message);
+ } else {
+ tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN;
+ tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT;
+ mod_tgt = tmp_type50_msg->meb2.modulus;
+ mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus);
+ exp_tgt = tmp_type50_msg->meb2.exponent;
+ exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent);
+ inp_tgt = tmp_type50_msg->meb2.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->meb2.message);
+ }
+
+ mod_tgt += (mod_tgt_len - mod_len);
+ if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(mod_tgt, mod_len))
+ return SEN_USER_ERROR;
+ exp_tgt += (exp_tgt_len - mod_len);
+ if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(exp_tgt, mod_len))
+ return SEN_USER_ERROR;
+ inp_tgt += (inp_tgt_len - mod_len);
+ if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(inp_tgt, mod_len))
+ return SEN_USER_ERROR;
+
+ *z90cMsg_l_p = msg_size - CALLER_HEADER;
+
+ return 0;
+}
+
+static int
+ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p,
+ int *z90cMsg_l_p, union type50_msg *z90cMsg_p)
+{
+ int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len,
+ dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset;
+ unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt,
+ temp[8];
+ union type50_msg *tmp_type50_msg;
+
+ mod_len = icaMsg_p->inputdatalength;
+ short_len = mod_len / 2;
+ long_len = mod_len / 2 + 8;
+ long_offset = 0;
+
+ if (long_len > 128) {
+ memset(temp, 0x00, sizeof(temp));
+ if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128))
+ return SEN_RELEASED;
+ if (!is_empty(temp, 8))
+ return SEN_NOT_AVAIL;
+ if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128))
+ return SEN_RELEASED;
+ if (!is_empty(temp, 8))
+ return SEN_NOT_AVAIL;
+ if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128))
+ return SEN_RELEASED;
+ if (!is_empty(temp, 8))
+ return SEN_NOT_AVAIL;
+ long_offset = long_len - 128;
+ long_len = 128;
+ }
+
+ tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) +
+ CALLER_HEADER;
+
+ memset(z90cMsg_p, 0, tmp_size);
+
+ tmp_type50_msg = (union type50_msg *)
+ ((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+ tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE;
+ if (long_len <= 64) {
+ tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN;
+ tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT;
+ p_tgt = tmp_type50_msg->crb1.p;
+ p_tgt_len = sizeof(tmp_type50_msg->crb1.p);
+ q_tgt = tmp_type50_msg->crb1.q;
+ q_tgt_len = sizeof(tmp_type50_msg->crb1.q);
+ dp_tgt = tmp_type50_msg->crb1.dp;
+ dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp);
+ dq_tgt = tmp_type50_msg->crb1.dq;
+ dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq);
+ u_tgt = tmp_type50_msg->crb1.u;
+ u_tgt_len = sizeof(tmp_type50_msg->crb1.u);
+ inp_tgt = tmp_type50_msg->crb1.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->crb1.message);
+ } else {
+ tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN;
+ tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT;
+ p_tgt = tmp_type50_msg->crb2.p;
+ p_tgt_len = sizeof(tmp_type50_msg->crb2.p);
+ q_tgt = tmp_type50_msg->crb2.q;
+ q_tgt_len = sizeof(tmp_type50_msg->crb2.q);
+ dp_tgt = tmp_type50_msg->crb2.dp;
+ dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp);
+ dq_tgt = tmp_type50_msg->crb2.dq;
+ dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq);
+ u_tgt = tmp_type50_msg->crb2.u;
+ u_tgt_len = sizeof(tmp_type50_msg->crb2.u);
+ inp_tgt = tmp_type50_msg->crb2.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->crb2.message);
+ }
+
+ p_tgt += (p_tgt_len - long_len);
+ if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len))
+ return SEN_RELEASED;
+ if (is_empty(p_tgt, long_len))
+ return SEN_USER_ERROR;
+ q_tgt += (q_tgt_len - short_len);
+ if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len))
+ return SEN_RELEASED;
+ if (is_empty(q_tgt, short_len))
+ return SEN_USER_ERROR;
+ dp_tgt += (dp_tgt_len - long_len);
+ if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len))
+ return SEN_RELEASED;
+ if (is_empty(dp_tgt, long_len))
+ return SEN_USER_ERROR;
+ dq_tgt += (dq_tgt_len - short_len);
+ if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len))
+ return SEN_RELEASED;
+ if (is_empty(dq_tgt, short_len))
+ return SEN_USER_ERROR;
+ u_tgt += (u_tgt_len - long_len);
+ if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len))
+ return SEN_RELEASED;
+ if (is_empty(u_tgt, long_len))
+ return SEN_USER_ERROR;
+ inp_tgt += (inp_tgt_len - mod_len);
+ if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(inp_tgt, mod_len))
+ return SEN_USER_ERROR;
+
+ *z90cMsg_l_p = tmp_size - CALLER_HEADER;
+
+ return 0;
+}
+
int
convert_request(unsigned char *buffer, int func, unsigned short function,
int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p)
@@ -2071,6 +2339,16 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
cdx, msg_l_p, (struct type6_msg *) msg_p,
dev_type);
}
+ if (dev_type == CEX2A) {
+ if (func == ICARSACRT)
+ return ICACRT_msg_to_type50CRT_msg(
+ (struct ica_rsa_modexpo_crt *) buffer,
+ msg_l_p, (union type50_msg *) msg_p);
+ else
+ return ICAMEX_msg_to_type50MEX_msg(
+ (struct ica_rsa_modexpo *) buffer,
+ msg_l_p, (union type50_msg *) msg_p);
+ }
return 0;
}
@@ -2081,8 +2359,8 @@ unset_ext_bitlens(void)
{
if (!ext_bitlens_msg_count) {
PRINTK("Unable to use coprocessors for extended bitlengths. "
- "Using PCICAs (if present) for extended bitlengths. "
- "This is not an error.\n");
+ "Using PCICAs/CEX2As (if present) for extended "
+ "bitlengths. This is not an error.\n");
ext_bitlens_msg_count++;
}
ext_bitlens = 0;
@@ -2094,6 +2372,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
{
struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
struct error_hdr *errh_p = (struct error_hdr *) response;
+ struct type80_hdr *t80h_p = (struct type80_hdr *) response;
struct type84_hdr *t84h_p = (struct type84_hdr *) response;
struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response;
int reply_code, service_rc, service_rs, src_l;
@@ -2108,6 +2387,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_l = 0;
switch (errh_p->type) {
case TYPE82_RSP_CODE:
+ case TYPE88_RSP_CODE:
reply_code = errh_p->reply_code;
src_p = (unsigned char *)errh_p;
PRINTK("Hardware error: Type %02X Message Header: "
@@ -2116,6 +2396,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_p[0], src_p[1], src_p[2], src_p[3],
src_p[4], src_p[5], src_p[6], src_p[7]);
break;
+ case TYPE80_RSP_CODE:
+ src_l = icaMsg_p->outputdatalength;
+ src_p = response + (int)t80h_p->len - src_l;
+ break;
case TYPE84_RSP_CODE:
src_l = icaMsg_p->outputdatalength;
src_p = response + (int)t84h_p->len - src_l;
@@ -2202,6 +2486,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (reply_code)
switch (reply_code) {
case REP82_ERROR_OPERAND_INVALID:
+ case REP88_ERROR_MESSAGE_MALFORMD:
return REC_OPERAND_INV;
case REP82_ERROR_OPERAND_SIZE:
return REC_OPERAND_SIZE;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 790fcbb74b4..2f54d033d7c 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>
@@ -228,7 +227,7 @@ struct device_x {
*/
struct device {
int dev_type; // PCICA, PCICC, PCIXCC_MCL2,
- // PCIXCC_MCL3, CEX2C
+ // PCIXCC_MCL3, CEX2C, CEX2A
enum devstat dev_stat; // current device status
int dev_self_x; // Index in array
int disabled; // Set when device is in error
@@ -295,26 +294,30 @@ struct caller {
/**
* Function prototypes from z90hardware.c
*/
-enum hdstat query_online(int, int, int, int *, int *);
-enum devstat reset_device(int, int, int);
-enum devstat send_to_AP(int, int, int, unsigned char *);
-enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *);
-int convert_request(unsigned char *, int, short, int, int, int *,
- unsigned char *);
-int convert_response(unsigned char *, unsigned char *, int *, unsigned char *);
+enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth,
+ int *dev_type);
+enum devstat reset_device(int deviceNr, int cdx, int resetNr);
+enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext);
+enum devstat receive_from_AP(int dev_nr, int cdx, int resplen,
+ unsigned char *resp, unsigned char *psmid);
+int convert_request(unsigned char *buffer, int func, unsigned short function,
+ int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p);
+int convert_response(unsigned char *response, unsigned char *buffer,
+ int *respbufflen_p, unsigned char *resp_buff);
/**
* Low level function prototypes
*/
-static int create_z90crypt(int *);
-static int refresh_z90crypt(int *);
-static int find_crypto_devices(struct status *);
-static int create_crypto_device(int);
-static int destroy_crypto_device(int);
+static int create_z90crypt(int *cdx_p);
+static int refresh_z90crypt(int *cdx_p);
+static int find_crypto_devices(struct status *deviceMask);
+static int create_crypto_device(int index);
+static int destroy_crypto_device(int index);
static void destroy_z90crypt(void);
-static int refresh_index_array(struct status *, struct device_x *);
-static int probe_device_type(struct device *);
-static int probe_PCIXCC_type(struct device *);
+static int refresh_index_array(struct status *status_str,
+ struct device_x *index_array);
+static int probe_device_type(struct device *devPtr);
+static int probe_PCIXCC_type(struct device *devPtr);
/**
* proc fs definitions
@@ -425,7 +428,7 @@ static struct miscdevice z90crypt_misc_device = {
MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
"and Jochen Roehrig");
MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
- "Copyright 2001, 2004 IBM Corporation");
+ "Copyright 2001, 2005 IBM Corporation");
MODULE_LICENSE("GPL");
module_param(domain, int, 0);
MODULE_PARM_DESC(domain, "domain index for device");
@@ -860,6 +863,12 @@ get_status_CEX2Ccount(void)
}
static inline int
+get_status_CEX2Acount(void)
+{
+ return z90crypt.hdware_info->type_mask[CEX2A].st_count;
+}
+
+static inline int
get_status_requestq_count(void)
{
return requestq_count;
@@ -1008,11 +1017,13 @@ static inline int
select_device_type(int *dev_type_p, int bytelength)
{
static int count = 0;
- int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;
+ int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail,
+ index_to_use;
struct status *stat;
if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
(*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
- (*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV))
+ (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) &&
+ (*dev_type_p != ANYDEV))
return -1;
if (*dev_type_p != ANYDEV) {
stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
@@ -1022,7 +1033,13 @@ select_device_type(int *dev_type_p, int bytelength)
return -1;
}
- /* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */
+ /**
+ * Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in
+ * speed.
+ *
+ * PCICA and CEX2A do NOT co-exist, so it would be either one or the
+ * other present.
+ */
stat = &z90crypt.hdware_info->type_mask[PCICA];
PCICA_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
@@ -1032,29 +1049,38 @@ select_device_type(int *dev_type_p, int bytelength)
stat = &z90crypt.hdware_info->type_mask[CEX2C];
CEX2C_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
- if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
+ stat = &z90crypt.hdware_info->type_mask[CEX2A];
+ CEX2A_avail = stat->st_count -
+ (stat->disabled_count + stat->user_disabled_count);
+ if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) {
/**
- * bitlength is a factor, PCICA is the most capable, even with
- * the new MCL for PCIXCC.
+ * bitlength is a factor, PCICA or CEX2A are the most capable,
+ * even with the new MCL for PCIXCC.
*/
if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
- if (!PCICA_avail)
- return -1;
- else {
+ if (PCICA_avail) {
*dev_type_p = PCICA;
return 0;
}
+ if (CEX2A_avail) {
+ *dev_type_p = CEX2A;
+ return 0;
+ }
+ return -1;
}
index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
- CEX2C_avail);
+ CEX2C_avail + CEX2A_avail);
if (index_to_use < PCICA_avail)
*dev_type_p = PCICA;
else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))
*dev_type_p = PCIXCC_MCL3;
- else
+ else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail +
+ CEX2C_avail))
*dev_type_p = CEX2C;
+ else
+ *dev_type_p = CEX2A;
count++;
return 0;
}
@@ -1359,7 +1385,7 @@ build_caller(struct work_element *we_p, short function)
if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
- (we_p->devtype != CEX2C))
+ (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A))
return SEN_NOT_AVAIL;
memcpy(caller_p->caller_id, we_p->caller_id,
@@ -1428,7 +1454,8 @@ get_crypto_request_buffer(struct work_element *we_p)
if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
- (we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) {
+ (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) &&
+ (we_p->devtype != ANYDEV)) {
PRINTK("invalid device type\n");
return SEN_USER_ERROR;
}
@@ -1503,8 +1530,9 @@ get_crypto_request_buffer(struct work_element *we_p)
function = PCI_FUNC_KEY_ENCRYPT;
switch (we_p->devtype) {
- /* PCICA does everything with a simple RSA mod-expo operation */
+ /* PCICA and CEX2A do everything with a simple RSA mod-expo operation */
case PCICA:
+ case CEX2A:
function = PCI_FUNC_KEY_ENCRYPT;
break;
/**
@@ -1662,7 +1690,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
* trigger a fallback to software.
*/
case -EINVAL:
- if (we_p->devtype != PCICA)
+ if ((we_p->devtype != PCICA) &&
+ (we_p->devtype != CEX2A))
rv = -EGETBUFF;
break;
case -ETIMEOUT:
@@ -1779,6 +1808,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ret = -EFAULT;
break;
+ case Z90STAT_CEX2ACOUNT:
+ tempstat = get_status_CEX2Acount();
+ if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
+ ret = -EFAULT;
+ break;
+
case Z90STAT_REQUESTQ_COUNT:
tempstat = get_status_requestq_count();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
@@ -2019,6 +2054,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
get_status_PCIXCCMCL3count());
len += sprintf(resp_buff+len, "CEX2C count: %d\n",
get_status_CEX2Ccount());
+ len += sprintf(resp_buff+len, "CEX2A count: %d\n",
+ get_status_CEX2Acount());
len += sprintf(resp_buff+len, "requestq count: %d\n",
get_status_requestq_count());
len += sprintf(resp_buff+len, "pendingq count: %d\n",
@@ -2026,8 +2063,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
get_status_totalopen_count());
len += sprinthx(
- "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), "
- "4: PCIXCC (MCL3), 5: CEX2C",
+ "Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
+ "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A",
resp_buff+len,
get_status_status_mask(workarea),
Z90CRYPT_NUM_APS);
@@ -2140,6 +2177,7 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
case '3': // PCIXCC_MCL2
case '4': // PCIXCC_MCL3
case '5': // CEX2C
+ case '6': // CEX2A
j++;
break;
case 'd':
@@ -3007,7 +3045,9 @@ create_crypto_device(int index)
z90crypt.hdware_info->device_type_array[index] = 4;
else if (deviceType == CEX2C)
z90crypt.hdware_info->device_type_array[index] = 5;
- else
+ else if (deviceType == CEX2A)
+ z90crypt.hdware_info->device_type_array[index] = 6;
+ else // No idea how this would happen.
z90crypt.hdware_info->device_type_array[index] = -1;
}
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index a7efc394515..54885475492 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -1,5 +1,5 @@
menu "S/390 network device drivers"
- depends on NETDEVICES && ARCH_S390
+ depends on NETDEVICES && S390
config LCS
tristate "Lan Channel Station Interface"
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 6b63d21612e..e70af7f3994 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -1603,7 +1603,7 @@ dumpit(char* buf, int len)
__u32 ct, sw, rm, dup;
char *ptr, *rptr;
char tbuf[82], tdup[82];
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
char addr[22];
#else
char addr[12];
@@ -1619,7 +1619,7 @@ dumpit(char* buf, int len)
dup = 0;
for ( ct=0; ct < len; ct++, ptr++, rptr++ ) {
if (sw == 0) {
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
sprintf(addr, "%16.16lX",(unsigned long)rptr);
#else
sprintf(addr, "%8.8X",(__u32)rptr);
@@ -1634,7 +1634,7 @@ dumpit(char* buf, int len)
if (sw == 8) {
strcat(bhex, " ");
}
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
#else
sprintf(tbuf,"%2.2X", (__u32)*ptr);
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 968f2c113ef..93d1725eb79 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 0075894c71d..77dacb46573 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,5 +1,5 @@
/*
- * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $
+ * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $
*
* CTC / LCS ccw_device driver
*
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/err.h>
+#include <asm/s390_rdev.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index df7647c3c10..ea817739256 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $
+ * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $
*
* IUCV network driver
*
@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $
*
*/
@@ -54,7 +54,7 @@
#include <asm/s390_ext.h>
#include <asm/ebcdic.h>
#include <asm/smp.h>
-#include <asm/ccwdev.h> //for root device stuff
+#include <asm/s390_rdev.h>
/* FLAGS:
* All flags are defined in the field IPFLAGS1 of each function
@@ -355,7 +355,7 @@ do { \
static void
iucv_banner(void)
{
- char vbuf[] = "$Revision: 1.45 $";
+ char vbuf[] = "$Revision: 1.47 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
@@ -477,7 +477,7 @@ grab_param(void)
ptr++;
if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
ptr = iucv_param_pool;
- } while (atomic_compare_and_swap(0, 1, &ptr->in_use));
+ } while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
hint = ptr - iucv_param_pool;
memset(&ptr->param, 0, sizeof(ptr->param));
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index f8f55cc468b..97f927c01a8 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -65,6 +65,7 @@
#include <asm/timex.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
+#include <asm/s390_rdev.h>
#include "qeth.h"
#include "qeth_mpc.h"
@@ -1396,7 +1397,7 @@ qeth_idx_activate_get_answer(struct qeth_channel *channel,
channel->ccw.cda = (__u32) __pa(iob->data);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+ atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(setup, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
@@ -1463,7 +1464,7 @@ qeth_idx_activate_channel(struct qeth_channel *channel,
memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+ atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(setup, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
@@ -1616,7 +1617,7 @@ qeth_issue_next_read(struct qeth_card *card)
}
qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&card->read.irq_pending) == 0);
+ atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(trace, 6, "noirqpnd");
rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
(addr_t) iob, 0, 0);
@@ -1882,7 +1883,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
spin_unlock_irqrestore(&card->lock, flags);
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
qeth_prepare_control_data(card, len, iob);
if (IS_IPA(iob->data))
timer.expires = jiffies + QETH_IPA_TIMEOUT;
@@ -1924,7 +1925,7 @@ qeth_osn_send_control_data(struct qeth_card *card, int len,
QETH_DBF_TEXT(trace, 5, "osndctrd");
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
qeth_prepare_control_data(card, len, iob);
QETH_DBF_TEXT(trace, 6, "osnoirqp");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
@@ -4236,9 +4237,8 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
QETH_DBF_TEXT(trace, 6, "dosndpfa");
/* spin until we get the queue ... */
- while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
- QETH_OUT_Q_LOCKED,
- &queue->state));
+ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+ QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
/* ... now we've got the queue */
index = queue->next_buf_to_fill;
buffer = &queue->bufs[queue->next_buf_to_fill];
@@ -4292,9 +4292,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
QETH_DBF_TEXT(trace, 6, "dosndpkt");
/* spin until we get the queue ... */
- while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
- QETH_OUT_Q_LOCKED,
- &queue->state));
+ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+ QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
start_index = queue->next_buf_to_fill;
buffer = &queue->bufs[queue->next_buf_to_fill];
/*
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
new file mode 100644
index 00000000000..566cc3d185b
--- /dev/null
+++ b/drivers/s390/s390_rdev.c
@@ -0,0 +1,53 @@
+/*
+ * drivers/s390/s390_rdev.c
+ * s390 root device
+ * $Revision: 1.2 $
+ *
+ * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
+ * IBM Corporation
+ * Author(s): Cornelia Huck (cohuck@de.ibm.com)
+ * Carsten Otte (cotte@de.ibm.com)
+ */
+
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <asm/s390_rdev.h>
+
+static void
+s390_root_dev_release(struct device *dev)
+{
+ kfree(dev);
+}
+
+struct device *
+s390_root_dev_register(const char *name)
+{
+ struct device *dev;
+ int ret;
+
+ if (!strlen(name))
+ return ERR_PTR(-EINVAL);
+ dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+ memset(dev, 0, sizeof(struct device));
+ strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
+ dev->release = s390_root_dev_release;
+ ret = device_register(dev);
+ if (ret) {
+ kfree(dev);
+ return ERR_PTR(ret);
+ }
+ return dev;
+}
+
+void
+s390_root_dev_unregister(struct device *dev)
+{
+ if (dev)
+ device_unregister(dev);
+}
+
+EXPORT_SYMBOL(s390_root_dev_register);
+EXPORT_SYMBOL(s390_root_dev_unregister);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 4191fd9d4d1..3bf46660351 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -23,7 +23,7 @@
static struct semaphore m_sem;
-extern int css_process_crw(int);
+extern int css_process_crw(int, int);
extern int chsc_process_crw(void);
extern int chp_process_crw(int, int);
extern void css_reiterate_subchannels(void);
@@ -49,9 +49,10 @@ s390_handle_damage(char *msg)
static int
s390_collect_crw_info(void *param)
{
- struct crw crw;
+ struct crw crw[2];
int ccode, ret, slow;
struct semaphore *sem;
+ unsigned int chain;
sem = (struct semaphore *)param;
/* Set a nice name. */
@@ -59,25 +60,50 @@ s390_collect_crw_info(void *param)
repeat:
down_interruptible(sem);
slow = 0;
+ chain = 0;
while (1) {
- ccode = stcrw(&crw);
+ if (unlikely(chain > 1)) {
+ struct crw tmp_crw;
+
+ printk(KERN_WARNING"%s: Code does not support more "
+ "than two chained crws; please report to "
+ "linux390@de.ibm.com!\n", __FUNCTION__);
+ ccode = stcrw(&tmp_crw);
+ printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+ "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+ __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
+ tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+ tmp_crw.erc, tmp_crw.rsid);
+ printk(KERN_WARNING"%s: This was crw number %x in the "
+ "chain\n", __FUNCTION__, chain);
+ if (ccode != 0)
+ break;
+ chain = tmp_crw.chn ? chain + 1 : 0;
+ continue;
+ }
+ ccode = stcrw(&crw[chain]);
if (ccode != 0)
break;
DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
"chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
- crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc,
- crw.erc, crw.rsid);
+ crw[chain].slct, crw[chain].oflw, crw[chain].chn,
+ crw[chain].rsc, crw[chain].anc, crw[chain].erc,
+ crw[chain].rsid);
/* Check for overflows. */
- if (crw.oflw) {
+ if (crw[chain].oflw) {
pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
css_reiterate_subchannels();
+ chain = 0;
slow = 1;
continue;
}
- switch (crw.rsc) {
+ switch (crw[chain].rsc) {
case CRW_RSC_SCH:
- pr_debug("source is subchannel %04X\n", crw.rsid);
- ret = css_process_crw (crw.rsid);
+ if (crw[0].chn && !chain)
+ break;
+ pr_debug("source is subchannel %04X\n", crw[0].rsid);
+ ret = css_process_crw (crw[0].rsid,
+ chain ? crw[1].rsid : 0);
if (ret == -EAGAIN)
slow = 1;
break;
@@ -85,18 +111,18 @@ repeat:
pr_debug("source is monitoring facility\n");
break;
case CRW_RSC_CPATH:
- pr_debug("source is channel path %02X\n", crw.rsid);
- switch (crw.erc) {
+ pr_debug("source is channel path %02X\n", crw[0].rsid);
+ switch (crw[0].erc) {
case CRW_ERC_IPARM: /* Path has come. */
- ret = chp_process_crw(crw.rsid, 1);
+ ret = chp_process_crw(crw[0].rsid, 1);
break;
case CRW_ERC_PERRI: /* Path has gone. */
case CRW_ERC_PERRN:
- ret = chp_process_crw(crw.rsid, 0);
+ ret = chp_process_crw(crw[0].rsid, 0);
break;
default:
pr_debug("Don't know how to handle erc=%x\n",
- crw.erc);
+ crw[0].erc);
ret = 0;
}
if (ret == -EAGAIN)
@@ -115,6 +141,8 @@ repeat:
pr_debug("unknown source\n");
break;
}
+ /* chain is always 0 or 1 here. */
+ chain = crw[chain].chn ? chain + 1 : 0;
}
if (slow)
queue_work(slow_path_wq, &slow_path_work);
@@ -218,7 +246,7 @@ s390_revalidate_registers(struct mci *mci)
*/
kill_task = 1;
-#ifndef __s390x__
+#ifndef CONFIG_64BIT
asm volatile("ld 0,0(%0)\n"
"ld 2,8(%0)\n"
"ld 4,16(%0)\n"
@@ -227,7 +255,7 @@ s390_revalidate_registers(struct mci *mci)
#endif
if (MACHINE_HAS_IEEE) {
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
fpt_save_area = &S390_lowcore.floating_pt_save_area;
fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
#else
@@ -286,7 +314,7 @@ s390_revalidate_registers(struct mci *mci)
*/
s390_handle_damage("invalid control registers.");
else
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
asm volatile("lctlg 0,15,0(%0)"
: : "a" (&S390_lowcore.cregs_save_area));
#else
@@ -299,7 +327,7 @@ s390_revalidate_registers(struct mci *mci)
* can't write something sensible into that register.
*/
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
/*
* See if we can revalidate the TOD programmable register with its
* old contents (should be zero) otherwise set it to zero.
@@ -356,7 +384,7 @@ s390_do_machine_check(struct pt_regs *regs)
if (mci->b) {
/* Processing backup -> verify if we can survive this */
u64 z_mcic, o_mcic, t_mcic;
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 87c2db1bd4f..66da840c931 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -106,7 +106,7 @@ static inline int stsi (void *sysinfo,
{
int cc, retv;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
__asm__ __volatile__ ( "lr\t0,%2\n"
"\tlr\t1,%3\n"
"\tstsi\t0(%4)\n"
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4c42065dea8..3c606cf8c8c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -914,7 +914,7 @@ config SCSI_INIA100
config SCSI_PPA
tristate "IOMEGA parallel port (ppa - older drives)"
- depends on SCSI && PARPORT
+ depends on SCSI && PARPORT_PC
---help---
This driver supports older versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -941,7 +941,7 @@ config SCSI_PPA
config SCSI_IMM
tristate "IOMEGA parallel port (imm - newer drives)"
- depends on SCSI && PARPORT
+ depends on SCSI && PARPORT_PC
---help---
This driver supports newer versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -968,7 +968,7 @@ config SCSI_IMM
config SCSI_IZIP_EPP16
bool "ppa/imm option - Use slow (but safe) EPP-16"
- depends on PARPORT && (SCSI_PPA || SCSI_IMM)
+ depends on SCSI_PPA || SCSI_IMM
---help---
EPP (Enhanced Parallel Port) is a standard for parallel ports which
allows them to act as expansion buses that can handle up to 64
@@ -983,7 +983,7 @@ config SCSI_IZIP_EPP16
config SCSI_IZIP_SLOW_CTR
bool "ppa/imm option - Assume slow parport control register"
- depends on PARPORT && (SCSI_PPA || SCSI_IMM)
+ depends on SCSI_PPA || SCSI_IMM
help
Some parallel ports are known to have excessive delays between
changing the parallel port control register and good data being
@@ -1815,7 +1815,7 @@ config SCSI_SUNESP
config ZFCP
tristate "FCP host bus adapter driver for IBM eServer zSeries"
- depends on ARCH_S390 && QDIO && SCSI
+ depends on S390 && QDIO && SCSI
select SCSI_FC_ATTRS
help
If you want to access SCSI devices attached to your IBM eServer
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index f062ea0f813..6e0c059df6a 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
@@ -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 640590bd014..c7dd0154d01 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/linit.c b/drivers/scsi/aacraid/linit.c
index 3cb68af9045..9b9062f0246 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>
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 887eaa2a3eb..d113290b5fc 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -214,7 +214,6 @@ static struct scsi_host_template ahci_sht = {
.dma_boundary = AHCI_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations ahci_ops = {
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 09ed05727bc..dda5a5f79c5 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 804125e35fc..a2894015670 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 81e266be26d..e6c9491dc5c 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 3a7a46b0dc4..583d2d8c833 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 4d1e8f52c92..3ffec7efc9d 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 3333d7b3913..3113bdcedb1 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 0ea27873b9f..557788ec4ee 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -166,6 +166,8 @@ static struct pci_driver piix_pci_driver = {
.id_table = piix_pci_tbl,
.probe = piix_init_one,
.remove = ata_pci_remove_one,
+ .suspend = ata_pci_device_suspend,
+ .resume = ata_pci_device_resume,
};
static struct scsi_host_template piix_sht = {
@@ -185,7 +187,8 @@ static struct scsi_host_template piix_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
+ .resume = ata_scsi_device_resume,
+ .suspend = ata_scsi_device_suspend,
};
static const struct ata_port_operations piix_pata_ops = {
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
index 763e409a1ff..3867ac2de4c 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 d72d05fffdf..4ebe69e3275 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 0920220f331..4299fabca55 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/chio.h> /* here are all the ioctls */
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
index f9b940e5643..a4a4fac5c0a 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 a3caabfd755..3a803d73bc5 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/fastlane.c b/drivers/scsi/fastlane.c
index ccee68b52f7..8ae9c406a83 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/hosts.c b/drivers/scsi/hosts.c
index 5b9c2c5a7f0..66783c860a1 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -347,17 +347,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->cmd_per_lun = sht->cmd_per_lun;
shost->unchecked_isa_dma = sht->unchecked_isa_dma;
shost->use_clustering = sht->use_clustering;
- shost->ordered_flush = sht->ordered_flush;
shost->ordered_tag = sht->ordered_tag;
- /*
- * hosts/devices that do queueing must support ordered tags
- */
- if (shost->can_queue > 1 && shost->ordered_flush) {
- printk(KERN_ERR "scsi: ordered flushes don't support queueing\n");
- shost->ordered_flush = 0;
- }
-
if (sht->max_host_blocked)
shost->max_host_blocked = sht->max_host_blocked;
else
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 4cb1f3ed910..3c688ef5466 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -1046,7 +1046,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
/* kill current request */
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
if (req->flags & REQ_SENSE)
kfree(scsi->pc->buffer);
kfree(scsi->pc);
@@ -1056,7 +1056,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
/* now nuke the drive queue */
while ((req = elv_next_request(drive->queue))) {
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
}
HWGROUP(drive)->rq = NULL;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9ea10258791..f55b9b3f7b3 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = {
ATA_CMD_WRITE_MULTI,
ATA_CMD_READ_MULTI_EXT,
ATA_CMD_WRITE_MULTI_EXT,
+ 0,
+ 0,
+ 0,
+ ATA_CMD_WRITE_MULTI_FUA_EXT,
/* pio */
ATA_CMD_PIO_READ,
ATA_CMD_PIO_WRITE,
ATA_CMD_PIO_READ_EXT,
ATA_CMD_PIO_WRITE_EXT,
+ 0,
+ 0,
+ 0,
+ 0,
/* dma */
ATA_CMD_READ,
ATA_CMD_WRITE,
ATA_CMD_READ_EXT,
- ATA_CMD_WRITE_EXT
+ ATA_CMD_WRITE_EXT,
+ 0,
+ 0,
+ 0,
+ ATA_CMD_WRITE_FUA_EXT
};
/**
@@ -584,25 +596,32 @@ static const u8 ata_rw_cmds[] = {
* LOCKING:
* caller.
*/
-void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
{
struct ata_taskfile *tf = &qc->tf;
struct ata_device *dev = qc->dev;
+ u8 cmd;
- int index, lba48, write;
+ int index, fua, lba48, write;
+ fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
if (dev->flags & ATA_DFLAG_PIO) {
tf->protocol = ATA_PROT_PIO;
- index = dev->multi_count ? 0 : 4;
+ index = dev->multi_count ? 0 : 8;
} else {
tf->protocol = ATA_PROT_DMA;
- index = 8;
+ index = 16;
}
- tf->command = ata_rw_cmds[index + lba48 + write];
+ cmd = ata_rw_cmds[index + fua + lba48 + write];
+ if (cmd) {
+ tf->command = cmd;
+ return 0;
+ }
+ return -1;
}
static const char * const xfer_mode_str[] = {
@@ -4154,6 +4173,96 @@ err_out:
* Inherited from caller.
*/
+/*
+ * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
+ * without filling any other registers
+ */
+static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
+ u8 cmd)
+{
+ struct ata_taskfile tf;
+ int err;
+
+ ata_tf_init(ap, &tf, dev->devno);
+
+ tf.command = cmd;
+ tf.flags |= ATA_TFLAG_DEVICE;
+ tf.protocol = ATA_PROT_NODATA;
+
+ err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+ if (err)
+ printk(KERN_ERR "%s: ata command failed: %d\n",
+ __FUNCTION__, err);
+
+ return err;
+}
+
+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+{
+ u8 cmd;
+
+ if (!ata_try_flush_cache(dev))
+ return 0;
+
+ if (ata_id_has_flush_ext(dev->id))
+ cmd = ATA_CMD_FLUSH_EXT;
+ else
+ cmd = ATA_CMD_FLUSH;
+
+ return ata_do_simple_cmd(ap, dev, cmd);
+}
+
+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+{
+ return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+}
+
+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+{
+ return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+}
+
+/**
+ * ata_device_resume - wakeup a previously suspended devices
+ *
+ * Kick the drive back into action, by sending it an idle immediate
+ * command and making sure its transfer mode matches between drive
+ * and host.
+ *
+ */
+int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+{
+ if (ap->flags & ATA_FLAG_SUSPENDED) {
+ ap->flags &= ~ATA_FLAG_SUSPENDED;
+ ata_set_mode(ap);
+ }
+ if (!ata_dev_present(dev))
+ return 0;
+ if (dev->class == ATA_DEV_ATA)
+ ata_start_drive(ap, dev);
+
+ return 0;
+}
+
+/**
+ * ata_device_suspend - prepare a device for suspend
+ *
+ * Flush the cache on the drive, if appropriate, then issue a
+ * standbynow command.
+ *
+ */
+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
+{
+ if (!ata_dev_present(dev))
+ return 0;
+ if (dev->class == ATA_DEV_ATA)
+ ata_flush_cache(ap, dev);
+
+ ata_standby_drive(ap, dev);
+ ap->flags |= ATA_FLAG_SUSPENDED;
+ return 0;
+}
+
int ata_port_start (struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
@@ -4902,6 +5011,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0;
}
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+ return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ return 0;
+}
#endif /* CONFIG_PCI */
@@ -5005,4 +5131,11 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
#endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL_GPL(ata_device_suspend);
+EXPORT_SYMBOL_GPL(ata_device_resume);
+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
+EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index e0439be4b57..cfbceb50471 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -396,6 +396,22 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
}
}
+int ata_scsi_device_resume(struct scsi_device *sdev)
+{
+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+ struct ata_device *dev = &ap->device[sdev->id];
+
+ return ata_device_resume(ap, dev);
+}
+
+int ata_scsi_device_suspend(struct scsi_device *sdev)
+{
+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+ struct ata_device *dev = &ap->device[sdev->id];
+
+ return ata_device_suspend(ap, dev);
+}
+
/**
* ata_to_sense_error - convert ATA error to SCSI error
* @id: ATA device number
@@ -1080,11 +1096,13 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
scsicmd[0] == WRITE_16)
tf->flags |= ATA_TFLAG_WRITE;
- /* Calculate the SCSI LBA and transfer length. */
+ /* Calculate the SCSI LBA, transfer length and FUA. */
switch (scsicmd[0]) {
case READ_10:
case WRITE_10:
scsi_10_lba_len(scsicmd, &block, &n_block);
+ if (unlikely(scsicmd[1] & (1 << 3)))
+ tf->flags |= ATA_TFLAG_FUA;
break;
case READ_6:
case WRITE_6:
@@ -1099,6 +1117,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
case READ_16:
case WRITE_16:
scsi_16_lba_len(scsicmd, &block, &n_block);
+ if (unlikely(scsicmd[1] & (1 << 3)))
+ tf->flags |= ATA_TFLAG_FUA;
break;
default:
DPRINTK("no-byte command\n");
@@ -1142,7 +1162,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
tf->device |= (block >> 24) & 0xf;
}
- ata_rwcmd_protocol(qc);
+ if (unlikely(ata_rwcmd_protocol(qc) < 0))
+ goto invalid_fld;
qc->nsect = n_block;
tf->nsect = n_block & 0xff;
@@ -1160,7 +1181,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
if ((block >> 28) || (n_block > 256))
goto out_of_range;
- ata_rwcmd_protocol(qc);
+ if (unlikely(ata_rwcmd_protocol(qc) < 0))
+ goto invalid_fld;
/* Convert LBA to CHS */
track = (u32)block / dev->sectors;
@@ -1695,6 +1717,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{
+ struct ata_device *dev = args->dev;
u8 *scsicmd = args->cmd->cmnd, *p, *last;
const u8 sat_blk_desc[] = {
0, 0, 0, 0, /* number of blocks: sat unspecified */
@@ -1703,6 +1726,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
};
u8 pg, spg;
unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+ u8 dpofua;
VPRINTK("ENTER\n");
@@ -1771,9 +1795,17 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
if (minlen < 1)
return 0;
+
+ dpofua = 0;
+ if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+ (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
+ dpofua = 1 << 4;
+
if (six_byte) {
output_len--;
rbuf[0] = output_len;
+ if (minlen > 2)
+ rbuf[2] |= dpofua;
if (ebd) {
if (minlen > 3)
rbuf[3] = sizeof(sat_blk_desc);
@@ -1786,6 +1818,8 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
rbuf[0] = output_len >> 8;
if (minlen > 1)
rbuf[1] = output_len;
+ if (minlen > 3)
+ rbuf[3] |= dpofua;
if (ebd) {
if (minlen > 7)
rbuf[7] = sizeof(sat_blk_desc);
@@ -2446,7 +2480,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
if (xlat_func)
ata_scsi_translate(ap, dev, cmd, done, xlat_func);
else
- ata_scsi_simulate(dev->id, cmd, done);
+ ata_scsi_simulate(ap, dev, cmd, done);
} else
ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
@@ -2469,14 +2503,16 @@ out_unlock:
* spin_lock_irqsave(host_set lock)
*/
-void ata_scsi_simulate(u16 *id,
+void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
struct ata_scsi_args args;
const u8 *scsicmd = cmd->cmnd;
- args.id = id;
+ args.ap = ap;
+ args.dev = dev;
+ args.id = dev->id;
args.cmd = cmd;
args.done = done;
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 251e53bdc6e..e03ce48b7b4 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -32,6 +32,8 @@
#define DRV_VERSION "1.20" /* must be exactly four chars */
struct ata_scsi_args {
+ struct ata_port *ap;
+ struct ata_device *dev;
u16 *id;
struct scsi_cmnd *cmd;
void (*done)(struct scsi_cmnd *);
@@ -41,7 +43,7 @@ struct ata_scsi_args {
extern int atapi_enabled;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
-extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 932dcf0366e..311a4122bd7 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/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index eb8c390a0fa..3d9e67d6849 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/mesh.c b/drivers/scsi/mesh.c
index bdccf73cf9f..d6d2125f904 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 5d9c9ada814..dee426f8c07 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/sata_mv.c b/drivers/scsi/sata_mv.c
index b2bf16a9bf4..cd54244058b 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -374,7 +374,6 @@ static struct scsi_host_template mv_sht = {
.dma_boundary = MV_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations mv5_ops = {
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 4954896dfdb..bbbb55eeb73 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[] = {
@@ -235,7 +241,6 @@ static struct scsi_host_template nv_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations nv_ops = {
@@ -310,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);
@@ -498,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;
@@ -523,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)
@@ -561,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;
@@ -586,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 da7fa04b8a7..3d1ea09a06a 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -114,7 +114,6 @@ static struct scsi_host_template pdc_ata_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations pdc_sata_ops = {
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index d2053487c73..b017f85e6d6 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -147,7 +147,6 @@ static struct scsi_host_template sil_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations sil_ops = {
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index a0ad3ed2200..923130185a9 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -292,7 +292,6 @@ static struct scsi_host_template sil24_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1, /* NCQ not supported yet */
};
static const struct ata_port_operations sil24_ops = {
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 32e12620b16..2df8c5632ac 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -99,7 +99,6 @@ static struct scsi_host_template sis_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations sis_ops = {
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 6e7f7c83a75..668373590aa 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -303,7 +303,6 @@ static struct scsi_host_template k2_sata_sht = {
.proc_info = k2_sata_proc_info,
#endif
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 94b253b80da..bc87c16c80d 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -194,7 +194,6 @@ static struct scsi_host_template pdc_sata_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations pdc_20621_ops = {
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index b2422a0f25c..9635ca70097 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -87,7 +87,6 @@ static struct scsi_host_template uli_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations uli_ops = {
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index c76215692da..6d5b0a794cf 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -106,7 +106,6 @@ static struct scsi_host_template svia_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations svia_sata_ops = {
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index fcfa486965b..2e2c3b7acb0 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -235,7 +235,6 @@ static struct scsi_host_template vsc_sata_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 180676d7115..ee5f4dfdab1 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -69,7 +69,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.
@@ -752,7 +751,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 +762,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 +782,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 +1215,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 +1248,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 +1275,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_lib.c b/drivers/scsi/scsi_lib.c
index a7f3f0c84db..00c9bf383e2 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -308,7 +308,7 @@ struct scsi_io_context {
static kmem_cache_t *scsi_io_context_cache;
-static void scsi_end_async(struct request *req)
+static void scsi_end_async(struct request *req, int uptodate)
{
struct scsi_io_context *sioc = req->end_io_data;
@@ -791,7 +791,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
spin_lock_irqsave(q->queue_lock, flags);
if (blk_rq_tagged(req))
blk_queue_end_tag(q, req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
spin_unlock_irqrestore(q->queue_lock, flags);
/*
@@ -932,9 +932,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
int sense_valid = 0;
int sense_deferred = 0;
- if (blk_complete_barrier_rq(q, req, good_bytes >> 9))
- return;
-
/*
* Free up any indirection buffers we allocated for DMA purposes.
* For the case of a READ, we need to copy the data out of the
@@ -1199,38 +1196,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
return BLKPREP_KILL;
}
-static int scsi_prepare_flush_fn(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct scsi_driver *drv;
-
- if (sdev->sdev_state == SDEV_RUNNING) {
- drv = *(struct scsi_driver **) rq->rq_disk->private_data;
-
- if (drv->prepare_flush)
- return drv->prepare_flush(q, rq);
- }
-
- return 0;
-}
-
-static void scsi_end_flush_fn(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct request *flush_rq = rq->end_io_data;
- struct scsi_driver *drv;
-
- if (flush_rq->errors) {
- printk("scsi: barrier error, disabling flush support\n");
- blk_queue_ordered(q, QUEUE_ORDERED_NONE);
- }
-
- if (sdev->sdev_state == SDEV_RUNNING) {
- drv = *(struct scsi_driver **) rq->rq_disk->private_data;
- drv->end_flush(q, rq);
- }
-}
-
static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
@@ -1528,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()
*
@@ -1702,17 +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);
-
- /*
- * ordered tags are superior to flush ordering
- */
- if (shost->ordered_tag)
- blk_queue_ordered(q, QUEUE_ORDERED_TAG);
- else if (shost->ordered_flush) {
- blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
- q->prepare_flush_fn = scsi_prepare_flush_fn;
- q->end_flush_fn = scsi_end_flush_fn;
- }
+ 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 f04e7e11f57..14a6198cb8d 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -44,6 +44,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_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 15842b1f0f4..ea7f3a43357 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -263,9 +263,40 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
}
+static int scsi_bus_suspend(struct device * dev, pm_message_t state)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_host_template *sht = sdev->host->hostt;
+ int err;
+
+ err = scsi_device_quiesce(sdev);
+ if (err)
+ return err;
+
+ if (sht->suspend)
+ err = sht->suspend(sdev);
+
+ return err;
+}
+
+static int scsi_bus_resume(struct device * dev)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_host_template *sht = sdev->host->hostt;
+ int err = 0;
+
+ if (sht->resume)
+ err = sht->resume(sdev);
+
+ scsi_device_resume(sdev);
+ return err;
+}
+
struct bus_type scsi_bus_type = {
.name = "scsi",
.match = scsi_bus_match,
+ .suspend = scsi_bus_suspend,
+ .resume = scsi_bus_resume,
};
int scsi_sysfs_register(void)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3d3ad7d1b77..4c5127ed379 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -102,6 +102,7 @@ struct scsi_disk {
u8 write_prot;
unsigned WCE : 1; /* state of disk WCE bit */
unsigned RCD : 1; /* state of disk RCD bit, unused */
+ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
};
static DEFINE_IDR(sd_index_idr);
@@ -121,8 +122,7 @@ static void sd_shutdown(struct device *dev);
static void sd_rescan(struct device *);
static int sd_init_command(struct scsi_cmnd *);
static int sd_issue_flush(struct device *, sector_t *);
-static void sd_end_flush(request_queue_t *, struct request *);
-static int sd_prepare_flush(request_queue_t *, struct request *);
+static void sd_prepare_flush(request_queue_t *, struct request *);
static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
unsigned char *buffer);
@@ -137,8 +137,6 @@ static struct scsi_driver sd_template = {
.rescan = sd_rescan,
.init_command = sd_init_command,
.issue_flush = sd_issue_flush,
- .prepare_flush = sd_prepare_flush,
- .end_flush = sd_end_flush,
};
/*
@@ -346,6 +344,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
if (block > 0xffffffff) {
SCpnt->cmnd[0] += READ_16 - READ_6;
+ SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0;
SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0;
@@ -365,6 +364,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
this_count = 0xffff;
SCpnt->cmnd[0] += READ_10 - READ_6;
+ SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
@@ -373,6 +373,17 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
} else {
+ if (unlikely(blk_fua_rq(rq))) {
+ /*
+ * This happens only if this drive failed
+ * 10byte rw command with ILLEGAL_REQUEST
+ * during operation and thus turned off
+ * use_10_for_rw.
+ */
+ printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n");
+ return 0;
+ }
+
SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff);
SCpnt->cmnd[3] = (unsigned char) block & 0xff;
@@ -516,7 +527,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;
@@ -534,15 +545,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;
}
@@ -582,12 +587,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
@@ -729,42 +728,13 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector)
return ret;
}
-static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
+static void sd_prepare_flush(request_queue_t *q, struct request *rq)
{
- struct request *rq = flush_rq->end_io_data;
- struct scsi_cmnd *cmd = rq->special;
- unsigned int bytes = rq->hard_nr_sectors << 9;
-
- if (!flush_rq->errors) {
- spin_unlock(q->queue_lock);
- scsi_io_completion(cmd, bytes, 0);
- spin_lock(q->queue_lock);
- } else if (blk_barrier_postflush(rq)) {
- spin_unlock(q->queue_lock);
- scsi_io_completion(cmd, 0, bytes);
- spin_lock(q->queue_lock);
- } else {
- /*
- * force journal abort of barriers
- */
- end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors);
- end_that_request_last(rq);
- }
-}
-
-static int sd_prepare_flush(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev);
-
- if (!sdkp || !sdkp->WCE)
- return 0;
-
memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+ rq->flags |= REQ_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
rq->cmd[0] = SYNCHRONIZE_CACHE;
- return 1;
+ rq->cmd_len = 10;
}
static void sd_rescan(struct device *dev)
@@ -818,6 +788,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
@@ -1427,10 +1398,18 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
sdkp->RCD = 0;
}
+ sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
+ if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+ printk(KERN_NOTICE "SCSI device %s: uses "
+ "READ/WRITE(6), disabling FUA\n", diskname);
+ sdkp->DPOFUA = 0;
+ }
+
ct = sdkp->RCD + 2*sdkp->WCE;
- printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n",
- diskname, types[ct]);
+ printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n",
+ diskname, types[ct],
+ sdkp->DPOFUA ? " w/ FUA" : "");
return;
}
@@ -1462,6 +1441,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
unsigned char *buffer;
+ unsigned ordered;
SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
@@ -1498,7 +1478,21 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
sd_read_cache_type(sdkp, disk->disk_name, buffer);
}
-
+
+ /*
+ * We now have all cache related info, determine how we deal
+ * with ordered requests. Note that as the current SCSI
+ * dispatch function can alter request order, we cannot use
+ * QUEUE_ORDERED_TAG_* even when ordered tag is supported.
+ */
+ if (sdkp->WCE)
+ ordered = sdkp->DPOFUA
+ ? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH;
+ else
+ ordered = QUEUE_ORDERED_DRAIN;
+
+ blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush);
+
set_capacity(disk, sdkp->capacity);
kfree(buffer);
@@ -1598,6 +1592,7 @@ static int sd_probe(struct device *dev)
strcpy(gd->devfs_name, sdp->devfs_name);
gd->private_data = &sdkp->driver;
+ gd->queue = sdkp->device->request_queue;
sd_revalidate_disk(gd);
@@ -1605,7 +1600,6 @@ static int sd_probe(struct device *dev)
gd->flags = GENHD_FL_DRIVERFS;
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;
- gd->queue = sdkp->device->request_queue;
dev_set_drvdata(dev, sdkp);
add_disk(gd);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 221e96e2620..78aad9582bc 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/wd33c93.c b/drivers/scsi/wd33c93.c
index fd63add6a57..fb53eeaee61 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 b5cf39468d1..221999bcf8f 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 67e9afa000c..4dd5c3f9816 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -294,7 +294,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 +332,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 170c9d2a749..60f5a5dc17f 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 d2bcd1f87cd..fb610c3634a 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)
@@ -2480,7 +2468,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 +2477,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 +2486,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 +2495,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 +2523,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 +2545,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 +2562,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 +2572,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 +2580,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++)
@@ -2653,6 +2644,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 a607b98016d..490606b8709 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 8adca0ce267..589fb076654 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,
@@ -1029,6 +1039,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 +1183,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,
@@ -1801,6 +1849,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,
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 812bae62c8e..843717275d4 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
@@ -270,6 +280,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 240, minor 0-4) 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 +403,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
@@ -873,7 +894,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
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d7c7c7180e3..24a583e482b 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,4 @@ 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_AT91) += at91_serial.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index ddd0307fece..3490022e9fd 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 d84476ee659..034a029e356 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 00000000000..0e206063d68
--- /dev/null
+++ b/drivers/serial/at91_serial.c
@@ -0,0 +1,894 @@
+/*
+ * 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);
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ goto ignore_char;
+ 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 a274ebf256a..ceb5d7f37bb 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 87ef368384f..8ef999481f9 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 987d22b53c2..16af5626c24 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 08c42c00018..be12623d854 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 4d8516d1bb7..a64ba26a94e 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 eb31125c6a3..144a7a352b2 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 83c4c121658..5c098be9346 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);
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 771676abee6..1d85533d46d 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 ef132349f31..66f117d1506 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 b0ecc7537ce..b48066a64a7 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 47f7404cb04..d957a3a9edf 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 b8727d9bf69..61dd17d7bac 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -37,11 +37,11 @@
* by the bootloader or in the platform init code.
*
* The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
- * and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
- * on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
- * the console code : without this 1:1 mapping, at early boot time, when we are
- * parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
- * mapped to.
+ * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and
+ * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly
+ * fpr the console code : without this 1:1 mapping, at early boot time, when we
+ * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it
+ * will be mapped to.
*/
#include <linux/config.h>
@@ -65,6 +65,10 @@
#include <linux/serial_core.h>
+/* We've been assigned a range on the "Low-density serial ports" major */
+#define SERIAL_PSC_MAJOR 204
+#define SERIAL_PSC_MINOR 148
+
#define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */
@@ -401,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);
@@ -424,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);
@@ -668,15 +658,15 @@ mpc52xx_console_setup(struct console *co, char *options)
}
-extern struct uart_driver mpc52xx_uart_driver;
+static struct uart_driver mpc52xx_uart_driver;
static struct console mpc52xx_console = {
- .name = "ttyS",
+ .name = "ttyPSC",
.write = mpc52xx_console_write,
.device = uart_console_device,
.setup = mpc52xx_console_setup,
.flags = CON_PRINTBUFFER,
- .index = -1, /* Specified on the cmdline (e.g. console=ttyS0 ) */
+ .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0 ) */
.data = &mpc52xx_uart_driver,
};
@@ -703,10 +693,10 @@ console_initcall(mpc52xx_console_init);
static struct uart_driver mpc52xx_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "mpc52xx_psc_uart",
- .dev_name = "ttyS",
- .devfs_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
+ .dev_name = "ttyPSC",
+ .devfs_name = "ttyPSC",
+ .major = SERIAL_PSC_MAJOR,
+ .minor = SERIAL_PSC_MINOR,
.nr = MPC52xx_PSC_MAXNUM,
.cons = MPC52xx_PSC_CONSOLE,
};
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 8f83e4007ec..0ca83ac31d0 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 7633132a10a..4e49168c317 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 5ddd8ab1f10..5f52883e64d 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>
@@ -96,7 +97,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 +211,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 +246,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 +281,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 +301,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 +923,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 +941,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 +982,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 +1003,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 +1020,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 +1409,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 +1426,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,7 +1592,7 @@ 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);
+ mutex_lock(&pmz_irq_mutex);
down(&state->sem);
spin_lock_irqsave(&uap->port.lock, flags);
@@ -1640,7 +1625,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
pmz_set_scc_power(uap, 0);
up(&state->sem);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
pmz_debug("suspend, switching complete\n");
@@ -1667,7 +1652,7 @@ static int pmz_resume(struct macio_dev *mdev)
state = pmz_uart_reg.state + uap->port.line;
- down(&pmz_irq_sem);
+ mutex_lock(&pmz_irq_mutex);
down(&state->sem);
spin_lock_irqsave(&uap->port.lock, flags);
@@ -1701,7 +1686,7 @@ static int pmz_resume(struct macio_dev *mdev)
bail:
up(&state->sem);
- up(&pmz_irq_sem);
+ 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 cc998b99a19..10535f00301 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 47681c4654e..eb4883efb7c 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 25a086458ab..1bd93168f50 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 c17d680e3f0..2ca620900bc 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)
@@ -1440,6 +1441,7 @@ 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)
@@ -1471,7 +1473,7 @@ 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)) {
state = ERR_PTR(-ERESTARTSYS);
@@ -1508,7 +1510,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
}
out:
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return state;
}
@@ -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 96969cb960a..c30333694fd 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 d01dbe5da3b..d4a1f0e798c 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 f10c86d60b6..ee98a867bc6 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 430754ebac8..a9e07075962 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 313f9df24a2..5468e5a767e 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -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++;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index ba9381fd3f2..7e773ff76c6 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)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f0738533f39..9a3665b34d9 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 7653d6cf05a..3c72484adea 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 47b504ff38b..00000000000
--- 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 865d4dea65d..d61494d185c 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/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index b2833614865..c1b47d74e20 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/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 248279e44c9..b9fd39fd1b5 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 c44bbedec81..3cf945cc5b9 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/file_storage.c b/drivers/usb/gadget/file_storage.c
index 0cea9782d7d..de59c58896d 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 5c40980a5bd..c6c279de832 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;
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 65e084a2c87..2e6926b3345 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1271,6 +1271,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 +1291,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 +1308,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/host/Kconfig b/drivers/usb/host/Kconfig
index ed1899d307d..be3fd9bce57 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 d9cf3b327d9..77cd6ac07e3 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 3959ccc8833..0020ed7a39d 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 c9e29d80871..3785b3f7df1 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 2ec6a78bd65..b2a8dfa4887 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 35cc9402adc..372527a8359 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 458f2acdeb0..28538db9eaf 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/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index 6a5700e9d42..25646804d5b 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 3a0e8ce67eb..8af665bbe33 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 09ca6128ac2..4f9b0dc6fd7 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 b2ae29af594..2ba562285fd 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 774038b352c..b497a6a0a20 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 4bd113325ef..63a72e550a1 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 1c73155c8d7..5df14407387 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 04d69339c05..bff9434c8e5 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -1533,12 +1533,12 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
}
} else {
DBG(4, "Rejected client [%s] with driver [%s]",
- client->name, client->driver->name)
+ client->name, client->driver->driver.name)
return -EINVAL;
}
DBG(5, "I2C attach client [%s] with driver [%s]",
- client->name, client->driver->name)
+ client->name, client->driver->driver.name)
return 0;
}
@@ -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 14f55fd26a6..be5dc80836c 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/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6d18d4eaba3..2357b1d102d 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 af18355e94c..68067fe117a 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 8fc414bd5b2..b3f776a90c9 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 79a766e9ca2..63f7c78a115 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 eb863b3f2d7..10bc1bf23b3 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 452efce7271..d6f55e9dcca 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 4ddac620fc0..476cda107f4 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 faedbeb6ba4..3f29e6b0fd1 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 2edf9cabad2..afc0f34b3a4 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 06d07cea0b7..9a5c9798956 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 2dd191f5fe7..e760a70242c 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 4e2f7dfb58b..78335a5f774 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 d9c21e27513..b8b213185d0 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 3fd2405304f..52bdf6fe46f 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 f0372105619..9ffff193823 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -924,16 +924,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 abb830cb77b..c18db325707 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 8bc8337c99c..4dd6865d32b 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 49b1fbe61f2..bce3d55affd 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 a7c3c4734d8..557411c6e7c 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/Kconfig b/drivers/video/Kconfig
index cc8e3bf5001..3e153d313bb 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/amba-clcd.c b/drivers/video/amba-clcd.c
index a3c2c45e29e..0da4083ba90 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)
@@ -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 d549e215f3c..2c42a812655 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
@@ -1164,8 +1166,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);
@@ -2179,6 +2181,7 @@ static int amifb_ioctl(struct inode *inode, struct file *file,
struct fb_var_cursorinfo var;
struct fb_cursorstate state;
} crsr;
+ void __user *argp = (void __user *)arg;
int i;
switch (cmd) {
@@ -2186,33 +2189,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 +3327,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 +3349,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 +3402,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 +3429,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 +3444,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 2784f0a9d69..89060b2db8e 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;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index c64de59398f..69f75547865 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/aty/Makefile b/drivers/video/aty/Makefile
index 9dec96249ff..18521397a6e 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/atyfb.h b/drivers/video/aty/atyfb.h
index 09de173c116..e9b7a64c1ac 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 3fefdb0cbf0..ed81005cbdb 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
@@ -340,6 +349,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 +369,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 +443,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 +463,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 +729,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 +877,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 +898,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 +995,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 +1010,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 +1072,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 +1095,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 +1213,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 +1271,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 +1477,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;
@@ -2291,10 +2324,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 +2667,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 +2684,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 +3186,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 +3501,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 +3721,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 +3730,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 9bdb2aab01a..e7056934c6a 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_monitor.c b/drivers/video/aty/radeon_monitor.c
index ea7c8630691..7f9838dceab 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/xlinit.c b/drivers/video/aty/xlinit.c
deleted file mode 100644
index a085cbf74ec..00000000000
--- 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/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 6a219b2c77e..d0aaf450e8c 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/console/Kconfig b/drivers/video/console/Kconfig
index a5d09e159cd..6ee449858a5 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 e65fc3ef763..eea422eb1ab 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 3660e51b261..041d0698786 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 6892e7ff34d..c38c3d8e7a7 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 4952b66ae20..990289a69b7 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 6d92b845620..d44c5fa515f 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 ec0dd8fe241..2dc091fbd5c 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 1b8f92fdc6a..75be5ce53dc 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 9dd059e8b64..f56ed068a5b 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 8529bf08db2..3957fc7523e 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 cb25324a563..153352ca946 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 167de397e4b..12d9329d140 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 403d17377f8..03798e9c882 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -133,12 +133,6 @@ static int controlfb_mmap(struct fb_info *info, struct file *file,
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);
@@ -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 a9300f930ef..55a3514157e 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 03fbe83d71a..2b972461a03 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 0b6af00d197..ac90883dc3a 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 10dfdf03526..32a9b69becc 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;
@@ -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 fc7965b6677..7c74e7325d9 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 08dac9580d1..6d26057337e 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/hgafb.c b/drivers/video/hgafb.c
index b37cea7d109..4e39035cf33 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 c61bad0da20..bd410e06db7 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 64cd1c827cf..76764ea3486 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 64f087a4466..9743d51e7f8 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 c0c974b1afa..266d0ab9266 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 06072a6466f..51d4f3d4116 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/imsttfb.c b/drivers/video/imsttfb.c
index 7fbe24206b1..a5d813050db 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)
@@ -1266,7 +1270,7 @@ static int
imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, struct fb_info *info)
{
- 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 +1354,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 +1417,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 +1453,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 +1478,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 +1515,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 +1532,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 +1540,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 5924cc225c9..1718baaeed2 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/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index 7e33cd307d4..ab5285a7f1d 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 e75b3b4a4aa..b7c83d5dfb1 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 2ae9bafacdd..a8c9713413e 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 5eb4d5c177b..bcd359b6d4f 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;
}
@@ -675,6 +675,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 +684,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 +714,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 +738,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 +753,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 +761,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 +785,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/logo/Makefile b/drivers/video/logo/Makefile
index d0244c04af5..4ef5cd19609 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 cfc748e9427..e6cbd9de944 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.h b/drivers/video/matrox/matroxfb_base.h
index a8c47ad2cdb..3a3e1804c56 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_g450.c b/drivers/video/matrox/matroxfb_g450.c
index 35008af7db7..c122d8743dd 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 ad60bbb16cd..a1f2c5e8fc8 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1288,18 +1288,13 @@ static int maven_detach_client(struct i2c_client* client) {
return 0;
}
-static int maven_command(struct i2c_client* client, unsigned int cmd, void* arg) {
- return -ENOIOCTLCMD; /* or -EINVAL, depends on who will call this */
-}
-
static struct i2c_driver maven_driver={
- .owner = THIS_MODULE,
- .name = "maven",
+ .driver = {
+ .name = "maven",
+ },
.id = I2C_DRIVERID_MGATVO,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = maven_attach_adapter,
.detach_client = maven_detach_client,
- .command = maven_command,
};
/* ************************** */
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index d9d3e9f6c08..455a46ce840 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 8486e77872d..e18c9f98a40 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;
@@ -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 b989358437b..99c3a8e6a23 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 12f2884d3f0..bd9eca05e14 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 3353103e8b0..b149a690ee0 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 1f06a9f1bd0..a18a9aebf05 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 bee09c6e48f..dbcb8962e57 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 00d87f5bb7b..ad1434e3f22 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/platinumfb.c b/drivers/video/platinumfb.c
index ca4082ae5a1..335e3746555 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 2834fc1c344..f6bd77cafd1 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 0277ce031e5..5fe197943de 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/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9f96e9237..6c19ab6afb0 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 77151d8e076..8b1967fc116 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 ce6e749db3a..d574dd3c9c8 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 2ea1354e439..087e58689e4 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>
@@ -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 3c98457783c..00719a91479 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 bac8ea3a010..bbcc055d3bb 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 09e2f284190..ab727eaa7f4 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/skeletonfb.c b/drivers/video/skeletonfb.c
index a01e7ecc15e..9b707771d75 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 e0f14df840d..8a5ce210bb2 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,7 +766,7 @@ 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;
}
@@ -773,7 +774,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static int sstfb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, struct fb_info *info )
{
- 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 +831,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 +856,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 +926,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 +951,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 +987,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 +1024,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 +1078,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 +1115,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 +1150,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 +1309,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 +1395,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 +1402,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 +1465,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 +1521,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 +1531,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 +1539,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 +1607,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 fbb17332afd..56d71d6e9a7 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/tdfxfb.c b/drivers/video/tdfxfb.c
index 9d53387e6a6..3e7baf4c9fa 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 ce97ec8eae9..2bdeb4baa95 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 3e58ddc2bc3..8982e540214 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/vga16fb.c b/drivers/video/vga16fb.c
index 226ae8a8848..f3f16fd9f23 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 d9e01daee63..15179ec6233 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 9a1e00dd3e0..4baf61a2232 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 1a409c2c320..7aa2d3de6d3 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);