From 1a1d77dd589de5a567fa95e36aa6999c704ceca4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 28 Aug 2000 22:00:09 +0000 Subject: Merge with 2.4.0-test7. --- drivers/char/Config.in | 105 +- drivers/char/Makefile | 65 +- drivers/char/agp/agp.h | 7 +- drivers/char/agp/agpgart_be.c | 38 +- drivers/char/audiochip.h | 60 - drivers/char/bt848.h | 355 --- drivers/char/bttv-cards.c | 835 ------ drivers/char/bttv-driver.c | 3272 ---------------------- drivers/char/bttv-if.c | 337 --- drivers/char/bttv.h | 425 --- drivers/char/buz.c | 3479 ----------------------- drivers/char/buz.h | 319 --- drivers/char/bw-qcam.c | 1066 -------- drivers/char/bw-qcam.h | 68 - drivers/char/c-qcam.c | 901 ------ drivers/char/cpia.c | 3324 ---------------------- drivers/char/cpia.h | 421 --- drivers/char/cpia_pp.c | 745 ----- drivers/char/cpia_usb.c | 626 ----- drivers/char/cs8420.h | 50 - drivers/char/drm/agpsupport.c | 6 +- drivers/char/drm/auth.c | 4 +- drivers/char/drm/drmP.h | 9 + drivers/char/drm/ffb_drv.c | 43 +- drivers/char/drm/lists.c | 41 +- drivers/char/drm/lock.c | 32 + drivers/char/drm/mga_dma.c | 2 +- drivers/char/drm/r128_drv.c | 10 +- drivers/char/drm/vm.c | 5 +- drivers/char/ds1620.c | 1 + drivers/char/efirtc.c | 3 +- drivers/char/generic_serial.c | 129 +- drivers/char/i2c-old.c | 458 ---- drivers/char/i2c-parport.c | 147 - drivers/char/i810-tco.c | 326 +++ drivers/char/i810-tco.h | 45 + drivers/char/ibmmpeg2.h | 94 - drivers/char/joystick/Config.in | 60 +- drivers/char/joystick/Makefile | 16 +- drivers/char/joystick/amijoy.c | 21 +- drivers/char/joystick/db9.c | 104 +- drivers/char/joystick/gamecon.c | 28 +- drivers/char/joystick/iforce.c | 342 +++ drivers/char/joystick/ns558.c | 38 +- drivers/char/joystick/sidewinder.c | 6 +- drivers/char/joystick/spaceball.c | 47 +- drivers/char/msp3400.c | 1454 ---------- drivers/char/nwbutton.c | 2 + drivers/char/nwflash.c | 1 + drivers/char/pcxx.c | 122 +- drivers/char/pcxx.h | 1 + drivers/char/planb.c | 2341 ---------------- drivers/char/planb.h | 232 -- drivers/char/pms.c | 1074 -------- drivers/char/radio-aimslab.c | 390 --- drivers/char/radio-aztech.c | 330 --- drivers/char/radio-cadet.c | 603 ---- drivers/char/radio-gemtek.c | 319 --- drivers/char/radio-miropcm20.c | 239 -- drivers/char/radio-rtrack2.c | 280 -- drivers/char/radio-sf16fmi.c | 339 --- drivers/char/radio-terratec.c | 358 --- drivers/char/radio-trust.c | 350 --- drivers/char/radio-typhoon.c | 402 --- drivers/char/radio-zoltrix.c | 412 --- drivers/char/rio/linux_compat.h | 4 +- drivers/char/rio/rio_linux.c | 46 +- drivers/char/rio/rio_linux.h | 23 +- drivers/char/rio/rioboot.c | 186 +- drivers/char/rio/riocmd.c | 248 +- drivers/char/rio/rioctrl.c | 430 +-- drivers/char/rio/rioinit.c | 252 +- drivers/char/rio/riointr.c | 142 +- drivers/char/rio/rioparam.c | 174 +- drivers/char/rio/rioroute.c | 148 +- drivers/char/rio/riotable.c | 168 +- drivers/char/rio/riotty.c | 222 +- drivers/char/saa5249.c | 683 ----- drivers/char/saa7110.c | 429 --- drivers/char/saa7111.c | 418 --- drivers/char/saa7121.h | 132 - drivers/char/saa7146.h | 117 - drivers/char/saa7146reg.h | 283 -- drivers/char/saa7185.c | 377 --- drivers/char/saa7196.h | 117 - drivers/char/scan_keyb.c | 24 +- drivers/char/serial.c | 289 +- drivers/char/serial_21285.c | 511 ++++ drivers/char/stallion.c | 5329 ------------------------------------ drivers/char/stradis.c | 2287 ---------------- drivers/char/sx.c | 10 +- drivers/char/tda7432.c | 505 ---- drivers/char/tda8425.c | 324 --- drivers/char/tda985x.c | 536 ---- drivers/char/tda9875.c | 403 --- drivers/char/tea6300.c | 344 --- drivers/char/tea6420.c | 268 -- drivers/char/tty_io.c | 8 +- drivers/char/tuner-3036.c | 227 -- drivers/char/tuner.c | 451 --- drivers/char/tuner.h | 57 - drivers/char/tvmixer.c | 353 --- drivers/char/videodev.c | 581 ---- drivers/char/vino.c | 275 -- drivers/char/vino.h | 118 - drivers/char/wdt285.c | 2 +- drivers/char/zr36057.h | 168 -- drivers/char/zr36060.h | 35 - drivers/char/zr36120.c | 2086 -------------- drivers/char/zr36120.h | 279 -- drivers/char/zr36120_i2c.c | 133 - drivers/char/zr36120_mem.c | 77 - drivers/char/zr36120_mem.h | 3 - 113 files changed, 2971 insertions(+), 45075 deletions(-) delete mode 100644 drivers/char/audiochip.h delete mode 100644 drivers/char/bt848.h delete mode 100644 drivers/char/bttv-cards.c delete mode 100644 drivers/char/bttv-driver.c delete mode 100644 drivers/char/bttv-if.c delete mode 100644 drivers/char/bttv.h delete mode 100644 drivers/char/buz.c delete mode 100644 drivers/char/buz.h delete mode 100644 drivers/char/bw-qcam.c delete mode 100644 drivers/char/bw-qcam.h delete mode 100644 drivers/char/c-qcam.c delete mode 100644 drivers/char/cpia.c delete mode 100644 drivers/char/cpia.h delete mode 100644 drivers/char/cpia_pp.c delete mode 100644 drivers/char/cpia_usb.c delete mode 100644 drivers/char/cs8420.h delete mode 100644 drivers/char/i2c-old.c delete mode 100644 drivers/char/i2c-parport.c create mode 100644 drivers/char/i810-tco.c create mode 100644 drivers/char/i810-tco.h delete mode 100644 drivers/char/ibmmpeg2.h create mode 100644 drivers/char/joystick/iforce.c delete mode 100644 drivers/char/msp3400.c delete mode 100644 drivers/char/planb.c delete mode 100644 drivers/char/planb.h delete mode 100644 drivers/char/pms.c delete mode 100644 drivers/char/radio-aimslab.c delete mode 100644 drivers/char/radio-aztech.c delete mode 100644 drivers/char/radio-cadet.c delete mode 100644 drivers/char/radio-gemtek.c delete mode 100644 drivers/char/radio-miropcm20.c delete mode 100644 drivers/char/radio-rtrack2.c delete mode 100644 drivers/char/radio-sf16fmi.c delete mode 100644 drivers/char/radio-terratec.c delete mode 100644 drivers/char/radio-trust.c delete mode 100644 drivers/char/radio-typhoon.c delete mode 100644 drivers/char/radio-zoltrix.c delete mode 100644 drivers/char/saa5249.c delete mode 100644 drivers/char/saa7110.c delete mode 100644 drivers/char/saa7111.c delete mode 100644 drivers/char/saa7121.h delete mode 100644 drivers/char/saa7146.h delete mode 100644 drivers/char/saa7146reg.h delete mode 100644 drivers/char/saa7185.c delete mode 100644 drivers/char/saa7196.h create mode 100644 drivers/char/serial_21285.c delete mode 100644 drivers/char/stallion.c delete mode 100644 drivers/char/stradis.c delete mode 100644 drivers/char/tda7432.c delete mode 100644 drivers/char/tda8425.c delete mode 100644 drivers/char/tda985x.c delete mode 100644 drivers/char/tda9875.c delete mode 100644 drivers/char/tea6300.c delete mode 100644 drivers/char/tea6420.c delete mode 100644 drivers/char/tuner-3036.c delete mode 100644 drivers/char/tuner.c delete mode 100644 drivers/char/tuner.h delete mode 100644 drivers/char/tvmixer.c delete mode 100644 drivers/char/videodev.c delete mode 100644 drivers/char/vino.c delete mode 100644 drivers/char/vino.h delete mode 100644 drivers/char/zr36057.h delete mode 100644 drivers/char/zr36060.h delete mode 100644 drivers/char/zr36120.c delete mode 100644 drivers/char/zr36120.h delete mode 100644 drivers/char/zr36120_i2c.c delete mode 100644 drivers/char/zr36120_mem.c delete mode 100644 drivers/char/zr36120_mem.h (limited to 'drivers/char') diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 08b50aaa1..7872a6f00 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -8,7 +8,7 @@ bool 'Virtual terminal' CONFIG_VT if [ "$CONFIG_VT" = "y" ]; then bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE fi -tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL +tristate 'Standard/generic (8250/16550 and compatible UARTs) serial support' CONFIG_SERIAL if [ "$CONFIG_SERIAL" = "y" ]; then bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE if [ "$CONFIG_ARCH_ACORN" = "y" ]; then @@ -60,6 +60,15 @@ if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION fi fi +if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then + bool 'DC21285 serial port support' CONFIG_SERIAL_21285 + if [ "$CONFIG_SERIAL_21285" = "y" ]; then + if [ "$CONFIG_OBSOLETE" = "y" ]; then + bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD + fi + bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE + fi +fi bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 @@ -124,8 +133,9 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT - tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT + tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD + tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then @@ -154,98 +164,7 @@ if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then bool 'Tadpole ANA H8 Support' CONFIG_H8 fi -mainmenu_option next_comment -comment 'Video For Linux' - -tristate 'Video For Linux' CONFIG_VIDEO_DEV -if [ "$CONFIG_VIDEO_DEV" != "n" ]; then - bool ' V4L information in proc filesystem' CONFIG_VIDEO_PROC_FS Y - dep_tristate ' I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT $CONFIG_I2C - comment 'Radio Adapters' - dep_tristate ' ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV - dep_tristate ' AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then - hex ' RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f - fi - dep_tristate ' AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then - hex ' RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c - fi - dep_tristate ' Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then - hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350 - fi - dep_tristate ' GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then - hex ' GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c - fi - dep_tristate ' Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV - dep_tristate ' SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then - hex ' SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284 - fi - dep_tristate ' TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then - hex ' Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590 - fi - dep_tristate ' Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_TRUST" = "y" ]; then - hex ' Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350 - fi - dep_tristate ' Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV - if [ "$CONFIG_PROC_FS" = "y" ]; then - if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then - bool ' Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS - fi - fi - if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then - hex ' Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316 - int ' Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500 - fi - dep_tristate ' Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then - hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c - fi - comment 'Video Adapters' - if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then - dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT - fi - dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV - if [ "$CONFIG_ALL_PPC" = "y" ]; then - dep_tristate ' PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV - fi - if [ "$CONFIG_PARPORT" != "n" ]; then - dep_tristate ' Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' QuickCam Colour Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT - fi - fi - dep_tristate ' CPiA Video For Linux' CONFIG_VIDEO_CPIA $CONFIG_VIDEO_DEV - if [ "$CONFIG_VIDEO_CPIA" != "n" ]; then - if [ "CONFIG_PARPORT_1284" != "n" ]; then - dep_tristate ' CPiA Parallel Port Lowlevel Support' CONFIG_VIDEO_CPIA_PP $CONFIG_VIDEO_CPIA $CONFIG_PARPORT - fi - if [ "$CONFIG_USB" != "n" ]; then - dep_tristate ' CPiA USB Lowlevel Support' CONFIG_VIDEO_CPIA_USB $CONFIG_VIDEO_CPIA $CONFIG_USB - fi - fi - dep_tristate ' SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV $CONFIG_I2C - dep_tristate ' SAB3036 tuner' CONFIG_TUNER_3036 $CONFIG_VIDEO_DEV $CONFIG_I2C - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_SGI" = "y" ]; then - dep_tristate ' SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV $CONFIG_SGI - fi - dep_tristate ' Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)' CONFIG_VIDEO_STRADIS $CONFIG_VIDEO_DEV $CONFIG_PCI - fi - dep_tristate ' Zoran ZR36057/36060 Video For Linux' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI - dep_tristate ' Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN - dep_tristate ' Zoran ZR36120/36125 Video For Linux' CONFIG_VIDEO_ZR36120 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C -fi - -endmenu - tristate 'Double Talk PC internal speech card support' CONFIG_DTLK - tristate 'Siemens R3964 line discipline' CONFIG_R3964 tristate 'Applicom intelligent fieldbus card support' CONFIG_APPLICOM diff --git a/drivers/char/Makefile b/drivers/char/Makefile index a83719fb7..b7a71c0f5 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -36,12 +36,11 @@ obj-y += tty_io.o n_tty.o tty_ioctl.o mem.o raw.o pty.o misc.o random.o # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := busmouse.o console.o i2c-old.o keyboard.o sysrq.o \ - misc.o pty.o random.o selection.o serial.o videodev.o \ - tty_io.o bttv-if.o cpia.o +export-objs := busmouse.o console.o keyboard.o sysrq.o \ + misc.o pty.o random.o selection.o serial.o \ + tty_io.o -list-multi := bttv.o -bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o +list-multi := KEYMAP =defkeymap.o KEYBD =pc_keyb.o @@ -65,11 +64,12 @@ ifeq ($(ARCH),m68k) endif ifeq ($(ARCH),arm) -# we actually need to be able to select various different keymaps -# and keyboards dependent on which actual machine we're going to -# run on. - KEYMAP = - KEYBD = + ifneq ($(CONFIG_PC_KEYMAP),y) + KEYMAP = + endif + ifneq ($(CONFIG_PC_KEYB),y) + KEYBD = + endif endif ifeq ($(ARCH),sh) @@ -142,12 +142,12 @@ obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o obj-$(CONFIG_PRINTER) += lp.o -ifeq ($(CONFIG_JOYSTICK),y) +ifeq ($(CONFIG_INPUT),y) obj-y += joystick/js.o SUB_DIRS += joystick MOD_SUB_DIRS += joystick else - ifeq ($(CONFIG_JOYSTICK),m) + ifeq ($(CONFIG_INPUT),m) MOD_SUB_DIRS += joystick endif endif @@ -175,44 +175,12 @@ ifeq ($(CONFIG_PPC),) obj-$(CONFIG_NVRAM) += nvram.o endif -obj-$(CONFIG_VIDEO_DEV) += videodev.o - obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o +obj-$(CONFIG_I810_TCO) += i810-tco.o obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_INTEL_RNG) += i810_rng.o -obj-$(CONFIG_BUS_I2C) += i2c-old.o -obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \ - tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o tuner.o -obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o - -obj-$(CONFIG_VIDEO_ZR36120) += zoran.o i2c-old.o tuner.o saa7110.o saa7111.o saa7185.o -obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o i2c-old.o -obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o i2c-old.o -obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o -obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o -obj-$(CONFIG_VIDEO_ZORAN) += buz.o i2c-old.o saa7110.o saa7111.o saa7185.o -obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o -obj-$(CONFIG_VIDEO_PMS) += pms.o -obj-$(CONFIG_VIDEO_PLANB) += planb.o -obj-$(CONFIG_VIDEO_VINO) += vino.o -obj-$(CONFIG_VIDEO_STRADIS) += stradis.o -obj-$(CONFIG_VIDEO_CPIA) += cpia.o -obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o -obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o -obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o -obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o -obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o -obj-$(CONFIG_RADIO_CADET) += radio-cadet.o -obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o -obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o -obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o -obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o -obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o -obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o -obj-$(CONFIG_RADIO_TRUST) += radio-trust.o -obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_QIC02_TAPE) += tpqic02.o ifeq ($(CONFIG_FTAPE),y) @@ -300,10 +268,3 @@ consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h defkeymap.c: defkeymap.map loadkeys --mktable defkeymap.map > defkeymap.c - -zoran.o: zr36120.o zr36120_i2c.o zr36120_mem.o - $(LD) $(LD_RFLAG) -r -o $@ zr36120.o zr36120_i2c.o zr36120_mem.o - -bttv.o: $(bttv-objs) - $(LD) $(LD_RFLAG) -r -o $@ $(bttv-objs) - diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index af32ba284..acad5947a 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -154,8 +154,11 @@ struct agp_bridge_data { #ifndef PCI_DEVICE_ID_VIA_82C691_0 #define PCI_DEVICE_ID_VIA_82C691_0 0x0691 #endif -#ifndef PCI_DEVICE_ID_VIA_82C691_1 -#define PCI_DEVICE_ID_VIA_82C691_1 0x8691 +#ifndef PCI_DEVICE_ID_VIA_8371_0 +#define PCI_DEVICE_ID_VIA_8371_0 0x0391 +#endif +#ifndef PCI_DEVICE_ID_VIA_8363_0 +#define PCI_DEVICE_ID_VIA_8363_0 0x0305 #endif #ifndef PCI_DEVICE_ID_INTEL_810_0 #define PCI_DEVICE_ID_INTEL_810_0 0x7120 diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c index e5fbba8b5..44bd3bfb4 100644 --- a/drivers/char/agp/agpgart_be.c +++ b/drivers/char/agp/agpgart_be.c @@ -67,14 +67,16 @@ static inline void flush_cache(void) { #if defined(__i386__) asm volatile ("wbinvd":::"memory"); -#elif defined(__alpha__) +#elif defined(__alpha__) || defined(__ia64__) /* ??? I wonder if we'll really need to flush caches, or if the core logic can manage to keep the system coherent. The ARM speaks only of using `cflush' to get things in memory in preparation for power failure. If we do need to call `cflush', we'll need a target page, - as we can only flush one page at a time. */ + as we can only flush one page at a time. + + Ditto for IA-64. --davidm 00/08/07 */ mb(); #else #error "Please define flush_cache." @@ -412,10 +414,9 @@ int agp_unbind_memory(agp_memory * curr) /* * Driver routines - start - * Currently this module supports the - * i810, 440lx, 440bx, 440gx, via vp3, via mvp3, - * amd irongate, ALi M1541 and generic support for the - * SiS chipsets. + * Currently this module supports the following chipsets: + * i810, 440lx, 440bx, 440gx, via vp3, via mvp3, via kx133, via kt133, + * amd irongate, ALi M1541, and generic support for the SiS chipsets. */ /* Generic Agp routines - Start */ @@ -637,7 +638,7 @@ static int agp_generic_create_gatt_table(void) } table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); - for (page = virt_to_page(table); page < virt_to_page(table_end); page++) + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) set_bit(PG_reserved, &page->flags); agp_bridge.gatt_table_real = (unsigned long *) table; @@ -647,7 +648,7 @@ static int agp_generic_create_gatt_table(void) CACHE_FLUSH(); if (agp_bridge.gatt_table == NULL) { - for (page = virt_to_page(table); page < virt_to_page(table_end); page++) + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) clear_bit(PG_reserved, &page->flags); free_pages((unsigned long) table, page_order); @@ -704,7 +705,7 @@ static int agp_generic_free_gatt_table(void) table = (char *) agp_bridge.gatt_table_real; table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); - for (page = virt_to_page(table); page < virt_to_page(table_end); page++) + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) clear_bit(PG_reserved, &page->flags); free_pages((unsigned long) agp_bridge.gatt_table_real, page_order); @@ -976,6 +977,7 @@ static int intel_i810_remove_entries(agp_memory * mem, off_t pg_start, agp_bridge.scratch_page); } + CACHE_FLUSH(); agp_bridge.tlb_flush(mem); return 0; } @@ -2127,12 +2129,6 @@ static struct { #endif /* CONFIG_AGP_SIS */ #ifdef CONFIG_AGP_VIA - { PCI_DEVICE_ID_VIA_8371_0, - PCI_VENDOR_ID_VIA, - VIA_APOLLO_SUPER, - "Via", - "Apollo Super", - via_generic_setup }, { PCI_DEVICE_ID_VIA_8501_0, PCI_VENDOR_ID_VIA, VIA_MVP4, @@ -2157,6 +2153,18 @@ static struct { "Via", "Apollo Pro", via_generic_setup }, + { PCI_DEVICE_ID_VIA_8371_0, + PCI_VENDOR_ID_VIA, + VIA_APOLLO_KX133, + "Via", + "Apollo Pro KX133", + via_generic_setup }, + { PCI_DEVICE_ID_VIA_8363_0, + PCI_VENDOR_ID_VIA, + VIA_APOLLO_KT133, + "Via", + "Apollo Pro KT133", + via_generic_setup }, { 0, PCI_VENDOR_ID_VIA, VIA_GENERIC, diff --git a/drivers/char/audiochip.h b/drivers/char/audiochip.h deleted file mode 100644 index 23d1b1259..000000000 --- a/drivers/char/audiochip.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef AUDIOCHIP_H -#define AUDIOCHIP_H - -/* ---------------------------------------------------------------------- */ - -#define MIN(a,b) (((a)>(b))?(b):(a)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -/* v4l device was opened in Radio mode */ -#define AUDC_SET_RADIO _IO('m',2) -/* select from TV,radio,extern,MUTE */ -#define AUDC_SET_INPUT _IOW('m',17,int) - -/* all the stuff below is obsolete and just here for reference. I'll - * remove it once the driver is tested and works fine. - * - * Instead creating alot of tiny API's for all kinds of different - * chips, we'll just pass throuth the v4l ioctl structs (v4l2 not - * yet...). It is a bit less flexible, but most/all used i2c chips - * make sense in v4l context only. So I think that's acceptable... - */ - -#if 0 - -/* TODO (if it is ever [to be] accessible in the V4L[2] spec): - * maybe fade? (back/front) - * notes: - * NEWCHANNEL and SWITCH_MUTE are here because the MSP3400 has a special - * routine to go through when it tunes in to a new channel before turning - * back on the sound. - * Either SET_RADIO, NEWCHANNEL, and SWITCH_MUTE or SET_INPUT need to be - * implemented (MSP3400 uses SET_RADIO to select inputs, and SWITCH_MUTE for - * channel-change mute -- TEA6300 et al use SET_AUDIO to select input [TV, - * radio, external, or MUTE]). If both methods are implemented, you get a - * cookie for doing such a good job! :) - */ - -#define AUDC_SET_TVNORM _IOW('m',1,int) /* TV mode + PAL/SECAM/NTSC */ -#define AUDC_NEWCHANNEL _IO('m',3) /* indicate new chan - off mute */ - -#define AUDC_GET_VOLUME_LEFT _IOR('m',4,__u16) -#define AUDC_GET_VOLUME_RIGHT _IOR('m',5,__u16) -#define AUDC_SET_VOLUME_LEFT _IOW('m',6,__u16) -#define AUDC_SET_VOLUME_RIGHT _IOW('m',7,__u16) - -#define AUDC_GET_STEREO _IOR('m',8,__u16) -#define AUDC_SET_STEREO _IOW('m',9,__u16) - -#define AUDC_GET_DC _IOR('m',10,__u16)/* ??? */ - -#define AUDC_GET_BASS _IOR('m',11,__u16) -#define AUDC_SET_BASS _IOW('m',12,__u16) -#define AUDC_GET_TREBLE _IOR('m',13,__u16) -#define AUDC_SET_TREBLE _IOW('m',14,__u16) - -#define AUDC_GET_UNIT _IOR('m',15,int) /* ??? - unimplemented in MSP3400 */ -#define AUDC_SWITCH_MUTE _IO('m',16) /* turn on mute */ -#endif - -#endif /* AUDIOCHIP_H */ diff --git a/drivers/char/bt848.h b/drivers/char/bt848.h deleted file mode 100644 index 340accf31..000000000 --- a/drivers/char/bt848.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - bt848.h - Bt848 register offsets - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _BT848_H_ -#define _BT848_H_ - -#ifndef PCI_VENDOR_ID_BROOKTREE -#define PCI_VENDOR_ID_BROOKTREE 0x109e -#endif -#ifndef PCI_DEVICE_ID_BT848 -#define PCI_DEVICE_ID_BT848 0x350 -#endif -#ifndef PCI_DEVICE_ID_BT849 -#define PCI_DEVICE_ID_BT849 0x351 -#endif -#ifndef PCI_DEVICE_ID_BT878 -#define PCI_DEVICE_ID_BT878 0x36e -#endif -#ifndef PCI_DEVICE_ID_BT879 -#define PCI_DEVICE_ID_BT879 0x36f -#endif - - -/* Brooktree 848 registers */ - -#define BT848_DSTATUS 0x000 -#define BT848_DSTATUS_PRES (1<<7) -#define BT848_DSTATUS_HLOC (1<<6) -#define BT848_DSTATUS_FIELD (1<<5) -#define BT848_DSTATUS_NUML (1<<4) -#define BT848_DSTATUS_CSEL (1<<3) -#define BT848_DSTATUS_PLOCK (1<<2) -#define BT848_DSTATUS_LOF (1<<1) -#define BT848_DSTATUS_COF (1<<0) - -#define BT848_IFORM 0x004 -#define BT848_IFORM_HACTIVE (1<<7) -#define BT848_IFORM_MUXSEL (3<<5) -#define BT848_IFORM_MUX0 (2<<5) -#define BT848_IFORM_MUX1 (3<<5) -#define BT848_IFORM_MUX2 (1<<5) -#define BT848_IFORM_XTSEL (3<<3) -#define BT848_IFORM_XT0 (1<<3) -#define BT848_IFORM_XT1 (2<<3) -#define BT848_IFORM_XTAUTO (3<<3) -#define BT848_IFORM_XTBOTH (3<<3) -#define BT848_IFORM_NTSC 1 -#define BT848_IFORM_NTSC_J 2 -#define BT848_IFORM_PAL_BDGHI 3 -#define BT848_IFORM_PAL_M 4 -#define BT848_IFORM_PAL_N 5 -#define BT848_IFORM_SECAM 6 -#define BT848_IFORM_PAL_NC 7 -#define BT848_IFORM_AUTO 0 -#define BT848_IFORM_NORM 7 - -#define BT848_TDEC 0x008 -#define BT848_TDEC_DEC_FIELD (1<<7) -#define BT848_TDEC_FLDALIGN (1<<6) -#define BT848_TDEC_DEC_RAT (0x1f) - -#define BT848_E_CROP 0x00C -#define BT848_O_CROP 0x08C - -#define BT848_E_VDELAY_LO 0x010 -#define BT848_O_VDELAY_LO 0x090 - -#define BT848_E_VACTIVE_LO 0x014 -#define BT848_O_VACTIVE_LO 0x094 - -#define BT848_E_HDELAY_LO 0x018 -#define BT848_O_HDELAY_LO 0x098 - -#define BT848_E_HACTIVE_LO 0x01C -#define BT848_O_HACTIVE_LO 0x09C - -#define BT848_E_HSCALE_HI 0x020 -#define BT848_O_HSCALE_HI 0x0A0 - -#define BT848_E_HSCALE_LO 0x024 -#define BT848_O_HSCALE_LO 0x0A4 - -#define BT848_BRIGHT 0x028 - -#define BT848_E_CONTROL 0x02C -#define BT848_O_CONTROL 0x0AC -#define BT848_CONTROL_LNOTCH (1<<7) -#define BT848_CONTROL_COMP (1<<6) -#define BT848_CONTROL_LDEC (1<<5) -#define BT848_CONTROL_CBSENSE (1<<4) -#define BT848_CONTROL_CON_MSB (1<<2) -#define BT848_CONTROL_SAT_U_MSB (1<<1) -#define BT848_CONTROL_SAT_V_MSB (1<<0) - -#define BT848_CONTRAST_LO 0x030 -#define BT848_SAT_U_LO 0x034 -#define BT848_SAT_V_LO 0x038 -#define BT848_HUE 0x03C - -#define BT848_E_SCLOOP 0x040 -#define BT848_O_SCLOOP 0x0C0 -#define BT848_SCLOOP_CAGC (1<<6) -#define BT848_SCLOOP_CKILL (1<<5) -#define BT848_SCLOOP_HFILT_AUTO (0<<3) -#define BT848_SCLOOP_HFILT_CIF (1<<3) -#define BT848_SCLOOP_HFILT_QCIF (2<<3) -#define BT848_SCLOOP_HFILT_ICON (3<<3) - -#define BT848_SCLOOP_PEAK (1<<7) -#define BT848_SCLOOP_HFILT_MINP (1<<3) -#define BT848_SCLOOP_HFILT_MEDP (2<<3) -#define BT848_SCLOOP_HFILT_MAXP (3<<3) - - -#define BT848_OFORM 0x048 -#define BT848_OFORM_RANGE (1<<7) -#define BT848_OFORM_CORE0 (0<<5) -#define BT848_OFORM_CORE8 (1<<5) -#define BT848_OFORM_CORE16 (2<<5) -#define BT848_OFORM_CORE32 (3<<5) - -#define BT848_E_VSCALE_HI 0x04C -#define BT848_O_VSCALE_HI 0x0CC -#define BT848_VSCALE_YCOMB (1<<7) -#define BT848_VSCALE_COMB (1<<6) -#define BT848_VSCALE_INT (1<<5) -#define BT848_VSCALE_HI 15 - -#define BT848_E_VSCALE_LO 0x050 -#define BT848_O_VSCALE_LO 0x0D0 -#define BT848_TEST 0x054 -#define BT848_ADELAY 0x060 -#define BT848_BDELAY 0x064 - -#define BT848_ADC 0x068 -#define BT848_ADC_RESERVED (2<<6) -#define BT848_ADC_SYNC_T (1<<5) -#define BT848_ADC_AGC_EN (1<<4) -#define BT848_ADC_CLK_SLEEP (1<<3) -#define BT848_ADC_Y_SLEEP (1<<2) -#define BT848_ADC_C_SLEEP (1<<1) -#define BT848_ADC_CRUSH (1<<0) - -#define BT848_E_VTC 0x06C -#define BT848_O_VTC 0x0EC -#define BT848_VTC_HSFMT (1<<7) -#define BT848_VTC_VFILT_2TAP 0 -#define BT848_VTC_VFILT_3TAP 1 -#define BT848_VTC_VFILT_4TAP 2 -#define BT848_VTC_VFILT_5TAP 3 - -#define BT848_SRESET 0x07C - -#define BT848_COLOR_FMT 0x0D4 -#define BT848_COLOR_FMT_O_RGB32 (0<<4) -#define BT848_COLOR_FMT_O_RGB24 (1<<4) -#define BT848_COLOR_FMT_O_RGB16 (2<<4) -#define BT848_COLOR_FMT_O_RGB15 (3<<4) -#define BT848_COLOR_FMT_O_YUY2 (4<<4) -#define BT848_COLOR_FMT_O_BtYUV (5<<4) -#define BT848_COLOR_FMT_O_Y8 (6<<4) -#define BT848_COLOR_FMT_O_RGB8 (7<<4) -#define BT848_COLOR_FMT_O_YCrCb422 (8<<4) -#define BT848_COLOR_FMT_O_YCrCb411 (9<<4) -#define BT848_COLOR_FMT_O_RAW (14<<4) -#define BT848_COLOR_FMT_E_RGB32 0 -#define BT848_COLOR_FMT_E_RGB24 1 -#define BT848_COLOR_FMT_E_RGB16 2 -#define BT848_COLOR_FMT_E_RGB15 3 -#define BT848_COLOR_FMT_E_YUY2 4 -#define BT848_COLOR_FMT_E_BtYUV 5 -#define BT848_COLOR_FMT_E_Y8 6 -#define BT848_COLOR_FMT_E_RGB8 7 -#define BT848_COLOR_FMT_E_YCrCb422 8 -#define BT848_COLOR_FMT_E_YCrCb411 9 -#define BT848_COLOR_FMT_E_RAW 14 - -#define BT848_COLOR_FMT_RGB32 0x00 -#define BT848_COLOR_FMT_RGB24 0x11 -#define BT848_COLOR_FMT_RGB16 0x22 -#define BT848_COLOR_FMT_RGB15 0x33 -#define BT848_COLOR_FMT_YUY2 0x44 -#define BT848_COLOR_FMT_BtYUV 0x55 -#define BT848_COLOR_FMT_Y8 0x66 -#define BT848_COLOR_FMT_RGB8 0x77 -#define BT848_COLOR_FMT_YCrCb422 0x88 -#define BT848_COLOR_FMT_YCrCb411 0x99 -#define BT848_COLOR_FMT_RAW 0xee - -#define BT848_COLOR_CTL 0x0D8 -#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7) -#define BT848_COLOR_CTL_COLOR_BARS (1<<6) -#define BT848_COLOR_CTL_RGB_DED (1<<5) -#define BT848_COLOR_CTL_GAMMA (1<<4) -#define BT848_COLOR_CTL_WSWAP_ODD (1<<3) -#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2) -#define BT848_COLOR_CTL_BSWAP_ODD (1<<1) -#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0) - -#define BT848_CAP_CTL 0x0DC -#define BT848_CAP_CTL_DITH_FRAME (1<<4) -#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3) -#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) -#define BT848_CAP_CTL_CAPTURE_ODD (1<<1) -#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0) - -#define BT848_VBI_PACK_SIZE 0x0E0 - -#define BT848_VBI_PACK_DEL 0x0E4 -#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc -#define BT848_VBI_PACK_DEL_EXT_FRAME 2 -#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1 - - -#define BT848_INT_STAT 0x100 -#define BT848_INT_MASK 0x104 - -#define BT848_INT_ETBF (1<<23) - -#define BT848_INT_RISCS (0xf<<28) -#define BT848_INT_RISC_EN (1<<27) -#define BT848_INT_RACK (1<<25) -#define BT848_INT_FIELD (1<<24) -#define BT848_INT_SCERR (1<<19) -#define BT848_INT_OCERR (1<<18) -#define BT848_INT_PABORT (1<<17) -#define BT848_INT_RIPERR (1<<16) -#define BT848_INT_PPERR (1<<15) -#define BT848_INT_FDSR (1<<14) -#define BT848_INT_FTRGT (1<<13) -#define BT848_INT_FBUS (1<<12) -#define BT848_INT_RISCI (1<<11) -#define BT848_INT_GPINT (1<<9) -#define BT848_INT_I2CDONE (1<<8) -#define BT848_INT_VPRES (1<<5) -#define BT848_INT_HLOCK (1<<4) -#define BT848_INT_OFLOW (1<<3) -#define BT848_INT_HSYNC (1<<2) -#define BT848_INT_VSYNC (1<<1) -#define BT848_INT_FMTCHG (1<<0) - - -#define BT848_GPIO_DMA_CTL 0x10C -#define BT848_GPIO_DMA_CTL_GPINTC (1<<15) -#define BT848_GPIO_DMA_CTL_GPINTI (1<<14) -#define BT848_GPIO_DMA_CTL_GPWEC (1<<13) -#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11) -#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10) -#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6) -#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6) -#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6) -#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6) -#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4) -#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4) -#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4) -#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4) -#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2) -#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2) -#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2) -#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2) -#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1) -#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0) - -#define BT848_I2C 0x110 -#define BT848_I2C_DIV (0xf<<4) -#define BT848_I2C_SYNC (1<<3) -#define BT848_I2C_W3B (1<<2) -#define BT848_I2C_SCL (1<<1) -#define BT848_I2C_SDA (1<<0) - - -#define BT848_RISC_STRT_ADD 0x114 -#define BT848_GPIO_OUT_EN 0x118 -#define BT848_GPIO_REG_INP 0x11C -#define BT848_RISC_COUNT 0x120 -#define BT848_GPIO_DATA 0x200 - - -/* Bt848 RISC commands */ - -/* only for the SYNC RISC command */ -#define BT848_FIFO_STATUS_FM1 0x06 -#define BT848_FIFO_STATUS_FM3 0x0e -#define BT848_FIFO_STATUS_SOL 0x02 -#define BT848_FIFO_STATUS_EOL4 0x01 -#define BT848_FIFO_STATUS_EOL3 0x0d -#define BT848_FIFO_STATUS_EOL2 0x09 -#define BT848_FIFO_STATUS_EOL1 0x05 -#define BT848_FIFO_STATUS_VRE 0x04 -#define BT848_FIFO_STATUS_VRO 0x0c -#define BT848_FIFO_STATUS_PXV 0x00 - -#define BT848_RISC_RESYNC (1<<15) - -/* WRITE and SKIP */ -/* disable which bytes of each DWORD */ -#define BT848_RISC_BYTE0 (1<<12) -#define BT848_RISC_BYTE1 (1<<13) -#define BT848_RISC_BYTE2 (1<<14) -#define BT848_RISC_BYTE3 (1<<15) -#define BT848_RISC_BYTE_ALL (0x0f<<12) -#define BT848_RISC_BYTE_NONE 0 -/* cause RISCI */ -#define BT848_RISC_IRQ (1<<24) -/* RISC command is last one in this line */ -#define BT848_RISC_EOL (1<<26) -/* RISC command is first one in this line */ -#define BT848_RISC_SOL (1<<27) - -#define BT848_RISC_WRITE (0x01<<28) -#define BT848_RISC_SKIP (0x02<<28) -#define BT848_RISC_WRITEC (0x05<<28) -#define BT848_RISC_JUMP (0x07<<28) -#define BT848_RISC_SYNC (0x08<<28) - -#define BT848_RISC_WRITE123 (0x09<<28) -#define BT848_RISC_SKIP123 (0x0a<<28) -#define BT848_RISC_WRITE1S23 (0x0b<<28) - - - -/* Bt848A and higher only !! */ -#define BT848_TGLB 0x080 -#define BT848_TGCTRL 0x084 -#define BT848_FCAP 0x0E8 -#define BT848_PLL_F_LO 0x0F0 -#define BT848_PLL_F_HI 0x0F4 - -#define BT848_PLL_XCI 0x0F8 -#define BT848_PLL_X (1<<7) -#define BT848_PLL_C (1<<6) - -/* Bt878 register */ - -#define BT878_DEVCTRL 0x40 -#define BT878_EN_TBFX 0x02 - -#endif diff --git a/drivers/char/bttv-cards.c b/drivers/char/bttv-cards.c deleted file mode 100644 index b2c26e35b..000000000 --- a/drivers/char/bttv-cards.c +++ /dev/null @@ -1,835 +0,0 @@ -/* - bttv-cards.c -- this file has card-specific stuff - - - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999,2000 Gerd Knorr - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#define __NO_VERSION__ 1 - -#include -#include -#include -#include -#include - -#include - -#include "bttv.h" -#include "tuner.h" - -/* fwd decl */ -static void hauppauge_eeprom(struct bttv *btv); -static void hauppauge_boot_msp34xx(struct bttv *btv); -static void init_PXC200(struct bttv *btv); -static void init_tea5757(struct bttv *btv); - -MODULE_PARM(card,"1-4i"); -MODULE_PARM(pll,"1-4i"); -MODULE_PARM(autoload,"i"); - -static unsigned int card[4] = { -1, -1, -1, -1 }; -static unsigned int pll[4] = { -1, -1, -1, -1 }; -#ifdef MODULE -static unsigned int autoload = 1; -#else -static unsigned int autoload = 0; -#endif - -/* ----------------------------------------------------------------------- */ -/* list of card IDs for bt878+ cards */ - -static struct CARD { - unsigned id; - int cardnr; - char *name; -} cards[] __devinitdata = { - { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, - { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00021461, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, - { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00041461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, - { 0x1118153b, BTTV_TERRATVALUE, "Terratec TV Value" }, - { 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV/Radio+" }, - { 0x1200bd11, BTTV_PINNACLERAVE, "Pinnacle PCTV Rave" }, - { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, - { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" }, - { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, - { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" }, - { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, - { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, - { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" }, - { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, - { 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, - { 0x402010fc, 0 /* no tvcards entry yet */, "I-O Data Co. GV-BCV3/PCI" }, -#if 0 /* probably wrong */ - { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, - { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, -#endif - { 0, -1, NULL } -}; - -/* ----------------------------------------------------------------------- */ -/* array with description for bt848 / bt878 tv/grabber cards */ - -struct tvcard bttv_tvcards[] = -{ - /* 0x00 */ - { " *** UNKNOWN *** ", - 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "MIRO PCTV", - 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Hauppauge old", - 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0,0,0,1, PLL_NONE, -1 }, - { "STB", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, - 0,1,1,1,1,0,0,1, PLL_NONE, -1 }, - - { "Intel", - 3, 1, 0, -1, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Diamond DTV2000", - 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "AVerMedia TVPhone", - 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "MATRIX-Vision MV-Delta", - 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x08 */ - { "Fly Video II", - 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1}, - { 0, 0xc00, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "TurboTV", - 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Hauppauge new (bt878)", - 4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0,0,0,1, PLL_28, -1 }, - { "MIRO PCTV pro", - 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0, - /* 3, 1, 0, 2, 0x3004F, { 2, 3, 1, 1}, {1, 0x10011, 5, 0,10}, 0x3004F, */ - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - { "ADS Technologies Channel Surfer TV", - 3, 1, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "AVerMedia TVCapture 98", - 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Aimslab VHX", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Zoltrix TV-Max", - 3, 1, 0, 2,15, { 2, 3, 1, 1}, {0 , 0, 1 , 0, 10},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x10 */ - { "Pixelview PlayTV (bt878)", - 3, 1, 0, 2, 0x01fe00, { 2, 3, 1, 1}, - { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Leadtek WinView 601", - 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, - { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "AVEC Intercapture", - 3, 2, 0, 2, 0, {2, 3, 1, 1}, {1, 0, 0, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "LifeView FlyKit w/o Tuner", - 3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}, { 0 },0, - 0,0,0,0,0,0,0,1, PLL_NONE, -1 }, - - { "CEI Raffles Card", - 3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Lucky Star Image World ConferenceTV", - 3, 1, 0, 2, 0x00fffe07, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_28, TUNER_PHILIPS_PAL_I }, - { "Phoebe Tv Master + FM", - 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Modular Technology MM205 PCTV, bt878", - 2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 },0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x18 */ - { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)", - 3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Terratec/Vobis TV-Boostar", - 3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Newer Hauppauge WinCam (bt878)", - 4, 1, 0, 3, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "MAXI TV Video PCI2", - 3, 1, 0, 2, 0xffff, { 2, 3, 1, 1}, { 0, 1, 2, 3, 0xc00},0, - 1,1,1,1,0,0,0,1, PLL_NONE, TUNER_PHILIPS_SECAM }, - - { "Terratec TerraTV+", - 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, - { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Imagenation PXC200", - 5, 1, -1, 4, 0, { 2, 3, 1, 0, 0}, { 0 }, 0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "FlyVideo 98", - 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, - { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "iProTV", - 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x20 */ - { "Intel Create and Share PCI", - 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Terratec TerraTValue", - 3, 1, 0, 2, 0xffff00, { 2, 3, 1, 1}, - { 0x500, 0, 0x300, 0x900, 0x900},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Leadtek WinFast 2000", - 3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0}, - { 0x621000,0x6ddf07,0x621100,0x620000,0xE210000,0x620000},0, - 1,1,1,1,1,0,0,1, PLL_28, -1 }, - { "Chronos Video Shuttle II", - 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - - { "Typhoon TView TV/FM Tuner", - 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "PixelView PlayTV pro", - 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, - { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0, - 0,0,0,0,0,0,0,1, PLL_28, -1 }, - { "TView99 CPH063", - 3, 1, 0, 2, 0x551e00, { 2, 3, 1, 1}, - { 0x551400, 0x551200, 0, 0, 0, 0x551200 }, 0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Pinnacle PCTV Rave", - 3, 1, 0, 2, 0x03000F, { 2, 3, 1, 1}, { 2, 0, 0, 0, 1},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - - /* 0x28 */ - { "STB2", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, - 0,1,1,1,0,1,1,1, PLL_NONE, -1 }, - { "AVerMedia TVPhone 98", - 3, 4, 0, 2, 4, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, 5 }, - { "ProVideo PV951", /* pic16c54 */ - 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, - 0,0,0,0,0,0,0,0, PLL_28, 1 }, - { "Little OnAir TV", - 3, 1, 0, 2, 0xe00b, {2, 3, 1, 1}, - {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},0, - 0,0,0,0,0,0,0,0, PLL_NONE, -1 }, - - { "Sigma TVII-FM", - 2, 1, 0, -1, 3, {2, 3, 1, 1}, {1, 1, 0, 2, 3},0, - 0,0,0,0,0,0,0,0, PLL_NONE, -1 }, - { "MATRIX-Vision MV-Delta 2", - 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, - 0,0,0,0,0,0,0,0, PLL_28, -1 }, - { "Zoltrix Genie TV", - 3, 1, 0, 2, 0xbcf03f, { 2, 3, 1, 1}, - { 0xbc803f, 0, 0xbcb03f, 0, 0xbcb03f}, 0, - 0,0,0,0,0,0,0,0, PLL_28, 5 }, - { "Terratec TV/Radio+", /* Radio ?? */ - 3, 1, 0, 2, 0x1f0000, { 2, 3, 1, 1}, - { 0xe2ffff, 0xebffff, 0, 0, 0xe0ffff, 0xe2ffff },0, - 0,0,0,0,0,0,0,0, PLL_35, 1 }, - - /* 0x30 */ - { "Dynalink Magic TView ", - 3, 1, 0, 2, 15, { 2, 3, 1, 1}, {2,0,0,0,1},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, -}; -const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard)); - -/* ----------------------------------------------------------------------- */ - -static unsigned char eeprom_data[256]; - -static void __devinit bttv_dump_eeprom(struct bttv *btv,int addr) -{ - int i; - - if (bttv_verbose < 2) - return; - /* for debugging: dump eeprom to syslog */ - printk(KERN_DEBUG "bttv%d: dump eeprom @ 0x%02x\n",btv->nr,addr); - for (i = 0; i < 256;) { - printk(KERN_DEBUG " %02x:",i); - do { - printk(" %02x",eeprom_data[i++]); - } while (i % 16); - printk("\n"); - } -} - -static int __devinit bttv_idcard_eeprom(struct bttv *btv) -{ - unsigned id; - int i,n; - - id = (eeprom_data[252] << 24) | - (eeprom_data[253] << 16) | - (eeprom_data[254] << 8) | - (eeprom_data[255]); - if (id == 0 || id == 0xffffffff) - return -1; - - /* look for the card */ - btv->cardid = id; - for (n = -1, i = 0; cards[i].id != 0; i++) - if (cards[i].id == id) - n = i; - - if (n != -1) { - /* found it */ - printk(KERN_INFO "bttv%d: card id: %s (0x%08x) => card=%d\n", - btv->nr,cards[n].name,id,cards[n].cardnr); - return cards[n].cardnr; - } else { - /* 404 */ - printk(KERN_INFO "bttv%d: id: unknown (0x%08x)\n", - btv->nr, id); - printk(KERN_INFO "please mail id, board name and " - "the correct card= insmod option to " - "kraxel@goldbach.in-berlin.de\n"); - return -1; - } -} - -#ifndef HAVE_TVAUDIO -/* can tda9855.c handle this too maybe? */ -static void __devinit init_tda9840(struct bttv *btv) -{ - /* Horrible Hack */ - bttv_I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1); /* sound mode switching */ - /* 00 - mute - 10 - mono / averaged stereo - 2a - stereo - 12 - dual A - 1a - dual AB - 16 - dual BA - 1e - dual B - 7a - external */ -} -#endif - -void __devinit bttv_idcard(struct bttv *btv) -{ - int type,eeprom = 0; - - btwrite(0, BT848_GPIO_OUT_EN); - - /* try to autodetect the card */ - /* many bt878 cards have a eeprom @ 0xa0 => read ID - and try to identify it */ - if (bttv_I2CRead(btv, I2C_HAUPEE, "eeprom") >= 0) { - eeprom = 0xa0; - bttv_readee(btv,eeprom_data,0xa0); - bttv_dump_eeprom(btv,0xa0); /* DEBUG */ - type = bttv_idcard_eeprom(btv); - if (-1 != type) { - btv->type = type; - } else if (btv->id <= 849) { - /* for unknown bt848, assume old Hauppauge */ - btv->type=BTTV_HAUPPAUGE; - } - - /* STB cards have a eeprom @ 0xae (old bt848) */ - } else if (bttv_I2CRead(btv, I2C_STBEE, "eeprom")>=0) { - btv->type=BTTV_STB; - } - - /* let the user override the autodetected type */ - if (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) - btv->type=card[btv->nr]; - - /* print which card config we are using */ - sprintf(btv->video_dev.name,"BT%d%s(%.23s)", - btv->id, - (btv->id==848 && btv->revision==0x12) ? "A" : "", - bttv_tvcards[btv->type].name); - printk(KERN_INFO "bttv%d: model: %s [%s]\n",btv->nr,btv->video_dev.name, - (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ? - "insmod option" : "autodetected"); - - /* board specific initialisations */ - if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) { - /* auto detect tuner for MIRO cards */ - btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; -#if 0 - if (btv->type == BTTV_MIROPRO) { - if (bttv_verbose) - printk(KERN_INFO "Initializing TEA5757...\n"); - init_tea5757(btv); - } -#endif - } - if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) { - /* pick up some config infos from the eeprom */ - if (0xa0 != eeprom) { - eeprom = 0xa0; - bttv_readee(btv,eeprom_data,0xa0); - } - hauppauge_eeprom(btv); - hauppauge_boot_msp34xx(btv); - } - if (btv->type == BTTV_PXC200) - init_PXC200(btv); - - /* pll configuration */ - if (!(btv->id==848 && btv->revision==0x11)) { - /* defaults from card list */ - if (PLL_28 == bttv_tvcards[btv->type].pll) { - btv->pll.pll_ifreq=28636363; - btv->pll.pll_crystal=BT848_IFORM_XT0; - } - /* insmod options can override */ - switch (pll[btv->nr]) { - case 0: /* none */ - btv->pll.pll_crystal = 0; - btv->pll.pll_ifreq = 0; - btv->pll.pll_ofreq = 0; - break; - case 1: /* 28 MHz */ - btv->pll.pll_ifreq = 28636363; - btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal=BT848_IFORM_XT0; - break; - case 2: /* 35 MHz */ - btv->pll.pll_ifreq = 35468950; - btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal=BT848_IFORM_XT1; - break; - } - } - - - /* tuner configuration */ - if (-1 != bttv_tvcards[btv->type].tuner_type) - btv->tuner_type = bttv_tvcards[btv->type].tuner_type; - if (btv->tuner_type != -1) - bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - - /* try to detect audio/fader chips */ - if (bttv_tvcards[btv->type].msp34xx && - bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) { - if (autoload) - request_module("msp3400"); - } - -#ifndef HAVE_TVAUDIO - if (bttv_tvcards[btv->type].tda8425 && - bttv_I2CRead(btv, I2C_TDA8425, "TDA8425") >=0) { - if (autoload) - request_module("tda8425"); - } - - if (bttv_tvcards[btv->type].tda9840 && - bttv_I2CRead(btv, I2C_TDA9840, "TDA9840") >=0) { - init_tda9840(btv); - btv->audio_chip = TDA9840; - /* move this to a module too? */ - init_tda9840(btv); - } - - if (bttv_tvcards[btv->type].tda985x && - bttv_I2CRead(btv, I2C_TDA9850, "TDA985x") >=0) { - if (autoload) - request_module("tda985x"); - } - if (bttv_tvcards[btv->type].tea63xx) { - if (autoload) - request_module("tea6300"); - } -#else - if (bttv_tvcards[btv->type].tda8425 || - bttv_tvcards[btv->type].tda9840 || - bttv_tvcards[btv->type].tda985x || - bttv_tvcards[btv->type].tea63xx) { - if (autoload) - request_module("tvaudio"); - } -#endif - - if (bttv_tvcards[btv->type].tda9875 && - bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { - if (autoload) - request_module("tda9875"); - } - - if (bttv_tvcards[btv->type].tda7432 && - bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { - if (autoload) - request_module("tda7432"); - } - - - if (bttv_tvcards[btv->type].tea64xx) { - if (autoload) - request_module("tea6420"); - } - - if (bttv_tvcards[btv->type].tuner != -1) { - if (autoload) - request_module("tuner"); - } -} - - -/* ----------------------------------------------------------------------- */ -/* some hauppauge specific stuff */ - -static struct HAUPPAUGE_TUNER -{ - int id; - char *name; -} -hauppauge_tuner[] __devinitdata = -{ - { TUNER_ABSENT, "" }, - { TUNER_ABSENT, "External" }, - { TUNER_ABSENT, "Unspecified" }, - { TUNER_ABSENT, "Philips FI1216" }, - { TUNER_PHILIPS_SECAM, "Philips FI1216MF" }, - { TUNER_PHILIPS_NTSC, "Philips FI1236" }, - { TUNER_ABSENT, "Philips FI1246" }, - { TUNER_ABSENT, "Philips FI1256" }, - { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" }, - { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" }, - { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" }, - { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" }, - { TUNER_ABSENT, "Philips FI1256 MK2" }, - { TUNER_ABSENT, "Temic 4032FY5" }, - { TUNER_TEMIC_PAL, "Temic 4002FH5" }, - { TUNER_TEMIC_PAL_I, "Temic 4062FY5" }, - { TUNER_ABSENT, "Philips FR1216 MK2" }, - { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" }, - { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" }, - { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" }, - { TUNER_ABSENT, "Philips FR1256 MK2" }, - { TUNER_PHILIPS_PAL, "Philips FM1216" }, - { TUNER_ABSENT, "Philips FM1216MF" }, - { TUNER_PHILIPS_NTSC, "Philips FM1236" }, - { TUNER_PHILIPS_PAL_I, "Philips FM1246" }, - { TUNER_ABSENT, "Philips FM1256" }, - { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" }, - { TUNER_ABSENT, "Samsung TCPN9082D" }, - { TUNER_ABSENT, "Samsung TCPM9092P" }, - { TUNER_TEMIC_PAL, "Temic 4006FH5" }, - { TUNER_ABSENT, "Samsung TCPN9085D" }, - { TUNER_ABSENT, "Samsung TCPB9085P" }, - { TUNER_ABSENT, "Samsung TCPL9091P" }, - { TUNER_ABSENT, "Temic 4039FR5" }, - { TUNER_ABSENT, "Philips FQ1216 ME" }, - { TUNER_TEMIC_PAL_I, "Temic 4066FY5" }, - { TUNER_ABSENT, "Philips TD1536" }, - { TUNER_ABSENT, "Philips TD1536D" }, - { TUNER_ABSENT, "Philips FMR1236" }, - { TUNER_ABSENT, "Philips FI1256MP" }, - { TUNER_ABSENT, "Samsung TCPQ9091P" }, - { TUNER_ABSENT, "Temic 4006FN5" }, - { TUNER_ABSENT, "Temic 4009FR5" }, - { TUNER_ABSENT, "Temic 4046FM5" }, -}; - -static void __devinit hauppauge_eeprom(struct bttv *btv) -{ - if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) - { - btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id; - if (bttv_verbose) - printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr, - hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type); - } -} - -static void __devinit hauppauge_boot_msp34xx(struct bttv *btv) -{ - int i; - - /* reset/enable the MSP on some Hauppauge cards */ - /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */ - btaor(32, ~32, BT848_GPIO_OUT_EN); - btaor(0, ~32, BT848_GPIO_DATA); - udelay(2500); - btaor(32, ~32, BT848_GPIO_DATA); - - if (bttv_verbose) - printk("bttv%d: Hauppauge msp34xx: reset line init\n",btv->nr); - - /* look if the msp3400 driver is already registered */ - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] != NULL && - btv->i2c_clients[i]->driver->id == I2C_DRIVERID_MSP3400) { - return; - } - } - - /* if not: look for the chip ... */ - if (bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx")) { - /* ... if found re-register to trigger a i2c bus rescan, */ - /* this time with the msp34xx chip activated */ - i2c_bit_del_bus(&btv->i2c_adap); - i2c_bit_add_bus(&btv->i2c_adap); - } -} - - -/* ----------------------------------------------------------------------- */ -/* Imagenation L-Model PXC200 Framegrabber */ -/* This is basically the same procedure as - * used by Alessandro Rubini in his pxc200 - * driver, but using BTTV functions */ - -static void __devinit init_PXC200(struct bttv *btv) -{ - static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x00 }; - int i,tmp; - - /* Initialise GPIO-connevted stuff */ - btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */ - btwrite(0,BT848_GPIO_DATA); - udelay(3); - btwrite(1<<13,BT848_GPIO_DATA); - /* GPIO inputs are pulled up, so no need to drive - * reset pin any longer */ - btwrite(0,BT848_GPIO_OUT_EN); - - /* we could/should try and reset/control the AD pots? but - right now we simply turned off the crushing. Without - this the AGC drifts drifts - remember the EN is reverse logic --> - setting BT848_ADC_AGC_EN disable the AGC - tboult@eecs.lehigh.edu - */ - btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC); - - /* Initialise MAX517 DAC */ - printk(KERN_INFO "Setting DAC reference voltage level ...\n"); - bttv_I2CWrite(btv,0x5E,0,0x80,1); - - /* Initialise 12C508 PIC */ - /* The I2CWrite and I2CRead commmands are actually to the - * same chips - but the R/W bit is included in the address - * argument so the numbers are different */ - - printk(KERN_INFO "Initialising 12C508 PIC chip ...\n"); - - for (i = 0; i < sizeof(vals)/sizeof(int); i++) { - tmp=bttv_I2CWrite(btv,0x1E,vals[i],0,1); - printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n", - tmp,bttv_I2CRead(btv,0x1F,NULL)); - } - printk(KERN_INFO "PXC200 Initialised.\n"); -} - -/* ----------------------------------------------------------------------- */ -/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */ -/* - * Copyright (c) 1999 Csaba Halasz - * This code is placed under the terms of the GNU General Public License - * - * Brutally hacked by Dan Sheridan djs52 8/3/00 - */ - -/* bus bits on the GPIO port */ -#define TEA_WE 6 -#define TEA_DATA 9 -#define TEA_CLK 8 -#define TEA_MOST 7 - -#define BUS_LOW(bit) btand(~(1<> TEA_##bit) & 1) - -/* TEA5757 register bits */ -#define TEA_FREQ 0:14 -#define TEA_BUFFER 15:15 - -#define TEA_SIGNAL_STRENGTH 16:17 - -#define TEA_PORT1 18:18 -#define TEA_PORT0 19:19 - -#define TEA_BAND 20:21 -#define TEA_BAND_FM 0 -#define TEA_BAND_MW 1 -#define TEA_BAND_LW 2 -#define TEA_BAND_SW 3 - -#define TEA_MONO 22:22 -#define TEA_ALLOW_STEREO 0 -#define TEA_FORCE_MONO 1 - -#define TEA_SEARCH_DIRECTION 23:23 -#define TEA_SEARCH_DOWN 0 -#define TEA_SEARCH_UP 1 - -#define TEA_STATUS 24:24 -#define TEA_STATUS_TUNED 0 -#define TEA_STATUS_SEARCHING 1 - -/* Low-level stuff */ -static int tea_read(struct bttv *btv) -{ - int value = 0; - long timeout; - int i; - - /* better safe than sorry */ - btaor((1<volume>>11)); - /* units */ - bits_out = (PT2254_DBS_IN_2>>(vol%5)); - /* tens */ - bits_out |= (PT2254_DBS_IN_10>>(vol/5)); - bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL; - data = btread(BT848_GPIO_DATA); - data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| - WINVIEW_PT2254_STROBE); - for (loops = 17; loops >= 0 ; loops--) { - if (bits_out & (1< - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HACKING -# include -#endif - -#include "bttv.h" -#include "tuner.h" - -#define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ -#define MIN(a,b) (((a)>(b))?(b):(a)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - - -static void bt848_set_risc_jmps(struct bttv *btv, int state); - -int bttv_num; /* number of Bt848s in use */ -struct bttv bttvs[BTTV_MAX]; - - -/* insmod args */ -MODULE_PARM(triton1,"i"); -MODULE_PARM(radio,"1-4i"); -MODULE_PARM(bigendian,"i"); -MODULE_PARM(fieldnr,"i"); -MODULE_PARM(bttv_verbose,"i"); -MODULE_PARM(bttv_debug,"i"); -MODULE_PARM(gbuffers,"i"); -MODULE_PARM(gbufsize,"i"); - -MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards"); -MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); - -#if defined(__sparc__) || defined(__powerpc__) -static unsigned int bigendian=1; -#else -static unsigned int bigendian=0; -#endif -static int triton1=0; -static unsigned int radio[BTTV_MAX]; -static unsigned int fieldnr = 0; -static unsigned int gbuffers = 2; -static unsigned int gbufsize = BTTV_MAX_FBUF; -unsigned int bttv_debug = 0; -unsigned int bttv_verbose = 1; - -#define I2C_TIMING (0x7<<4) -#define I2C_DELAY 10 - -#define I2C_SET(CTRL,DATA) \ - { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); } -#define I2C_GET() (btread(BT848_I2C)&1) - -#define BURSTOFFSET 76 -#define BTTV_ERRORS 5 - - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -#define MDEBUG(x) do { } while(0) /* Debug memory management */ - -/* [DaveM] I've recoded most of this so that: - * 1) It's easier to tell what is happening - * 2) It's more portable, especially for translating things - * out of vmalloc mapped areas in the kernel. - * 3) Less unnecessary translations happen. - * - * The code used to assume that the kernel vmalloc mappings - * existed in the page tables of every process, this is simply - * not guarenteed. We now use pgd_offset_k which is the - * defined way to get at the kernel page tables. - */ - -/* Given PGD from the address space's page table, return the kernel - * virtual mapping of the physical memory mapped at ADR. - */ -static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) -{ - unsigned long ret = 0UL; - pmd_t *pmd; - pte_t *ptep, pte; - - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, adr); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, adr); - pte = *ptep; - if(pte_present(pte)) { - ret = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE - 1)); - } - } - } - MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); - return ret; -} - -static inline unsigned long uvirt_to_bus(unsigned long adr) -{ - unsigned long kva, ret; - - kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); - ret = virt_to_bus((void *)kva); - MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); - return ret; -} - -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = virt_to_bus((void *)kva); - MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); - return ret; -} - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = __pa(kva); - MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); - return ret; -} - -static void * rvmalloc(signed long size) -{ - void * mem; - unsigned long adr, page; - - mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } - return mem; -} - -static void rvfree(void * mem, signed long size) -{ - unsigned long adr, page; - - if (mem) - { - adr=(unsigned long) mem; - while (size > 0) - { - page = kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } -} - - - -/* - * Create the giant waste of buffer space we need for now - * until we get DMA to user space sorted out (probably 2.3.x) - * - * We only create this as and when someone uses mmap - */ - -static int fbuffer_alloc(struct bttv *btv) -{ - if(!btv->fbuffer) - btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize); - else - printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n", - btv->nr); - if(!btv->fbuffer) - return -ENOBUFS; - return 0; -} - - -static int __devinit init_bttv_i2c(struct bttv *btv) -{ - /* i2c bit_adapter */ - memcpy(&btv->i2c_adap, &bttv_i2c_adap_template, sizeof(struct i2c_adapter)); - memcpy(&btv->i2c_algo, &bttv_i2c_algo_template, sizeof(struct i2c_algo_bit_data)); - memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client)); - - sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name), - " #%d", btv->nr); - btv->i2c_algo.data = btv; - btv->i2c_adap.data = btv; - btv->i2c_adap.algo_data = &btv->i2c_algo; - btv->i2c_client.adapter = &btv->i2c_adap; - - bttv_bit_setscl(btv,1); - bttv_bit_setsda(btv,1); - - btv->i2c_ok = i2c_bit_add_bus(&btv->i2c_adap); - return btv->i2c_ok; -} - - -/* ----------------------------------------------------------------------- */ - -static void audio(struct bttv *btv, int mode, int no_irq_context) -{ - btaor(bttv_tvcards[btv->type].gpiomask, ~bttv_tvcards[btv->type].gpiomask, - BT848_GPIO_OUT_EN); - - switch (mode) - { - case AUDIO_MUTE: - btv->audio|=AUDIO_MUTE; - break; - case AUDIO_UNMUTE: - btv->audio&=~AUDIO_MUTE; - mode=btv->audio; - break; - case AUDIO_OFF: - mode=AUDIO_OFF; - break; - case AUDIO_ON: - mode=btv->audio; - break; - default: - btv->audio&=AUDIO_MUTE; - btv->audio|=mode; - break; - } - /* if audio mute or not in H-lock, turn audio off */ - if ((btv->audio&AUDIO_MUTE)) - mode=AUDIO_OFF; - if ((mode == AUDIO_TUNER) && (btv->radio)) - mode = AUDIO_RADIO; - btaor(bttv_tvcards[btv->type].audiomux[mode], - ~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); - if (no_irq_context) - bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(mode)); -} - - -extern inline void bt848_dma(struct bttv *btv, uint state) -{ - if (state) - btor(3, BT848_GPIO_DMA_CTL); - else - btand(~3, BT848_GPIO_DMA_CTL); -} - - -/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/ - -/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C - PLL_X = Reference pre-divider (0=1, 1=2) - PLL_C = Post divider (0=6, 1=4) - PLL_I = Integer input - PLL_F = Fractional input - - F_input = 28.636363 MHz: - PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0 -*/ - -static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) -{ - unsigned char fl, fh, fi; - - /* prevent overflows */ - fin/=4; - fout/=4; - - fout*=12; - fi=fout/fin; - - fout=(fout%fin)*256; - fh=fout/fin; - - fout=(fout%fin)*256; - fl=fout/fin; - - /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/ - btwrite(fl, BT848_PLL_F_LO); - btwrite(fh, BT848_PLL_F_HI); - btwrite(fi|BT848_PLL_X, BT848_PLL_XCI); -} - -static int set_pll(struct bttv *btv) -{ - int i; - unsigned long tv; - - if (!btv->pll.pll_crystal) - return 0; - - if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) { - /* no PLL needed */ - if (btv->pll.pll_current == 0) { - /* printk ("bttv%d: PLL: is off\n",btv->nr); */ - return 0; - } - printk ("bttv%d: PLL: switching off\n",btv->nr); - btwrite(0x00,BT848_TGCTRL); - btwrite(0x00,BT848_PLL_XCI); - btv->pll.pll_current = 0; - return 0; - } - - if (btv->pll.pll_ofreq == btv->pll.pll_current) { - /* printk("bttv%d: PLL: no change required\n",btv->nr); */ - return 1; - } - - if (bttv_verbose) - printk("bttv%d: PLL: %d => %d ... ",btv->nr, - btv->pll.pll_ifreq, btv->pll.pll_ofreq); - - set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); - - /* Let other people run while the PLL stabilizes */ - tv=jiffies+HZ/10; /* .1 seconds */ - do - { - schedule(); - } - while(time_before(jiffies,tv)); - - for (i=0; i<100; i++) - { - if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK)) - btwrite(0,BT848_DSTATUS); - else - { - btwrite(0x08,BT848_TGCTRL); - btv->pll.pll_current = btv->pll.pll_ofreq; - if (bttv_verbose) - printk("ok\n"); - return 1; - } - mdelay(10); - } - btv->pll.pll_current = 0; - if (bttv_verbose) - printk("oops\n"); - return -1; -} - -static void bt848_muxsel(struct bttv *btv, unsigned int input) -{ - btaor(bttv_tvcards[btv->type].gpiomask2,~bttv_tvcards[btv->type].gpiomask2, - BT848_GPIO_OUT_EN); - - /* This seems to get rid of some synchronization problems */ - btand(~(3<<5), BT848_IFORM); - mdelay(10); - - - input %= bttv_tvcards[btv->type].video_inputs; - if (input==bttv_tvcards[btv->type].svhs) - { - btor(BT848_CONTROL_COMP, BT848_E_CONTROL); - btor(BT848_CONTROL_COMP, BT848_O_CONTROL); - } - else - { - btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); - btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); - } - btaor((bttv_tvcards[btv->type].muxsel[input&7]&3)<<5, ~(3<<5), BT848_IFORM); - audio(btv, (input!=bttv_tvcards[btv->type].tuner) ? - AUDIO_EXTERN : AUDIO_TUNER, 1); - btaor(bttv_tvcards[btv->type].muxsel[input]>>4, - ~bttv_tvcards[btv->type].gpiomask2, BT848_GPIO_DATA); -} - - -struct tvnorm -{ - u32 Fsc; - u16 swidth, sheight; /* scaled standard width, height */ - u16 totalwidth; - u8 adelay, bdelay, iform; - u32 scaledtwidth; - u16 hdelayx1, hactivex1; - u16 vdelay; - u8 vbipack; -}; - -static struct tvnorm tvnorms[] = { - /* PAL-BDGHI */ - /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ - { 35468950, - 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), - 1135, 186, 924, 0x20, 255}, - - /* NTSC */ - { 28636363, - 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), - 910, 128, 910, 0x1a, 144}, -#if 0 - /* SECAM EAST */ - { 35468950, - 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), - 944, 186, 922, 0x20, 255}, -#else - /* SECAM L */ - { 35468950, - 924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), - 1135, 186, 922, 0x20, 255}, -#endif - /* PAL-NC */ - { 28636363, - 640, 576, 910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), - 780, 130, 734, 0x1a, 144}, - /* PAL-M */ - { 28636363, - 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), - 780, 135, 754, 0x1a, 144}, - /* PAL-N */ - { 35468950, - 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1), - 944, 186, 922, 0x20, 144}, - /* NTSC-Japan */ - { 28636363, - 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), - 780, 135, 754, 0x16, 144}, -}; -#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) -#define VBI_SPL 2044 - -/* RISC command to write one VBI data line */ -#define VBI_RISC BT848_RISC_WRITE|VBI_SPL|BT848_RISC_EOL|BT848_RISC_SOL - -static void make_vbitab(struct bttv *btv) -{ - int i; - unsigned int *po=(unsigned int *) btv->vbi_odd; - unsigned int *pe=(unsigned int *) btv->vbi_even; - - if (bttv_debug > 1) - printk("bttv%d: vbi1: po=%08lx pe=%08lx\n", - btv->nr,virt_to_bus(po), virt_to_bus(pe)); - - *(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0; - for (i=0; i<16; i++) - { - *(po++)=cpu_to_le32(VBI_RISC); - *(po++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048)); - } - *(po++)=cpu_to_le32(BT848_RISC_JUMP); - *(po++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+4)); - - *(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0; - for (i=16; i<32; i++) - { - *(pe++)=cpu_to_le32(VBI_RISC); - *(pe++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048)); - } - *(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16)); - *(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); - - if (bttv_debug > 1) - printk("bttv%d: vbi2: po=%08lx pe=%08lx\n", - btv->nr,virt_to_bus(po), virt_to_bus(pe)); -} - -static int fmtbppx2[16] = { - 8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 -}; - -static int palette2fmt[] = { - 0, - BT848_COLOR_FMT_Y8, - BT848_COLOR_FMT_RGB8, - BT848_COLOR_FMT_RGB16, - BT848_COLOR_FMT_RGB24, - BT848_COLOR_FMT_RGB32, - BT848_COLOR_FMT_RGB15, - BT848_COLOR_FMT_YUY2, - BT848_COLOR_FMT_BtYUV, - -1, - -1, - -1, - BT848_COLOR_FMT_RAW, - BT848_COLOR_FMT_YCrCb422, - BT848_COLOR_FMT_YCrCb411, - BT848_COLOR_FMT_YCrCb422, - BT848_COLOR_FMT_YCrCb411, -}; -#define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int)) - -static int make_rawrisctab(struct bttv *btv, unsigned int *ro, - unsigned int *re, unsigned int *vbuf) -{ - unsigned long line; - unsigned long bpl=1024; /* bytes per line */ - unsigned long vadr=(unsigned long) vbuf; - - *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(ro++)=cpu_to_le32(0); - *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(re++)=cpu_to_le32(0); - - /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY - is 2 and without separate VBI grabbing. - We'll have to handle this inside the IRQ handler ... */ - - for (line=0; line < 640; line++) - { - *(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); - *(ro++)=cpu_to_le32(kvirt_to_bus(vadr)); - *(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); - *(re++)=cpu_to_le32(kvirt_to_bus(vadr+gbufsize/2)); - vadr+=bpl; - } - - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - - return 0; -} - -static int make_prisctab(struct bttv *btv, unsigned int *ro, - unsigned int *re, - unsigned int *vbuf, unsigned short width, - unsigned short height, unsigned short fmt) -{ - unsigned long line, lmask; - unsigned long bl, blcr, blcb, rcmd; - unsigned long todo; - unsigned int **rp; - int inter; - unsigned long cbadr, cradr; - unsigned long vadr=(unsigned long) vbuf; - int shift, csize; - - if (bttv_debug > 1) - printk("bttv%d: prisc1: ro=%08lx re=%08lx\n", - btv->nr,virt_to_bus(ro), virt_to_bus(re)); - - switch(fmt) - { - case VIDEO_PALETTE_YUV422P: - csize=(width*height)>>1; - shift=1; - lmask=0; - break; - - case VIDEO_PALETTE_YUV411P: - csize=(width*height)>>2; - shift=2; - lmask=0; - break; - - case VIDEO_PALETTE_YUV420P: - csize=(width*height)>>2; - shift=1; - lmask=1; - break; - - case VIDEO_PALETTE_YUV410P: - csize=(width*height)>>4; - shift=2; - lmask=3; - break; - - default: - return -1; - } - cbadr=vadr+(width*height); - cradr=cbadr+csize; - inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; - - *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); - *(ro++)=0; - *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); - *(re++)=0; - - for (line=0; line < (height<<(1^inter)); line++) - { - if(line==height) - { - vadr+=csize<<1; - cbadr=vadr+(width*height); - cradr=cbadr+csize; - } - if (inter) - rp= (line&1) ? &re : &ro; - else - rp= (line>=height) ? &ro : &re; - - - if(line&lmask) - rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL; - else - rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL; - - todo=width; - while(todo) - { - bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); - blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<todo) ? todo : bl; - blcr=bl>>shift; - blcb=blcr; - /* bl now containts the longest row that can be written */ - todo-=bl; - if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */ - - *((*rp)++)=cpu_to_le32(rcmd|bl); - *((*rp)++)=cpu_to_le32(blcb|(blcr<<16)); - *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); - vadr+=bl; - if((rcmd&(15<<28))==BT848_RISC_WRITE123) - { - *((*rp)++)=(kvirt_to_bus(cbadr)); - cbadr+=blcb; - *((*rp)++)=cpu_to_le32(kvirt_to_bus(cradr)); - cradr+=blcr; - } - - rcmd&=~BT848_RISC_SOL; /* only the first has SOL */ - } - } - - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - - if (bttv_debug > 1) - printk("bttv%d: prisc2: ro=%08lx re=%08lx\n", - btv->nr,virt_to_bus(ro), virt_to_bus(re)); - - return 0; -} - -static int make_vrisctab(struct bttv *btv, unsigned int *ro, - unsigned int *re, - unsigned int *vbuf, unsigned short width, - unsigned short height, unsigned short palette) -{ - unsigned long line; - unsigned long bpl; /* bytes per line */ - unsigned long bl; - unsigned long todo; - unsigned int **rp; - int inter; - unsigned long vadr=(unsigned long) vbuf; - - if (palette==VIDEO_PALETTE_RAW) - return make_rawrisctab(btv, ro, re, vbuf); - if (palette>=VIDEO_PALETTE_PLANAR) - return make_prisctab(btv, ro, re, vbuf, width, height, palette); - - if (bttv_debug > 1) - printk("bttv%d: vrisc1: ro=%08lx re=%08lx\n", - btv->nr,virt_to_bus(ro), virt_to_bus(re)); - - inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; - bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; - - *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(ro++)=cpu_to_le32(0); - *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(re++)=cpu_to_le32(0); - - for (line=0; line < (height<<(1^inter)); line++) - { - if (inter) - rp= (line&1) ? &re : &ro; - else - rp= (line>=height) ? &ro : &re; - - bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); - if (bpl<=bl) - { - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| - BT848_RISC_EOL|bpl); - *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); - vadr+=bpl; - } - else - { - todo=bpl; - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|bl); - *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); - vadr+=bl; - todo-=bl; - while (todo>PAGE_SIZE) - { - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE); - *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); - vadr+=PAGE_SIZE; - todo-=PAGE_SIZE; - } - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo); - *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); - vadr+=todo; - } - } - - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - - if (bttv_debug > 1) - printk("bttv%d: vrisc2: ro=%08lx re=%08lx\n", - btv->nr,virt_to_bus(ro), virt_to_bus(re)); - - return 0; -} - -static unsigned char lmaskt[8] = -{ 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; -static unsigned char rmaskt[8] = -{ 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; - -static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h) -{ - unsigned char lmask, rmask, *p; - int W, l, r; - int i; - - if (bttv_debug > 1) - printk("bttv clip: %dx%d+%d+%d\n",w,h,x,y); - - /* bitmap is fixed width, 128 bytes (1024 pixels represented) */ - if (x<0) - { - w+=x; - x=0; - } - if (y<0) - { - h+=y; - y=0; - } - if (w < 0 || h < 0) /* catch bad clips */ - return; - /* out of range data should just fall through */ - if (y+h>=625) - h=625-y; - if (x+w>=1024) - w=1024-x; - - l=x>>3; - r=(x+w-1)>>3; - W=r-l-1; - lmask=lmaskt[x&7]; - rmask=rmaskt[(x+w-1)&7]; - p=clipmap+128*y+l; - - if (W>0) - { - for (i=0; iwin.bpp is allowed here */ - bpp = fmtbppx2[btv->win.color_fmt&0xf]/2; - bpl=btv->win.bpl; - adr=btv->win.vidadr + btv->win.x * btv->win.bpp + btv->win.y * bpl; - inter=(btv->win.interlace&1)^1; - width=btv->win.width; - height=btv->win.height; - if (bttv_debug > 1) - printk("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n", - btv->nr,btv->picture.palette,width,height,bpl,bpp); - if(width > 1023) - width = 1023; /* sanity check */ - if(height > 625) - height = 625; /* sanity check */ - ro=btv->risc_scr_odd; - re=btv->risc_scr_even; - - if (bttv_debug) - printk("bttv%d: clip: ro=%08lx re=%08lx\n", - btv->nr,virt_to_bus(ro), virt_to_bus(re)); - - if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) { - /* can't clip, don't generate any risc code */ - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - } - if (ncr < 0) { /* bitmap was pased */ - memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE); - } else { /* convert rectangular clips to a bitmap */ - memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ - for (i=0; iwin.x * btv->win.bpp) / bpp; - clip_draw_rectangle(clipmap, (width > maxw) ? maxw : width, - 0, 1024, 768); - clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ? - (btv->win.sheight-btv->win.y) : height,1024,768); - if (btv->win.x<0) - clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768); - if (btv->win.y<0) - clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y)); - - *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(ro++)=cpu_to_le32(0); - *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(re++)=cpu_to_le32(0); - - /* translate bitmap to risc code */ - for (line=outofmem=0; line < (height<>inter; - rp= (line&1) ? &re : &ro; - clipline = clipmap + (y<<7); /* running pointers ... */ - lastbit = *clipline & 1; - for(x=dx=0,sx=0; x<=width && !outofmem;) { - if (0 == (x&7)) { - /* check bytes not bits if we can ... */ - if (lastbit) { - while (0xff==*clipline && xrisc_scr_odd>RISCMEM_LEN/2 - 16) - outofmem++; - if (re - btv->risc_scr_even>RISCMEM_LEN/2 - 16) - outofmem++; - } - x++; - if (0 == (x&7)) - clipline++; - } - if ((!inter)||(line&1)) - adr+=bpl; - } - - vfree(clipmap); - /* outofmem flag relies on the following code to discard extra data */ - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - - if (bttv_debug > 1) - printk("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n", - btv->nr,btv->picture.palette,width,height,bpl,bpp); -} - -/* - * Set the registers for the size we have specified. Don't bother - * trying to understand this without the BT848 manual in front of - * you [AC]. - * - * PS: The manual is free for download in .pdf format from - * www.brooktree.com - nicely done those folks. - */ - -static inline void bt848_set_eogeo(struct bttv *btv, struct tvnorm *tvn, - int odd, int width, int height) -{ - u16 vscale, hscale; - u32 xsf, sr; - u16 hdelay; - u8 crop, vtc; - int inter = (height>tvn->sheight/2) ? 0 : 1; - int off = odd ? 0x80 : 0x00; - - xsf = (width*tvn->scaledtwidth)/tvn->swidth; - hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - hdelay = tvn->hdelayx1; - hdelay = (hdelay*width)/tvn->swidth; - hdelay &= 0x3fe; - sr=((tvn->sheight>>inter)*512)/height-512; - vscale=(0x10000UL-sr)&0x1fff; - crop=((width>>8)&0x03)|((hdelay>>6)&0x0c)| - ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); - vscale |= inter ? (BT848_VSCALE_INT<<8) : 0; - -#if 0 - /* Some people say interpolation looks bad ... */ - vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); - if (width < 767) - btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - else - btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); -#else - vtc = 0; - btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); -#endif - - btwrite(vtc, BT848_E_VTC+off); - btwrite(hscale>>8, BT848_E_HSCALE_HI+off); - btwrite(hscale&0xff, BT848_E_HSCALE_LO+off); - btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); - btwrite(vscale&0xff, BT848_E_VSCALE_LO+off); - btwrite(width&0xff, BT848_E_HACTIVE_LO+off); - btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off); - btwrite(tvn->sheight&0xff, BT848_E_VACTIVE_LO+off); - btwrite(tvn->vdelay&0xff, BT848_E_VDELAY_LO+off); - btwrite(crop, BT848_E_CROP+off); -} - - -static void bt848_set_geo(struct bttv *btv, - int no_irq_context) -{ - u16 ewidth, eheight, owidth, oheight; - u16 format, bswap; - struct tvnorm *tvn; - - tvn=&tvnorms[btv->win.norm]; - - btwrite(tvn->adelay, BT848_ADELAY); - btwrite(tvn->bdelay, BT848_BDELAY); - btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM); - btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE); - btwrite(1, BT848_VBI_PACK_DEL); - - btv->pll.pll_ofreq = tvn->Fsc; - if (no_irq_context) - set_pll(btv); - - btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0; - - if (0 == btv->risc_cap_odd && - 0 == btv->risc_cap_even) { - /* overlay only */ - owidth = btv->win.width; - oheight = btv->win.height; - ewidth = btv->win.width; - eheight = btv->win.height; - format = btv->win.color_fmt; - bswap = btv->fb_color_ctl; - } else if (-1 != btv->gq_grab && - 0 == btv->risc_cap_odd && - !btv->win.interlace && - btv->scr_on) { - /* odd field -> overlay, even field -> capture */ - owidth = btv->win.width; - oheight = btv->win.height; - ewidth = btv->gbuf[btv->gq_grab].width; - eheight = btv->gbuf[btv->gq_grab].height; - format = (btv->win.color_fmt & 0xf0) | - (btv->gbuf[btv->gq_grab].fmt & 0x0f); - bswap = btv->fb_color_ctl & 0x0a; - } else { - /* capture only */ - owidth = btv->gbuf[btv->gq_grab].width; - oheight = btv->gbuf[btv->gq_grab].height; - ewidth = btv->gbuf[btv->gq_grab].width; - eheight = btv->gbuf[btv->gq_grab].height; - format = btv->gbuf[btv->gq_grab].fmt; - bswap = 0; - } - - /* program odd + even fields */ - bt848_set_eogeo(btv, tvn, 1, owidth, oheight); - bt848_set_eogeo(btv, tvn, 0, ewidth, eheight); - - btwrite(format, BT848_COLOR_FMT); - btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); -} - - -static int bpp2fmt[4] = { - BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16, - BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32 -}; - -static void bt848_set_winsize(struct bttv *btv) -{ - unsigned short format; - - if (btv->picture.palette > 0 && btv->picture.palette <= VIDEO_PALETTE_YUV422) { - /* format set by VIDIOCSPICT */ - format = palette2fmt[btv->picture.palette]; - } else { - /* use default for the given color depth */ - format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 : - bpp2fmt[(btv->win.bpp-1)&3]; - } - btv->win.color_fmt = format; - if (bigendian && - format == BT848_COLOR_FMT_RGB32) { - btv->fb_color_ctl = - BT848_COLOR_CTL_WSWAP_ODD | - BT848_COLOR_CTL_WSWAP_EVEN | - BT848_COLOR_CTL_BSWAP_ODD | - BT848_COLOR_CTL_BSWAP_EVEN; - } else if (bigendian && - (format == BT848_COLOR_FMT_RGB16 || - format == BT848_COLOR_FMT_RGB15)) { - btv->fb_color_ctl = - BT848_COLOR_CTL_BSWAP_ODD | - BT848_COLOR_CTL_BSWAP_EVEN; - } else { - btv->fb_color_ctl = 0; - } - - /* RGB8 seems to be a 9x5x5 GRB color cube starting at - * color 16. Why the h... can't they even mention this in the - * data sheet? [AC - because it's a standard format so I guess - * it never occurred to them] - * Enable dithering in this mode. - */ - - if (format==BT848_COLOR_FMT_RGB8) - btand(~BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); - else - btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); - - bt848_set_geo(btv,1); -} - -#ifdef HACKING -/* playing with kiobufs and dma-to-userspace. 2.4.x only - Yes, I know: cut+paste programming is ugly. - will fix later, this is proof-of-concept right now. */ -static int make_vrisctab_kiobuf(struct bttv *btv, unsigned int *ro, - unsigned int *re, struct kiobuf *iobuf, - unsigned short width, unsigned short height, - unsigned short palette) -{ - unsigned long bpl; /* bytes per line */ - unsigned long bl; - unsigned long todo; - unsigned long pageaddr; - unsigned int **rp; - unsigned long line,inter,offset,page; - - inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; - bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; - - *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(ro++)=cpu_to_le32(0); - *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(re++)=cpu_to_le32(0); - - offset = iobuf->offset; - page = 0; - pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); - for (line=0; line < (height<<(1^inter)); line++) - { - if (inter) - rp= (line&1) ? &re : &ro; - else - rp= (line>=height) ? &ro : &re; - - bl = PAGE_SIZE - offset; - if (bpl <= bl) { - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| - BT848_RISC_EOL|bpl); - *((*rp)++)=cpu_to_le32(pageaddr+offset); - offset+=bpl; - } else { - todo = bpl; - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|bl); - *((*rp)++)=cpu_to_le32(pageaddr+offset); - todo -= bl; - offset = 0; - page++; - pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); - while (todo>PAGE_SIZE) - { - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE); - *((*rp)++)=cpu_to_le32(pageaddr); - page++; - pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); - } - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo); - *((*rp)++)=cpu_to_le32(pageaddr); - offset += todo; - } - } - - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - - return 0; -} - -static int vgrab_kiobuf(struct bttv *btv, struct bttv_just_hacking *mp, - struct kiobuf *iobuf) -{ - unsigned int *ro, *re; - unsigned long flags; - - if(btv->gbuf[0].stat != GBUFFER_UNUSED) - return -EBUSY; - - if(mp->height < 32 || mp->width < 32) - return -EINVAL; - if (mp->format >= 12 /* more is'nt yet ... PALETTEFMT_MAX */) - return -EINVAL; - - if(-1 == palette2fmt[mp->format]) - return -EINVAL; - - /* - * Ok load up the BT848 - */ - - ro=btv->gbuf[0].risc; - re=ro+2048; - make_vrisctab_kiobuf(btv, ro, re, iobuf, mp->width, mp->height, mp->format); - - if (bttv_debug) - printk("bttv%d: cap vgrab_kiobuf: queue %d (%d:%dx%d)\n", - btv->nr,0,mp->format,mp->width,mp->height); - spin_lock_irqsave(&btv->s_lock, flags); - btv->gbuf[0].stat = GBUFFER_GRABBING; - btv->gbuf[0].fmt = palette2fmt[mp->format]; - btv->gbuf[0].width = mp->width; - btv->gbuf[0].height = mp->height; - btv->gbuf[0].ro = virt_to_bus(ro); - btv->gbuf[0].re = virt_to_bus(re); - -#if 1 - if (mp->height <= tvnorms[btv->win.norm].sheight/2 && - mp->format != VIDEO_PALETTE_RAW) - btv->gbuf[0].ro = 0; -#endif - - if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) { - btv->gq_start = 1; - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); - } - btv->gqueue[btv->gq_in++] = 0; - btv->gq_in = btv->gq_in % MAX_GBUFFERS; - - btor(3, BT848_CAP_CTL); - btor(3, BT848_GPIO_DMA_CTL); - spin_unlock_irqrestore(&btv->s_lock, flags); - return 0; -} -#endif - -/* - * Grab into virtual memory. - */ - -static int vgrab(struct bttv *btv, struct video_mmap *mp) -{ - unsigned int *ro, *re; - unsigned int *vbuf; - unsigned long flags; - - if(btv->fbuffer==NULL) - { - if(fbuffer_alloc(btv)) - return -ENOBUFS; - } - - if(mp->frame >= gbuffers || mp->frame < 0) - return -EINVAL; - if(btv->gbuf[mp->frame].stat != GBUFFER_UNUSED) - return -EBUSY; - - if(mp->height < 32 || mp->width < 32) - return -EINVAL; - if (mp->format >= PALETTEFMT_MAX) - return -EINVAL; - - if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2 - > gbufsize) - return -EINVAL; - if(-1 == palette2fmt[mp->format]) - return -EINVAL; - - /* - * Ok load up the BT848 - */ - - vbuf=(unsigned int *)(btv->fbuffer+gbufsize*mp->frame); - ro=btv->gbuf[mp->frame].risc; - re=ro+2048; - make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); - - if (bttv_debug) - printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n", - btv->nr,mp->frame,mp->format,mp->width,mp->height); - spin_lock_irqsave(&btv->s_lock, flags); - btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; - btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; - btv->gbuf[mp->frame].width = mp->width; - btv->gbuf[mp->frame].height = mp->height; - btv->gbuf[mp->frame].ro = virt_to_bus(ro); - btv->gbuf[mp->frame].re = virt_to_bus(re); - -#if 1 - if (mp->height <= tvnorms[btv->win.norm].sheight/2 && - mp->format != VIDEO_PALETTE_RAW) - btv->gbuf[mp->frame].ro = 0; -#endif - - if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) { - btv->gq_start = 1; - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); - } - btv->gqueue[btv->gq_in++] = mp->frame; - btv->gq_in = btv->gq_in % MAX_GBUFFERS; - - btor(3, BT848_CAP_CTL); - btor(3, BT848_GPIO_DMA_CTL); - spin_unlock_irqrestore(&btv->s_lock, flags); - return 0; -} - -static long bttv_write(struct video_device *v, const char *buf, unsigned long count, int nonblock) -{ - return -EINVAL; -} - -static long bttv_read(struct video_device *v, char *buf, unsigned long count, int nonblock) -{ - struct bttv *btv= (struct bttv *)v; - int q,todo; - DECLARE_WAITQUEUE(wait, current); - - /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */ - todo=count; - while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) - { - if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) - return -EFAULT; - todo-=q; - buf+=q; - - add_wait_queue(&btv->vbiq, &wait); - current->state = TASK_INTERRUPTIBLE; - if (todo && q==VBIBUF_SIZE-btv->vbip) - { - if(nonblock) - { - remove_wait_queue(&btv->vbiq, &wait); - current->state = TASK_RUNNING; - if(count==todo) - return -EWOULDBLOCK; - return count-todo; - } - schedule(); - if(signal_pending(current)) - { - remove_wait_queue(&btv->vbiq, &wait); - current->state = TASK_RUNNING; - - if(todo==count) - return -EINTR; - else - return count-todo; - } - } - remove_wait_queue(&btv->vbiq, &wait); - current->state = TASK_RUNNING; - } - if (todo) - { - if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo)) - return -EFAULT; - btv->vbip+=todo; - } - return count; -} - -static inline void burst(int on) -{ - tvnorms[0].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0); - tvnorms[0].hdelayx1 = 186 - (on?BURSTOFFSET :0); - tvnorms[2].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0); - tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0); -} - -static void bt848_restart(struct bttv *btv) -{ - unsigned long irq_flags; - - if (bttv_verbose) - printk("bttv%d: resetting chip\n",btv->nr); - btwrite(0xfffffUL, BT848_INT_STAT); - btand(~15, BT848_GPIO_DMA_CTL); - btwrite(0, BT848_SRESET); - btwrite(virt_to_bus(btv->risc_jmp+2), - BT848_RISC_STRT_ADD); - - /* enforce pll reprogramming */ - btv->pll.pll_current = 0; - set_pll(btv); - - spin_lock_irqsave(&btv->s_lock, irq_flags); - btv->errors = 0; - btv->needs_restart = 0; - bt848_set_geo(btv,0); - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); -} - -/* - * Open a bttv card. Right now the flags stuff is just playing - */ - -static int bttv_open(struct video_device *dev, int flags) -{ - struct bttv *btv = (struct bttv *)dev; - int i,ret; - - ret = -EBUSY; - - MOD_INC_USE_COUNT; - down(&btv->lock); - if (btv->user) - goto out_unlock; - - btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize); - ret = -ENOMEM; - if (!btv->fbuffer) - goto out_unlock; - - btv->gq_in = 0; - btv->gq_out = 0; - btv->gq_grab = -1; - for (i = 0; i < gbuffers; i++) - btv->gbuf[i].stat = GBUFFER_UNUSED; - - if (btv->needs_restart) - bt848_restart(btv); - burst(0); - set_pll(btv); - btv->user++; - up(&btv->lock); - return 0; - - out_unlock: - up(&btv->lock); - MOD_DEC_USE_COUNT; - return ret; -} - -static void bttv_close(struct video_device *dev) -{ - struct bttv *btv=(struct bttv *)dev; - unsigned long irq_flags; - - down(&btv->lock); - btv->user--; - spin_lock_irqsave(&btv->s_lock, irq_flags); - btv->scr_on = 0; - btv->risc_cap_odd = 0; - btv->risc_cap_even = 0; - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - - /* - * A word of warning. At this point the chip - * is still capturing because its FIFO hasn't emptied - * and the DMA control operations are posted PCI - * operations. - */ - - btread(BT848_I2C); /* This fixes the PCI posting delay */ - - if (-1 != btv->gq_grab) { - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ - } - - /* - * We have allowed it to drain. - */ - - if(btv->fbuffer) - rvfree((void *) btv->fbuffer, gbuffers*gbufsize); - btv->fbuffer=0; - up(&btv->lock); - MOD_DEC_USE_COUNT; -} - - -/***********************************/ -/* ioctls and supporting functions */ -/***********************************/ - -extern inline void bt848_bright(struct bttv *btv, uint bright) -{ - btwrite(bright&0xff, BT848_BRIGHT); -} - -extern inline void bt848_hue(struct bttv *btv, uint hue) -{ - btwrite(hue&0xff, BT848_HUE); -} - -extern inline void bt848_contrast(struct bttv *btv, uint cont) -{ - unsigned int conthi; - - conthi=(cont>>6)&4; - btwrite(cont&0xff, BT848_CONTRAST_LO); - btaor(conthi, ~4, BT848_E_CONTROL); - btaor(conthi, ~4, BT848_O_CONTROL); -} - -extern inline void bt848_sat_u(struct bttv *btv, unsigned long data) -{ - u32 datahi; - - datahi=(data>>7)&2; - btwrite(data&0xff, BT848_SAT_U_LO); - btaor(datahi, ~2, BT848_E_CONTROL); - btaor(datahi, ~2, BT848_O_CONTROL); -} - -static inline void bt848_sat_v(struct bttv *btv, unsigned long data) -{ - u32 datahi; - - datahi=(data>>8)&1; - btwrite(data&0xff, BT848_SAT_V_LO); - btaor(datahi, ~1, BT848_E_CONTROL); - btaor(datahi, ~1, BT848_O_CONTROL); -} - -/* - * ioctl routine - */ - - -static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct bttv *btv=(struct bttv *)dev; - unsigned long irq_flags; - int i,ret = 0; - - if (bttv_debug > 1) - printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd); - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability b; - strcpy(b.name,btv->video_dev.name); - b.type = VID_TYPE_CAPTURE| - ((bttv_tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) | - VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING| - VID_TYPE_FRAMERAM| - VID_TYPE_SCALES; - b.channels = bttv_tvcards[btv->type].video_inputs; - b.audios = bttv_tvcards[btv->type].audio_inputs; - b.maxwidth = tvnorms[btv->win.norm].swidth; - b.maxheight = tvnorms[btv->win.norm].sheight; - b.minwidth = 32; - b.minheight = 32; - if(copy_to_user(arg,&b,sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel v; - if(copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - v.flags=VIDEO_VC_AUDIO; - v.tuners=0; - v.type=VIDEO_TYPE_CAMERA; - v.norm = btv->win.norm; - if (v.channel>=bttv_tvcards[btv->type].video_inputs) - return -EINVAL; - if(v.channel==bttv_tvcards[btv->type].tuner) - { - strcpy(v.name,"Television"); - v.flags|=VIDEO_VC_TUNER; - v.type=VIDEO_TYPE_TV; - v.tuners=1; - } - else if(v.channel==bttv_tvcards[btv->type].svhs) - strcpy(v.name,"S-Video"); - else - sprintf(v.name,"Composite%d",v.channel); - - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - /* - * Each channel has 1 tuner - */ - case VIDIOCSCHAN: - { - struct video_channel v; - if(copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - - if (v.channel>bttv_tvcards[btv->type].video_inputs) - return -EINVAL; - if (v.norm > (sizeof(tvnorms)/sizeof(*tvnorms))) - return -EOPNOTSUPP; - - bttv_call_i2c_clients(btv,cmd,&v); - down(&btv->lock); - bt848_muxsel(btv, v.channel); - btv->channel=v.channel; - if (btv->win.norm != v.norm) { - btv->win.norm = v.norm; - make_vbitab(btv); - spin_lock_irqsave(&btv->s_lock, irq_flags); - bt848_set_winsize(btv); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - } - up(&btv->lock); - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v,arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner||btv->channel) /* Only tuner 0 */ - return -EINVAL; - strcpy(v.name, "Television"); - v.rangelow=0; - v.rangehigh=0xFFFFFFFF; - v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; - v.mode = btv->win.norm; - v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; - bttv_call_i2c_clients(btv,cmd,&v); - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - /* We have but one tuner */ - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - /* Only one channel has a tuner */ - if(v.tuner!=bttv_tvcards[btv->type].tuner) - return -EINVAL; - - if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC - &&v.mode!=VIDEO_MODE_SECAM) - return -EOPNOTSUPP; - bttv_call_i2c_clients(btv,cmd,&v); - if (btv->win.norm != v.mode) { - btv->win.norm = v.mode; - down(&btv->lock); - set_pll(btv); - make_vbitab(btv); - spin_lock_irqsave(&btv->s_lock, irq_flags); - bt848_set_winsize(btv); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - up(&btv->lock); - } - return 0; - } - case VIDIOCGPICT: - { - struct video_picture p=btv->picture; - if(copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - if(copy_from_user(&p, arg,sizeof(p))) - return -EFAULT; - if (p.palette > PALETTEFMT_MAX) - return -EINVAL; - down(&btv->lock); - /* We want -128 to 127 we get 0-65535 */ - bt848_bright(btv, (p.brightness>>8)-128); - /* 0-511 for the colour */ - bt848_sat_u(btv, p.colour>>7); - bt848_sat_v(btv, ((p.colour>>7)*201L)/237); - /* -128 to 127 */ - bt848_hue(btv, (p.hue>>8)-128); - /* 0-511 */ - bt848_contrast(btv, p.contrast>>7); - btv->picture = p; - up(&btv->lock); - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - struct video_clip *vcp = NULL; - - if(copy_from_user(&vw,arg,sizeof(vw))) - return -EFAULT; - - down(&btv->lock); - if(vw.flags || vw.width < 16 || vw.height < 16) - { - spin_lock_irqsave(&btv->s_lock, irq_flags); - btv->scr_on = 0; - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - return -EINVAL; - } - if (btv->win.bpp < 4) - { /* adjust and align writes */ - vw.x = (vw.x + 3) & ~3; - vw.width &= ~3; - } - if (btv->needs_restart) - bt848_restart(btv); - btv->win.x=vw.x; - btv->win.y=vw.y; - btv->win.width=vw.width; - btv->win.height=vw.height; - - spin_lock_irqsave(&btv->s_lock, irq_flags); - bt848_set_risc_jmps(btv,0); - bt848_set_winsize(btv); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - - /* - * Do any clips. - */ - if(vw.clipcount<0) { - if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) - return -ENOMEM; - if(copy_from_user(vcp, vw.clips, - VIDEO_CLIPMAP_SIZE)) { - vfree(vcp); - return -EFAULT; - } - } else if (vw.clipcount) { - if((vcp=vmalloc(sizeof(struct video_clip)* - (vw.clipcount))) == NULL) - return -ENOMEM; - if(copy_from_user(vcp,vw.clips, - sizeof(struct video_clip)* - vw.clipcount)) { - vfree(vcp); - return -EFAULT; - } - } - make_clip_tab(btv, vcp, vw.clipcount); - if (vw.clipcount != 0) - vfree(vcp); - spin_lock_irqsave(&btv->s_lock, irq_flags); - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - up(&btv->lock); - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - /* Oh for a COBOL move corresponding .. */ - vw.x=btv->win.x; - vw.y=btv->win.y; - vw.width=btv->win.width; - vw.height=btv->win.height; - vw.chromakey=0; - vw.flags=0; - if(btv->win.interlace) - vw.flags|=VIDEO_WINDOW_INTERLACE; - if(copy_to_user(arg,&vw,sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - { - int v; - if(copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - if(btv->win.vidadr == 0) - return -EINVAL; - if (btv->win.width==0 || btv->win.height==0) - return -EINVAL; - spin_lock_irqsave(&btv->s_lock, irq_flags); - if (v == 1 && btv->win.vidadr != 0) - btv->scr_on = 1; - if (v == 0) - btv->scr_on = 0; - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - return 0; - } - case VIDIOCGFBUF: - { - struct video_buffer v; - v.base=(void *)btv->win.vidadr; - v.height=btv->win.sheight; - v.width=btv->win.swidth; - v.depth=btv->win.depth; - v.bytesperline=btv->win.bpl; - if(copy_to_user(arg, &v,sizeof(v))) - return -EFAULT; - return 0; - - } - case VIDIOCSFBUF: - { - struct video_buffer v; - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; - 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.height > 16 && v.bytesperline > 16) - return -EINVAL; - down(&btv->lock); - if (v.base) - btv->win.vidadr=(unsigned long)v.base; - btv->win.sheight=v.height; - btv->win.swidth=v.width; - btv->win.bpp=((v.depth+7)&0x38)/8; - btv->win.depth=v.depth; - btv->win.bpl=v.bytesperline; - - /* set sefault color format */ - switch (btv->win.bpp) { - case 8: btv->picture.palette = VIDEO_PALETTE_HI240; break; - case 15: btv->picture.palette = VIDEO_PALETTE_RGB555; break; - case 16: btv->picture.palette = VIDEO_PALETTE_RGB565; break; - case 24: btv->picture.palette = VIDEO_PALETTE_RGB24; break; - case 32: btv->picture.palette = VIDEO_PALETTE_RGB32; break; - } - - if (bttv_debug) - printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", - v.base, v.width,v.height, btv->win.bpp, btv->win.bpl); - spin_lock_irqsave(&btv->s_lock, irq_flags); - bt848_set_winsize(btv); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - up(&btv->lock); - return 0; - } - case VIDIOCKEY: - { - /* Will be handled higher up .. */ - return 0; - } - case VIDIOCGFREQ: - { - unsigned long v=btv->win.freq; - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSFREQ: - { - unsigned long v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - btv->win.freq=v; - bttv_call_i2c_clients(btv,cmd,&v); -#if 0 - if (btv->type == BTTV_MIROPRO && btv->radio) - tea5757_set_freq(btv,v); -#endif - return 0; - } - - case VIDIOCGAUDIO: - { - struct video_audio v; - - v=btv->audio_dev; - v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE); - v.flags|=VIDEO_AUDIO_MUTABLE; - strcpy(v.name,"TV"); - - v.mode = VIDEO_SOUND_MONO; - bttv_call_i2c_clients(btv,cmd,&v); - - if (btv->type == BTTV_TERRATV) { - v.mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -#ifndef HAVE_TVAUDIO - else if (btv->audio_chip == TDA9840) { - /* begin of Horrible Hack */ - v.flags|=VIDEO_AUDIO_VOLUME; - v.mode = VIDEO_SOUND_MONO; - v.mode |= VIDEO_SOUND_STEREO; - v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2; - v.volume = 32768; /* fixme */ - v.step = 4096; - } -#endif - - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - - if(copy_from_user(&v,arg, sizeof(v))) - return -EFAULT; - down(&btv->lock); - if(v.flags&VIDEO_AUDIO_MUTE) - audio(btv, AUDIO_MUTE, 1); - /* One audio source per tuner -- huh? */ - if(v.audio<0 || v.audio >= bttv_tvcards[btv->type].audio_inputs) { - up(&btv->lock); - return -EINVAL; - } - /* bt848_muxsel(btv,v.audio); */ - if(!(v.flags&VIDEO_AUDIO_MUTE)) - audio(btv, AUDIO_UNMUTE, 1); - - bttv_call_i2c_clients(btv,cmd,&v); - - if (btv->type == BTTV_TERRATV) { - unsigned int con = 0; - btor(0x180000, BT848_GPIO_OUT_EN); - if (v.mode & VIDEO_SOUND_LANG2) - con = 0x080000; - if (v.mode & VIDEO_SOUND_STEREO) - con = 0x180000; - btaor(con, ~0x180000, BT848_GPIO_DATA); - - } else if (btv->type == BTTV_WINVIEW_601) - winview_setvol(btv,&v); - - btv->audio_dev=v; - up(&btv->lock); - return 0; - } - - case VIDIOCSYNC: - { - DECLARE_WAITQUEUE(wait, current); - - if(copy_from_user((void *)&i,arg,sizeof(int))) - return -EFAULT; - if (i < 0 || i >= gbuffers) - return -EINVAL; - switch (btv->gbuf[i].stat) { - case GBUFFER_UNUSED: - ret = -EINVAL; - break; - case GBUFFER_GRABBING: - add_wait_queue(&btv->capq, &wait); - current->state = TASK_INTERRUPTIBLE; - while(btv->gbuf[i].stat==GBUFFER_GRABBING) { - if (bttv_debug) - printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); - schedule(); - if(signal_pending(current)) { - remove_wait_queue(&btv->capq, &wait); - current->state = TASK_RUNNING; - return -EINTR; - } - } - remove_wait_queue(&btv->capq, &wait); - current->state = TASK_RUNNING; - /* fall throuth */ - case GBUFFER_DONE: - case GBUFFER_ERROR: - ret = (btv->gbuf[i].stat == GBUFFER_ERROR) ? -EIO : 0; - if (bttv_debug) - printk("bttv%d: cap sync: buffer %d, retval %d\n",btv->nr,i,ret); - btv->gbuf[i].stat = GBUFFER_UNUSED; - } - if (btv->needs_restart) { - down(&btv->lock); - bt848_restart(btv); - up(&btv->lock); - } - return ret; - } - - case BTTV_FIELDNR: - if(copy_to_user((void *) arg, (void *) &btv->last_field, - sizeof(btv->last_field))) - return -EFAULT; - break; - - case BTTV_PLLSET: { - struct bttv_pll_info p; - if(!capable(CAP_SYS_ADMIN)) - return -EPERM; - if(copy_from_user(&p , (void *) arg, sizeof(btv->pll))) - return -EFAULT; - down(&btv->lock); - btv->pll.pll_ifreq = p.pll_ifreq; - btv->pll.pll_ofreq = p.pll_ofreq; - btv->pll.pll_crystal = p.pll_crystal; - up(&btv->lock); - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - int ret; - if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) - return -EFAULT; - down(&btv->lock); - ret = vgrab(btv, &vm); - up(&btv->lock); - return ret; - } - - case VIDIOCGMBUF: - { - struct video_mbuf vm; - memset(&vm, 0 , sizeof(vm)); - vm.size=gbufsize*gbuffers; - vm.frames=gbuffers; - for (i = 0; i < gbuffers; i++) - vm.offsets[i]=i*gbufsize; - if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) - return -EFAULT; - return 0; - } - - case VIDIOCGUNIT: - { - struct video_unit vu; - vu.video=btv->video_dev.minor; - vu.vbi=btv->vbi_dev.minor; - if(btv->radio_dev.minor!=-1) - vu.radio=btv->radio_dev.minor; - else - vu.radio=VIDEO_NO_UNIT; - vu.audio=VIDEO_NO_UNIT; - vu.teletext=VIDEO_NO_UNIT; - if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu))) - return -EFAULT; - return 0; - } - - case BTTV_BURST_ON: - { - burst(1); - return 0; - } - - case BTTV_BURST_OFF: - { - burst(0); - return 0; - } - - case BTTV_VERSION: - { - return BTTV_VERSION_CODE; - } - - case BTTV_PICNR: - { - /* return picture;*/ - return 0; - } - -#ifdef HACKING - /* playing with kiobufs and dma-to-userspace */ - case BTTV_JUST_HACKING: - { - DECLARE_WAITQUEUE(wait, current); - struct bttv_just_hacking hack; - struct kiobuf *iobuf; - int err; - - if(copy_from_user((void *) &hack, (void *) arg, sizeof(hack))) - return -EFAULT; - printk("bttv%d: hack: userland args: %dx%d, fmt=%d, buf=%lx, len=%d\n", - btv->nr,hack.width,hack.height,hack.format, - hack.buf,hack.len); - - /* pin down */ - err = alloc_kiovec(1,&iobuf); - if (err) - goto hack_oops; - err = map_user_kiobuf(READ, iobuf, hack.buf, hack.len); - if (err) - goto hack_oops; - err = lock_kiovec(1,&iobuf,1); - if (err) - goto hack_oops; - - /* have a look */ - printk("bttv%d: hack: kiobuf: nr_pages=%d, offset=%d, length=%d, locked=%d\n", - btv->nr,iobuf->nr_pages,iobuf->offset,iobuf->length, - iobuf->locked); - printk("bttv%d: hack: pages (bus addr):",btv->nr); - for (i = 0; i < iobuf->nr_pages; i++) { - printk(" %lx", virt_to_bus(page_address(iobuf->maplist[i]))); - } - printk("\n"); - - /* start capture */ - err = -EINVAL; - if (hack.height * hack.width * 2 * /* fixme: *2 */ - fmtbppx2[palette2fmt[hack.format]&0x0f]/2 > hack.len) - goto hack_oops; - err = vgrab_kiobuf(btv,&hack,iobuf); - if (err) - goto hack_oops; - printk("bttv%d: hack: capture started\n",btv->nr); - - /* wait */ - add_wait_queue(&btv->capq, &wait); - current->state = TASK_INTERRUPTIBLE; - while(btv->gbuf[0].stat==GBUFFER_GRABBING) { - if (bttv_debug) - printk("bttv%d: hack: cap sync: sleep on %d\n",btv->nr,0); - schedule(); -#if 0 - if(signal_pending(current)) { - remove_wait_queue(&btv->capq, &wait); - current->state = TASK_RUNNING; - return -EINTR; - } -#endif - } - remove_wait_queue(&btv->capq, &wait); - current->state = TASK_RUNNING; - printk("bttv%d: hack: capture done\n",btv->nr); - - /* release */ - err = 0; - hack_oops: - free_kiovec(1,&iobuf); - return 0; - } -#endif - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int bttv_init_done(struct video_device *dev) -{ - return 0; -} - -/* - * This maps the vmalloced and reserved fbuffer to user space. - * - * FIXME: - * - PAGE_READONLY should suffice!? - * - remap_page_range is kind of inefficient for page by page remapping. - * But e.g. pte_alloc() does not work in modules ... :-( - */ - -static int do_bttv_mmap(struct bttv *btv, const char *adr, unsigned long size) -{ - unsigned long start=(unsigned long) adr; - unsigned long page,pos; - - if (size>gbuffers*gbufsize) - return -EINVAL; - if (!btv->fbuffer) { - if(fbuffer_alloc(btv)) - return -EINVAL; - } - pos=(unsigned long) btv->fbuffer; - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start+=PAGE_SIZE; - pos+=PAGE_SIZE; - size-=PAGE_SIZE; - } - return 0; -} - -static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size) -{ - struct bttv *btv=(struct bttv *)dev; - int r; - - down(&btv->lock); - r=do_bttv_mmap(btv, adr, size); - up(&btv->lock); - return r; -} - - -static struct video_device bttv_template= -{ - "UNSET", - VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY|VID_TYPE_TELETEXT, - VID_HARDWARE_BT848, - bttv_open, - bttv_close, - bttv_read, - bttv_write, - NULL, - bttv_ioctl, - bttv_mmap, - bttv_init_done, - NULL, - 0, - -1 -}; - - -static long vbi_read(struct video_device *v, char *buf, unsigned long count, - int nonblock) -{ - struct bttv *btv=(struct bttv *)(v-2); - int q,todo; - DECLARE_WAITQUEUE(wait, current); - - todo=count; - while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) - { - if (btv->needs_restart) { - down(&btv->lock); - bt848_restart(btv); - up(&btv->lock); - } - if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) - return -EFAULT; - todo-=q; - buf+=q; - - add_wait_queue(&btv->vbiq, &wait); - current->state = TASK_INTERRUPTIBLE; - if (todo && q==VBIBUF_SIZE-btv->vbip) - { - if(nonblock) - { - remove_wait_queue(&btv->vbiq, &wait); - current->state = TASK_RUNNING; - if(count==todo) - return -EWOULDBLOCK; - return count-todo; - } - schedule(); - if(signal_pending(current)) - { - remove_wait_queue(&btv->vbiq, &wait); - current->state = TASK_RUNNING; - if(todo==count) - return -EINTR; - else - return count-todo; - } - } - remove_wait_queue(&btv->vbiq, &wait); - current->state = TASK_RUNNING; - } - if (todo) - { - if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo)) - return -EFAULT; - btv->vbip+=todo; - } - return count; -} - -static unsigned int vbi_poll(struct video_device *dev, struct file *file, - poll_table *wait) -{ - struct bttv *btv=(struct bttv *)(dev-2); - unsigned int mask = 0; - - poll_wait(file, &btv->vbiq, wait); - - if (btv->vbip < VBIBUF_SIZE) - mask |= (POLLIN | POLLRDNORM); - - return mask; -} - -static int vbi_open(struct video_device *dev, int flags) -{ - struct bttv *btv=(struct bttv *)(dev-2); - unsigned long irq_flags; - - MOD_INC_USE_COUNT; - down(&btv->lock); - if (btv->needs_restart) - bt848_restart(btv); - set_pll(btv); - btv->vbip=VBIBUF_SIZE; - spin_lock_irqsave(&btv->s_lock, irq_flags); - btv->vbi_on = 1; - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - up(&btv->lock); - - return 0; -} - -static void vbi_close(struct video_device *dev) -{ - struct bttv *btv=(struct bttv *)(dev-2); - unsigned long irq_flags; - - spin_lock_irqsave(&btv->s_lock, irq_flags); - btv->vbi_on = 0; - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - MOD_DEC_USE_COUNT; -} - -static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct bttv *btv=(struct bttv *)dev; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability b; - strcpy(b.name,btv->vbi_dev.name); - b.type = ((bttv_tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) | - VID_TYPE_TELETEXT; - b.channels = 0; - b.audios = 0; - b.maxwidth = 0; - b.maxheight = 0; - b.minwidth = 0; - b.minheight = 0; - if(copy_to_user(arg,&b,sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCGFREQ: - case VIDIOCSFREQ: - return bttv_ioctl((struct video_device *)btv,cmd,arg); - case BTTV_VBISIZE: - /* make alevt happy :-) */ - return VBIBUF_SIZE; - default: - return -EINVAL; - } -} - -static struct video_device vbi_template= -{ - "bttv vbi", - VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, - VID_HARDWARE_BT848, - vbi_open, - vbi_close, - vbi_read, - bttv_write, - vbi_poll, - vbi_ioctl, - NULL, /* no mmap yet */ - bttv_init_done, - NULL, - 0, - -1 -}; - - -static int radio_open(struct video_device *dev, int flags) -{ - struct bttv *btv = (struct bttv *)(dev-1); - unsigned long v; - - MOD_INC_USE_COUNT; - down(&btv->lock); - if (btv->user) - goto busy_unlock; - btv->user++; - - btv->radio = 1; - v = 400*16; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,&v); - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); - bt848_muxsel(btv,0); - up(&btv->lock); - - return 0; - - busy_unlock: - up(&btv->lock); - MOD_DEC_USE_COUNT; - return -EBUSY; -} - -static void radio_close(struct video_device *dev) -{ - struct bttv *btv=(struct bttv *)(dev-1); - - down(&btv->lock); - btv->user--; - btv->radio = 0; - up(&btv->lock); - MOD_DEC_USE_COUNT; -} - -static long radio_read(struct video_device *v, char *buf, unsigned long count, int nonblock) -{ - return -EINVAL; -} - -static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct bttv *btv=(struct bttv *)(dev-1); - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability v; - strcpy(v.name,btv->video_dev.name); - v.type = VID_TYPE_TUNER; - v.channels = 1; - v.audios = 1; - /* No we don't do pictures */ - v.maxwidth = 0; - v.maxheight = 0; - v.minwidth = 0; - v.minheight = 0; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - break; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v,arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner||btv->channel) /* Only tuner 0 */ - return -EINVAL; - strcpy(v.name, "Radio"); - v.rangelow=(int)(76*16); /* jp: 76.0MHz - 89.9MHz */ - v.rangehigh=(int)(108*16); /* eu: 87.5MHz - 108.0MHz */ - v.flags= 0; /* XXX */ - v.mode = 0; /* XXX */ - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - /* Only channel 0 has a tuner */ - if(v.tuner!=0 || btv->channel) - return -EINVAL; - /* XXX anything to do ??? */ - return 0; - } - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - bttv_ioctl((struct video_device *)btv,cmd,arg); - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static struct video_device radio_template= -{ - "bttv radio", - VID_TYPE_TUNER, - VID_HARDWARE_BT848, - radio_open, - radio_close, - radio_read, /* just returns -EINVAL */ - bttv_write, /* just returns -EINVAL */ - NULL, /* no poll */ - radio_ioctl, - NULL, /* no mmap */ - bttv_init_done, /* just returns 0 */ - NULL, - 0, - -1 -}; - - -#define TRITON_PCON 0x50 -#define TRITON_BUS_CONCURRENCY (1<<0) -#define TRITON_STREAMING (1<<1) -#define TRITON_WRITE_BURST (1<<2) -#define TRITON_PEER_CONCURRENCY (1<<3) - - -static void __devinit handle_chipset(void) -{ - struct pci_dev *dev = NULL; - - /* Just in case some nut set this to something dangerous */ - if (triton1) - triton1=BT848_INT_ETBF; - - while ((dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, dev))) - { - /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */ - printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n"); - } - - while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82441, dev))) - { - unsigned char b; - pci_read_config_byte(dev, 0x53, &b); - DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, ")); - DEBUG(printk("bufcon=0x%02x\n",b)); - } - - while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, dev))) - { - printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n"); - triton1=BT848_INT_ETBF; - } -} - - -static void bt848_set_risc_jmps(struct bttv *btv, int flags) -{ - if (-1 == flags) { - /* defaults */ - flags = 0; - if (btv->scr_on) - flags |= 0x03; - if (btv->vbi_on) - flags |= 0x0c; - } - - if (bttv_debug > 1) - printk("bttv%d: set_risc_jmp %08lx:", - btv->nr,virt_to_bus(btv->risc_jmp)); - - /* Sync to start of odd field */ - btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC - |BT848_FIFO_STATUS_VRE); - btv->risc_jmp[1]=cpu_to_le32(0); - - /* Jump to odd vbi sub */ - btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20)); - if (flags&8) { - if (bttv_debug > 1) - printk(" ev=%08lx",virt_to_bus(btv->vbi_odd)); - btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd)); - } else { - if (bttv_debug > 1) - printk(" -----------"); - btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4)); - } - - /* Jump to odd sub */ - btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20)); - if (0 != btv->risc_cap_odd) { - if (bttv_debug > 1) - printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd); - flags |= 3; - btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd); - } else if (flags&2) { - if (bttv_debug > 1) - printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd)); - btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_scr_odd)); - } else { - if (bttv_debug > 1) - printk(" -----------"); - btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6)); - } - - - /* Sync to start of even field */ - btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC - |BT848_FIFO_STATUS_VRO); - btv->risc_jmp[7]=cpu_to_le32(0); - - /* Jump to even vbi sub */ - btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP); - if (flags&4) { - if (bttv_debug > 1) - printk(" ov=%08lx",virt_to_bus(btv->vbi_even)); - btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even)); - } else { - if (bttv_debug > 1) - printk(" -----------"); - btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); - } - - /* Jump to even sub */ - btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20)); - if (0 != btv->risc_cap_even) { - if (bttv_debug > 1) - printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even); - flags |= 3; - btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even); - } else if (flags&1) { - if (bttv_debug > 1) - printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even)); - btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_scr_even)); - } else { - if (bttv_debug > 1) - printk(" -----------"); - btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12)); - } - - if (btv->gq_start) { - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); - } else { - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); - } - btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp)); - - /* enable cpaturing and DMA */ - if (bttv_debug > 1) - printk(" flags=0x%x dma=%s\n", - flags,(flags&0x0f) ? "on" : "off"); - btaor(flags, ~0x0f, BT848_CAP_CTL); - if (flags&0x0f) - bt848_dma(btv, 3); - else - bt848_dma(btv, 0); -} - -static int __devinit init_video_dev(struct bttv *btv) -{ - memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template)); - memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); - memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template)); - - bttv_idcard(btv); - audio(btv, AUDIO_MUTE, 1); - - if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0) - return -1; - if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI)<0) - { - video_unregister_device(&btv->video_dev); - return -1; - } - if (radio[btv->nr]) - { - if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) - { - video_unregister_device(&btv->vbi_dev); - video_unregister_device(&btv->video_dev); - return -1; - } - } - return 1; -} - -static int __devinit init_bt848(struct bttv *btv) -{ - int j; - unsigned long irq_flags; - - btv->user=0; - init_MUTEX(&btv->lock); - - /* dump current state of the gpio registers before changing them, - * might help to make a new card work */ - if (bttv_verbose >= 2) - printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n", - btv->nr, - btread(BT848_GPIO_OUT_EN), - btread(BT848_GPIO_DATA), - btread(BT848_GPIO_REG_INP)); - - /* reset the bt848 */ - btwrite(0, BT848_SRESET); - DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem)); - - /* not registered yet */ - btv->video_dev.minor = -1; - btv->radio_dev.minor = -1; - btv->vbi_dev.minor = -1; - - /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */ - btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */ - btv->win.interlace=1; - btv->win.x=0; - btv->win.y=0; - btv->win.width=768; /* 640 */ - btv->win.height=576; /* 480 */ - btv->win.bpp=2; - btv->win.depth=16; - btv->win.color_fmt=BT848_COLOR_FMT_RGB16; - btv->win.bpl=1024*btv->win.bpp; - btv->win.swidth=1024; - btv->win.sheight=768; - btv->win.vidadr=0; - btv->vbi_on=0; - btv->scr_on=0; - - btv->risc_scr_odd=0; - btv->risc_scr_even=0; - btv->risc_cap_odd=0; - btv->risc_cap_even=0; - btv->risc_jmp=0; - btv->vbibuf=0; - btv->field=btv->last_field=0; - - btv->errors=0; - btv->needs_restart=0; - - /* i2c */ - btv->tuner_type=-1; - init_bttv_i2c(btv); - - if (!(btv->risc_scr_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) - return -1; - if (!(btv->risc_scr_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) - return -1; - if (!(btv->risc_jmp =(unsigned int *) kmalloc(2048, GFP_KERNEL))) - return -1; - btv->vbi_odd=btv->risc_jmp+16; - btv->vbi_even=btv->vbi_odd+256; - btv->bus_vbi_odd=virt_to_bus(btv->risc_jmp+12); - btv->bus_vbi_even=virt_to_bus(btv->risc_jmp+6); - - btwrite(virt_to_bus(btv->risc_jmp+2), BT848_RISC_STRT_ADD); - btv->vbibuf=(unsigned char *) vmalloc_32(VBIBUF_SIZE); - if (!btv->vbibuf) - return -1; - if (!(btv->gbuf = kmalloc(sizeof(struct bttv_gbuf)*gbuffers,GFP_KERNEL))) - return -1; - for (j = 0; j < gbuffers; j++) { - if (!(btv->gbuf[j].risc = kmalloc(16384,GFP_KERNEL))) - return -1; - } - - memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random - memory to the user */ - - btv->fbuffer=NULL; - - bt848_muxsel(btv, 1); - bt848_set_winsize(btv); - -/* btwrite(0, BT848_TDEC); */ - btwrite(0x10, BT848_COLOR_CTL); - btwrite(0x00, BT848_CAP_CTL); - /* set planar and packed mode trigger points and */ - /* set rising edge of inverted GPINTR pin as irq trigger */ - btwrite(BT848_GPIO_DMA_CTL_PKTP_32| - BT848_GPIO_DMA_CTL_PLTP1_16| - BT848_GPIO_DMA_CTL_PLTP23_16| - BT848_GPIO_DMA_CTL_GPINTC| - BT848_GPIO_DMA_CTL_GPINTI, - BT848_GPIO_DMA_CTL); - - /* select direct input */ - btwrite(0x00, BT848_GPIO_REG_INP); - - btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, - BT848_IFORM); - - btwrite(0xd8, BT848_CONTRAST_LO); - bt848_bright(btv, 0x10); - - btwrite(0x20, BT848_E_VSCALE_HI); - btwrite(0x20, BT848_O_VSCALE_HI); - btwrite(/*BT848_ADC_SYNC_T|*/ - BT848_ADC_RESERVED|BT848_ADC_CRUSH, BT848_ADC); - - btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL); - btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL); - - btv->picture.colour=254<<7; - btv->picture.brightness=128<<8; - btv->picture.hue=128<<8; - btv->picture.contrast=0xd8<<7; - - btwrite(0x00, BT848_E_SCLOOP); - btwrite(0x00, BT848_O_SCLOOP); - - /* clear interrupt status */ - btwrite(0xfffffUL, BT848_INT_STAT); - - /* set interrupt mask */ - btwrite(btv->triton1| - /*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR| - BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/ - (fieldnr ? BT848_INT_VSYNC : 0)| - BT848_INT_GPINT| - BT848_INT_SCERR| - BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| - BT848_INT_FMTCHG|BT848_INT_HLOCK, - BT848_INT_MASK); - - make_vbitab(btv); - spin_lock_irqsave(&btv->s_lock, irq_flags); - bt848_set_risc_jmps(btv,-1); - spin_unlock_irqrestore(&btv->s_lock, irq_flags); - - /* - * Now add the template and register the device unit. - */ - init_video_dev(btv); - - return 0; -} - -static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) -{ - u32 stat,astat; - u32 dstat; - int count,i; - struct bttv *btv; - - btv=(struct bttv *)dev_id; - count=0; - while (1) - { - /* get/clear interrupt status bits */ - stat=btread(BT848_INT_STAT); - astat=stat&btread(BT848_INT_MASK); - if (!astat) - return; - btwrite(astat,BT848_INT_STAT); - IDEBUG(printk ("bttv%d: astat=%08x\n", btv->nr, astat)); - IDEBUG(printk ("bttv%d: stat=%08x\n", btv->nr, stat)); - - /* get device status bits */ - dstat=btread(BT848_DSTATUS); - - if (astat&BT848_INT_GPINT) { - IDEBUG(printk ("bttv%d: IRQ_GPINT\n", btv->nr)); - wake_up_interruptible(&btv->gpioq); - } - - if (astat&BT848_INT_FMTCHG) - { - IDEBUG(printk ("bttv%d: IRQ_FMTCHG\n", btv->nr)); - /*btv->win.norm&= - (dstat&BT848_DSTATUS_NUML) ? (~1) : (~0); */ - } - if (astat&BT848_INT_VPRES) - { - IDEBUG(printk ("bttv%d: IRQ_VPRES\n", btv->nr)); - } - if (astat&BT848_INT_VSYNC) - { - IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr)); - btv->field++; - } - if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) { - if (bttv_verbose) - printk("bttv%d: irq:%s%s risc_count=%08x\n", - btv->nr, - (astat&BT848_INT_SCERR) ? " SCERR" : "", - (astat&BT848_INT_OCERR) ? " OCERR" : "", - btread(BT848_RISC_COUNT)); - btv->errors++; - if (btv->errors < BTTV_ERRORS) { - spin_lock(&btv->s_lock); - btand(~15, BT848_GPIO_DMA_CTL); - btwrite(virt_to_bus(btv->risc_jmp+2), - BT848_RISC_STRT_ADD); - bt848_set_geo(btv,0); - bt848_set_risc_jmps(btv,-1); - spin_unlock(&btv->s_lock); - } else { - if (bttv_verbose) - printk("bttv%d: aiee: error loops\n",btv->nr); - /* cancel all outstanding grab requests */ - spin_lock(&btv->s_lock); - btv->gq_in = 0; - btv->gq_out = 0; - btv->gq_grab = -1; - for (i = 0; i < gbuffers; i++) - if (btv->gbuf[i].stat == GBUFFER_GRABBING) - btv->gbuf[i].stat = GBUFFER_ERROR; - /* disable DMA */ - btv->risc_cap_odd = 0; - btv->risc_cap_even = 0; - bt848_set_risc_jmps(btv,0); - btv->needs_restart = 1; - spin_unlock(&btv->s_lock); - - wake_up_interruptible(&btv->vbiq); - wake_up_interruptible(&btv->capq); - } - } - if (astat&BT848_INT_RISCI) - { - if (bttv_debug > 1) - printk("bttv%d: IRQ_RISCI\n",btv->nr); - - /* captured VBI frame */ - if (stat&(1<<28)) - { - btv->vbip=0; - /* inc vbi frame count for detecting drops */ - (*(u32 *)&(btv->vbibuf[VBIBUF_SIZE - 4]))++; - wake_up_interruptible(&btv->vbiq); - } - - /* captured full frame */ - if (stat&(2<<28) && btv->gq_grab != -1) - { - btv->last_field=btv->field; - if (bttv_debug) - printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab); - do_gettimeofday(&btv->gbuf[btv->gq_grab].tv); - spin_lock(&btv->s_lock); - btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE; - btv->gq_grab = -1; - if (btv->gq_in != btv->gq_out) - { - btv->gq_grab = btv->gqueue[btv->gq_out++]; - btv->gq_out = btv->gq_out % MAX_GBUFFERS; - if (bttv_debug) - printk("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab); - btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; - btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; - bt848_set_risc_jmps(btv,-1); - bt848_set_geo(btv,0); - btwrite(BT848_COLOR_CTL_GAMMA, - BT848_COLOR_CTL); - } else { - btv->risc_cap_odd = 0; - btv->risc_cap_even = 0; - bt848_set_risc_jmps(btv,-1); - bt848_set_geo(btv,0); - btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA, - BT848_COLOR_CTL); - } - spin_unlock(&btv->s_lock); - wake_up_interruptible(&btv->capq); - break; - } - if (stat&(8<<28)) - { - spin_lock(&btv->s_lock); - btv->gq_start = 0; - btv->gq_grab = btv->gqueue[btv->gq_out++]; - btv->gq_out = btv->gq_out % MAX_GBUFFERS; - if (bttv_debug) - printk("bttv%d: cap irq: capture %d [start]\n",btv->nr,btv->gq_grab); - btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; - btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; - bt848_set_risc_jmps(btv,-1); - bt848_set_geo(btv,0); - btwrite(BT848_COLOR_CTL_GAMMA, - BT848_COLOR_CTL); - spin_unlock(&btv->s_lock); - } - } - if (astat&BT848_INT_OCERR) - { - IDEBUG(printk ("bttv%d: IRQ_OCERR\n", btv->nr)); - } - if (astat&BT848_INT_PABORT) - { - IDEBUG(printk ("bttv%d: IRQ_PABORT\n", btv->nr)); - } - if (astat&BT848_INT_RIPERR) - { - IDEBUG(printk ("bttv%d: IRQ_RIPERR\n", btv->nr)); - } - if (astat&BT848_INT_PPERR) - { - IDEBUG(printk ("bttv%d: IRQ_PPERR\n", btv->nr)); - } - if (astat&BT848_INT_FDSR) - { - IDEBUG(printk ("bttv%d: IRQ_FDSR\n", btv->nr)); - } - if (astat&BT848_INT_FTRGT) - { - IDEBUG(printk ("bttv%d: IRQ_FTRGT\n", btv->nr)); - } - if (astat&BT848_INT_FBUS) - { - IDEBUG(printk ("bttv%d: IRQ_FBUS\n", btv->nr)); - } - if (astat&BT848_INT_HLOCK) - { - if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio)) - audio(btv, AUDIO_ON,0); - else - audio(btv, AUDIO_OFF,0); - } - - if (astat&BT848_INT_I2CDONE) - { - IDEBUG(printk ("bttv%d: IRQ_I2CDONE\n", btv->nr)); - } - count++; - if (count > 10) - printk (KERN_WARNING "bttv%d: irq loop %d\n", - btv->nr,count); - if (count > 20) - { - btwrite(0, BT848_INT_MASK); - printk(KERN_ERR - "bttv%d: IRQ lockup, cleared int mask\n", btv->nr); - } - } -} - - - -/* - * Scan for a Bt848 card, request the irq and map the io memory - */ - -static void __devinit bttv_remove(struct pci_dev *pci_dev) -{ - u8 command; - int j; - struct bttv *btv = PCI_GET_DRIVER_DATA(pci_dev); - - /* unregister i2c_bus */ - if (0 == btv->i2c_ok) - i2c_bit_del_bus(&btv->i2c_adap); - - /* turn off all capturing, DMA and IRQs */ - btand(~15, BT848_GPIO_DMA_CTL); - - /* first disable interrupts before unmapping the memory! */ - btwrite(0, BT848_INT_MASK); - btwrite(~0x0UL,BT848_INT_STAT); - btwrite(0x0, BT848_GPIO_OUT_EN); - - /* disable PCI bus-mastering */ - pci_read_config_byte(btv->dev, PCI_COMMAND, &command); - /* Should this be &=~ ?? */ - command&=~PCI_COMMAND_MASTER; - pci_write_config_byte(btv->dev, PCI_COMMAND, command); - - /* unmap and free memory */ - for (j = 0; j < gbuffers; j++) - if (btv->gbuf[j].risc) - kfree(btv->gbuf[j].risc); - if (btv->gbuf) - kfree((void *) btv->gbuf); - - if (btv->risc_scr_odd) - kfree((void *) btv->risc_scr_odd); - - if (btv->risc_scr_even) - kfree((void *) btv->risc_scr_even); - - DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp)); - if (btv->risc_jmp) - kfree((void *) btv->risc_jmp); - - DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf)); - if (btv->vbibuf) - vfree((void *) btv->vbibuf); - - free_irq(btv->irq,btv); - DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem)); - if (btv->bt848_mem) - iounmap(btv->bt848_mem); - - if(btv->video_dev.minor!=-1) - video_unregister_device(&btv->video_dev); - if(btv->vbi_dev.minor!=-1) - video_unregister_device(&btv->vbi_dev); - if (radio[btv->nr] && btv->radio_dev.minor != -1) - video_unregister_device(&btv->radio_dev); - - release_mem_region(btv->bt848_adr, - pci_resource_len(btv->dev,0)); - /* wake up any waiting processes - because shutdown flag is set, no new processes (in this queue) - are expected - */ - btv->shutdown=1; - wake_up(&btv->gpioq); - - return; -} - - -static int __devinit bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) -{ - int result; - unsigned char command; - struct bttv *btv; -#if defined(__powerpc__) - unsigned int cmd; -#endif - - printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); - - btv=&bttvs[bttv_num]; - btv->dev=dev; - btv->nr = bttv_num; - btv->bt848_mem=NULL; - btv->vbibuf=NULL; - btv->risc_jmp=NULL; - btv->vbi_odd=NULL; - btv->vbi_even=NULL; - init_waitqueue_head(&btv->vbiq); - init_waitqueue_head(&btv->capq); - btv->vbip=VBIBUF_SIZE; - btv->s_lock = SPIN_LOCK_UNLOCKED; - init_waitqueue_head(&btv->gpioq); - btv->shutdown=0; - - btv->id=dev->device; - btv->irq=dev->irq; - btv->bt848_adr=pci_resource_start(dev,0); - if (pci_enable_device(dev)) - return -EIO; - if (!request_mem_region(pci_resource_start(dev,0), - pci_resource_len(dev,0), - "bttv")) { - return -EBUSY; - } - if (btv->id >= 878) - btv->i2c_command = 0x83; - else - btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA); - - pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); - printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ", - bttv_num,btv->id, btv->revision); - printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn); - printk("irq: %d, ",btv->irq); - printk("memory: 0x%lx.\n", btv->bt848_adr); - -#if defined(__powerpc__) - /* on OpenFirmware machines (PowerMac at least), PCI memory cycle */ - /* response on cards with no firmware is not enabled by OF */ - pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); - pci_write_config_dword(dev, PCI_COMMAND, cmd); -#endif - -#ifdef __sparc__ - btv->bt848_mem=(unsigned char *)btv->bt848_adr; -#else - btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000); -#endif - - /* clear interrupt mask */ - btwrite(0, BT848_INT_MASK); - - result = request_irq(btv->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv); - if (result==-EINVAL) - { - printk(KERN_ERR "bttv%d: Bad irq number or handler\n", - bttv_num); - goto fail; - } - if (result==-EBUSY) - { - printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq); - goto fail; - } - if (result < 0) - goto fail; - - pci_set_master(dev); - - btv->triton1=triton1 ? BT848_INT_ETBF : 0; - if (triton1 && btv->id >= 878) - { - btv->triton1 = 0; - printk("bttv: Enabling 430FX compatibilty for bt878\n"); - pci_read_config_byte(dev, BT878_DEVCTRL, &command); - command|=BT878_EN_TBFX; - pci_write_config_byte(dev, BT878_DEVCTRL, command); - pci_read_config_byte(dev, BT878_DEVCTRL, &command); - if (!(command&BT878_EN_TBFX)) - { - printk("bttv: 430FX compatibility could not be enabled\n"); - free_irq(btv->irq,btv); - result = -1; - goto fail; - } - } - - PCI_SET_DRIVER_DATA(dev,btv); - - if(init_bt848(btv) < 0) { - bttv_remove(dev); - return -EIO; - } - bttv_num++; - - return 0; - - fail: - release_mem_region(pci_resource_start(btv->dev,0), - pci_resource_len(btv->dev,0)); - return result; -} - -static struct pci_device_id bttv_pci_tbl[] __devinitdata = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); - -static struct pci_driver bttv_pci_driver = { - name: "bttv", - id_table: bttv_pci_tbl, - probe: bttv_probe, - remove: bttv_remove, -}; - -int bttv_init_module(void) -{ - bttv_num = 0; - - printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", - (BTTV_VERSION_CODE >> 16) & 0xff, - (BTTV_VERSION_CODE >> 8) & 0xff, - BTTV_VERSION_CODE & 0xff); - if (gbuffers < 2 || gbuffers > MAX_GBUFFERS) - gbuffers = 2; - if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) - gbufsize = BTTV_MAX_FBUF; - if (bttv_verbose) - printk(KERN_INFO "bttv: using %d buffers with %dk (%dk total) for capture\n", - gbuffers,gbufsize/1024,gbuffers*gbufsize/1024); - - handle_chipset(); - - return pci_module_init(&bttv_pci_driver); -} - -void bttv_cleanup_module(void) -{ - pci_unregister_driver(&bttv_pci_driver); - return; -} - -module_init(bttv_init_module); -module_exit(bttv_cleanup_module); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/bttv-if.c b/drivers/char/bttv-if.c deleted file mode 100644 index a58e441db..000000000 --- a/drivers/char/bttv-if.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - bttv-if.c -- interfaces to other kernel modules - all the i2c code is here - also the gpio interface exported by bttv (used by lirc) - - - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999,2000 Gerd Knorr - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#define __NO_VERSION__ 1 - -#include -#include -#include - -#include - -#include "bttv.h" -#include "tuner.h" - - -EXPORT_SYMBOL(bttv_get_cardinfo); -EXPORT_SYMBOL(bttv_get_id); -EXPORT_SYMBOL(bttv_gpio_enable); -EXPORT_SYMBOL(bttv_read_gpio); -EXPORT_SYMBOL(bttv_write_gpio); -EXPORT_SYMBOL(bttv_get_gpio_queue); - -/* ----------------------------------------------------------------------- */ -/* Exported functions - for other modules which want to access the */ -/* gpio ports (IR for example) */ -/* see bttv.h for comments */ - -int bttv_get_cardinfo(unsigned int card, int *type, int *cardid) -{ - if (card >= bttv_num) { - return -1; - } - *type = bttvs[card].type; - *cardid = bttvs[card].cardid; - return 0; -} - -int bttv_get_id(unsigned int card) -{ - printk("bttv_get_id is obsolete, use bttv_get_cardinfo instead\n"); - if (card >= bttv_num) { - return -1; - } - return bttvs[card].type; -} - -int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return -EINVAL; - } - - btv = &bttvs[card]; - btaor(data, ~mask, BT848_GPIO_OUT_EN); - return 0; -} - -int bttv_read_gpio(unsigned int card, unsigned long *data) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return -EINVAL; - } - - btv = &bttvs[card]; - - if(btv->shutdown) { - return -ENODEV; - } - -/* prior setting BT848_GPIO_REG_INP is (probably) not needed - because we set direct input on init */ - *data = btread(BT848_GPIO_DATA); - return 0; -} - -int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return -EINVAL; - } - - btv = &bttvs[card]; - -/* prior setting BT848_GPIO_REG_INP is (probably) not needed - because direct input is set on init */ - btaor(data & mask, ~mask, BT848_GPIO_DATA); - return 0; -} - -wait_queue_head_t* bttv_get_gpio_queue(unsigned int card) -{ - struct bttv *btv; - - if (card >= bttv_num) { - return NULL; - } - - btv = &bttvs[card]; - if (bttvs[card].shutdown) { - return NULL; - } - return &btv->gpioq; -} - - -/* ----------------------------------------------------------------------- */ -/* I2C functions */ - -void bttv_bit_setscl(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x02; - else - btv->i2c_state &= ~0x02; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -void bttv_bit_setsda(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x01; - else - btv->i2c_state &= ~0x01; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -static int bttv_bit_getscl(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x02 ? 1 : 0; - return state; -} - -static int bttv_bit_getsda(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x01; - return state; -} - -static void bttv_inc_use(struct i2c_adapter *adap) -{ - MOD_INC_USE_COUNT; -} - -static void bttv_dec_use(struct i2c_adapter *adap) -{ - MOD_DEC_USE_COUNT; -} - -static int attach_inform(struct i2c_client *client) -{ - struct bttv *btv = (struct bttv*)client->adapter->data; - int i; - - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] == NULL || - btv->i2c_clients[i]->driver->id == client->driver->id) { - btv->i2c_clients[i] = client; - break; - } - } - if (btv->tuner_type != -1) - bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - if (bttv_verbose) - printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name); - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct bttv *btv = (struct bttv*)client->adapter->data; - int i; - - if (bttv_verbose) - printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name); - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (NULL != btv->i2c_clients[i] && - btv->i2c_clients[i]->driver->id == client->driver->id) { - btv->i2c_clients[i] = NULL; - break; - } - } - return 0; -} - -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) -{ - int i; - - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (NULL == btv->i2c_clients[i]) - continue; - if (NULL == btv->i2c_clients[i]->driver->command) - continue; - btv->i2c_clients[i]->driver->command( - btv->i2c_clients[i],cmd,arg); - } -} - -struct i2c_algo_bit_data bttv_i2c_algo_template = { - NULL, - bttv_bit_setsda, - bttv_bit_setscl, - bttv_bit_getsda, - bttv_bit_getscl, - 10, 10, 100, -}; - -struct i2c_adapter bttv_i2c_adap_template = { - "bt848", - I2C_HW_B_BT848, - NULL, - NULL, - bttv_inc_use, - bttv_dec_use, - attach_inform, - detach_inform, - NULL, -}; - -struct i2c_client bttv_i2c_client_template = { - "bttv internal", - -1, - 0, - 0, - NULL, - NULL -}; - - -/* read I2C */ -int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) -{ - unsigned char buffer = 0; - - if (0 != btv->i2c_ok) - return -1; - if (bttv_verbose && NULL != probe_for) - printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", - btv->nr,probe_for,addr); - btv->i2c_client.addr = addr >> 1; - if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { - if (NULL != probe_for) { - if (bttv_verbose) - printk("not found\n"); - } else - printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", - btv->nr,addr); - return -1; - } - if (bttv_verbose && NULL != probe_for) - printk("found\n"); - return buffer; -} - -/* write I2C */ -int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both) -{ - unsigned char buffer[2]; - int bytes = both ? 2 : 1; - - if (0 != btv->i2c_ok) - return -1; - btv->i2c_client.addr = addr >> 1; - buffer[0] = b1; - buffer[1] = b2; - if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) - return -1; - return 0; -} - -/* read EEPROM content */ -void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) -{ - int i; - - if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) { - printk(KERN_WARNING "bttv: readee error\n"); - return; - } - btv->i2c_client.addr = addr >> 1; - for (i=0; i<256; i+=16) { - if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) { - printk(KERN_WARNING "bttv: readee error\n"); - break; - } - } -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h deleted file mode 100644 index 6b35d23e5..000000000 --- a/drivers/char/bttv.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _BTTV_H_ -#define _BTTV_H_ - -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,38) - -#ifndef PCI_GET_DRIVER_DATA -# define PCI_GET_DRIVER_DATA(pdev) ((pdev)->driver_data) -# define PCI_SET_DRIVER_DATA(pdev,data) (((pdev)->driver_data) = (data)) -#endif /* PCI_GET_DRIVER_DATA */ - -#include -#include -#include -#include -#include - -#include "audiochip.h" -#include "bt848.h" - -#ifdef __KERNEL__ - -/* fwd decl */ -struct bttv; - - -/* ---------------------------------------------------------- */ -/* exported by bttv-cards.c */ - -#define BTTV_UNKNOWN 0x00 -#define BTTV_MIRO 0x01 -#define BTTV_HAUPPAUGE 0x02 -#define BTTV_STB 0x03 -#define BTTV_INTEL 0x04 -#define BTTV_DIAMOND 0x05 -#define BTTV_AVERMEDIA 0x06 -#define BTTV_MATRIX_VISION 0x07 -#define BTTV_FLYVIDEO 0x08 -#define BTTV_TURBOTV 0x09 -#define BTTV_HAUPPAUGE878 0x0a -#define BTTV_MIROPRO 0x0b -#define BTTV_ADSTECH_TV 0x0c -#define BTTV_AVERMEDIA98 0x0d -#define BTTV_VHX 0x0e -#define BTTV_ZOLTRIX 0x0f -#define BTTV_PIXVIEWPLAYTV 0x10 -#define BTTV_WINVIEW_601 0x11 -#define BTTV_AVEC_INTERCAP 0x12 -#define BTTV_LIFE_FLYKIT 0x13 -#define BTTV_CEI_RAFFLES 0x14 -#define BTTV_CONFERENCETV 0x15 -#define BTTV_PHOEBE_TVMAS 0x16 -#define BTTV_MODTEC_205 0x17 -#define BTTV_MAGICTVIEW061 0x18 -#define BTTV_VOBIS_BOOSTAR 0x19 -#define BTTV_HAUPPAUG_WCAM 0x1a -#define BTTV_MAXI 0x1b -#define BTTV_TERRATV 0x1c -#define BTTV_PXC200 0x1d -#define BTTV_FLYVIDEO_98 0x1e -#define BTTV_IPROTV 0x1f -#define BTTV_INTEL_C_S_PCI 0x20 -#define BTTV_TERRATVALUE 0x21 -#define BTTV_WINFAST2000 0x22 -#define BTTV_CHRONOS_VS2 0x23 -#define BTTV_TYPHOON_TVIEW 0x24 -#define BTTV_PXELVWPLTVPRO 0x25 -#define BTTV_MAGICTVIEW063 0x26 -#define BTTV_PINNACLERAVE 0x27 -#define BTTV_STB2 0x28 -#define BTTV_AVPHONE98 0x29 -#define BTTV_PV951 0x2a -#define BTTV_ONAIR_TV 0x2b -#define BTTV_SIGMA_TVII_FM 0x2c -#define BTTV_MATRIX_VISION2 0x2d -#define BTTV_ZOLTRIX_GENIE 0x2e -#define BTTV_TERRATVRADIO 0x2f -#define BTTV_DYNALINK 0x30 - -struct tvcard -{ - char *name; - int video_inputs; - int audio_inputs; - int tuner; - int svhs; - u32 gpiomask; - u32 muxsel[8]; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ - u32 gpiomask2; /* GPIO MUX mask */ - - /* look for these i2c audio chips */ - int msp34xx:1; - int tda8425:1; - int tda9840:1; - int tda985x:1; - int tea63xx:1; - int tea64xx:1; - int tda7432:1; - int tda9875:1; - - /* other settings */ - int pll; -#define PLL_NONE 0 -#define PLL_28 1 -#define PLL_35 2 - - int tuner_type; -}; - -extern struct tvcard bttv_tvcards[]; -extern const int bttv_num_tvcards; - -/* identification / initialization of the card */ -extern void bttv_idcard(struct bttv *btv); - -/* card-specific funtions */ -extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); -extern void winview_setvol(struct bttv *btv, struct video_audio *v); - -/* ---------------------------------------------------------- */ -/* exported by bttv-if.c */ -/* interface for gpio access by other modules */ - -/* returns card type + card ID (for bt878-based ones) - for possible values see lines below beginning with #define BTTV_UNKNOWN - returns negative value if error ocurred -*/ -extern int bttv_get_cardinfo(unsigned int card, int *type, int *cardid); - -/* obsolete, use bttv_get_cardinfo instead */ -extern int bttv_get_id(unsigned int card); - -/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: - data | (current_GPOE_value & ~mask) - returns negative value if error ocurred -*/ -extern int bttv_gpio_enable(unsigned int card, - unsigned long mask, unsigned long data); - -/* fills data with GPDATA register contents - returns negative value if error ocurred -*/ -extern int bttv_read_gpio(unsigned int card, unsigned long *data); - -/* sets GPDATA register to new value: - (data & mask) | (current_GPDATA_value & ~mask) - returns negative value if error ocurred -*/ -extern int bttv_write_gpio(unsigned int card, - unsigned long mask, unsigned long data); - -/* returns pointer to task queue which can be used as parameter to - interruptible_sleep_on - in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated - (wake_up_interruptible) and following call to the function bttv_read_gpio - should return new value of GPDATA, - returns NULL value if error ocurred or queue is not available - WARNING: because there is no buffer for GPIO data, one MUST - process data ASAP -*/ -extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); - -/* i2c */ -struct i2c_algo_bit_data bttv_i2c_algo_template; -struct i2c_adapter bttv_i2c_adap_template; -struct i2c_client bttv_i2c_client_template; -void bttv_bit_setscl(void *data, int state); -void bttv_bit_setsda(void *data, int state); -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); -int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); -int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both); -void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); - - -/* ---------------------------------------------------------- */ -/* bttv-driver.c */ - -/* insmod options */ -extern unsigned int bttv_verbose; -extern unsigned int bttv_debug; - -/* Anybody who uses more than four? */ -#define BTTV_MAX 4 -extern int bttv_num; /* number of Bt848s in use */ -extern struct bttv bttvs[BTTV_MAX]; - - -#ifndef O_NONCAP -#define O_NONCAP O_TRUNC -#endif - -#define MAX_GBUFFERS 64 -#define RISCMEM_LEN (32744*2) -#define VBI_MAXLINES 16 -#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) - -#define BTTV_MAX_FBUF 0x208000 -#define I2C_CLIENTS_MAX 8 - -struct bttv_window -{ - int x, y; - ushort width, height; - ushort bpp, bpl; - ushort swidth, sheight; - unsigned long vidadr; - ushort freq; - int norm; - int interlace; - int color_fmt; - ushort depth; -}; - -struct bttv_pll_info { - unsigned int pll_ifreq; /* PLL input frequency */ - unsigned int pll_ofreq; /* PLL output frequency */ - unsigned int pll_crystal; /* Crystal used for input */ - unsigned int pll_current; /* Currently programmed ofreq */ -}; - -struct bttv_gbuf { - int stat; -#define GBUFFER_UNUSED 0 -#define GBUFFER_GRABBING 1 -#define GBUFFER_DONE 2 -#define GBUFFER_ERROR 3 - struct timeval tv; - - u16 width; - u16 height; - u16 fmt; - - u32 *risc; - unsigned long ro; - unsigned long re; -}; - -struct bttv { - struct video_device video_dev; - struct video_device radio_dev; - struct video_device vbi_dev; - struct video_picture picture; /* Current picture params */ - struct video_audio audio_dev; /* Current audio params */ - - spinlock_t s_lock; - struct semaphore lock; - int user; - int capuser; - - /* i2c */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - int i2c_state, i2c_ok; - struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; - - int tuner_type; - int channel; - - unsigned int nr; - unsigned short id; - struct pci_dev *dev; - unsigned int irq; /* IRQ used by Bt848 card */ - unsigned char revision; - unsigned long bt848_adr; /* bus address of IO mem returned by PCI BIOS */ - unsigned char *bt848_mem; /* pointer to mapped IO memory */ - unsigned long busriscmem; - u32 *riscmem; - - unsigned char *vbibuf; - struct bttv_window win; - int fb_color_ctl; - int type; /* card type */ - int cardid; - int audio; /* audio mode */ - int audio_chip; /* set to one of the chips supported by bttv.c */ - int radio; - - u32 *risc_jmp; - u32 *vbi_odd; - u32 *vbi_even; - u32 bus_vbi_even; - u32 bus_vbi_odd; - wait_queue_head_t vbiq; - wait_queue_head_t capq; - int vbip; - - u32 *risc_scr_odd; - u32 *risc_scr_even; - u32 risc_cap_odd; - u32 risc_cap_even; - int scr_on; - int vbi_on; - struct video_clip *cliprecs; - - struct bttv_gbuf *gbuf; - int gqueue[MAX_GBUFFERS]; - int gq_in,gq_out,gq_grab,gq_start; - char *fbuffer; - - struct bttv_pll_info pll; - unsigned int Fsc; - unsigned int field; - unsigned int last_field; /* number of last grabbed field */ - int i2c_command; - int triton1; - - int errors; - int needs_restart; - - wait_queue_head_t gpioq; - int shutdown; -}; -#endif - -#if defined(__powerpc__) /* big-endian */ -extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) -{ - __asm__ __volatile__ ("stwbrx %1,0,%2" : \ - "=m" (*addr) : "r" (val), "r" (addr)); - __asm__ __volatile__ ("eieio" : : : "memory"); -} - -#define btwrite(dat,adr) io_st_le32((unsigned *)(btv->bt848_mem+(adr)),(dat)) -#define btread(adr) ld_le32((unsigned *)(btv->bt848_mem+(adr))) -#else -#define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mem+(adr))) -#define btread(adr) readl(btv->bt848_mem+(adr)) -#endif - -#define btand(dat,adr) btwrite((dat) & btread(adr), adr) -#define btor(dat,adr) btwrite((dat) | btread(adr), adr) -#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) - -/* bttv ioctls */ - -#define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]) -#define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]) -#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int) -#define BTTV_PLLSET _IOW('v' , BASE_VIDIOCPRIVATE+3, struct bttv_pll_info) -#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int) -#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int) -#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) -#define BTTV_PICNR _IOR('v' , BASE_VIDIOCPRIVATE+7, int) -#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) - -#define AUDIO_TUNER 0x00 -#define AUDIO_RADIO 0x01 -#define AUDIO_EXTERN 0x02 -#define AUDIO_INTERN 0x03 -#define AUDIO_OFF 0x04 -#define AUDIO_ON 0x05 -#define AUDIO_MUTE 0x80 -#define AUDIO_UNMUTE 0x81 - -#define TDA9850 0x01 -#define TDA9840 0x02 -#define TDA8425 0x03 -#define TEA6300 0x04 - -#define I2C_TSA5522 0xc2 -#define I2C_TDA7432 0x8a -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 -#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ -#define I2C_TDA9875 0xb0 -#define I2C_HAUPEE 0xa0 -#define I2C_STBEE 0xae -#define I2C_VHX 0xc0 -#define I2C_MSP3400 0x80 -#define I2C_TEA6300 0x80 -#define I2C_DPL3518 0x84 - -#ifndef HAVE_TVAUDIO -#define TDA9840_SW 0x00 -#define TDA9840_LVADJ 0x02 -#define TDA9840_STADJ 0x03 -#define TDA9840_TEST 0x04 -#endif - -#define PT2254_L_CHANEL 0x10 -#define PT2254_R_CHANEL 0x08 -#define PT2254_DBS_IN_2 0x400 -#define PT2254_DBS_IN_10 0x20000 -#define WINVIEW_PT2254_CLK 0x40 -#define WINVIEW_PT2254_DATA 0x20 -#define WINVIEW_PT2254_STROBE 0x80 - -struct bttv_just_hacking { - int height,width; /* size */ - unsigned int format; /* should be VIDEO_PALETTE_* */ - long buf; - int len; -}; - -#define BTTV_JUST_HACKING _IOR('v' , BASE_VIDIOCPRIVATE+31,struct bttv_just_hacking) - -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/buz.c b/drivers/char/buz.c deleted file mode 100644 index ca3cb4f47..000000000 --- a/drivers/char/buz.c +++ /dev/null @@ -1,3479 +0,0 @@ -#define MAX_KMALLOC_MEM (512*1024) -/* - buz - Iomega Buz driver version 1.0 - - Copyright (C) 1999 Rainer Johanni - - based on - - buz.0.0.3 Copyright (C) 1998 Dave Perks - - and - - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include "buz.h" -#include -#include - -#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | /* ZR36057_ISR_GIRQ1 | ZR36057_ISR_CodRepIRQ | */ ZR36057_ISR_JPEGRepIRQ ) -#define GPIO_MASK 0xdf - -/* - - BUZ - - GPIO0 = 1, take board out of reset - GPIO1 = 1, take JPEG codec out of sleep mode - GPIO3 = 1, deassert FRAME# to 36060 - - - GIRQ0 signals a vertical sync of the video signal - GIRQ1 signals that ZR36060's DATERR# line is asserted. - - SAA7111A - - In their infinite wisdom, the Iomega engineers decided to - use the same input line for composite and S-Video Color, - although there are two entries not connected at all! - Through this ingenious strike, it is not possible to - keep two running video sources connected at the same time - to Composite and S-VHS input! - - mode 0 - N/C - mode 1 - S-Video Y - mode 2 - noise or something I don't know - mode 3 - Composite and S-Video C - mode 4 - N/C - mode 5 - S-Video (gain C independently selectable of gain Y) - mode 6 - N/C - mode 7 - S-Video (gain C adapted to gain Y) - */ - -#define MAJOR_VERSION 1 /* driver major version */ -#define MINOR_VERSION 0 /* driver minor version */ - -#define BUZ_NAME "Iomega BUZ V-1.0" /* name of the driver */ - -#define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ -#define IOCTL_DEBUG(x) - - -/* The parameters for this driver */ - -/* - The video mem address of the video card. - The driver has a little database for some videocards - to determine it from there. If your video card is not in there - you have either to give it to the driver as a parameter - or set in in a VIDIOCSFBUF ioctl - */ - -static unsigned long vidmem = 0; /* Video memory base address */ - -/* Special purposes only: */ - -static int triton = 0; /* 0=no, 1=yes */ -static int natoma = 0; /* 0=no, 1=yes */ - -/* - Number and size of grab buffers for Video 4 Linux - The vast majority of applications should not need more than 2, - the very popular BTTV driver actually does ONLY have 2. - Time sensitive applications might need more, the maximum - is VIDEO_MAX_FRAME (defined in ). - - The size is set so that the maximum possible request - can be satisfied. Decrease it, if bigphys_area alloc'd - memory is low. If you don't have the bigphys_area patch, - set it to 128 KB. Will you allow only to grab small - images with V4L, but that's better than nothing. - - v4l_bufsize has to be given in KB ! - - */ - -static int v4l_nbufs = 2; -static int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ - -/* - Default input and video norm at startup of the driver. - */ - -static int default_input = 0; /* 0=Composite, 1=S-VHS */ -static int default_norm = 0; /* 0=PAL, 1=NTSC */ - -MODULE_PARM(vidmem, "i"); -MODULE_PARM(triton, "i"); -MODULE_PARM(natoma, "i"); -MODULE_PARM(v4l_nbufs, "i"); -MODULE_PARM(v4l_bufsize, "i"); -MODULE_PARM(default_input, "i"); -MODULE_PARM(default_norm, "i"); - -/* Anybody who uses more than four? */ -#define BUZ_MAX 4 - -static int zoran_num; /* number of Buzs in use */ -static struct zoran zoran[BUZ_MAX]; - -/* forward references */ - -static void v4l_fbuffer_free(struct zoran *zr); -static void jpg_fbuffer_free(struct zoran *zr); -static void zoran_feed_stat_com(struct zoran *zr); - - - -/* - * Allocate the V4L grab buffers - * - * These have to be pysically contiguous. - * If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc - */ - -static int v4l_fbuffer_alloc(struct zoran *zr) -{ - int i, off; - unsigned char *mem; - - for (i = 0; i < v4l_nbufs; i++) { - if (zr->v4l_gbuf[i].fbuffer) - printk(KERN_WARNING "%s: v4l_fbuffer_alloc: buffer %d allready allocated ?\n", zr->name, i); - - if (v4l_bufsize <= MAX_KMALLOC_MEM) { - /* Use kmalloc */ - - mem = (unsigned char *) kmalloc(v4l_bufsize, GFP_KERNEL); - if (mem == 0) { - printk(KERN_ERR "%s: kmalloc for V4L bufs failed\n", zr->name); - v4l_fbuffer_free(zr); - return -ENOBUFS; - } - zr->v4l_gbuf[i].fbuffer = mem; - zr->v4l_gbuf[i].fbuffer_phys = virt_to_phys(mem); - zr->v4l_gbuf[i].fbuffer_bus = virt_to_bus(mem); - for (off = 0; off < v4l_bufsize; off += PAGE_SIZE) - mem_map_reserve(virt_to_page(mem + off)); - DEBUG(printk(BUZ_INFO ": V4L frame %d mem 0x%x (bus: 0x%x=%d)\n", i, mem, virt_to_bus(mem), virt_to_bus(mem))); - } else { - return -ENOBUFS; - } - } - - return 0; -} - -/* free the V4L grab buffers */ -static void v4l_fbuffer_free(struct zoran *zr) -{ - int i, off; - unsigned char *mem; - - for (i = 0; i < v4l_nbufs; i++) { - if (!zr->v4l_gbuf[i].fbuffer) - continue; - - mem = zr->v4l_gbuf[i].fbuffer; - for (off = 0; off < v4l_bufsize; off += PAGE_SIZE) - mem_map_unreserve(virt_to_page(mem + off)); - kfree((void *) zr->v4l_gbuf[i].fbuffer); - zr->v4l_gbuf[i].fbuffer = NULL; - } -} - -/* - * Allocate the MJPEG grab buffers. - * - * If the requested buffer size is smaller than MAX_KMALLOC_MEM, - * kmalloc is used to request a physically contiguous area, - * else we allocate the memory in framgents with get_free_page. - * - * If a Natoma chipset is present and this is a revision 1 zr36057, - * each MJPEG buffer needs to be physically contiguous. - * (RJ: This statement is from Dave Perks' original driver, - * I could never check it because I have a zr36067) - * The driver cares about this because it reduces the buffer - * size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation). - * - * RJ: The contents grab buffers needs never be accessed in the driver. - * Therefore there is no need to allocate them with vmalloc in order - * to get a contiguous virtual memory space. - * I don't understand why many other drivers first allocate them with - * vmalloc (which uses internally also get_free_page, but delivers you - * virtual addresses) and then again have to make a lot of efforts - * to get the physical address. - * - */ - -static int jpg_fbuffer_alloc(struct zoran *zr) -{ - int i, j, off, alloc_contig; - unsigned long mem; - - /* Decide if we should alloc contiguous or fragmented memory */ - /* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */ - - alloc_contig = (zr->jpg_bufsize < MAX_KMALLOC_MEM); - - for (i = 0; i < zr->jpg_nbufs; i++) { - if (zr->jpg_gbuf[i].frag_tab) - printk(KERN_WARNING "%s: jpg_fbuffer_alloc: buffer %d allready allocated ???\n", zr->name, i); - - /* Allocate fragment table for this buffer */ - - mem = get_free_page(GFP_KERNEL); - if (mem == 0) { - printk(KERN_ERR "%s: jpg_fbuffer_alloc: get_free_page (frag_tab) failed for buffer %d\n", zr->name, i); - jpg_fbuffer_free(zr); - return -ENOBUFS; - } - memset((void *) mem, 0, PAGE_SIZE); - zr->jpg_gbuf[i].frag_tab = (u32 *) mem; - zr->jpg_gbuf[i].frag_tab_bus = virt_to_bus((void *) mem); - - if (alloc_contig) { - mem = (unsigned long) kmalloc(zr->jpg_bufsize, GFP_KERNEL); - if (mem == 0) { - jpg_fbuffer_free(zr); - return -ENOBUFS; - } - zr->jpg_gbuf[i].frag_tab[0] = virt_to_bus((void *) mem); - zr->jpg_gbuf[i].frag_tab[1] = ((zr->jpg_bufsize / 4) << 1) | 1; - for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE) - mem_map_reserve(virt_to_page(mem + off)); - } else { - /* jpg_bufsize is alreay page aligned */ - for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { - mem = get_free_page(GFP_KERNEL); - if (mem == 0) { - jpg_fbuffer_free(zr); - return -ENOBUFS; - } - zr->jpg_gbuf[i].frag_tab[2 * j] = virt_to_bus((void *) mem); - zr->jpg_gbuf[i].frag_tab[2 * j + 1] = (PAGE_SIZE / 4) << 1; - mem_map_reserve(virt_to_page(mem)); - } - - zr->jpg_gbuf[i].frag_tab[2 * j - 1] |= 1; - } - } - - DEBUG(printk("jpg_fbuffer_alloc: %d KB allocated\n", - (zr->jpg_nbufs * zr->jpg_bufsize) >> 10)); - zr->jpg_buffers_allocated = 1; - return 0; -} - -/* free the MJPEG grab buffers */ -static void jpg_fbuffer_free(struct zoran *zr) -{ - int i, j, off, alloc_contig; - unsigned char *mem; - - /* Decide if we should alloc contiguous or fragmented memory */ - /* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */ - - alloc_contig = (zr->jpg_bufsize < MAX_KMALLOC_MEM); - - for (i = 0; i < zr->jpg_nbufs; i++) { - if (!zr->jpg_gbuf[i].frag_tab) - continue; - - if (alloc_contig) { - if (zr->jpg_gbuf[i].frag_tab[0]) { - mem = (unsigned char *) bus_to_virt(zr->jpg_gbuf[i].frag_tab[0]); - for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE) - mem_map_unreserve(virt_to_page(mem + off)); - kfree((void *) mem); - zr->jpg_gbuf[i].frag_tab[0] = 0; - zr->jpg_gbuf[i].frag_tab[1] = 0; - } - } else { - for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { - if (!zr->jpg_gbuf[i].frag_tab[2 * j]) - break; - mem_map_unreserve(virt_to_page(bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j]))); - free_page((unsigned long) bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j])); - zr->jpg_gbuf[i].frag_tab[2 * j] = 0; - zr->jpg_gbuf[i].frag_tab[2 * j + 1] = 0; - } - } - - free_page((unsigned long) zr->jpg_gbuf[i].frag_tab); - zr->jpg_gbuf[i].frag_tab = NULL; - } - zr->jpg_buffers_allocated = 0; -} - - -/* ----------------------------------------------------------------------- */ - -/* I2C functions */ - -#define I2C_DELAY 10 - - -/* software I2C functions */ - -static void i2c_setlines(struct i2c_bus *bus, int ctrl, int data) -{ - struct zoran *zr = (struct zoran *) bus->data; - btwrite((data << 1) | ctrl, ZR36057_I2CBR); - btread(ZR36057_I2CBR); - udelay(I2C_DELAY); -} - -static int i2c_getdataline(struct i2c_bus *bus) -{ - struct zoran *zr = (struct zoran *) bus->data; - return (btread(ZR36057_I2CBR) >> 1) & 1; -} - -static void attach_inform(struct i2c_bus *bus, int id) -{ - DEBUG(struct zoran *zr = (struct zoran *) bus->data); - DEBUG(printk(BUZ_DEBUG "-%u: i2c attach %02x\n", zr->id, id)); -} - -static void detach_inform(struct i2c_bus *bus, int id) -{ - DEBUG(struct zoran *zr = (struct zoran *) bus->data); - DEBUG(printk(BUZ_DEBUG "-%u: i2c detach %02x\n", zr->id, id)); -} - -static struct i2c_bus zoran_i2c_bus_template = -{ - "zr36057", - I2C_BUSID_BT848, - NULL, - - SPIN_LOCK_UNLOCKED, - - attach_inform, - detach_inform, - - i2c_setlines, - i2c_getdataline, - NULL, - NULL, -}; - - -/* ----------------------------------------------------------------------- */ - -static void GPIO(struct zoran *zr, unsigned bit, unsigned value) -{ - u32 reg; - u32 mask; - - mask = 1 << (24 + bit); - reg = btread(ZR36057_GPPGCR1) & ~mask; - if (value) { - reg |= mask; - } - btwrite(reg, ZR36057_GPPGCR1); - /* Stop any PCI posting on the GPIO bus */ - btread(ZR36057_I2CBR); -} - - -/* - * Set the registers for the size we have specified. Don't bother - * trying to understand this without the ZR36057 manual in front of - * you [AC]. - * - * PS: The manual is free for download in .pdf format from - * www.zoran.com - nicely done those folks. - */ - -struct tvnorm { - u16 Wt, Wa, Ht, Ha, HStart, VStart; -}; - -static struct tvnorm tvnorms[] = -{ - /* PAL-BDGHI */ - {864, 720, 625, 576, 31, 16}, - /* NTSC */ - {858, 720, 525, 480, 21, 8}, -}; -#define TVNORMS (sizeof(tvnorms) / sizeof(tvnorm)) - -static int format2bpp(int format) -{ - int bpp; - - /* Determine the number of bytes per pixel for the video format requested */ - - switch (format) { - - case VIDEO_PALETTE_YUV422: - bpp = 2; - break; - - case VIDEO_PALETTE_RGB555: - bpp = 2; - break; - - case VIDEO_PALETTE_RGB565: - bpp = 2; - break; - - case VIDEO_PALETTE_RGB24: - bpp = 3; - break; - - case VIDEO_PALETTE_RGB32: - bpp = 4; - break; - - default: - bpp = 0; - } - - return bpp; -} - -/* - * set geometry - */ -static void zr36057_set_vfe(struct zoran *zr, int video_width, int video_height, - unsigned int video_format) -{ - struct tvnorm *tvn; - unsigned HStart, HEnd, VStart, VEnd; - unsigned DispMode; - unsigned VidWinWid, VidWinHt; - unsigned hcrop1, hcrop2, vcrop1, vcrop2; - unsigned Wa, We, Ha, He; - unsigned X, Y, HorDcm, VerDcm; - u32 reg; - unsigned mask_line_size; - - if (zr->params.norm < 0 || zr->params.norm > 1) { - printk(KERN_ERR "%s: set_vfe: video_norm = %d not valid\n", zr->name, zr->params.norm); - return; - } - if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT) { - printk(KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n", zr->name, video_width, video_height); - return; - } - tvn = &tvnorms[zr->params.norm]; - - Wa = tvn->Wa; - Ha = tvn->Ha; - - /* if window has more than half of active height, - switch on interlacing - we want the full information */ - - zr->video_interlace = (video_height > Ha / 2); - -/**** zr36057 ****/ - - /* horizontal */ - VidWinWid = video_width; - X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa; - We = (VidWinWid * 64) / X; - HorDcm = 64 - X; - hcrop1 = 2 * ((tvn->Wa - We) / 4); - hcrop2 = tvn->Wa - We - hcrop1; - HStart = tvn->HStart | 1; - HEnd = HStart + tvn->Wa - 1; - HStart += hcrop1; - HEnd -= hcrop2; - reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart) - | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd); - reg |= ZR36057_VFEHCR_HSPol; - btwrite(reg, ZR36057_VFEHCR); - - /* Vertical */ - DispMode = !zr->video_interlace; - VidWinHt = DispMode ? video_height : video_height / 2; - Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha; - He = (VidWinHt * 64) / Y; - VerDcm = 64 - Y; - vcrop1 = (tvn->Ha / 2 - He) / 2; - vcrop2 = tvn->Ha / 2 - He - vcrop1; - VStart = tvn->VStart; - VEnd = VStart + tvn->Ha / 2 - 1; - VStart += vcrop1; - VEnd -= vcrop2; - reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart) - | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd); - reg |= ZR36057_VFEVCR_VSPol; - btwrite(reg, ZR36057_VFEVCR); - - /* scaler and pixel format */ - reg = 0 // ZR36057_VFESPFR_ExtFl /* Trying to live without ExtFl */ - | (HorDcm << ZR36057_VFESPFR_HorDcm) - | (VerDcm << ZR36057_VFESPFR_VerDcm) - | (DispMode << ZR36057_VFESPFR_DispMode) - | ZR36057_VFESPFR_LittleEndian; - /* RJ: I don't know, why the following has to be the opposite - of the corresponding ZR36060 setting, but only this way - we get the correct colors when uncompressing to the screen */ - reg |= ZR36057_VFESPFR_VCLKPol; - /* RJ: Don't know if that is needed for NTSC also */ - reg |= ZR36057_VFESPFR_TopField; - switch (video_format) { - - case VIDEO_PALETTE_YUV422: - reg |= ZR36057_VFESPFR_YUV422; - break; - - case VIDEO_PALETTE_RGB555: - reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif; - break; - - case VIDEO_PALETTE_RGB565: - reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif; - break; - - case VIDEO_PALETTE_RGB24: - reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24; - break; - - case VIDEO_PALETTE_RGB32: - reg |= ZR36057_VFESPFR_RGB888; - break; - - default: - printk(KERN_INFO "%s: Unknown color_fmt=%x\n", zr->name, video_format); - return; - - } - if (HorDcm >= 48) { - reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */ - } else if (HorDcm >= 32) { - reg |= 2 << ZR36057_VFESPFR_HFilter; /* 4 tap filter */ - } else if (HorDcm >= 16) { - reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */ - } - btwrite(reg, ZR36057_VFESPFR); - - /* display configuration */ - - reg = (16 << ZR36057_VDCR_MinPix) - | (VidWinHt << ZR36057_VDCR_VidWinHt) - | (VidWinWid << ZR36057_VDCR_VidWinWid); - if (triton) - reg &= ~ZR36057_VDCR_Triton; - else - reg |= ZR36057_VDCR_Triton; - btwrite(reg, ZR36057_VDCR); - - /* Write overlay clipping mask data, but don't enable overlay clipping */ - /* RJ: since this makes only sense on the screen, we use - zr->window.width instead of video_width */ - - mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; - reg = virt_to_bus(zr->overlay_mask); - btwrite(reg, ZR36057_MMTR); - reg = virt_to_bus(zr->overlay_mask + mask_line_size); - btwrite(reg, ZR36057_MMBR); - reg = mask_line_size - (zr->window.width + 31) / 32; - if (DispMode == 0) - reg += mask_line_size; - reg <<= ZR36057_OCR_MaskStride; - btwrite(reg, ZR36057_OCR); - -} - -/* - * Switch overlay on or off - */ - -static void zr36057_overlay(struct zoran *zr, int on) -{ - int fmt, bpp; - u32 reg; - - if (on) { - /* do the necessary settings ... */ - - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); /* switch it off first */ - - switch (zr->buffer.depth) { - case 15: - fmt = VIDEO_PALETTE_RGB555; - bpp = 2; - break; - case 16: - fmt = VIDEO_PALETTE_RGB565; - bpp = 2; - break; - case 24: - fmt = VIDEO_PALETTE_RGB24; - bpp = 3; - break; - case 32: - fmt = VIDEO_PALETTE_RGB32; - bpp = 4; - break; - default: - fmt = 0; - bpp = 0; - } - - zr36057_set_vfe(zr, zr->window.width, zr->window.height, fmt); - - /* Start and length of each line MUST be 4-byte aligned. - This should be allready checked before the call to this routine. - All error messages are internal driver checking only! */ - - /* video display top and bottom registers */ - - reg = (u32) zr->buffer.base - + zr->window.x * bpp - + zr->window.y * zr->buffer.bytesperline; - btwrite(reg, ZR36057_VDTR); - if (reg & 3) - printk(KERN_ERR "%s: zr36057_overlay: video_address not aligned\n", zr->name); - if (zr->video_interlace) - reg += zr->buffer.bytesperline; - btwrite(reg, ZR36057_VDBR); - - /* video stride, status, and frame grab register */ - - reg = zr->buffer.bytesperline - zr->window.width * bpp; - if (zr->video_interlace) - reg += zr->buffer.bytesperline; - if (reg & 3) - printk(KERN_ERR "%s: zr36057_overlay: video_stride not aligned\n", zr->name); - reg = (reg << ZR36057_VSSFGR_DispStride); - reg |= ZR36057_VSSFGR_VidOvf; /* clear overflow status */ - btwrite(reg, ZR36057_VSSFGR); - - /* Set overlay clipping */ - - if (zr->window.clipcount) - btor(ZR36057_OCR_OvlEnable, ZR36057_OCR); - - /* ... and switch it on */ - - btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); - } else { - /* Switch it off */ - - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); - } -} - -/* - * The overlay mask has one bit for each pixel on a scan line, - * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. - */ -static void write_overlay_mask(struct zoran *zr, struct video_clip *vp, int count) -{ - unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; - u32 *mask; - int x, y, width, height; - unsigned i, j, k; - u32 reg; - - /* fill mask with one bits */ - memset(zr->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT); - reg = 0; - - for (i = 0; i < count; ++i) { - /* pick up local copy of clip */ - x = vp[i].x; - y = vp[i].y; - width = vp[i].width; - height = vp[i].height; - - /* trim clips that extend beyond the window */ - if (x < 0) { - width += x; - x = 0; - } - if (y < 0) { - height += y; - y = 0; - } - if (x + width > zr->window.width) { - width = zr->window.width - x; - } - if (y + height > zr->window.height) { - height = zr->window.height - y; - } - /* ignore degenerate clips */ - if (height <= 0) { - continue; - } - if (width <= 0) { - continue; - } - /* apply clip for each scan line */ - for (j = 0; j < height; ++j) { - /* reset bit for each pixel */ - /* this can be optimized later if need be */ - mask = zr->overlay_mask + (y + j) * mask_line_size; - for (k = 0; k < width; ++k) { - mask[(x + k) / 32] &= ~((u32) 1 << (x + k) % 32); - } - } - } -} - -/* Enable/Disable uncompressed memory grabbing of the 36057 */ - -static void zr36057_set_memgrab(struct zoran *zr, int mode) -{ - if (mode) { - if (btread(ZR36057_VSSFGR) & (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab)) - printk(KERN_WARNING "%s: zr36057_set_memgrab_on with SnapShot or FrameGrab on ???\n", zr->name); - - /* switch on VSync interrupts */ - - btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts - - btor(ZR36057_ICR_GIRQ0, ZR36057_ICR); - - /* enable SnapShot */ - - btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); - - /* Set zr36057 video front end and enable video */ - -#ifdef XAWTV_HACK - zr36057_set_vfe(zr, zr->gwidth > 720 ? 720 : zr->gwidth, zr->gheight, zr->gformat); -#else - zr36057_set_vfe(zr, zr->gwidth, zr->gheight, zr->gformat); -#endif - - zr->v4l_memgrab_active = 1; - } else { - zr->v4l_memgrab_active = 0; - - /* switch off VSync interrupts */ - - btand(~ZR36057_ICR_GIRQ0, ZR36057_ICR); - - /* reenable grabbing to screen if it was running */ - - if (zr->v4l_overlay_active) { - zr36057_overlay(zr, 1); - } else { - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); - btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); - } - } -} - -static int wait_grab_pending(struct zoran *zr) -{ - unsigned long flags; - - /* wait until all pending grabs are finished */ - - if (!zr->v4l_memgrab_active) - return 0; - - while (zr->v4l_pend_tail != zr->v4l_pend_head) { - interruptible_sleep_on(&zr->v4l_capq); - if (signal_pending(current)) - return -ERESTARTSYS; - } - - spin_lock_irqsave(&zr->lock, flags); - zr36057_set_memgrab(zr, 0); - spin_unlock_irqrestore(&zr->lock, flags); - - return 0; -} - -/* - * V4L Buffer grabbing - */ - -static int v4l_grab(struct zoran *zr, struct video_mmap *mp) -{ - unsigned long flags; - int res, bpp; - - /* - * There is a long list of limitations to what is allowed to be grabbed - * We don't output error messages her, since some programs (e.g. xawtv) - * just try several settings to find out what is valid or not. - */ - - /* No grabbing outside the buffer range! */ - - if (mp->frame >= v4l_nbufs || mp->frame < 0) - return -EINVAL; - - /* Check size and format of the grab wanted */ - - if (mp->height < BUZ_MIN_HEIGHT || mp->width < BUZ_MIN_WIDTH) - return -EINVAL; - if (mp->height > BUZ_MAX_HEIGHT || mp->width > BUZ_MAX_WIDTH) - return -EINVAL; - - bpp = format2bpp(mp->format); - if (bpp == 0) - return -EINVAL; - - /* Check against available buffer size */ - - if (mp->height * mp->width * bpp > v4l_bufsize) - return -EINVAL; - - /* The video front end needs 4-byte alinged line sizes */ - - if ((bpp == 2 && (mp->width & 1)) || (bpp == 3 && (mp->width & 3))) - return -EINVAL; - - /* - * To minimize the time spent in the IRQ routine, we avoid setting up - * the video front end there. - * If this grab has different parameters from a running streaming capture - * we stop the streaming capture and start it over again. - */ - - if (zr->v4l_memgrab_active && - (zr->gwidth != mp->width || zr->gheight != mp->height || zr->gformat != mp->format)) { - res = wait_grab_pending(zr); - if (res) - return res; - } - zr->gwidth = mp->width; - zr->gheight = mp->height; - zr->gformat = mp->format; - zr->gbpl = bpp * zr->gwidth; - - - spin_lock_irqsave(&zr->lock, flags); - - /* make sure a grab isn't going on currently with this buffer */ - - switch (zr->v4l_gbuf[mp->frame].state) { - - default: - case BUZ_STATE_PEND: - res = -EBUSY; /* what are you doing? */ - break; - - case BUZ_STATE_USER: - case BUZ_STATE_DONE: - /* since there is at least one unused buffer there's room for at least one more pend[] entry */ - zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = mp->frame; - zr->v4l_gbuf[mp->frame].state = BUZ_STATE_PEND; - res = 0; - break; - - } - - /* put the 36057 into frame grabbing mode */ - - if (!res && !zr->v4l_memgrab_active) - zr36057_set_memgrab(zr, 1); - - spin_unlock_irqrestore(&zr->lock, flags); - - return res; -} - -/* - * Sync on a V4L buffer - */ - -static int v4l_sync(struct zoran *zr, int frame) -{ - unsigned long flags; - - - /* check passed-in frame number */ - if (frame >= v4l_nbufs || frame < 0) { - printk(KERN_ERR "%s: v4l_sync: frame %d is invalid\n", zr->name, frame); - return -EINVAL; - } - /* Check if is buffer was queued at all */ - - if (zr->v4l_gbuf[frame].state == BUZ_STATE_USER) { -// printk(KERN_ERR "%s: v4l_sync: Trying to sync on a buffer which was not queued?\n", zr->name); - return -EINVAL; - } - /* wait on this buffer to get ready */ - - while (zr->v4l_gbuf[frame].state == BUZ_STATE_PEND) { - interruptible_sleep_on(&zr->v4l_capq); - if (signal_pending(current)) - return -ERESTARTSYS; - } - - /* buffer should now be in BUZ_STATE_DONE */ - - if (zr->v4l_gbuf[frame].state != BUZ_STATE_DONE) - printk(KERN_ERR "%s: v4l_sync - internal error\n", zr->name); - - /* Check if streaming capture has finished */ - - spin_lock_irqsave(&zr->lock, flags); - - if (zr->v4l_pend_tail == zr->v4l_pend_head) - zr36057_set_memgrab(zr, 0); - - spin_unlock_irqrestore(&zr->lock, flags); - - return 0; -} -/***************************************************************************** - * * - * Set up the Buz-specific MJPEG part * - * * - *****************************************************************************/ - -/* - * Wait til post office is no longer busy - */ - -static int post_office_wait(struct zoran *zr) -{ - u32 por; - u32 ct=0; - - while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) { - ct++; - if(ct>100000) - { - printk(KERN_ERR "%s: timeout on post office.\n", zr->name); - return -1; - } - /* wait for something to happen */ - } - if ((por & ZR36057_POR_POPen) != 0) { - printk(KERN_WARNING "%s: pop pending %08x\n", zr->name, por); - return -1; - } - if ((por & (ZR36057_POR_POTime | ZR36057_POR_POPen)) != 0) { - printk(KERN_WARNING "%s: pop timeout %08x\n", zr->name, por); - return -1; - } - return 0; -} - -static int post_office_write(struct zoran *zr, unsigned guest, unsigned reg, unsigned value) -{ - u32 por; - - post_office_wait(zr); - por = ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16) | (value & 0xFF); - btwrite(por, ZR36057_POR); - return post_office_wait(zr); -} - -static int post_office_read(struct zoran *zr, unsigned guest, unsigned reg) -{ - u32 por; - - post_office_wait(zr); - por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16); - btwrite(por, ZR36057_POR); - if (post_office_wait(zr) < 0) { - return -1; - } - return btread(ZR36057_POR) & 0xFF; -} - -static int zr36060_write_8(struct zoran *zr, unsigned reg, unsigned val) -{ - if (post_office_wait(zr) - || post_office_write(zr, 0, 1, reg >> 8) - || post_office_write(zr, 0, 2, reg)) { - return -1; - } - return post_office_write(zr, 0, 3, val); -} - -static int zr36060_write_16(struct zoran *zr, unsigned reg, unsigned val) -{ - if (zr36060_write_8(zr, reg + 0, val >> 8)) { - return -1; - } - return zr36060_write_8(zr, reg + 1, val >> 0); -} - -static int zr36060_write_24(struct zoran *zr, unsigned reg, unsigned val) -{ - if (zr36060_write_8(zr, reg + 0, val >> 16)) { - return -1; - } - return zr36060_write_16(zr, reg + 1, val >> 0); -} - -static int zr36060_write_32(struct zoran *zr, unsigned reg, unsigned val) -{ - if (zr36060_write_16(zr, reg + 0, val >> 16)) { - return -1; - } - return zr36060_write_16(zr, reg + 2, val >> 0); -} - -static u32 zr36060_read_8(struct zoran *zr, unsigned reg) -{ - if (post_office_wait(zr) - || post_office_write(zr, 0, 1, reg >> 8) - || post_office_write(zr, 0, 2, reg)) { - return -1; - } - return post_office_read(zr, 0, 3) & 0xFF; -} - -static int zr36060_reset(struct zoran *zr) -{ - return post_office_write(zr, 3, 0, 0); -} - -static void zr36060_sleep(struct zoran *zr, int sleep) -{ - GPIO(zr, 1, !sleep); -} - - -static void zr36060_set_jpg(struct zoran *zr, enum zoran_codec_mode mode) -{ - struct tvnorm *tvn; - u32 reg; - int size; - - reg = (1 << 0) /* CodeMstr */ - |(0 << 2) /* CFIS=0 */ - |(0 << 6) /* Endian=0 */ - |(0 << 7); /* Code16=0 */ - zr36060_write_8(zr, 0x002, reg); - - switch (mode) { - - case BUZ_MODE_MOTION_DECOMPRESS: - case BUZ_MODE_STILL_DECOMPRESS: - reg = 0x00; /* Codec mode = decompression */ - break; - - case BUZ_MODE_MOTION_COMPRESS: - case BUZ_MODE_STILL_COMPRESS: - default: - reg = 0xa4; /* Codec mode = compression with variable scale factor */ - break; - - } - zr36060_write_8(zr, 0x003, reg); - - reg = 0x00; /* reserved, mbz */ - zr36060_write_8(zr, 0x004, reg); - - reg = 0xff; /* 510 bits/block */ - zr36060_write_8(zr, 0x005, reg); - - /* JPEG markers */ - reg = (zr->params.jpeg_markers) & 0x38; /* DRI, DQT, DHT */ - if (zr->params.COM_len) - reg |= JPEG_MARKER_COM; - if (zr->params.APP_len) - reg |= JPEG_MARKER_APP; - zr36060_write_8(zr, 0x006, reg); - - reg = (0 << 3) /* DATERR=0 */ - |(0 << 2) /* END=0 */ - |(0 << 1) /* EOI=0 */ - |(0 << 0); /* EOAV=0 */ - zr36060_write_8(zr, 0x007, reg); - - /* code volume */ - - /* Target field size in pixels: */ - tvn = &tvnorms[zr->params.norm]; - size = (tvn->Ha / 2) * (tvn->Wa) / (zr->params.HorDcm) / (zr->params.VerDcm); - - /* Target compressed field size in bits: */ - size = size * 16; /* uncompressed size in bits */ - size = size * zr->params.quality / 400; /* quality = 100 is a compression ratio 1:4 */ - - /* Lower limit (arbitrary, 1 KB) */ - if (size < 8192) - size = 8192; - - /* Upper limit: 7/8 of the code buffers */ - if (size * zr->params.field_per_buff > zr->jpg_bufsize * 7) - size = zr->jpg_bufsize * 7 / zr->params.field_per_buff; - - reg = size; - zr36060_write_32(zr, 0x009, reg); - - /* how do we set initial SF as a function of quality parameter? */ - reg = 0x0100; /* SF=1.0 */ - zr36060_write_16(zr, 0x011, reg); - - reg = 0x00ffffff; /* AF=max */ - zr36060_write_24(zr, 0x013, reg); - - reg = 0x0000; /* test */ - zr36060_write_16(zr, 0x024, reg); -} - -static void zr36060_set_video(struct zoran *zr, enum zoran_codec_mode mode) -{ - struct tvnorm *tvn; - u32 reg; - - reg = (0 << 7) /* Video8=0 */ - |(0 << 6) /* Range=0 */ - |(0 << 3) /* FlDet=0 */ - |(1 << 2) /* FlVedge=1 */ - |(0 << 1) /* FlExt=0 */ - |(0 << 0); /* SyncMstr=0 */ - - /* According to ZR36067 documentation, FlDet should correspond - to the odd_even flag of the ZR36067 */ - if (zr->params.odd_even) - reg |= (1 << 3); - - if (mode != BUZ_MODE_STILL_DECOMPRESS) { - /* limit pixels to range 16..235 as per CCIR-601 */ - reg |= (1 << 6); /* Range=1 */ - } - zr36060_write_8(zr, 0x030, reg); - - reg = (0 << 7) /* VCLKPol=0 */ - |(0 << 6) /* PValPol=0 */ - |(1 << 5) /* PoePol=1 */ - |(0 << 4) /* SImgPol=0 */ - |(0 << 3) /* BLPol=0 */ - |(0 << 2) /* FlPol=0 */ - |(0 << 1) /* HSPol=0, sync on falling edge */ - |(1 << 0); /* VSPol=1 */ - zr36060_write_8(zr, 0x031, reg); - - switch (zr->params.HorDcm) { - default: - case 1: - reg = (0 << 0); - break; /* HScale = 0 */ - - case 2: - reg = (1 << 0); - break; /* HScale = 1 */ - - case 4: - reg = (2 << 0); - break; /* HScale = 2 */ - } - if (zr->params.VerDcm == 2) - reg |= (1 << 2); - zr36060_write_8(zr, 0x032, reg); - - reg = 0x80; /* BackY */ - zr36060_write_8(zr, 0x033, reg); - - reg = 0xe0; /* BackU */ - zr36060_write_8(zr, 0x034, reg); - - reg = 0xe0; /* BackV */ - zr36060_write_8(zr, 0x035, reg); - - /* sync generator */ - - tvn = &tvnorms[zr->params.norm]; - - reg = tvn->Ht - 1; /* Vtotal */ - zr36060_write_16(zr, 0x036, reg); - - reg = tvn->Wt - 1; /* Htotal */ - zr36060_write_16(zr, 0x038, reg); - - reg = 6 - 1; /* VsyncSize */ - zr36060_write_8(zr, 0x03a, reg); - - reg = 100 - 1; /* HsyncSize */ - zr36060_write_8(zr, 0x03b, reg); - - reg = tvn->VStart - 1; /* BVstart */ - zr36060_write_8(zr, 0x03c, reg); - - reg += tvn->Ha / 2; /* BVend */ - zr36060_write_16(zr, 0x03e, reg); - - reg = tvn->HStart - 1; /* BHstart */ - zr36060_write_8(zr, 0x03d, reg); - - reg += tvn->Wa; /* BHend */ - zr36060_write_16(zr, 0x040, reg); - - /* active area */ - reg = zr->params.img_y + tvn->VStart; /* Vstart */ - zr36060_write_16(zr, 0x042, reg); - - reg += zr->params.img_height; /* Vend */ - zr36060_write_16(zr, 0x044, reg); - - reg = zr->params.img_x + tvn->HStart; /* Hstart */ - zr36060_write_16(zr, 0x046, reg); - - reg += zr->params.img_width; /* Hend */ - zr36060_write_16(zr, 0x048, reg); - - /* subimage area */ - reg = zr->params.img_y + tvn->VStart; /* SVstart */ - zr36060_write_16(zr, 0x04a, reg); - - reg += zr->params.img_height; /* SVend */ - zr36060_write_16(zr, 0x04c, reg); - - reg = zr->params.img_x + tvn->HStart; /* SHstart */ - zr36060_write_16(zr, 0x04e, reg); - - reg += zr->params.img_width; /* SHend */ - zr36060_write_16(zr, 0x050, reg); -} - -static void zr36060_set_jpg_SOF(struct zoran *zr) -{ - u32 reg; - - - reg = 0xffc0; /* SOF marker */ - zr36060_write_16(zr, 0x060, reg); - - reg = 17; /* SOF length */ - zr36060_write_16(zr, 0x062, reg); - - reg = 8; /* precision 8 bits */ - zr36060_write_8(zr, 0x064, reg); - - reg = zr->params.img_height / zr->params.VerDcm; /* image height */ - zr36060_write_16(zr, 0x065, reg); - - reg = zr->params.img_width / zr->params.HorDcm; /* image width */ - zr36060_write_16(zr, 0x067, reg); - - reg = 3; /* 3 color components */ - zr36060_write_8(zr, 0x069, reg); - - reg = 0x002100; /* Y component */ - zr36060_write_24(zr, 0x06a, reg); - - reg = 0x011101; /* U component */ - zr36060_write_24(zr, 0x06d, reg); - - reg = 0x021101; /* V component */ - zr36060_write_24(zr, 0x070, reg); -} - -static void zr36060_set_jpg_SOS(struct zoran *zr) -{ - u32 reg; - - - reg = 0xffda; /* SOS marker */ - zr36060_write_16(zr, 0x07a, reg); - - reg = 12; /* SOS length */ - zr36060_write_16(zr, 0x07c, reg); - - reg = 3; /* 3 color components */ - zr36060_write_8(zr, 0x07e, reg); - - reg = 0x0000; /* Y component */ - zr36060_write_16(zr, 0x07f, reg); - - reg = 0x0111; /* U component */ - zr36060_write_16(zr, 0x081, reg); - - reg = 0x0211; /* V component */ - zr36060_write_16(zr, 0x083, reg); - - reg = 0x003f00; /* Start, end spectral scans */ - zr36060_write_24(zr, 0x085, reg); -} - -static void zr36060_set_jpg_DRI(struct zoran *zr) -{ - u32 reg; - - - reg = 0xffdd; /* DRI marker */ - zr36060_write_16(zr, 0x0c0, reg); - - reg = 4; /* DRI length */ - zr36060_write_16(zr, 0x0c2, reg); - - reg = 8; /* length in MCUs */ - zr36060_write_16(zr, 0x0c4, reg); -} - -static void zr36060_set_jpg_DQT(struct zoran *zr) -{ - unsigned i; - unsigned adr; - static const u8 dqt[] = - { - 0xff, 0xdb, /* DHT marker */ - 0x00, 0x84, /* DHT length */ - 0x00, /* table ID 0 */ - 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, - 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, - 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, - 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, - 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, - 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, - 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, - 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, - 0x01, /* table ID 1 */ - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 - }; - - /* write fixed quantitization tables */ - adr = 0x0cc; - for (i = 0; i < sizeof(dqt); ++i) { - zr36060_write_8(zr, adr++, dqt[i]); - } -} - -static void zr36060_set_jpg_DHT(struct zoran *zr) -{ - unsigned i; - unsigned adr; - static const u8 dht[] = - { - 0xff, 0xc4, /* DHT marker */ - 0x01, 0xa2, /* DHT length */ - 0x00, /* table class 0, ID 0 */ - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, /* # codes of length 1..8 */ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* # codes of length 8..16 */ - 0x00, /* values for codes of length 2 */ - 0x01, 0x02, 0x03, 0x04, 0x05, /* values for codes of length 3 */ - 0x06, /* values for codes of length 4 */ - 0x07, /* values for codes of length 5 */ - 0x08, /* values for codes of length 6 */ - 0x09, /* values for codes of length 7 */ - 0x0a, /* values for codes of length 8 */ - 0x0b, /* values for codes of length 9 */ - 0x01, /* table class 0, ID 1 */ - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* # codes of length 1..8 */ - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* # codes of length 9..16 */ - 0x00, 0x01, 0x02, /* values for codes of length 2 */ - 0x03, /* values for codes of length 3 */ - 0x04, /* values for codes of length 4 */ - 0x05, /* values for codes of length 5 */ - 0x06, /* values for codes of length 6 */ - 0x07, /* values for codes of length 7 */ - 0x08, /* values for codes of length 8 */ - 0x09, /* values for codes of length 9 */ - 0x0a, /* values for codes of length 10 */ - 0x0b, /* values for codes of length 11 */ - 0x10, - 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, - 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, - 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, - 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, - 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, - 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, - 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, - 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, - 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, - 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, - 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, - 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, - 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, - 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, - 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, - 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, - 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, - 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, - 0xf6, 0xf7, 0xf8, 0xf9, 0xfa - }; - - /* write fixed Huffman tables */ - adr = 0x1d4; - for (i = 0; i < sizeof(dht); ++i) { - zr36060_write_8(zr, adr++, dht[i]); - } -} - -static void zr36060_set_jpg_APP(struct zoran *zr) -{ - unsigned adr; - int len, i; - u32 reg; - - - len = zr->params.APP_len; - if (len < 0) - len = 0; - if (len > 60) - len = 60; - - i = zr->params.APPn; - if (i < 0) - i = 0; - if (i > 15) - i = 15; - - reg = 0xffe0 + i; /* APPn marker */ - zr36060_write_16(zr, 0x380, reg); - - reg = len + 2; /* APPn len */ - zr36060_write_16(zr, 0x382, reg); - - /* write APPn data */ - adr = 0x384; - for (i = 0; i < 60; i++) { - zr36060_write_8(zr, adr++, (i < len ? zr->params.APP_data[i] : 0)); - } -} - -static void zr36060_set_jpg_COM(struct zoran *zr) -{ - unsigned adr; - int len, i; - u32 reg; - - - len = zr->params.COM_len; - if (len < 0) - len = 0; - if (len > 60) - len = 60; - - reg = 0xfffe; /* COM marker */ - zr36060_write_16(zr, 0x3c0, reg); - - reg = len + 2; /* COM len */ - zr36060_write_16(zr, 0x3c2, reg); - - /* write COM data */ - adr = 0x3c4; - for (i = 0; i < 60; i++) { - zr36060_write_8(zr, adr++, (i < len ? zr->params.COM_data[i] : 0)); - } -} - -static void zr36060_set_cap(struct zoran *zr, enum zoran_codec_mode mode) -{ - unsigned i; - u32 reg; - - zr36060_reset(zr); - mdelay(10); - - reg = (0 << 7) /* Load=0 */ - |(1 << 0); /* SynRst=1 */ - zr36060_write_8(zr, 0x000, reg); - - zr36060_set_jpg(zr, mode); - zr36060_set_video(zr, mode); - zr36060_set_jpg_SOF(zr); - zr36060_set_jpg_SOS(zr); - zr36060_set_jpg_DRI(zr); - zr36060_set_jpg_DQT(zr); - zr36060_set_jpg_DHT(zr); - zr36060_set_jpg_APP(zr); - zr36060_set_jpg_COM(zr); - - reg = (1 << 7) /* Load=1 */ - |(0 << 0); /* SynRst=0 */ - zr36060_write_8(zr, 0x000, reg); - - /* wait for codec to unbusy */ - for (i = 0; i < 1000; ++i) { - reg = zr36060_read_8(zr, 0x001); - if ((reg & (1 << 7)) == 0) { - DEBUG(printk(KERN_DEBUG "060: loaded, loops=%u\n", i)); - return; - } - udelay(1000); - } - printk(KERN_INFO "060: stuck busy, statux=%02x\n", reg); -} - -static void zr36057_set_jpg(struct zoran *zr, enum zoran_codec_mode mode) -{ - struct tvnorm *tvn; - u32 reg; - int i; - - tvn = &tvnorms[zr->params.norm]; - - /* assert P_Reset */ - btwrite(0, ZR36057_JPC); - - /* re-initialize DMA ring stuff */ - zr->jpg_que_head = 0; - zr->jpg_dma_head = 0; - zr->jpg_dma_tail = 0; - zr->jpg_que_tail = 0; - zr->jpg_seq_num = 0; - for (i = 0; i < BUZ_NUM_STAT_COM; ++i) { - zr->stat_com[i] = 1; /* mark as unavailable to zr36057 */ - } - for (i = 0; i < zr->jpg_nbufs; i++) { - zr->jpg_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */ - } - - /* MJPEG compression mode */ - switch (mode) { - - case BUZ_MODE_MOTION_COMPRESS: - default: - reg = ZR36057_JMC_MJPGCmpMode; - break; - - case BUZ_MODE_MOTION_DECOMPRESS: - reg = ZR36057_JMC_MJPGExpMode; - reg |= ZR36057_JMC_SyncMstr; - /* RJ: The following is experimental - improves the output to screen */ - if (zr->params.VFIFO_FB) - reg |= ZR36057_JMC_VFIFO_FB; - break; - - case BUZ_MODE_STILL_COMPRESS: - reg = ZR36057_JMC_JPGCmpMode; - break; - - case BUZ_MODE_STILL_DECOMPRESS: - reg = ZR36057_JMC_JPGExpMode; - break; - - } - reg |= ZR36057_JMC_JPG; - if (zr->params.field_per_buff == 1) - reg |= ZR36057_JMC_Fld_per_buff; - btwrite(reg, ZR36057_JMC); - - /* vertical */ - btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR); - reg = (6 << ZR36057_VSP_VsyncSize) | (tvn->Ht << ZR36057_VSP_FrmTot); - btwrite(reg, ZR36057_VSP); - reg = ((zr->params.img_y + tvn->VStart) << ZR36057_FVAP_NAY) - | (zr->params.img_height << ZR36057_FVAP_PAY); - btwrite(reg, ZR36057_FVAP); - - /* horizontal */ - btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); - reg = ((tvn->Wt - 100) << ZR36057_HSP_HsyncStart) | (tvn->Wt << ZR36057_HSP_LineTot); - btwrite(reg, ZR36057_HSP); - reg = ((zr->params.img_x + tvn->HStart) << ZR36057_FHAP_NAX) - | (zr->params.img_width << ZR36057_FHAP_PAX); - btwrite(reg, ZR36057_FHAP); - - /* field process parameters */ - if (zr->params.odd_even) - reg = ZR36057_FPP_Odd_Even; - else - reg = 0; - btwrite(reg, ZR36057_FPP); - - /* Set proper VCLK Polarity, else colors will be wrong during playback */ - btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR); - - /* code base address and FIFO threshold */ - reg = virt_to_bus(zr->stat_com); - btwrite(reg, ZR36057_JCBA); - reg = 0x50; - btwrite(reg, ZR36057_JCFT); - - /* JPEG codec guest ID */ - reg = (1 << ZR36057_JCGI_JPEGuestID) | (0 << ZR36057_JCGI_JPEGuestReg); - btwrite(reg, ZR36057_JCGI); - - /* Code transfer guest ID */ - reg = (0 << ZR36057_MCTCR_CodGuestID) | (3 << ZR36057_MCTCR_CodGuestReg); - reg |= ZR36057_MCTCR_CFlush; - btwrite(reg, ZR36057_MCTCR); - - /* deassert P_Reset */ - btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); -} - -static void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode) -{ - static int zero = 0; - static int one = 1; - - switch (mode) { - - case BUZ_MODE_MOTION_COMPRESS: - zr36060_set_cap(zr, mode); - zr36057_set_jpg(zr, mode); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &one); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &zero); - - /* deassert P_Reset, assert Code transfer enable */ - btwrite(IRQ_MASK, ZR36057_ISR); - btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - break; - - case BUZ_MODE_MOTION_DECOMPRESS: - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &zero); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &one); - zr36060_set_cap(zr, mode); - zr36057_set_jpg(zr, mode); - - /* deassert P_Reset, assert Code transfer enable */ - btwrite(IRQ_MASK, ZR36057_ISR); - btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - break; - - case BUZ_MODE_IDLE: - default: - /* shut down processing */ - btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); - btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC); - btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC); - btand(~ZR36057_JMC_Go_en, ZR36057_JMC); - btwrite(0, ZR36057_ISR); - zr36060_reset(zr); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &one); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &zero); - break; - - } - zr->codec_mode = mode; -} - -/* - * Queue a MJPEG buffer for capture/playback - */ - -static int jpg_qbuf(struct zoran *zr, int frame, enum zoran_codec_mode mode) -{ - unsigned long flags; - int res; - - /* Check if buffers are allocated */ - - if (!zr->jpg_buffers_allocated) { - printk(KERN_ERR "%s: jpg_qbuf: buffers not yet allocated\n", zr->name); - return -ENOMEM; - } - /* Does the user want to stop streaming? */ - - if (frame < 0) { - if (zr->codec_mode == mode) { - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - return 0; - } else { - printk(KERN_ERR "%s: jpg_qbuf - stop streaming but not in streaming mode\n", zr->name); - return -EINVAL; - } - } - /* No grabbing outside the buffer range! */ - - if (frame >= zr->jpg_nbufs) { - printk(KERN_ERR "%s: jpg_qbuf: buffer %d out of range\n", zr->name, frame); - return -EINVAL; - } - /* what is the codec mode right now? */ - - if (zr->codec_mode == BUZ_MODE_IDLE) { - /* Ok load up the zr36060 and go */ - zr36057_enable_jpg(zr, mode); - } else if (zr->codec_mode != mode) { - /* wrong codec mode active - invalid */ - printk(KERN_ERR "%s: jpg_qbuf - codec in wrong mode\n", zr->name); - return -EINVAL; - } - spin_lock_irqsave(&zr->lock, flags); - - /* make sure a grab isn't going on currently with this buffer */ - - switch (zr->jpg_gbuf[frame].state) { - - default: - case BUZ_STATE_DMA: - case BUZ_STATE_PEND: - case BUZ_STATE_DONE: - res = -EBUSY; /* what are you doing? */ - break; - - case BUZ_STATE_USER: - /* since there is at least one unused buffer there's room for at least one more pend[] entry */ - zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = frame; - zr->jpg_gbuf[frame].state = BUZ_STATE_PEND; - zoran_feed_stat_com(zr); - res = 0; - break; - - } - - spin_unlock_irqrestore(&zr->lock, flags); - - /* Start the zr36060 when the first frame is queued */ - if (zr->jpg_que_head == 1) { - btor(ZR36057_JMC_Go_en, ZR36057_JMC); - btwrite(ZR36057_JPC_P_Reset | ZR36057_JPC_CodTrnsEn | ZR36057_JPC_Active, ZR36057_JPC); - } - return res; -} - -/* - * Sync on a MJPEG buffer - */ - -static int jpg_sync(struct zoran *zr, struct zoran_sync *bs) -{ - unsigned long flags; - int frame; - - if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && - zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { - return -EINVAL; - } - while (zr->jpg_que_tail == zr->jpg_dma_tail) { - interruptible_sleep_on(&zr->jpg_capq); - if (signal_pending(current)) - return -ERESTARTSYS; - } - - spin_lock_irqsave(&zr->lock, flags); - - frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME]; - - /* buffer should now be in BUZ_STATE_DONE */ - - if (zr->jpg_gbuf[frame].state != BUZ_STATE_DONE) - printk(KERN_ERR "%s: jpg_sync - internal error\n", zr->name); - - *bs = zr->jpg_gbuf[frame].bs; - zr->jpg_gbuf[frame].state = BUZ_STATE_USER; - - spin_unlock_irqrestore(&zr->lock, flags); - - return 0; -} - -/* when this is called the spinlock must be held */ -static void zoran_feed_stat_com(struct zoran *zr) -{ - /* move frames from pending queue to DMA */ - - int frame, i, max_stat_com; - - max_stat_com = (zr->params.TmpDcm == 1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1); - - while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com - && zr->jpg_dma_head != zr->jpg_que_head) { - - frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME]; - if (zr->params.TmpDcm == 1) { - /* fill 1 stat_com entry */ - i = zr->jpg_dma_head & BUZ_MASK_STAT_COM; - zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus; - } else { - /* fill 2 stat_com entries */ - i = (zr->jpg_dma_head & 1) * 2; - zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus; - zr->stat_com[i + 1] = zr->jpg_gbuf[frame].frag_tab_bus; - } - zr->jpg_gbuf[frame].state = BUZ_STATE_DMA; - zr->jpg_dma_head++; - - } -} - -/* when this is called the spinlock must be held */ -static void zoran_reap_stat_com(struct zoran *zr) -{ - /* move frames from DMA queue to done queue */ - - int i; - u32 stat_com; - unsigned int seq; - unsigned int dif; - int frame; - struct zoran_gbuffer *gbuf; - - /* In motion decompress we don't have a hardware frame counter, - we just count the interrupts here */ - - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) - zr->jpg_seq_num++; - - while (zr->jpg_dma_tail != zr->jpg_dma_head) { - if (zr->params.TmpDcm == 1) - i = zr->jpg_dma_tail & BUZ_MASK_STAT_COM; - else - i = (zr->jpg_dma_tail & 1) * 2 + 1; - - stat_com = zr->stat_com[i]; - - if ((stat_com & 1) == 0) { - return; - } - frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; - gbuf = &zr->jpg_gbuf[frame]; - get_fast_time(&gbuf->bs.timestamp); - - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - gbuf->bs.length = (stat_com & 0x7fffff) >> 1; - - /* update sequence number with the help of the counter in stat_com */ - - seq = stat_com >> 24; - dif = (seq - zr->jpg_seq_num) & 0xff; - zr->jpg_seq_num += dif; - } else { - gbuf->bs.length = 0; - } - gbuf->bs.seq = zr->params.TmpDcm == 2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num; - gbuf->state = BUZ_STATE_DONE; - - zr->jpg_dma_tail++; - } -} - -static void zoran_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - u32 stat, astat; - int count; - struct zoran *zr; - unsigned long flags; - - zr = (struct zoran *) dev_id; - count = 0; - - spin_lock_irqsave(&zr->lock, flags); - while (1) { - /* get/clear interrupt status bits */ - stat = btread(ZR36057_ISR); - astat = stat & IRQ_MASK; - if (!astat) { - break; - } - btwrite(astat, ZR36057_ISR); - IDEBUG(printk(BUZ_DEBUG "-%u: astat %08x stat %08x\n", zr->id, astat, stat)); - -#if (IRQ_MASK & ZR36057_ISR_GIRQ0) - if (astat & ZR36057_ISR_GIRQ0) { - - /* Interrupts may still happen when zr->v4l_memgrab_active is switched off. - We simply ignore them */ - - if (zr->v4l_memgrab_active) { - -/* A lot more checks should be here ... */ - if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0) - printk(KERN_WARNING "%s: BuzIRQ with SnapShot off ???\n", zr->name); - - if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) { - /* There is a grab on a frame going on, check if it has finished */ - - if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) { - /* it is finished, notify the user */ - - zr->v4l_gbuf[zr->v4l_grab_frame].state = BUZ_STATE_DONE; - zr->v4l_grab_frame = NO_GRAB_ACTIVE; - zr->v4l_grab_seq++; - zr->v4l_pend_tail++; - } - } - if (zr->v4l_grab_frame == NO_GRAB_ACTIVE) - wake_up_interruptible(&zr->v4l_capq); - - /* Check if there is another grab queued */ - - if (zr->v4l_grab_frame == NO_GRAB_ACTIVE && - zr->v4l_pend_tail != zr->v4l_pend_head) { - - int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; - u32 reg; - - zr->v4l_grab_frame = frame; - - /* Set zr36057 video front end and enable video */ - - /* Buffer address */ - - reg = zr->v4l_gbuf[frame].fbuffer_bus; - btwrite(reg, ZR36057_VDTR); - if (zr->video_interlace) - reg += zr->gbpl; - btwrite(reg, ZR36057_VDBR); - - /* video stride, status, and frame grab register */ - -#ifdef XAWTV_HACK - reg = (zr->gwidth > 720) ? ((zr->gwidth & ~3) - 720) * zr->gbpl / zr->gwidth : 0; -#else - reg = 0; -#endif - if (zr->video_interlace) - reg += zr->gbpl; - reg = (reg << ZR36057_VSSFGR_DispStride); - reg |= ZR36057_VSSFGR_VidOvf; - reg |= ZR36057_VSSFGR_SnapShot; - reg |= ZR36057_VSSFGR_FrameGrab; - btwrite(reg, ZR36057_VSSFGR); - - btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); - } - } - } -#endif /* (IRQ_MASK & ZR36057_ISR_GIRQ0) */ - -#if (IRQ_MASK & ZR36057_ISR_GIRQ1) - if (astat & ZR36057_ISR_GIRQ1) { - unsigned csr = zr36060_read_8(zr, 0x001); - unsigned isr = zr36060_read_8(zr, 0x008); - - IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_GIRQ1 60_code=%02x 60_intr=%02x\n", - zr->name, csr, isr)); - - btand(~ZR36057_ICR_GIRQ1, ZR36057_ICR); - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - } -#endif /* (IRQ_MASK & ZR36057_ISR_GIRQ1) */ - -#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ) - if (astat & ZR36057_ISR_CodRepIRQ) { - IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", zr->name)); - btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR); - } -#endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */ - -#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) - if ((astat & ZR36057_ISR_JPEGRepIRQ) && - (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) { - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - } -#endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */ - - count++; - if (count > 10) { - printk(KERN_WARNING "%s: irq loop %d\n", zr->name, count); - if (count > 20) { - btwrite(0, ZR36057_ICR); - printk(KERN_ERR "%s: IRQ lockup, cleared int mask\n", zr->name); - break; - } - } - } - spin_unlock_irqrestore(&zr->lock, flags); -} - -/* Check a zoran_params struct for correctness, insert default params */ - -static int zoran_check_params(struct zoran *zr, struct zoran_params *params) -{ - int err = 0, err0 = 0; - - /* insert constant params */ - - params->major_version = MAJOR_VERSION; - params->minor_version = MINOR_VERSION; - - /* Check input and norm */ - - if (params->input != 0 && params->input != 1) { - err++; - } - if (params->norm != VIDEO_MODE_PAL && params->norm != VIDEO_MODE_NTSC) { - err++; - } - /* Check decimation, set default values for decimation = 1, 2, 4 */ - - switch (params->decimation) { - case 1: - - params->HorDcm = 1; - params->VerDcm = 1; - params->TmpDcm = 1; - params->field_per_buff = 2; - - params->img_x = 0; - params->img_y = 0; - params->img_width = 720; - params->img_height = tvnorms[params->norm].Ha / 2; - break; - - case 2: - - params->HorDcm = 2; - params->VerDcm = 1; - params->TmpDcm = 2; - params->field_per_buff = 1; - - params->img_x = 8; - params->img_y = 0; - params->img_width = 704; - params->img_height = tvnorms[params->norm].Ha / 2; - break; - - case 4: - - params->HorDcm = 4; - params->VerDcm = 2; - params->TmpDcm = 2; - params->field_per_buff = 1; - - params->img_x = 8; - params->img_y = 0; - params->img_width = 704; - params->img_height = tvnorms[params->norm].Ha / 2; - break; - - case 0: - - /* We have to check the data the user has set */ - - if (params->HorDcm != 1 && params->HorDcm != 2 && params->HorDcm != 4) - err0++; - if (params->VerDcm != 1 && params->VerDcm != 2) - err0++; - if (params->TmpDcm != 1 && params->TmpDcm != 2) - err0++; - if (params->field_per_buff != 1 && params->field_per_buff != 2) - err0++; - - if (params->img_x < 0) - err0++; - if (params->img_y < 0) - err0++; - if (params->img_width < 0) - err0++; - if (params->img_height < 0) - err0++; - if (params->img_x + params->img_width > 720) - err0++; - if (params->img_y + params->img_height > tvnorms[params->norm].Ha / 2) - err0++; - if (params->img_width % (16 * params->HorDcm) != 0) - err0++; - if (params->img_height % (8 * params->VerDcm) != 0) - err0++; - - if (err0) { - err++; - } - break; - - default: - err++; - break; - } - - if (params->quality > 100) - params->quality = 100; - if (params->quality < 5) - params->quality = 5; - - if (params->APPn < 0) - params->APPn = 0; - if (params->APPn > 15) - params->APPn = 15; - if (params->APP_len < 0) - params->APP_len = 0; - if (params->APP_len > 60) - params->APP_len = 60; - if (params->COM_len < 0) - params->COM_len = 0; - if (params->COM_len > 60) - params->COM_len = 60; - - if (err) - return -EINVAL; - - return 0; - -} -static void zoran_open_init_params(struct zoran *zr) -{ - int i; - - /* Per default, map the V4L Buffers */ - - zr->map_mjpeg_buffers = 0; - - /* User must explicitly set a window */ - - zr->window_set = 0; - - zr->window.x = 0; - zr->window.y = 0; - zr->window.width = 0; - zr->window.height = 0; - zr->window.chromakey = 0; - zr->window.flags = 0; - zr->window.clips = NULL; - zr->window.clipcount = 0; - - zr->video_interlace = 0; - - zr->v4l_memgrab_active = 0; - zr->v4l_overlay_active = 0; - - zr->v4l_grab_frame = NO_GRAB_ACTIVE; - zr->v4l_grab_seq = 0; - - zr->gwidth = 0; - zr->gheight = 0; - zr->gformat = 0; - zr->gbpl = 0; - - /* DMA ring stuff for V4L */ - - zr->v4l_pend_tail = 0; - zr->v4l_pend_head = 0; - for (i = 0; i < v4l_nbufs; i++) { - zr->v4l_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */ - } - - /* Set necessary params and call zoran_check_params to set the defaults */ - - zr->params.decimation = 1; - - zr->params.quality = 50; /* default compression factor 8 */ - zr->params.odd_even = 1; - - zr->params.APPn = 0; - zr->params.APP_len = 0; /* No APPn marker */ - for (i = 0; i < 60; i++) - zr->params.APP_data[i] = 0; - - zr->params.COM_len = 0; /* No COM marker */ - for (i = 0; i < 60; i++) - zr->params.COM_data[i] = 0; - - zr->params.VFIFO_FB = 0; - - memset(zr->params.reserved, 0, sizeof(zr->params.reserved)); - - zr->params.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT; - - i = zoran_check_params(zr, &zr->params); - if (i) - printk(KERN_ERR "%s: zoran_open_init_params internal error\n", zr->name); -} - -/* - * Open a buz card. Right now the flags stuff is just playing - */ - -static int zoran_open(struct video_device *dev, int flags) -{ - struct zoran *zr = (struct zoran *) dev; - - DEBUG(printk(KERN_INFO ": zoran_open\n")); - - switch (flags) { - - case 0: - if (zr->user) - return -EBUSY; - zr->user++; - - if (v4l_fbuffer_alloc(zr) < 0) { - zr->user--; - return -ENOMEM; - } - /* default setup */ - - zoran_open_init_params(zr); - - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - - btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts - - btor(ZR36057_ICR_IntPinEn, ZR36057_ICR); - - break; - - default: - return -EBUSY; - - } - MOD_INC_USE_COUNT; - return 0; -} - -static void zoran_close(struct video_device *dev) -{ - struct zoran *zr = (struct zoran *) dev; - - DEBUG(printk(KERN_INFO ": zoran_close\n")); - - /* disable interrupts */ - btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); - - /* wake up sleeping beauties */ - wake_up_interruptible(&zr->v4l_capq); - wake_up_interruptible(&zr->jpg_capq); - - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - zr36057_set_memgrab(zr, 0); - if (zr->v4l_overlay_active) - zr36057_overlay(zr, 0); - - zr->user--; - - v4l_fbuffer_free(zr); - jpg_fbuffer_free(zr); - zr->jpg_nbufs = 0; - - MOD_DEC_USE_COUNT; - DEBUG(printk(KERN_INFO ": zoran_close done\n")); -} - - -static long zoran_read(struct video_device *dev, char *buf, unsigned long count, int nonblock) -{ - return -EINVAL; -} - -static long zoran_write(struct video_device *dev, const char *buf, unsigned long count, int nonblock) -{ - return -EINVAL; -} - -/* - * ioctl routine - */ - - -static int zoran_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct zoran *zr = (struct zoran *) dev; - - switch (cmd) { - - case VIDIOCGCAP: - { - struct video_capability b; - IOCTL_DEBUG(printk("buz ioctl VIDIOCGCAP\n")); - strncpy(b.name, zr->video_dev.name, sizeof(b.name)); - b.type = VID_TYPE_CAPTURE | - VID_TYPE_OVERLAY | - VID_TYPE_CLIPPING | - VID_TYPE_FRAMERAM | - VID_TYPE_SCALES; - /* theoretically we could also flag VID_TYPE_SUBCAPTURE - but this is not even implemented in the BTTV driver */ - - b.channels = 2; /* composite, svhs */ - b.audios = 0; - b.maxwidth = BUZ_MAX_WIDTH; - b.maxheight = BUZ_MAX_HEIGHT; - b.minwidth = BUZ_MIN_WIDTH; - b.minheight = BUZ_MIN_HEIGHT; - if (copy_to_user(arg, &b, sizeof(b))) { - return -EFAULT; - } - return 0; - } - - case VIDIOCGCHAN: - { - struct video_channel v; - - if (copy_from_user(&v, arg, sizeof(v))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl VIDIOCGCHAN for channel %d\n", v.channel)); - switch (v.channel) { - case 0: - strcpy(v.name, "Composite"); - break; - case 1: - strcpy(v.name, "SVHS"); - break; - default: - return -EINVAL; - } - v.tuners = 0; - v.flags = 0; - v.type = VIDEO_TYPE_CAMERA; - v.norm = zr->params.norm; - if (copy_to_user(arg, &v, sizeof(v))) { - return -EFAULT; - } - return 0; - } - - /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: - - * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input." - * ^^^^^^^ - * The famos BTTV driver has it implemented with a struct video_channel argument - * and we follow it for compatibility reasons - * - * BTW: this is the only way the user can set the norm! - */ - - case VIDIOCSCHAN: - { - struct video_channel v; - int input; - int on, res; - - if (copy_from_user(&v, arg, sizeof(v))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl VIDIOCSCHAN: channel=%d, norm=%d\n", v.channel, v.norm)); - switch (v.channel) { - case 0: - input = 3; - break; - case 1: - input = 7; - break; - default: - return -EINVAL; - } - - if (v.norm != VIDEO_MODE_PAL - && v.norm != VIDEO_MODE_NTSC) { - return -EINVAL; - } - zr->params.norm = v.norm; - zr->params.input = v.channel; - - /* We switch overlay off and on since a change in the norm - needs different VFE settings */ - - on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; - if (on) - zr36057_overlay(zr, 0); - - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); - - if (on) - zr36057_overlay(zr, 1); - - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); - if (res) - return res; - - return 0; - } - - case VIDIOCGTUNER: - case VIDIOCSTUNER: - return -EINVAL; - - case VIDIOCGPICT: - { - struct video_picture p = zr->picture; - - IOCTL_DEBUG(printk("buz ioctl VIDIOCGPICT\n")); - p.depth = zr->buffer.depth; - switch (zr->buffer.depth) { - case 15: - p.palette = VIDEO_PALETTE_RGB555; - break; - - case 16: - p.palette = VIDEO_PALETTE_RGB565; - break; - - case 24: - p.palette = VIDEO_PALETTE_RGB24; - break; - - case 32: - p.palette = VIDEO_PALETTE_RGB32; - break; - } - - if (copy_to_user(arg, &p, sizeof(p))) { - return -EFAULT; - } - return 0; - } - - case VIDIOCSPICT: - { - struct video_picture p; - - if (copy_from_user(&p, arg, sizeof(p))) { - return -EFAULT; - } - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); - IOCTL_DEBUG(printk("buz ioctl VIDIOCSPICT bri=%d hue=%d col=%d con=%d dep=%d pal=%d\n", - p.brightness, p.hue, p.colour, p.contrast, p.depth, p.palette)); - /* The depth and palette values have no meaning to us, - should we return -EINVAL if they don't fit ? */ - zr->picture = p; - return 0; - } - - case VIDIOCCAPTURE: - { - int v, res; - - if (copy_from_user(&v, arg, sizeof(v))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl VIDIOCCAPTURE: %d\n", v)); - /* If there is nothing to do, return immediatly */ - - if ((v && zr->v4l_overlay_active) || (!v && !zr->v4l_overlay_active)) - return 0; - - if (v == 0) { - zr->v4l_overlay_active = 0; - if (!zr->v4l_memgrab_active) - zr36057_overlay(zr, 0); - /* When a grab is running, the video simply won't be switched on any more */ - } else { - if (!zr->buffer_set || !zr->window_set) { - return -EINVAL; - } - zr->v4l_overlay_active = 1; - if (!zr->v4l_memgrab_active) - zr36057_overlay(zr, 1); - /* When a grab is running, the video will be switched on when grab is finished */ - } - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); - if (res) - return res; - return 0; - } - - case VIDIOCGWIN: - { - IOCTL_DEBUG(printk("buz ioctl VIDIOCGWIN\n")); - if (copy_to_user(arg, &zr->window, sizeof(zr->window))) { - return -EFAULT; - } - return 0; - } - - case VIDIOCSWIN: - { - struct video_clip *vcp; - struct video_window vw; - int on, end, res; - - if (copy_from_user(&vw, arg, sizeof(vw))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl VIDIOCSWIN: x=%d y=%d w=%d h=%d clipcount=%d\n", vw.x, vw.y, vw.width, vw.height, vw.clipcount)); - if (!zr->buffer_set) { - return -EINVAL; - } - /* - * The video front end needs 4-byte alinged line sizes, we correct that - * silently here if necessary - */ - - if (zr->buffer.depth == 15 || zr->buffer.depth == 16) { - end = (vw.x + vw.width) & ~1; /* round down */ - vw.x = (vw.x + 1) & ~1; /* round up */ - vw.width = end - vw.x; - } - if (zr->buffer.depth == 24) { - end = (vw.x + vw.width) & ~3; /* round down */ - vw.x = (vw.x + 3) & ~3; /* round up */ - vw.width = end - vw.x; - } -#if 0 - // At least xawtv seems to care about the following - just leave it away - /* - * Also corrected silently (as long as window fits at all): - * video not fitting the screen - */ -#if 0 - if (vw.x < 0 || vw.y < 0 || vw.x + vw.width > zr->buffer.width || - vw.y + vw.height > zr->buffer.height) { - printk(BUZ_ERR ": VIDIOCSWIN: window does not fit frame buffer: %dx%d+%d*%d\n", - vw.width, vw.height, vw.x, vw.y); - return -EINVAL; - } -#else - if (vw.x < 0) - vw.x = 0; - if (vw.y < 0) - vw.y = 0; - if (vw.x + vw.width > zr->buffer.width) - vw.width = zr->buffer.width - vw.x; - if (vw.y + vw.height > zr->buffer.height) - vw.height = zr->buffer.height - vw.y; -#endif -#endif - - /* Check for vaild parameters */ - if (vw.width < BUZ_MIN_WIDTH || vw.height < BUZ_MIN_HEIGHT || - vw.width > BUZ_MAX_WIDTH || vw.height > BUZ_MAX_HEIGHT) { - return -EINVAL; - } -#ifdef XAWTV_HACK - if (vw.width > 720) - vw.width = 720; -#endif - - zr->window.x = vw.x; - zr->window.y = vw.y; - zr->window.width = vw.width; - zr->window.height = vw.height; - zr->window.chromakey = 0; - zr->window.flags = 0; // RJ: Is this intended for interlace on/off ? - - zr->window.clips = NULL; - zr->window.clipcount = vw.clipcount; - - /* - * If an overlay is running, we have to switch it off - * and switch it on again in order to get the new settings in effect. - * - * We also want to avoid that the overlay mask is written - * when an overlay is running. - */ - - on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; - if (on) - zr36057_overlay(zr, 0); - - /* - * Write the overlay mask if clips are wanted. - */ - if (vw.clipcount) { - vcp = vmalloc(sizeof(struct video_clip) * (vw.clipcount + 4)); - if (vcp == NULL) { - return -ENOMEM; - } - if (copy_from_user(vcp, vw.clips, sizeof(struct video_clip) * vw.clipcount)) { - vfree(vcp); - return -EFAULT; - } - write_overlay_mask(zr, vcp, vw.clipcount); - vfree(vcp); - } - if (on) - zr36057_overlay(zr, 1); - zr->window_set = 1; - - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); - if (res) - return res; - - return 0; - } - - case VIDIOCGFBUF: - { - IOCTL_DEBUG(printk("buz ioctl VIDIOCGFBUF\n")); - if (copy_to_user(arg, &zr->buffer, sizeof(zr->buffer))) { - return -EFAULT; - } - return 0; - } - - case VIDIOCSFBUF: - { - struct video_buffer v; - - if (!capable(CAP_SYS_ADMIN) - || !capable(CAP_SYS_RAWIO)) - return -EPERM; - - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - - IOCTL_DEBUG(printk("buz ioctl VIDIOCSFBUF: base=0x%x w=%d h=%d depth=%d bpl=%d\n", (u32) v.base, v.width, v.height, v.depth, v.bytesperline)); - if (zr->v4l_overlay_active) { - /* Has the user gotten crazy ... ? */ - return -EINVAL; - } - if (v.depth != 15 - && v.depth != 16 - && v.depth != 24 - && v.depth != 32) { - return -EINVAL; - } - if (v.height <= 0 || v.width <= 0 || v.bytesperline <= 0) { - return -EINVAL; - } - if (v.bytesperline & 3) { - return -EINVAL; - } - if (v.base) { - zr->buffer.base = (void *) ((unsigned long) v.base & ~3); - } - zr->buffer.height = v.height; - zr->buffer.width = v.width; - zr->buffer.depth = v.depth; - zr->buffer.bytesperline = v.bytesperline; - - if (zr->buffer.base) - zr->buffer_set = 1; - zr->window_set = 0; /* The user should set new window parameters */ - return 0; - } - - /* RJ: what is VIDIOCKEY intended to do ??? */ - - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - - case VIDIOCSYNC: - { - int v; - - if (copy_from_user(&v, arg, sizeof(v))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl VIDIOCSYNC %d\n", v)); - return v4l_sync(zr, v); - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - - if (copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl VIDIOCMCAPTURE frame=%d geom=%dx%d fmt=%d\n", - vm.frame, vm.height, vm.width, vm.format)); - return v4l_grab(zr, &vm); - } - - case VIDIOCGMBUF: - { - struct video_mbuf vm; - int i; - - IOCTL_DEBUG(printk("buz ioctl VIDIOCGMBUF\n")); - - vm.size = v4l_nbufs * v4l_bufsize; - vm.frames = v4l_nbufs; - for (i = 0; i < v4l_nbufs; i++) { - vm.offsets[i] = i * v4l_bufsize; - } - - /* The next mmap will map the V4L buffers */ - zr->map_mjpeg_buffers = 0; - - if (copy_to_user(arg, &vm, sizeof(vm))) { - return -EFAULT; - } - return 0; - } - - case VIDIOCGUNIT: - { - struct video_unit vu; - - IOCTL_DEBUG(printk("buz ioctl VIDIOCGUNIT\n")); - vu.video = zr->video_dev.minor; - vu.vbi = VIDEO_NO_UNIT; - vu.radio = VIDEO_NO_UNIT; - vu.audio = VIDEO_NO_UNIT; - vu.teletext = VIDEO_NO_UNIT; - if (copy_to_user(arg, &vu, sizeof(vu))) - return -EFAULT; - return 0; - } - - /* - * RJ: In principal we could support subcaptures for V4L grabbing. - * Not even the famous BTTV driver has them, however. - * If there should be a strong demand, one could consider - * to implement them. - */ - case VIDIOCGCAPTURE: - case VIDIOCSCAPTURE: - return -EINVAL; - - case BUZIOC_G_PARAMS: - { - IOCTL_DEBUG(printk("buz ioctl BUZIOC_G_PARAMS\n")); - if (copy_to_user(arg, &(zr->params), sizeof(zr->params))) - return -EFAULT; - return 0; - } - - case BUZIOC_S_PARAMS: - { - struct zoran_params bp; - int input, on; - - if (zr->codec_mode != BUZ_MODE_IDLE) { - return -EINVAL; - } - if (copy_from_user(&bp, arg, sizeof(bp))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl BUZIOC_S_PARAMS\n")); - - /* Check the params first before overwriting our internal values */ - - if (zoran_check_params(zr, &bp)) - return -EINVAL; - - zr->params = bp; - - /* Make changes of input and norm go into effect immediatly */ - - /* We switch overlay off and on since a change in the norm - needs different VFE settings */ - - on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; - if (on) - zr36057_overlay(zr, 0); - - input = zr->params.input == 0 ? 3 : 7; - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); - - if (on) - zr36057_overlay(zr, 1); - - if (copy_to_user(arg, &bp, sizeof(bp))) { - return -EFAULT; - } - return 0; - } - - case BUZIOC_REQBUFS: - { - struct zoran_requestbuffers br; - - if (zr->jpg_buffers_allocated) { - return -EINVAL; - } - if (copy_from_user(&br, arg, sizeof(br))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl BUZIOC_REQBUFS count = %lu size=%lu\n", - br.count, br.size)); - /* Enforce reasonable lower and upper limits */ - if (br.count < 4) - br.count = 4; /* Could be choosen smaller */ - if (br.count > BUZ_MAX_FRAME) - br.count = BUZ_MAX_FRAME; - br.size = PAGE_ALIGN(br.size); - if (br.size < 8192) - br.size = 8192; /* Arbitrary */ - /* br.size is limited by 1 page for the stat_com tables to a Maximum of 2 MB */ - if (br.size > (512 * 1024)) - br.size = (512 * 1024); /* 512 K should be enough */ - if (zr->need_contiguous && br.size > MAX_KMALLOC_MEM) - br.size = MAX_KMALLOC_MEM; - - zr->jpg_nbufs = br.count; - zr->jpg_bufsize = br.size; - - if (jpg_fbuffer_alloc(zr)) - return -ENOMEM; - - /* The next mmap will map the MJPEG buffers */ - zr->map_mjpeg_buffers = 1; - - if (copy_to_user(arg, &br, sizeof(br))) { - return -EFAULT; - } - return 0; - } - - case BUZIOC_QBUF_CAPT: - { - int nb; - - if (copy_from_user((void *) &nb, (void *) arg, sizeof(int))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl BUZIOC_QBUF_CAPT %d\n", nb)); - return jpg_qbuf(zr, nb, BUZ_MODE_MOTION_COMPRESS); - } - - case BUZIOC_QBUF_PLAY: - { - int nb; - - if (copy_from_user((void *) &nb, (void *) arg, sizeof(int))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl BUZIOC_QBUF_PLAY %d\n", nb)); - return jpg_qbuf(zr, nb, BUZ_MODE_MOTION_DECOMPRESS); - } - - case BUZIOC_SYNC: - { - struct zoran_sync bs; - int res; - - IOCTL_DEBUG(printk("buz ioctl BUZIOC_SYNC\n")); - res = jpg_sync(zr, &bs); - if (copy_to_user(arg, &bs, sizeof(bs))) { - return -EFAULT; - } - return res; - } - - case BUZIOC_G_STATUS: - { - struct zoran_status bs; - int norm, input, status; - - if (zr->codec_mode != BUZ_MODE_IDLE) { - return -EINVAL; - } - if (copy_from_user(&bs, arg, sizeof(bs))) { - return -EFAULT; - } - IOCTL_DEBUG(printk("buz ioctl BUZIOC_G_STATUS\n")); - switch (bs.input) { - case 0: - input = 3; - break; - case 1: - input = 7; - break; - default: - return -EINVAL; - } - - /* Set video norm to VIDEO_MODE_AUTO */ - - norm = VIDEO_MODE_AUTO; - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); - - /* sleep 1 second */ - - schedule_timeout(HZ); - - /* Get status of video decoder */ - - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_STATUS, &status); - bs.signal = (status & DECODER_STATUS_GOOD) ? 1 : 0; - bs.norm = (status & DECODER_STATUS_NTSC) ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL; - bs.color = (status & DECODER_STATUS_COLOR) ? 1 : 0; - - /* restore previous input and norm */ - input = zr->params.input == 0 ? 3 : 7; - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); - - if (copy_to_user(arg, &bs, sizeof(bs))) { - return -EFAULT; - } - return 0; - } - - default: - return -ENOIOCTLCMD; - - } - return 0; -} - - -/* - * This maps the buffers to user space. - * - * Depending on the state of zr->map_mjpeg_buffers - * the V4L or the MJPEG buffers are mapped - * - */ - -static int zoran_mmap(struct video_device *dev, const char *adr, unsigned long size) -{ - struct zoran *zr = (struct zoran *) dev; - unsigned long start = (unsigned long) adr; - unsigned long page, pos, todo, fraglen; - int i, j; - - if (zr->map_mjpeg_buffers) { - /* Map the MJPEG buffers */ - - if (!zr->jpg_buffers_allocated) { - return -ENOMEM; - } - if (size > zr->jpg_nbufs * zr->jpg_bufsize) { - return -EINVAL; - } - - for (i = 0; i < zr->jpg_nbufs; i++) { - for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { - fraglen = (zr->jpg_gbuf[i].frag_tab[2 * j + 1] & ~1) << 1; - todo = size; - if (todo > fraglen) - todo = fraglen; - pos = (unsigned long) zr->jpg_gbuf[i].frag_tab[2 * j]; - page = virt_to_phys(bus_to_virt(pos)); /* should just be pos on i386 */ - if (remap_page_range(start, page, todo, PAGE_SHARED)) { - printk(KERN_ERR "%s: zoran_mmap(V4L): remap_page_range failed\n", zr->name); - return -EAGAIN; - } - size -= todo; - start += todo; - if (size == 0) - break; - if (zr->jpg_gbuf[i].frag_tab[2 * j + 1] & 1) - break; /* was last fragment */ - } - if (size == 0) - break; - } - } else { - /* Map the V4L buffers */ - - if (size > v4l_nbufs * v4l_bufsize) { - return -EINVAL; - } - - for (i = 0; i < v4l_nbufs; i++) { - todo = size; - if (todo > v4l_bufsize) - todo = v4l_bufsize; - page = zr->v4l_gbuf[i].fbuffer_phys; - DEBUG(printk("V4L remap page range %d 0x%x %d to 0x%x\n", i, page, todo, start)); - if (remap_page_range(start, page, todo, PAGE_SHARED)) { - printk(KERN_ERR "%s: zoran_mmap(V4L): remap_page_range failed\n", zr->name); - return -EAGAIN; - } - size -= todo; - start += todo; - if (size == 0) - break; - } - } - return 0; -} - -static int zoran_init_done(struct video_device *dev) -{ - return 0; -} - -static struct video_device zoran_template = -{ - BUZ_NAME, - VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | - VID_TYPE_SCALES | VID_TYPE_SUBCAPTURE, - VID_HARDWARE_ZR36067, - zoran_open, - zoran_close, - zoran_read, - zoran_write, - NULL, - zoran_ioctl, - zoran_mmap, - zoran_init_done, - NULL, - 0, - 0 -}; - -static int zr36057_init(int i) -{ - struct zoran *zr = &zoran[i]; - unsigned long mem; - unsigned mem_needed; - int j; - int rev; - - /* reset zr36057 */ - btwrite(0, ZR36057_SPGPPCR); - mdelay(10); - - /* default setup of all parameters which will persist beetween opens */ - - zr->user = 0; - - init_waitqueue_head(&zr->v4l_capq); - init_waitqueue_head(&zr->jpg_capq); - - zr->map_mjpeg_buffers = 0; /* Map V4L buffers by default */ - - zr->jpg_nbufs = 0; - zr->jpg_bufsize = 0; - zr->jpg_buffers_allocated = 0; - - zr->buffer_set = 0; /* Flag if frame buffer has been set */ - zr->buffer.base = (void *) vidmem; - zr->buffer.width = 0; - zr->buffer.height = 0; - zr->buffer.depth = 0; - zr->buffer.bytesperline = 0; - - zr->params.norm = default_norm ? 1 : 0; /* Avoid nonsense settings from user */ - zr->params.input = default_input ? 1 : 0; /* Avoid nonsense settings from user */ - zr->video_interlace = 0; - - /* Should the following be reset at every open ? */ - - zr->picture.colour = 32768; - zr->picture.brightness = 32768; - zr->picture.hue = 32768; - zr->picture.contrast = 32768; - zr->picture.whiteness = 0; - zr->picture.depth = 0; - zr->picture.palette = 0; - - for (j = 0; j < VIDEO_MAX_FRAME; j++) { - zr->v4l_gbuf[i].fbuffer = 0; - zr->v4l_gbuf[i].fbuffer_phys = 0; - zr->v4l_gbuf[i].fbuffer_bus = 0; - } - - zr->stat_com = 0; - - /* default setup (will be repeated at every open) */ - - zoran_open_init_params(zr); - - /* allocate memory *before* doing anything to the hardware in case allocation fails */ - - /* STAT_COM table and overlay mask */ - - mem_needed = (BUZ_NUM_STAT_COM + ((BUZ_MAX_WIDTH + 31) / 32) * BUZ_MAX_HEIGHT) * 4; - mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL); - if (!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 */ - } - zr->overlay_mask = (u32 *) (mem + BUZ_NUM_STAT_COM * 4); - - /* Initialize zr->jpg_gbuf */ - - for (j = 0; j < BUZ_MAX_FRAME; j++) { - zr->jpg_gbuf[j].frag_tab = 0; - zr->jpg_gbuf[j].frag_tab_bus = 0; - zr->jpg_gbuf[j].state = BUZ_STATE_USER; - zr->jpg_gbuf[j].bs.frame = j; - } - - /* take zr36057 out of reset now */ - btwrite(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR); - mdelay(10); - - /* stop all DMA processes */ - btwrite(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); - /* assert P_Reset */ - btwrite(0, ZR36057_JPC); - - switch(zr->board) - { - case BOARD_BUZ: - - /* set up GPIO direction */ - btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR); - - /* Set up guest bus timing - Guests 0..3 Tdur=12, Trec=3 */ - btwrite((GPIO_MASK << 24) | 0x8888, ZR36057_GPPGCR1); - mdelay(10); - - /* reset video decoder */ - - GPIO(zr, 0, 0); - mdelay(10); - GPIO(zr, 0, 1); - mdelay(10); - - /* reset JPEG codec */ - zr36060_sleep(zr, 0); - mdelay(10); - zr36060_reset(zr); - mdelay(10); - - /* display codec revision */ - if ((rev=zr36060_read_8(zr, 0x022)) == 0x33) { - printk(KERN_INFO "%s: Zoran ZR36060 (rev %d)\n", - zr->name, zr36060_read_8(zr, 0x023)); - } else { - printk(KERN_ERR "%s: Zoran ZR36060 not found (Rev=%d)\n", zr->name, rev); - kfree((void *) zr->stat_com); - return -1; - } - break; - - case BOARD_LML33: -// btwrite(btread(ZR36057_SPGPPCR)&~ZR36057_SPGPPCR_SoftReset , ZR36057_SPGPPCR); -// udelay(100); -// btwrite(btread(ZR36057_SPGPPCR)|ZR36057_SPGPPCR_SoftReset , ZR36057_SPGPPCR); -// udelay(1000); - - /* - * Set up the GPIO direction - */ - btwrite(btread(ZR36057_SPGPPCR_SoftReset)|0 , ZR36057_SPGPPCR); - /* Set up guest bus timing - Guests 0..2 Tdur=12, Trec=3 */ - btwrite(0xFF00F888, ZR36057_GPPGCR1); - mdelay(10); - GPIO(zr, 5, 0); /* Analog video bypass */ - udelay(3000); - GPIO(zr, 0, 0); /* Reset 819 */ - udelay(3000); - GPIO(zr, 0, 1); /* 819 back */ - udelay(3000); - /* reset JPEG codec */ - zr36060_sleep(zr, 0); - udelay(3000); - zr36060_reset(zr); - udelay(3000); - - /* display codec revision */ - if ((rev=zr36060_read_8(zr, 0x022)) == 0x33) { - printk(KERN_INFO "%s: Zoran ZR36060 (rev %d)\n", - zr->name, zr36060_read_8(zr, 0x023)); - } else { - printk(KERN_ERR "%s: Zoran ZR36060 not found (rev=%d)\n", zr->name, rev); - kfree((void *) zr->stat_com); - return -1; - } - break; - } - /* i2c */ - memcpy(&zr->i2c, &zoran_i2c_bus_template, sizeof(struct i2c_bus)); - sprintf(zr->i2c.name, "zoran%u", zr->id); - zr->i2c.data = zr; - if (i2c_register_bus(&zr->i2c) < 0) { - kfree((void *) zr->stat_com); - return -1; - } - /* - * Now add the template and register the device unit. - */ - memcpy(&zr->video_dev, &zoran_template, sizeof(zoran_template)); - sprintf(zr->video_dev.name, "zoran%u", zr->id); - if (video_register_device(&zr->video_dev, VFL_TYPE_GRABBER) < 0) { - i2c_unregister_bus(&zr->i2c); - kfree((void *) zr->stat_com); - return -1; - } - /* toggle JPEG codec sleep to sync PLL */ - zr36060_sleep(zr, 1); - mdelay(10); - zr36060_sleep(zr, 0); - mdelay(10); - - /* Enable bus-mastering */ - pci_set_master(zr->pci_dev); - - j = zr->params.input == 0 ? 3 : 7; - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &j); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); - i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); - - /* set individual interrupt enables (without GIRQ0) - but don't global enable until zoran_open() */ - - btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ0, ZR36057_ICR); - - if(request_irq(zr->pci_dev->irq, zoran_irq, - SA_SHIRQ | SA_INTERRUPT, zr->name, (void *) zr)<0) - { - printk(KERN_ERR "%s: Can't assign irq.\n", zr->name); - video_unregister_device(&zr->video_dev); - i2c_unregister_bus(&zr->i2c); - kfree((void *) zr->stat_com); - return -1; - } - zr->initialized = 1; - return 0; -} - - - -static void release_zoran(void) -{ - u8 command; - int i; - struct zoran *zr; - - for (i = 0; i < zoran_num; i++) { - zr = &zoran[i]; - - if (!zr->initialized) - continue; - - /* unregister i2c_bus */ - i2c_unregister_bus((&zr->i2c)); - - /* disable PCI bus-mastering */ - pci_read_config_byte(zr->pci_dev, PCI_COMMAND, &command); - command &= ~PCI_COMMAND_MASTER; - pci_write_config_byte(zr->pci_dev, PCI_COMMAND, command); - - /* put chip into reset */ - btwrite(0, ZR36057_SPGPPCR); - - free_irq(zr->pci_dev->irq, zr); - - /* unmap and free memory */ - - kfree((void *) zr->stat_com); - - iounmap(zr->zr36057_mem); - - video_unregister_device(&zr->video_dev); - } -} - -/* - * Scan for a Buz card (actually for the PCI controller ZR36057), - * request the irq and map the io memory - */ - -static int find_zr36057(void) -{ - unsigned char latency; - struct zoran *zr; - struct pci_dev *dev = NULL; - - zoran_num = 0; - - while (zoran_num < BUZ_MAX - && (dev = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) { - zr = &zoran[zoran_num]; - zr->pci_dev = dev; - zr->zr36057_mem = NULL; - zr->id = zoran_num; - sprintf(zr->name, "zoran%u", zr->id); - - spin_lock_init(&zr->lock); - - if (pci_enable_device(dev)) - continue; - - zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); - pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); - if (zr->revision < 2) { - printk(KERN_INFO "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n", - zr->name, zr->revision, zr->pci_dev->irq, zr->zr36057_adr); - } else { - unsigned short ss_vendor_id, ss_id; - - ss_vendor_id = zr->pci_dev->subsystem_vendor; - ss_id = zr->pci_dev->subsystem_device; - printk(KERN_INFO "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n", - zr->name, zr->revision, zr->pci_dev->irq, zr->zr36057_adr); - printk(KERN_INFO "%s: subsystem vendor=0x%04x id=0x%04x\n", - zr->name, ss_vendor_id, ss_id); - if(ss_vendor_id==0xFF10 && ss_id == 0xDE41) - { - zr->board = BOARD_LML33; - printk(KERN_INFO "%s: LML33 detected.\n", zr->name); - } - } - - zr->zr36057_mem = ioremap(zr->zr36057_adr, 0x1000); - if (!zr->zr36057_mem) { - printk(KERN_ERR "%s: ioremap failed\n", zr->name); - /* XXX handle error */ - } - - /* set PCI latency timer */ - pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, &latency); - if (latency != 48) { - printk(KERN_INFO "%s: Changing PCI latency from %d to 48.\n", zr->name, latency); - latency = 48; - pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, latency); - } - zoran_num++; - } - if (zoran_num == 0) - printk(KERN_INFO "zoran: no cards found.\n"); - - return zoran_num; -} - -static void handle_chipset(void) -{ - if(pci_pci_problems&PCIPCI_FAIL) - { - printk(KERN_WARNING "buz: This configuration is known to have PCI to PCI DMA problems\n"); - printk(KERN_WARNING "buz: You may not be able to use overlay mode.\n"); - } - - - if(pci_pci_problems&PCIPCI_TRITON) - { - printk("buz: Enabling Triton support.\n"); - triton = 1; - } - - if(pci_pci_problems&PCIPCI_NATOMA) - { - printk("buz: Enabling Natoma workaround.\n"); - natoma = 1; - } -} - -#ifdef MODULE -int init_module(void) -#else -int init_zoran_cards(struct video_init *unused) -#endif -{ - int i; - - - printk(KERN_INFO "Zoran driver 1.00 (c) 1999 Rainer Johanni, Dave Perks.\n"); - - /* Look for Buz cards */ - - if (find_zr36057() <= 0) { - return -EIO; - } - printk(KERN_INFO"zoran: %d zoran card(s) found\n", zoran_num); - - if (zoran_num == 0) - return -ENXIO; - - - /* check the parameters we have been given, adjust if necessary */ - - if (v4l_nbufs < 0) - v4l_nbufs = 0; - if (v4l_nbufs > VIDEO_MAX_FRAME) - v4l_nbufs = VIDEO_MAX_FRAME; - /* The user specfies the in KB, we want them in byte (and page aligned) */ - v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024); - if (v4l_bufsize < 32768) - v4l_bufsize = 32768; - /* 2 MB is arbitrary but sufficient for the maximum possible images */ - if (v4l_bufsize > 2048 * 1024) - v4l_bufsize = 2048 * 1024; - - printk(KERN_INFO "zoran: using %d V4L buffers of size %d KB\n", v4l_nbufs, v4l_bufsize >> 10); - - /* Use parameter for vidmem or try to find a video card */ - - if (vidmem) { - printk(KERN_INFO "zoran: Using supplied video memory base address @ 0x%lx\n", vidmem); - } - - /* check if we have a Triton or Natome chipset */ - - handle_chipset(); - - /* take care of Natoma chipset and a revision 1 zr36057 */ - - for (i = 0; i < zoran_num; i++) { - if (natoma && zoran[i].revision <= 1) { - zoran[i].need_contiguous = 1; - printk(KERN_INFO "%s: ZR36057/Natome bug, max. buffer size is 128K\n", zoran[i].name); - } else { - zoran[i].need_contiguous = 0; - } - } - - /* initialize the Buzs */ - - /* We have to know which ones must be released if an error occurs */ - for (i = 0; i < zoran_num; i++) - zoran[i].initialized = 0; - - for (i = 0; i < zoran_num; i++) { - if (zr36057_init(i) < 0) { - release_zoran(); - return -EIO; - } - } - - return 0; -} - - - -#ifdef MODULE - -void cleanup_module(void) -{ - release_zoran(); -} - -#endif diff --git a/drivers/char/buz.h b/drivers/char/buz.h deleted file mode 100644 index 06b794a09..000000000 --- a/drivers/char/buz.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - buz - Iomega Buz driver - - Copyright (C) 1999 Rainer Johanni - - based on - - buz.0.0.3 Copyright (C) 1998 Dave Perks - - and - - bttv - Bt848 frame grabber driver - Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _BUZ_H_ -#define _BUZ_H_ - -/* The Buz only supports a maximum width of 720, but some V4L - applications (e.g. xawtv are more happy with 768). - If XAWTV_HACK is defined, we try to fake a device with bigger width */ - -#define XAWTV_HACK - -#ifdef XAWTV_HACK -#define BUZ_MAX_WIDTH 768 /* never display more than 768 pixels */ -#else -#define BUZ_MAX_WIDTH 720 /* never display more than 720 pixels */ -#endif -#define BUZ_MAX_HEIGHT 576 /* never display more than 576 rows */ -#define BUZ_MIN_WIDTH 32 /* never display less than 32 pixels */ -#define BUZ_MIN_HEIGHT 24 /* never display less than 24 rows */ - -struct zoran_requestbuffers { - unsigned long count; /* Number of buffers for MJPEG grabbing */ - unsigned long size; /* Size PER BUFFER in bytes */ -}; - -struct zoran_sync { - unsigned long frame; /* number of buffer that has been free'd */ - unsigned long length; /* number of code bytes in buffer (capture only) */ - unsigned long seq; /* frame sequence number */ - struct timeval timestamp; /* timestamp */ -}; - -struct zoran_status { - int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ - int signal; /* Returned: 1 if valid video signal detected */ - int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ - int color; /* Returned: 1 if color signal detected */ -}; - -struct zoran_params { - - /* The following parameters can only be queried */ - - int major_version; /* Major version number of driver */ - int minor_version; /* Minor version number of driver */ - - /* Main control parameters */ - - int input; /* Input channel: 0 = Composite, 1 = S-VHS */ - int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ - int decimation; /* decimation of captured video, - enlargement of video played back. - Valid values are 1, 2, 4 or 0. - 0 is a special value where the user - has full control over video scaling */ - - /* The following parameters only have to be set if decimation==0, - for other values of decimation they provide the data how the image is captured */ - - int HorDcm; /* Horizontal decimation: 1, 2 or 4 */ - int VerDcm; /* Vertical decimation: 1 or 2 */ - int TmpDcm; /* Temporal decimation: 1 or 2, - if TmpDcm==2 in capture every second frame is dropped, - in playback every frame is played twice */ - int field_per_buff; /* Number of fields per buffer: 1 or 2 */ - int img_x; /* start of image in x direction */ - int img_y; /* start of image in y direction */ - int img_width; /* image width BEFORE decimation, - must be a multiple of HorDcm*16 */ - int img_height; /* image height BEFORE decimation, - must be a multiple of VerDcm*8 */ - - /* --- End of parameters for decimation==0 only --- */ - - /* JPEG control parameters */ - - int quality; /* Measure for quality of compressed images. - Scales linearly with the size of the compressed images. - Must be beetween 0 and 100, 100 is a compression - ratio of 1:4 */ - - int odd_even; /* Which field should come first ??? */ - - int APPn; /* Number of APP segment to be written, must be 0..15 */ - int APP_len; /* Length of data in JPEG APPn segment */ - char APP_data[60]; /* Data in the JPEG APPn segment. */ - - int COM_len; /* Length of data in JPEG COM segment */ - char COM_data[60]; /* Data in JPEG COM segment */ - - unsigned long jpeg_markers; /* Which markers should go into the JPEG output. - Unless you exactly know what you do, leave them untouched. - Inluding less markers will make the resulting code - smaller, but there will be fewer aplications - which can read it. - The presence of the APP and COM marker is - influenced by APP0_len and COM_len ONLY! */ -#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ -#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ -#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ -#define JPEG_MARKER_COM (1<<6) /* Comment segment */ -#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ - - int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. - If this flag is turned on and JPEG decompressing - is going to the screen, the decompress process - is stopped every time the Video Fifo is full. - This enables a smooth decompress to the screen - but the video output signal will get scrambled */ - - /* Misc */ - - char reserved[312]; /* Makes 512 bytes for this structure */ -}; - -/* - Private IOCTL to set up for displaying MJPEG - */ -#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct zoran_params) -#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct zoran_params) -#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct zoran_requestbuffers) -#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) -#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) -#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct zoran_sync) -#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct zoran_status) - - -#ifdef __KERNEL__ - -#define BUZ_NUM_STAT_COM 4 -#define BUZ_MASK_STAT_COM 3 - -#define BUZ_MAX_FRAME 256 /* Must be a power of 2 */ -#define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */ - -#if VIDEO_MAX_FRAME <= 32 -#define V4L_MAX_FRAME 32 -#elif VIDEO_MAX_FRAME <= 64 -#define V4L_MAX_FRAME 64 -#else -#error "Too many video frame buffers to handle" -#endif -#define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) - - -#include "zr36057.h" - -enum zoran_codec_mode { - BUZ_MODE_IDLE, /* nothing going on */ - BUZ_MODE_MOTION_COMPRESS, /* grabbing frames */ - BUZ_MODE_MOTION_DECOMPRESS, /* playing frames */ - BUZ_MODE_STILL_COMPRESS, /* still frame conversion */ - BUZ_MODE_STILL_DECOMPRESS /* still frame conversion */ -}; - -enum zoran_buffer_state { - BUZ_STATE_USER, /* buffer is owned by application */ - BUZ_STATE_PEND, /* buffer is queued in pend[] ready to feed to I/O */ - BUZ_STATE_DMA, /* buffer is queued in dma[] for I/O */ - BUZ_STATE_DONE /* buffer is ready to return to application */ -}; - -struct zoran_gbuffer { - u32 *frag_tab; /* addresses of frag table */ - u32 frag_tab_bus; /* same value cached to save time in ISR */ - enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ - struct zoran_sync bs; /* DONE: info to return to application */ -}; - -struct v4l_gbuffer { - char *fbuffer; /* virtual address of frame buffer */ - unsigned long fbuffer_phys; /* physical address of frame buffer */ - unsigned long fbuffer_bus; /* bus address of frame buffer */ - enum zoran_buffer_state state; /* state: unused/pending/done */ -}; - -struct zoran { - struct video_device video_dev; - struct i2c_bus i2c; - - int initialized; /* flag if zoran has been correctly initalized */ - int user; /* number of current users (0 or 1) */ - - unsigned short id; /* number of this device */ - char name[32]; /* name of this device */ - struct pci_dev *pci_dev; /* PCI device */ - unsigned char revision; /* revision of zr36057 */ - int board; /* Board type */ -#define BOARD_BUZ 0 -#define BOARD_LML33 1 - unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */ - unsigned char *zr36057_mem; /* pointer to mapped IO memory */ - - int map_mjpeg_buffers; /* Flag which bufferset will map by next mmap() */ - - spinlock_t lock; /* Spinlock */ - - /* Video for Linux parameters */ - - struct video_picture picture; /* Current picture params */ - struct video_buffer buffer; /* Current buffer params */ - struct video_window window; /* Current window params */ - int buffer_set, window_set; /* Flags if the above structures are set */ - int video_interlace; /* Image on screen is interlaced */ - - u32 *overlay_mask; - - wait_queue_head_t v4l_capq; /* wait here for grab to finish */ - - int v4l_overlay_active; /* Overlay grab is activated */ - int v4l_memgrab_active; /* Memory grab is activated */ - - int v4l_grab_frame; /* Frame number being currently grabbed */ -#define NO_GRAB_ACTIVE (-1) - int v4l_grab_seq; /* Number of frames grabbed */ - int gwidth; /* Width of current memory capture */ - int gheight; /* Height of current memory capture */ - int gformat; /* Format of ... */ - int gbpl; /* byte per line of ... */ - - /* V4L grab queue of frames pending */ - - unsigned v4l_pend_head; - unsigned v4l_pend_tail; - int v4l_pend[V4L_MAX_FRAME]; - - struct v4l_gbuffer v4l_gbuf[VIDEO_MAX_FRAME]; /* V4L buffers' info */ - - /* Buz MJPEG parameters */ - - unsigned long jpg_nbufs; /* Number of buffers */ - unsigned long jpg_bufsize; /* Size of mjpeg buffers in bytes */ - int jpg_buffers_allocated; /* Flag if buffers are allocated */ - int need_contiguous; /* Flag if contiguous buffers are needed */ - - enum zoran_codec_mode codec_mode; /* status of codec */ - struct zoran_params params; /* structure with a lot of things to play with */ - - wait_queue_head_t jpg_capq; /* wait here for grab to finish */ - - /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */ - /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */ - /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */ - unsigned long jpg_que_head; /* Index where to put next buffer which is queued */ - unsigned long jpg_dma_head; /* Index of next buffer which goes into stat_com */ - unsigned long jpg_dma_tail; /* Index of last buffer in stat_com */ - unsigned long jpg_que_tail; /* Index of last buffer in queue */ - unsigned long jpg_seq_num; /* count of frames since grab/play started */ - - /* zr36057's code buffer table */ - u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ - - /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */ - int jpg_pend[BUZ_MAX_FRAME]; - - /* array indexed by frame number */ - struct zoran_gbuffer jpg_gbuf[BUZ_MAX_FRAME]; /* MJPEG buffers' info */ -}; - -#endif - -/*The following should be done in more portable way. It depends on define - of _ALPHA_BUZ in the Makefile. */ - -#ifdef _ALPHA_BUZ -#define btwrite(dat,adr) writel((dat),(char *) (zr->zr36057_adr+(adr))) -#define btread(adr) readl(zr->zr36057_adr+(adr)) -#else -#define btwrite(dat,adr) writel((dat), (char *) (zr->zr36057_mem+(adr))) -#define btread(adr) readl(zr->zr36057_mem+(adr)) -#endif - -#define btand(dat,adr) btwrite((dat) & btread(adr), adr) -#define btor(dat,adr) btwrite((dat) | btread(adr), adr) -#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) - -#define I2C_TSA5522 0xc2 -#define I2C_TDA9850 0xb6 -#define I2C_HAUPEE 0xa0 -#define I2C_STBEE 0xae -#define I2C_SAA7111 0x48 -#define I2C_SAA7185 0x88 - -#define TDA9850_CON1 0x04 -#define TDA9850_CON2 0x05 -#define TDA9850_CON3 0x06 -#define TDA9850_CON4 0x07 -#define TDA9850_ALI1 0x08 -#define TDA9850_ALI2 0x09 -#define TDA9850_ALI3 0x0a - -#endif diff --git a/drivers/char/bw-qcam.c b/drivers/char/bw-qcam.c deleted file mode 100644 index 17f7d25dc..000000000 --- a/drivers/char/bw-qcam.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * QuickCam Driver For Video4Linux. - * - * This version only works as a module. - * - * Video4Linux conversion work by Alan Cox. - * Parport compatibility by Phil Blundell. - * Busy loop avoidance by Mark Cooke. - * - * Module parameters: - * - * maxpoll=<1 - 5000> - * - * When polling the QuickCam for a response, busy-wait for a - * maximum of this many loops. The default of 250 gives little - * impact on interactive response. - * - * NOTE: If this parameter is set too high, the processor - * will busy wait until this loop times out, and then - * slowly poll for a further 5 seconds before failing - * the transaction. You have been warned. - * - * yieldlines=<1 - 250> - * - * When acquiring a frame from the camera, the data gathering - * loop will yield back to the scheduler after completing - * this many lines. The default of 4 provides a trade-off - * between increased frame acquisition time and impact on - * interactive response. - */ - -/* qcam-lib.c -- Library for programming with the Connectix QuickCam. - * See the included documentation for usage instructions and details - * of the protocol involved. */ - - -/* Version 0.5, August 4, 1996 */ -/* Version 0.7, August 27, 1996 */ -/* Version 0.9, November 17, 1996 */ - - -/****************************************************************** - -Copyright (C) 1996 by Scott Laird - -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 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 SCOTT LAIRD 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bw-qcam.h" - -static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */ -static unsigned int yieldlines=4; /* Yield after this many during capture */ - -#if LINUX_VERSION_CODE >= 0x020117 -MODULE_PARM(maxpoll,"i"); -MODULE_PARM(yieldlines,"i"); -#endif - -extern __inline__ int read_lpstatus(struct qcam_device *q) -{ - return parport_read_status(q->pport); -} - -extern __inline__ int read_lpcontrol(struct qcam_device *q) -{ - return parport_read_control(q->pport); -} - -extern __inline__ int read_lpdata(struct qcam_device *q) -{ - return parport_read_data(q->pport); -} - -extern __inline__ void write_lpdata(struct qcam_device *q, int d) -{ - parport_write_data(q->pport, d); -} - -extern __inline__ void write_lpcontrol(struct qcam_device *q, int d) -{ - parport_write_control(q->pport, d); -} - -static int qc_waithand(struct qcam_device *q, int val); -static int qc_command(struct qcam_device *q, int command); -static int qc_readparam(struct qcam_device *q); -static int qc_setscanmode(struct qcam_device *q); -static int qc_readbytes(struct qcam_device *q, char buffer[]); - -static struct video_device qcam_template; - -static int qc_calibrate(struct qcam_device *q) -{ - /* - * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96 - * The white balance is an individiual value for each - * quickcam. - */ - - int value; - int count = 0; - - qc_command(q, 27); /* AutoAdjustOffset */ - qc_command(q, 0); /* Dummy Parameter, ignored by the camera */ - - /* GetOffset (33) will read 255 until autocalibration */ - /* is finished. After that, a value of 1-254 will be */ - /* returned. */ - - do { - qc_command(q, 33); - value = qc_readparam(q); - mdelay(1); - schedule(); - count++; - } while (value == 0xff && count<2048); - - q->whitebal = value; - return value; -} - -/* Initialize the QuickCam driver control structure. This is where - * defaults are set for people who don't have a config file.*/ - -static struct qcam_device *qcam_init(struct parport *port) -{ - struct qcam_device *q; - - q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); - if(q==NULL) - return NULL; - - q->pport = port; - q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, - NULL, 0, NULL); - if (q->pdev == NULL) - { - printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", - port->name); - kfree(q); - return NULL; - } - - memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - - init_MUTEX(&q->lock); - - q->port_mode = (QC_ANY | QC_NOTSET); - q->width = 320; - q->height = 240; - q->bpp = 4; - q->transfer_scale = 2; - q->contrast = 192; - q->brightness = 180; - q->whitebal = 105; - q->top = 1; - q->left = 14; - q->mode = -1; - q->status = QC_PARAM_CHANGE; - return q; -} - - -/* qc_command is probably a bit of a misnomer -- it's used to send - * bytes *to* the camera. Generally, these bytes are either commands - * or arguments to commands, so the name fits, but it still bugs me a - * bit. See the documentation for a list of commands. */ - -static int qc_command(struct qcam_device *q, int command) -{ - int n1, n2; - int cmd; - - write_lpdata(q, command); - write_lpcontrol(q, 6); - - n1 = qc_waithand(q, 1); - - write_lpcontrol(q, 0xe); - n2 = qc_waithand(q, 0); - - cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); - return cmd; -} - -static int qc_readparam(struct qcam_device *q) -{ - int n1, n2; - int cmd; - - write_lpcontrol(q, 6); - n1 = qc_waithand(q, 1); - - write_lpcontrol(q, 0xe); - n2 = qc_waithand(q, 0); - - cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); - return cmd; -} - -/* qc_waithand busy-waits for a handshake signal from the QuickCam. - * Almost all communication with the camera requires handshaking. */ - -static int qc_waithand(struct qcam_device *q, int val) -{ - int status; - int runs=0; - - if (val) - { - while (!((status = read_lpstatus(q)) & 8)) - { - /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly - until the camera wakes up. However, we are - busy blocked until the camera responds, so - setting it lower is much better for interactive - response. */ - - if(runs++>maxpoll) - { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); - } - if(runs>(maxpoll+1000)) /* 5 seconds */ - return -1; - } - } - else - { - while (((status = read_lpstatus(q)) & 8)) - { - /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly - until the camera wakes up. However, we are - busy blocked until the camera responds, so - setting it lower is much better for interactive - response. */ - - if(runs++>maxpoll) - { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); - } - if(runs++>(maxpoll+1000)) /* 5 seconds */ - return -1; - } - } - - return status; -} - -/* Waithand2 is used when the qcam is in bidirectional mode, and the - * handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1 - * (bit 3 of status register). It also returns the last value read, - * since this data is useful. */ - -static unsigned int qc_waithand2(struct qcam_device *q, int val) -{ - unsigned int status; - int runs=0; - - do - { - status = read_lpdata(q); - /* 1000 is enough spins on the I/O for all normal - cases, at that point we start to poll slowly - until the camera wakes up. However, we are - busy blocked until the camera responds, so - setting it lower is much better for interactive - response. */ - - if(runs++>maxpoll) - { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); - } - if(runs++>(maxpoll+1000)) /* 5 seconds */ - return 0; - } - while ((status & 1) != val); - - return status; -} - - -/* Try to detect a QuickCam. It appears to flash the upper 4 bits of - the status register at 5-10 Hz. This is only used in the autoprobe - code. Be aware that this isn't the way Connectix detects the - camera (they send a reset and try to handshake), but this should be - almost completely safe, while their method screws up my printer if - I plug it in before the camera. */ - -static int qc_detect(struct qcam_device *q) -{ - int reg, lastreg; - int count = 0; - int i; - - lastreg = reg = read_lpstatus(q) & 0xf0; - - for (i = 0; i < 500; i++) - { - reg = read_lpstatus(q) & 0xf0; - if (reg != lastreg) - count++; - lastreg = reg; - mdelay(2); - } - - -#if 0 - /* Force camera detection during testing. Sometimes the camera - won't be flashing these bits. Possibly unloading the module - in the middle of a grab? Or some timeout condition? - I've seen this parameter as low as 19 on my 450Mhz box - mpc */ - printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); - return 1; -#endif - - /* Be (even more) liberal in what you accept... */ - -/* if (count > 30 && count < 200) */ - if (count > 20 && count < 300) - return 1; /* found */ - else - return 0; /* not found */ -} - - -/* Reset the QuickCam. This uses the same sequence the Windows - * QuickPic program uses. Someone with a bi-directional port should - * check that bi-directional mode is detected right, and then - * implement bi-directional mode in qc_readbyte(). */ - -static void qc_reset(struct qcam_device *q) -{ - switch (q->port_mode & QC_FORCE_MASK) - { - case QC_FORCE_UNIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - break; - - case QC_FORCE_BIDIR: - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - break; - - case QC_ANY: - write_lpcontrol(q, 0x20); - write_lpdata(q, 0x75); - - if (read_lpdata(q) != 0x75) { - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; - } else { - q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; - } - break; - } - - write_lpcontrol(q, 0xb); - udelay(250); - write_lpcontrol(q, 0xe); - qc_setscanmode(q); /* in case port_mode changed */ -} - - -/* Decide which scan mode to use. There's no real requirement that - * the scanmode match the resolution in q->height and q-> width -- the - * camera takes the picture at the resolution specified in the - * "scanmode" and then returns the image at the resolution specified - * with the resolution commands. If the scan is bigger than the - * requested resolution, the upper-left hand corner of the scan is - * returned. If the scan is smaller, then the rest of the image - * returned contains garbage. */ - -static int qc_setscanmode(struct qcam_device *q) -{ - int old_mode = q->mode; - - switch (q->transfer_scale) - { - case 1: - q->mode = 0; - break; - case 2: - q->mode = 4; - break; - case 4: - q->mode = 8; - break; - } - - switch (q->bpp) - { - case 4: - break; - case 6: - q->mode += 2; - break; - } - - switch (q->port_mode & QC_MODE_MASK) - { - case QC_BIDIR: - q->mode += 1; - break; - case QC_NOTSET: - case QC_UNIDIR: - break; - } - - if (q->mode != old_mode) - q->status |= QC_PARAM_CHANGE; - - return 0; -} - - -/* Reset the QuickCam and program for brightness, contrast, - * white-balance, and resolution. */ - -void qc_set(struct qcam_device *q) -{ - int val; - int val2; - - qc_reset(q); - - /* Set the brightness. Yes, this is repetitive, but it works. - * Shorter versions seem to fail subtly. Feel free to try :-). */ - /* I think the problem was in qc_command, not here -- bls */ - - qc_command(q, 0xb); - qc_command(q, q->brightness); - - val = q->height / q->transfer_scale; - qc_command(q, 0x11); - qc_command(q, val); - if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) { - /* The normal "transfers per line" calculation doesn't seem to work - as expected here (and yet it works fine in qc_scan). No idea - why this case is the odd man out. Fortunately, Laird's original - working version gives me a good way to guess at working values. - -- bls */ - val = q->width; - val2 = q->transfer_scale * 4; - } else { - val = q->width * q->bpp; - val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * - q->transfer_scale; - } - val = (val + val2 - 1) / val2; - qc_command(q, 0x13); - qc_command(q, val); - - /* Setting top and left -- bls */ - qc_command(q, 0xd); - qc_command(q, q->top); - qc_command(q, 0xf); - qc_command(q, q->left / 2); - - qc_command(q, 0x19); - qc_command(q, q->contrast); - qc_command(q, 0x1f); - qc_command(q, q->whitebal); - - /* Clear flag that we must update the grabbing parameters on the camera - before we grab the next frame */ - q->status &= (~QC_PARAM_CHANGE); -} - -/* Qc_readbytes reads some bytes from the QC and puts them in - the supplied buffer. It returns the number of bytes read, - or -1 on error. */ - -extern __inline__ int qc_readbytes(struct qcam_device *q, char buffer[]) -{ - int ret=1; - unsigned int hi, lo; - unsigned int hi2, lo2; - static int state = 0; - - if (buffer == NULL) - { - state = 0; - return 0; - } - - switch (q->port_mode & QC_MODE_MASK) - { - case QC_BIDIR: /* Bi-directional Port */ - write_lpcontrol(q, 0x26); - lo = (qc_waithand2(q, 1) >> 1); - hi = (read_lpstatus(q) >> 3) & 0x1f; - write_lpcontrol(q, 0x2e); - lo2 = (qc_waithand2(q, 0) >> 1); - hi2 = (read_lpstatus(q) >> 3) & 0x1f; - switch (q->bpp) - { - case 4: - buffer[0] = lo & 0xf; - buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); - buffer[2] = (hi & 0x1e) >> 1; - buffer[3] = lo2 & 0xf; - buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); - buffer[5] = (hi2 & 0x1e) >> 1; - ret = 6; - break; - case 6: - buffer[0] = lo & 0x3f; - buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); - buffer[2] = lo2 & 0x3f; - buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); - ret = 4; - break; - } - break; - - case QC_UNIDIR: /* Unidirectional Port */ - write_lpcontrol(q, 6); - lo = (qc_waithand(q, 1) & 0xf0) >> 4; - write_lpcontrol(q, 0xe); - hi = (qc_waithand(q, 0) & 0xf0) >> 4; - - switch (q->bpp) - { - case 4: - buffer[0] = lo; - buffer[1] = hi; - ret = 2; - break; - case 6: - switch (state) - { - case 0: - buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); - q->saved_bits = (hi & 3) << 4; - state = 1; - ret = 1; - break; - case 1: - buffer[0] = lo | q->saved_bits; - q->saved_bits = hi << 2; - state = 2; - ret = 1; - break; - case 2: - buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits; - buffer[1] = ((lo & 3) << 4) | hi; - state = 0; - ret = 2; - break; - } - break; - } - break; - } - return ret; -} - -/* requests a scan from the camera. It sends the correct instructions - * to the camera and then reads back the correct number of bytes. In - * previous versions of this routine the return structure contained - * the raw output from the camera, and there was a 'qc_convertscan' - * function that converted that to a useful format. In version 0.3 I - * rolled qc_convertscan into qc_scan and now I only return the - * converted scan. The format is just an one-dimensional array of - * characters, one for each pixel, with 0=black up to n=white, where - * n=2^(bit depth)-1. Ask me for more details if you don't understand - * this. */ - -long qc_capture(struct qcam_device * q, char *buf, unsigned long len) -{ - int i, j, k, yield; - int bytes; - int linestotrans, transperline; - int divisor; - int pixels_per_line; - int pixels_read = 0; - int got=0; - char buffer[6]; - int shift=8-q->bpp; - char invert; - - if (q->mode == -1) - return -ENXIO; - - qc_command(q, 0x7); - qc_command(q, q->mode); - - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) - { - write_lpcontrol(q, 0x2e); /* turn port around */ - write_lpcontrol(q, 0x26); - (void) qc_waithand(q, 1); - write_lpcontrol(q, 0x2e); - (void) qc_waithand(q, 0); - } - - /* strange -- should be 15:63 below, but 4bpp is odd */ - invert = (q->bpp == 4) ? 16 : 63; - - linestotrans = q->height / q->transfer_scale; - pixels_per_line = q->width / q->transfer_scale; - transperline = q->width * q->bpp; - divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * - q->transfer_scale; - transperline = (transperline + divisor - 1) / divisor; - - for (i = 0, yield = yieldlines; i < linestotrans; i++) - { - for (pixels_read = j = 0; j < transperline; j++) - { - bytes = qc_readbytes(q, buffer); - for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) - { - int o; - if (buffer[k] == 0 && invert == 16) - { - /* 4bpp is odd (again) -- inverter is 16, not 15, but output - must be 0-15 -- bls */ - buffer[k] = 16; - } - o=i*pixels_per_line + pixels_read + k; - if(o= yield) { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); - yield = i + yieldlines; - } - } - - if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) - { - write_lpcontrol(q, 2); - write_lpcontrol(q, 6); - udelay(3); - write_lpcontrol(q, 0xe); - } - if(gotbrightness<<8; - p.contrast=qcam->contrast<<8; - p.whiteness=qcam->whitebal<<8; - p.depth=qcam->bpp; - p.palette=VIDEO_PALETTE_GREY; - if(copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - if(copy_from_user(&p, arg, sizeof(p))) - return -EFAULT; - if(p.palette!=VIDEO_PALETTE_GREY) - return -EINVAL; - if(p.depth!=4 && p.depth!=6) - return -EINVAL; - - /* - * Now load the camera. - */ - - qcam->brightness = p.brightness>>8; - qcam->contrast = p.contrast>>8; - qcam->whitebal = p.whiteness>>8; - qcam->bpp = p.depth; - - down(&qcam->lock); - qc_setscanmode(qcam); - up(&qcam->lock); - qcam->status |= QC_PARAM_CHANGE; - - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - if(copy_from_user(&vw, arg,sizeof(vw))) - return -EFAULT; - if(vw.flags) - return -EINVAL; - if(vw.clipcount) - return -EINVAL; - if(vw.height<60||vw.height>240) - return -EINVAL; - if(vw.width<80||vw.width>320) - return -EINVAL; - - qcam->width = 320; - qcam->height = 240; - qcam->transfer_scale = 4; - - if(vw.width>=160 && vw.height>=120) - { - qcam->transfer_scale = 2; - } - if(vw.width>=320 && vw.height>=240) - { - qcam->width = 320; - qcam->height = 240; - qcam->transfer_scale = 1; - } - down(&qcam->lock); - qc_setscanmode(qcam); - up(&qcam->lock); - - /* We must update the camera before we grab. We could - just have changed the grab size */ - qcam->status |= QC_PARAM_CHANGE; - - /* Ok we figured out what to use from our wide choice */ - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - vw.x=0; - vw.y=0; - vw.width=qcam->width/qcam->transfer_scale; - vw.height=qcam->height/qcam->transfer_scale; - vw.chromakey=0; - vw.flags=0; - if(copy_to_user(arg, &vw, sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCGFBUF: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCKEY: - return 0; - case VIDIOCGFREQ: - return -EINVAL; - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - return -EINVAL; - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static long qcam_read(struct video_device *v, char *buf, unsigned long count, int noblock) -{ - struct qcam_device *qcam=(struct qcam_device *)v; - int len; - parport_claim_or_block(qcam->pdev); - - down(&qcam->lock); - - qc_reset(qcam); - - /* Update the camera parameters if we need to */ - if (qcam->status & QC_PARAM_CHANGE) - qc_set(qcam); - - len=qc_capture(qcam, buf,count); - - up(&qcam->lock); - - parport_release(qcam->pdev); - return len; -} - -static struct video_device qcam_template= -{ - "Connectix Quickcam", - VID_TYPE_CAPTURE, - VID_HARDWARE_QCAM_BW, - qcam_open, - qcam_close, - qcam_read, - qcam_write, - NULL, - qcam_ioctl, - NULL, - qcam_init_done, - NULL, - 0, - 0 -}; - -#define MAX_CAMS 4 -static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; - -int init_bwqcam(struct parport *port) -{ - struct qcam_device *qcam; - - if (num_cams == MAX_CAMS) - { - printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); - return -ENOSPC; - } - - qcam=qcam_init(port); - if(qcam==NULL) - return -ENODEV; - - parport_claim_or_block(qcam->pdev); - - qc_reset(qcam); - - if(qc_detect(qcam)==0) - { - parport_release(qcam->pdev); - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - qc_calibrate(qcam); - - parport_release(qcam->pdev); - - printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); - - if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1) - { - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - - qcams[num_cams++] = qcam; - - return 0; -} - -void close_bwqcam(struct qcam_device *qcam) -{ - video_unregister_device(&qcam->vdev); - parport_unregister_device(qcam->pdev); - kfree(qcam); -} - -/* The parport parameter controls which parports will be scanned. - * Scanning all parports causes some printers to print a garbage page. - * -- March 14, 1999 Billy Donahue */ -#ifdef MODULE -static char *parport[MAX_CAMS] = { NULL, }; -MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "s"); -#endif - -#ifdef MODULE -int init_module(void) -{ - struct parport *port; - int n; - if(parport[0] && strncmp(parport[0], "auto", 4)){ - /* user gave parport parameters */ - for(n=0; parport[n] && nnext){ - if(r!=port->number) - continue; - init_bwqcam(port); - break; - } - } - return (num_cams)?0:-ENODEV; - } - /* no parameter or "auto" */ - for (port = parport_enumerate(); port; port=port->next) - init_bwqcam(port); - - /* Do some sanity checks on the module parameters. */ - if (maxpoll > 5000) { - printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n"); - maxpoll = 5000; - } - - if (yieldlines < 1) { - printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n"); - yieldlines = 1; - } - - return (num_cams)?0:-ENODEV; -} - -void cleanup_module(void) -{ - unsigned int i; - for (i = 0; i < num_cams; i++) - close_bwqcam(qcams[i]); -} -#else -int __init init_bw_qcams(struct video_init *unused) -{ - struct parport *port; - - for (port = parport_enumerate(); port; port=port->next) - init_bwqcam(port); - return 0; -} -#endif diff --git a/drivers/char/bw-qcam.h b/drivers/char/bw-qcam.h deleted file mode 100644 index 723e8ad9e..000000000 --- a/drivers/char/bw-qcam.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Video4Linux bw-qcam driver - * - * Derived from code.. - */ - -/****************************************************************** - -Copyright (C) 1996 by Scott Laird - -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 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 SCOTT LAIRD 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. - -******************************************************************/ - -/* One from column A... */ -#define QC_NOTSET 0 -#define QC_UNIDIR 1 -#define QC_BIDIR 2 -#define QC_SERIAL 3 - -/* ... and one from column B */ -#define QC_ANY 0x00 -#define QC_FORCE_UNIDIR 0x10 -#define QC_FORCE_BIDIR 0x20 -#define QC_FORCE_SERIAL 0x30 -/* in the port_mode member */ - -#define QC_MODE_MASK 0x07 -#define QC_FORCE_MASK 0x70 - -#define MAX_HEIGHT 243 -#define MAX_WIDTH 336 - -/* Bit fields for status flags */ -#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ - -struct qcam_device { - struct video_device vdev; - struct pardevice *pdev; - struct parport *pport; - struct semaphore lock; - int width, height; - int bpp; - int mode; - int contrast, brightness, whitebal; - int port_mode; - int transfer_scale; - int top, left; - int status; - unsigned int saved_bits; -}; diff --git a/drivers/char/c-qcam.c b/drivers/char/c-qcam.c deleted file mode 100644 index fa96cc925..000000000 --- a/drivers/char/c-qcam.c +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Video4Linux Colour QuickCam driver - * Copyright 1997-2000 Philip Blundell - * - * Module parameters: - * - * parport=auto -- probe all parports (default) - * parport=0 -- parport0 becomes qcam1 - * parport=2,0,1 -- parports 2,0,1 are tried in that order - * - * probe=0 -- do no probing, assume camera is present - * probe=1 -- use IEEE-1284 autoprobe data only (default) - * probe=2 -- probe aggressively for cameras - * - * force_rgb=1 -- force data format to RGB (default is BGR) - * - * The parport parameter controls which parports will be scanned. - * Scanning all parports causes some printers to print a garbage page. - * -- March 14, 1999 Billy Donahue - * - * Fixed data format to BGR, added force_rgb parameter. Added missing - * parport_unregister_driver() on module removal. - * -- May 28, 2000 Claudio Matsuoka - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct qcam_device { - struct video_device vdev; - struct pardevice *pdev; - struct parport *pport; - int width, height; - int ccd_width, ccd_height; - int mode; - int contrast, brightness, whitebal; - int top, left; - unsigned int bidirectional; - struct semaphore lock; -}; - -/* cameras maximum */ -#define MAX_CAMS 4 - -/* The three possible QuickCam modes */ -#define QC_MILLIONS 0x18 -#define QC_BILLIONS 0x10 -#define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */ - -/* The three possible decimations */ -#define QC_DECIMATION_1 0 -#define QC_DECIMATION_2 2 -#define QC_DECIMATION_4 4 - -#define BANNER "Colour QuickCam for Video4Linux v0.05" - -static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; -static int probe = 2; -static int force_rgb = 0; - -static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) -{ - /* note: the QC specs refer to the PCAck pin by voltage, not - software level. PC ports have builtin inverters. */ - parport_frob_control(qcam->pport, 8, i?8:0); -} - -static inline unsigned int qcam_ready1(struct qcam_device *qcam) -{ - return (parport_read_status(qcam->pport) & 0x8)?1:0; -} - -static inline unsigned int qcam_ready2(struct qcam_device *qcam) -{ - return (parport_read_data(qcam->pport) & 0x1)?1:0; -} - -static unsigned int qcam_await_ready1(struct qcam_device *qcam, - int value) -{ - unsigned long oldjiffies = jiffies; - unsigned int i; - - for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); ) - if (qcam_ready1(qcam) == value) - return 0; - - /* If the camera didn't respond within 1/25 second, poll slowly - for a while. */ - for (i = 0; i < 50; i++) - { - if (qcam_ready1(qcam) == value) - return 0; - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - } - - /* Probably somebody pulled the plug out. Not much we can do. */ - printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value, - parport_read_status(qcam->pport), - parport_read_control(qcam->pport)); - return 1; -} - -static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) -{ - unsigned long oldjiffies = jiffies; - unsigned int i; - - for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); ) - if (qcam_ready2(qcam) == value) - return 0; - - /* If the camera didn't respond within 1/25 second, poll slowly - for a while. */ - for (i = 0; i < 50; i++) - { - if (qcam_ready2(qcam) == value) - return 0; - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - } - - /* Probably somebody pulled the plug out. Not much we can do. */ - printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value, - parport_read_status(qcam->pport), - parport_read_control(qcam->pport), - parport_read_data(qcam->pport)); - return 1; -} - -static int qcam_read_data(struct qcam_device *qcam) -{ - unsigned int idata; - qcam_set_ack(qcam, 0); - if (qcam_await_ready1(qcam, 1)) return -1; - idata = parport_read_status(qcam->pport) & 0xf0; - qcam_set_ack(qcam, 1); - if (qcam_await_ready1(qcam, 0)) return -1; - idata |= (parport_read_status(qcam->pport) >> 4); - return idata; -} - -static int qcam_write_data(struct qcam_device *qcam, unsigned int data) -{ - unsigned int idata; - parport_write_data(qcam->pport, data); - idata = qcam_read_data(qcam); - if (data != idata) - { - printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, - idata); - return 1; - } - return 0; -} - -static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data) -{ - if (qcam_write_data(qcam, cmd)) - return -1; - if (qcam_write_data(qcam, data)) - return -1; - return 0; -} - -static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd) -{ - if (qcam_write_data(qcam, cmd)) - return -1; - return qcam_read_data(qcam); -} - -static int qc_detect(struct qcam_device *qcam) -{ - unsigned int stat, ostat, i, count = 0; - - /* The probe routine below is not very reliable. The IEEE-1284 - probe takes precedence. */ - /* XXX Currently parport provides no way to distinguish between - "the IEEE probe was not done" and "the probe was done, but - no device was found". Fix this one day. */ - if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA - && qcam->pport->probe_info[0].model - && !strcmp(qcam->pdev->port->probe_info[0].model, - "Color QuickCam 2.0")) { - printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n"); - return 1; - } - - if (probe < 2) - return 0; - - parport_write_control(qcam->pport, 0xc); - - /* look for a heartbeat */ - ostat = stat = parport_read_status(qcam->pport); - for (i=0; i<250; i++) - { - mdelay(1); - stat = parport_read_status(qcam->pport); - if (ostat != stat) - { - if (++count >= 3) return 1; - ostat = stat; - } - } - - /* Reset the camera and try again */ - parport_write_control(qcam->pport, 0xc); - parport_write_control(qcam->pport, 0x8); - mdelay(1); - parport_write_control(qcam->pport, 0xc); - mdelay(1); - count = 0; - - ostat = stat = parport_read_status(qcam->pport); - for (i=0; i<250; i++) - { - mdelay(1); - stat = parport_read_status(qcam->pport); - if (ostat != stat) - { - if (++count >= 3) return 1; - ostat = stat; - } - } - - /* no (or flatline) camera, give up */ - return 0; -} - -static void qc_reset(struct qcam_device *qcam) -{ - parport_write_control(qcam->pport, 0xc); - parport_write_control(qcam->pport, 0x8); - mdelay(1); - parport_write_control(qcam->pport, 0xc); - mdelay(1); -} - -/* Reset the QuickCam and program for brightness, contrast, - * white-balance, and resolution. */ - -static void qc_setup(struct qcam_device *q) -{ - qc_reset(q); - - /* Set the brightness. */ - qcam_set(q, 11, q->brightness); - - /* Set the height and width. These refer to the actual - CCD area *before* applying the selected decimation. */ - qcam_set(q, 17, q->ccd_height); - qcam_set(q, 19, q->ccd_width / 2); - - /* Set top and left. */ - qcam_set(q, 0xd, q->top); - qcam_set(q, 0xf, q->left); - - /* Set contrast and white balance. */ - qcam_set(q, 0x19, q->contrast); - qcam_set(q, 0x1f, q->whitebal); - - /* Set the speed. */ - qcam_set(q, 45, 2); -} - -/* Read some bytes from the camera and put them in the buffer. - nbytes should be a multiple of 3, because bidirectional mode gives - us three bytes at a time. */ - -static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes) -{ - unsigned int bytes = 0; - - qcam_set_ack(q, 0); - if (q->bidirectional) - { - /* It's a bidirectional port */ - while (bytes < nbytes) - { - unsigned int lo1, hi1, lo2, hi2; - unsigned char r, g, b; - - if (qcam_await_ready2(q, 1)) return bytes; - lo1 = parport_read_data(q->pport) >> 1; - hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; - qcam_set_ack(q, 1); - if (qcam_await_ready2(q, 0)) return bytes; - lo2 = parport_read_data(q->pport) >> 1; - hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; - qcam_set_ack(q, 0); - r = (lo1 | ((hi1 & 1)<<7)); - g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1); - b = (lo2 | ((hi2 & 1)<<7)); - if (force_rgb) { - buf[bytes++] = r; - buf[bytes++] = g; - buf[bytes++] = b; - } else { - buf[bytes++] = b; - buf[bytes++] = g; - buf[bytes++] = r; - } - } - } - else - { - /* It's a unidirectional port */ - int i = 0, n = bytes; - unsigned char rgb[3]; - - while (bytes < nbytes) - { - unsigned int hi, lo; - - if (qcam_await_ready1(q, 1)) return bytes; - hi = (parport_read_status(q->pport) & 0xf0); - qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) return bytes; - lo = (parport_read_status(q->pport) & 0xf0); - qcam_set_ack(q, 0); - /* flip some bits */ - rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; - if (i >= 2) { -get_fragment: - if (force_rgb) { - buf[n++] = rgb[0]; - buf[n++] = rgb[1]; - buf[n++] = rgb[2]; - } else { - buf[n++] = rgb[2]; - buf[n++] = rgb[1]; - buf[n++] = rgb[0]; - } - } - } - if (i) { - i = 0; - goto get_fragment; - } - } - return bytes; -} - -#define BUFSZ 150 - -static long qc_capture(struct qcam_device *q, char *buf, unsigned long len) -{ - unsigned lines, pixelsperline, bitsperxfer; - unsigned int is_bi_dir = q->bidirectional; - size_t wantlen, outptr = 0; - char tmpbuf[BUFSZ]; - - if (verify_area(VERIFY_WRITE, buf, len)) - return -EFAULT; - - /* Wait for camera to become ready */ - for (;;) - { - int i = qcam_get(q, 41); - if (i == -1) { - qc_setup(q); - return -EIO; - } - if ((i & 0x80) == 0) - break; - else - schedule(); - } - - if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1)) - return -EIO; - - lines = q->height; - pixelsperline = q->width; - bitsperxfer = (is_bi_dir) ? 24 : 8; - - if (is_bi_dir) - { - /* Turn the port around */ - parport_data_reverse(q->pport); - mdelay(3); - qcam_set_ack(q, 0); - if (qcam_await_ready1(q, 1)) { - qc_setup(q); - return -EIO; - } - qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) { - qc_setup(q); - return -EIO; - } - } - - wantlen = lines * pixelsperline * 24 / 8; - - while (wantlen) - { - size_t t, s; - s = (wantlen > BUFSZ)?BUFSZ:wantlen; - t = qcam_read_bytes(q, tmpbuf, s); - if (outptr < len) - { - size_t sz = len - outptr; - if (sz > t) sz = t; - if (__copy_to_user(buf+outptr, tmpbuf, sz)) - break; - outptr += sz; - } - wantlen -= t; - if (t < s) - break; - if (current->need_resched) - schedule(); - } - - len = outptr; - - if (wantlen) - { - printk("qcam: short read.\n"); - if (is_bi_dir) - parport_data_forward(q->pport); - qc_setup(q); - return len; - } - - if (is_bi_dir) - { - int l; - do { - l = qcam_read_bytes(q, tmpbuf, 3); - if (current->need_resched) - schedule(); - } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); - if (force_rgb) { - if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk("qcam: bad EOF\n"); - } else { - if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - printk("qcam: bad EOF\n"); - } - qcam_set_ack(q, 0); - if (qcam_await_ready1(q, 1)) - { - printk("qcam: no ack after EOF\n"); - parport_data_forward(q->pport); - qc_setup(q); - return len; - } - parport_data_forward(q->pport); - mdelay(3); - qcam_set_ack(q, 1); - if (qcam_await_ready1(q, 0)) - { - printk("qcam: no ack to port turnaround\n"); - qc_setup(q); - return len; - } - } - else - { - int l; - do { - l = qcam_read_bytes(q, tmpbuf, 1); - if (current->need_resched) - schedule(); - } while (l && tmpbuf[0] == 0x7e); - l = qcam_read_bytes(q, tmpbuf+1, 2); - if (force_rgb) { - if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk("qcam: bad EOF\n"); - } else { - if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) - printk("qcam: bad EOF\n"); - } - } - - qcam_write_data(q, 0); - return len; -} - -/* - * Video4linux interfacing - */ - -static int qcam_open(struct video_device *dev, int flags) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static void qcam_close(struct video_device *dev) -{ - MOD_DEC_USE_COUNT; -} - -static int qcam_init_done(struct video_device *dev) -{ - return 0; -} - -static long qcam_write(struct video_device *v, const char *buf, unsigned long count, int noblock) -{ - return -EINVAL; -} - -static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct qcam_device *qcam=(struct qcam_device *)dev; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability b; - strcpy(b.name, "Quickcam"); - b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES; - b.channels = 1; - b.audios = 0; - b.maxwidth = 320; - b.maxheight = 240; - b.minwidth = 80; - b.minheight = 60; - if(copy_to_user(arg, &b,sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.channel!=0) - return -EINVAL; - v.flags=0; - v.tuners=0; - /* Good question.. its composite or SVHS so.. */ - v.type = VIDEO_TYPE_CAMERA; - strcpy(v.name, "Camera"); - if(copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSCHAN: - { - int v; - if(copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - if(v!=0) - return -EINVAL; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))!=0) - return -EFAULT; - if(v.tuner) - return -EINVAL; - strcpy(v.name, "Format"); - v.rangelow=0; - v.rangehigh=0; - v.flags= 0; - v.mode = VIDEO_MODE_AUTO; - if(copy_to_user(arg,&v,sizeof(v))!=0) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))!=0) - return -EFAULT; - if(v.tuner) - return -EINVAL; - if(v.mode!=VIDEO_MODE_AUTO) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture p; - p.colour=0x8000; - p.hue=0x8000; - p.brightness=qcam->brightness<<8; - p.contrast=qcam->contrast<<8; - p.whiteness=qcam->whitebal<<8; - p.depth=24; - p.palette=VIDEO_PALETTE_RGB24; - if(copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - if(copy_from_user(&p, arg, sizeof(p))) - return -EFAULT; - - /* - * Sanity check args - */ - if (p.depth != 24 || p.palette != VIDEO_PALETTE_RGB24) - return -EINVAL; - - /* - * Now load the camera. - */ - qcam->brightness = p.brightness>>8; - qcam->contrast = p.contrast>>8; - qcam->whitebal = p.whiteness>>8; - - down(&qcam->lock); - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - up(&qcam->lock); - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - - if(copy_from_user(&vw, arg,sizeof(vw))) - return -EFAULT; - if(vw.flags) - return -EINVAL; - if(vw.clipcount) - return -EINVAL; - if(vw.height<60||vw.height>240) - return -EINVAL; - if(vw.width<80||vw.width>320) - return -EINVAL; - - qcam->width = 80; - qcam->height = 60; - qcam->mode = QC_DECIMATION_4; - - if(vw.width>=160 && vw.height>=120) - { - qcam->width = 160; - qcam->height = 120; - qcam->mode = QC_DECIMATION_2; - } - if(vw.width>=320 && vw.height>=240) - { - qcam->width = 320; - qcam->height = 240; - qcam->mode = QC_DECIMATION_1; - } - qcam->mode |= QC_MILLIONS; -#if 0 - if(vw.width>=640 && vw.height>=480) - { - qcam->width = 640; - qcam->height = 480; - qcam->mode = QC_BILLIONS | QC_DECIMATION_1; - } -#endif - /* Ok we figured out what to use from our - wide choice */ - down(&qcam->lock); - parport_claim_or_block(qcam->pdev); - qc_setup(qcam); - parport_release(qcam->pdev); - up(&qcam->lock); - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - vw.x=0; - vw.y=0; - vw.width=qcam->width; - vw.height=qcam->height; - vw.chromakey=0; - vw.flags=0; - if(copy_to_user(arg, &vw, sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCGFBUF: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCKEY: - return 0; - case VIDIOCGFREQ: - return -EINVAL; - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - return -EINVAL; - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static long qcam_read(struct video_device *v, char *buf, unsigned long count, int noblock) -{ - struct qcam_device *qcam=(struct qcam_device *)v; - int len; - - down(&qcam->lock); - parport_claim_or_block(qcam->pdev); - /* Probably should have a semaphore against multiple users */ - len = qc_capture(qcam, buf,count); - parport_release(qcam->pdev); - up(&qcam->lock); - return len; -} - -/* video device template */ -static struct video_device qcam_template= -{ - "Colour QuickCam", - VID_TYPE_CAPTURE, - VID_HARDWARE_QCAM_C, - qcam_open, - qcam_close, - qcam_read, - qcam_write, - NULL, - qcam_ioctl, - NULL, - qcam_init_done, - NULL, - 0, - 0 -}; - -/* Initialize the QuickCam driver control structure. */ - -static struct qcam_device *qcam_init(struct parport *port) -{ - struct qcam_device *q; - - q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); - if(q==NULL) - return NULL; - - q->pport = port; - q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, - NULL, 0, NULL); - - q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0; - - if (q->pdev == NULL) - { - printk(KERN_ERR "c-qcam: couldn't register for %s.\n", - port->name); - kfree(q); - return NULL; - } - - memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); - - init_MUTEX(&q->lock); - q->width = q->ccd_width = 320; - q->height = q->ccd_height = 240; - q->mode = QC_MILLIONS | QC_DECIMATION_1; - q->contrast = 192; - q->brightness = 240; - q->whitebal = 128; - q->top = 1; - q->left = 14; - return q; -} - -static struct qcam_device *qcams[MAX_CAMS]; -static unsigned int num_cams = 0; - -int init_cqcam(struct parport *port) -{ - struct qcam_device *qcam; - - if (parport[0] != -1) - { - /* The user gave specific instructions */ - int i, found = 0; - for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) - { - if (parport[0] == port->number) - found = 1; - } - if (!found) - return -ENODEV; - } - - if (num_cams == MAX_CAMS) - return -ENOSPC; - - qcam = qcam_init(port); - if (qcam==NULL) - return -ENODEV; - - parport_claim_or_block(qcam->pdev); - - qc_reset(qcam); - - if (probe && qc_detect(qcam)==0) - { - parport_release(qcam->pdev); - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - - qc_setup(qcam); - - parport_release(qcam->pdev); - - if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1) - { - printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", - qcam->pport->name); - parport_unregister_device(qcam->pdev); - kfree(qcam); - return -ENODEV; - } - - printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", - qcam->vdev.minor, qcam->pport->name); - - qcams[num_cams++] = qcam; - - return 0; -} - -void close_cqcam(struct qcam_device *qcam) -{ - video_unregister_device(&qcam->vdev); - parport_unregister_device(qcam->pdev); - kfree(qcam); -} - -static void cq_attach(struct parport *port) -{ - init_cqcam(port); -} - -static void cq_detach(struct parport *port) -{ - /* Write this some day. */ -} - -static struct parport_driver cqcam_driver = { - "cqcam", - cq_attach, - cq_detach, - NULL -}; - -static int __init cqcam_init (void) -{ - printk(BANNER "\n"); - - return parport_register_driver(&cqcam_driver); -} - -static void __exit cqcam_cleanup (void) -{ - unsigned int i; - - for (i = 0; i < num_cams; i++) - close_cqcam(qcams[i]); - - parport_unregister_driver(&cqcam_driver); -} - -MODULE_AUTHOR("Philip Blundell "); -MODULE_DESCRIPTION(BANNER); -MODULE_PARM_DESC(parport ,"parport= for port detection method\n\ -probe=<0|1|2> for camera detection method\n\ -force_rgb=<0|1> for RGB data format (default BGR)"); -MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "i"); -MODULE_PARM(probe, "i"); -MODULE_PARM(force_rgb, "i"); - -module_init(cqcam_init); -module_exit(cqcam_cleanup); diff --git a/drivers/char/cpia.c b/drivers/char/cpia.c deleted file mode 100644 index d7d007f01..000000000 --- a/drivers/char/cpia.c +++ /dev/null @@ -1,3324 +0,0 @@ -/* - * cpia CPiA driver - * - * Supports CPiA based Video Camera's. - * - * (C) Copyright 1999-2000 Peter Pregler, - * (C) Copyright 1999-2000 Scott J. Bertin, - * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@valinux.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. - */ - -/* #define _CPIA_DEBUG_ define for verbose debug output */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif - -#include "cpia.h" - -#ifdef CONFIG_VIDEO_CPIA_PP -extern int cpia_pp_init(void); -#endif -#ifdef CONFIG_VIDEO_CPIA_USB -extern int cpia_usb_init(void); -#endif - -#ifdef MODULE -MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); -MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras"); -MODULE_SUPPORTED_DEVICE("video"); -#endif - -#define ABOUT "V4L-Driver for Vision CPiA based cameras" - -#ifndef VID_HARDWARE_CPIA -#define VID_HARDWARE_CPIA 24 /* FIXME -> from linux/videodev.h */ -#endif - -#define CPIA_MODULE_CPIA (0<<5) -#define CPIA_MODULE_SYSTEM (1<<5) -#define CPIA_MODULE_VP_CTRL (5<<5) -#define CPIA_MODULE_CAPTURE (6<<5) -#define CPIA_MODULE_DEBUG (7<<5) - -#define INPUT (DATA_IN << 8) -#define OUTPUT (DATA_OUT << 8) - -#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) -#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) -#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) -#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) -#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) -#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) -#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) -#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) - -#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) -#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) -#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) -#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) -#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) -#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) -#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) -#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) -#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) -#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) -#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) -#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) -#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) - -#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) -#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) -#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) -#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) -#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) -#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) -#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) -#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) -#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) -#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) -#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) -#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) -#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) -#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) -#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) -#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) - -#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) -#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) -#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) -#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) -#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) -#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) -#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) -#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) -#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) -#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) -#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) -#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) -#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) -#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) - -#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) -#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) -#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) -#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) -#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) -#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) -#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) - -enum { - FRAME_READY, /* Ready to grab into */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_UNUSED, /* Unused (no MCAPTURE) */ -}; - -#define COMMAND_NONE 0x0000 -#define COMMAND_SETCOMPRESSION 0x0001 -#define COMMAND_SETCOMPRESSIONTARGET 0x0002 -#define COMMAND_SETCOLOURPARAMS 0x0004 -#define COMMAND_SETFORMAT 0x0008 -#define COMMAND_PAUSE 0x0010 -#define COMMAND_RESUME 0x0020 -#define COMMAND_SETYUVTHRESH 0x0040 -#define COMMAND_SETECPTIMING 0x0080 -#define COMMAND_SETCOMPRESSIONPARAMS 0x0100 -#define COMMAND_SETEXPOSURE 0x0200 -#define COMMAND_SETCOLOURBALANCE 0x0400 -#define COMMAND_SETSENSORFPS 0x0800 -#define COMMAND_SETAPCOR 0x1000 -#define COMMAND_SETFLICKERCTRL 0x2000 -#define COMMAND_SETVLOFFSET 0x4000 - -/* Developer's Guide Table 5 p 3-34 - * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ -static u8 flicker_jumps[2][2][4] = -{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, - { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } -}; - -/* forward declaration of local function */ -static void reset_camera_struct(struct cam_data *cam); - -/********************************************************************** - * - * Memory management - * - * This is a shameless copy from the USB-cpia driver (linux kernel - * version 2.3.29 or so, I have no idea what this code actually does ;). - * Actually it seems to be a copy of a shameless copy of the bttv-driver. - * Or that is a copy of a shameless copy of ... (To the powers: is there - * no generic kernel-function to do this sort of stuff?) - * - * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says - * there will be one, but apparentely not yet - jerdfelt - * - **********************************************************************/ - -/* Given PGD from the address space's page table, return the kernel - * virtual mapping of the physical memory mapped at ADR. - */ -static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) -{ - unsigned long ret = 0UL; - pmd_t *pmd; - pte_t *ptep, pte; - - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, adr); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, adr); - pte = *ptep; - if (pte_present(pte)) { - ret = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE-1)); - } - } - } - return ret; -} - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long va, kva, ret; - - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = __pa(kva); - return ret; -} - -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr, page; - - /* Round it off to PAGE_SIZE */ - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); - - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); - adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr, page; - - if (!mem) - return; - - size += (PAGE_SIZE - 1); - size &= ~(PAGE_SIZE - 1); - - adr = (unsigned long) mem; - while (size > 0) { - page = kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); - adr += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - vfree(mem); -} - -/********************************************************************** - * - * /proc interface - * - **********************************************************************/ -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *cpia_proc_root=NULL; - -static int cpia_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *out = page; - int len, tmp; - struct cam_data *cam = data; - char tmpstr[20]; - - /* IMPORTANT: This output MUST be kept under PAGE_SIZE - * or we need to get more sophisticated. */ - - out += sprintf(out, "read-only\n-----------------------\n"); - out += sprintf(out, "V4L Driver version: %d.%d.%d\n", - CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); - out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", - cam->params.version.firmwareVersion, - cam->params.version.firmwareRevision, - cam->params.version.vcVersion, - cam->params.version.vcRevision); - out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", - cam->params.pnpID.vendor, cam->params.pnpID.product, - cam->params.pnpID.deviceRevision); - out += sprintf(out, "VP-Version: %d.%d %04x\n", - cam->params.vpVersion.vpVersion, - cam->params.vpVersion.vpRevision, - cam->params.vpVersion.cameraHeadID); - - out += sprintf(out, "system_state: %#04x\n", - cam->params.status.systemState); - out += sprintf(out, "grab_state: %#04x\n", - cam->params.status.grabState); - out += sprintf(out, "stream_state: %#04x\n", - cam->params.status.streamState); - out += sprintf(out, "fatal_error: %#04x\n", - cam->params.status.fatalError); - out += sprintf(out, "cmd_error: %#04x\n", - cam->params.status.cmdError); - out += sprintf(out, "debug_flags: %#04x\n", - cam->params.status.debugFlags); - out += sprintf(out, "vp_status: %#04x\n", - cam->params.status.vpStatus); - out += sprintf(out, "error_code: %#04x\n", - cam->params.status.errorCode); - out += sprintf(out, "video_size: %s\n", - cam->params.format.videoSize == VIDEOSIZE_CIF ? - "CIF " : "QCIF"); - out += sprintf(out, "sub_sample: %s\n", - cam->params.format.subSample == SUBSAMPLE_420 ? - "420" : "422"); - out += sprintf(out, "yuv_order: %s\n", - cam->params.format.yuvOrder == YUVORDER_YUYV ? - "YUYV" : "UYVY"); - out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n", - cam->params.roi.colStart*8, - cam->params.roi.rowStart*4, - cam->params.roi.colEnd*8, - cam->params.roi.rowEnd*4); - out += sprintf(out, "actual_fps: %3d\n", cam->fps); - out += sprintf(out, "transfer_rate: %4dkB/s\n", - cam->transfer_rate); - - out += sprintf(out, "\nread-write\n"); - out += sprintf(out, "----------------------- current min" - " max default comment\n"); - out += sprintf(out, "brightness: %8d %8d %8d %8d\n", - cam->params.colourParams.brightness, 0, 100, 50); - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits contrast to 80 */ - tmp = 80; - else - tmp = 96; - - out += sprintf(out, "contrast: %8d %8d %8d %8d" - " steps of 8\n", - cam->params.colourParams.contrast, 0, tmp, 48); - out += sprintf(out, "saturation: %8d %8d %8d %8d\n", - cam->params.colourParams.saturation, 0, 100, 50); - tmp = (25000+5000*cam->params.sensorFps.baserate)/ - (1<params.sensorFps.divisor); - out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n", - tmp/1000, tmp%1000, 3, 30, 15); - out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n", - 2*cam->params.streamStartLine, 0, - cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, - cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); - out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n", - cam->params.ecpTiming ? "slow" : "normal", "slow", - "normal", "normal"); - - if (cam->params.colourBalance.balanceModeIsAuto) { - sprintf(tmpstr, "auto"); - } else { - sprintf(tmpstr, "manual"); - } - out += sprintf(out, "color_balance_mode: %8s %8s %8s" - " %8s\n", tmpstr, "manual", "auto", "auto"); - out += sprintf(out, "red_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.redGain, 0, 212, 32); - out += sprintf(out, "green_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.greenGain, 0, 212, 6); - out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.blueGain, 0, 212, 92); - - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits gain to 2 */ - sprintf(tmpstr, "%8d %8d", 1, 2); - else - sprintf(tmpstr, "1,2,4,8"); - - if (cam->params.exposure.gainMode == 0) - out += sprintf(out, "max_gain: unknown %18s" - " %8d\n", tmpstr, 2); - else - out += sprintf(out, "max_gain: %8d %18s %8d\n", - 1<<(cam->params.exposure.gainMode-1), tmpstr, 2); - - switch(cam->params.exposure.expMode) { - case 1: - case 3: - sprintf(tmpstr, "manual"); - break; - case 2: - sprintf(tmpstr, "auto"); - break; - default: - sprintf(tmpstr, "unknown"); - break; - } - out += sprintf(out, "exposure_mode: %8s %8s %8s" - " %8s\n", tmpstr, "manual", "auto", "auto"); - out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n", - (2-cam->params.exposure.centreWeight) ? "on" : "off", - "off", "on", "on"); - out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", - 1<params.exposure.gain, 1, 1); - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits fineExp to 127 */ - tmp = 255; - else - tmp = 511; - - out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n", - cam->params.exposure.fineExp*2, 0, tmp, 0); - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits coarseExpHi to 0 */ - tmp = 255; - else - tmp = 65535; - - out += sprintf(out, "coarse_exp: %8d %8d %8d" - " %8d\n", cam->params.exposure.coarseExpLo+ - 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); - out += sprintf(out, "red_comp: %8d %8d %8d %8d\n", - cam->params.exposure.redComp, 220, 255, 220); - out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n", - cam->params.exposure.green1Comp, 214, 255, 214); - out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n", - cam->params.exposure.green2Comp, 214, 255, 214); - out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n", - cam->params.exposure.blueComp, 230, 255, 230); - - out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain1, 0, 0xff, 0x1c); - out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain2, 0, 0xff, 0x1a); - out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain4, 0, 0xff, 0x2d); - out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain8, 0, 0xff, 0x2a); - out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain1, 0, 255, 24); - out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain2, 0, 255, 28); - out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain4, 0, 255, 30); - out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain8, 0, 255, 30); - out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n", - cam->params.flickerControl.flickerMode ? "on" : "off", - "off", "on", "off"); - out += sprintf(out, "mains_frequency: %8d %8d %8d %8d" - " only 50/60\n", - cam->mainsFreq ? 60 : 50, 50, 60, 50); - out += sprintf(out, "allowable_overexposure: %8d %8d %8d %8d\n", - cam->params.flickerControl.allowableOverExposure, 0, - 255, 0); - out += sprintf(out, "compression_mode: "); - switch(cam->params.compression.mode) { - case CPIA_COMPRESSION_NONE: - out += sprintf(out, "%8s", "none"); - break; - case CPIA_COMPRESSION_AUTO: - out += sprintf(out, "%8s", "auto"); - break; - case CPIA_COMPRESSION_MANUAL: - out += sprintf(out, "%8s", "manual"); - break; - default: - out += sprintf(out, "%8s", "unknown"); - break; - } - out += sprintf(out, " none,auto,manual auto\n"); - out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n", - cam->params.compression.decimation == - DECIMATION_ENAB ? "on":"off", "off", "off", - "off"); - out += sprintf(out, "compression_target: %9s %9s %9s %9s\n", - cam->params.compressionTarget.frTargeting == - CPIA_COMPRESSION_TARGET_FRAMERATE ? - "framerate":"quality", - "framerate", "quality", "quality"); - out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n", - cam->params.compressionTarget.targetFR, 0, 30, 7); - out += sprintf(out, "target_quality: %8d %8d %8d %8d\n", - cam->params.compressionTarget.targetQ, 0, 255, 10); - out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n", - cam->params.yuvThreshold.yThreshold, 0, 31, 15); - out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n", - cam->params.yuvThreshold.uvThreshold, 0, 31, 15); - out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n", - cam->params.compressionParams.hysteresis, 0, 255, 3); - out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n", - cam->params.compressionParams.threshMax, 0, 255, 11); - out += sprintf(out, "small_step: %8d %8d %8d %8d\n", - cam->params.compressionParams.smallStep, 0, 255, 1); - out += sprintf(out, "large_step: %8d %8d %8d %8d\n", - cam->params.compressionParams.largeStep, 0, 255, 3); - out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n", - cam->params.compressionParams.decimationHysteresis, - 0, 255, 2); - out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n", - cam->params.compressionParams.frDiffStepThresh, - 0, 255, 5); - out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n", - cam->params.compressionParams.qDiffStepThresh, - 0, 255, 3); - out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", - cam->params.compressionParams.decimationThreshMod, - 0, 255, 2); - - len = out - page; - len -= off; - if (len < count) { - *eof = 1; - if (len <= 0) return 0; - } else - len = count; - - *start = page + off; - return len; -} - -static int cpia_write_proc(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct cam_data *cam = data; - struct cam_params new_params; - int retval, find_colon; - int size = count; - unsigned long val; - u32 command_flags = 0; - u8 new_mains; - - if (down_interruptible(&cam->param_lock)) - return -ERESTARTSYS; - - /* - * Skip over leading whitespace - */ - while (count && isspace(*buffer)) { - --count; - ++buffer; - } - - memcpy(&new_params, &cam->params, sizeof(struct cam_params)); - new_mains = cam->mainsFreq; - -#define MATCH(x) \ - ({ \ - int _len = strlen(x), _ret, _colon_found; \ - _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \ - if (_ret) { \ - buffer += _len; \ - count -= _len; \ - if (find_colon) { \ - _colon_found = 0; \ - while (count && (*buffer == ' ' || *buffer == '\t' || \ - (!_colon_found && *buffer == ':'))) { \ - if (*buffer == ':') \ - _colon_found = 1; \ - --count; \ - ++buffer; \ - } \ - if (!count || !_colon_found) \ - retval = -EINVAL; \ - find_colon = 0; \ - } \ - } \ - _ret; \ - }) -#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \ - new_params.version.firmwareRevision == (y)) -#define VALUE \ - ({ \ - char *_p; \ - unsigned long int _ret; \ - _ret = simple_strtoul(buffer, &_p, 0); \ - if (_p == buffer) \ - retval = -EINVAL; \ - else { \ - count -= _p - buffer; \ - buffer = _p; \ - } \ - _ret; \ - }) - - retval = 0; - while (count && !retval) { - find_colon = 1; - if (MATCH("brightness")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 100) - new_params.colourParams.brightness = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURPARAMS; - } else if (MATCH("contrast")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 100) { - /* contrast is in steps of 8, so round*/ - val = ((val + 3) / 8) * 8; - /* 1-02 firmware limits contrast to 80*/ - if (FIRMWARE_VERSION(1,2) && val > 80) - val = 80; - - new_params.colourParams.contrast = val; - } else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURPARAMS; - } else if (MATCH("saturation")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 100) - new_params.colourParams.saturation = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURPARAMS; - } else if (MATCH("sensor_fps")) { - if (!retval) - val = VALUE; - - if (!retval) { - /* find values so that sensorFPS is minimized, - * but >= val */ - if (val > 30) - retval = -EINVAL; - else if (val > 25) { - new_params.sensorFps.divisor = 0; - new_params.sensorFps.baserate = 1; - } else if (val > 15) { - new_params.sensorFps.divisor = 0; - new_params.sensorFps.baserate = 0; - } else if (val > 12) { - new_params.sensorFps.divisor = 1; - new_params.sensorFps.baserate = 1; - } else if (val > 7) { - new_params.sensorFps.divisor = 1; - new_params.sensorFps.baserate = 0; - } else if (val > 6) { - new_params.sensorFps.divisor = 2; - new_params.sensorFps.baserate = 1; - } else if (val > 3) { - new_params.sensorFps.divisor = 2; - new_params.sensorFps.baserate = 0; - } else { - new_params.sensorFps.divisor = 3; - /* Either base rate would work here */ - new_params.sensorFps.baserate = 1; - } - new_params.flickerControl.coarseJump = - flicker_jumps[new_mains] - [new_params.sensorFps.baserate] - [new_params.sensorFps.divisor]; - if (new_params.flickerControl.flickerMode) - command_flags |= COMMAND_SETFLICKERCTRL; - } - command_flags |= COMMAND_SETSENSORFPS; - } else if (MATCH("stream_start_line")) { - if (!retval) - val = VALUE; - - if (!retval) { - int max_line = 288; - - if (new_params.format.videoSize == VIDEOSIZE_QCIF) - max_line = 144; - if (val <= max_line) - new_params.streamStartLine = val/2; - else - retval = -EINVAL; - } - } else if (MATCH("ecp_timing")) { - if (!retval && MATCH("normal")) - new_params.ecpTiming = 0; - else if (!retval && MATCH("slow")) - new_params.ecpTiming = 1; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETECPTIMING; - } else if (MATCH("color_balance_mode")) { - if (!retval && MATCH("manual")) - new_params.colourBalance.balanceModeIsAuto = 0; - else if (!retval && MATCH("auto")) - new_params.colourBalance.balanceModeIsAuto = 1; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("red_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 212) - new_params.colourBalance.redGain = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("green_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 212) - new_params.colourBalance.greenGain = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("blue_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 212) - new_params.colourBalance.blueGain = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("max_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - /* 1-02 firmware limits gain to 2 */ - if (FIRMWARE_VERSION(1,2) && val > 2) - val = 2; - switch(val) { - case 1: - new_params.exposure.gainMode = 1; - break; - case 2: - new_params.exposure.gainMode = 2; - break; - case 4: - new_params.exposure.gainMode = 3; - break; - case 8: - new_params.exposure.gainMode = 4; - break; - default: - retval = -EINVAL; - break; - } - } - command_flags |= COMMAND_SETEXPOSURE; - } else if (MATCH("exposure_mode")) { - if (!retval && MATCH("auto")) - new_params.exposure.expMode = 2; - else if (!retval && MATCH("manual")) { - if (new_params.exposure.expMode == 2) - new_params.exposure.expMode = 3; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - - command_flags |= COMMAND_SETEXPOSURE; - } else if (MATCH("centre_weight")) { - if (!retval && MATCH("on")) - new_params.exposure.centreWeight = 1; - else if (!retval && MATCH("off")) - new_params.exposure.centreWeight = 2; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETEXPOSURE; - } else if (MATCH("gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - switch(val) { - case 1: - new_params.exposure.gain = 0; - new_params.exposure.expMode = 1; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - break; - case 2: - new_params.exposure.gain = 1; - new_params.exposure.expMode = 1; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - break; - case 4: - new_params.exposure.gain = 2; - new_params.exposure.expMode = 1; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - break; - case 8: - new_params.exposure.gain = 3; - new_params.exposure.expMode = 1; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - break; - default: - retval = -EINVAL; - break; - } - command_flags |= COMMAND_SETEXPOSURE; - if (new_params.exposure.gain > - new_params.exposure.gainMode-1) - retval = -EINVAL; - } - } else if (MATCH("fine_exp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val < 256) { - /* 1-02 firmware limits fineExp to 127*/ - if (FIRMWARE_VERSION(1,2) && val > 127) - val = 127; - new_params.exposure.fineExp = val; - new_params.exposure.expMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } - } else if (MATCH("coarse_exp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val < 65536) { - /* 1-02 firmware limits - * coarseExp to 255 */ - if (FIRMWARE_VERSION(1,2) && val > 255) - val = 255; - new_params.exposure.coarseExpLo = - val & 0xff; - new_params.exposure.coarseExpHi = - val >> 8; - new_params.exposure.expMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } - } else if (MATCH("red_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= 220 && val <= 255) { - new_params.exposure.redComp = val; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("green1_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= 214 && val <= 255) { - new_params.exposure.green1Comp = val; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("green2_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= 214 && val <= 255) { - new_params.exposure.green2Comp = val; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("blue_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= 230 && val <= 255) { - new_params.exposure.blueComp = val; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain1")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain1 = val; - else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain2")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain2 = val; - else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain4")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain4 = val; - else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain8")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain8 = val; - else - retval = -EINVAL; - } - } else if (MATCH("vl_offset_gain1")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain1 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("vl_offset_gain2")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain2 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("vl_offset_gain4")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain4 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("vl_offset_gain8")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain8 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("flicker_control")) { - if (!retval && MATCH("on")) { - new_params.flickerControl.flickerMode = 1; - new_params.exposure.expMode = 2; - command_flags |= COMMAND_SETEXPOSURE; - } else if (!retval && MATCH("off")) - new_params.flickerControl.flickerMode = 0; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETFLICKERCTRL; - } else if (MATCH("mains_frequency")) { - if (!retval && MATCH("50")) { - new_mains = 0; - new_params.flickerControl.coarseJump = - flicker_jumps[new_mains] - [new_params.sensorFps.baserate] - [new_params.sensorFps.divisor]; - if (new_params.flickerControl.flickerMode) - command_flags |= COMMAND_SETFLICKERCTRL; - } else if (!retval && MATCH("60")) { - new_mains = 1; - new_params.flickerControl.coarseJump = - flicker_jumps[new_mains] - [new_params.sensorFps.baserate] - [new_params.sensorFps.divisor]; - if (new_params.flickerControl.flickerMode) - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } else if (MATCH("allowable_overexposure")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) { - new_params.flickerControl. - allowableOverExposure = val; - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } - } else if (MATCH("compression_mode")) { - if (!retval && MATCH("none")) - new_params.compression.mode = - CPIA_COMPRESSION_NONE; - else if (!retval && MATCH("auto")) - new_params.compression.mode = - CPIA_COMPRESSION_AUTO; - else if (!retval && MATCH("manual")) - new_params.compression.mode = - CPIA_COMPRESSION_MANUAL; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOMPRESSION; - } else if (MATCH("decimation_enable")) { - if (!retval && MATCH("off")) - new_params.compression.decimation = 0; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOMPRESSION; - } else if (MATCH("compression_target")) { - if (!retval && MATCH("quality")) - new_params.compressionTarget.frTargeting = - CPIA_COMPRESSION_TARGET_QUALITY; - else if (!retval && MATCH("framerate")) - new_params.compressionTarget.frTargeting = - CPIA_COMPRESSION_TARGET_FRAMERATE; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOMPRESSIONTARGET; - } else if (MATCH("target_framerate")) { - if (!retval) - val = VALUE; - - if (!retval) - new_params.compressionTarget.targetFR = val; - command_flags |= COMMAND_SETCOMPRESSIONTARGET; - } else if (MATCH("target_quality")) { - if (!retval) - val = VALUE; - - if (!retval) - new_params.compressionTarget.targetQ = val; - - command_flags |= COMMAND_SETCOMPRESSIONTARGET; - } else if (MATCH("y_threshold")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val < 32) - new_params.yuvThreshold.yThreshold = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETYUVTHRESH; - } else if (MATCH("uv_threshold")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val < 32) - new_params.yuvThreshold.uvThreshold = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETYUVTHRESH; - } else if (MATCH("hysteresis")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.hysteresis = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("threshold_max")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.threshMax = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("small_step")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.smallStep = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("large_step")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.largeStep = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("decimation_hysteresis")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.decimationHysteresis = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("fr_diff_step_thresh")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.frDiffStepThresh = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("q_diff_step_thresh")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.qDiffStepThresh = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("decimation_thresh_mod")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.decimationThreshMod = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else { - DBG("No match found\n"); - retval = -EINVAL; - } - - if (!retval) { - while (count && isspace(*buffer) && *buffer != '\n') { - --count; - ++buffer; - } - if (count) { - if (*buffer != '\n' && *buffer != ';') - retval = -EINVAL; - else { - --count; - ++buffer; - } - } - } - } -#undef MATCH -#undef FIRMWARE_VERSION -#undef VALUE -#undef FIND_VALUE -#undef FIND_END - if (!retval) { - if (command_flags & COMMAND_SETCOLOURPARAMS) { - /* Adjust cam->vp to reflect these changes */ - cam->vp.brightness = - new_params.colourParams.brightness*65535/100; - cam->vp.contrast = - new_params.colourParams.contrast*65535/100; - cam->vp.colour = - new_params.colourParams.saturation*65535/100; - } - - memcpy(&cam->params, &new_params, sizeof(struct cam_params)); - cam->mainsFreq = new_mains; - cam->cmd_queue |= command_flags; - retval = size; - } else - DBG("error: %d\n", retval); - - up(&cam->param_lock); - - return retval; -} - -static void create_proc_cpia_cam(struct cam_data *cam) -{ - char name[7]; - struct proc_dir_entry *ent; - - if (!cpia_proc_root || !cam) - return; - - sprintf(name, "video%d", cam->vdev.minor); - - ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); - if (!ent) - return; - - ent->data = cam; - ent->read_proc = cpia_read_proc; - ent->write_proc = cpia_write_proc; - ent->size = 3626; - cam->proc_entry = ent; -} - -static void destroy_proc_cpia_cam(struct cam_data *cam) -{ - char name[7]; - - if (!cam || !cam->proc_entry) - return; - - sprintf(name, "video%d", cam->vdev.minor); - remove_proc_entry(name, cpia_proc_root); - cam->proc_entry = NULL; -} - -static void proc_cpia_create(void) -{ - cpia_proc_root = create_proc_entry("cpia", S_IFDIR, 0); - - if (cpia_proc_root) - cpia_proc_root->owner = THIS_MODULE; - else - LOG("Unable to initialise /proc/cpia\n"); -} - -static void proc_cpia_destroy(void) -{ - remove_proc_entry("cpia", 0); -} -#endif /* CONFIG_PROC_FS */ - -/* ----------------------- debug functions ---------------------- */ - -#define printstatus(cam) \ - DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\ - cam->params.status.systemState, cam->params.status.grabState, \ - cam->params.status.streamState, cam->params.status.fatalError, \ - cam->params.status.cmdError, cam->params.status.debugFlags, \ - cam->params.status.vpStatus, cam->params.status.errorCode); - -/* ----------------------- v4l helpers -------------------------- */ - -/* supported frame palettes and depths */ -static inline int valid_mode(u16 palette, u16 depth) -{ - return (palette == VIDEO_PALETTE_GREY && depth == 8) || - (palette == VIDEO_PALETTE_RGB555 && depth == 16) || - (palette == VIDEO_PALETTE_RGB565 && depth == 16) || - (palette == VIDEO_PALETTE_RGB24 && depth == 24) || - (palette == VIDEO_PALETTE_RGB32 && depth == 32) || - (palette == VIDEO_PALETTE_YUV422 && depth == 16) || - (palette == VIDEO_PALETTE_YUYV && depth == 16) || - (palette == VIDEO_PALETTE_UYVY && depth == 16); -} - -static int match_videosize( int width, int height ) -{ - /* return the best match, where 'best' is as always - * the largest that is not bigger than what is requested. */ - if (width>=352 && height>=288) - return VIDEOSIZE_352_288; /* CIF */ - - if (width>=320 && height>=240) - return VIDEOSIZE_320_240; /* SIF */ - - if (width>=288 && height>=216) - return VIDEOSIZE_288_216; - - if (width>=256 && height>=192) - return VIDEOSIZE_256_192; - - if (width>=224 && height>=168) - return VIDEOSIZE_224_168; - - if (width>=192 && height>=144) - return VIDEOSIZE_192_144; - - if (width>=176 && height>=144) - return VIDEOSIZE_176_144; /* QCIF */ - - if (width>=160 && height>=120) - return VIDEOSIZE_160_120; /* QSIF */ - - if (width>=128 && height>=96) - return VIDEOSIZE_128_96; - - if (width>=88 && height>=72) - return VIDEOSIZE_88_72; - - if (width>=64 && height>=48) - return VIDEOSIZE_64_48; - - if (width>=48 && height>=48) - return VIDEOSIZE_48_48; - - return -1; -} - -/* these are the capture sizes we support */ -static void set_vw_size(struct cam_data *cam) -{ - /* the col/row/start/end values are the result of simple math */ - /* study the SetROI-command in cpia developers guide p 2-22 */ - /* streamStartLine is set to the recommended value in the cpia */ - /* developers guide p 3-37 */ - switch(cam->video_size) { - case VIDEOSIZE_CIF: - cam->vw.width = 352; - cam->vw.height = 288; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=0; - cam->params.roi.colEnd=44; - cam->params.roi.rowStart=0; - cam->params.roi.rowEnd=72; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_SIF: - cam->vw.width = 320; - cam->vw.height = 240; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=2; - cam->params.roi.colEnd=42; - cam->params.roi.rowStart=6; - cam->params.roi.rowEnd=66; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_288_216: - cam->vw.width = 288; - cam->vw.height = 216; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=4; - cam->params.roi.colEnd=40; - cam->params.roi.rowStart=9; - cam->params.roi.rowEnd=63; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_256_192: - cam->vw.width = 256; - cam->vw.height = 192; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=6; - cam->params.roi.colEnd=38; - cam->params.roi.rowStart=12; - cam->params.roi.rowEnd=60; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_224_168: - cam->vw.width = 224; - cam->vw.height = 168; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=8; - cam->params.roi.colEnd=36; - cam->params.roi.rowStart=15; - cam->params.roi.rowEnd=57; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_192_144: - cam->vw.width = 192; - cam->vw.height = 144; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=10; - cam->params.roi.colEnd=34; - cam->params.roi.rowStart=18; - cam->params.roi.rowEnd=54; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_QCIF: - cam->vw.width = 176; - cam->vw.height = 144; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=0; - cam->params.roi.colEnd=22; - cam->params.roi.rowStart=0; - cam->params.roi.rowEnd=36; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_QSIF: - cam->vw.width = 160; - cam->vw.height = 120; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=1; - cam->params.roi.colEnd=21; - cam->params.roi.rowStart=3; - cam->params.roi.rowEnd=33; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_128_96: - cam->vw.width = 128; - cam->vw.height = 96; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=3; - cam->params.roi.colEnd=19; - cam->params.roi.rowStart=6; - cam->params.roi.rowEnd=30; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_88_72: - cam->vw.width = 88; - cam->vw.height = 72; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=5; - cam->params.roi.colEnd=16; - cam->params.roi.rowStart=9; - cam->params.roi.rowEnd=27; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_64_48: - cam->vw.width = 64; - cam->vw.height = 48; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=7; - cam->params.roi.colEnd=15; - cam->params.roi.rowStart=12; - cam->params.roi.rowEnd=24; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_48_48: - cam->vw.width = 48; - cam->vw.height = 48; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=8; - cam->params.roi.colEnd=14; - cam->params.roi.rowStart=6; - cam->params.roi.rowEnd=30; - cam->params.streamStartLine = 60; - break; - default: - LOG("bad videosize value: %d\n", cam->video_size); - } - - return; -} - -static int allocate_frame_buf(struct cam_data *cam) -{ - int i; - - cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE); - if (!cam->frame_buf) - return -ENOBUFS; - - for (i = 0; i < FRAME_NUM; i++) - cam->frame[i].data = cam->frame_buf + i * CPIA_MAX_FRAME_SIZE; - - return 0; -} - -static int free_frame_buf(struct cam_data *cam) -{ - int i; - - rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE); - cam->frame_buf = 0; - for (i=0; i < FRAME_NUM; i++) - cam->frame[i].data = NULL; - - return 0; -} - - -static void inline free_frames(struct cpia_frame frame[FRAME_NUM]) -{ - int i; - - for (i=0; i < FRAME_NUM; i++) - frame[i].state = FRAME_UNUSED; - return; -} - -/********************************************************************** - * - * General functions - * - **********************************************************************/ -/* send an arbitrary command to the camera */ -static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) -{ - int retval, datasize; - u8 cmd[8], data[8]; - - switch(command) { - case CPIA_COMMAND_GetCPIAVersion: - case CPIA_COMMAND_GetPnPID: - case CPIA_COMMAND_GetCameraStatus: - case CPIA_COMMAND_GetVPVersion: - datasize=8; - break; - case CPIA_COMMAND_GetColourParams: - case CPIA_COMMAND_GetColourBalance: - case CPIA_COMMAND_GetExposure: - down(&cam->param_lock); - datasize=8; - break; - default: - datasize=0; - break; - } - - cmd[0] = command>>8; - cmd[1] = command&0xff; - cmd[2] = a; - cmd[3] = b; - cmd[4] = c; - cmd[5] = d; - cmd[6] = datasize; - cmd[7] = 0; - - retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); - if (retval) { - DBG("%x - failed, retval=%d\n", command, retval); - if (command == CPIA_COMMAND_GetColourParams || - command == CPIA_COMMAND_GetColourBalance || - command == CPIA_COMMAND_GetExposure) - up(&cam->param_lock); - } else { - switch(command) { - case CPIA_COMMAND_GetCPIAVersion: - cam->params.version.firmwareVersion = data[0]; - cam->params.version.firmwareRevision = data[1]; - cam->params.version.vcVersion = data[2]; - cam->params.version.vcRevision = data[3]; - break; - case CPIA_COMMAND_GetPnPID: - cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8); - cam->params.pnpID.product = data[2]+(((u16)data[3])<<8); - cam->params.pnpID.deviceRevision = - data[4]+(((u16)data[5])<<8); - break; - case CPIA_COMMAND_GetCameraStatus: - cam->params.status.systemState = data[0]; - cam->params.status.grabState = data[1]; - cam->params.status.streamState = data[2]; - cam->params.status.fatalError = data[3]; - cam->params.status.cmdError = data[4]; - cam->params.status.debugFlags = data[5]; - cam->params.status.vpStatus = data[6]; - cam->params.status.errorCode = data[7]; - break; - case CPIA_COMMAND_GetVPVersion: - cam->params.vpVersion.vpVersion = data[0]; - cam->params.vpVersion.vpRevision = data[1]; - cam->params.vpVersion.cameraHeadID = - data[2]+(((u16)data[3])<<8); - break; - case CPIA_COMMAND_GetColourParams: - cam->params.colourParams.brightness = data[0]; - cam->params.colourParams.contrast = data[1]; - cam->params.colourParams.saturation = data[2]; - up(&cam->param_lock); - break; - case CPIA_COMMAND_GetColourBalance: - cam->params.colourBalance.redGain = data[0]; - cam->params.colourBalance.greenGain = data[1]; - cam->params.colourBalance.blueGain = data[2]; - up(&cam->param_lock); - break; - case CPIA_COMMAND_GetExposure: - cam->params.exposure.gain = data[0]; - cam->params.exposure.fineExp = data[1]; - cam->params.exposure.coarseExpLo = data[2]; - cam->params.exposure.coarseExpHi = data[3]; - cam->params.exposure.redComp = data[4]; - cam->params.exposure.green1Comp = data[5]; - cam->params.exposure.green2Comp = data[6]; - cam->params.exposure.blueComp = data[7]; - /* If the *Comp parameters are wacko, generate - * a warning, and reset them back to default - * values. - rich@annexia.org - */ - if (cam->params.exposure.redComp < 220 || - cam->params.exposure.redComp > 255 || - cam->params.exposure.green1Comp < 214 || - cam->params.exposure.green1Comp > 255 || - cam->params.exposure.green2Comp < 214 || - cam->params.exposure.green2Comp > 255 || - cam->params.exposure.blueComp < 230 || - cam->params.exposure.blueComp > 255) - { - printk (KERN_WARNING "*_comp parameters have gone AWOL (%d/%d/%d/%d) - reseting them\n", - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); - cam->params.exposure.redComp = 220; - cam->params.exposure.green1Comp = 214; - cam->params.exposure.green2Comp = 214; - cam->params.exposure.blueComp = 230; - } - up(&cam->param_lock); - break; - default: - break; - } - } - return retval; -} - -/* send a command to the camera with an additional data transaction */ -static int do_command_extended(struct cam_data *cam, u16 command, - u8 a, u8 b, u8 c, u8 d, - u8 e, u8 f, u8 g, u8 h, - u8 i, u8 j, u8 k, u8 l) -{ - int retval; - u8 cmd[8], data[8]; - - cmd[0] = command>>8; - cmd[1] = command&0xff; - cmd[2] = a; - cmd[3] = b; - cmd[4] = c; - cmd[5] = d; - cmd[6] = 8; - cmd[7] = 0; - data[0] = e; - data[1] = f; - data[2] = g; - data[3] = h; - data[4] = i; - data[5] = j; - data[6] = k; - data[7] = l; - - retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); - if (retval) - LOG("%x - failed\n", command); - - return retval; -} - -/********************************************************************** - * - * Colorspace conversion - * - **********************************************************************/ -#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) - -static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt, - int in_uyvy, int mmap_kludge) -{ - int y, u, v, r, g, b, y1; - - switch(out_fmt) { - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_RGB24: - case VIDEO_PALETTE_RGB32: - if (in_uyvy) { - u = *yuv++ - 128; - y = (*yuv++ - 16) * 76310; - v = *yuv++ - 128; - y1 = (*yuv - 16) * 76310; - } else { - y = (*yuv++ - 16) * 76310; - u = *yuv++ - 128; - y1 = (*yuv++ - 16) * 76310; - v = *yuv - 128; - } - r = 104635 * v; - g = -25690 * u + -53294 * v; - b = 132278 * u; - break; - default: - y = *yuv++; - u = *yuv++; - y1 = *yuv++; - v = *yuv; - /* Just to avoid compiler warnings */ - r = 0; - g = 0; - b = 0; - break; - } - switch(out_fmt) { - case VIDEO_PALETTE_RGB555: - *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3); - *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6); - *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3); - *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6); - return 4; - case VIDEO_PALETTE_RGB565: - *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3); - *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5); - *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3); - *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5); - return 4; - case VIDEO_PALETTE_RGB24: - if (mmap_kludge) { - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(b+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(r+y1); - } else { - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(r+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(b+y1); - } - return 6; - case VIDEO_PALETTE_RGB32: - if (mmap_kludge) { - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(r+y); - rgb++; - *rgb++ = LIMIT(b+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(r+y1); - } else { - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(b+y); - rgb++; - *rgb++ = LIMIT(r+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(b+y1); - } - return 8; - case VIDEO_PALETTE_GREY: - *rgb++ = y; - *rgb = y1; - return 2; - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - *rgb++ = y; - *rgb++ = u; - *rgb++ = y1; - *rgb = v; - return 4; - case VIDEO_PALETTE_UYVY: - *rgb++ = u; - *rgb++ = y; - *rgb++ = v; - *rgb = y1; - return 4; - default: - DBG("Empty: %d\n", out_fmt); - return 0; - } -} - -static int skipcount(int count, int fmt) -{ - switch(fmt) { - case VIDEO_PALETTE_GREY: - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_UYVY: - return 2*count; - case VIDEO_PALETTE_RGB24: - return 3*count; - case VIDEO_PALETTE_RGB32: - return 4*count; - default: - return 0; - } -} - -static int parse_picture(struct cam_data *cam, int size) -{ - u8 *obuf, *ibuf, *end_obuf; - int ll, in_uyvy, compressed, origsize, out_fmt; - - /* make sure params don't change while we are decoding */ - down(&cam->param_lock); - - obuf = cam->decompressed_frame.data; - end_obuf = obuf+CPIA_MAX_FRAME_SIZE; - ibuf = cam->raw_image; - origsize = size; - out_fmt = cam->vp.palette; - - if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) { - LOG("header not found\n"); - up(&cam->param_lock); - return -1; - } - - if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) { - LOG("wrong video size\n"); - up(&cam->param_lock); - return -1; - } - - if (ibuf[17] != SUBSAMPLE_422) { - LOG("illegal subtype %d\n",ibuf[17]); - up(&cam->param_lock); - return -1; - } - - if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) { - LOG("illegal yuvorder %d\n",ibuf[18]); - up(&cam->param_lock); - return -1; - } - in_uyvy = ibuf[18] == YUVORDER_UYVY; - -#if 0 - /* FIXME: ROI mismatch occurs when switching capture sizes */ - if ((ibuf[24] != cam->params.roi.colStart) || - (ibuf[25] != cam->params.roi.colEnd) || - (ibuf[26] != cam->params.roi.rowStart) || - (ibuf[27] != cam->params.roi.rowEnd)) { - LOG("ROI mismatch\n"); - up(&cam->param_lock); - return -1; - } -#endif - - if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) { - LOG("illegal compression %d\n",ibuf[28]); - up(&cam->param_lock); - return -1; - } - compressed = (ibuf[28] == COMPRESSED); - - if (ibuf[29] != NO_DECIMATION) { - LOG("decimation not supported\n"); - up(&cam->param_lock); - return -1; - } - - cam->params.yuvThreshold.yThreshold = ibuf[30]; - cam->params.yuvThreshold.uvThreshold = ibuf[31]; - cam->params.status.systemState = ibuf[32]; - cam->params.status.grabState = ibuf[33]; - cam->params.status.streamState = ibuf[34]; - cam->params.status.fatalError = ibuf[35]; - cam->params.status.cmdError = ibuf[36]; - cam->params.status.debugFlags = ibuf[37]; - cam->params.status.vpStatus = ibuf[38]; - cam->params.status.errorCode = ibuf[39]; - cam->fps = ibuf[41]; - up(&cam->param_lock); - - ibuf += FRAME_HEADER_SIZE; - size -= FRAME_HEADER_SIZE; - ll = ibuf[0] | (ibuf[1] << 8); - ibuf += 2; - - while (size > 0) { - size -= (ll+2); - if (size < 0) { - LOG("Insufficient data in buffer\n"); - return -1; - } - - while (ll > 1) { - if (!compressed || (compressed && !(*ibuf & 1))) { - obuf += yuvconvert(ibuf, obuf, out_fmt, - in_uyvy, cam->mmap_kludge); - ibuf += 4; - ll -= 4; - } else { - /*skip compressed interval from previous frame*/ - int skipsize = skipcount(*ibuf >> 1, out_fmt); - obuf += skipsize; - if (obuf > end_obuf) { - LOG("Insufficient data in buffer\n"); - return -1; - } - ++ibuf; - ll--; - } - } - if (ll == 1) { - if (*ibuf != EOL) { - LOG("EOL not found giving up after %d/%d" - " bytes\n", origsize-size, origsize); - return -1; - } - - ibuf++; /* skip over EOL */ - - if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) && - (ibuf[2] == EOI) && (ibuf[3] == EOI)) { - size -= 4; - break; - } - - if (size > 1) { - ll = ibuf[0] | (ibuf[1] << 8); - ibuf += 2; /* skip over line length */ - } - } else { - LOG("line length was not 1 but %d after %d/%d bytes\n", - ll, origsize-size, origsize); - return -1; - } - } - - cam->decompressed_frame.count = obuf-cam->decompressed_frame.data; - - return cam->decompressed_frame.count; -} - -/* InitStreamCap wrapper to select correct start line */ -static inline int init_stream_cap(struct cam_data *cam) -{ - return do_command(cam, CPIA_COMMAND_InitStreamCap, - 0, cam->params.streamStartLine, 0, 0); -} - -/* update various camera modes and settings */ -static void dispatch_commands(struct cam_data *cam) -{ - down(&cam->param_lock); - if (cam->cmd_queue==COMMAND_NONE) { - up(&cam->param_lock); - return; - } - DEB_BYTE(cam->cmd_queue); - DEB_BYTE(cam->cmd_queue>>8); - if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS) - do_command(cam, CPIA_COMMAND_SetColourParams, - cam->params.colourParams.brightness, - cam->params.colourParams.contrast, - cam->params.colourParams.saturation, 0); - - if (cam->cmd_queue & COMMAND_SETCOMPRESSION) - do_command(cam, CPIA_COMMAND_SetCompression, - cam->params.compression.mode, - cam->params.compression.decimation, 0, 0); - - if (cam->cmd_queue & COMMAND_SETFORMAT) { - do_command(cam, CPIA_COMMAND_SetFormat, - cam->params.format.videoSize, - cam->params.format.subSample, - cam->params.format.yuvOrder, 0); - do_command(cam, CPIA_COMMAND_SetROI, - cam->params.roi.colStart, cam->params.roi.colEnd, - cam->params.roi.rowStart, cam->params.roi.rowEnd); - cam->first_frame = 1; - } - - if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET) - do_command(cam, CPIA_COMMAND_SetCompressionTarget, - cam->params.compressionTarget.frTargeting, - cam->params.compressionTarget.targetFR, - cam->params.compressionTarget.targetQ, 0); - - if (cam->cmd_queue & COMMAND_SETYUVTHRESH) - do_command(cam, CPIA_COMMAND_SetYUVThresh, - cam->params.yuvThreshold.yThreshold, - cam->params.yuvThreshold.uvThreshold, 0, 0); - - if (cam->cmd_queue & COMMAND_SETECPTIMING) - do_command(cam, CPIA_COMMAND_SetECPTiming, - cam->params.ecpTiming, 0, 0, 0); - - if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS) - do_command_extended(cam, CPIA_COMMAND_SetCompressionParams, - 0, 0, 0, 0, - cam->params.compressionParams.hysteresis, - cam->params.compressionParams.threshMax, - cam->params.compressionParams.smallStep, - cam->params.compressionParams.largeStep, - cam->params.compressionParams.decimationHysteresis, - cam->params.compressionParams.frDiffStepThresh, - cam->params.compressionParams.qDiffStepThresh, - cam->params.compressionParams.decimationThreshMod); - - if (cam->cmd_queue & COMMAND_SETEXPOSURE) - do_command_extended(cam, CPIA_COMMAND_SetExposure, - cam->params.exposure.gainMode, - cam->params.exposure.expMode, - cam->params.exposure.compMode, - cam->params.exposure.centreWeight, - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); - - if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) { - if (cam->params.colourBalance.balanceModeIsAuto) { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 2, 0, 0, 0); - } else { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 1, - cam->params.colourBalance.redGain, - cam->params.colourBalance.greenGain, - cam->params.colourBalance.blueGain); - do_command(cam, CPIA_COMMAND_SetColourBalance, - 3, 0, 0, 0); - } - } - - if (cam->cmd_queue & COMMAND_SETSENSORFPS) - do_command(cam, CPIA_COMMAND_SetSensorFPS, - cam->params.sensorFps.divisor, - cam->params.sensorFps.baserate, 0, 0); - - if (cam->cmd_queue & COMMAND_SETAPCOR) - do_command(cam, CPIA_COMMAND_SetApcor, - cam->params.apcor.gain1, - cam->params.apcor.gain2, - cam->params.apcor.gain4, - cam->params.apcor.gain8); - - if (cam->cmd_queue & COMMAND_SETFLICKERCTRL) - do_command(cam, CPIA_COMMAND_SetFlickerCtrl, - cam->params.flickerControl.flickerMode, - cam->params.flickerControl.coarseJump, - cam->params.flickerControl.allowableOverExposure, 0); - - if (cam->cmd_queue & COMMAND_SETVLOFFSET) - do_command(cam, CPIA_COMMAND_SetVLOffset, - cam->params.vlOffset.gain1, - cam->params.vlOffset.gain2, - cam->params.vlOffset.gain4, - cam->params.vlOffset.gain8); - - if (cam->cmd_queue & COMMAND_PAUSE) - do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); - - if (cam->cmd_queue & COMMAND_RESUME) - init_stream_cap(cam); - - up(&cam->param_lock); - cam->cmd_queue = COMMAND_NONE; - return; -} - -/* kernel thread function to read image from camera */ -static void fetch_frame(void *data) -{ - int image_size, retry; - struct cam_data *cam = (struct cam_data *)data; - unsigned long oldjif, rate, diff; - - /* Allow up to two bad images in a row to be read and - * ignored before an error is reported */ - for (retry = 0; retry < 3; ++retry) { - if (retry) - DBG("retry=%d\n", retry); - - if (!cam->ops) - continue; - - /* load first frame always uncompressed */ - if (cam->first_frame && - cam->params.compression.mode != CPIA_COMPRESSION_NONE) - do_command(cam, CPIA_COMMAND_SetCompression, - CPIA_COMPRESSION_NONE, - NO_DECIMATION, 0, 0); - - /* init camera upload */ - if (do_command(cam, CPIA_COMMAND_SetGrabMode, - CPIA_GRAB_CONTINUOUS, 0, 0, 0)) - continue; - - if (do_command(cam, CPIA_COMMAND_GrabFrame, 0, - cam->params.streamStartLine, 0, 0)) - continue; - - if (cam->ops->wait_for_stream_ready) { - /* loop until image ready */ - do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0); - while (cam->params.status.streamState != STREAM_READY) { - if (current->need_resched) - schedule(); - - current->state = TASK_INTERRUPTIBLE; - - /* sleep for 10 ms, hopefully ;) */ - schedule_timeout(10*HZ/1000); - if (signal_pending(current)) - return; - - do_command(cam, CPIA_COMMAND_GetCameraStatus, - 0, 0, 0, 0); - } - } - - /* grab image from camera */ - if (current->need_resched) - schedule(); - - oldjif = jiffies; - image_size = cam->ops->streamRead(cam->lowlevel_data, - cam->raw_image, 0); - if (image_size <= 0) { - DBG("streamRead failed: %d\n", image_size); - continue; - } - - rate = image_size * HZ / 1024; - diff = jiffies-oldjif; - cam->transfer_rate = diff==0 ? rate : rate/diff; - /* diff==0 ? unlikely but possible */ - - /* camera idle now so dispatch queued commands */ - dispatch_commands(cam); - - /* Update our knowledge of the camera state - FIXME: necessary? */ - do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); - do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); - - /* decompress and convert image to by copying it from - * raw_image to decompressed_frame - */ - if (current->need_resched) - schedule(); - - cam->image_size = parse_picture(cam, image_size); - if (cam->image_size <= 0) - DBG("parse_picture failed %d\n", cam->image_size); - else - break; - } - - if (retry < 3) { - /* FIXME: this only works for double buffering */ - if (cam->frame[cam->curframe].state == FRAME_READY) { - memcpy(cam->frame[cam->curframe].data, - cam->decompressed_frame.data, - cam->decompressed_frame.count); - cam->frame[cam->curframe].state = FRAME_DONE; - } else - cam->decompressed_frame.state = FRAME_DONE; - -#if 0 - if (cam->first_frame && - cam->params.compression.mode != CPIA_COMPRESSION_NONE) { - cam->first_frame = 0; - cam->cmd_queue |= COMMAND_SETCOMPRESSION; - } -#else - if (cam->first_frame) { - cam->first_frame = 0; - cam->cmd_queue |= COMMAND_SETCOMPRESSION; - cam->cmd_queue |= COMMAND_SETEXPOSURE; - } -#endif - } -} - -static int capture_frame(struct cam_data *cam, struct video_mmap *vm) -{ - int retval = 0; - - if (!cam->frame_buf) { - /* we do lazy allocation */ - if ((retval = allocate_frame_buf(cam))) - return retval; - } - - /* FIXME: the first frame seems to be captured by the camera - without regards to any initial settings, so we throw away - that one, the next one is generated with our settings - (exposure, color balance, ...) - */ - if (cam->first_frame) { - cam->curframe = vm->frame; - cam->frame[cam->curframe].state = FRAME_READY; - fetch_frame(cam); - if (cam->frame[cam->curframe].state != FRAME_DONE) - retval = -EIO; - } - cam->curframe = vm->frame; - cam->frame[cam->curframe].state = FRAME_READY; - fetch_frame(cam); - if (cam->frame[cam->curframe].state != FRAME_DONE) - retval=-EIO; - - return retval; -} - -static int goto_high_power(struct cam_data *cam) -{ - if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0)) - return -1; - mdelay(100); /* windows driver does it too */ - if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) - return -1; - if (cam->params.status.systemState == HI_POWER_STATE) { - DBG("camera now in HIGH power state\n"); - return 0; - } - printstatus(cam); - return -1; -} - -static int goto_low_power(struct cam_data *cam) -{ - if (do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0)) - return -1; - if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) - return -1; - if (cam->params.status.systemState == LO_POWER_STATE) { - DBG("camera now in LOW power state\n"); - return 0; - } - printstatus(cam); - return -1; -} - -static void save_camera_state(struct cam_data *cam) -{ - do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); - do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); - - DBG("%d/%d/%d/%d/%d/%d/%d/%d\n", - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); - DBG("%d/%d/%d\n", - cam->params.colourBalance.redGain, - cam->params.colourBalance.greenGain, - cam->params.colourBalance.blueGain); -} - -static void set_camera_state(struct cam_data *cam) -{ - if(cam->params.colourBalance.balanceModeIsAuto) { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 2, 0, 0, 0); - } else { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 1, - cam->params.colourBalance.redGain, - cam->params.colourBalance.greenGain, - cam->params.colourBalance.blueGain); - do_command(cam, CPIA_COMMAND_SetColourBalance, - 3, 0, 0, 0); - } - - - do_command_extended(cam, CPIA_COMMAND_SetExposure, - cam->params.exposure.gainMode, 1, 1, - cam->params.exposure.centreWeight, - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); - do_command_extended(cam, CPIA_COMMAND_SetExposure, - 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0); - - if (!cam->params.exposure.gainMode) - cam->params.exposure.gainMode = 2; - if (!cam->params.exposure.expMode) - cam->params.exposure.expMode = 2; - if (!cam->params.exposure.centreWeight) - cam->params.exposure.centreWeight = 1; - - cam->cmd_queue = COMMAND_SETCOMPRESSION | - COMMAND_SETCOMPRESSIONTARGET | - COMMAND_SETCOLOURPARAMS | - COMMAND_SETFORMAT | - COMMAND_SETYUVTHRESH | - COMMAND_SETECPTIMING | - COMMAND_SETCOMPRESSIONPARAMS | -#if 0 - COMMAND_SETEXPOSURE | -#endif - COMMAND_SETCOLOURBALANCE | - COMMAND_SETSENSORFPS | - COMMAND_SETAPCOR | - COMMAND_SETFLICKERCTRL | - COMMAND_SETVLOFFSET; - dispatch_commands(cam); - save_camera_state(cam); - - return; -} - -static void get_version_information(struct cam_data *cam) -{ - /* GetCPIAVersion */ - do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); - - /* GetPnPID */ - do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); -} - -/* initialize camera */ -static int reset_camera(struct cam_data *cam) -{ - /* Start the camera in low power mode */ - if (goto_low_power(cam)) { - if (cam->params.status.systemState != WARM_BOOT_STATE) - return -ENODEV; - - /* FIXME: this is just dirty trial and error */ - reset_camera_struct(cam); - goto_high_power(cam); - do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0); - if (goto_low_power(cam)) - return -NODEV; - } - - /* procedure described in developer's guide p3-28 */ - - /* Check the firmware version FIXME: should we check PNPID? */ - cam->params.version.firmwareVersion = 0; - get_version_information(cam); - if (cam->params.version.firmwareVersion != 1) - return -ENODEV; - - /* The fatal error checking should be done after - * the camera powers up (developer's guide p 3-38) */ - - /* Set streamState before transition to high power to avoid bug - * in firmware 1-02 */ - do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0, - STREAM_NOT_READY, 0); - - /* GotoHiPower */ - if (goto_high_power(cam)) - return -ENODEV; - - /* Check the camera status */ - if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) - return -EIO; - - if (cam->params.status.fatalError) { - DBG("fatal_error: %#04x\n", - cam->params.status.fatalError); - DBG("vp_status: %#04x\n", - cam->params.status.vpStatus); - if (cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) { - /* Fatal error in camera */ - return -EIO; - } else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) { - /* Firmware 1-02 may do this for parallel port cameras, - * just clear the flags (developer's guide p 3-38) */ - do_command(cam, CPIA_COMMAND_ModifyCameraStatus, - FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0); - } - } - - /* Check the camera status again */ - if (cam->params.status.fatalError) { - if (cam->params.status.fatalError) - return -EIO; - } - - /* VPVersion can't be retrieved before the camera is in HiPower, - * so get it here instead of in get_version_information. */ - do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); - - /* set camera to a known state */ - set_camera_state(cam); - - return 0; -} - -/* ------------------------- V4L interface --------------------- */ -static int cpia_open(struct video_device *dev, int flags) -{ - int i; - struct cam_data *cam = dev->priv; - - if (!cam) { - DBG("Internal error, cam_data not found!\n"); - return -EBUSY; - } - - if (cam->open_count > 0) { - DBG("Camera already open\n"); - return -EBUSY; - } - - if (!cam->raw_image) { - cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); - if (!cam->raw_image) - return -ENOMEM; - } - - if (!cam->decompressed_frame.data) { - cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE); - if (!cam->decompressed_frame.data) { - rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); - cam->raw_image = NULL; - return -ENOMEM; - } - } - - /* open cpia */ - if (cam->ops->open(cam->lowlevel_data)) { - rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); - cam->decompressed_frame.data = NULL; - rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); - cam->raw_image = NULL; - return -ENODEV; - } - - /* reset the camera */ - if ((i = reset_camera(cam)) != 0) { - cam->ops->close(cam->lowlevel_data); - rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); - cam->decompressed_frame.data = NULL; - rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); - cam->raw_image = NULL; - return i; - } - - /* Set ownership of /proc/cpia/videoX to current user */ - if(cam->proc_entry) - cam->proc_entry->uid = current->uid; - - /* set mark for loading first frame uncompressed */ - cam->first_frame = 1; - - /* init it to something */ - cam->mmap_kludge = 0; - - ++cam->open_count; -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static void cpia_close(struct video_device *dev) -{ - struct cam_data *cam; - - cam = dev->priv; - - if (cam->ops) { - /* Return ownership of /proc/cpia/videoX to root */ - if(cam->proc_entry) - cam->proc_entry->uid = 0; - - /* save camera state for later open (developers guide ch 3.5.3) */ - save_camera_state(cam); - - /* GotoLoPower */ - goto_low_power(cam); - - /* Update the camera ststus */ - do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); - - /* cleanup internal state stuff */ - free_frames(cam->frame); - - /* close cpia */ - cam->ops->close(cam->lowlevel_data); - } - - if (--cam->open_count == 0) { - /* clean up capture-buffers */ - if (cam->raw_image) { - rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); - cam->raw_image = NULL; - } - - if (cam->decompressed_frame.data) { - rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); - cam->decompressed_frame.data = NULL; - } - - if (cam->frame_buf) - free_frame_buf(cam); - - if (!cam->ops) { - video_unregister_device(dev); - kfree(cam); - } - } - - -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - return; -} - -static long cpia_read(struct video_device *dev, char *buf, - unsigned long count, int noblock) -{ - struct cam_data *cam = dev->priv; - - /* make this _really_ smp and multithredi-safe */ - if (down_interruptible(&cam->busy_lock)) - return -EINTR; - - if (!buf) { - DBG("buf NULL\n"); - up(&cam->busy_lock); - return -EINVAL; - } - - if (!count) { - DBG("count 0\n"); - up(&cam->busy_lock); - return 0; - } - - if (!cam->ops) { - DBG("ops NULL\n"); - up(&cam->busy_lock); - return -ENODEV; - } - - /* upload frame */ - cam->decompressed_frame.state = FRAME_READY; - cam->mmap_kludge=0; - fetch_frame(cam); - if (cam->decompressed_frame.state != FRAME_DONE) { - DBG("upload failed %d/%d\n", cam->decompressed_frame.count, - cam->decompressed_frame.state); - up(&cam->busy_lock); - return -EIO; - } - cam->decompressed_frame.state = FRAME_UNUSED; - - /* copy data to user space */ - if (cam->decompressed_frame.count > count) { - DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count, - count); - up(&cam->busy_lock); - return -EFAULT; - } - if (copy_to_user(buf, cam->decompressed_frame.data, - cam->decompressed_frame.count)) { - DBG("copy_to_user failed\n"); - up(&cam->busy_lock); - return -EFAULT; - } - - up(&cam->busy_lock); - return cam->decompressed_frame.count; -} - -static int cpia_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg) -{ - struct cam_data *cam = dev->priv; - int retval = 0; - - if (!cam || !cam->ops) - return -ENODEV; - - /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) - return -EINTR; - - //DBG("cpia_ioctl: %u\n", ioctlnr); - - switch (ioctlnr) { - /* query capabilites */ - case VIDIOCGCAP: - { - struct video_capability b; - - DBG("VIDIOCGCAP\n"); - strcpy(b.name, "CPiA Camera"); - b.type = VID_TYPE_CAPTURE; - b.channels = 1; - b.audios = 0; - b.maxwidth = 352; /* VIDEOSIZE_CIF */ - b.maxheight = 288; - b.minwidth = 48; /* VIDEOSIZE_48_48 */ - b.minheight = 48; - - if (copy_to_user(arg, &b, sizeof(b))) - retval = -EFAULT; - - break; - } - - /* get/set video source - we are a camera and nothing else */ - case VIDIOCGCHAN: - { - struct video_channel v; - - DBG("VIDIOCGCHAN\n"); - if (copy_from_user(&v, arg, sizeof(v))) { - retval = -EFAULT; - break; - } - if (v.channel != 0) { - retval = -EINVAL; - break; - } - - v.channel = 0; - strcpy(v.name, "Camera"); - v.tuners = 0; - v.flags = 0; - v.type = VIDEO_TYPE_CAMERA; - v.norm = 0; - - if (copy_to_user(arg, &v, sizeof(v))) - retval = -EFAULT; - break; - } - - case VIDIOCSCHAN: - { - int v; - - DBG("VIDIOCSCHAN\n"); - if (copy_from_user(&v, arg, sizeof(v))) - retval = -EFAULT; - - if (retval == 0 && v != 0) - retval = -EINVAL; - - break; - } - - /* image properties */ - case VIDIOCGPICT: - DBG("VIDIOCGPICT\n"); - if (copy_to_user(arg, &cam->vp, sizeof(struct video_picture))) - retval = -EFAULT; - break; - - case VIDIOCSPICT: - { - struct video_picture vp; - - DBG("VIDIOCSPICT\n"); - - /* copy_from_user */ - if (copy_from_user(&vp, arg, sizeof(vp))) { - retval = -EFAULT; - break; - } - - /* check validity */ - DBG("palette: %d\n", vp.palette); - DBG("depth: %d\n", vp.depth); - if (!valid_mode(vp.palette, vp.depth)) { - retval = -EINVAL; - break; - } - - down(&cam->param_lock); - /* brightness, colour, contrast need no check 0-65535 */ - memcpy( &cam->vp, &vp, sizeof(vp) ); - /* update cam->params.colourParams */ - cam->params.colourParams.brightness = vp.brightness*100/65535; - cam->params.colourParams.contrast = vp.contrast*100/65535; - cam->params.colourParams.saturation = vp.colour*100/65535; - /* contrast is in steps of 8, so round */ - cam->params.colourParams.contrast = - ((cam->params.colourParams.contrast + 3) / 8) * 8; - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2 && - cam->params.colourParams.contrast > 80) { - /* 1-02 firmware limits contrast to 80 */ - cam->params.colourParams.contrast = 80; - } - - /* queue command to update camera */ - cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; - up(&cam->param_lock); - DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n", - vp.depth, vp.palette, vp.brightness, vp.hue, vp.colour, - vp.contrast); - break; - } - - /* get/set capture window */ - case VIDIOCGWIN: - DBG("VIDIOCGWIN\n"); - - if (copy_to_user(arg, &cam->vw, sizeof(struct video_window))) - retval = -EFAULT; - break; - - case VIDIOCSWIN: - { - /* copy_from_user, check validity, copy to internal structure */ - struct video_window vw; - DBG("VIDIOCSWIN\n"); - if (copy_from_user(&vw, arg, sizeof(vw))) { - retval = -EFAULT; - break; - } - - if (vw.clipcount != 0) { /* clipping not supported */ - retval = -EINVAL; - break; - } - if (vw.clips != NULL) { /* clipping not supported */ - retval = -EINVAL; - break; - } - - /* we set the video window to something smaller or equal to what - * is requested by the user??? - */ - down(&cam->param_lock); - if (vw.width != cam->vw.width || vw.height != cam->vw.height) { - int video_size = match_videosize(vw.width, vw.height); - - if (video_size < 0) { - retval = -EINVAL; - up(&cam->param_lock); - break; - } - cam->video_size = video_size; - set_vw_size(cam); - DBG("%d / %d\n", cam->vw.width, cam->vw.height); - cam->cmd_queue |= COMMAND_SETFORMAT; - } - - // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw)); - up(&cam->param_lock); - - /* setformat ignored by camera during streaming, - * so stop/dispatch/start */ - if (cam->cmd_queue & COMMAND_SETFORMAT) { - DBG("\n"); - dispatch_commands(cam); - } - DBG("%d/%d:%d\n", cam->video_size, - cam->vw.width, cam->vw.height); - break; - } - - /* mmap interface */ - case VIDIOCGMBUF: - { - struct video_mbuf vm; - int i; - - DBG("VIDIOCGMBUF\n"); - memset(&vm, 0, sizeof(vm)); - vm.size = CPIA_MAX_FRAME_SIZE*FRAME_NUM; - vm.frames = FRAME_NUM; - for (i = 0; i < FRAME_NUM; i++) - vm.offsets[i] = CPIA_MAX_FRAME_SIZE * i; - - if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) - retval = -EFAULT; - - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - int video_size; - - if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) { - retval = -EFAULT; - break; - } -#if 1 - DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm.format, vm.frame, - vm.width, vm.height); -#endif - if (vm.frame<0||vm.frame>FRAME_NUM) { - retval = -EINVAL; - break; - } - - /* set video format */ - cam->vp.palette = vm.format; - switch(vm.format) { - case VIDEO_PALETTE_GREY: - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_UYVY: - cam->vp.depth = 16; - break; - case VIDEO_PALETTE_RGB24: - cam->vp.depth = 24; - break; - case VIDEO_PALETTE_RGB32: - cam->vp.depth = 32; - break; - default: - retval = -EINVAL; - break; - } - if (retval) - break; - - /* set video size */ - video_size = match_videosize(vm.width, vm.height); - if (cam->video_size < 0) { - retval = -EINVAL; - break; - } - if (video_size != cam->video_size) { - cam->video_size = video_size; - set_vw_size(cam); - cam->cmd_queue |= COMMAND_SETFORMAT; - dispatch_commands(cam); - } -#if 0 - DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam->video_size, - cam->vw.width, cam->vw.height); -#endif - /* according to v4l-spec we must start streaming here */ - cam->mmap_kludge = 1; - retval = capture_frame(cam, &vm); - - break; - } - - case VIDIOCSYNC: - { - int frame; - - if (copy_from_user((void *)&frame, arg, sizeof(int))) { - retval = -EFAULT; - break; - } - //DBG("VIDIOCSYNC: %d\n", frame); - - if (frame<0 || frame >= FRAME_NUM) { - retval = -EINVAL; - break; - } - - switch (cam->frame[frame].state) { - case FRAME_UNUSED: - case FRAME_READY: - case FRAME_GRABBING: - DBG("sync to unused frame %d\n", frame); - retval = -EINVAL; - break; - - case FRAME_DONE: - cam->frame[frame].state = FRAME_UNUSED; - //DBG("VIDIOCSYNC: %d synced\n", frame); - break; - } - if (retval == -EINTR) { - /* FIXME - xawtv does not handle this nice */ - retval = 0; - } - break; - } - - /* pointless to implement overlay with this camera */ - case VIDIOCCAPTURE: - retval = -EINVAL; - break; - case VIDIOCGFBUF: - retval = -EINVAL; - break; - case VIDIOCSFBUF: - retval = -EINVAL; - break; - case VIDIOCKEY: - retval = -EINVAL; - break; - - /* tuner interface - we have none */ - case VIDIOCGTUNER: - retval = -EINVAL; - break; - case VIDIOCSTUNER: - retval = -EINVAL; - break; - case VIDIOCGFREQ: - retval = -EINVAL; - break; - case VIDIOCSFREQ: - retval = -EINVAL; - break; - - /* audio interface - we have none */ - case VIDIOCGAUDIO: - retval = -EINVAL; - break; - case VIDIOCSAUDIO: - retval = -EINVAL; - break; - default: - retval = -ENOIOCTLCMD; - break; - } - - up(&cam->param_lock); - up(&cam->busy_lock); - return retval; -} - -/* FIXME */ -static int cpia_mmap(struct video_device *dev, const char *adr, - unsigned long size) -{ - unsigned long start = (unsigned long)adr; - unsigned long page, pos; - struct cam_data *cam = dev->priv; - int retval; - - if (!cam || !cam->ops) - return -ENODEV; - - DBG("cpia_mmap: %ld\n", size); - - if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) - return -EINVAL; - - if (!cam || !cam->ops) - return -ENODEV; - - /* make this _really_ smp-safe */ - if (down_interruptible(&cam->busy_lock)) - return -EINTR; - - if (!cam->frame_buf) { /* we do lazy allocation */ - if ((retval = allocate_frame_buf(cam))) { - up(&cam->busy_lock); - return retval; - } - } - - pos = (unsigned long)(cam->frame_buf); - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) { - up(&cam->busy_lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - DBG("cpia_mmap: %ld\n", size); - up(&cam->busy_lock); - - return 0; -} - -int cpia_video_init(struct video_device *vdev) -{ -#ifdef CONFIG_PROC_FS - create_proc_cpia_cam(vdev->priv); -#endif - return 0; -} - -static struct video_device cpia_template = { - "CPiA Camera", - VID_TYPE_CAPTURE, - VID_HARDWARE_CPIA, /* FIXME */ - cpia_open, /* open */ - cpia_close, /* close */ - cpia_read, /* read */ - NULL, /* no write */ - NULL, /* no poll */ - cpia_ioctl, /* ioctl */ - cpia_mmap, /* mmap */ - cpia_video_init, /* initialize */ - NULL, /* priv */ - 0, /* busy */ - -1 /* minor - unset */ -}; - -/* initialise cam_data structure */ -static void reset_camera_struct(struct cam_data *cam) -{ - /* The following parameter values are the defaults from - * "Software Developer's Guide for CPiA Cameras". Any changes - * to the defaults are noted in comments. */ - cam->params.colourParams.brightness = 50; - cam->params.colourParams.contrast = 48; - cam->params.colourParams.saturation = 50; - cam->params.exposure.gainMode = 2; - cam->params.exposure.expMode = 2; /* AEC */ - cam->params.exposure.compMode = 1; - cam->params.exposure.centreWeight = 1; - cam->params.exposure.gain = 0; - cam->params.exposure.fineExp = 0; - cam->params.exposure.coarseExpLo = 185; - cam->params.exposure.coarseExpHi = 0; - cam->params.exposure.redComp = 220; - cam->params.exposure.green1Comp = 214; - cam->params.exposure.green2Comp = 214; - cam->params.exposure.blueComp = 230; - cam->params.colourBalance.balanceModeIsAuto = 1; - cam->params.colourBalance.redGain = 32; - cam->params.colourBalance.greenGain = 6; - cam->params.colourBalance.blueGain = 92; - cam->params.apcor.gain1 = 0x1c; - cam->params.apcor.gain2 = 0x1a; - cam->params.apcor.gain4 = 0x2d; - cam->params.apcor.gain8 = 0x2a; - cam->params.flickerControl.flickerMode = 0; - cam->params.flickerControl.coarseJump = - flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; - cam->params.vlOffset.gain1 = 24; - cam->params.vlOffset.gain2 = 28; - cam->params.vlOffset.gain4 = 30; - cam->params.vlOffset.gain8 = 30; - cam->params.compressionParams.hysteresis = 3; - cam->params.compressionParams.threshMax = 11; - cam->params.compressionParams.smallStep = 1; - cam->params.compressionParams.largeStep = 3; - cam->params.compressionParams.decimationHysteresis = 2; - cam->params.compressionParams.frDiffStepThresh = 5; - cam->params.compressionParams.qDiffStepThresh = 3; - cam->params.compressionParams.decimationThreshMod = 2; - /* End of default values from Software Developer's Guide */ - - cam->transfer_rate = 0; - - /* Set Sensor FPS to 15fps. This seems better than 30fps - * for indoor lighting. */ - cam->params.sensorFps.divisor = 1; - cam->params.sensorFps.baserate = 1; - - cam->params.yuvThreshold.yThreshold = 15; /* FIXME? */ - cam->params.yuvThreshold.uvThreshold = 15; /* FIXME? */ - - cam->params.format.subSample = SUBSAMPLE_422; - cam->params.format.yuvOrder = YUVORDER_YUYV; - - cam->params.compression.mode = CPIA_COMPRESSION_AUTO; - cam->params.compressionTarget.frTargeting = - CPIA_COMPRESSION_TARGET_QUALITY; - cam->params.compressionTarget.targetFR = 7; /* FIXME? */ - cam->params.compressionTarget.targetQ = 10; /* FIXME? */ - - cam->video_size = VIDEOSIZE_CIF; - - cam->vp.colour = 32768; /* 50% */ - cam->vp.hue = 32768; /* 50% */ - cam->vp.brightness = 32768; /* 50% */ - cam->vp.contrast = 32768; /* 50% */ - cam->vp.whiteness = 0; /* not used -> grayscale only */ - cam->vp.depth = 0; /* FIXME: to be set by user? */ - cam->vp.palette = VIDEO_PALETTE_RGB24; /* FIXME: to be set by user? */ - - cam->vw.x = 0; - cam->vw.y = 0; - set_vw_size(cam); - cam->vw.chromakey = 0; - /* PP NOTE: my extension to use vw.flags for this, bear it! */ - cam->vw.flags = 0; - cam->vw.clipcount = 0; - cam->vw.clips = NULL; - - cam->cmd_queue = COMMAND_NONE; - cam->first_frame = 0; - - return; -} - -/* initialize cam_data structure */ -static void init_camera_struct(struct cam_data *cam, - struct cpia_camera_ops *ops ) -{ - int i; - - /* Default everything to 0 */ - memset(cam, 0, sizeof(struct cam_data)); - - cam->ops = ops; - init_MUTEX(&cam->param_lock); - init_MUTEX(&cam->busy_lock); - - reset_camera_struct(cam); - - cam->proc_entry = NULL; - - memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); - cam->vdev.priv = cam; - - cam->curframe = 0; - for (i = 0; i < FRAME_NUM; i++) { - cam->frame[i].width = 0; - cam->frame[i].height = 0; - cam->frame[i].state = FRAME_UNUSED; - cam->frame[i].data = NULL; - } - cam->decompressed_frame.width = 0; - cam->decompressed_frame.height = 0; - cam->decompressed_frame.state = FRAME_UNUSED; - cam->decompressed_frame.data = NULL; -} - -struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel) -{ - struct cam_data *camera; - - /* Need a lock when adding/removing cameras. This doesn't happen - * often and doesn't take very long, so grabbing the kernel lock - * should be OK. */ - - if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) { - unlock_kernel(); - return NULL; - } - - init_camera_struct( camera, ops ); - camera->lowlevel_data = lowlevel; - - /* register v4l device */ - if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER) == -1) { - kfree(camera); - unlock_kernel(); - printk(KERN_DEBUG "video_register_device failed\n"); - return NULL; - } - - /* get version information from camera: open/reset/close */ - - /* open cpia */ - if (camera->ops->open(camera->lowlevel_data)) - return camera; - - /* reset the camera */ - if (reset_camera(camera) != 0) { - camera->ops->close(camera->lowlevel_data); - return camera; - } - - /* close cpia */ - camera->ops->close(camera->lowlevel_data); - -/* Eh? Feeling happy? - jerdfelt */ -/* - camera->ops->open(camera->lowlevel_data); - camera->ops->close(camera->lowlevel_data); -*/ - - printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n", - camera->params.version.firmwareVersion, - camera->params.version.firmwareRevision, - camera->params.version.vcVersion, - camera->params.version.vcRevision); - printk(KERN_INFO " CPiA PnP-ID: %04x:%04x:%04x\n", - camera->params.pnpID.vendor, - camera->params.pnpID.product, - camera->params.pnpID.deviceRevision); - printk(KERN_INFO " VP-Version: %d.%d %04x\n", - camera->params.vpVersion.vpVersion, - camera->params.vpVersion.vpRevision, - camera->params.vpVersion.cameraHeadID); - - return camera; -} - -void cpia_unregister_camera(struct cam_data *cam) -{ - if (!cam->open_count) { - DBG("unregistering video\n"); - video_unregister_device(&cam->vdev); - } else { - LOG("/dev/video%d removed while open, " - "deferring video_unregister_device\n", cam->vdev.minor); - DBG("camera open -- setting ops to NULL\n"); - cam->ops = NULL; - } - -#ifdef CONFIG_PROC_FS - DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor); - destroy_proc_cpia_cam(cam); -#endif - if (!cam->open_count) { - DBG("freeing camera\n"); - kfree(cam); - } -} - -/**************************************************************************** - * - * Module routines - * - ***************************************************************************/ - -#ifdef MODULE -int init_module(void) -{ - printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT, - CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); -#ifdef CONFIG_PROC_FS - proc_cpia_create(); -#endif -#ifdef CONFIG_KMOD -#ifdef CONFIG_VIDEO_CPIA_PP_MODULE - request_module("cpia_pp"); -#endif -#ifdef CONFIG_VIDEO_CPIA_USB_MODULE - request_module("cpia_usb"); -#endif -#endif -return 0; -} - -void cleanup_module(void) -{ -#ifdef CONFIG_PROC_FS - proc_cpia_destroy(); -#endif -} - -#else - -int cpia_init(struct video_init *unused) -{ - printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT, - CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); -#ifdef CONFIG_PROC_FS - proc_cpia_create(); -#endif - -#ifdef CONFIG_VIDEO_CPIA_PP - cpia_pp_init(); -#endif -#ifdef CONFIG_KMOD -#ifdef CONFIG_VIDEO_CPIA_PP_MODULE - request_module("cpia_pp"); -#endif - -#ifdef CONFIG_VIDEO_CPIA_USB_MODULE - request_module("cpia_usb"); -#endif -#endif /* CONFIG_KMOD */ -#ifdef CONFIG_VIDEO_CPIA_USB - cpia_usb_init(); -#endif - return 0; -} - -/* Exported symbols for modules. */ - -EXPORT_SYMBOL(cpia_register_camera); -EXPORT_SYMBOL(cpia_unregister_camera); - -#endif diff --git a/drivers/char/cpia.h b/drivers/char/cpia.h deleted file mode 100644 index 579b5e153..000000000 --- a/drivers/char/cpia.h +++ /dev/null @@ -1,421 +0,0 @@ -#ifndef cpia_h -#define cpia_h - -/* - * CPiA Parallel Port Video4Linux driver - * - * Supports CPiA based parallel port Video Camera's. - * - * (C) Copyright 1999 Bas Huisman, - * Peter Pregler, - * Scott J. Bertin, - * VLSI Vision Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define CPIA_MAJ_VER 0 -#define CPIA_MIN_VER 7 -#define CPIA_PATCH_VER 4 - -#define CPIA_PP_MAJ_VER 0 -#define CPIA_PP_MIN_VER 7 -#define CPIA_PP_PATCH_VER 4 - -#define CPIA_MAX_FRAME_SIZE_UNALIGNED (352 * 288 * 4) /* CIF at RGB32 */ -#define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */ - -#ifdef __KERNEL__ - -#include -#include -#include - -struct cpia_camera_ops -{ - /* open sets privdata to point to structure for this camera. - * Returns negative value on error, otherwise 0. - */ - int (*open)(void *privdata); - - /* Registers callback function cb to be called with cbdata - * when an image is ready. If cb is NULL, only single image grabs - * should be used. cb should immediately call streamRead to read - * the data or data may be lost. Returns negative value on error, - * otherwise 0. - */ - int (*registerCallback)(void *privdata, void (*cb)(void *cbdata), - void *cbdata); - - /* transferCmd sends commands to the camera. command MUST point to - * an 8 byte buffer in kernel space. data can be NULL if no extra - * data is needed. The size of the data is given by the last 2 - * bytes of comand. data must also point to memory in kernel space. - * Returns negative value on error, otherwise 0. - */ - int (*transferCmd)(void *privdata, u8 *command, u8 *data); - - /* streamStart initiates stream capture mode. - * Returns negative value on error, otherwise 0. - */ - int (*streamStart)(void *privdata); - - /* streamStop terminates stream capture mode. - * Returns negative value on error, otherwise 0. - */ - int (*streamStop)(void *privdata); - - /* streamRead reads a frame from the camera. buffer points to a - * buffer large enough to hold a complete frame in kernel space. - * noblock indicates if this should be a non blocking read. - * Returns the number of bytes read, or negative value on error. - */ - int (*streamRead)(void *privdata, u8 *buffer, int noblock); - - /* close disables the device until open() is called again. - * Returns negative value on error, otherwise 0. - */ - int (*close)(void *privdata); - - /* If wait_for_stream_ready is non-zero, wait until the streamState - * is STREAM_READY before calling streamRead. - */ - int wait_for_stream_ready; -}; - -struct cpia_frame { - u8 *data; - int count; - int width; - int height; - volatile int state; -}; - -struct cam_params { - struct { - u8 firmwareVersion; - u8 firmwareRevision; - u8 vcVersion; - u8 vcRevision; - } version; - struct { - u16 vendor; - u16 product; - u16 deviceRevision; - } pnpID; - struct { - u8 vpVersion; - u8 vpRevision; - u16 cameraHeadID; - } vpVersion; - struct { - u8 systemState; - u8 grabState; - u8 streamState; - u8 fatalError; - u8 cmdError; - u8 debugFlags; - u8 vpStatus; - u8 errorCode; - } status; - struct { - u8 brightness; - u8 contrast; - u8 saturation; - } colourParams; - struct { - u8 gainMode; - u8 expMode; - u8 compMode; - u8 centreWeight; - u8 gain; - u8 fineExp; - u8 coarseExpLo; - u8 coarseExpHi; - u8 redComp; - u8 green1Comp; - u8 green2Comp; - u8 blueComp; - } exposure; - struct { - u8 balanceModeIsAuto; - u8 redGain; - u8 greenGain; - u8 blueGain; - } colourBalance; - struct { - u8 divisor; - u8 baserate; - } sensorFps; - struct { - u8 gain1; - u8 gain2; - u8 gain4; - u8 gain8; - } apcor; - struct { - u8 flickerMode; - u8 coarseJump; - u8 allowableOverExposure; - } flickerControl; - struct { - u8 gain1; - u8 gain2; - u8 gain4; - u8 gain8; - } vlOffset; - struct { - u8 mode; - u8 decimation; - } compression; - struct { - u8 frTargeting; - u8 targetFR; - u8 targetQ; - } compressionTarget; - struct { - u8 yThreshold; - u8 uvThreshold; - } yuvThreshold; - struct { - u8 hysteresis; - u8 threshMax; - u8 smallStep; - u8 largeStep; - u8 decimationHysteresis; - u8 frDiffStepThresh; - u8 qDiffStepThresh; - u8 decimationThreshMod; - } compressionParams; - struct { - u8 videoSize; /* CIF/QCIF */ - u8 subSample; - u8 yuvOrder; - } format; - struct { - u8 colStart; /* skip first 8*colStart pixels */ - u8 colEnd; /* finish at 8*colEnd pixels */ - u8 rowStart; /* skip first 4*rowStart lines */ - u8 rowEnd; /* finish at 4*rowEnd lines */ - } roi; - u8 ecpTiming; - u8 streamStartLine; -}; - -enum v4l_camstates { - CPIA_V4L_IDLE = 0, - CPIA_V4L_ERROR, - CPIA_V4L_COMMAND, - CPIA_V4L_GRABBING, - CPIA_V4L_STREAMING, - CPIA_V4L_STREAMING_PAUSED, -}; - -#define FRAME_NUM 2 /* double buffering for now */ - -struct cam_data { - struct cam_data **previous; - struct cam_data *next; - - struct semaphore busy_lock; /* guard against SMP multithreading */ - struct cpia_camera_ops *ops; /* lowlevel driver operations */ - void *lowlevel_data; /* private data for lowlevel driver */ - u8 *raw_image; /* buffer for raw image data */ - struct cpia_frame decompressed_frame; - /* buffer to hold decompressed frame */ - int image_size; /* sizeof last decompressed image */ - int open_count; /* # of process that have camera open */ - - /* camera status */ - int fps; /* actual fps reported by the camera */ - int transfer_rate; /* transfer rate from camera in kB/s */ - u8 mainsFreq; /* for flicker control */ - - /* proc interface */ - struct semaphore param_lock; /* params lock for this camera */ - struct cam_params params; /* camera settings */ - struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ - - /* v4l */ - int video_size; /* VIDEO_SIZE_ */ - volatile enum v4l_camstates camstate; /* v4l layer status */ - struct video_device vdev; /* v4l videodev */ - struct video_picture vp; /* v4l camera settings */ - struct video_window vw; /* v4l capture area */ - - /* mmap interface */ - int curframe; /* the current frame to grab into */ - u8 *frame_buf; /* frame buffer data */ - struct cpia_frame frame[FRAME_NUM]; - /* FRAME_NUM-buffering, so we need a array */ - - int first_frame; - int mmap_kludge; /* 'wrong' byte order for mmap */ - volatile u32 cmd_queue; /* queued commands */ -}; - -/* cpia_register_camera is called by low level driver for each camera. - * A unique camera number is returned, or a negative value on error */ -struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel); - -/* cpia_unregister_camera is called by low level driver when a camera - * is removed. This must not fail. */ -void cpia_unregister_camera(struct cam_data *cam); - -/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI + - * one byte 16bit DMA alignment - */ -#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5) - -/* constant value's */ -#define MAGIC_0 0x19 -#define MAGIC_1 0x68 -#define DATA_IN 0xC0 -#define DATA_OUT 0x40 -#define VIDEOSIZE_QCIF 0 /* 176x144 */ -#define VIDEOSIZE_CIF 1 /* 352x288 */ -#define VIDEOSIZE_SIF 2 /* 320x240 */ -#define VIDEOSIZE_QSIF 3 /* 160x120 */ -#define VIDEOSIZE_48_48 4 /* where no one has gone before, iconsize! */ -#define VIDEOSIZE_64_48 5 -#define VIDEOSIZE_128_96 6 -#define VIDEOSIZE_160_120 VIDEOSIZE_QSIF -#define VIDEOSIZE_176_144 VIDEOSIZE_QCIF -#define VIDEOSIZE_192_144 7 -#define VIDEOSIZE_224_168 8 -#define VIDEOSIZE_256_192 9 -#define VIDEOSIZE_288_216 10 -#define VIDEOSIZE_320_240 VIDEOSIZE_SIF -#define VIDEOSIZE_352_288 VIDEOSIZE_CIF -#define VIDEOSIZE_88_72 11 /* quarter CIF */ -#define SUBSAMPLE_420 0 -#define SUBSAMPLE_422 1 -#define YUVORDER_YUYV 0 -#define YUVORDER_UYVY 1 -#define NOT_COMPRESSED 0 -#define COMPRESSED 1 -#define NO_DECIMATION 0 -#define DECIMATION_ENAB 1 -#define EOI 0xff /* End Of Image */ -#define EOL 0xfd /* End Of Line */ -#define FRAME_HEADER_SIZE 64 - -/* Image grab modes */ -#define CPIA_GRAB_SINGLE 0 -#define CPIA_GRAB_CONTINUOUS 1 - -/* Compression parameters */ -#define CPIA_COMPRESSION_NONE 0 -#define CPIA_COMPRESSION_AUTO 1 -#define CPIA_COMPRESSION_MANUAL 2 -#define CPIA_COMPRESSION_TARGET_QUALITY 0 -#define CPIA_COMPRESSION_TARGET_FRAMERATE 1 - -/* Return offsets for GetCameraState */ -#define SYSTEMSTATE 0 -#define GRABSTATE 1 -#define STREAMSTATE 2 -#define FATALERROR 3 -#define CMDERROR 4 -#define DEBUGFLAGS 5 -#define VPSTATUS 6 -#define ERRORCODE 7 - -/* SystemState */ -#define UNINITIALISED_STATE 0 -#define PASS_THROUGH_STATE 1 -#define LO_POWER_STATE 2 -#define HI_POWER_STATE 3 -#define WARM_BOOT_STATE 4 - -/* GrabState */ -#define GRAB_IDLE 0 -#define GRAB_ACTIVE 1 -#define GRAB_DONE 2 - -/* StreamState */ -#define STREAM_NOT_READY 0 -#define STREAM_READY 1 -#define STREAM_OPEN 2 -#define STREAM_PAUSED 3 -#define STREAM_FINISHED 4 - -/* Fatal Error, CmdError, and DebugFlags */ -#define CPIA_FLAG 1 -#define SYSTEM_FLAG 2 -#define INT_CTRL_FLAG 4 -#define PROCESS_FLAG 8 -#define COM_FLAG 16 -#define VP_CTRL_FLAG 32 -#define CAPTURE_FLAG 64 -#define DEBUG_FLAG 128 - -/* VPStatus */ -#define VP_STATE_OK 0x00 - -#define VP_STATE_FAILED_VIDEOINIT 0x01 -#define VP_STATE_FAILED_AECACBINIT 0x02 -#define VP_STATE_AEC_MAX 0x04 -#define VP_STATE_ACB_BMAX 0x08 - -#define VP_STATE_ACB_RMIN 0x10 -#define VP_STATE_ACB_GMIN 0x20 -#define VP_STATE_ACB_RMAX 0x40 -#define VP_STATE_ACB_GMAX 0x80 - -/* ErrorCode */ -#define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */ - -#define ALOG(lineno,fmt,args...) printk(fmt,lineno,##args) -#define LOG(fmt,args...) ALOG((__LINE__),KERN_INFO __FILE__":"__FUNCTION__"(%d):"fmt,##args) - -#ifdef _CPIA_DEBUG_ -#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, lineno, ##args) -#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):"__FUNCTION__"(%d):"fmt,##args) -#else -#define DBG(fmn,args...) do {} while(0) -#endif - -#define DEB_BYTE(p)\ - DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\ - (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\ - (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); - -#define ADD_TO_LIST(l, drv) \ - {\ - lock_kernel();\ - (drv)->next = l;\ - (drv)->previous = &(l);\ - (l) = drv;\ - unlock_kernel();\ - } while(0) - -#define REMOVE_FROM_LIST(drv) \ - {\ - if ((drv)->previous != NULL) {\ - lock_kernel();\ - if ((drv)->next != NULL)\ - (drv)->next->previous = (drv)->previous;\ - *((drv)->previous) = (drv)->next;\ - (drv)->previous = NULL;\ - (drv)->next = NULL;\ - unlock_kernel();\ - }\ - } while (0) - - -#endif /* __KERNEL__ */ - -#endif /* cpia_h */ diff --git a/drivers/char/cpia_pp.c b/drivers/char/cpia_pp.c deleted file mode 100644 index 7d4be2744..000000000 --- a/drivers/char/cpia_pp.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * cpia_pp CPiA Parallel Port driver - * - * Supports CPiA based parallel port Video Camera's. - * - * (C) Copyright 1999 Bas Huisman - * (C) Copyright 1999-2000 Scott J. Bertin , - * (C) Copyright 1999-2000 Peter Pregler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 -#include - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif - -/* #define _CPIA_DEBUG_ define for verbose debug output */ -#include "cpia.h" - -static int cpia_pp_open(void *privdata); -static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata); -static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data); -static int cpia_pp_streamStart(void *privdata); -static int cpia_pp_streamStop(void *privdata); -static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock); -static int cpia_pp_close(void *privdata); - -#define ABOUT "Parallel port driver for Vision CPiA based cameras" - -/* IEEE 1284 Compatiblity Mode signal names */ -#define nStrobe PARPORT_CONTROL_STROBE /* inverted */ -#define nAutoFd PARPORT_CONTROL_AUTOFD /* inverted */ -#define nInit PARPORT_CONTROL_INIT -#define nSelectIn PARPORT_CONTROL_SELECT -#define IntrEnable PARPORT_CONTROL_INTEN /* normally zero for no IRQ */ -#define DirBit PARPORT_CONTROL_DIRECTION /* 0 = Forward, 1 = Reverse */ - -#define nFault PARPORT_STATUS_ERROR -#define Select PARPORT_STATUS_SELECT -#define PError PARPORT_STATUS_PAPEROUT -#define nAck PARPORT_STATUS_ACK -#define Busy PARPORT_STATUS_BUSY /* inverted */ - -/* some more */ -#define HostClk nStrobe -#define HostAck nAutoFd -#define nReverseRequest nInit -#define Active_1284 nSelectIn -#define nPeriphRequest nFault -#define XFlag Select -#define nAckReverse PError -#define PeriphClk nAck -#define PeriphAck Busy - -/* these can be used to correct for the inversion on some bits */ -#define STATUS_INVERSION_MASK (Busy) -#define CONTROL_INVERSION_MASK (nStrobe|nAutoFd|nSelectIn) - -#define ECR_empty 0x01 -#define ECR_full 0x02 -#define ECR_serviceIntr 0x04 -#define ECR_dmaEn 0x08 -#define ECR_nErrIntrEn 0x10 - -#define ECR_mode_mask 0xE0 -#define ECR_SPP_mode 0x00 -#define ECR_PS2_mode 0x20 -#define ECR_FIFO_mode 0x40 -#define ECR_ECP_mode 0x60 - -#define ECP_FIFO_SIZE 16 -#define DMA_BUFFER_SIZE PAGE_SIZE - /* for 16bit DMA make sure DMA_BUFFER_SIZE is 16 bit aligned */ -#define PARPORT_CHUNK_SIZE PAGE_SIZE/* >=2.3.x */ - /* we read this many bytes at once */ - -#define GetECRMasked(port,mask) (parport_read_econtrol(port) & (mask)) -#define GetStatus(port) ((parport_read_status(port)^STATUS_INVERSION_MASK)&(0xf8)) -#define SetStatus(port,val) parport_write_status(port,(val)^STATUS_INVERSION_MASK) -#define GetControl(port) ((parport_read_control(port)^CONTROL_INVERSION_MASK)&(0x3f)) -#define SetControl(port,val) parport_write_control(port,(val)^CONTROL_INVERSION_MASK) - -#define GetStatusMasked(port,mask) (GetStatus(port) & (mask)) -#define GetControlMasked(port,mask) (GetControl(port) & (mask)) -#define SetControlMasked(port,mask) SetControl(port,GetControl(port) | (mask)); -#define ClearControlMasked(port,mask) SetControl(port,GetControl(port)&~(mask)); -#define FrobControlBit(port,mask,value) SetControl(port,(GetControl(port)&~(mask))|((value)&(mask))); - -#define PACKET_LENGTH 8 - -/* Magic numbers for defining port-device mappings */ -#define PPCPIA_PARPORT_UNSPEC -4 -#define PPCPIA_PARPORT_AUTO -3 -#define PPCPIA_PARPORT_OFF -2 -#define PPCPIA_PARPORT_NONE -1 - -#ifdef MODULE -static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; -static char *parport[PARPORT_MAX] = {NULL,}; - -MODULE_AUTHOR("B. Huisman & Peter Pregler "); -MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras"); -MODULE_PARM(parport, "1-" __MODULE_STRING(PARPORT_MAX) "s"); -MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp."); -#else -static int parport_nr[PARPORT_MAX] __initdata = - {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; -static int parport_ptr = 0; -#endif - -struct pp_cam_entry { - struct pardevice *pdev; - struct parport *port; - struct tq_struct cb_task; - int open_count; - wait_queue_head_t wq_stream; - /* image state flags */ - int image_ready; /* we got an interrupt */ - int image_complete; /* we have seen 4 EOI */ - - int streaming; /* we are in streaming mode */ - int stream_irq; -}; - -static struct cpia_camera_ops cpia_pp_ops = -{ - cpia_pp_open, - cpia_pp_registerCallback, - cpia_pp_transferCmd, - cpia_pp_streamStart, - cpia_pp_streamStop, - cpia_pp_streamRead, - cpia_pp_close, - 1 -}; - -static struct cam_data *cam_list; - -#ifdef _CPIA_DEBUG_ -#define DEB_PORT(port) { \ -u8 controll = GetControl(port); \ -u8 statusss = GetStatus(port); \ -DBG("nsel %c per %c naut %c nstrob %c nak %c busy %c nfaul %c sel %c init %c dir %c\n",\ -((controll & nSelectIn) ? 'U' : 'D'), \ -((statusss & PError) ? 'U' : 'D'), \ -((controll & nAutoFd) ? 'U' : 'D'), \ -((controll & nStrobe) ? 'U' : 'D'), \ -((statusss & nAck) ? 'U' : 'D'), \ -((statusss & Busy) ? 'U' : 'D'), \ -((statusss & nFault) ? 'U' : 'D'), \ -((statusss & Select) ? 'U' : 'D'), \ -((controll & nInit) ? 'U' : 'D'), \ -((controll & DirBit) ? 'R' : 'F') \ -); } -#else -#define DEB_PORT(port) {} -#endif - -#define WHILE_OUT_TIMEOUT (HZ/10) -#define DMA_TIMEOUT 10*HZ - -/* FIXME */ -static void cpia_parport_enable_irq( struct parport *port ) { - parport_enable_irq(port); - mdelay(10); - return; -} - -static void cpia_parport_disable_irq( struct parport *port ) { - parport_disable_irq(port); - mdelay(10); - return; -} - -/**************************************************************************** - * - * EndTransferMode - * - ***************************************************************************/ -static void EndTransferMode(struct pp_cam_entry *cam) -{ - parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); -} - -/**************************************************************************** - * - * ForwardSetup - * - ***************************************************************************/ -static int ForwardSetup(struct pp_cam_entry *cam) -{ - int retry; - - /* After some commands the camera needs extra time before - * it will respond again, so we try up to 3 times */ - for(retry=0; retry<3; ++retry) { - if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) { - break; - } - } - if(retry == 3) { - DBG("Unable to negotiate ECP mode\n"); - return -1; - } - return 0; -} - -/**************************************************************************** - * - * ReverseSetup - * - ***************************************************************************/ -static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) -{ - int retry; - int mode = IEEE1284_MODE_ECP; - if(extensibility) mode = 8|3|IEEE1284_EXT_LINK; - - /* After some commands the camera needs extra time before - * it will respond again, so we try up to 3 times */ - for(retry=0; retry<3; ++retry) { - if(!parport_negotiate(cam->port, mode)) { - break; - } - } - if(retry == 3) { - if(extensibility) - DBG("Unable to negotiate extensibility mode\n"); - else - DBG("Unable to negotiate ECP mode\n"); - return -1; - } - if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP; - return 0; -} - -/**************************************************************************** - * - * WritePacket - * - ***************************************************************************/ -static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size) -{ - int retval=0; - int size_written; - - if (packet == NULL) { - return -EINVAL; - } - if (ForwardSetup(cam)) { - DBG("Write failed in setup\n"); - return -EIO; - } - size_written = parport_write(cam->port, packet, size); - if(size_written != size) { - DBG("Write failed, wrote %d/%d\n", size_written, size); - retval = -EIO; - } - EndTransferMode(cam); - return retval; -} - -/**************************************************************************** - * - * ReadPacket - * - ***************************************************************************/ -static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) -{ - int retval=0; - if (packet == NULL) { - return -EINVAL; - } - if (ReverseSetup(cam, 0)) { - return -EIO; - } - if(parport_read(cam->port, packet, size) != size) { - retval = -EIO; - } - EndTransferMode(cam); - return retval; -} - -/**************************************************************************** - * - * cpia_pp_streamStart - * - ***************************************************************************/ -static int cpia_pp_streamStart(void *privdata) -{ - struct pp_cam_entry *cam = privdata; - DBG("\n"); - cam->streaming=1; - cam->image_ready=0; - //if (ReverseSetup(cam,1)) return -EIO; - if(cam->stream_irq) cpia_parport_enable_irq(cam->port); - return 0; -} - -/**************************************************************************** - * - * cpia_pp_streamStop - * - ***************************************************************************/ -static int cpia_pp_streamStop(void *privdata) -{ - struct pp_cam_entry *cam = privdata; - - DBG("\n"); - cam->streaming=0; - cpia_parport_disable_irq(cam->port); - //EndTransferMode(cam); - - return 0; -} - -static int cpia_pp_read(struct parport *port, u8 *buffer, int len) -{ - int bytes_read, new_bytes; - for(bytes_read=0; bytes_readstreaming) DBG("%d / %d\n", cam->image_ready, noblock); - if( cam->stream_irq ) { - DBG("%d\n", cam->image_ready); - cam->image_ready--; - } - cam->image_complete=0; - if (0/*cam->streaming*/) { - if(!cam->image_ready) { - if(noblock) return -EWOULDBLOCK; - interruptible_sleep_on(&cam->wq_stream); - if( signal_pending(current) ) return -EINTR; - DBG("%d\n", cam->image_ready); - } - } else { - if (ReverseSetup(cam, 1)) { - DBG("unable to ReverseSetup\n"); - return -EIO; - } - } - endseen = 0; - block_size = PARPORT_CHUNK_SIZE; - while( !cam->image_complete ) { - if(current->need_resched) schedule(); - - new_bytes = cpia_pp_read(cam->port, buffer, block_size ); - if( new_bytes <= 0 ) { - break; - } - i=-1; - while(++iimage_complete=1; - break; - } - if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) { - block_size=CPIA_MAX_IMAGE_SIZE-read_bytes; - } - } - EndTransferMode(cam); - return cam->image_complete ? read_bytes : -EIO; -} - -/**************************************************************************** - * - * cpia_pp_transferCmd - * - ***************************************************************************/ -static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data) -{ - int err; - int retval=0; - int databytes; - struct pp_cam_entry *cam = privdata; - - if(cam == NULL) { - DBG("Internal driver error: cam is NULL\n"); - return -EINVAL; - } - if(command == NULL) { - DBG("Internal driver error: command is NULL\n"); - return -EINVAL; - } - databytes = (((int)command[7])<<8) | command[6]; - if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) { - DBG("Error writing command\n"); - return err; - } - if(command[0] == DATA_IN) { - u8 buffer[8]; - if(data == NULL) { - DBG("Internal driver error: data is NULL\n"); - return -EINVAL; - } - if((err = ReadPacket(cam, buffer, 8)) < 0) { - return err; - DBG("Error reading command result\n"); - } - memcpy(data, buffer, databytes); - } else if(command[0] == DATA_OUT) { - if(databytes > 0) { - if(data == NULL) { - DBG("Internal driver error: data is NULL\n"); - retval = -EINVAL; - } else { - if((err=WritePacket(cam, data, databytes)) < 0){ - DBG("Error writing command data\n"); - return err; - } - } - } - } else { - DBG("Unexpected first byte of command: %x\n", command[0]); - retval = -EINVAL; - } - return retval; -} - -/**************************************************************************** - * - * cpia_pp_open - * - ***************************************************************************/ -static int cpia_pp_open(void *privdata) -{ - struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata; - - if (cam == NULL) - return -EINVAL; - - if(cam->open_count == 0) { - if (parport_claim(cam->pdev)) { - DBG("failed to claim the port\n"); - return -EBUSY; - } - parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); - parport_data_forward(cam->port); - parport_write_control(cam->port, PARPORT_CONTROL_SELECT); - udelay(50); - parport_write_control(cam->port, - PARPORT_CONTROL_SELECT - | PARPORT_CONTROL_INIT); - } - - ++cam->open_count; - -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - return 0; -} - -/**************************************************************************** - * - * cpia_pp_registerCallback - * - ***************************************************************************/ -static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata) -{ - struct pp_cam_entry *cam = privdata; - int retval = 0; - - if(cam->port->irq != PARPORT_IRQ_NONE) { - cam->cb_task.routine = cb; - cam->cb_task.data = cbdata; - } else { - retval = -1; - } - return retval; -} - -/**************************************************************************** - * - * cpia_pp_close - * - ***************************************************************************/ -static int cpia_pp_close(void *privdata) -{ - struct pp_cam_entry *cam = privdata; -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - if (--cam->open_count == 0) { - parport_release(cam->pdev); - } - return 0; -} - -/**************************************************************************** - * - * cpia_pp_register - * - ***************************************************************************/ -static int cpia_pp_register(struct parport *port) -{ - struct pardevice *pdev = NULL; - struct pp_cam_entry *cam; - struct cam_data *cpia; - - if (!(port->modes & PARPORT_MODE_ECP) && - !(port->modes & PARPORT_MODE_TRISTATE)) { - LOG("port is not ECP capable\n"); - return -ENXIO; - } - - cam = kmalloc(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); - - if (!pdev) { - LOG("failed to parport_register_device\n"); - kfree(cam); - return -ENXIO; - } - - cam->pdev = pdev; - cam->port = port; - init_waitqueue_head(&cam->wq_stream); - - cam->streaming = 0; - cam->stream_irq = 0; - - if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) { - LOG("failed to cpia_register_camera\n"); - parport_unregister_device(pdev); - kfree(cam); - return -ENXIO; - } - ADD_TO_LIST(cam_list, cpia); - - return 0; -} - -static void cpia_pp_detach (struct parport *port) -{ - struct cam_data *cpia; - - for(cpia = cam_list; cpia != NULL; cpia = cpia->next) { - struct pp_cam_entry *cam = cpia->lowlevel_data; - if (cam && cam->port->number == port->number) { - REMOVE_FROM_LIST(cpia); - - cpia_unregister_camera(cpia); - - if(cam->open_count > 0) { - cpia_pp_close(cam); - } - - parport_unregister_device(cam->pdev); - - kfree(cam); - cpia->lowlevel_data = NULL; - break; - } - } -} - -static void cpia_pp_attach (struct parport *port) -{ - unsigned int i; - - switch (parport_nr[0]) - { - case PPCPIA_PARPORT_UNSPEC: - case PPCPIA_PARPORT_AUTO: - if (port->probe_info[0].class != PARPORT_CLASS_MEDIA || - port->probe_info[0].cmdset == NULL || - strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0) - return; - - cpia_pp_register(port); - - break; - - default: - for (i = 0; i < PARPORT_MAX; ++i) { - if (port->number == parport_nr[i]) { - cpia_pp_register(port); - break; - } - } - break; - } -} - -static struct parport_driver cpia_pp_driver = { - "cpia_pp", - cpia_pp_attach, - cpia_pp_detach, - NULL -}; - -int cpia_pp_init(void) -{ - printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, - CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); - - if(parport_nr[0] == PPCPIA_PARPORT_OFF) { - printk(" disabled\n"); - return 0; - } - - if (parport_register_driver (&cpia_pp_driver)) { - LOG ("unable to register with parport\n"); - return -EIO; - } - - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - if (parport[0]) { - /* The user gave some parameters. Let's see what they were. */ - if (!strncmp(parport[0], "auto", 4)) { - parport_nr[0] = PPCPIA_PARPORT_AUTO; - } else { - int n; - for (n = 0; n < PARPORT_MAX && parport[n]; n++) { - if (!strncmp(parport[n], "none", 4)) { - parport_nr[n] = PPCPIA_PARPORT_NONE; - } else { - char *ep; - unsigned long r = simple_strtoul(parport[n], &ep, 0); - if (ep != parport[n]) { - parport_nr[n] = r; - } else { - LOG("bad port specifier `%s'\n", parport[n]); - return -ENODEV; - } - } - } - } - } -#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE) - if(parport_enumerate() && !parport_enumerate()->probe_info.model) { - request_module("parport_probe"); - } -#endif - return cpia_pp_init(); -} - -void cleanup_module(void) -{ - parport_unregister_driver (&cpia_pp_driver); - return; -} - -#else /* !MODULE */ - -static int __init cpia_pp_setup(char *str) -{ -#if 0 - /* Is this only a 2.2ism? -jerdfelt */ - if (!str) { - if (ints[0] == 0 || ints[1] == 0) { - /* disable driver on "cpia_pp=" or "cpia_pp=0" */ - parport_nr[0] = PPCPIA_PARPORT_OFF; - } - } else -#endif - if (!strncmp(str, "parport", 7)) { - int n = simple_strtoul(str + 7, NULL, 10); - if (parport_ptr < PARPORT_MAX) { - parport_nr[parport_ptr++] = n; - } else { - LOG("too many ports, %s ignored.\n", str); - } - } else if (!strcmp(str, "auto")) { - parport_nr[0] = PPCPIA_PARPORT_AUTO; - } else if (!strcmp(str, "none")) { - parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; - } - - return 0; -} - -__setup("cpia_pp=", cpia_pp_setup); - -#endif /* !MODULE */ diff --git a/drivers/char/cpia_usb.c b/drivers/char/cpia_usb.c deleted file mode 100644 index 6b67fbc81..000000000 --- a/drivers/char/cpia_usb.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * cpia_usb CPiA USB driver - * - * Supports CPiA based parallel port Video Camera's. - * - * Copyright (C) 1999 Jochen Scharrlach - * Copyright (C) 1999, 2000 Johannes Erdfelt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include - -#include "cpia.h" - -#define USB_REQ_CPIA_GRAB_FRAME 0xC1 -#define USB_REQ_CPIA_UPLOAD_FRAME 0xC2 -#define WAIT_FOR_NEXT_FRAME 0 -#define FORCE_FRAME_UPLOAD 1 - -#define FRAMES_PER_DESC 10 -#define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */ -#define CPIA_NUMSBUF 2 -#define STREAM_BUF_SIZE (PAGE_SIZE * 4) -#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2) - -struct cpia_sbuf { - char *data; - urb_t *urb; -}; - -#define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100) -enum framebuf_status { - FRAME_EMPTY, - FRAME_READING, - FRAME_READY, - FRAME_ERROR, -}; - -struct framebuf { - int length; - enum framebuf_status status; - u8 data[FRAMEBUF_LEN]; - struct framebuf *next; -}; - -struct usb_cpia { - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - wait_queue_head_t wq_stream; - - int cursbuf; /* Current receiving sbuf */ - struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */ - - int streaming; - int open; - int present; - struct framebuf *buffers[3]; - struct framebuf *curbuff, *workbuff; -}; - -static int cpia_usb_open(void *privdata); -static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata); -static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data); -static int cpia_usb_streamStart(void *privdata); -static int cpia_usb_streamStop(void *privdata); -static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock); -static int cpia_usb_close(void *privdata); - -#define ABOUT "USB driver for Vision CPiA based cameras" - -static struct cpia_camera_ops cpia_usb_ops = { - cpia_usb_open, - cpia_usb_registerCallback, - cpia_usb_transferCmd, - cpia_usb_streamStart, - cpia_usb_streamStop, - cpia_usb_streamRead, - cpia_usb_close, - 0 -}; - -static struct cam_data *cam_list; - -static void cpia_usb_complete(struct urb *urb) -{ - int i; - char *cdata; - struct usb_cpia *ucpia; - - if (!urb || !urb->context) - return; - - ucpia = (struct usb_cpia *) urb->context; - - if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open) - return; - - if (ucpia->workbuff->status == FRAME_EMPTY) { - ucpia->workbuff->status = FRAME_READING; - ucpia->workbuff->length = 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - - cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - if (st) - printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st); - - if (FRAMEBUF_LEN < ucpia->workbuff->length + n) { - printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n); - return; - } - - if (n) { - if ((ucpia->workbuff->length > 0) || - (0x19 == cdata[0] && 0x68 == cdata[1])) { - memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n); - ucpia->workbuff->length += n; - } else - DBG("Ignoring packet!\n"); - } else { - if (ucpia->workbuff->length > 4 && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) { - ucpia->workbuff->status = FRAME_READY; - ucpia->curbuff = ucpia->workbuff; - ucpia->workbuff = ucpia->workbuff->next; - ucpia->workbuff->status = FRAME_EMPTY; - ucpia->workbuff->length = 0; - - if (waitqueue_active(&ucpia->wq_stream)) - wake_up_interruptible(&ucpia->wq_stream); - } - } - } -} - -static int cpia_usb_open(void *privdata) -{ - struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - urb_t *urb; - int ret, retval = 0, fx, err; - - if (!ucpia) - return -EINVAL; - - ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ucpia->sbuf[0].data) - return -EINVAL; - - ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ucpia->sbuf[1].data) { - retval = -EINVAL; - goto error_0; - } - - ret = usb_set_interface(ucpia->dev, ucpia->iface, 3); - if (ret < 0) { - printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret); - retval = -EBUSY; - goto error_all; - } - - ucpia->buffers[0]->status = FRAME_EMPTY; - ucpia->buffers[0]->length = 0; - ucpia->buffers[1]->status = FRAME_EMPTY; - ucpia->buffers[1]->length = 0; - ucpia->buffers[2]->status = FRAME_EMPTY; - ucpia->buffers[2]->length = 0; - ucpia->curbuff = ucpia->buffers[0]; - ucpia->workbuff = ucpia->buffers[1]; - - /* We double buffer the Iso lists */ - urb = usb_alloc_urb(FRAMES_PER_DESC); - if (!urb) { - printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n"); - retval = -ENOMEM; - goto error_all; - } - - ucpia->sbuf[0].urb = urb; - urb->dev = ucpia->dev; - urb->context = ucpia; - urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); - urb->transfer_flags = USB_ISO_ASAP; - urb->transfer_buffer = ucpia->sbuf[0].data; - urb->complete = cpia_usb_complete; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - - urb = usb_alloc_urb(FRAMES_PER_DESC); - if (!urb) { - printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n"); - retval = -ENOMEM; - goto error_all; - } - - ucpia->sbuf[1].urb = urb; - urb->dev = ucpia->dev; - urb->context = ucpia; - urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); - urb->transfer_flags = USB_ISO_ASAP; - urb->transfer_buffer = ucpia->sbuf[1].data; - urb->complete = cpia_usb_complete; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - - ucpia->sbuf[1].urb->next = ucpia->sbuf[0].urb; - ucpia->sbuf[0].urb->next = ucpia->sbuf[1].urb; - - err = usb_submit_urb(ucpia->sbuf[0].urb); - if (err) - printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n", - err); - err = usb_submit_urb(ucpia->sbuf[1].urb); - if (err) - printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n", - err); - - ucpia->streaming = 1; - ucpia->open = 1; - - return 0; - -error_all: - kfree (ucpia->sbuf[1].data); -error_0: - kfree (ucpia->sbuf[0].data); - - return retval; -} - -// -// convenience functions -// - -/**************************************************************************** - * - * WritePacket - * - ***************************************************************************/ -static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size) -{ - if (!packet) - return -EINVAL; - - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - packet[1] + (packet[0] << 8), - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - packet[2] + (packet[3] << 8), - packet[4] + (packet[5] << 8), buf, size, HZ); -} - -/**************************************************************************** - * - * ReadPacket - * - ***************************************************************************/ -static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size) -{ - if (!packet || size <= 0) - return -EINVAL; - - return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - packet[1] + (packet[0] << 8), - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - packet[2] + (packet[3] << 8), - packet[4] + (packet[5] << 8), buf, size, HZ); -} - -static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data) -{ - int err = 0; - int databytes; - struct usb_cpia *ucpia = (struct usb_cpia *)privdata; - struct usb_device *udev = ucpia->dev; - - if (!udev) { - DBG("Internal driver error: udev is NULL\n"); - return -EINVAL; - } - - if (!command) { - DBG("Internal driver error: command is NULL\n"); - return -EINVAL; - } - - databytes = (((int)command[7])<<8) | command[6]; - - if (command[0] == DATA_IN) { - u8 buffer[8]; - - if (!data) { - DBG("Internal driver error: data is NULL\n"); - return -EINVAL; - } - - err = ReadPacket(udev, command, buffer, 8); - if (err < 0) - return err; - - memcpy(data, buffer, databytes); - } else if(command[0] == DATA_OUT) - WritePacket(udev, command, data, databytes); - else { - DBG("Unexpected first byte of command: %x\n", command[0]); - err = -EINVAL; - } - - return 0; -} - -static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata) -{ - return -ENODEV; -} - -static int cpia_usb_streamStart(void *privdata) -{ - return -ENODEV; -} - -static int cpia_usb_streamStop(void *privdata) -{ - return -ENODEV; -} - -static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) -{ - struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - struct framebuf *mybuff; - - if (!ucpia || !ucpia->present) - return -1; - - if (ucpia->curbuff->status != FRAME_READY) - interruptible_sleep_on(&ucpia->wq_stream); - else - DBG("Frame already waiting!\n"); - - mybuff = ucpia->curbuff; - - if (!mybuff) - return -1; - - if (mybuff->status != FRAME_READY || mybuff->length < 4) { - DBG("Something went wrong!\n"); - return -1; - } - - memcpy(frame, mybuff->data, mybuff->length); - mybuff->status = FRAME_EMPTY; - -/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */ -/* mybuff->length, frame[0], frame[1], */ -/* frame[mybuff->length-4], frame[mybuff->length-3], */ -/* frame[mybuff->length-2], frame[mybuff->length-1]); */ - - return mybuff->length; -} - -static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try) -{ - if (!ucpia->streaming) - return; - - ucpia->streaming = 0; - - /* Set packet size to 0 */ - if (try) { - int ret; - - ret = usb_set_interface(ucpia->dev, ucpia->iface, 0); - if (ret < 0) { - printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret); - return; - } - } - - /* Unschedule all of the iso td's */ - if (ucpia->sbuf[1].urb) { - usb_unlink_urb(ucpia->sbuf[1].urb); - usb_free_urb(ucpia->sbuf[1].urb); - ucpia->sbuf[1].urb = NULL; - } - - if (ucpia->sbuf[0].urb) { - usb_unlink_urb(ucpia->sbuf[0].urb); - usb_free_urb(ucpia->sbuf[0].urb); - ucpia->sbuf[0].urb = NULL; - } -} - -static int cpia_usb_close(void *privdata) -{ - struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - - ucpia->open = 0; - - cpia_usb_free_resources(ucpia, 1); - - if (!ucpia->present) - kfree(ucpia); - - return 0; -} - -int cpia_usb_init(void) -{ - /* return -ENODEV; */ - return 0; -} - -/* Probing and initializing */ - -static void *cpia_probe(struct usb_device *udev, unsigned int ifnum) -{ - struct usb_interface_descriptor *interface; - struct usb_cpia *ucpia; - struct cam_data *cam; - int ret; - - /* A multi-config CPiA camera? */ - if (udev->descriptor.bNumConfigurations != 1) - return NULL; - - interface = &udev->actconfig->interface[ifnum].altsetting[0]; - - /* Is it a CPiA? */ - if (udev->descriptor.idVendor != 0x0553) - return NULL; - if (udev->descriptor.idProduct != 0x0002) - return NULL; - - /* We found a CPiA */ - printk(KERN_INFO "USB CPiA camera found\n"); - - ucpia = kmalloc(sizeof(*ucpia), GFP_KERNEL); - if (!ucpia) { - printk(KERN_ERR "couldn't kmalloc cpia struct\n"); - return NULL; - } - - memset(ucpia, 0, sizeof(*ucpia)); - - ucpia->dev = udev; - ucpia->iface = interface->bInterfaceNumber; - init_waitqueue_head(&ucpia->wq_stream); - - ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0])); - if (!ucpia->buffers[0]) { - printk(KERN_ERR "couldn't vmalloc frame buffer 0\n"); - goto fail_alloc_0; - } - - ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1])); - if (!ucpia->buffers[1]) { - printk(KERN_ERR "couldn't vmalloc frame buffer 1\n"); - goto fail_alloc_1; - } - - ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2])); - if (!ucpia->buffers[2]) { - printk(KERN_ERR "couldn't vmalloc frame buffer 2\n"); - goto fail_alloc_2; - } - - ucpia->buffers[0]->next = ucpia->buffers[1]; - ucpia->buffers[1]->next = ucpia->buffers[2]; - ucpia->buffers[2]->next = ucpia->buffers[0]; - - ret = usb_set_interface(udev, ucpia->iface, 0); - if (ret < 0) { - printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret); - /* goto fail_all; */ - } - - /* Before register_camera, important */ - ucpia->present = 1; - - cam = cpia_register_camera(&cpia_usb_ops, ucpia); - if (!cam) { - LOG("failed to cpia_register_camera\n"); - goto fail_all; - } - - ADD_TO_LIST(cam_list, cam); - - return cam; - -fail_all: - vfree(ucpia->buffers[2]); - ucpia->buffers[2] = NULL; -fail_alloc_2: - vfree(ucpia->buffers[1]); - ucpia->buffers[1] = NULL; -fail_alloc_1: - vfree(ucpia->buffers[0]); - ucpia->buffers[0] = NULL; -fail_alloc_0: - - return NULL; -} - -static void cpia_disconnect(struct usb_device *dev, void *ptr); - -static struct usb_driver cpia_driver = { - "cpia", - cpia_probe, - cpia_disconnect, - { NULL, NULL } -}; - -/* don't use dev, it may be NULL! (see usb_cpia_cleanup) */ -/* _disconnect from usb_cpia_cleanup is not necessary since usb_deregister */ -/* will do it for us as well as passing a udev structure - jerdfelt */ -static void cpia_disconnect(struct usb_device *udev, void *ptr) -{ - struct cam_data *cam = (struct cam_data *) ptr; - struct usb_cpia *ucpia = (struct usb_cpia *) cam->lowlevel_data; - - REMOVE_FROM_LIST(cam); - - /* Don't even try to reset the altsetting if we're disconnected */ - cpia_usb_free_resources(ucpia, 0); - - ucpia->present = 0; - - cpia_unregister_camera(cam); - - ucpia->curbuff->status = FRAME_ERROR; - - if (waitqueue_active(&ucpia->wq_stream)) - wake_up_interruptible(&ucpia->wq_stream); - - usb_driver_release_interface(&cpia_driver, - &udev->actconfig->interface[0]); - - ucpia->curbuff = ucpia->workbuff = NULL; - - if (ucpia->buffers[2]) { - vfree(ucpia->buffers[2]); - ucpia->buffers[2] = NULL; - } - - if (ucpia->buffers[1]) { - vfree(ucpia->buffers[1]); - ucpia->buffers[1] = NULL; - } - - if (ucpia->buffers[0]) { - vfree(ucpia->buffers[0]); - ucpia->buffers[0] = NULL; - } - - if (!ucpia->open) - kfree(ucpia); -} - -int usb_cpia_init(void) -{ - cam_list = NULL; - - return usb_register(&cpia_driver); -} - -void usb_cpia_cleanup(void) -{ -/* - struct cam_data *cam; - - while ((cam = cam_list) != NULL) - cpia_disconnect(NULL, cam); -*/ - - usb_deregister(&cpia_driver); -} - -#ifdef MODULE -int init_module(void) -{ - return usb_cpia_init(); -} - -void cleanup_module(void) -{ - usb_cpia_cleanup(); -} -#endif /* !MODULE */ diff --git a/drivers/char/cs8420.h b/drivers/char/cs8420.h deleted file mode 100644 index 2b22f3a38..000000000 --- a/drivers/char/cs8420.h +++ /dev/null @@ -1,50 +0,0 @@ -/* cs8420.h - cs8420 initializations - Copyright (C) 1999 Nathan Laredo (laredo@gnu.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. - - */ -#ifndef __CS8420_H__ -#define __CS8420_H__ - -/* Initialization Sequence */ - -static __u8 init8420[] = { - 1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46, - 5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13, -}; - -#define INIT8420LEN (sizeof(init8420)/2) - -static __u8 mode8420pro[] = { /* professional output mode */ - 32, 0xa1, 33, 0x00, 34, 0x00, 35, 0x00, - 36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00, - 40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00, - 44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00, - 48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00, - 52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00, -}; -#define MODE8420LEN (sizeof(mode8420pro)/2) - -static __u8 mode8420con[] = { /* consumer output mode */ - 32, 0x20, 33, 0x00, 34, 0x00, 35, 0x48, - 36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00, - 40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00, - 44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00, - 48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00, - 52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00, -}; - -#endif diff --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c index 7ed234e15..42a1bc2f6 100644 --- a/drivers/char/drm/agpsupport.c +++ b/drivers/char/drm/agpsupport.c @@ -309,7 +309,9 @@ drm_agp_head_t *drm_agp_init(void) #if LINUX_VERSION_CODE >= 0x020400 case VIA_MVP4: head->chipset = "VIA MVP4"; break; - case VIA_APOLLO_SUPER: head->chipset = "VIA Apollo Super"; + case VIA_APOLLO_KX133: head->chipset = "VIA Apollo KX133"; + break; + case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133"; break; #endif @@ -322,7 +324,7 @@ drm_agp_head_t *drm_agp_init(void) case ALI_M1541: head->chipset = "ALi M1541"; break; default: head->chipset = "Unknown"; break; } - DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n", + DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n", head->agp_info.version.major, head->agp_info.version.minor, head->chipset, diff --git a/drivers/char/drm/auth.c b/drivers/char/drm/auth.c index 9f81c5391..4556bd966 100644 --- a/drivers/char/drm/auth.c +++ b/drivers/char/drm/auth.c @@ -126,12 +126,12 @@ int drm_getmagic(struct inode *inode, struct file *filp, unsigned int cmd, if (priv->magic) { auth.magic = priv->magic; } else { - spin_lock(&lock); do { + spin_lock(&lock); if (!sequence) ++sequence; /* reserve 0 */ auth.magic = sequence++; + spin_unlock(&lock); } while (drm_find_file(dev, auth.magic)); - spin_unlock(&lock); priv->magic = auth.magic; drm_add_magic(dev, priv, auth.magic); } diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 0fa205717..e8ec9bdbc 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -328,6 +328,7 @@ typedef struct drm_freelist { int low_mark; /* Low water mark */ int high_mark; /* High water mark */ atomic_t wfh; /* If waiting for high mark */ + spinlock_t lock; } drm_freelist_t; typedef struct drm_buf_entry { @@ -450,6 +451,11 @@ typedef struct { extern drm_agp_func_t drm_agp; #endif +typedef struct drm_sigdata { + int context; + drm_hw_lock_t *lock; +} drm_sigdata_t; + typedef struct drm_device { const char *name; /* Simple driver name */ char *unique; /* Unique identifier: e.g., busid */ @@ -534,6 +540,8 @@ typedef struct drm_device { #endif unsigned long *ctx_bitmap; void *dev_private; + drm_sigdata_t sigdata; /* For block_all_signals */ + sigset_t sigmask; } drm_device_t; @@ -728,6 +736,7 @@ extern int drm_flush_unblock(drm_device_t *dev, int context, drm_lock_flags_t flags); extern int drm_flush_block_and_flush(drm_device_t *dev, int context, drm_lock_flags_t flags); +extern int drm_notifier(void *priv); /* Context Bitmap support (ctxbitmap.c) */ extern int drm_ctxbitmap_init(drm_device_t *dev); diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c index d81685230..84c7f0644 100644 --- a/drivers/char/drm/ffb_drv.c +++ b/drivers/char/drm/ffb_drv.c @@ -1,4 +1,4 @@ -/* $Id: ffb_drv.c,v 1.5 2000/07/26 01:03:57 davem Exp $ +/* $Id: ffb_drv.c,v 1.6 2000/08/10 05:26:23 davem Exp $ * ffb_drv.c: Creator/Creator3D direct rendering driver. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) @@ -754,6 +754,7 @@ static void align_shm_mapping(struct vm_area_struct *vma, unsigned long kvirt) extern struct vm_operations_struct drm_vm_ops; extern struct vm_operations_struct drm_vm_shm_ops; +extern struct vm_operations_struct drm_vm_shm_lock_ops; static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) { @@ -766,7 +767,6 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", vma->vm_start, vma->vm_end, VM_OFFSET(vma)); - lock_kernel(); minor = MINOR(filp->f_dentry->d_inode->i_rdev); ffb_priv = NULL; for (i = 0; i < ffb_dev_table_size; i++) { @@ -774,15 +774,13 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) if (ffb_priv->miscdev.minor == minor) break; } - if (i >= ffb_dev_table_size) { - unlock_kernel(); + if (i >= ffb_dev_table_size) return -EINVAL; - } + /* We don't support/need dma mappings, so... */ - if (!VM_OFFSET(vma)) { - unlock_kernel(); + if (!VM_OFFSET(vma)) return -EINVAL; - } + for (i = 0; i < dev->map_count; i++) { unsigned long off; @@ -794,19 +792,16 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) break; } - if (i >= dev->map_count) { - unlock_kernel(); + if (i >= dev->map_count) return -EINVAL; - } + if (!map || - ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) { - unlock_kernel(); + ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) return -EPERM; - } - if (map->size != (vma->vm_end - vma->vm_start)) { - unlock_kernel(); + + if (map->size != (vma->vm_end - vma->vm_start)) return -EINVAL; - } + /* Set read-only attribute before mappings are created * so it works for fb/reg maps too. */ @@ -829,15 +824,19 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) if (io_remap_page_range(vma->vm_start, ffb_priv->card_phys_base + VM_OFFSET(vma), vma->vm_end - vma->vm_start, - vma->vm_page_prot, 0)) { - unlock_kernel(); + vma->vm_page_prot, 0)) return -EAGAIN; - } + vma->vm_ops = &drm_vm_ops; break; case _DRM_SHM: align_shm_mapping(vma, (unsigned long)dev->lock.hw_lock); - vma->vm_ops = &drm_vm_shm_ops; + if (map->flags & _DRM_CONTAINS_LOCK) + vma->vm_ops = &drm_vm_shm_lock_ops; + else { + vma->vm_ops = &drm_vm_shm_ops; + vma->vm_private_data = (void *) map; + } /* Don't let this area swap. Change when * DRM_KERNEL advisory is supported. @@ -845,10 +844,8 @@ static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_LOCKED; break; default: - unlock_kernel(); return -EINVAL; /* This should never happen. */ }; - unlock_kernel(); vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ diff --git a/drivers/char/drm/lists.c b/drivers/char/drm/lists.c index f62495aa2..5da7cc6c5 100644 --- a/drivers/char/drm/lists.c +++ b/drivers/char/drm/lists.c @@ -116,6 +116,7 @@ int drm_freelist_create(drm_freelist_t *bl, int count) bl->low_mark = 0; bl->high_mark = 0; atomic_set(&bl->wfh, 0); + bl->lock = SPIN_LOCK_UNLOCKED; ++bl->initialized; return 0; } @@ -130,8 +131,6 @@ int drm_freelist_destroy(drm_freelist_t *bl) int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf) { - drm_buf_t *old, *prev; - int count = 0; drm_device_dma_t *dma = dev->dma; if (!dma) { @@ -152,15 +151,12 @@ int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf) drm_histogram_compute(dev, buf); #endif buf->list = DRM_LIST_FREE; - do { - old = bl->next; - buf->next = old; - prev = cmpxchg(&bl->next, old, buf); - if (++count > DRM_LOOPING_LIMIT) { - DRM_ERROR("Looping\n"); - return 1; - } - } while (prev != old); + + spin_lock(&bl->lock); + buf->next = bl->next; + bl->next = buf; + spin_unlock(&bl->lock); + atomic_inc(&bl->count); if (atomic_read(&bl->count) > dma->buf_count) { DRM_ERROR("%d of %d buffers free after addition of %d\n", @@ -177,26 +173,21 @@ int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf) static drm_buf_t *drm_freelist_try(drm_freelist_t *bl) { - drm_buf_t *old, *new, *prev; drm_buf_t *buf; - int count = 0; if (!bl) return NULL; /* Get buffer */ - do { - old = bl->next; - if (!old) return NULL; - new = bl->next->next; - prev = cmpxchg(&bl->next, old, new); - if (++count > DRM_LOOPING_LIMIT) { - DRM_ERROR("Looping\n"); - return NULL; - } - } while (prev != old); - atomic_dec(&bl->count); + spin_lock(&bl->lock); + if (!bl->next) { + spin_unlock(&bl->lock); + return NULL; + } + buf = bl->next; + bl->next = bl->next->next; + spin_unlock(&bl->lock); - buf = old; + atomic_dec(&bl->count); buf->next = NULL; buf->list = DRM_LIST_NONE; DRM_DEBUG("%d, count = %d, wfh = %d, w%d, p%d\n", diff --git a/drivers/char/drm/lock.c b/drivers/char/drm/lock.c index 550827278..33b2cc03f 100644 --- a/drivers/char/drm/lock.c +++ b/drivers/char/drm/lock.c @@ -223,3 +223,35 @@ int drm_finish(struct inode *inode, struct file *filp, unsigned int cmd, drm_flush_unblock(dev, lock.context, lock.flags); return ret; } + +/* If we get here, it means that the process has called DRM_IOCTL_LOCK + without calling DRM_IOCTL_UNLOCK. + + If the lock is not held, then let the signal proceed as usual. + + If the lock is held, then set the contended flag and keep the signal + blocked. + + + Return 1 if the signal should be delivered normally. + Return 0 if the signal should be blocked. */ + +int drm_notifier(void *priv) +{ + drm_sigdata_t *s = (drm_sigdata_t *)priv; + unsigned int old, new, prev; + + + /* Allow signal delivery if lock isn't held */ + if (!_DRM_LOCK_IS_HELD(s->lock->lock) + || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1; + + /* Otherwise, set flag to force call to + drmUnlock */ + do { + old = s->lock->lock; + new = old | _DRM_LOCK_CONT; + prev = cmpxchg(&s->lock->lock, old, new); + } while (prev != old); + return 0; +} diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index d02c3b581..0df0906e5 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c @@ -765,7 +765,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { dev_priv->mAccess = init->mAccess; init_waitqueue_head(&dev_priv->flush_queue); init_waitqueue_head(&dev_priv->buf_queue); - dev_priv->WarpPipe = -1; + dev_priv->WarpPipe = 0xff000000; DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n", dev_priv->chipset, dev_priv->warp_ucode_size, diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index fac882471..e0080e595 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -656,6 +656,14 @@ int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, #endif if (!ret) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); if (lock.flags & _DRM_LOCK_READY) { /* Wait for space in DMA/FIFO */ } @@ -719,6 +727,6 @@ int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, current->priority = DEF_PRIORITY; } #endif - + unblock_all_signals(); return 0; } diff --git a/drivers/char/drm/vm.c b/drivers/char/drm/vm.c index d295529ba..7c5a24bc9 100644 --- a/drivers/char/drm/vm.c +++ b/drivers/char/drm/vm.c @@ -250,7 +250,7 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) vma->vm_start, vma->vm_end, VM_OFFSET(vma)); /* Length must match exact page count */ - if ((length >> PAGE_SHIFT) != dma->page_count) { + if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { unlock_kernel(); return -EINVAL; } @@ -323,6 +323,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; } +#elif defined(__ia64__) + if (map->type != _DRM_AGP) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); #endif vma->vm_flags |= VM_IO; /* not in core dump */ } diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index f0c76181b..8b8d0f123 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -13,6 +13,7 @@ #include #include +#include #include #include diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 9bb1748ae..4639f34eb 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -395,11 +395,10 @@ efi_rtc_init(void) return 0; } -static int __exit +static void __exit efi_rtc_exit(void) { /* not yet used */ - return 0; } module_init(efi_rtc_init); diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 01eb20e92..6ceb5a152 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -12,7 +12,12 @@ * Version 0.1 -- December, 1998. Initial version. * Version 0.2 -- March, 1999. Some more routines. Bugfixes. Etc. * Version 0.5 -- August, 1999. Some more fixes. Reformat for Linus. - */ + * + * BitWizard is actively maintaining this file. We sometimes find + * that someone submitted changes to this file. We really appreciate + * your help, but please submit changes through us. We're doing our + * best to be responsive. -- REW + * */ #include #include @@ -80,10 +85,18 @@ static void my_hd (unsigned char *addr, int len) void gs_put_char(struct tty_struct * tty, unsigned char ch) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; DECL - /* func_enter (); */ + func_enter (); + + if (!tty) return; + + port = tty->driver_data; + + if (!port) return; + + if (! (port->flags & ASYNC_INITIALIZED)) return; /* Take a lock on the serial tranmit buffer! */ LOCKIT; @@ -99,7 +112,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) port->xmit_cnt++; /* Characters in buffer */ RELEASEIT; - /* func_exit ();*/ + func_exit (); } @@ -115,11 +128,17 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) int gs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; int c, total = 0; int t; - /* func_enter (); */ + func_enter (); + + if (!tty) return 0; + + port = tty->driver; + + if (!port) return 0; if (! (port->flags & ASYNC_INITIALIZED)) return 0; @@ -170,7 +189,7 @@ int gs_write(struct tty_struct * tty, int from_user, port->flags |= GS_TX_INTEN; port->rd->enable_tx_interrupts (port); } - /* func_exit (); */ + func_exit (); return total; } #else @@ -309,11 +328,11 @@ int gs_write_room(struct tty_struct * tty) struct gs_port *port = tty->driver_data; int ret; - /* func_enter (); */ + func_enter (); ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; if (ret < 0) ret = 0; - /* func_exit (); */ + func_exit (); return ret; } @@ -361,7 +380,7 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) if (!port || port->xmit_cnt < 0 || !port->xmit_buf) { gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n"); - func_exit(); + func_exit(); return -EINVAL; /* This is an error which we don't know how to handle. */ } @@ -399,7 +418,7 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies " "(%d chars).\n", jiffies_to_transmit, charsleft); - current->state = TASK_INTERRUPTIBLE; + set_current_state (TASK_INTERRUPTIBLE); schedule_timeout(jiffies_to_transmit); if (signal_pending (current)) { gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); @@ -409,7 +428,7 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) } gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); - current->state = TASK_RUNNING; + set_current_state (TASK_RUNNING); func_exit(); return rv; @@ -419,10 +438,17 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) void gs_flush_buffer(struct tty_struct *tty) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; unsigned long flags; func_enter (); + + if (!tty) return; + + port = tty->driver_data; + + if (!port) return; + /* XXX Would the write semaphore do? */ save_flags(flags); cli(); port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; @@ -438,9 +464,16 @@ void gs_flush_buffer(struct tty_struct *tty) void gs_flush_chars(struct tty_struct * tty) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; func_enter (); + + if (!tty) return; + + port = tty->driver_data; + + if (!port) return; + if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !port->xmit_buf) { func_exit (); @@ -456,9 +489,16 @@ void gs_flush_chars(struct tty_struct * tty) void gs_stop(struct tty_struct * tty) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; func_enter (); + + if (!tty) return; + + port = tty->driver_data; + + if (!port) return; + if (port->xmit_cnt && port->xmit_buf && (port->flags & GS_TX_INTEN) ) { @@ -471,7 +511,13 @@ void gs_stop(struct tty_struct * tty) void gs_start(struct tty_struct * tty) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; + + if (!tty) return; + + port = tty->driver_data; + + if (!port) return; if (port->xmit_cnt && port->xmit_buf && @@ -486,7 +532,11 @@ void gs_start(struct tty_struct * tty) void gs_shutdown_port (struct gs_port *port) { long flags; + func_enter(); + + if (!port) return; + if (!(port->flags & ASYNC_INITIALIZED)) return; @@ -505,16 +555,20 @@ void gs_shutdown_port (struct gs_port *port) port->flags &= ~ASYNC_INITIALIZED; restore_flags (flags); + func_exit(); } void gs_hangup(struct tty_struct *tty) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; func_enter (); + if (!tty) return; + + port = tty->driver_data; tty = port->tty; if (!tty) return; @@ -534,8 +588,13 @@ void gs_do_softint(void *private_) struct gs_port *port = private_; struct tty_struct *tty; + func_enter (); + + if (!port) return; + tty = port->tty; - if(!tty) return; + + if (!tty) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && @@ -557,8 +616,13 @@ int block_til_ready(void *port_, struct file * filp) struct tty_struct *tty; func_enter (); + + if (!port) return 0; + tty = port->tty; + if (!tty) return 0; + gs_dprintk (GS_DEBUG_BTR, "Entering block_till_ready.\n"); /* * If the device is in the middle of being closed, then block @@ -571,6 +635,7 @@ int block_til_ready(void *port_, struct file * filp) else return -ERESTARTSYS; } + gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); /* @@ -593,6 +658,7 @@ int block_til_ready(void *port_, struct file * filp) } gs_dprintk (GS_DEBUG_BTR, "after subtype\n"); + /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. @@ -606,6 +672,7 @@ int block_til_ready(void *port_, struct file * filp) } gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); + if (port->flags & ASYNC_CALLOUT_ACTIVE) { if (port->normal_termios.c_cflag & CLOCAL) do_clocal = 1; @@ -614,7 +681,6 @@ int block_til_ready(void *port_, struct file * filp) do_clocal = 1; } - gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -623,9 +689,9 @@ int block_til_ready(void *port_, struct file * filp) * exit, either normal or abnormal. */ retval = 0; - + add_wait_queue(&port->open_wait, &wait); - + gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); cli(); if (!tty_hung_up_p(filp)) @@ -635,7 +701,7 @@ int block_til_ready(void *port_, struct file * filp) while (1) { CD = port->rd->get_CD (port); gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state (TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { if (port->flags & ASYNC_HUP_NOTIFY) @@ -679,12 +745,11 @@ void gs_close(struct tty_struct * tty, struct file * filp) func_enter (); + if (!tty) return; + port = (struct gs_port *) tty->driver_data; - if(! port) { - func_exit(); - return; - } + if (!port) return; if (!port->tty) { /* This seems to happen when this is called from vhangup. */ @@ -693,6 +758,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) } save_flags(flags); cli(); + if (tty_hung_up_p(filp)) { restore_flags(flags); port->rd->hungup (port); @@ -761,7 +827,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) if (port->blocked_open) { if (port->close_delay) { - current->state = TASK_INTERRUPTIBLE; + set_current_state (TASK_INTERRUPTIBLE); schedule_timeout(port->close_delay); } wake_up_interruptible(&port->open_wait); @@ -784,14 +850,19 @@ static unsigned int gs_baudrates[] = { void gs_set_termios (struct tty_struct * tty, struct termios * old_termios) { - struct gs_port *port = tty->driver_data; + struct gs_port *port; int baudrate, tmp, rv; struct termios *tiosp; func_enter(); - tiosp = tty->termios; + if (!tty) return; + + port = tty->driver_data; + if (!port) return; + + tiosp = tty->termios; if (gs_debug & GS_DEBUG_TERMIOS) { gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); diff --git a/drivers/char/i2c-old.c b/drivers/char/i2c-old.c deleted file mode 100644 index bd9750fc3..000000000 --- a/drivers/char/i2c-old.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Generic i2c interface for linux - * - * (c) 1998 Gerd Knorr - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REGPRINT(x) if (verbose) (x) -#define I2C_DEBUG(x) if (i2c_debug) (x) - -static int scan = 0; -static int verbose = 0; -static int i2c_debug = 0; - -#if LINUX_VERSION_CODE >= 0x020117 -MODULE_PARM(scan,"i"); -MODULE_PARM(verbose,"i"); -MODULE_PARM(i2c_debug,"i"); -#endif - -/* ----------------------------------------------------------------------- */ - -static struct i2c_bus *busses[I2C_BUS_MAX]; -static struct i2c_driver *drivers[I2C_DRIVER_MAX]; -static int bus_count = 0, driver_count = 0; - -#ifdef CONFIG_VIDEO_BT848 -extern int i2c_tuner_init(void); -extern int msp3400c_init(void); -#endif -#ifdef CONFIG_VIDEO_BUZ -extern int saa7111_init(void); -extern int saa7185_init(void); -#endif -#ifdef CONFIG_VIDEO_LML33 -extern int bt819_init(void); -extern int bt856_init(void); -#endif - -int i2c_init(void) -{ - printk(KERN_INFO "i2c: initialized%s\n", - scan ? " (i2c bus scan enabled)" : ""); - /* anything to do here ? */ -#ifdef CONFIG_VIDEO_BT848 - i2c_tuner_init(); - msp3400c_init(); -#endif -#ifdef CONFIG_VIDEO_BUZ - saa7111_init(); - saa7185_init(); -#endif -#ifdef CONFIG_VIDEO_LML33 - bt819_init(); - bt856_init(); -#endif - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static void i2c_attach_device(struct i2c_bus *bus, struct i2c_driver *driver) -{ - struct i2c_device *device; - int i,j,ack=1; - unsigned char addr; - LOCK_FLAGS; - - /* probe for device */ - LOCK_I2C_BUS(bus); - for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2) - { - i2c_start(bus); - ack = i2c_sendbyte(bus,addr,0); - i2c_stop(bus); - if (!ack) - break; - } - UNLOCK_I2C_BUS(bus); - if (ack) - return; - - /* got answer */ - for (i = 0; i < I2C_DEVICE_MAX; i++) - if (NULL == driver->devices[i]) - break; - if (I2C_DEVICE_MAX == i) - return; - - for (j = 0; j < I2C_DEVICE_MAX; j++) - if (NULL == bus->devices[j]) - break; - if (I2C_DEVICE_MAX == j) - return; - - if (NULL == (device = kmalloc(sizeof(struct i2c_device),GFP_KERNEL))) - return; - device->bus = bus; - device->driver = driver; - device->addr = addr; - - /* Attach */ - - if (driver->attach(device)!=0) - { - kfree(device); - return; - } - driver->devices[i] = device; - driver->devcount++; - bus->devices[j] = device; - bus->devcount++; - - if (bus->attach_inform) - bus->attach_inform(bus,driver->id); - REGPRINT(printk("i2c: device attached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,addr,bus->name,driver->name)); -} - -static void i2c_detach_device(struct i2c_device *device) -{ - int i; - - if (device->bus->detach_inform) - device->bus->detach_inform(device->bus,device->driver->id); - device->driver->detach(device); - - for (i = 0; i < I2C_DEVICE_MAX; i++) - if (device == device->driver->devices[i]) - break; - if (I2C_DEVICE_MAX == i) - { - printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n", - device->name); - return; - } - device->driver->devices[i] = NULL; - device->driver->devcount--; - - for (i = 0; i < I2C_DEVICE_MAX; i++) - if (device == device->bus->devices[i]) - break; - if (I2C_DEVICE_MAX == i) - { - printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n", - device->name); - return; - } - device->bus->devices[i] = NULL; - device->bus->devcount--; - - REGPRINT(printk("i2c: device detached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,device->addr,device->bus->name,device->driver->name)); - kfree(device); -} - -/* ----------------------------------------------------------------------- */ - -int i2c_register_bus(struct i2c_bus *bus) -{ - int i,ack; - LOCK_FLAGS; - - memset(bus->devices,0,sizeof(bus->devices)); - bus->devcount = 0; - - for (i = 0; i < I2C_BUS_MAX; i++) - if (NULL == busses[i]) - break; - if (I2C_BUS_MAX == i) - return -ENOMEM; - - busses[i] = bus; - bus_count++; - REGPRINT(printk("i2c: bus registered: %s\n",bus->name)); - - MOD_INC_USE_COUNT; - - if (scan) - { - /* scan whole i2c bus */ - LOCK_I2C_BUS(bus); - for (i = 0; i < 256; i+=2) - { - i2c_start(bus); - ack = i2c_sendbyte(bus,i,0); - i2c_stop(bus); - if (!ack) - { - printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n", - bus->name,i); - } - } - UNLOCK_I2C_BUS(bus); - } - - /* probe available drivers */ - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (drivers[i]) - i2c_attach_device(bus,drivers[i]); - return 0; -} - -int i2c_unregister_bus(struct i2c_bus *bus) -{ - int i; - - /* detach devices */ - for (i = 0; i < I2C_DEVICE_MAX; i++) - if (bus->devices[i]) - i2c_detach_device(bus->devices[i]); - - for (i = 0; i < I2C_BUS_MAX; i++) - if (bus == busses[i]) - break; - if (I2C_BUS_MAX == i) - { - printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n", - bus->name); - return -ENODEV; - } - - MOD_DEC_USE_COUNT; - - busses[i] = NULL; - bus_count--; - REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name)); - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -int i2c_register_driver(struct i2c_driver *driver) -{ - int i; - - memset(driver->devices,0,sizeof(driver->devices)); - driver->devcount = 0; - - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (NULL == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) - return -ENOMEM; - - drivers[i] = driver; - driver_count++; - - MOD_INC_USE_COUNT; - - REGPRINT(printk("i2c: driver registered: %s\n",driver->name)); - - /* Probe available busses */ - for (i = 0; i < I2C_BUS_MAX; i++) - if (busses[i]) - i2c_attach_device(busses[i],driver); - - return 0; -} - -int i2c_unregister_driver(struct i2c_driver *driver) -{ - int i; - - /* detach devices */ - for (i = 0; i < I2C_DEVICE_MAX; i++) - if (driver->devices[i]) - i2c_detach_device(driver->devices[i]); - - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (driver == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) - { - printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n", - driver->name); - return -ENODEV; - } - - MOD_DEC_USE_COUNT; - - drivers[i] = NULL; - driver_count--; - REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name)); - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -int i2c_control_device(struct i2c_bus *bus, int id, - unsigned int cmd, void *arg) -{ - int i; - - for (i = 0; i < I2C_DEVICE_MAX; i++) - if (bus->devices[i] && bus->devices[i]->driver->id == id) - break; - if (i == I2C_DEVICE_MAX) - return -ENODEV; - if (NULL == bus->devices[i]->driver->command) - return -ENODEV; - return bus->devices[i]->driver->command(bus->devices[i],cmd,arg); -} - -/* ----------------------------------------------------------------------- */ - -#define I2C_SET(bus,ctrl,data) (bus->i2c_setlines(bus,ctrl,data)) -#define I2C_GET(bus) (bus->i2c_getdataline(bus)) - -void i2c_start(struct i2c_bus *bus) -{ - I2C_SET(bus,0,1); - I2C_SET(bus,1,1); - I2C_SET(bus,1,0); - I2C_SET(bus,0,0); - I2C_DEBUG(printk("%s: < ",bus->name)); -} - -void i2c_stop(struct i2c_bus *bus) -{ - I2C_SET(bus,0,0); - I2C_SET(bus,1,0); - I2C_SET(bus,1,1); - I2C_DEBUG(printk(">\n")); -} - -void i2c_one(struct i2c_bus *bus) -{ - I2C_SET(bus,0,1); - I2C_SET(bus,1,1); - I2C_SET(bus,0,1); -} - -void i2c_zero(struct i2c_bus *bus) -{ - I2C_SET(bus,0,0); - I2C_SET(bus,1,0); - I2C_SET(bus,0,0); -} - -int i2c_ack(struct i2c_bus *bus) -{ - int ack; - - I2C_SET(bus,0,1); - I2C_SET(bus,1,1); - ack = I2C_GET(bus); - I2C_SET(bus,0,1); - return ack; -} - -int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack) -{ - int i, ack; - - I2C_SET(bus,0,0); - for (i=7; i>=0; i--) - (data&(1<=0; i--) - { - I2C_SET(bus,1,1); - if (I2C_GET(bus)) - data |= (1<i2c_read) - return bus->i2c_read(bus, addr); - - i2c_start(bus); - i2c_sendbyte(bus,addr,0); - ret = i2c_readbyte(bus,1); - i2c_stop(bus); - return ret; -} - -int i2c_write(struct i2c_bus *bus, unsigned char addr, - unsigned char data1, unsigned char data2, int both) -{ - int ack; - - if (bus->i2c_write) - return bus->i2c_write(bus, addr, data1, data2, both); - - i2c_start(bus); - i2c_sendbyte(bus,addr,0); - ack = i2c_sendbyte(bus,data1,0); - if (both) - ack = i2c_sendbyte(bus,data2,0); - i2c_stop(bus); - return ack ? -1 : 0 ; -} - -/* ----------------------------------------------------------------------- */ - -#ifdef MODULE - -#if LINUX_VERSION_CODE >= 0x020100 -EXPORT_SYMBOL(i2c_register_bus); -EXPORT_SYMBOL(i2c_unregister_bus); -EXPORT_SYMBOL(i2c_register_driver); -EXPORT_SYMBOL(i2c_unregister_driver); -EXPORT_SYMBOL(i2c_control_device); -EXPORT_SYMBOL(i2c_start); -EXPORT_SYMBOL(i2c_stop); -EXPORT_SYMBOL(i2c_one); -EXPORT_SYMBOL(i2c_zero); -EXPORT_SYMBOL(i2c_ack); -EXPORT_SYMBOL(i2c_sendbyte); -EXPORT_SYMBOL(i2c_readbyte); -EXPORT_SYMBOL(i2c_read); -EXPORT_SYMBOL(i2c_write); -#endif - -int init_module(void) -{ - return i2c_init(); -} - -void cleanup_module(void) -{ -} -#endif diff --git a/drivers/char/i2c-parport.c b/drivers/char/i2c-parport.c deleted file mode 100644 index 00b574f60..000000000 --- a/drivers/char/i2c-parport.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * I2C driver for parallel port - * - * Author: Phil Blundell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * This driver implements a simple I2C protocol by bit-twiddling some - * signals on the parallel port. Since the outputs on the parallel port - * aren't open collector, three lines rather than two are used: - * - * D0 clock out - * D1 data out - * BUSY data in - */ - -#include -#include -#include -#include -#include -#include - -#define I2C_DELAY 10 - -static int debug = 0; - -struct parport_i2c_bus -{ - struct i2c_bus i2c; - struct parport_i2c_bus *next; -}; - -static struct parport_i2c_bus *bus_list; - -static spinlock_t bus_list_lock = SPIN_LOCK_UNLOCKED; - -/* software I2C functions */ - -static void i2c_setlines(struct i2c_bus *bus, int clk, int data) -{ - struct parport *p = bus->data; - parport_write_data(p, (clk?1:0) | (data?2:0)); - udelay(I2C_DELAY); -} - -static int i2c_getdataline(struct i2c_bus *bus) -{ - struct parport *p = bus->data; - return (parport_read_status(p) & PARPORT_STATUS_BUSY) ? 0 : 1; -} - -static struct i2c_bus parport_i2c_bus_template = -{ - "...", - I2C_BUSID_PARPORT, - NULL, - - SPIN_LOCK_UNLOCKED, - - NULL, - NULL, - - i2c_setlines, - i2c_getdataline, - NULL, - NULL, -}; - -static void i2c_parport_attach(struct parport *port) -{ - struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus), - GFP_KERNEL); - b->i2c = parport_i2c_bus_template; - b->i2c.data = parport_get_port (port); - strncpy(b->i2c.name, port->name, 32); - spin_lock(&bus_list_lock); - b->next = bus_list; - bus_list = b; - spin_unlock(&bus_list_lock); - i2c_register_bus(&b->i2c); - if (debug) - printk(KERN_DEBUG "i2c: attached to %s\n", port->name); -} - -static void i2c_parport_detach(struct parport *port) -{ - struct parport_i2c_bus *b, *old_b = NULL; - spin_lock(&bus_list_lock); - b = bus_list; - while (b) - { - if (b->i2c.data == port) - { - if (old_b) - old_b->next = b->next; - else - bus_list = b->next; - i2c_unregister_bus(&b->i2c); - kfree(b); - break; - } - old_b = b; - b = b->next; - } - spin_unlock(&bus_list_lock); - if (debug) - printk(KERN_DEBUG "i2c: detached from %s\n", port->name); -} - -static struct parport_driver parport_i2c_driver = -{ - "i2c", - i2c_parport_attach, - i2c_parport_detach -}; - -#ifdef MODULE -int init_module(void) -#else -int __init i2c_parport_init(void) -#endif -{ - printk("I2C: driver for parallel port v0.1 philb@gnu.org\n"); - parport_register_driver(&parport_i2c_driver); - return 0; -} - -#ifdef MODULE -MODULE_PARM(debug, "i"); - -void cleanup_module(void) -{ - struct parport_i2c_bus *b = bus_list; - while (b) - { - struct parport_i2c_bus *next = b->next; - i2c_unregister_bus(&b->i2c); - kfree(b); - b = next; - } - parport_unregister_driver(&parport_i2c_driver); -} -#endif diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c new file mode 100644 index 000000000..fcd105d35 --- /dev/null +++ b/drivers/char/i810-tco.c @@ -0,0 +1,326 @@ +/* + * i810-tco 0.02: TCO timer driver for i810 chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i810/i815 chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the 82801AA (82801AB) chip, + * see intel documentation from http://developer.intel.com, + * order number 290655-003 + * + * 20000710 Nils Faerber + * Initial Version 0.01 + * 20000728 Nils Faerber + * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i810-tco.h" + + +/* Just in case that the PCI vendor and device IDs are not yet defined */ +#ifndef PCI_DEVICE_ID_INTEL_82801AA_0 +#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 +#endif + +/* Default expire timeout */ +#define TIMER_MARGIN 50 /* steps of 0.6sec, 2 0x3f || tmrval < 0x03) + return -1; + + val = inb (TCO1_TMR); + val &= 0xc0; + val |= tmrval; + outb (val, TCO1_TMR); + val = inb (TCO1_TMR); + if ((val & 0x3f) != tmrval) + return -1; + + return 0; +} + +/* + * Reload (trigger) the timer + */ +static void tco_timer_reload (void) +{ + outb (0x01, TCO1_RLD); +} + +/* + * Read the current timer value + */ +static unsigned char tco_timer_read (void) +{ + return (inb (TCO1_RLD)); +} + + +/* + * Allow only one person to hold it open + */ + +static int i810tco_open (struct inode *inode, struct file *file) +{ + if (timer_alive) + return -EBUSY; + + /* + * Reload and activate timer + */ + tco_timer_reload (); + tco_timer_start (); + timer_alive = 1; + return 0; +} + +static int i810tco_release (struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + tco_timer_stop (); + timer_alive = 0; + return 0; +} + +static ssize_t i810tco_write (struct file *file, const char *data, + size_t len, loff_t * ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* + * Refresh the timer. + */ + if (len) { + tco_timer_reload (); + return 1; + } + return 0; +} + +static int i810tco_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + 0, + 0, + "i810 TCO timer" + }; + switch (cmd) { + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + if (copy_to_user + ((struct watchdog_info *) arg, &ident, sizeof (ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + return put_user (tco_timer_read (), + (unsigned int *) (int) arg); + case WDIOC_GETBOOTSTATUS: + return put_user (boot_status, (int *) arg); + case WDIOC_KEEPALIVE: + tco_timer_reload (); + return 0; + } +} + +static struct pci_dev *i810tco_pci; + +static unsigned char i810tco_getdevice (void) +{ + u8 val1, val2; + u16 badr; + /* + * Find the PCI device which has vendor id 0x8086 + * and device ID 0x2410 + */ + i810tco_pci = pci_find_device (PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801AA_0, NULL); + if (i810tco_pci) { + /* + * Find the ACPI base I/O address which is the base + * for the TCO registers (TCOBASE=ACPIBASE + 0x60) + * ACPIBASE is bits [15:7] from 0x40-0x43 + */ + pci_read_config_byte (i810tco_pci, 0x40, &val1); + pci_read_config_byte (i810tco_pci, 0x41, &val2); + badr = ((val2 << 1) | (val1 >> 7)) << 7; + ACPIBASE = badr; + /* Something's wrong here, ACPIBASE has to be set */ + if (badr == 0x0001 || badr == 0x0000) { + printk (KERN_ERR "i810tco init: failed to get TCOBASE address\n"); + return 0; + } + /* + * Check chipset's NO_REBOOT bit + */ + pci_read_config_byte (i810tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + val1 &= 0xfd; + pci_write_config_byte (i810tco_pci, 0xd4, val1); + pci_read_config_byte (i810tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag\n"); + return 0; /* Cannot reset NO_REBOOT bit */ + } + } + /* Set the TCO_EN bit in SMI_EN register */ + val1 = inb (SMI_EN + 1); + val1 &= 0xdf; + outb (val1, SMI_EN + 1); + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + boot_status = (int) inb (TCO2_STS); + outb (3, TCO2_STS); + return 1; + } + return 0; +} + +static struct file_operations i810tco_fops = { + owner: THIS_MODULE, + write: i810tco_write, + ioctl: i810tco_ioctl, + open: i810tco_open, + release: i810tco_release, +}; + +static struct miscdevice i810tco_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &i810tco_fops +}; + +static int __init watchdog_init (void) +{ + if (!i810tco_getdevice () || i810tco_pci == NULL) + return -ENODEV; + if (!request_region (TCOBASE, 0x10, "i810 TCO")) { + printk (KERN_ERR + "i810 TCO timer: I/O address 0x%04x already in use\n", + TCOBASE); + return -EIO; + } + if (misc_register (&i810tco_miscdev) != 0) { + release_region (TCOBASE, 0x10); + printk (KERN_ERR "i810 TCO timer: cannot register miscdev\n"); + return -EIO; + } + tco_timer_settimer ((unsigned char) i810_margin); + tco_timer_reload (); + + /* FIXME: no floating point math */ + printk (KERN_INFO + "i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n", + (int) (i810_margin * 0.6), TCOBASE); + return 0; +} + +static void __exit watchdog_cleanup (void) +{ + u8 val; + + /* Reset the timer before we leave */ + tco_timer_reload (); + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ + pci_read_config_byte (i810tco_pci, 0xd4, &val); + val |= 0x02; + pci_write_config_byte (i810tco_pci, 0xd4, val); + release_region (TCOBASE, 0x10); + misc_deregister (&i810tco_miscdev); +} + +module_init(watchdog_init); +module_exit(watchdog_cleanup); diff --git a/drivers/char/i810-tco.h b/drivers/char/i810-tco.h new file mode 100644 index 000000000..a078ae8f6 --- /dev/null +++ b/drivers/char/i810-tco.h @@ -0,0 +1,45 @@ +/* + * i810-tco 0.02: TCO timer driver for i810 chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i810 chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the 82801AA (82801AB) chip, + * see intel documentation from http://developer.intel.com, + * order number 290655-003 + * + * For history see i810-tco.c + */ + + +/* + * Some address definitions for the i810 TCO + */ + +#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ +#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ +#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ +#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ +#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ +#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ +#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ +#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ + +#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff --git a/drivers/char/ibmmpeg2.h b/drivers/char/ibmmpeg2.h deleted file mode 100644 index 68e10387c..000000000 --- a/drivers/char/ibmmpeg2.h +++ /dev/null @@ -1,94 +0,0 @@ -/* ibmmpeg2.h - IBM MPEGCD21 definitions */ - -#ifndef __IBM_MPEG2__ -#define __IBM_MPEG2__ - -/* Define all MPEG Decoder registers */ -/* Chip Control and Status */ -#define IBM_MP2_CHIP_CONTROL 0x200*2 -#define IBM_MP2_CHIP_MODE 0x201*2 -/* Timer Control and Status */ -#define IBM_MP2_SYNC_STC2 0x202*2 -#define IBM_MP2_SYNC_STC1 0x203*2 -#define IBM_MP2_SYNC_STC0 0x204*2 -#define IBM_MP2_SYNC_PTS2 0x205*2 -#define IBM_MP2_SYNC_PTS1 0x206*2 -#define IBM_MP2_SYNC_PTS0 0x207*2 -/* Video FIFO Control */ -#define IBM_MP2_FIFO 0x208*2 -#define IBM_MP2_FIFOW 0x100*2 -#define IBM_MP2_FIFO_STAT 0x209*2 -#define IBM_MP2_RB_THRESHOLD 0x22b*2 -/* Command buffer */ -#define IBM_MP2_COMMAND 0x20a*2 -#define IBM_MP2_CMD_DATA 0x20b*2 -#define IBM_MP2_CMD_STAT 0x20c*2 -#define IBM_MP2_CMD_ADDR 0x20d*2 -/* Internal Processor Control and Status */ -#define IBM_MP2_PROC_IADDR 0x20e*2 -#define IBM_MP2_PROC_IDATA 0x20f*2 -#define IBM_MP2_WR_PROT 0x235*2 -/* DRAM Access */ -#define IBM_MP2_DRAM_ADDR 0x210*2 -#define IBM_MP2_DRAM_DATA 0x212*2 -#define IBM_MP2_DRAM_CMD_STAT 0x213*2 -#define IBM_MP2_BLOCK_SIZE 0x23b*2 -#define IBM_MP2_SRC_ADDR 0x23c*2 -/* Onscreen Display */ -#define IBM_MP2_OSD_ADDR 0x214*2 -#define IBM_MP2_OSD_DATA 0x215*2 -#define IBM_MP2_OSD_MODE 0x217*2 -#define IBM_MP2_OSD_LINK_ADDR 0x229*2 -#define IBM_MP2_OSD_SIZE 0x22a*2 -/* Interrupt Control */ -#define IBM_MP2_HOST_INT 0x218*2 -#define IBM_MP2_MASK0 0x219*2 -#define IBM_MP2_HOST_INT1 0x23e*2 -#define IBM_MP2_MASK1 0x23f*2 -/* Audio Control */ -#define IBM_MP2_AUD_IADDR 0x21a*2 -#define IBM_MP2_AUD_IDATA 0x21b*2 -#define IBM_MP2_AUD_FIFO 0x21c*2 -#define IBM_MP2_AUD_FIFOW 0x101*2 -#define IBM_MP2_AUD_CTL 0x21d*2 -#define IBM_MP2_BEEP_CTL 0x21e*2 -#define IBM_MP2_FRNT_ATTEN 0x22d*2 -/* Display Control */ -#define IBM_MP2_DISP_MODE 0x220*2 -#define IBM_MP2_DISP_DLY 0x221*2 -#define IBM_MP2_VBI_CTL 0x222*2 -#define IBM_MP2_DISP_LBOR 0x223*2 -#define IBM_MP2_DISP_TBOR 0x224*2 -/* Polarity Control */ -#define IBM_MP2_INFC_CTL 0x22c*2 - -/* control commands */ -#define IBM_MP2_PLAY 0 -#define IBM_MP2_PAUSE 1 -#define IBM_MP2_SINGLE_FRAME 2 -#define IBM_MP2_FAST_FORWARD 3 -#define IBM_MP2_SLOW_MOTION 4 -#define IBM_MP2_IMED_NORM_PLAY 5 -#define IBM_MP2_RESET_WINDOW 6 -#define IBM_MP2_FREEZE_FRAME 7 -#define IBM_MP2_RESET_VID_RATE 8 -#define IBM_MP2_CONFIG_DECODER 9 -#define IBM_MP2_CHANNEL_SWITCH 10 -#define IBM_MP2_RESET_AUD_RATE 11 -#define IBM_MP2_PRE_OP_CHN_SW 12 -#define IBM_MP2_SET_STILL_MODE 14 - -/* Define Xilinx FPGA Internal Registers */ - -/* general control register 0 */ -#define XILINX_CTL0 0x600 -/* genlock delay resister 1 */ -#define XILINX_GLDELAY 0x602 -/* send 16 bits to CS3310 port */ -#define XILINX_CS3310 0x604 -/* send 16 bits to CS3310 and complete */ -#define XILINX_CS3310_CMPLT 0x60c -/* pulse width modulator control */ -#define XILINX_PWM 0x606 - -#endif diff --git a/drivers/char/joystick/Config.in b/drivers/char/joystick/Config.in index b020f1728..e99afa949 100644 --- a/drivers/char/joystick/Config.in +++ b/drivers/char/joystick/Config.in @@ -5,50 +5,50 @@ mainmenu_option next_comment comment 'Joysticks' -tristate 'Joystick support' CONFIG_JOYSTICK +dep_mbool 'Joystick support' CONFIG_JOYSTICK $CONFIG_INPUT if [ "$CONFIG_JOYSTICK" != "n" ]; then - define_tristate CONFIG_INPUT_JOYDEV $CONFIG_JOYSTICK - comment 'Game port support' - dep_tristate ' ns558 gameports' CONFIG_INPUT_NS558 $CONFIG_JOYSTICK - dep_tristate ' PDPI Lightning 4 gamecard' CONFIG_INPUT_LIGHTNING $CONFIG_JOYSTICK - dep_tristate ' Aureal Vortex and Trident 4DWave gameports' CONFIG_INPUT_PCIGAME $CONFIG_JOYSTICK + dep_tristate ' ns558 gameports' CONFIG_INPUT_NS558 $CONFIG_INPUT + dep_tristate ' PDPI Lightning 4 gamecard' CONFIG_INPUT_LIGHTNING $CONFIG_INPUT + dep_tristate ' Aureal Vortex and Trident 4DWave gameports' CONFIG_INPUT_PCIGAME $CONFIG_INPUT comment 'Gameport joysticks' - dep_tristate ' Classic PC analog joysticks and gamepads' CONFIG_INPUT_ANALOG $CONFIG_JOYSTICK - dep_tristate ' Assasin 3D and MadCatz Panther devices' CONFIG_INPUT_A3D $CONFIG_JOYSTICK - dep_tristate ' Logitech ADI digital joysticks and gamepads' CONFIG_INPUT_ADI $CONFIG_JOYSTICK - dep_tristate ' Creative Labs Blaster Cobra gamepad' CONFIG_INPUT_COBRA $CONFIG_JOYSTICK - dep_tristate ' Genius Flight2000 Digital joysticks and gamepads' CONFIG_INPUT_GF2K $CONFIG_JOYSTICK - dep_tristate ' Gravis GrIP joysticks and gamepads' CONFIG_INPUT_GRIP $CONFIG_JOYSTICK - dep_tristate ' InterAct digital joysticks and gamepads' CONFIG_INPUT_INTERACT $CONFIG_JOYSTICK - dep_tristate ' ThrustMaster DirectConnect joysticks and gamepads' CONFIG_INPUT_TMDC $CONFIG_JOYSTICK - dep_tristate ' Microsoft SideWinder digital joysticks and gamepads' CONFIG_INPUT_SIDEWINDER $CONFIG_JOYSTICK + dep_tristate ' Classic PC analog joysticks and gamepads' CONFIG_INPUT_ANALOG $CONFIG_INPUT + dep_tristate ' Assasin 3D and MadCatz Panther devices' CONFIG_INPUT_A3D $CONFIG_INPUT + dep_tristate ' Logitech ADI digital joysticks and gamepads' CONFIG_INPUT_ADI $CONFIG_INPUT + dep_tristate ' Creative Labs Blaster Cobra gamepad' CONFIG_INPUT_COBRA $CONFIG_INPUT + dep_tristate ' Genius Flight2000 Digital joysticks and gamepads' CONFIG_INPUT_GF2K $CONFIG_INPUT + dep_tristate ' Gravis GrIP joysticks and gamepads' CONFIG_INPUT_GRIP $CONFIG_INPUT + dep_tristate ' InterAct digital joysticks and gamepads' CONFIG_INPUT_INTERACT $CONFIG_INPUT + dep_tristate ' ThrustMaster DirectConnect joysticks and gamepads' CONFIG_INPUT_TMDC $CONFIG_INPUT + dep_tristate ' Microsoft SideWinder digital joysticks and gamepads' CONFIG_INPUT_SIDEWINDER $CONFIG_INPUT comment 'Serial port support' - dep_tristate ' Serial port input line discipline' CONFIG_INPUT_SERPORT $CONFIG_JOYSTICK + dep_tristate ' Serial port input line discipline' CONFIG_INPUT_SERPORT $CONFIG_INPUT comment 'Serial port joysticks' - dep_tristate ' Logitech WingMan Warrior joystick' CONFIG_INPUT_WARRIOR $CONFIG_JOYSTICK - dep_tristate ' LogiCad3d Magellan/SpaceMouse 6dof controller' CONFIG_INPUT_MAGELLAN $CONFIG_JOYSTICK - dep_tristate ' SpaceTec SpaceOrb/Avenger 6dof controller' CONFIG_INPUT_SPACEORB $CONFIG_JOYSTICK - dep_tristate ' SpaceTec SpaceBall 4000 FLX 6dof controller' CONFIG_INPUT_SPACEBALL $CONFIG_JOYSTICK - dep_tristate ' I-Force joysticks/wheels' CONFIG_INPUT_IFORCE_232 $CONFIG_JOYSTICK - if [ "$CONFIG_INPUT_IFORCE_232" != "n" ]; then - define_tristate CONFIG_INPUT_IFORCE $CONFIG_INPUT_IFORCE_232 - fi + dep_tristate ' Logitech WingMan Warrior joystick' CONFIG_INPUT_WARRIOR $CONFIG_INPUT + dep_tristate ' LogiCad3d Magellan/SpaceMouse 6dof controller' CONFIG_INPUT_MAGELLAN $CONFIG_INPUT + dep_tristate ' SpaceTec SpaceOrb/Avenger 6dof controller' CONFIG_INPUT_SPACEORB $CONFIG_INPUT + dep_tristate ' SpaceTec SpaceBall 4000 FLX 6dof controller' CONFIG_INPUT_SPACEBALL $CONFIG_INPUT + dep_tristate ' I-Force/Serial controllers' CONFIG_INPUT_IFORCE_232 $CONFIG_INPUT + dep_tristate ' I-Force/USB controllers' CONFIG_INPUT_IFORCE_USB $CONFIG_INPUT $CONFIG_USB - if [ "$CONFIG_PARPORT" != "n" ]; then comment 'Parallel port joysticks' - dep_tristate ' Multisystem, Sega Genesis, Saturn joysticks and gamepads' CONFIG_INPUT_DB9 $CONFIG_JOYSTICK - dep_tristate ' Multisystem, NES, SNES, N64, PSX joysticks and gamepads' CONFIG_INPUT_GAMECON $CONFIG_JOYSTICK - dep_tristate ' Multisystem joysticks via TurboGraFX device' CONFIG_INPUT_TURBOGRAFX $CONFIG_JOYSTICK + if [ "$CONFIG_PARPORT" != "n" ]; then + dep_tristate ' Multisystem, Sega Genesis, Saturn joysticks and gamepads' CONFIG_INPUT_DB9 $CONFIG_INPUT $CONFIG_PARPORT + dep_tristate ' Multisystem, NES, SNES, N64, PSX joysticks and gamepads' CONFIG_INPUT_GAMECON $CONFIG_INPUT $CONFIG_PARPORT + dep_tristate ' Multisystem joysticks via TurboGraFX device' CONFIG_INPUT_TURBOGRAFX $CONFIG_INPUT $CONFIG_PARPORT + else + comment ' Parport support is needed for parallel port joysticks' fi if [ "$CONFIG_AMIGA" = "y" ]; then comment 'System joysticks' - dep_tristate ' Amiga joysticks' CONFIG_INPUT_AMIJOY $CONFIG_JOYSTICK + dep_tristate ' Amiga joysticks' CONFIG_INPUT_AMIJOY $CONFIG_INPUT fi +else + comment 'Input core support is needed for joysticks' fi - + endmenu diff --git a/drivers/char/joystick/Makefile b/drivers/char/joystick/Makefile index ae6a42cb8..e8eadc870 100644 --- a/drivers/char/joystick/Makefile +++ b/drivers/char/joystick/Makefile @@ -19,6 +19,19 @@ O_OBJS := export-objs := serio.o gameport.o +# I-Force may need both USB and RS-232 + +ifeq ($(CONFIG_INPUT_IFORCE_232),m) + ifeq ($(CONFIG_INPUT_IFORCE_USB),y) + CONFIG_INPUT_IFORCE_USB := m + endif +endif +ifeq ($(CONFIG_INPUT_IFORCE_USB),m) + ifeq ($(CONFIG_INPUT_IFORCE_232),y) + CONFIG_INPUT_IFORCE_232 := m + endif +endif + # Object file lists. obj-y := @@ -38,7 +51,8 @@ obj-$(CONFIG_INPUT_WARRIOR) += warrior.o serio.o obj-$(CONFIG_INPUT_MAGELLAN) += magellan.o serio.o obj-$(CONFIG_INPUT_SPACEORB) += spaceorb.o serio.o obj-$(CONFIG_INPUT_SPACEBALL) += spaceball.o serio.o -obj-$(CONFIG_INPUT_IFORCE_232) += serio.o +obj-$(CONFIG_INPUT_IFORCE_232) += iforce.o serio.o +obj-$(CONFIG_INPUT_IFORCE_USB) += iforce.o obj-$(CONFIG_INPUT_ANALOG) += analog.o gameport.o obj-$(CONFIG_INPUT_A3D) += a3d.o gameport.o diff --git a/drivers/char/joystick/amijoy.c b/drivers/char/joystick/amijoy.c index f17aeda24..452d173d7 100644 --- a/drivers/char/joystick/amijoy.c +++ b/drivers/char/joystick/amijoy.c @@ -1,5 +1,5 @@ /* - * $Id: amijoy.c,v 1.4 2000/05/29 10:39:54 vojtech Exp $ + * $Id: amijoy.c,v 1.5 2000/07/21 22:52:24 vojtech Exp $ * * Copyright (c) 1998-2000 Vojtech Pavlik * @@ -77,7 +77,7 @@ static int amijoy_open(struct input_dev *dev) return 0; if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", NULL)) { - amijoy_used--; + (*used)--; printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", amijoy_irq); return -EBUSY; } @@ -89,7 +89,7 @@ static void amijoy_close(struct input_dev *dev) { int *used = dev->private; - if (!--(*port->used)) + if (!--(*used)) free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); } @@ -112,13 +112,21 @@ static int __init amijoy_init(void) for (i = 0; i < 2; i++) if (amijoy[i]) { + if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2, + amijoy [Denise]")) { + if (i == 1 && amijoy[0]) { + input_unregister_device(amijoy_dev); + release_mem_region(CUSTOM_PHYSADDR+10, 2); + } + return -EBUSY; + } amijoy_dev[i].open = amijoy_open; amijoy_dev[i].close = amijoy_close; amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y); amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - for (j = 0; j < 2; j++) + for (j = 0; j < 2; j++) { amijoy_dev[i].absmin[ABS_X + j] = -1; amijoy_dev[i].absmax[ABS_X + j] = 1; } @@ -134,6 +142,7 @@ static int __init amijoy_init(void) input_register_device(amijoy_dev + i); printk(KERN_INFO "input%d: %s at joy%ddat\n", amijoy_dev[i].number, amijoy_name, i); } + return 0; } static void _exit amijoy_exit(void) @@ -141,8 +150,10 @@ static void _exit amijoy_exit(void) int i; for (i = 0; i < 2; i++) - if (amijoy[i]) + if (amijoy[i]) { input_unregister_device(amijoy_dev + i); + release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2); + } } module_init(amijoy_init); diff --git a/drivers/char/joystick/db9.c b/drivers/char/joystick/db9.c index f9edd0755..4277e7f3d 100644 --- a/drivers/char/joystick/db9.c +++ b/drivers/char/joystick/db9.c @@ -1,5 +1,5 @@ /* - * $Id: db9.c,v 1.5 2000/05/29 20:39:38 vojtech Exp $ + * $Id: db9.c,v 1.6 2000/06/25 10:57:50 vojtech Exp $ * * Copyright (c) 1999 Vojtech Pavlik * @@ -95,7 +95,7 @@ static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START }; static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 8, 1, 1, 7 }; -static short *db9_btn[DB9_MAX_PAD] = { db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn, +static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn, db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn }; static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad", NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick", @@ -113,36 +113,36 @@ static void db9_timer(unsigned long private) data = parport_read_data(port) >> 3; - input_report_abs(dev + 1, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev + 1, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev + 1, BTN_TRIGGER, ~data&DB9_FIRE1); + input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1); case DB9_MULTI_0802: data = parport_read_status(port) >> 3; - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev, BTN_TRIGGER, data&DB9_FIRE1); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1); break; case DB9_MULTI_STICK: data = parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev, BTN_TRIGGER, ~data&DB9_FIRE1); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1); break; case DB9_MULTI2_STICK: data = parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev, BTN_TRIGGER, ~data&DB9_FIRE1); - input_report_key(dev, BTN_THUMB, ~data&DB9_FIRE2); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1); + input_report_key(dev, BTN_THUMB, ~data & DB9_FIRE2); break; case DB9_GENESIS_PAD: @@ -150,16 +150,16 @@ static void db9_timer(unsigned long private) parport_write_control(port, DB9_NOSELECT); data = parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev, BTN_B, ~data&DB9_FIRE1); - input_report_key(dev, BTN_C, ~data&DB9_FIRE2); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev, BTN_B, ~data & DB9_FIRE1); + input_report_key(dev, BTN_C, ~data & DB9_FIRE2); parport_write_control(port, DB9_NORMAL); data=parport_read_data(port); - input_report_key(dev, BTN_A, ~data&DB9_FIRE1); - input_report_key(dev, BTN_START, ~data&DB9_FIRE2); + input_report_key(dev, BTN_A, ~data & DB9_FIRE1); + input_report_key(dev, BTN_START, ~data & DB9_FIRE2); break; case DB9_GENESIS5_PAD: @@ -167,18 +167,18 @@ static void db9_timer(unsigned long private) parport_write_control(port, DB9_NOSELECT); data=parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev, BTN_B, ~data&DB9_FIRE1); - input_report_key(dev, BTN_C, ~data&DB9_FIRE2); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev, BTN_B, ~data & DB9_FIRE1); + input_report_key(dev, BTN_C, ~data & DB9_FIRE2); parport_write_control(port, DB9_NORMAL); data=parport_read_data(port); - input_report_key(dev, BTN_A, ~data&DB9_FIRE1); - input_report_key(dev, BTN_X, ~data&DB9_FIRE2); - input_report_key(dev, BTN_Y, ~data&DB9_LEFT); - input_report_key(dev, BTN_START, ~data&DB9_RIGHT); + input_report_key(dev, BTN_A, ~data & DB9_FIRE1); + input_report_key(dev, BTN_X, ~data & DB9_FIRE2); + input_report_key(dev, BTN_Y, ~data & DB9_LEFT); + input_report_key(dev, BTN_START, ~data & DB9_RIGHT); break; case DB9_GENESIS6_PAD: @@ -187,17 +187,17 @@ static void db9_timer(unsigned long private) udelay(DB9_GENESIS6_DELAY); data=parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); - input_report_key(dev, BTN_B, ~data&DB9_FIRE1); - input_report_key(dev, BTN_C, ~data&DB9_FIRE2); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); + input_report_key(dev, BTN_B, ~data & DB9_FIRE1); + input_report_key(dev, BTN_C, ~data & DB9_FIRE2); parport_write_control(port, DB9_NORMAL); udelay(DB9_GENESIS6_DELAY); data=parport_read_data(port); - input_report_key(dev, BTN_A, ~data&DB9_FIRE1); - input_report_key(dev, BTN_X, ~data&DB9_FIRE2); + input_report_key(dev, BTN_A, ~data & DB9_FIRE1); + input_report_key(dev, BTN_X, ~data & DB9_FIRE2); parport_write_control(port, DB9_NOSELECT); /* 2 */ udelay(DB9_GENESIS6_DELAY); @@ -207,10 +207,10 @@ static void db9_timer(unsigned long private) udelay(DB9_GENESIS6_DELAY); data=parport_read_data(port); - input_report_key(dev, BTN_Y, ~data&DB9_LEFT); - input_report_key(dev, BTN_Z, ~data&DB9_DOWN); - input_report_key(dev, BTN_MODE, ~data&DB9_UP); - input_report_key(dev, BTN_START, ~data&DB9_RIGHT); + input_report_key(dev, BTN_Y, ~data & DB9_LEFT); + input_report_key(dev, BTN_Z, ~data & DB9_DOWN); + input_report_key(dev, BTN_MODE, ~data & DB9_UP); + input_report_key(dev, BTN_START, ~data & DB9_RIGHT); parport_write_control(port, DB9_NORMAL); udelay(DB9_GENESIS6_DELAY); @@ -224,32 +224,32 @@ static void db9_timer(unsigned long private) parport_write_control(port, DB9_SATURN0); data = parport_read_data(port); - input_report_key(dev, BTN_Y, ~data&DB9_LEFT); - input_report_key(dev, BTN_Z, ~data&DB9_DOWN); - input_report_key(dev, BTN_TL,~data&DB9_UP); - input_report_key(dev, BTN_TR,~data&DB9_RIGHT); + input_report_key(dev, BTN_Y, ~data & DB9_LEFT); + input_report_key(dev, BTN_Z, ~data & DB9_DOWN); + input_report_key(dev, BTN_TL, ~data & DB9_UP); + input_report_key(dev, BTN_TR, ~data & DB9_RIGHT); parport_write_control(port, DB9_SATURN2); data = parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); parport_write_control(port, DB9_NORMAL); data = parport_read_data(port); - input_report_key(dev, BTN_A, ~data&DB9_LEFT); - input_report_key(dev, BTN_B, ~data&DB9_UP); - input_report_key(dev, BTN_C, ~data&DB9_DOWN); - input_report_key(dev, BTN_X, ~data&DB9_RIGHT); + input_report_key(dev, BTN_A, ~data & DB9_LEFT); + input_report_key(dev, BTN_B, ~data & DB9_UP); + input_report_key(dev, BTN_C, ~data & DB9_DOWN); + input_report_key(dev, BTN_X, ~data & DB9_RIGHT); break; case DB9_CD32_PAD: data=parport_read_data(port); - input_report_abs(dev, ABS_X, (data&DB9_DOWN ?0:1) - (data&DB9_UP ?0:1)); - input_report_abs(dev, ABS_Y, (data&DB9_RIGHT?0:1) - (data&DB9_LEFT?0:1)); + input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); + input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); parport_write_control(port, 0x0a); @@ -257,7 +257,7 @@ static void db9_timer(unsigned long private) data = parport_read_data(port); parport_write_control(port, 0x02); parport_write_control(port, 0x0a); - input_report_key(dev, db9_cd32_btn[i], ~data&DB9_FIRE2); + input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2); } parport_write_control(port, 0x00); diff --git a/drivers/char/joystick/gamecon.c b/drivers/char/joystick/gamecon.c index a92ef58a9..c1d37248f 100644 --- a/drivers/char/joystick/gamecon.c +++ b/drivers/char/joystick/gamecon.c @@ -1,5 +1,5 @@ /* - * $Id: gamecon.c,v 1.4 2000/05/29 21:08:45 vojtech Exp $ + * $Id: gamecon.c,v 1.5 2000/06/25 09:56:58 vojtech Exp $ * * Copyright (c) 1999-2000 Vojtech Pavlik * @@ -157,7 +157,7 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; -static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_START, BTN_SELECT, BTN_X, BTN_Y, BTN_TL, BTN_TR }; +static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR }; /* * gc_nes_read_packet() reads a NES/SNES packet. @@ -515,7 +515,7 @@ static struct gc __init *gc_probe(int *config) case GC_N64: for (j = 0; j < 10; j++) - set_bit(gc_n64_btn[j], gc->dev[j].keybit); + set_bit(gc_n64_btn[j], gc->dev[i].keybit); for (j = 0; j < 2; j++) { set_bit(ABS_X + j, gc->dev[i].absbit); @@ -530,18 +530,15 @@ static struct gc __init *gc_probe(int *config) break; case GC_SNES: - for (j = 0; j < 8; j++) - set_bit(gc_snes_btn[j], gc->dev[j].keybit); - break; - + for (j = 4; j < 8; j++) + set_bit(gc_snes_btn[j], gc->dev[i].keybit); case GC_NES: for (j = 0; j < 4; j++) - set_bit(gc_snes_btn[j], gc->dev[j].keybit); + set_bit(gc_snes_btn[j], gc->dev[i].keybit); break; case GC_MULTI2: set_bit(BTN_THUMB, gc->dev[i].keybit); - case GC_MULTI: set_bit(BTN_TRIGGER, gc->dev[i].keybit); break; @@ -656,12 +653,13 @@ void __exit gc_exit(void) { int i, j; - for (i = 0; i < 3; i++) { - for (j = 0; j < 5; j++) - if (gc_base[i]->pads[0] & gc_status_bit[j]) - input_unregister_device(gc_base[i]->dev + j); - parport_unregister_device(gc_base[i]->pd); - } + for (i = 0; i < 3; i++) + if (gc_base[i]) { + for (j = 0; j < 5; j++) + if (gc_base[i]->pads[0] & gc_status_bit[j]) + input_unregister_device(gc_base[i]->dev + j); + parport_unregister_device(gc_base[i]->pd); + } } module_init(gc_init); diff --git a/drivers/char/joystick/iforce.c b/drivers/char/joystick/iforce.c new file mode 100644 index 000000000..acb0bfe5b --- /dev/null +++ b/drivers/char/joystick/iforce.c @@ -0,0 +1,342 @@ +/* + * $Id: iforce.c,v 1.7 2000/06/04 14:03:36 vojtech Exp $ + * + * Copyright (c) 2000 Vojtech Pavlik + * + * USB/RS232 I-Force joysticks and wheels. + * + * Sponsored by SuSE + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver"); + +#define USB_VENDOR_ID_LOGITECH 0x046d +#define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281 + +#define IFORCE_MAX_LENGTH 16 + +#if defined(CONFIG_INPUT_IFORCE_232) || defined(CONFIG_INPUT_IFORCE_232_MODULE) +#define IFORCE_232 +#endif +#if defined(CONFIG_INPUT_IFORCE_USB) || defined(CONFIG_INPUT_IFORCE_USB_MODULE) +#define IFORCE_USB +#endif + +struct iforce { + signed char data[IFORCE_MAX_LENGTH]; + struct input_dev dev; + struct urb irq; + int open; + int idx, pkt, len, id; + unsigned char csum; +}; + +static struct { + __s32 x; + __s32 y; +} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; + +static char *iforce_name = "I-Force joystick/wheel"; + +static void iforce_process_packet(struct input_dev *dev, unsigned char id, int idx, unsigned char *data) +{ + switch (id) { + + case 1: /* joystick position data */ + case 3: /* wheel position data */ + + if (id == 1) { + input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0])); + input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2])); + input_report_abs(dev, ABS_THROTTLE, 255 - data[4]); + } else { + input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0])); + input_report_abs(dev, ABS_GAS, 255 - data[2]); + input_report_abs(dev, ABS_BRAKE, 255 - data[3]); + } + + input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x); + input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y); + + input_report_key(dev, BTN_TRIGGER, data[5] & 0x01); + input_report_key(dev, BTN_TOP, data[5] & 0x02); + input_report_key(dev, BTN_THUMB, data[5] & 0x04); + input_report_key(dev, BTN_TOP2, data[5] & 0x08); + input_report_key(dev, BTN_BASE, data[5] & 0x10); + input_report_key(dev, BTN_BASE2, data[5] & 0x20); + input_report_key(dev, BTN_BASE3, data[5] & 0x40); + input_report_key(dev, BTN_BASE4, data[5] & 0x80); + input_report_key(dev, BTN_BASE5, data[6] & 0x01); + input_report_key(dev, BTN_A, data[6] & 0x02); + input_report_key(dev, BTN_B, data[6] & 0x04); + input_report_key(dev, BTN_C, data[6] & 0x08); + break; + + case 2: /* force feedback effect status */ + break; + } +} + +#ifdef IFORCE_USB + +static int iforce_open(struct input_dev *dev) +{ + struct iforce *iforce = dev->private; + + if (dev->idbus == BUS_USB && !iforce->open++) + if (usb_submit_urb(&iforce->irq)) + return -EIO; + + return 0; +} + +static void iforce_close(struct input_dev *dev) +{ + struct iforce *iforce = dev->private; + + if (dev->idbus == BUS_USB && !--iforce->open) + usb_unlink_urb(&iforce->irq); +} + +#endif + +static void iforce_input_setup(struct iforce *iforce) +{ + int i; + + iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + iforce->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_TOP) | BIT(BTN_THUMB) | BIT(BTN_TOP2) | + BIT(BTN_BASE) | BIT(BTN_BASE2) | BIT(BTN_BASE3) | BIT(BTN_BASE4) | BIT(BTN_BASE5); + iforce->dev.keybit[LONG(BTN_GAMEPAD)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C); + iforce->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) + | BIT(ABS_WHEEL) | BIT(ABS_GAS) | BIT(ABS_BRAKE); + + for (i = ABS_X; i <= ABS_Y; i++) { + iforce->dev.absmax[i] = 1920; + iforce->dev.absmin[i] = -1920; + iforce->dev.absflat[i] = 128; + iforce->dev.absfuzz[i] = 16; + } + + for (i = ABS_THROTTLE; i <= ABS_RUDDER; i++) { + iforce->dev.absmax[i] = 255; + iforce->dev.absmin[i] = 0; + } + + for (i = ABS_HAT0X; i <= ABS_HAT0Y; i++) { + iforce->dev.absmax[i] = 1; + iforce->dev.absmin[i] = -1; + } + + iforce->dev.private = iforce; + +#ifdef IFORCE_USB + iforce->dev.open = iforce_open; + iforce->dev.close = iforce_close; +#endif + + input_register_device(&iforce->dev); +} + +#ifdef IFORCE_USB + +static void iforce_usb_irq(struct urb *urb) +{ + struct iforce *iforce = urb->context; + if (urb->status) return; + iforce_process_packet(&iforce->dev, iforce->data[0], 8, iforce->data + 1); +} + +static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_endpoint_descriptor *endpoint; + struct iforce *iforce; + + if (dev->descriptor.idVendor != USB_VENDOR_ID_LOGITECH || + dev->descriptor.idProduct != USB_DEVICE_ID_LOGITECH_WMFORCE) + return NULL; + + endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; + + if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return NULL; + memset(iforce, 0, sizeof(struct iforce)); + + iforce->dev.name = iforce_name; + iforce->dev.idbus = BUS_USB; + iforce->dev.idvendor = dev->descriptor.idVendor; + iforce->dev.idproduct = dev->descriptor.idProduct; + iforce->dev.idversion = dev->descriptor.bcdDevice; + + FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), + iforce->data, 8, iforce_usb_irq, iforce, endpoint->bInterval); + + iforce_input_setup(iforce); + + printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n", + iforce->dev.number, iforce_name, dev->bus->busnum, dev->devnum, ifnum); + + return iforce; +} + +static void iforce_usb_disconnect(struct usb_device *dev, void *ptr) +{ + struct iforce *iforce = ptr; + usb_unlink_urb(&iforce->irq); + input_unregister_device(&iforce->dev); + kfree(iforce); +} + +static struct usb_driver iforce_usb_driver = { + name: "iforce", + probe: iforce_usb_probe, + disconnect: iforce_usb_disconnect, +}; + +#endif + +#ifdef IFORCE_232 + +static void iforce_serio_irq(struct serio *serio, unsigned char data, unsigned int flags) +{ + struct iforce* iforce = serio->private; + + if (!iforce->pkt) { + if (data != 0x2b) { + return; + } + iforce->pkt = 1; + return; + } + + if (!iforce->id) { + if (data > 3) { + iforce->pkt = 0; + return; + } + iforce->id = data; + return; + } + + if (!iforce->len) { + if (data > IFORCE_MAX_LENGTH) { + iforce->pkt = 0; + iforce->id = 0; + return; + } + iforce->len = data; + return; + } + + if (iforce->idx < iforce->len) { + iforce->csum += iforce->data[iforce->idx++] = data; + return; + } + + if (iforce->idx == iforce->len) { + iforce_process_packet(&iforce->dev, iforce->id, iforce->idx, iforce->data); + iforce->pkt = 0; + iforce->id = 0; + iforce->len = 0; + iforce->idx = 0; + iforce->csum = 0; + } +} + +static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev) +{ + struct iforce *iforce; + + if (serio->type != (SERIO_RS232 | SERIO_IFORCE)) + return; + + if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return; + memset(iforce, 0, sizeof(struct iforce)); + + iforce->dev.name = iforce_name; + iforce->dev.idbus = BUS_RS232; + iforce->dev.idvendor = SERIO_IFORCE; + iforce->dev.idproduct = 0x0001; + iforce->dev.idversion = 0x0100; + + serio->private = iforce; + + if (serio_open(serio, dev)) { + kfree(iforce); + return; + } + + iforce_input_setup(iforce); + + printk(KERN_INFO "input%d: %s on serio%d\n", + iforce->dev.number, iforce_name, serio->number); +} + +static void iforce_serio_disconnect(struct serio *serio) +{ + struct iforce* iforce = serio->private; + input_unregister_device(&iforce->dev); + serio_close(serio); + kfree(iforce); +} + +static struct serio_dev iforce_serio_dev = { + interrupt: iforce_serio_irq, + connect: iforce_serio_connect, + disconnect: iforce_serio_disconnect, +}; + +#endif + +static int __init iforce_init(void) +{ +#ifdef IFORCE_USB + usb_register(&iforce_usb_driver); +#endif +#ifdef IFORCE_232 + serio_register_device(&iforce_serio_dev); +#endif + return 0; +} + +static void __exit iforce_exit(void) +{ +#ifdef IFORCE_USB + usb_deregister(&iforce_usb_driver); +#endif +#ifdef IFORCE_232 + serio_unregister_device(&iforce_serio_dev); +#endif +} + +module_init(iforce_init); +module_exit(iforce_exit); diff --git a/drivers/char/joystick/ns558.c b/drivers/char/joystick/ns558.c index f34a18640..9ea833113 100644 --- a/drivers/char/joystick/ns558.c +++ b/drivers/char/joystick/ns558.c @@ -1,5 +1,5 @@ /* - * $Id: ns558.c,v 1.11 2000/06/20 23:35:03 vojtech Exp $ + * $Id: ns558.c,v 1.16 2000/08/17 20:03:56 vojtech Exp $ * * Copyright (c) 1999-2000 Vojtech Pavlik * Copyright (c) 1999 Brian Gerst @@ -138,7 +138,7 @@ static struct ns558* ns558_isa_probe(int io, struct ns558 *next) port->next = next; port->type = NS558_ISA; - port->gameport.io = io; + port->gameport.io = io & (-1 << i); port->gameport.size = (1 << i); request_region(port->gameport.io, port->gameport.size, "ns558-isa"); @@ -182,6 +182,7 @@ static int __devinit ns558_pci_probe(struct pci_dev *pdev, const struct pci_devi if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) { printk(KERN_ERR "Memory allocation failed.\n"); + release_region(ioport, iolen); return -ENOMEM; } memset(port, 0, sizeof(struct ns558)); @@ -208,6 +209,7 @@ static void __devexit ns558_pci_remove(struct pci_dev *pdev) { struct ns558 *port = (struct ns558 *)pdev->driver_data; release_region(port->gameport.io, port->gameport.size); + kfree(port); } static struct pci_driver ns558_pci_driver = { @@ -216,10 +218,16 @@ static struct pci_driver ns558_pci_driver = { probe: ns558_pci_probe, remove: ns558_pci_remove, }; +#else +static struct pci_driver ns558_pci_driver; #endif /* CONFIG_PCI */ -#ifdef CONFIG_ISAPNP +#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) +#define NSS558_ISAPNP +#endif + +#ifdef NSS558_ISAPNP /* * PnP IDs: * @@ -297,7 +305,7 @@ deactivate: int __init ns558_init(void) { int i = 0; -#ifdef CONFIG_ISAPNP +#ifdef NSS558_ISAPNP struct pci_dev *dev = NULL; struct pnp_devid *devid; #endif @@ -309,18 +317,11 @@ int __init ns558_init(void) while (ns558_isa_portlist[i]) ns558 = ns558_isa_probe(ns558_isa_portlist[i++], ns558); -/* - * Probe for PCI ports. - */ -#ifdef CONFIG_PCI - pci_register_driver(&ns558_pci_driver); -#endif - /* * Probe for PnP ports. */ -#ifdef CONFIG_ISAPNP +#ifdef NSS558_ISAPNP for (devid = pnp_devids; devid->vendor; devid++) { while ((dev = isapnp_find_dev(NULL, devid->vendor, devid->device, dev))) { ns558 = ns558_pnp_probe(dev, ns558); @@ -328,7 +329,14 @@ int __init ns558_init(void) } #endif - return -!ns558; +/* + * Probe for PCI ports. + */ + + if (!ns558 && pci_module_init(&ns558_pci_driver)) + return -ENODEV; + + return 0; } void __exit ns558_exit(void) @@ -339,7 +347,7 @@ void __exit ns558_exit(void) gameport_unregister_port(&port->gameport); switch (port->type) { -#ifdef CONFIG_ISAPNP +#ifdef NSS558_ISAPNP case NS558_PNP: if (port->dev->deactivate) port->dev->deactivate(port->dev); @@ -357,9 +365,7 @@ void __exit ns558_exit(void) port = port->next; } -#ifdef CONFIG_PCI pci_unregister_driver(&ns558_pci_driver); -#endif } module_init(ns558_init); diff --git a/drivers/char/joystick/sidewinder.c b/drivers/char/joystick/sidewinder.c index 861966b4e..85be9f8b1 100644 --- a/drivers/char/joystick/sidewinder.c +++ b/drivers/char/joystick/sidewinder.c @@ -1,5 +1,5 @@ /* - * $Id: sidewinder.c,v 1.14 2000/05/29 11:27:55 vojtech Exp $ + * $Id: sidewinder.c,v 1.16 2000/07/14 09:02:41 vojtech Exp $ * * Copyright (c) 1998-2000 Vojtech Pavlik * @@ -330,8 +330,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw) if (sw_parity(GB(i*15,15))) return -1; - input_report_key(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1)); - input_report_key(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1)); + input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1)); + input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1)); for (j = 0; j < 10; j++) input_report_key(dev, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1)); diff --git a/drivers/char/joystick/spaceball.c b/drivers/char/joystick/spaceball.c index 4f5059330..8e2936f73 100644 --- a/drivers/char/joystick/spaceball.c +++ b/drivers/char/joystick/spaceball.c @@ -1,5 +1,5 @@ /* - * $Id: spaceball.c,v 1.6 2000/05/29 11:19:51 vojtech Exp $ + * $Id: spaceball.c,v 1.7 2000/06/24 11:55:40 vojtech Exp $ * * Copyright (c) 1999-2000 Vojtech Pavlik * @@ -46,7 +46,7 @@ */ #define JS_SBALL_MAX_LENGTH 128 -static int spaceball_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; +static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY }; static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX"; /* @@ -70,10 +70,12 @@ static void spaceball_process_packet(struct spaceball* spaceball) { struct input_dev *dev = &spaceball->dev; unsigned char *data = spaceball->data; - int i, d; + int i; if (spaceball->idx < 2) return; + printk("%c %d\n", spaceball->data[0], spaceball->idx); + switch (spaceball->data[0]) { case '@': /* Reset packet */ @@ -84,17 +86,17 @@ static void spaceball_process_packet(struct spaceball* spaceball) break; case 'D': /* Ball data */ - if (spaceball->idx != 16) return; + if (spaceball->idx != 15) return; for (i = 0; i < 6; i++) { - d = ((data[2 * i + 3] << 8) | data[2 * i + 2]); - input_report_abs(dev, spaceball_axes[i], d - ((d & 0x8000) ? 0x10000 : 0)); + input_report_abs(dev, spaceball_axes[i], + (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2])); } break; case '.': /* Button data, part2 */ - if (spaceball->idx != 4) return; - input_report_key(dev, BTN_LEFT, data[2] & 1); - input_report_key(dev, BTN_RIGHT, data[2] & 2); + if (spaceball->idx != 3) return; + input_report_key(dev, BTN_0, data[2] & 1); + input_report_key(dev, BTN_1, data[2] & 2); break; case '?': /* Error packet */ @@ -118,22 +120,27 @@ static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigne switch (data) { case 0xd: - if (spaceball->idx) - spaceball_process_packet(spaceball); + spaceball_process_packet(spaceball); spaceball->idx = 0; spaceball->escape = 0; return; + case '^': + if (!spaceball->escape) { + spaceball->escape ^= 1; + return; + } + spaceball->escape = 0; case 'M': case 'Q': case 'S': - if (spaceball->escape) + if (spaceball->escape) { + spaceball->escape = 0; data = 0xd; - case '^': - spaceball->escape ^= 1; + } default: if (spaceball->escape) { - printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x\n", data); spaceball->escape = 0; + printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data); } if (spaceball->idx < JS_SBALL_MAX_LENGTH) spaceball->data[spaceball->idx++] = data; @@ -172,15 +179,15 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev) memset(spaceball, 0, sizeof(struct spaceball)); spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - spaceball->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); + spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1); for (i = 0; i < 6; i++) { t = spaceball_axes[i]; set_bit(t, spaceball->dev.absbit); - spaceball->dev.absmin[t] = i < 3 ? -10000 : -2000; - spaceball->dev.absmax[t] = i < 3 ? 10000 : 2000; - spaceball->dev.absflat[t] = i < 3 ? 50 : 10; - spaceball->dev.absfuzz[t] = i < 3 ? 12 : 2; + spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600; + spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600; + spaceball->dev.absflat[t] = i < 3 ? 40 : 8; + spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2; } spaceball->serio = serio; diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c deleted file mode 100644 index 2d2b1e89c..000000000 --- a/drivers/char/msp3400.c +++ /dev/null @@ -1,1454 +0,0 @@ -/* - * programming the msp34* sound processor family - * - * (c) 1997-2000 Gerd Knorr - * - * what works and what doesn't: - * - * AM-Mono - * Support for Hauppauge cards added (decoding handled by tuner) added by - * Frederic Crozat - * - * 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 - * - * - * TODO: - * - better SAT support - * - * - * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch) - * using soundcore instead of OSS - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SMP -#include -#include -#endif -/* kernel_thread */ -#define __KERNEL_SYSCALLS__ -#include - -#include "audiochip.h" - -/* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {0x40,0x40,I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -/* insmod parameters */ -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 simple = -1; /* use short programming (>= msp3410 only) */ -static int dolby = 0; - -struct msp3400c { - int simple; - int nicam; - int mode; - int norm; - int stereo; - int nicam_on; - int main, second; /* sound carrier */ - - int left, right; /* volume */ - int bass, treble; - - /* thread */ - struct task_struct *thread; - wait_queue_head_t wq; - - struct semaphore *notify; - int active,restart,rmmod; - - int watch_stereo; - struct timer_list wake_stereo; -}; - -#define MSP3400_MAX 4 -static struct i2c_client *msps[MSP3400_MAX]; - -#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */ - -/* ---------------------------------------------------------------------- */ - -#define dprintk if (debug) printk - -MODULE_PARM(once,"i"); -MODULE_PARM(debug,"i"); -MODULE_PARM(simple,"i"); -MODULE_PARM(amsound,"i"); -MODULE_PARM(dolby,"i"); - -/* ---------------------------------------------------------------------- */ - -#define I2C_MSP3400C 0x80 -#define I2C_MSP3400C_DEM 0x10 -#define I2C_MSP3400C_DFP 0x12 - -/* ----------------------------------------------------------------------- */ -/* functions for talking to the MSP3400C Sound processor */ - -static int msp3400c_reset(struct i2c_client *client) -{ - static char reset_off[3] = { 0x00, 0x80, 0x00 }; - static char reset_on[3] = { 0x00, 0x00, 0x00 }; - - i2c_master_send(client,reset_off,3); /* XXX ignore errors here */ - if (3 != i2c_master_send(client,reset_on, 3)) { - printk(KERN_ERR "msp3400: chip reset failed, penguin on i2c bus?\n"); - return -1; - } - return 0; -} - -static int -msp3400c_read(struct i2c_client *client, int dev, int addr) -{ - int err; - - 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++; - printk(KERN_WARNING "msp34xx: I/O error #%d (read 0x%02x/0x%02x)\n", - err, dev, addr); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - } - if (3 == err) { - printk(KERN_WARNING "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); - msp3400c_reset(client); - return -1; - } - return read[0] << 8 | read[1]; -} - -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; - - for (err = 0; err < 3;) { - if (5 == i2c_master_send(client, buffer, 5)) - break; - err++; - printk(KERN_WARNING "msp34xx: I/O error #%d (write 0x%02x/0x%02x)\n", - err, dev, addr); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - } - if (3 == err) { - printk(KERN_WARNING "msp34xx: 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 - -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)) - -/* ------------------------------------------------------------------------ */ - -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 left, int right) -{ - int vol,val,balance; - - vol = (left > right) ? left : right; - val = (vol * 0x73 / 65535) << 8; - balance = 0; - if (vol > 0) - balance = ((right-left) * 127) / vol; - - dprintk("msp34xx: setvolume: %d:%d 0x%02x 0x%02x\n", - left,right,val>>8,balance); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ - /* scart - on/off only */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0); - 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; - - dprintk("msp34xx: 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; - - dprintk("msp34xx: 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 = client->data; - int i; - - dprintk("msp3400: setmode: %d\n",type); - msp->mode = type; - msp->stereo = VIDEO_SOUND_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, 0x000a, - msp_init_data[type].dfp_src); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, - msp_init_data[type].dfp_matrix); - - if (msp->nicam) { - /* nicam prescale */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */ - } -} - -/* turn on/off nicam + stereo */ -static void msp3400c_setstereo(struct i2c_client *client, int mode) -{ - struct msp3400c *msp = client->data; - int nicam=0; /* channel source: FM/AM or nicam */ - int src=0; - - /* switch demodulator */ - switch (msp->mode) { - case MSP_MODE_FM_TERRA: - dprintk("msp3400: FM setstereo: %d\n",mode); - msp3400c_setcarrier(client,msp->second,msp->main); - switch (mode) { - case VIDEO_SOUND_STEREO: - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001); - break; - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - case VIDEO_SOUND_LANG2: - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000); - break; - } - break; - case MSP_MODE_FM_SAT: - dprintk("msp3400: SAT setstereo: %d\n",mode); - switch (mode) { - case VIDEO_SOUND_MONO: - msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); - break; - case VIDEO_SOUND_STEREO: - msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); - break; - case VIDEO_SOUND_LANG1: - msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); - break; - case VIDEO_SOUND_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: - dprintk("msp3400: NICAM setstereo: %d\n",mode); - msp3400c_setcarrier(client,msp->second,msp->main); - if (msp->nicam_on) - nicam=0x0100; - break; - case MSP_MODE_BTSC: - dprintk("msp3400: BTSC setstereo: %d\n",mode); - nicam=0x0300; - break; - default: - dprintk("msp3400: mono setstereo\n"); - return; - } - - /* switch audio */ - switch (mode) { - case VIDEO_SOUND_STEREO: - src = 0x0020 | nicam; -#if 0 - /* spatial effect */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000); -#endif - break; - case VIDEO_SOUND_MONO: - if (msp->mode == MSP_MODE_AM_NICAM) { - dprintk("msp3400: switching to AM mono\n"); - /* AM mono decoding is handled by tuner, not MSP chip */ - /* so let's redirect sound from tuner via SCART */ - /* volume prescale for SCART */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); - /* SCART switching control register*/ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, 0xe900); - src = 0x0200; - break; - } - case VIDEO_SOUND_LANG1: - src = 0x0000 | nicam; - break; - case VIDEO_SOUND_LANG2: - src = 0x0010 | nicam; - break; - } - 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); - } -} - -static void -msp3400c_print_mode(struct msp3400c *msp) -{ - if (msp->main == msp->second) { - printk("msp3400: mono sound carrier: %d.%03d MHz\n", - msp->main/910000,(msp->main/910)%1000); - } else { - printk("msp3400: 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) - printk("msp3400: NICAM/FM carrier : %d.%03d MHz\n", - msp->second/910000,(msp->second/910)%1000); - if (msp->mode == MSP_MODE_AM_NICAM) - printk("msp3400: 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) { - printk("msp3400: FM-stereo carrier : %d.%03d MHz\n", - msp->second/910000,(msp->second/910)%1000); - } -} - -/* ----------------------------------------------------------------------- */ - -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 = client->data; - int val; - int newstereo = msp->stereo; - 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 > 32768) - val -= 65536; - dprintk("msp34xx: stereo detect register: %d\n",val); - - if (val > 4096) { - newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO; - } else if (val < -4096) { - newstereo = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } else { - newstereo = VIDEO_SOUND_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); - dprintk("msp34xx: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1); - - if (val & 1) { - /* nicam synced */ - switch ((val & 0x1e) >> 1) { - case 0: - case 8: - newstereo = VIDEO_SOUND_STEREO; - break; - case 1: - case 9: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1; - break; - case 2: - case 10: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1 - | VIDEO_SOUND_LANG2; - break; - default: - newstereo = VIDEO_SOUND_MONO; - break; - } - newnicam=1; - } else { - newnicam = 0; - newstereo = VIDEO_SOUND_MONO; - } - break; - case MSP_MODE_BTSC: - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200); - dprintk("msp3410: 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" : ""); - newstereo = VIDEO_SOUND_MONO; - if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO; - if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1; - break; - } - if (newstereo != msp->stereo) { - update = 1; - dprintk("msp34xx: watch: stereo %d => %d\n", - msp->stereo,newstereo); - msp->stereo = newstereo; - } - if (newnicam != msp->nicam_on) { - update = 1; - dprintk("msp34xx: 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 void msp3400c_stereo_wake(unsigned long data) -{ - struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */ - - wake_up_interruptible(&msp->wq); -} - -/* stereo/multilang monitoring */ -static void watch_stereo(struct i2c_client *client) -{ - struct msp3400c *msp = client->data; - - if (autodetect_stereo(client)) { - if (msp->stereo & VIDEO_SOUND_STEREO) - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); - else if (msp->stereo & VIDEO_SOUND_LANG1) - msp3400c_setstereo(client,VIDEO_SOUND_LANG1); - else - msp3400c_setstereo(client,VIDEO_SOUND_MONO); - } - if (once) - msp->watch_stereo = 0; - if (msp->watch_stereo) - mod_timer(&msp->wake_stereo, jiffies+5*HZ); -} - -static int msp3400c_thread(void *data) -{ - struct i2c_client *client = data; - struct msp3400c *msp = client->data; - - struct CARRIER_DETECT *cd; - int count, max1,max2,val1,val2, val,this; - -#ifdef CONFIG_SMP - lock_kernel(); -#endif - - daemonize(); - sigfillset(¤t->blocked); - strcpy(current->comm,"msp3400"); - - msp->thread = current; - -#ifdef CONFIG_SMP - unlock_kernel(); -#endif - - printk("msp3400: daemon started\n"); - if(msp->notify != NULL) - up(msp->notify); - - for (;;) { - if (msp->rmmod) - goto done; - if (debug > 1) - printk("msp3400: thread: sleep\n"); - interruptible_sleep_on(&msp->wq); - if (debug > 1) - printk("msp3400: thread: wakeup\n"); - if (msp->rmmod || signal_pending(current)) - goto done; - - if (VIDEO_MODE_RADIO == msp->norm) - continue; /* nothing to do */ - - msp->active = 1; - - if (msp->watch_stereo) { - watch_stereo(client); - msp->active = 0; - continue; - } - - /* some time for the tuner to sync */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/5); - if (signal_pending(current)) - goto done; - - restart: - msp->restart = 0; - msp3400c_setvolume(client, 0, 0); - msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); - val1 = val2 = 0; - max1 = max2 = -1; - del_timer(&msp->wake_stereo); - msp->watch_stereo = 0; - - /* 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; - dprintk("msp3400: AM sound override\n"); - } - - for (this = 0; this < count; this++) { - msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); - - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - if (signal_pending(current)) - goto done; - if (msp->restart) - msp->restart = 0; - - val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); - if (val > 32768) - val -= 65536; - if (val1 < val) - val1 = val, max1 = this; - dprintk("msp3400: 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); - - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - if (signal_pending(current)) - goto done; - if (msp->restart) - goto restart; - - val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); - if (val > 32768) - val -= 65536; - if (val2 < val) - val2 = val, max2 = this; - dprintk("msp3400: 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, VIDEO_SOUND_MONO); - msp->watch_stereo = 1; - } else if (max2 == 1 && msp->nicam) { - /* 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, VIDEO_SOUND_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, VIDEO_SOUND_MONO); - msp3400c_setcarrier(client, msp->second, msp->main); - msp->watch_stereo = 1; - } else if (max2 == 0 && msp->nicam) { - /* 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->stereo = VIDEO_SOUND_MONO; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); - break; - } - - /* unmute */ - msp3400c_setvolume(client, msp->left, msp->right); - - if (msp->watch_stereo) - mod_timer(&msp->wake_stereo, jiffies+5*HZ); - - if (debug) - msp3400c_print_mode(msp); - - msp->active = 0; - } - -done: - dprintk("msp3400: thread: exit\n"); - msp->active = 0; - msp->thread = NULL; - - if(msp->notify != NULL) - up(msp->notify); - 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 int msp3410d_thread(void *data) -{ - struct i2c_client *client = data; - struct msp3400c *msp = client->data; - int mode,val,i,std; - -#ifdef CONFIG_SMP - lock_kernel(); -#endif - - daemonize(); - sigfillset(¤t->blocked); - strcpy(current->comm,"msp3410 [auto]"); - - msp->thread = current; - -#ifdef CONFIG_SMP - unlock_kernel(); -#endif - - printk("msp3410: daemon started\n"); - if(msp->notify != NULL) - up(msp->notify); - - for (;;) { - if (msp->rmmod) - goto done; - if (debug > 1) - printk("msp3410: thread: sleep\n"); - interruptible_sleep_on(&msp->wq); - if (debug > 1) - printk("msp3410: thread: wakeup\n"); - if (msp->rmmod || signal_pending(current)) - goto done; - - if (VIDEO_MODE_RADIO == msp->norm) - continue; /* nothing to do */ - - msp->active = 1; - - if (msp->watch_stereo) { - watch_stereo(client); - msp->active = 0; - continue; - } - - /* some time for the tuner to sync */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/5); - if (signal_pending(current)) - goto done; - - restart: - msp->restart = 0; - del_timer(&msp->wake_stereo); - msp->watch_stereo = 0; - - /* put into sane state (and mute) */ - msp3400c_reset(client); - - /* start autodetect */ - switch (msp->norm) { - case VIDEO_MODE_PAL: - mode = 0x1003; - std = 1; - break; - case VIDEO_MODE_NTSC: /* BTSC */ - mode = 0x2003; - std = 0x0020; - break; - case VIDEO_MODE_SECAM: - mode = 0x0003; - std = 1; - break; - default: - mode = 0x0003; - std = 1; - break; - } - msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode); - msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); - if (debug) { - int i; - for (i = 0; modelist[i].name != NULL; i++) - if (modelist[i].retval == std) - break; - printk("msp3410: setting mode: %s (0x%04x)\n", - modelist[i].name ? modelist[i].name : "unknown",std); - } - - if (std != 1) { - /* programmed some specific mode */ - val = std; - } else { - /* triggered autodetect */ - for (;;) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - if (signal_pending(current)) - goto done; - if (msp->restart) - goto restart; - - /* check results */ - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); - if (val < 0x07ff) - break; - dprintk("msp3410: detection still in progress\n"); - } - } - for (i = 0; modelist[i].name != NULL; i++) - if (modelist[i].retval == val) - break; - dprintk("msp3410: 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 */ - dprintk("msp3410: 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 prescale / stereo */ - switch (val) { - case 0x0009: - msp->mode = MSP_MODE_AM_NICAM; - msp->stereo = VIDEO_SOUND_MONO; - msp3400c_setstereo(client,VIDEO_SOUND_MONO); - msp->watch_stereo = 1; - break; - case 0x0020: /* BTSC */ - /* just turn on stereo */ - msp->mode = MSP_MODE_BTSC; - msp->stereo = VIDEO_SOUND_STEREO; - msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); - /* set prescale */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */ - break; - case 0x0003: - msp->mode = MSP_MODE_FM_TERRA; - msp->stereo = VIDEO_SOUND_MONO; - msp->watch_stereo = 1; - /* fall */ - default: - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* NICAM */ - break; - } - - /* unmute */ - msp3400c_setbass(client, msp->bass); - msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->left, msp->right); - - if (msp->watch_stereo) - mod_timer(&msp->wake_stereo, jiffies+HZ); - - msp->active = 0; - } - -done: - dprintk("msp3410: thread: exit\n"); - msp->active = 0; - msp->thread = NULL; - - if(msp->notify != NULL) - up(msp->notify); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static int msp_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, 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 struct i2c_driver driver = { - "i2c msp3400 driver", - I2C_DRIVERID_MSP3400, - I2C_DF_NOTIFY, - msp_probe, - msp_detach, - msp_command, -}; - -static struct i2c_client client_template = -{ - "unset", - -1, - 0, - 0, - NULL, - &driver -}; - -static int msp_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - DECLARE_MUTEX_LOCKED(sem); - struct msp3400c *msp; - struct i2c_client *c; - int rev1,rev2,i; - - client_template.adapter = adap; - client_template.addr = addr; - - if (-1 == msp3400c_reset(&client_template)) { - dprintk("msp3400: no chip found\n"); - return -1; - } - - if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) - return -ENOMEM; - memcpy(c,&client_template,sizeof(struct i2c_client)); - if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) { - kfree(c); - return -ENOMEM; - } - - memset(msp,0,sizeof(struct msp3400c)); - msp->left = 65535; - msp->right = 65535; - msp->bass = 32768; - msp->treble = 32768; - c->data = msp; - init_waitqueue_head(&msp->wq); - - if (-1 == msp3400c_reset(c)) { - kfree(msp); - dprintk("msp3400: no chip found\n"); - return -1; - } - - rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e); - rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f); - if (0 == rev1 && 0 == rev2) { - kfree(msp); - printk("msp3400: error while reading chip version\n"); - return -1; - } - -#if 0 - /* this will turn on a 1kHz beep - might be useful for debugging... */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0014, 0x1040); -#endif - - sprintf(c->name,"MSP34%02d%c-%c%d", - (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f); - msp->nicam = (((rev2>>8)&0xff) != 00) ? 1 : 0; - - if (simple == -1) { - /* default mode */ - /* msp->simple = (((rev2>>8)&0xff) == 0) ? 0 : 1; */ - msp->simple = ((rev1&0xff)+'@' > 'C'); - } else { - /* use insmod option */ - msp->simple = simple; - } - - /* timer for stereo checking */ - msp->wake_stereo.function = msp3400c_stereo_wake; - msp->wake_stereo.data = (unsigned long)msp; - - /* hello world :-) */ - printk(KERN_INFO "msp3400: init: chip=%s",c->name); - if (msp->nicam) - printk(", has NICAM support"); - printk("\n"); - - /* startup control thread */ - MOD_INC_USE_COUNT; - msp->notify = &sem; - kernel_thread(msp->simple ? msp3410d_thread : msp3400c_thread, - (void *)c, 0); - down(&sem); - msp->notify = NULL; - wake_up_interruptible(&msp->wq); - -#ifdef REGISTER_MIXER - if ((msp->mixer_num = register_sound_mixer(&msp3400c_mixer_fops,mixer)) < 0) - printk(KERN_ERR "msp3400c: cannot allocate mixer device\n"); -#endif - - /* update our own array */ - for (i = 0; i < MSP3400_MAX; i++) { - if (NULL == msps[i]) { - msps[i] = c; - break; - } - } - - /* done */ - i2c_attach_client(c); - return 0; -} - -static int msp_detach(struct i2c_client *client) -{ - DECLARE_MUTEX_LOCKED(sem); - struct msp3400c *msp = (struct msp3400c*)client->data; - int i; - -#ifdef REGISTER_MIXER - if (msp->mixer_num >= 0) - unregister_sound_mixer(msp->mixer_num); -#endif - - /* shutdown control thread */ - del_timer(&msp->wake_stereo); - if (msp->thread) - { - msp->notify = &sem; - msp->rmmod = 1; - wake_up_interruptible(&msp->wq); - down(&sem); - msp->notify = NULL; - } - 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); - MOD_DEC_USE_COUNT; - return 0; -} - -static int msp_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, msp_attach); - return 0; -} - -static int msp_command(struct i2c_client *client,unsigned int cmd, void *arg) -{ - struct msp3400c *msp = (struct msp3400c*)client->data; -#if 0 - int *iarg = (int*)arg; - __u16 *sarg = arg; -#endif - - switch (cmd) { - - case AUDC_SET_RADIO: - msp->norm = VIDEO_MODE_RADIO; - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - if (msp->simple) { - msp3400c_reset(client); - msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, 0x0003); /* automatic */ - msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, 0x0040); /* FM Radio */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM prescale */ - msp3400c_setbass(client, msp->bass); - msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->left, msp->right); - } else { - msp3400c_setmode(client,MSP_MODE_FM_RADIO); - msp3400c_setcarrier(client, MSP_CARRIER(10.7),MSP_CARRIER(10.7)); - msp3400c_setvolume(client,msp->left, msp->right); - } - 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_BASS | - VIDEO_AUDIO_TREBLE; - va->volume=MAX(msp->left,msp->right); - va->balance=(32768*MIN(msp->left,msp->right))/ - (va->volume ? va->volume : 1); - va->balance=(msp->leftright)? - (65535-va->balance) : va->balance; - va->bass = msp->bass; - va->treble = msp->treble; - - autodetect_stereo(client); - va->mode = msp->stereo; - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - 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; - msp3400c_setvolume(client,msp->left, msp->right); - msp3400c_setbass(client,msp->bass); - msp3400c_settreble(client,msp->treble); - - if (va->mode != 0) { - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - msp->stereo = va->mode; - msp3400c_setstereo(client,va->mode); - } - break; - } - case VIDIOCSCHAN: - { - struct video_channel *vc = arg; - - msp->norm = vc->norm; - break; - } - case VIDIOCSFREQ: - { - /* new channel -- kick audio carrier scan */ - msp3400c_setvolume(client,0,0); - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - if (msp->active) - msp->restart = 1; - wake_up_interruptible(&msp->wq); - break; - } - - /* --- v4l2 ioctls --- */ - /* NOT YET */ - -#if 0 - /* --- old, obsolete interface --- */ - case AUDC_SET_TVNORM: - msp->norm = *iarg; - break; - case AUDC_SWITCH_MUTE: - /* channels switching step one -- mute */ - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - msp3400c_setvolume(client,0,0); - break; - case AUDC_NEWCHANNEL: - /* channels switching step two -- trigger sound carrier scan */ - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - if (msp->active) - msp->restart = 1; - wake_up_interruptible(&msp->wq); - break; - - case AUDC_GET_VOLUME_LEFT: - *sarg = msp->left; - break; - case AUDC_GET_VOLUME_RIGHT: - *sarg = msp->right; - break; - case AUDC_SET_VOLUME_LEFT: - msp->left = *sarg; - msp3400c_setvolume(client,msp->left, msp->right); - break; - case AUDC_SET_VOLUME_RIGHT: - msp->right = *sarg; - msp3400c_setvolume(client,msp->left, msp->right); - break; - - case AUDC_GET_BASS: - *sarg = msp->bass; - break; - case AUDC_SET_BASS: - msp->bass = *sarg; - msp3400c_setbass(client,msp->bass); - break; - - case AUDC_GET_TREBLE: - *sarg = msp->treble; - break; - case AUDC_SET_TREBLE: - msp->treble = *sarg; - msp3400c_settreble(client,msp->treble); - break; - - case AUDC_GET_STEREO: - autodetect_stereo(client); - *sarg = msp->stereo; - break; - case AUDC_SET_STEREO: - if (*sarg) { - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - msp->stereo = *sarg; - msp3400c_setstereo(client,*sarg); - } - break; - - case AUDC_GET_DC: - if (msp->simple) - break; /* fixme */ - *sarg = ((int)msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b) + - (int)msp3400c_read(client, I2C_MSP3400C_DFP, 0x1c)); - break; -#endif - default: - /* nothing */ - } - return 0; -} - -/* ----------------------------------------------------------------------- */ - -int msp3400_init_module(void) -{ - i2c_add_driver(&driver); - return 0; -} - -void 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/char/nwbutton.c b/drivers/char/nwbutton.c index 8cf8a15a7..e99d92856 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -19,6 +19,8 @@ #include #include +#include + #define __NWBUTTON_C /* Tell the header file who we are */ #include "nwbutton.h" diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 5be07b769..8b5c266a6 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index 757af9c14..7629e24ad 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -1,5 +1,5 @@ /* - * linux/drivers/char/pcxe.c + * linux/drivers/char/pcxx.c * * Written by Troy De Jongh, November, 1994 * @@ -12,13 +12,11 @@ * This driver does NOT support DigiBoard's fastcook FEP option and * does not support the transparent print (i.e. digiprint) option. * - * This Driver is currently maintained by Christoph Lameter (clameter@fuller.edu) - * Please contact the mailing list for problems first. + * This Driver is currently maintained by Christoph Lameter (christoph@lameter.com) * - * Sources of Information: - * 1. The Linux Digiboard Page at http://private.fuller.edu/clameter/digi.html - * 2. The Linux Digiboard Mailing list at digiboard@list.fuller.edu - * (Simply write a message to introduce yourself to subscribe) + * Please contact digi for support issues at digilnux@dgii.com. Some + * information (mostly of historical interest) can be found at + * http://lameter.com/digi. * * 1.5.2 Fall 1995 Bug fixes by David Nugent * 1.5.3 March 9, 1996 Christoph Lameter: Fixed 115.2K Support. Memory @@ -39,6 +37,8 @@ * verbose messages to assist user during card configuration. * Currently only tested on a PC/Xi card, but should work on Xe * and Xeve also. + * 1.6.2 August, 7, 2000: Arnaldo Carvalho de Melo + * get rid of panics, release previously allocated resources * */ @@ -81,7 +81,7 @@ #include #include -#define VERSION "1.6.1" +#define VERSION "1.6.2" #include "digi.h" #include "fep.h" @@ -193,6 +193,30 @@ static inline void assertmemoff(struct channel *ch); #define TZ_BUFSZ 4096 /* function definitions */ + +/*****************************************************************************/ + +static void cleanup_board_resources(void) +{ + int crd, i; + struct board_info *bd; + struct channel *ch; + + for(crd = 0; crd < numcards; crd++) { + bd = &boards[crd]; + ch = digi_channels + bd->first_minor; + + if (bd->region) + release_region(bd->port, 4); + + for(i = 0; i < bd->numports; i++, ch++) + if (ch->tmp_buf) + kfree(ch->tmp_buf); + } +} + +/*****************************************************************************/ + #ifdef MODULE /* @@ -209,10 +233,7 @@ void cleanup_module() { unsigned long flags; - int crd, i; int e1, e2; - struct board_info *bd; - struct channel *ch; printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION); @@ -226,14 +247,7 @@ void cleanup_module() if ((e2 = tty_unregister_driver(&pcxe_callout))) printk("SERIAL: failed to unregister callout driver (%d)\n",e2); - for(crd=0; crd < numcards; crd++) { - bd = &boards[crd]; - ch = digi_channels+bd->first_minor; - for(i=0; i < bd->numports; i++, ch++) { - kfree(ch->tmp_buf); - } - release_region(bd->port, 4); - } + cleanup_board_resources(); kfree(digi_channels); kfree(pcxe_termios_locked); kfree(pcxe_termios); @@ -620,7 +634,7 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp) ** worth noting that while I'm not sure what this hunk of code is supposed ** to do, it is not present in the serial.c driver. Hmmm. If you know, ** please send me a note. brian@ilinx.com -** Don't know either what this is supposed to do clameter@waterf.org. +** Don't know either what this is supposed to do christoph@lameter.com. */ if(tty->ldisc.num != ldiscs[N_TTY].num) { if(tty->ldisc.close) @@ -1090,6 +1104,7 @@ int __init pcxe_init(void) { ulong memory_seg=0, memory_size=0; int lowwater, enabled_cards=0, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L; + int ret = -ENOMEM; unchar *fepos, *memaddr, *bios, v; volatile struct global_data *gd; volatile struct board_chan *bc; @@ -1099,7 +1114,7 @@ int __init pcxe_init(void) printk(KERN_NOTICE "Digiboard PC/X{i,e,eve} driver v%s\n", VERSION); #ifdef MODULE - for (i = 0; i < 4; i++) { + for (i = 0; i < MAX_DIGI_BOARDS; i++) { if (io[i]) { numcards = 0; break; @@ -1108,7 +1123,7 @@ int __init pcxe_init(void) if (numcards == 0) { int first_minor = 0; - for (i = 0; i < 4; i++) { + for (i = 0; i < MAX_DIGI_BOARDS; i++) { if (io[i] == 0) { boards[i].port = 0; boards[i].status = DISABLED; @@ -1139,6 +1154,7 @@ int __init pcxe_init(void) else boards[i].numports = 16; + boards[i].region = NULL; first_minor += boards[i].numports; } } @@ -1178,23 +1194,31 @@ int __init pcxe_init(void) * unused spaces. */ digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL); - if (!digi_channels) - panic("Unable to allocate digi_channel struct"); + if (!digi_channels) { + printk(KERN_ERR "Unable to allocate digi_channel struct\n"); + return -ENOMEM; + } memset(digi_channels, 0, sizeof(struct channel) * nbdevs); pcxe_table = kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL); - if (!pcxe_table) - panic("Unable to allocate pcxe_table struct"); + if (!pcxe_table) { + printk(KERN_ERR "Unable to allocate pcxe_table struct\n"); + goto cleanup_digi_channels; + } memset(pcxe_table, 0, sizeof(struct tty_struct *) * nbdevs); pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL); - if (!pcxe_termios) - panic("Unable to allocate pcxe_termios struct"); + if (!pcxe_termios) { + printk(KERN_ERR "Unable to allocate pcxe_termios struct\n"); + goto cleanup_pcxe_table; + } memset(pcxe_termios,0,sizeof(struct termios *)*nbdevs); pcxe_termios_locked = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL); - if (!pcxe_termios_locked) - panic("Unable to allocate pcxe_termios_locked struct"); + if (!pcxe_termios_locked) { + printk(KERN_ERR "Unable to allocate pcxe_termios_locked struct\n"); + goto cleanup_pcxe_termios; + } memset(pcxe_termios_locked,0,sizeof(struct termios *)*nbdevs); init_bh(DIGI_BH,do_pcxe_bh); @@ -1512,7 +1536,13 @@ load_fep: if((bd->type == PCXEVE) && (*(ushort *)((ulong)memaddr+NPORT) < 3)) shrinkmem = 1; - request_region(bd->port, 4, "PC/Xx"); + bd->region = request_region(bd->port, 4, "PC/Xx"); + + if (!bd->region) { + printk(KERN_ERR "I/O port 0x%x is already used\n", bd->port); + ret = -EBUSY; + goto cleanup_boards; + } for(i=0; i < bd->numports; i++, ch++, bc++) { if(((ushort *)((ulong)memaddr + PORTBASE))[i] == 0) { @@ -1562,6 +1592,12 @@ load_fep: ch->txbufsize = bc->tmax + 1; ch->rxbufsize = bc->rmax + 1; ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL); + + if (!ch->tmp_buf) { + printk(KERN_ERR "Unable to allocate memory for temp buffers\n"); + goto cleanup_boards; + } + lowwater = ch->txbufsize >= 2000 ? 1024 : ch->txbufsize/2; fepcmd(ch, STXLWATER, lowwater, 0, 10, 0); fepcmd(ch, SRXLWATER, ch->rxbufsize/4, 0, 10, 0); @@ -1608,14 +1644,21 @@ load_fep: if (enabled_cards <= 0) { printk(KERN_NOTICE "PC/Xx: No cards enabled, no driver.\n"); - return -EIO; + ret = -EIO; + goto cleanup_boards; } - if(tty_register_driver(&pcxe_driver)) - panic("Couldn't register PC/Xe driver"); + ret = tty_register_driver(&pcxe_driver); + if(ret) { + printk(KERN_ERR "Couldn't register PC/Xe driver\n"); + goto cleanup_boards; + } - if(tty_register_driver(&pcxe_callout)) - panic("Couldn't register PC/Xe callout"); + ret = tty_register_driver(&pcxe_callout); + if(ret) { + printk(KERN_ERR "Couldn't register PC/Xe callout\n"); + goto cleanup_pcxe_driver; + } /* * Start up the poller to check for events on all enabled boards @@ -1626,6 +1669,13 @@ load_fep: printk(KERN_NOTICE "PC/Xx: Driver with %d card(s) ready.\n", enabled_cards); return 0; +cleanup_pcxe_driver: tty_unregister_driver(&pcxe_driver); +cleanup_boards: cleanup_board_resources(); + kfree(pcxe_termios_locked); +cleanup_pcxe_termios: kfree(pcxe_termios); +cleanup_pcxe_table: kfree(pcxe_table); +cleanup_digi_channels: kfree(digi_channels); + return ret; } diff --git a/drivers/char/pcxx.h b/drivers/char/pcxx.h index 6d7a08b85..464fbe061 100644 --- a/drivers/char/pcxx.h +++ b/drivers/char/pcxx.h @@ -51,6 +51,7 @@ struct board_info { ulong membase; ulong memsize; ushort first_minor; + void *region; }; diff --git a/drivers/char/planb.c b/drivers/char/planb.c deleted file mode 100644 index 94707619d..000000000 --- a/drivers/char/planb.c +++ /dev/null @@ -1,2341 +0,0 @@ -/* - planb - PlanB frame grabber driver - - PlanB is used in the 7x00/8x00 series of PowerMacintosh - Computers as video input DMA controller. - - Copyright (C) 1998 Michel Lanners (mlan@cpu.lu) - - Based largely on the bttv driver by Ralph Metzler (rjkm@thp.uni-koeln.de) - - Additional debugging and coding by Takashi Oe (toe@unlserve.unl.edu) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - 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. -*/ - -/* $Id: planb.c,v 1.18 1999/05/02 17:36:34 mlan Exp $ */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "planb.h" -#include "saa7196.h" - - -/* Would you mind for some ugly debugging? */ -//#define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */ -#define DEBUG(x...) /* Don't debug driver */ -//#define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */ -#define IDEBUG(x...) /* Don't debug interrupt part */ - -/* Ever seen a Mac with more than 1 of these? */ -#define PLANB_MAX 1 - -static int planb_num; -static struct planb planbs[PLANB_MAX]; -static volatile struct planb_registers *planb_regs; - -static int def_norm = PLANB_DEF_NORM; /* default norm */ - -MODULE_PARM(def_norm, "i"); -MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)"); - -/* ------------------ PlanB Exported Functions ------------------ */ -static long planb_write(struct video_device *, const char *, unsigned long, int); -static long planb_read(struct video_device *, char *, unsigned long, int); -static int planb_open(struct video_device *, int); -static void planb_close(struct video_device *); -static int planb_ioctl(struct video_device *, unsigned int, void *); -static int planb_init_done(struct video_device *); -static int planb_mmap(struct video_device *, const char *, unsigned long); -static void planb_irq(int, void *, struct pt_regs *); -static void release_planb(void); -int init_planbs(struct video_init *); - -/* ------------------ PlanB Internal Functions ------------------ */ -static int planb_prepare_open(struct planb *); -static void planb_prepare_close(struct planb *); -static void saa_write_reg(unsigned char, unsigned char); -static unsigned char saa_status(int, struct planb *); -static void saa_set(unsigned char, unsigned char, struct planb *); -static void saa_init_regs(struct planb *); -static int grabbuf_alloc(struct planb *); -static int vgrab(struct planb *, struct video_mmap *); -static void add_clip(struct planb *, struct video_clip *); -static void fill_cmd_buff(struct planb *); -static void cmd_buff(struct planb *); -static volatile struct dbdma_cmd *setup_grab_cmd(int, struct planb *); -static void overlay_start(struct planb *); -static void overlay_stop(struct planb *); -static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *, unsigned short, - unsigned int); -static inline void tab_cmd_store(volatile struct dbdma_cmd *, unsigned int, - unsigned int); -static inline void tab_cmd_gen(volatile struct dbdma_cmd *, unsigned short, - unsigned short, unsigned int, unsigned int); -static int init_planb(struct planb *); -static int find_planb(void); -static void planb_pre_capture(int, int, struct planb *); -static volatile struct dbdma_cmd *cmd_geo_setup(volatile struct dbdma_cmd *, - int, int, int, int, int, struct planb *); -static inline void planb_dbdma_stop(volatile struct dbdma_regs *); -static unsigned int saa_geo_setup(int, int, int, int, struct planb *); -static inline int overlay_is_active(struct planb *); - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -static int grabbuf_alloc(struct planb *pb) -{ - int i, npage; - - npage = MAX_GBUFFERS * ((PLANB_MAX_FBUF / PAGE_SIZE + 1) -#ifndef PLANB_GSCANLINE - + MAX_LNUM -#endif /* PLANB_GSCANLINE */ - ); - if ((pb->rawbuf = (unsigned char**) kmalloc (npage - * sizeof(unsigned long), GFP_KERNEL)) == 0) - return -ENOMEM; - for (i = 0; i < npage; i++) { - pb->rawbuf[i] = (unsigned char *)__get_free_pages(GFP_KERNEL - |GFP_DMA, 0); - if (!pb->rawbuf[i]) - break; - mem_map_reserve(virt_to_page(pb->rawbuf[i])); - } - if (i-- < npage) { - printk(KERN_DEBUG "PlanB: init_grab: grab buffer not allocated\n"); - for (; i > 0; i--) { - mem_map_unreserve(virt_to_page(pb->rawbuf[i])); - free_pages((unsigned long)pb->rawbuf[i], 0); - } - kfree(pb->rawbuf); - return -ENOBUFS; - } - pb->rawbuf_size = npage; - return 0; -} - -/*****************************/ -/* Hardware access functions */ -/*****************************/ - -static void saa_write_reg(unsigned char addr, unsigned char val) -{ - planb_regs->saa_addr = addr; eieio(); - planb_regs->saa_regval = val; eieio(); - return; -} - -/* return status byte 0 or 1: */ -static unsigned char saa_status(int byte, struct planb *pb) -{ - saa_regs[pb->win.norm][SAA7196_STDC] = - (saa_regs[pb->win.norm][SAA7196_STDC] & ~2) | ((byte & 1) << 1); - saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]); - - /* Let's wait 30msec for this one */ - current->state = TASK_INTERRUPTIBLE; -#if LINUX_VERSION_CODE >= 0x02017F - schedule_timeout(30 * HZ / 1000); -#else - current->timeout = jiffies + 30 * HZ / 1000; /* 30 ms */; - schedule(); -#endif - - return (unsigned char)in_8 (&planb_regs->saa_status); -} - -static void saa_set(unsigned char addr, unsigned char val, struct planb *pb) -{ - if(saa_regs[pb->win.norm][addr] != val) { - saa_regs[pb->win.norm][addr] = val; - saa_write_reg (addr, val); - } - return; -} - -static void saa_init_regs(struct planb *pb) -{ - int i; - - for (i = 0; i < SAA7196_NUMREGS; i++) - saa_write_reg (i, saa_regs[pb->win.norm][i]); -} - -static unsigned int saa_geo_setup(int width, int height, int interlace, int bpp, - struct planb *pb) -{ - int ht, norm = pb->win.norm; - - switch(bpp) { - case 2: - /* RGB555+a 1x16-bit + 16-bit transparent */ - saa_regs[norm][SAA7196_FMTS] &= ~0x3; - break; - case 1: - case 4: - /* RGB888 1x24-bit + 8-bit transparent */ - saa_regs[norm][SAA7196_FMTS] &= ~0x1; - saa_regs[norm][SAA7196_FMTS] |= 0x2; - break; - default: - return -EINVAL; - } - ht = (interlace ? height / 2 : height); - saa_regs[norm][SAA7196_OUTPIX] = (unsigned char) (width & 0x00ff); - saa_regs[norm][SAA7196_HFILT] = (saa_regs[norm][SAA7196_HFILT] & ~0x3) - | (width >> 8 & 0x3); - saa_regs[norm][SAA7196_OUTLINE] = (unsigned char) (ht & 0xff); - saa_regs[norm][SAA7196_VYP] = (saa_regs[norm][SAA7196_VYP] & ~0x3) - | (ht >> 8 & 0x3); - /* feed both fields if interlaced, or else feed only even fields */ - saa_regs[norm][SAA7196_FMTS] = (interlace) ? - (saa_regs[norm][SAA7196_FMTS] & ~0x60) - : (saa_regs[norm][SAA7196_FMTS] | 0x60); - /* transparent mode; extended format enabled */ - saa_regs[norm][SAA7196_DPATH] |= 0x3; - - return 0; -} - -/***************************/ -/* DBDMA support functions */ -/***************************/ - -static inline void planb_dbdma_restart(volatile struct dbdma_regs *ch) -{ - out_le32(&ch->control, PLANB_CLR(RUN)); - out_le32(&ch->control, PLANB_SET(RUN|WAKE) | PLANB_CLR(PAUSE)); -} - -static inline void planb_dbdma_stop(volatile struct dbdma_regs *ch) -{ - int i = 0; - - out_le32(&ch->control, PLANB_CLR(RUN) | PLANB_SET(FLUSH)); - while((in_le32(&ch->status) == (ACTIVE | FLUSH)) && (i < 999)) { - IDEBUG("PlanB: waiting for DMA to stop\n"); - i++; - } -} - -static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *ch, - unsigned short command, unsigned int cmd_dep) -{ - st_le16(&ch->command, command); - st_le32(&ch->cmd_dep, cmd_dep); -} - -static inline void tab_cmd_store(volatile struct dbdma_cmd *ch, - unsigned int phy_addr, unsigned int cmd_dep) -{ - st_le16(&ch->command, STORE_WORD | KEY_SYSTEM); - st_le16(&ch->req_count, 4); - st_le32(&ch->phy_addr, phy_addr); - st_le32(&ch->cmd_dep, cmd_dep); -} - -static inline void tab_cmd_gen(volatile struct dbdma_cmd *ch, - unsigned short command, unsigned short req_count, - unsigned int phy_addr, unsigned int cmd_dep) -{ - st_le16(&ch->command, command); - st_le16(&ch->req_count, req_count); - st_le32(&ch->phy_addr, phy_addr); - st_le32(&ch->cmd_dep, cmd_dep); -} - -static volatile struct dbdma_cmd *cmd_geo_setup( - volatile struct dbdma_cmd *c1, int width, int height, int interlace, - int bpp, int clip, struct planb *pb) -{ - int norm = pb->win.norm; - - if((saa_geo_setup(width, height, interlace, bpp, pb)) != 0) - return (volatile struct dbdma_cmd *)NULL; - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr), - SAA7196_FMTS); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval), - saa_regs[norm][SAA7196_FMTS]); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr), - SAA7196_DPATH); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval), - saa_regs[norm][SAA7196_DPATH]); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->even), - bpp | ((clip)? PLANB_CLIPMASK: 0)); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->odd), - bpp | ((clip)? PLANB_CLIPMASK: 0)); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr), - SAA7196_OUTPIX); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval), - saa_regs[norm][SAA7196_OUTPIX]); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr), - SAA7196_HFILT); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval), - saa_regs[norm][SAA7196_HFILT]); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr), - SAA7196_OUTLINE); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval), - saa_regs[norm][SAA7196_OUTLINE]); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr), - SAA7196_VYP); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval), - saa_regs[norm][SAA7196_VYP]); - return c1; -} - -/******************************/ -/* misc. supporting functions */ -/******************************/ - -static void __planb_wait(struct planb *pb) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&pb->lockq, &wait); -repeat: - set_current_state(TASK_UNINTERRUPTIBLE); - if (pb->lock) { - schedule(); - goto repeat; - } - remove_wait_queue(&pb->lockq, &wait); - current->state = TASK_RUNNING; -} - -static inline void planb_wait(struct planb *pb) -{ - DEBUG("PlanB: planb_wait\n"); - if(pb->lock) - __planb_wait(pb); -} - -static inline void planb_lock(struct planb *pb) -{ - DEBUG("PlanB: planb_lock\n"); - if(pb->lock) - __planb_wait(pb); - pb->lock = 1; -} - -static inline void planb_unlock(struct planb *pb) -{ - DEBUG("PlanB: planb_unlock\n"); - pb->lock = 0; - wake_up(&pb->lockq); -} - -/***************/ -/* Driver Core */ -/***************/ - -static int planb_prepare_open(struct planb *pb) -{ - int i, size; - - /* allocate memory for two plus alpha command buffers (size: max lines, - plus 40 commands handling, plus 1 alignment), plus dummy command buf, - plus clipmask buffer, plus frame grabbing status */ - size = (pb->tab_size*(2+MAX_GBUFFERS*TAB_FACTOR)+1+MAX_GBUFFERS - * PLANB_DUMMY)*sizeof(struct dbdma_cmd) - +(PLANB_MAXLINES*((PLANB_MAXPIXELS+7)& ~7))/8 - +MAX_GBUFFERS*sizeof(unsigned int); - if ((pb->priv_space = kmalloc (size, GFP_KERNEL)) == 0) - return -ENOMEM; - memset ((void *) pb->priv_space, 0, size); - pb->overlay_last1 = pb->ch1_cmd = (volatile struct dbdma_cmd *) - DBDMA_ALIGN (pb->priv_space); - pb->overlay_last2 = pb->ch2_cmd = pb->ch1_cmd + pb->tab_size; - pb->ch1_cmd_phys = virt_to_bus(pb->ch1_cmd); - pb->cap_cmd[0] = pb->ch2_cmd + pb->tab_size; - pb->pre_cmd[0] = pb->cap_cmd[0] + pb->tab_size * TAB_FACTOR; - for (i = 1; i < MAX_GBUFFERS; i++) { - pb->cap_cmd[i] = pb->pre_cmd[i-1] + PLANB_DUMMY; - pb->pre_cmd[i] = pb->cap_cmd[i] + pb->tab_size * TAB_FACTOR; - } - pb->frame_stat=(volatile unsigned int *)(pb->pre_cmd[MAX_GBUFFERS-1] - + PLANB_DUMMY); - pb->mask = (unsigned char *)(pb->frame_stat+MAX_GBUFFERS); - - pb->rawbuf = NULL; - pb->rawbuf_size = 0; - pb->grabbing = 0; - for (i = 0; i < MAX_GBUFFERS; i++) { - pb->frame_stat[i] = GBUFFER_UNUSED; - pb->gwidth[i] = 0; - pb->gheight[i] = 0; - pb->gfmt[i] = 0; - pb->gnorm_switch[i] = 0; -#ifndef PLANB_GSCANLINE - pb->lsize[i] = 0; - pb->lnum[i] = 0; -#endif /* PLANB_GSCANLINE */ - } - pb->gcount = 0; - pb->suspend = 0; - pb->last_fr = -999; - pb->prev_last_fr = -999; - - /* Reset DMA controllers */ - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - - return 0; -} - -static void planb_prepare_close(struct planb *pb) -{ - int i; - - /* make sure the dma's are idle */ - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - /* free kernel memory of command buffers */ - if(pb->priv_space != 0) { - kfree (pb->priv_space); - pb->priv_space = 0; - pb->cmd_buff_inited = 0; - } - if(pb->rawbuf) { - for (i = 0; i < pb->rawbuf_size; i++) { - mem_map_unreserve(virt_to_page(pb->rawbuf[i])); - free_pages((unsigned long)pb->rawbuf[i], 0); - } - kfree(pb->rawbuf); - } - pb->rawbuf = NULL; -} - -/*****************************/ -/* overlay support functions */ -/*****************************/ - -static void overlay_start(struct planb *pb) -{ - - DEBUG("PlanB: overlay_start()\n"); - - if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) { - - DEBUG("PlanB: presumably, grabbing is in progress...\n"); - - planb_dbdma_stop(&pb->planb_base->ch2); - out_le32 (&pb->planb_base->ch2.cmdptr, - virt_to_bus(pb->ch2_cmd)); - planb_dbdma_restart(&pb->planb_base->ch2); - st_le16 (&pb->ch1_cmd->command, DBDMA_NOP); - tab_cmd_dbdma(pb->last_cmd[pb->last_fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->ch1_cmd)); - eieio(); - pb->prev_last_fr = pb->last_fr; - pb->last_fr = -2; - if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) { - IDEBUG("PlanB: became inactive " - "in the mean time... reactivating\n"); - planb_dbdma_stop(&pb->planb_base->ch1); - out_le32 (&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->ch1_cmd)); - planb_dbdma_restart(&pb->planb_base->ch1); - } - } else { - - DEBUG("PlanB: currently idle, so can do whatever\n"); - - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - st_le32 (&pb->planb_base->ch2.cmdptr, - virt_to_bus(pb->ch2_cmd)); - st_le32 (&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->ch1_cmd)); - out_le16 (&pb->ch1_cmd->command, DBDMA_NOP); - planb_dbdma_restart(&pb->planb_base->ch2); - planb_dbdma_restart(&pb->planb_base->ch1); - pb->last_fr = -1; - } - return; -} - -static void overlay_stop(struct planb *pb) -{ - DEBUG("PlanB: overlay_stop()\n"); - - if(pb->last_fr == -1) { - - DEBUG("PlanB: no grabbing, it seems...\n"); - - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - pb->last_fr = -999; - } else if(pb->last_fr == -2) { - unsigned int cmd_dep; - tab_cmd_dbdma(pb->cap_cmd[pb->prev_last_fr], DBDMA_STOP, 0); - eieio(); - cmd_dep = (unsigned int)in_le32(&pb->overlay_last1->cmd_dep); - if(overlay_is_active(pb)) { - - DEBUG("PlanB: overlay is currently active\n"); - - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - if(cmd_dep != pb->ch1_cmd_phys) { - out_le32(&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->overlay_last1)); - planb_dbdma_restart(&pb->planb_base->ch1); - } - } - pb->last_fr = pb->prev_last_fr; - pb->prev_last_fr = -999; - } - return; -} - -static void suspend_overlay(struct planb *pb) -{ - int fr = -1; - struct dbdma_cmd last; - - DEBUG("PlanB: suspend_overlay: %d\n", pb->suspend); - - if(pb->suspend++) - return; - if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) { - if(pb->last_fr == -2) { - fr = pb->prev_last_fr; - memcpy(&last, (void*)pb->last_cmd[fr], sizeof(last)); - tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0); - } - if(overlay_is_active(pb)) { - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - pb->suspended.overlay = 1; - pb->suspended.frame = fr; - memcpy(&pb->suspended.cmd, &last, sizeof(last)); - return; - } - } - pb->suspended.overlay = 0; - pb->suspended.frame = fr; - memcpy(&pb->suspended.cmd, &last, sizeof(last)); - return; -} - -static void resume_overlay(struct planb *pb) -{ - - DEBUG("PlanB: resume_overlay: %d\n", pb->suspend); - - if(pb->suspend > 1) - return; - if(pb->suspended.frame != -1) { - memcpy((void*)pb->last_cmd[pb->suspended.frame], - &pb->suspended.cmd, sizeof(pb->suspended.cmd)); - } - if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) { - goto finish; - } - if(pb->suspended.overlay) { - - DEBUG("PlanB: overlay being resumed\n"); - - st_le16 (&pb->ch1_cmd->command, DBDMA_NOP); - st_le16 (&pb->ch2_cmd->command, DBDMA_NOP); - /* Set command buffer addresses */ - st_le32(&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->overlay_last1)); - out_le32(&pb->planb_base->ch2.cmdptr, - virt_to_bus(pb->overlay_last2)); - /* Start the DMA controller */ - out_le32 (&pb->planb_base->ch2.control, - PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE)); - out_le32 (&pb->planb_base->ch1.control, - PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE)); - } else if(pb->suspended.frame != -1) { - out_le32(&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->last_cmd[pb->suspended.frame])); - out_le32 (&pb->planb_base->ch1.control, - PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE)); - } - -finish: - pb->suspend--; - wake_up_interruptible(&pb->suspendq); -} - -static void add_clip(struct planb *pb, struct video_clip *clip) -{ - volatile unsigned char *base; - int xc = clip->x, yc = clip->y; - int wc = clip->width, hc = clip->height; - int ww = pb->win.width, hw = pb->win.height; - int x, y, xtmp1, xtmp2; - - DEBUG("PlanB: clip %dx%d+%d+%d\n", wc, hc, xc, yc); - - if(xc < 0) { - wc += xc; - xc = 0; - } - if(yc < 0) { - hc += yc; - yc = 0; - } - if(xc + wc > ww) - wc = ww - xc; - if(wc <= 0) /* Nothing to do */ - return; - if(yc + hc > hw) - hc = hw - yc; - - for (y = yc; y < yc+hc; y++) { - xtmp1=xc>>3; - xtmp2=(xc+wc)>>3; - base = pb->mask + y*96; - if(xc != 0 || wc >= 8) - *(base + xtmp1) &= (unsigned char)(0x00ff & - (0xff00 >> (xc&7))); - for (x = xtmp1 + 1; x < xtmp2; x++) { - *(base + x) = 0; - } - if(xc < (ww & ~0x7)) - *(base + xtmp2) &= (unsigned char)(0x00ff >> - ((xc+wc) & 7)); - } - - return; -} - -static void fill_cmd_buff(struct planb *pb) -{ - int restore = 0; - volatile struct dbdma_cmd last; - - DEBUG("PlanB: fill_cmd_buff()\n"); - - if(pb->overlay_last1 != pb->ch1_cmd) { - restore = 1; - last = *(pb->overlay_last1); - } - memset ((void *) pb->ch1_cmd, 0, 2 * pb->tab_size - * sizeof(struct dbdma_cmd)); - cmd_buff (pb); - if(restore) - *(pb->overlay_last1) = last; - if(pb->suspended.overlay) { - unsigned long jump_addr = in_le32(&pb->overlay_last1->cmd_dep); - if(jump_addr != pb->ch1_cmd_phys) { - int i; - - DEBUG("PlanB: adjusting ch1's jump address\n"); - - for(i = 0; i < MAX_GBUFFERS; i++) { - if(pb->need_pre_capture[i]) { - if(jump_addr == virt_to_bus(pb->pre_cmd[i])) - goto found; - } else { - if(jump_addr == virt_to_bus(pb->cap_cmd[i])) - goto found; - } - } - - DEBUG("PlanB: not found...\n"); - - goto out; -found: - if(pb->need_pre_capture[i]) - out_le32(&pb->pre_cmd[i]->phy_addr, - virt_to_bus(pb->overlay_last1)); - else - out_le32(&pb->cap_cmd[i]->phy_addr, - virt_to_bus(pb->overlay_last1)); - } - } -out: - pb->cmd_buff_inited = 1; - - return; -} - -static void cmd_buff(struct planb *pb) -{ - int i, bpp, count, nlines, stepsize, interlace; - unsigned long base, jump, addr_com, addr_dep; - volatile struct dbdma_cmd *c1 = pb->ch1_cmd; - volatile struct dbdma_cmd *c2 = pb->ch2_cmd; - - interlace = pb->win.interlace; - bpp = pb->win.bpp; - count = (bpp * ((pb->win.x + pb->win.width > pb->win.swidth) ? - (pb->win.swidth - pb->win.x) : pb->win.width)); - nlines = ((pb->win.y + pb->win.height > pb->win.sheight) ? - (pb->win.sheight - pb->win.y) : pb->win.height); - - /* Do video in: */ - - /* Preamble commands: */ - addr_com = virt_to_bus(c1); - addr_dep = virt_to_bus(&c1->cmd_dep); - tab_cmd_dbdma(c1++, DBDMA_NOP, 0); - jump = virt_to_bus(c1+16); /* 14 by cmd_geo_setup() and 2 for padding */ - if((c1 = cmd_geo_setup(c1, pb->win.width, pb->win.height, interlace, - bpp, 1, pb)) == NULL) { - printk(KERN_WARNING "PlanB: encountered serious problems\n"); - tab_cmd_dbdma(pb->ch1_cmd + 1, DBDMA_STOP, 0); - tab_cmd_dbdma(pb->ch2_cmd + 1, DBDMA_STOP, 0); - return; - } - tab_cmd_store(c1++, addr_com, (unsigned)(DBDMA_NOP | BR_ALWAYS) << 16); - tab_cmd_store(c1++, addr_dep, jump); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel), - PLANB_SET(FIELD_SYNC)); - /* (1) wait for field sync to be set */ - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(ODD_FIELD)); - /* wait for field sync to be cleared */ - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0); - /* if not odd field, wait until field sync is set again */ - tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++; - /* assert ch_sync to ch2 */ - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control), - PLANB_SET(CH_SYNC)); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(DMA_ABORT)); - - base = (pb->frame_buffer_phys + pb->offset + pb->win.y * (pb->win.bpl - + pb->win.pad) + pb->win.x * bpp); - - if (interlace) { - stepsize = 2; - jump = virt_to_bus(c1 + (nlines + 1) / 2); - } else { - stepsize = 1; - jump = virt_to_bus(c1 + nlines); - } - - /* even field data: */ - for (i=0; i < nlines; i += stepsize, c1++) - tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, - count, base + i * (pb->win.bpl + pb->win.pad), jump); - - /* For non-interlaced, we use even fields only */ - if (!interlace) - goto cmd_tab_data_end; - - /* Resync to odd field */ - /* (2) wait for field sync to be set */ - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(ODD_FIELD)); - /* wait for field sync to be cleared */ - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0); - /* if not odd field, wait until field sync is set again */ - tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++; - /* assert ch_sync to ch2 */ - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control), - PLANB_SET(CH_SYNC)); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(DMA_ABORT)); - - /* odd field data: */ - jump = virt_to_bus(c1 + nlines / 2); - for (i=1; i < nlines; i += stepsize, c1++) - tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count, - base + i * (pb->win.bpl + pb->win.pad), jump); - - /* And jump back to the start */ -cmd_tab_data_end: - pb->overlay_last1 = c1; /* keep a pointer to the last command */ - tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch1_cmd)); - - /* Clipmask command buffer */ - - /* Preamble commands: */ - tab_cmd_dbdma(c2++, DBDMA_NOP, 0); - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel), - PLANB_SET(CH_SYNC)); - /* wait until ch1 asserts ch_sync */ - tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0); - /* clear ch_sync asserted by ch1 */ - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.control), - PLANB_CLR(CH_SYNC)); - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel), - PLANB_SET(FIELD_SYNC)); - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel), - PLANB_SET(ODD_FIELD)); - - /* jump to end of even field if appropriate */ - /* this points to (interlace)? pos. C: pos. B */ - jump = (interlace) ? virt_to_bus(c2 + (nlines + 1) / 2 + 2): - virt_to_bus(c2 + nlines + 2); - /* if odd field, skip over to odd field clipmasking */ - tab_cmd_dbdma(c2++, DBDMA_NOP | BR_IFSET, jump); - - /* even field mask: */ - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel), - PLANB_SET(DMA_ABORT)); - /* this points to pos. B */ - jump = (interlace) ? virt_to_bus(c2 + nlines + 1): - virt_to_bus(c2 + nlines); - base = virt_to_bus(pb->mask); - for (i=0; i < nlines; i += stepsize, c2++) - tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96, - base + i * 96, jump); - - /* For non-interlaced, we use only even fields */ - if(!interlace) - goto cmd_tab_mask_end; - - /* odd field mask: */ -/* C */ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel), - PLANB_SET(DMA_ABORT)); - /* this points to pos. B */ - jump = virt_to_bus(c2 + nlines / 2); - base = virt_to_bus(pb->mask); - for (i=1; i < nlines; i += 2, c2++) /* abort if set */ - tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96, - base + i * 96, jump); - - /* Inform channel 1 and jump back to start */ -cmd_tab_mask_end: - /* ok, I just realized this is kind of flawed. */ - /* this part is reached only after odd field clipmasking. */ - /* wanna clean up? */ - /* wait for field sync to be set */ - /* corresponds to fsync (1) of ch1 */ -/* B */ tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0); - /* restart ch1, meant to clear any dead bit or something */ - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control), - PLANB_CLR(RUN)); - tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control), - PLANB_SET(RUN)); - pb->overlay_last2 = c2; /* keep a pointer to the last command */ - /* start over even field clipmasking */ - tab_cmd_dbdma(c2, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch2_cmd)); - - eieio(); - return; -} - -/*********************************/ -/* grabdisplay support functions */ -/*********************************/ - -static int palette2fmt[] = { - 0, - PLANB_GRAY, - 0, - 0, - 0, - PLANB_COLOUR32, - PLANB_COLOUR15, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -}; - -#define PLANB_PALETTE_MAX 15 - -static inline int overlay_is_active(struct planb *pb) -{ - unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd); - unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr); - - return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys) - && (caddr < (pb->ch1_cmd_phys + size)) - && (caddr >= (unsigned)pb->ch1_cmd_phys); -} - -static int vgrab(struct planb *pb, struct video_mmap *mp) -{ - unsigned int fr = mp->frame; - unsigned int format; - - if(pb->rawbuf==NULL) { - int err; - if((err=grabbuf_alloc(pb))) - return err; - } - - IDEBUG("PlanB: grab %d: %dx%d(%u)\n", pb->grabbing, - mp->width, mp->height, fr); - - if(pb->grabbing >= MAX_GBUFFERS) - return -ENOBUFS; - if(fr > (MAX_GBUFFERS - 1) || fr < 0) - return -EINVAL; - if(mp->height <= 0 || mp->width <= 0) - return -EINVAL; - if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX) - return -EINVAL; - if((format = palette2fmt[mp->format]) == 0) - return -EINVAL; - if (mp->height * mp->width * format > PLANB_MAX_FBUF) /* format = bpp */ - return -EINVAL; - - planb_lock(pb); - if(mp->width != pb->gwidth[fr] || mp->height != pb->gheight[fr] || - format != pb->gfmt[fr] || (pb->gnorm_switch[fr])) { - int i; -#ifndef PLANB_GSCANLINE - unsigned int osize = pb->gwidth[fr] * pb->gheight[fr] - * pb->gfmt[fr]; - unsigned int nsize = mp->width * mp->height * format; -#endif - - IDEBUG("PlanB: gwidth = %d, gheight = %d, mp->format = %u\n", - mp->width, mp->height, mp->format); - -#ifndef PLANB_GSCANLINE - if(pb->gnorm_switch[fr]) - nsize = 0; - if (nsize < osize) { - for(i = pb->gbuf_idx[fr]; osize > 0; i++) { - memset((void *)pb->rawbuf[i], 0, PAGE_SIZE); - osize -= PAGE_SIZE; - } - } - for(i = pb->l_fr_addr_idx[fr]; i < pb->l_fr_addr_idx[fr] - + pb->lnum[fr]; i++) - memset((void *)pb->rawbuf[i], 0, PAGE_SIZE); -#else -/* XXX TODO */ -/* - if(pb->gnorm_switch[fr]) - memset((void *)pb->gbuffer[fr], 0, - pb->gbytes_per_line * pb->gheight[fr]); - else { - if(mp-> - for(i = 0; i < pb->gheight[fr]; i++) { - memset((void *)(pb->gbuffer[fr] - + pb->gbytes_per_line * i - } - } -*/ -#endif - pb->gwidth[fr] = mp->width; - pb->gheight[fr] = mp->height; - pb->gfmt[fr] = format; - pb->last_cmd[fr] = setup_grab_cmd(fr, pb); - planb_pre_capture(fr, pb->gfmt[fr], pb); /* gfmt = bpp */ - pb->need_pre_capture[fr] = 1; - pb->gnorm_switch[fr] = 0; - } else - pb->need_pre_capture[fr] = 0; - pb->frame_stat[fr] = GBUFFER_GRABBING; - if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) { - - IDEBUG("PlanB: ch1 inactive, initiating grabbing\n"); - - planb_dbdma_stop(&pb->planb_base->ch1); - if(pb->need_pre_capture[fr]) { - - IDEBUG("PlanB: padding pre-capture sequence\n"); - - out_le32 (&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->pre_cmd[fr])); - } else { - tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0); - tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0); - /* let's be on the safe side. here is not timing critical. */ - tab_cmd_dbdma((pb->cap_cmd[fr] + 1), DBDMA_NOP, 0); - out_le32 (&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->cap_cmd[fr])); - } - planb_dbdma_restart(&pb->planb_base->ch1); - pb->last_fr = fr; - } else { - int i; - - IDEBUG("PlanB: ch1 active, grabbing being queued\n"); - - if((pb->last_fr == -1) || ((pb->last_fr == -2) && - overlay_is_active(pb))) { - - IDEBUG("PlanB: overlay is active, grabbing defered\n"); - - tab_cmd_dbdma(pb->last_cmd[fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->ch1_cmd)); - if(pb->need_pre_capture[fr]) { - - IDEBUG("PlanB: padding pre-capture sequence\n"); - - tab_cmd_store(pb->pre_cmd[fr], - virt_to_bus(&pb->overlay_last1->cmd_dep), - virt_to_bus(pb->ch1_cmd)); - eieio(); - out_le32 (&pb->overlay_last1->cmd_dep, - virt_to_bus(pb->pre_cmd[fr])); - } else { - tab_cmd_store(pb->cap_cmd[fr], - virt_to_bus(&pb->overlay_last1->cmd_dep), - virt_to_bus(pb->ch1_cmd)); - tab_cmd_dbdma((pb->cap_cmd[fr] + 1), - DBDMA_NOP, 0); - eieio(); - out_le32 (&pb->overlay_last1->cmd_dep, - virt_to_bus(pb->cap_cmd[fr])); - } - for(i = 0; overlay_is_active(pb) && i < 999; i++) - IDEBUG("PlanB: waiting for overlay done\n"); - tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0); - pb->prev_last_fr = fr; - pb->last_fr = -2; - } else if(pb->last_fr == -2) { - - IDEBUG("PlanB: mixed mode detected, grabbing" - " will be done before activating overlay\n"); - - tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0); - if(pb->need_pre_capture[fr]) { - - IDEBUG("PlanB: padding pre-capture sequence\n"); - - tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->pre_cmd[fr])); - eieio(); - } else { - tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0); - if(pb->gwidth[pb->prev_last_fr] != - pb->gwidth[fr] - || pb->gheight[pb->prev_last_fr] != - pb->gheight[fr] - || pb->gfmt[pb->prev_last_fr] != - pb->gfmt[fr]) - tab_cmd_dbdma((pb->cap_cmd[fr] + 1), - DBDMA_NOP, 0); - else - tab_cmd_dbdma((pb->cap_cmd[fr] + 1), - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->cap_cmd[fr] + 16)); - tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->cap_cmd[fr])); - eieio(); - } - tab_cmd_dbdma(pb->last_cmd[fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->ch1_cmd)); - eieio(); - pb->prev_last_fr = fr; - pb->last_fr = -2; - } else { - - IDEBUG("PlanB: active grabbing session detected\n"); - - if(pb->need_pre_capture[fr]) { - - IDEBUG("PlanB: padding pre-capture sequence\n"); - - tab_cmd_dbdma(pb->last_cmd[pb->last_fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->pre_cmd[fr])); - eieio(); - } else { - tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0); - tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0); - if(pb->gwidth[pb->last_fr] != pb->gwidth[fr] - || pb->gheight[pb->last_fr] != - pb->gheight[fr] - || pb->gfmt[pb->last_fr] != - pb->gfmt[fr]) - tab_cmd_dbdma((pb->cap_cmd[fr] + 1), - DBDMA_NOP, 0); - else - tab_cmd_dbdma((pb->cap_cmd[fr] + 1), - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->cap_cmd[fr] + 16)); - tab_cmd_dbdma(pb->last_cmd[pb->last_fr], - DBDMA_NOP | BR_ALWAYS, - virt_to_bus(pb->cap_cmd[fr])); - eieio(); - } - pb->last_fr = fr; - } - if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) { - - IDEBUG("PlanB: became inactive in the mean time..." - "reactivating\n"); - - planb_dbdma_stop(&pb->planb_base->ch1); - out_le32 (&pb->planb_base->ch1.cmdptr, - virt_to_bus(pb->cap_cmd[fr])); - planb_dbdma_restart(&pb->planb_base->ch1); - } - } - pb->grabbing++; - planb_unlock(pb); - - return 0; -} - -static void planb_pre_capture(int fr, int bpp, struct planb *pb) -{ - volatile struct dbdma_cmd *c1 = pb->pre_cmd[fr]; - int interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0; - - tab_cmd_dbdma(c1++, DBDMA_NOP, 0); - if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace, - bpp, 0, pb)) == NULL) { - printk(KERN_WARNING "PlanB: encountered some problems\n"); - tab_cmd_dbdma(pb->pre_cmd[fr] + 1, DBDMA_STOP, 0); - return; - } - /* Sync to even field */ - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel), - PLANB_SET(FIELD_SYNC)); - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(ODD_FIELD)); - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0); - tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++; - tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(DMA_ABORT)); - /* For non-interlaced, we use even fields only */ - if (pb->gheight[fr] <= pb->maxlines/2) - goto cmd_tab_data_end; - /* Sync to odd field */ - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(ODD_FIELD)); - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0); - tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++; - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(DMA_ABORT)); -cmd_tab_data_end: - tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->cap_cmd[fr])); - - eieio(); -} - -static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb) -{ - int i, bpp, count, nlines, stepsize, interlace; -#ifdef PLANB_GSCANLINE - int scanline; -#else - int nlpp, leftover1; - unsigned long base; -#endif - unsigned long jump; - int pagei; - volatile struct dbdma_cmd *c1; - volatile struct dbdma_cmd *jump_addr; - - c1 = pb->cap_cmd[fr]; - interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0; - bpp = pb->gfmt[fr]; /* gfmt = bpp */ - count = bpp * pb->gwidth[fr]; - nlines = pb->gheight[fr]; -#ifdef PLANB_GSCANLINE - scanline = pb->gbytes_per_line; -#else - pb->lsize[fr] = count; - pb->lnum[fr] = 0; -#endif - - /* Do video in: */ - - /* Preamble commands: */ - tab_cmd_dbdma(c1++, DBDMA_NOP, 0); - tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(c1 + 16)); c1++; - if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace, - bpp, 0, pb)) == NULL) { - printk(KERN_WARNING "PlanB: encountered serious problems\n"); - tab_cmd_dbdma(pb->cap_cmd[fr] + 1, DBDMA_STOP, 0); - return (pb->cap_cmd[fr] + 2); - } - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel), - PLANB_SET(FIELD_SYNC)); - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(ODD_FIELD)); - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0); - tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++; - tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(DMA_ABORT)); - - if (interlace) { - stepsize = 2; - jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2; - } else { - stepsize = 1; - jump_addr = c1 + TAB_FACTOR * nlines; - } - jump = virt_to_bus(jump_addr); - - /* even field data: */ - - pagei = pb->gbuf_idx[fr]; -#ifdef PLANB_GSCANLINE - for (i = 0; i < nlines; i += stepsize) { - tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, - virt_to_bus(pb->rawbuf[pagei - + i * scanline / PAGE_SIZE]), jump); - } -#else - i = 0; - leftover1 = 0; - do { - int j; - - base = virt_to_bus(pb->rawbuf[pagei]); - nlpp = (PAGE_SIZE - leftover1) / count / stepsize; - for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++) - tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, - count, base + count * j * stepsize + leftover1, jump); - if(i < nlines) { - int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1; - - if(lov0 == 0) - leftover1 = 0; - else { - if(lov0 >= count) { - tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base - + count * nlpp * stepsize + leftover1, jump); - } else { - pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei] - + count * nlpp * stepsize + leftover1; - pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1; - pb->l_to_next_size[fr][pb->lnum[fr]] = count - lov0; - tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, - virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr] - + pb->lnum[fr]]), jump); - if(++pb->lnum[fr] > MAX_LNUM) - pb->lnum[fr]--; - } - leftover1 = count * stepsize - lov0; - i += stepsize; - } - } - pagei++; - } while(i < nlines); - tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump); - c1 = jump_addr; -#endif /* PLANB_GSCANLINE */ - - /* For non-interlaced, we use even fields only */ - if (!interlace) - goto cmd_tab_data_end; - - /* Sync to odd field */ - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0); - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(ODD_FIELD)); - tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0); - tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++; - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel), - PLANB_SET(DMA_ABORT)); - - /* odd field data: */ - jump_addr = c1 + TAB_FACTOR * nlines / 2; - jump = virt_to_bus(jump_addr); -#ifdef PLANB_GSCANLINE - for (i = 1; i < nlines; i += stepsize) { - tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, - virt_to_bus(pb->rawbuf[pagei - + i * scanline / PAGE_SIZE]), jump); - } -#else - i = 1; - leftover1 = 0; - pagei = pb->gbuf_idx[fr]; - if(nlines <= 1) - goto skip; - do { - int j; - - base = virt_to_bus(pb->rawbuf[pagei]); - nlpp = (PAGE_SIZE - leftover1) / count / stepsize; - if(leftover1 >= count) { - tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count, - base + leftover1 - count, jump); - i += stepsize; - } - for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++) - tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count, - base + count * (j * stepsize + 1) + leftover1, jump); - if(i < nlines) { - int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1; - - if(lov0 == 0) - leftover1 = 0; - else { - if(lov0 > count) { - pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei] - + count * (nlpp * stepsize + 1) + leftover1; - pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1; - pb->l_to_next_size[fr][pb->lnum[fr]] = count * stepsize - - lov0; - tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, - virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr] - + pb->lnum[fr]]), jump); - if(++pb->lnum[fr] > MAX_LNUM) - pb->lnum[fr]--; - i += stepsize; - } - leftover1 = count * stepsize - lov0; - } - } - pagei++; - } while(i < nlines); -skip: - tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump); - c1 = jump_addr; -#endif /* PLANB_GSCANLINE */ - -cmd_tab_data_end: - tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->intr_stat), - (fr << 9) | PLANB_FRM_IRQ | PLANB_GEN_IRQ); - /* stop it */ - tab_cmd_dbdma(c1, DBDMA_STOP, 0); - - eieio(); - return c1; -} - -static void planb_irq(int irq, void *dev_id, struct pt_regs * regs) -{ - unsigned int stat, astat; - struct planb *pb = (struct planb *)dev_id; - - IDEBUG("PlanB: planb_irq()\n"); - - /* get/clear interrupt status bits */ - eieio(); - stat = in_le32(&pb->planb_base->intr_stat); - astat = stat & pb->intr_mask; - out_le32(&pb->planb_base->intr_stat, PLANB_FRM_IRQ - & ~astat & stat & ~PLANB_GEN_IRQ); - IDEBUG("PlanB: stat = %X, astat = %X\n", stat, astat); - - if(astat & PLANB_FRM_IRQ) { - unsigned int fr = stat >> 9; -#ifndef PLANB_GSCANLINE - int i; -#endif - IDEBUG("PlanB: PLANB_FRM_IRQ\n"); - - pb->gcount++; - - IDEBUG("PlanB: grab %d: fr = %d, gcount = %d\n", - pb->grabbing, fr, pb->gcount); -#ifndef PLANB_GSCANLINE - IDEBUG("PlanB: %d * %d bytes are being copied over\n", - pb->lnum[fr], pb->lsize[fr]); - for(i = 0; i < pb->lnum[fr]; i++) { - int first = pb->lsize[fr] - pb->l_to_next_size[fr][i]; - - memcpy(pb->l_to_addr[fr][i], - pb->rawbuf[pb->l_fr_addr_idx[fr] + i], - first); - memcpy(pb->rawbuf[pb->l_to_next_idx[fr][i]], - pb->rawbuf[pb->l_fr_addr_idx[fr] + i] + first, - pb->l_to_next_size[fr][i]); - } -#endif - pb->frame_stat[fr] = GBUFFER_DONE; - pb->grabbing--; - wake_up_interruptible(&pb->capq); - return; - } - /* incorrect interrupts? */ - pb->intr_mask = PLANB_CLR_IRQ; - out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ); - printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts" - " unconditionally\n"); -} - -/******************************* - * Device Operations functions * - *******************************/ - -static int planb_open(struct video_device *dev, int mode) -{ - struct planb *pb = (struct planb *)dev; - - if (pb->user == 0) { - int err; - if((err = planb_prepare_open(pb)) != 0) - return err; - } - pb->user++; - - DEBUG("PlanB: device opened\n"); - - MOD_INC_USE_COUNT; - return 0; -} - -static void planb_close(struct video_device *dev) -{ - struct planb *pb = (struct planb *)dev; - - if(pb->user < 1) /* ??? */ - return; - planb_lock(pb); - if (pb->user == 1) { - if (pb->overlay) { - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - pb->overlay = 0; - } - planb_prepare_close(pb); - } - pb->user--; - planb_unlock(pb); - - DEBUG("PlanB: device closed\n"); - - MOD_DEC_USE_COUNT; -} - -static long planb_read(struct video_device *v, char *buf, unsigned long count, - int nonblock) -{ - DEBUG("planb: read request\n"); - return -EINVAL; -} - -static long planb_write(struct video_device *v, const char *buf, - unsigned long count, int nonblock) -{ - DEBUG("planb: write request\n"); - return -EINVAL; -} - -static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct planb *pb=(struct planb *)dev; - - switch (cmd) - { - case VIDIOCGCAP: - { - struct video_capability b; - - DEBUG("PlanB: IOCTL VIDIOCGCAP\n"); - - strcpy (b.name, pb->video_dev.name); - b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | - VID_TYPE_FRAMERAM | VID_TYPE_SCALES | - VID_TYPE_CAPTURE; - b.channels = 2; /* composite & svhs */ - b.audios = 0; - b.maxwidth = PLANB_MAXPIXELS; - b.maxheight = PLANB_MAXLINES; - b.minwidth = 32; /* wild guess */ - b.minheight = 32; - if (copy_to_user(arg,&b,sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCSFBUF: - { - struct video_buffer v; - unsigned short bpp; - unsigned int fmt; - - DEBUG("PlanB: IOCTL VIDIOCSFBUF\n"); - - if (!capable(CAP_SYS_ADMIN) - || !capable(CAP_SYS_RAWIO)) - return -EPERM; - if (copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - planb_lock(pb); - switch(v.depth) { - case 8: - bpp = 1; - fmt = PLANB_GRAY; - break; - case 15: - case 16: - bpp = 2; - fmt = PLANB_COLOUR15; - break; - case 24: - case 32: - bpp = 4; - fmt = PLANB_COLOUR32; - break; - default: - planb_unlock(pb); - return -EINVAL; - } - if (bpp * v.width > v.bytesperline) { - planb_unlock(pb); - return -EINVAL; - } - pb->win.bpp = bpp; - pb->win.color_fmt = fmt; - pb->frame_buffer_phys = (unsigned long) v.base; - pb->win.sheight = v.height; - pb->win.swidth = v.width; - pb->picture.depth = pb->win.depth = v.depth; - pb->win.bpl = pb->win.bpp * pb->win.swidth; - pb->win.pad = v.bytesperline - pb->win.bpl; - - DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d," - " bpl %d (+ %d)\n", v.base, v.width,v.height, - pb->win.bpp, pb->win.bpl, pb->win.pad); - - pb->cmd_buff_inited = 0; - if(pb->overlay) { - suspend_overlay(pb); - fill_cmd_buff(pb); - resume_overlay(pb); - } - planb_unlock(pb); - return 0; - } - case VIDIOCGFBUF: - { - struct video_buffer v; - - DEBUG("PlanB: IOCTL VIDIOCGFBUF\n"); - - v.base = (void *)pb->frame_buffer_phys; - v.height = pb->win.sheight; - v.width = pb->win.swidth; - v.depth = pb->win.depth; - v.bytesperline = pb->win.bpl + pb->win.pad; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - { - int i; - - if(copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - if(i==0) { - DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n"); - - if (!(pb->overlay)) - return 0; - planb_lock(pb); - pb->overlay = 0; - overlay_stop(pb); - planb_unlock(pb); - } else { - DEBUG("PlanB: IOCTL VIDIOCCAPTURE Start\n"); - - if (pb->frame_buffer_phys == 0 || - pb->win.width == 0 || - pb->win.height == 0) - return -EINVAL; - if (pb->overlay) - return 0; - planb_lock(pb); - pb->overlay = 1; - if(!(pb->cmd_buff_inited)) - fill_cmd_buff(pb); - overlay_start(pb); - planb_unlock(pb); - } - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel v; - - DEBUG("PlanB: IOCTL VIDIOCGCHAN\n"); - - if(copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - v.flags = 0; - v.tuners = 0; - v.type = VIDEO_TYPE_CAMERA; - v.norm = pb->win.norm; - switch(v.channel) - { - case 0: - strcpy(v.name,"Composite"); - break; - case 1: - strcpy(v.name,"SVHS"); - break; - default: - return -EINVAL; - break; - } - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel v; - - DEBUG("PlanB: IOCTL VIDIOCSCHAN\n"); - - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - - if (v.norm != pb->win.norm) { - int i, maxlines; - - switch (v.norm) - { - case VIDEO_MODE_PAL: - case VIDEO_MODE_SECAM: - maxlines = PLANB_MAXLINES; - break; - case VIDEO_MODE_NTSC: - maxlines = PLANB_NTSC_MAXLINES; - break; - default: - return -EINVAL; - break; - } - planb_lock(pb); - /* empty the grabbing queue */ - while(pb->grabbing) - interruptible_sleep_on(&pb->capq); - pb->maxlines = maxlines; - pb->win.norm = v.norm; - /* Stop overlay if running */ - suspend_overlay(pb); - for(i = 0; i < MAX_GBUFFERS; i++) - pb->gnorm_switch[i] = 1; - /* I know it's an overkill, but.... */ - fill_cmd_buff(pb); - /* ok, now init it accordingly */ - saa_init_regs (pb); - /* restart overlay if it was running */ - resume_overlay(pb); - planb_unlock(pb); - } - - switch(v.channel) - { - case 0: /* Composite */ - saa_set (SAA7196_IOCC, - ((saa_regs[pb->win.norm][SAA7196_IOCC] & - ~7) | 3), pb); - break; - case 1: /* SVHS */ - saa_set (SAA7196_IOCC, - ((saa_regs[pb->win.norm][SAA7196_IOCC] & - ~7) | 4), pb); - break; - default: - return -EINVAL; - break; - } - - return 0; - } - case VIDIOCGPICT: - { - struct video_picture vp = pb->picture; - - DEBUG("PlanB: IOCTL VIDIOCGPICT\n"); - - switch(pb->win.color_fmt) { - case PLANB_GRAY: - vp.palette = VIDEO_PALETTE_GREY; - case PLANB_COLOUR15: - vp.palette = VIDEO_PALETTE_RGB555; - break; - case PLANB_COLOUR32: - vp.palette = VIDEO_PALETTE_RGB32; - break; - default: - vp.palette = 0; - break; - } - - if(copy_to_user(arg,&vp,sizeof(vp))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture vp; - - DEBUG("PlanB: IOCTL VIDIOCSPICT\n"); - - if(copy_from_user(&vp,arg,sizeof(vp))) - return -EFAULT; - pb->picture = vp; - /* Should we do sanity checks here? */ - saa_set (SAA7196_BRIG, (unsigned char) - ((pb->picture.brightness) >> 8), pb); - saa_set (SAA7196_HUEC, (unsigned char) - ((pb->picture.hue) >> 8) ^ 0x80, pb); - saa_set (SAA7196_CSAT, (unsigned char) - ((pb->picture.colour) >> 9), pb); - saa_set (SAA7196_CONT, (unsigned char) - ((pb->picture.contrast) >> 9), pb); - - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - struct video_clip clip; - int i; - - DEBUG("PlanB: IOCTL VIDIOCSWIN\n"); - - if(copy_from_user(&vw,arg,sizeof(vw))) - return -EFAULT; - - planb_lock(pb); - /* Stop overlay if running */ - suspend_overlay(pb); - pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0; - if (pb->win.x != vw.x || - pb->win.y != vw.y || - pb->win.width != vw.width || - pb->win.height != vw.height || - !pb->cmd_buff_inited) { - pb->win.x = vw.x; - pb->win.y = vw.y; - pb->win.width = vw.width; - pb->win.height = vw.height; - fill_cmd_buff(pb); - } - /* Reset clip mask */ - memset ((void *) pb->mask, 0xff, (pb->maxlines - * ((PLANB_MAXPIXELS + 7) & ~7)) / 8); - /* Add any clip rects */ - for (i = 0; i < vw.clipcount; i++) { - if (copy_from_user(&clip, vw.clips + i, - sizeof(struct video_clip))) - return -EFAULT; - add_clip(pb, &clip); - } - /* restart overlay if it was running */ - resume_overlay(pb); - planb_unlock(pb); - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - - DEBUG("PlanB: IOCTL VIDIOCGWIN\n"); - - vw.x=pb->win.x; - vw.y=pb->win.y; - vw.width=pb->win.width; - vw.height=pb->win.height; - vw.chromakey=0; - vw.flags=0; - if(pb->win.interlace) - vw.flags|=VIDEO_WINDOW_INTERLACE; - if(copy_to_user(arg,&vw,sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCSYNC: { - int i; - - IDEBUG("PlanB: IOCTL VIDIOCSYNC\n"); - - if(copy_from_user((void *)&i,arg,sizeof(int))) - return -EFAULT; - - IDEBUG("PlanB: sync to frame %d\n", i); - - if(i > (MAX_GBUFFERS - 1) || i < 0) - return -EINVAL; -chk_grab: - switch (pb->frame_stat[i]) { - case GBUFFER_UNUSED: - return -EINVAL; - case GBUFFER_GRABBING: - IDEBUG("PlanB: waiting for grab" - " done (%d)\n", i); - interruptible_sleep_on(&pb->capq); - if(signal_pending(current)) - return -EINTR; - goto chk_grab; - case GBUFFER_DONE: - pb->frame_stat[i] = GBUFFER_UNUSED; - break; - } - return 0; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - volatile unsigned int status; - - IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n"); - - if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm))) - return -EFAULT; - status = pb->frame_stat[vm.frame]; - if (status != GBUFFER_UNUSED) - return -EBUSY; - - return vgrab(pb, &vm); - } - - case VIDIOCGMBUF: - { - int i; - struct video_mbuf vm; - - DEBUG("PlanB: IOCTL VIDIOCGMBUF\n"); - - memset(&vm, 0 , sizeof(vm)); - vm.size = PLANB_MAX_FBUF * MAX_GBUFFERS; - vm.frames = MAX_GBUFFERS; - for(i = 0; i= SAA7196_NUMREGS) - return -EINVAL; - preg.val = saa_regs[pb->win.norm][preg.addr]; - if(copy_to_user((void *)arg, (void *)&preg, - sizeof(preg))) - return -EFAULT; - return 0; - } - - case PLANBIOCSSAAREGS: - { - struct planb_saa_regs preg; - - DEBUG("PlanB: IOCTL PLANBIOCSSAAREGS\n"); - - if(copy_from_user(&preg, arg, sizeof(preg))) - return -EFAULT; - if(preg.addr >= SAA7196_NUMREGS) - return -EINVAL; - saa_set (preg.addr, preg.val, pb); - return 0; - } - - case PLANBIOCGSTAT: - { - struct planb_stat_regs pstat; - - DEBUG("PlanB: IOCTL PLANBIOCGSTAT\n"); - - pstat.ch1_stat = in_le32(&pb->planb_base->ch1.status); - pstat.ch2_stat = in_le32(&pb->planb_base->ch2.status); - pstat.saa_stat0 = saa_status(0, pb); - pstat.saa_stat1 = saa_status(1, pb); - - if(copy_to_user((void *)arg, (void *)&pstat, - sizeof(pstat))) - return -EFAULT; - return 0; - } - - case PLANBIOCSMODE: { - int v; - - DEBUG("PlanB: IOCTL PLANBIOCSMODE\n"); - - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - - switch(v) - { - case PLANB_TV_MODE: - saa_set (SAA7196_STDC, - (saa_regs[pb->win.norm][SAA7196_STDC] & - 0x7f), pb); - break; - case PLANB_VTR_MODE: - saa_set (SAA7196_STDC, - (saa_regs[pb->win.norm][SAA7196_STDC] | - 0x80), pb); - break; - default: - return -EINVAL; - break; - } - pb->win.mode = v; - return 0; - } - case PLANBIOCGMODE: { - int v=pb->win.mode; - - DEBUG("PlanB: IOCTL PLANBIOCGMODE\n"); - - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } -#ifdef PLANB_GSCANLINE - case PLANBG_GRAB_BPL: { - int v=pb->gbytes_per_line; - - DEBUG("PlanB: IOCTL PLANBG_GRAB_BPL\n"); - - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } -#endif /* PLANB_GSCANLINE */ - case PLANB_INTR_DEBUG: { - int i; - - DEBUG("PlanB: IOCTL PLANB_INTR_DEBUG\n"); - - if(copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - - /* avoid hang ups all together */ - for (i = 0; i < MAX_GBUFFERS; i++) { - if(pb->frame_stat[i] == GBUFFER_GRABBING) { - pb->frame_stat[i] = GBUFFER_DONE; - } - } - if(pb->grabbing) - pb->grabbing--; - wake_up_interruptible(&pb->capq); - return 0; - } - case PLANB_INV_REGS: { - int i; - struct planb_any_regs any; - - DEBUG("PlanB: IOCTL PLANB_INV_REGS\n"); - - if(copy_from_user(&any, arg, sizeof(any))) - return -EFAULT; - if(any.offset < 0 || any.offset + any.bytes > 0x400) - return -EINVAL; - if(any.bytes > 128) - return -EINVAL; - for (i = 0; i < any.bytes; i++) { - any.data[i] = - in_8((unsigned char *)pb->planb_base - + any.offset + i); - } - if(copy_to_user(arg,&any,sizeof(any))) - return -EFAULT; - return 0; - } - default: - { - DEBUG("PlanB: Unimplemented IOCTL\n"); - return -ENOIOCTLCMD; - } - /* Some IOCTLs are currently unsupported on PlanB */ - case VIDIOCGTUNER: { - DEBUG("PlanB: IOCTL VIDIOCGTUNER\n"); - goto unimplemented; } - case VIDIOCSTUNER: { - DEBUG("PlanB: IOCTL VIDIOCSTUNER\n"); - goto unimplemented; } - case VIDIOCSFREQ: { - DEBUG("PlanB: IOCTL VIDIOCSFREQ\n"); - goto unimplemented; } - case VIDIOCGFREQ: { - DEBUG("PlanB: IOCTL VIDIOCGFREQ\n"); - goto unimplemented; } - case VIDIOCKEY: { - DEBUG("PlanB: IOCTL VIDIOCKEY\n"); - goto unimplemented; } - case VIDIOCSAUDIO: { - DEBUG("PlanB: IOCTL VIDIOCSAUDIO\n"); - goto unimplemented; } - case VIDIOCGAUDIO: { - DEBUG("PlanB: IOCTL VIDIOCGAUDIO\n"); - goto unimplemented; } -unimplemented: - DEBUG(" Unimplemented\n"); - return -ENOIOCTLCMD; - } - return 0; -} - -static int planb_mmap(struct video_device *dev, const char *adr, unsigned long size) -{ - int i; - struct planb *pb = (struct planb *)dev; - unsigned long start = (unsigned long)adr; - - if (size > MAX_GBUFFERS * PLANB_MAX_FBUF) - return -EINVAL; - if (!pb->rawbuf) { - int err; - if((err=grabbuf_alloc(pb))) - return err; - } - for (i = 0; i < pb->rawbuf_size; i++) { - if (remap_page_range(start, virt_to_phys((void *)pb->rawbuf[i]), - PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start += PAGE_SIZE; - if (size <= PAGE_SIZE) - break; - size -= PAGE_SIZE; - } - return 0; -} - -/* This gets called upon device registration */ -/* we could do some init here */ -static int planb_init_done(struct video_device *dev) -{ - return 0; -} - -static struct video_device planb_template= -{ - PLANB_DEVICE_NAME, - VID_TYPE_OVERLAY, - VID_HARDWARE_PLANB, - planb_open, - planb_close, - planb_read, - planb_write, -#if LINUX_VERSION_CODE >= 0x020100 - NULL, /* poll */ -#endif - planb_ioctl, - planb_mmap, /* mmap? */ - planb_init_done, - NULL, /* pointer to private data */ - 0, - 0 -}; - -static int init_planb(struct planb *pb) -{ - unsigned char saa_rev; - int i, result; - unsigned long flags; - - memset ((void *) &pb->win, 0, sizeof (struct planb_window)); - /* Simple sanity check */ - if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) { - printk(KERN_ERR "PlanB: Option(s) invalid\n"); - return -2; - } - pb->win.norm = def_norm; - pb->win.mode = PLANB_TV_MODE; /* TV mode */ - pb->win.interlace=1; - pb->win.x=0; - pb->win.y=0; - pb->win.width=768; /* 640 */ - pb->win.height=576; /* 480 */ - pb->maxlines=576; -#if 0 - btv->win.cropwidth=768; /* 640 */ - btv->win.cropheight=576; /* 480 */ - btv->win.cropx=0; - btv->win.cropy=0; -#endif - pb->win.pad=0; - pb->win.bpp=4; - pb->win.depth=32; - pb->win.color_fmt=PLANB_COLOUR32; - pb->win.bpl=1024*pb->win.bpp; - pb->win.swidth=1024; - pb->win.sheight=768; -#ifdef PLANB_GSCANLINE - if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE - || (pb->gbytes_per_line <= 0)) - return -3; - else { - /* page align pb->gbytes_per_line for DMA purpose */ - for(i = PAGE_SIZE; pb->gbytes_per_line < (i>>1);) - i>>=1; - pb->gbytes_per_line = i; - } -#endif - pb->tab_size = PLANB_MAXLINES + 40; - pb->suspend = 0; - pb->lock = 0; - init_waitqueue_head(&pb->lockq); - pb->ch1_cmd = 0; - pb->ch2_cmd = 0; - pb->mask = 0; - pb->priv_space = 0; - pb->offset = 0; - pb->user = 0; - pb->overlay = 0; - init_waitqueue_head(&pb->suspendq); - pb->cmd_buff_inited = 0; - pb->frame_buffer_phys = 0; - - /* Reset DMA controllers */ - planb_dbdma_stop(&pb->planb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - - saa_rev = (saa_status(0, pb) & 0xf0) >> 4; - printk(KERN_INFO "PlanB: SAA7196 video processor rev. %d\n", saa_rev); - /* Initialize the SAA registers in memory and on chip */ - saa_init_regs (pb); - - /* clear interrupt mask */ - pb->intr_mask = PLANB_CLR_IRQ; - - save_flags(flags); cli(); - result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb); - if (result < 0) { - if (result==-EINVAL) - printk(KERN_ERR "PlanB: Bad irq number (%d) " - "or handler\n", (int)pb->irq); - else if (result==-EBUSY) - printk(KERN_ERR "PlanB: I don't know why, " - "but IRQ %d is busy\n", (int)pb->irq); - restore_flags(flags); - return result; - } - disable_irq(pb->irq); - restore_flags(flags); - - /* Now add the template and register the device unit. */ - memcpy(&pb->video_dev,&planb_template,sizeof(planb_template)); - - pb->picture.brightness=0x90<<8; - pb->picture.contrast = 0x70 << 8; - pb->picture.colour = 0x70<<8; - pb->picture.hue = 0x8000; - pb->picture.whiteness = 0; - pb->picture.depth = pb->win.depth; - - pb->frame_stat=NULL; - init_waitqueue_head(&pb->capq); - for(i=0; igbuf_idx[i] = PLANB_MAX_FBUF * i / PAGE_SIZE; - pb->gwidth[i]=0; - pb->gheight[i]=0; - pb->gfmt[i]=0; - pb->cap_cmd[i]=NULL; -#ifndef PLANB_GSCANLINE - pb->l_fr_addr_idx[i] = MAX_GBUFFERS * (PLANB_MAX_FBUF - / PAGE_SIZE + 1) + MAX_LNUM * i; - pb->lsize[i] = 0; - pb->lnum[i] = 0; -#endif - } - pb->rawbuf=NULL; - pb->grabbing=0; - - /* enable interrupts */ - out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ); - pb->intr_mask = PLANB_FRM_IRQ; - enable_irq(pb->irq); - - if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER)<0) - return -1; - - return 0; -} - -/* - * Scan for a PlanB controller, request the irq and map the io memory - */ - -static int find_planb(void) -{ - struct planb *pb; - struct device_node *planb_devices; - unsigned char dev_fn, confreg, bus; - unsigned int old_base, new_base; - unsigned int irq; - struct pci_dev *pdev; - - if (_machine != _MACH_Pmac) - return 0; - - planb_devices = find_devices("planb"); - if (planb_devices == 0) { - planb_num=0; - printk(KERN_WARNING "PlanB: no device found!\n"); - return planb_num; - } - - if (planb_devices->next != NULL) - printk(KERN_ERR "Warning: only using first PlanB device!\n"); - pb = &planbs[0]; - planb_num = 1; - - if (planb_devices->n_addrs != 1) { - printk (KERN_WARNING "PlanB: expecting 1 address for planb " - "(got %d)", planb_devices->n_addrs); - return 0; - } - - if (planb_devices->n_intrs == 0) { - printk(KERN_WARNING "PlanB: no intrs for device %s\n", - planb_devices->full_name); - return 0; - } else { - irq = planb_devices->intrs[0].line; - } - - /* Initialize PlanB's PCI registers */ - - /* There is a bug with the way OF assigns addresses - to the devices behind the chaos bridge. - control needs only 0x1000 of space, but decodes only - the upper 16 bits. It therefore occupies a full 64K. - OF assigns the planb controller memory within this space; - so we need to change that here in order to access planb. */ - - /* We remap to 0xf1000000 in hope that nobody uses it ! */ - - bus = (planb_devices->addrs[0].space >> 16) & 0xff; - dev_fn = (planb_devices->addrs[0].space >> 8) & 0xff; - confreg = planb_devices->addrs[0].space & 0xff; - old_base = planb_devices->addrs[0].address; - new_base = 0xf1000000; - - DEBUG("PlanB: Found on bus %d, dev %d, func %d, " - "membase 0x%x (base reg. 0x%x)\n", - bus, PCI_SLOT(dev_fn), PCI_FUNC(dev_fn), old_base, confreg); - - pdev = pci_find_slot (bus, dev_fn); - if (!pdev) { - printk(KERN_ERR "cannot find slot\n"); - /* XXX handle error */ - } - - /* Enable response in memory space, bus mastering, - use memory write and invalidate */ - pci_write_config_word (pdev, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_INVALIDATE); - /* Set PCI Cache line size & latency timer */ - pci_write_config_byte (pdev, PCI_CACHE_LINE_SIZE, 0x8); - pci_write_config_byte (pdev, PCI_LATENCY_TIMER, 0x40); - - /* Set the new base address */ - pci_write_config_dword (pdev, confreg, new_base); - - planb_regs = (volatile struct planb_registers *) - ioremap (new_base, 0x400); - pb->planb_base = planb_regs; - pb->planb_base_phys = (struct planb_registers *)new_base; - pb->irq = irq; - - return planb_num; -} - -static void release_planb(void) -{ - int i; - struct planb *pb; - - for (i=0;iplanb_base->ch2); - planb_dbdma_stop(&pb->planb_base->ch1); - - /* clear and free interrupts */ - pb->intr_mask = PLANB_CLR_IRQ; - out_le32 (&pb->planb_base->intr_stat, PLANB_CLR_IRQ); - free_irq(pb->irq, pb); - - /* make sure all allocated memory are freed */ - planb_prepare_close(pb); - - printk(KERN_INFO "PlanB: unregistering with v4l\n"); - video_unregister_device(&pb->video_dev); - - /* note that iounmap() does nothing on the PPC right now */ - iounmap ((void *)pb->planb_base); - } -} - -#ifdef MODULE - -int init_module(void) -{ -#else -int __init init_planbs(struct video_init *unused) -{ -#endif - int i; - - if (find_planb()<=0) - return -EIO; - - for (i=0; i -#include "saa7196.h" -#endif /* __KERNEL__ */ - -#define PLANB_DEVICE_NAME "Apple PlanB Video-In" -#define PLANB_REV "1.0" - -#ifdef __KERNEL__ -//#define PLANB_GSCANLINE /* use this if apps have the notion of */ - /* grab buffer scanline */ -/* This should be safe for both PAL and NTSC */ -#define PLANB_MAXPIXELS 768 -#define PLANB_MAXLINES 576 -#define PLANB_NTSC_MAXLINES 480 - -/* Uncomment your preferred norm ;-) */ -#define PLANB_DEF_NORM VIDEO_MODE_PAL -//#define PLANB_DEF_NORM VIDEO_MODE_NTSC -//#define PLANB_DEF_NORM VIDEO_MODE_SECAM - -/* fields settings */ -#define PLANB_GRAY 0x1 /* 8-bit mono? */ -#define PLANB_COLOUR15 0x2 /* 16-bit mode */ -#define PLANB_COLOUR32 0x4 /* 32-bit mode */ -#define PLANB_CLIPMASK 0x8 /* hardware clipmasking */ - -/* misc. flags for PlanB DMA operation */ -#define CH_SYNC 0x1 /* synchronize channels (set by ch1; - cleared by ch2) */ -#define FIELD_SYNC 0x2 /* used for the start of each field - (0 -> 1 -> 0 for ch1; 0 -> 1 for ch2) */ -#define EVEN_FIELD 0x0 /* even field is detected if unset */ -#define DMA_ABORT 0x2 /* error or just out of sync if set */ -#define ODD_FIELD 0x4 /* odd field is detected if set */ - -/* for capture operations */ -#define MAX_GBUFFERS 2 -/* note PLANB_MAX_FBUF must be divisible by PAGE_SIZE */ -#ifdef PLANB_GSCANLINE -#define PLANB_MAX_FBUF 0x240000 /* 576 * 1024 * 4 */ -#define TAB_FACTOR (1) -#else -#define PLANB_MAX_FBUF 0x1b0000 /* 576 * 768 * 4 */ -#define TAB_FACTOR (2) -#endif -#endif /* __KERNEL__ */ - -struct planb_saa_regs { - unsigned char addr; - unsigned char val; -}; - -struct planb_stat_regs { - unsigned int ch1_stat; - unsigned int ch2_stat; - unsigned char saa_stat0; - unsigned char saa_stat1; -}; - -struct planb_any_regs { - unsigned int offset; - unsigned int bytes; - unsigned char data[128]; -}; - -/* planb private ioctls */ -#define PLANBIOCGSAAREGS _IOWR('v', BASE_VIDIOCPRIVATE, struct planb_saa_regs) /* Read a saa7196 reg value */ -#define PLANBIOCSSAAREGS _IOW('v', BASE_VIDIOCPRIVATE + 1, struct planb_saa_regs) /* Set a saa7196 reg value */ -#define PLANBIOCGSTAT _IOR('v', BASE_VIDIOCPRIVATE + 2, struct planb_stat_regs) /* Read planb status */ -#define PLANB_TV_MODE 1 -#define PLANB_VTR_MODE 2 -#define PLANBIOCGMODE _IOR('v', BASE_VIDIOCPRIVATE + 3, int) /* Get TV/VTR mode */ -#define PLANBIOCSMODE _IOW('v', BASE_VIDIOCPRIVATE + 4, int) /* Set TV/VTR mode */ - -#ifdef PLANB_GSCANLINE -#define PLANBG_GRAB_BPL _IOR('v', BASE_VIDIOCPRIVATE + 5, int) /* # of bytes per scanline in grab buffer */ -#endif - -/* call wake_up_interruptible() with appropriate actions */ -#define PLANB_INTR_DEBUG _IOW('v', BASE_VIDIOCPRIVATE + 20, int) -/* investigate which reg does what */ -#define PLANB_INV_REGS _IOWR('v', BASE_VIDIOCPRIVATE + 21, struct planb_any_regs) - -#ifdef __KERNEL__ - -/* Potentially useful macros */ -#define PLANB_SET(x) ((x) << 16 | (x)) -#define PLANB_CLR(x) ((x) << 16) - -/* This represents the physical register layout */ -struct planb_registers { - volatile struct dbdma_regs ch1; /* 0x00: video in */ - volatile unsigned int even; /* 0x40: even field setting */ - volatile unsigned int odd; /* 0x44; odd field setting */ - unsigned int pad1[14]; /* empty? */ - volatile struct dbdma_regs ch2; /* 0x80: clipmask out */ - unsigned int pad2[16]; /* 0xc0: empty? */ - volatile unsigned int reg3; /* 0x100: ???? */ - volatile unsigned int intr_stat; /* 0x104: irq status */ -#define PLANB_CLR_IRQ 0x00 /* clear Plan B interrupt */ -#define PLANB_GEN_IRQ 0x01 /* assert Plan B interrupt */ -#define PLANB_FRM_IRQ 0x0100 /* end of frame */ - unsigned int pad3[1]; /* empty? */ - volatile unsigned int reg5; /* 0x10c: ??? */ - unsigned int pad4[60]; /* empty? */ - volatile unsigned char saa_addr; /* 0x200: SAA subadr */ - char pad5[3]; - volatile unsigned char saa_regval; /* SAA7196 write reg. val */ - char pad6[3]; - volatile unsigned char saa_status; /* SAA7196 status byte */ - /* There is more unused stuff here */ -}; - -struct planb_window { - int x, y; - ushort width, height; - ushort bpp, bpl, depth, pad; - ushort swidth, sheight; - int norm; - int interlace; - u32 color_fmt; - int chromakey; - int mode; /* used to switch between TV/VTR modes */ -}; - -struct planb_suspend { - int overlay; - int frame; - struct dbdma_cmd cmd; -}; - -struct planb { - struct video_device video_dev; - struct video_picture picture; /* Current picture params */ - struct video_audio audio_dev; /* Current audio params */ - - volatile struct planb_registers *planb_base; /* virt base of planb */ - struct planb_registers *planb_base_phys; /* phys base of planb */ - void *priv_space; /* Org. alloc. mem for kfree */ - int user; - unsigned int tab_size; - int maxlines; - int lock; - wait_queue_head_t lockq; - unsigned int irq; /* interrupt number */ - volatile unsigned int intr_mask; - - int overlay; /* overlay running? */ - struct planb_window win; - unsigned long frame_buffer_phys; /* We need phys for DMA */ - int offset; /* offset of pixel 1 */ - volatile struct dbdma_cmd *ch1_cmd; /* Video In DMA cmd buffer */ - volatile struct dbdma_cmd *ch2_cmd; /* Clip Out DMA cmd buffer */ - volatile struct dbdma_cmd *overlay_last1; - volatile struct dbdma_cmd *overlay_last2; - unsigned long ch1_cmd_phys; - volatile unsigned char *mask; /* Clipmask buffer */ - int suspend; - wait_queue_head_t suspendq; - struct planb_suspend suspended; - int cmd_buff_inited; /* cmd buffer inited? */ - - int grabbing; - unsigned int gcount; - wait_queue_head_t capq; - int last_fr; - int prev_last_fr; - unsigned char **rawbuf; - int rawbuf_size; - int gbuf_idx[MAX_GBUFFERS]; - volatile struct dbdma_cmd *cap_cmd[MAX_GBUFFERS]; - volatile struct dbdma_cmd *last_cmd[MAX_GBUFFERS]; - volatile struct dbdma_cmd *pre_cmd[MAX_GBUFFERS]; - int need_pre_capture[MAX_GBUFFERS]; -#define PLANB_DUMMY 40 /* # of command buf's allocated for pre-capture seq. */ - int gwidth[MAX_GBUFFERS], gheight[MAX_GBUFFERS]; - unsigned int gfmt[MAX_GBUFFERS]; - int gnorm_switch[MAX_GBUFFERS]; - volatile unsigned int *frame_stat; -#define GBUFFER_UNUSED 0x00U -#define GBUFFER_GRABBING 0x01U -#define GBUFFER_DONE 0x02U -#ifdef PLANB_GSCANLINE - int gbytes_per_line; -#else -#define MAX_LNUM 431 /* change this if PLANB_MAXLINES or */ - /* PLANB_MAXPIXELS changes */ - int l_fr_addr_idx[MAX_GBUFFERS]; - unsigned char *l_to_addr[MAX_GBUFFERS][MAX_LNUM]; - int l_to_next_idx[MAX_GBUFFERS][MAX_LNUM]; - int l_to_next_size[MAX_GBUFFERS][MAX_LNUM]; - int lsize[MAX_GBUFFERS], lnum[MAX_GBUFFERS]; -#endif -}; - -#endif /* __KERNEL__ */ - -#endif /* _PLANB_H_ */ diff --git a/drivers/char/pms.c b/drivers/char/pms.c deleted file mode 100644 index 1e50880a0..000000000 --- a/drivers/char/pms.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* - * Media Vision Pro Movie Studio - * or - * "all you need is an I2C bus some RAM and a prayer" - * - * This draws heavily on code - * - * (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994 - * Kiefernring 15 - * 14478 Potsdam, Germany - * - * Most of this code is directly derived from his userspace driver. - * His driver works so send any reports to alan@redhat.com unless the - * userspace driver also doesnt work for you... - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define MOTOROLA 1 -#define PHILIPS2 2 -#define PHILIPS1 3 -#define MVVMEMORYWIDTH 0x40 /* 512 bytes */ - -struct pms_device -{ - struct video_device v; - struct video_picture picture; - int height; - int width; -}; - -struct i2c_info -{ - u8 slave; - u8 sub; - u8 data; - u8 hits; -}; - -static int i2c_count = 0; -static struct i2c_info i2cinfo[64]; - -static int decoder = PHILIPS2; -static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ - -/* - * I/O ports and Shared Memory - */ - -static int io_port = 0x250; -static int data_port = 0x251; -static int mem_base = 0xC8000; - - - -extern __inline__ void mvv_write(u8 index, u8 value) -{ - outw(index|(value<<8), io_port); -} - -extern __inline__ u8 mvv_read(u8 index) -{ - outb(index, io_port); - return inb(data_port); -} - -static int pms_i2c_stat(u8 slave) -{ - int counter; - int i; - - outb(0x28, io_port); - - counter=0; - while((inb(data_port)&0x01)==0) - if(counter++==256) - break; - - while((inb(data_port)&0x01)!=0) - if(counter++==256) - break; - - outb(slave, io_port); - - counter=0; - while((inb(data_port)&0x01)==0) - if(counter++==256) - break; - - while((inb(data_port)&0x01)!=0) - if(counter++==256) - break; - - for(i=0;i<12;i++) - { - char st=inb(data_port); - if((st&2)!=0) - return -1; - if((st&1)==0) - break; - } - outb(0x29, io_port); - return inb(data_port); -} - -static int pms_i2c_write(u16 slave, u16 sub, u16 data) -{ - int skip=0; - int count; - int i; - - for(i=0;i255) - break; - while((inb(data_port)&1)!=0) - if(count>255) - break; - - count=inb(data_port); - - if(count&2) - return -1; - return count; -} - -static int pms_i2c_read(int slave, int sub) -{ - int i=0; - for(i=0;i>8)&0x01); -} - -#endif - -static void pms_secamcross(short cross) -{ - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A, 0x0F, 0xDF, (cross&1)<<5); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42, 0x0F, 0xDF, (cross&1)<<5); -} - - -static void pms_swsense(short sense) -{ - if(decoder==PHILIPS2) - { - pms_i2c_write(0x8A, 0x0A, sense); - pms_i2c_write(0x8A, 0x0B, sense); - } - else if(decoder==PHILIPS1) - { - pms_i2c_write(0x42, 0x0A, sense); - pms_i2c_write(0x42, 0x0B, sense); - } -} - - -static void pms_framerate(short frr) -{ - int fps=(standard==1)?30:25; - if(frr==0) - return; - fps=fps/frr; - mvv_write(0x14,0x80|fps); - mvv_write(0x15,1); -} - -static void pms_vert(u8 deciden, u8 decinum) -{ - mvv_write(0x1C, deciden); /* Denominator */ - mvv_write(0x1D, decinum); /* Numerator */ -} - -/* - * Turn 16bit ratios into best small ratio the chipset can grok - */ - -static void pms_vertdeci(unsigned short decinum, unsigned short deciden) -{ - /* Knock it down by /5 once */ - if(decinum%5==0) - { - deciden/=5; - decinum/=5; - } - /* - * 3's - */ - while(decinum%3==0 && deciden%3==0) - { - deciden/=3; - decinum/=3; - } - /* - * 2's - */ - while(decinum%2==0 && deciden%2==0) - { - decinum/=2; - deciden/=2; - } - /* - * Fudgyify - */ - while(deciden>32) - { - deciden/=2; - decinum=(decinum+1)/2; - } - if(deciden==32) - deciden--; - pms_vert(deciden,decinum); -} - -static void pms_horzdeci(short decinum, short deciden) -{ - if(decinum<=512) - { - if(decinum%5==0) - { - decinum/=5; - deciden/=5; - } - } - else - { - decinum=512; - deciden=640; /* 768 would be ideal */ - } - - while(((decinum|deciden)&1)==0) - { - decinum>>=1; - deciden>>=1; - } - while(deciden>32) - { - deciden>>=1; - decinum=(decinum+1)>>1; - } - if(deciden==32) - deciden--; - - mvv_write(0x24, 0x80|deciden); - mvv_write(0x25, decinum); -} - -static void pms_resolution(short width, short height) -{ - int fg_height; - - fg_height=height; - if(fg_height>280) - fg_height=280; - - mvv_write(0x18, fg_height); - mvv_write(0x19, fg_height>>8); - - if(standard==1) - { - mvv_write(0x1A, 0xFC); - mvv_write(0x1B, 0x00); - if(height>fg_height) - pms_vertdeci(240,240); - else - pms_vertdeci(fg_height,240); - } - else - { - mvv_write(0x1A, 0x1A); - mvv_write(0x1B, 0x01); - if(fg_height>256) - pms_vertdeci(270,270); - else - pms_vertdeci(fg_height, 270); - } - mvv_write(0x12,0); - mvv_write(0x13, MVVMEMORYWIDTH); - mvv_write(0x42, 0x00); - mvv_write(0x43, 0x00); - mvv_write(0x44, MVVMEMORYWIDTH); - - mvv_write(0x22, width+8); - mvv_write(0x23, (width+8)>> 8); - - if(standard==1) - pms_horzdeci(width,640); - else - pms_horzdeci(width+8, 768); - - mvv_write(0x30, mvv_read(0x30)&0xFE); - mvv_write(0x08, mvv_read(0x08)|0x01); - mvv_write(0x01, mvv_read(0x01)&0xFD); - mvv_write(0x32, 0x00); - mvv_write(0x33, MVVMEMORYWIDTH); -} - - -/* - * Set Input - */ - -static void pms_vcrinput(short input) -{ - if(decoder==PHILIPS2) - pms_i2c_andor(0x8A,0x0D,0x7F,(input&1)<<7); - else if(decoder==PHILIPS1) - pms_i2c_andor(0x42,0x0D,0x7F,(input&1)<<7); -} - - -static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count) -{ - int y; - int dw = 2*dev->width; - u32 src = mem_base; - - char tmp[dw+32]; /* using a temp buffer is faster than direct */ - int cnt = 0; - int len=0; - unsigned char r8 = 0x5; /* value for reg8 */ - - if (rgb555) - r8 |= 0x20; /* else use untranslated rgb = 565 */ - mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */ - -/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */ - - for (y = 0; y < dev->height; y++ ) - { - isa_writeb(0, src); /* synchronisiert neue Zeile */ - - /* - * This is in truth a fifo, be very careful as if you - * forgot this odd things will occur 8) - */ - - isa_memcpy_fromio(tmp, src, dw+32); /* discard 16 word */ - cnt -= dev->height; - while (cnt <= 0) - { - /* - * Don't copy too far - */ - int dt=dw; - if(dt+len>count) - dt=count-len; - cnt += dev->height; - copy_to_user(buf, tmp+32, dt); - buf += dt; - len += dt; - } - } - return len; -} - - -/* - * Video4linux interfacing - */ - -static int pms_open(struct video_device *dev, int flags) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static void pms_close(struct video_device *dev) -{ - MOD_DEC_USE_COUNT; -} - -static int pms_init_done(struct video_device *dev) -{ - return 0; -} - -static long pms_write(struct video_device *v, const char *buf, unsigned long count, int noblock) -{ - return -EINVAL; -} - -static int pms_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct pms_device *pd=(struct pms_device *)dev; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability b; - strcpy(b.name, "Mediavision PMS"); - b.type = VID_TYPE_CAPTURE|VID_TYPE_SCALES; - b.channels = 4; - b.audios = 0; - b.maxwidth = 640; - b.maxheight = 480; - b.minwidth = 16; - b.minheight = 16; - if(copy_to_user(arg, &b,sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.channel<0 || v.channel>3) - return -EINVAL; - v.flags=0; - v.tuners=1; - /* Good question.. its composite or SVHS so.. */ - v.type = VIDEO_TYPE_CAMERA; - switch(v.channel) - { - case 0: - strcpy(v.name, "Composite");break; - case 1: - strcpy(v.name, "SVideo");break; - case 2: - strcpy(v.name, "Composite(VCR)");break; - case 3: - strcpy(v.name, "SVideo(VCR)");break; - } - if(copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSCHAN: - { - int v; - if(copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - if(v<0 || v>3) - return -EINVAL; - pms_videosource(v&1); - pms_vcrinput(v>>1); - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))!=0) - return -EFAULT; - if(v.tuner) - return -EINVAL; - strcpy(v.name, "Format"); - v.rangelow=0; - v.rangehigh=0; - v.flags= VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; - switch(standard) - { - case 0: - v.mode = VIDEO_MODE_AUTO; - break; - case 1: - v.mode = VIDEO_MODE_NTSC; - break; - case 2: - v.mode = VIDEO_MODE_PAL; - break; - case 3: - v.mode = VIDEO_MODE_SECAM; - break; - } - if(copy_to_user(arg,&v,sizeof(v))!=0) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))!=0) - return -EFAULT; - if(v.tuner) - return -EINVAL; - switch(v.mode) - { - case VIDEO_MODE_AUTO: - pms_framerate(25); - pms_secamcross(0); - pms_format(0); - break; - case VIDEO_MODE_NTSC: - pms_framerate(30); - pms_secamcross(0); - pms_format(1); - break; - case VIDEO_MODE_PAL: - pms_framerate(25); - pms_secamcross(0); - pms_format(2); - break; - case VIDEO_MODE_SECAM: - pms_framerate(25); - pms_secamcross(1); - pms_format(2); - break; - default: - return -EINVAL; - } - return 0; - } - case VIDIOCGPICT: - { - struct video_picture p=pd->picture; - if(copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - if(copy_from_user(&p, arg, sizeof(p))) - return -EFAULT; - if(!((p.palette==VIDEO_PALETTE_RGB565 && p.depth==16) - ||(p.palette==VIDEO_PALETTE_RGB555 && p.depth==15))) - return -EINVAL; - pd->picture=p; - - /* - * Now load the card. - */ - - pms_brightness(p.brightness>>8); - pms_hue(p.hue>>8); - pms_colour(p.colour>>8); - pms_contrast(p.contrast>>8); - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - if(copy_from_user(&vw, arg,sizeof(vw))) - return -EFAULT; - if(vw.flags) - return -EINVAL; - if(vw.clipcount) - return -EINVAL; - if(vw.height<16||vw.height>480) - return -EINVAL; - if(vw.width<16||vw.width>640) - return -EINVAL; - pd->width=vw.width; - pd->height=vw.height; - pms_resolution(pd->width, pd->height); - /* Ok we figured out what to use from our wide choice */ - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - vw.x=0; - vw.y=0; - vw.width=pd->width; - vw.height=pd->height; - vw.chromakey=0; - vw.flags=0; - if(copy_to_user(arg, &vw, sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCGFBUF: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCKEY: - return 0; - case VIDIOCGFREQ: - return -EINVAL; - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - return -EINVAL; - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static long pms_read(struct video_device *v, char *buf, unsigned long count, int noblock) -{ - struct pms_device *pd=(struct pms_device *)v; - int len; - - /* FIXME: semaphore this */ - len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count); - return len; -} - - -struct video_device pms_template= -{ - "Mediavision PMS", - VID_TYPE_CAPTURE, - VID_HARDWARE_PMS, - pms_open, - pms_close, - pms_read, - pms_write, - NULL, /* FIXME - we can use POLL on this board with the irq */ - pms_ioctl, - NULL, - pms_init_done, - NULL, - 0, - 0 -}; - -struct pms_device pms_device; - - -/* - * Probe for and initialise the Mediavision PMS - */ - -static int init_mediavision(void) -{ - int id; - int idec, decst; - int i; - - unsigned char i2c_defs[]={ - 0x4C,0x30,0x00,0xE8, - 0xB6,0xE2,0x00,0x00, - 0xFF,0xFF,0x00,0x00, - 0x00,0x00,0x78,0x98, - 0x00,0x00,0x00,0x00, - 0x34,0x0A,0xF4,0xCE, - 0xE4 - }; - - if(check_region(0x9A01,1)) - { - printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); - return -EBUSY; - } - if(check_region(io_port,3)) - { - printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port); - return -EBUSY; - } - outb(0xB8, 0x9A01); /* Unlock */ - outb(io_port>>4, 0x9A01); /* Set IO port */ - - - id=mvv_read(3); - decst=pms_i2c_stat(0x43); - - if(decst!=-1) - idec=2; - else if(pms_i2c_stat(0xb9)!=-1) - idec=3; - else if(pms_i2c_stat(0x8b)!=-1) - idec=1; - else - idec=0; - - printk(KERN_INFO "PMS type is %d\n", idec); - if(idec==0) - return -ENODEV; - - /* - * Ok we have a PMS of some sort - */ - - request_region(io_port,3, "Mediavision PMS"); - request_region(0x9A01, 1, "Mediavision PMS config"); - - mvv_write(0x04, mem_base>>12); /* Set the memory area */ - - /* Ok now load the defaults */ - - for(i=0;i<0x19;i++) - { - if(i2c_defs[i]==0xFF) - pms_i2c_andor(0x8A, i, 0x07,0x00); - else - pms_i2c_write(0x8A, i, i2c_defs[i]); - } - - pms_i2c_write(0xB8,0x00,0x12); - pms_i2c_write(0xB8,0x04,0x00); - pms_i2c_write(0xB8,0x07,0x00); - pms_i2c_write(0xB8,0x08,0x00); - pms_i2c_write(0xB8,0x09,0xFF); - pms_i2c_write(0xB8,0x0A,0x00); - pms_i2c_write(0xB8,0x0B,0x10); - pms_i2c_write(0xB8,0x10,0x03); - - mvv_write(0x01, 0x00); - mvv_write(0x05, 0xA0); - mvv_write(0x08, 0x25); - mvv_write(0x09, 0x00); - mvv_write(0x0A, 0x20|MVVMEMORYWIDTH); - - mvv_write(0x10, 0x02); - mvv_write(0x1E, 0x0C); - mvv_write(0x1F, 0x03); - mvv_write(0x26, 0x06); - - mvv_write(0x2B, 0x00); - mvv_write(0x2C, 0x20); - mvv_write(0x2D, 0x00); - mvv_write(0x2F, 0x70); - mvv_write(0x32, 0x00); - mvv_write(0x33, MVVMEMORYWIDTH); - mvv_write(0x34, 0x00); - mvv_write(0x35, 0x00); - mvv_write(0x3A, 0x80); - mvv_write(0x3B, 0x10); - mvv_write(0x20, 0x00); - mvv_write(0x21, 0x00); - mvv_write(0x30, 0x22); - return 0; -} - -/* - * Initialization and module stuff - */ - -static int __init init_pms_cards(void) -{ - printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); - - data_port = io_port +1; - - if(init_mediavision()) - { - printk(KERN_INFO "Board not found.\n"); - return -ENODEV; - } - memcpy(&pms_device, &pms_template, sizeof(pms_template)); - pms_device.height=240; - pms_device.width=320; - pms_swsense(75); - pms_resolution(320,240); - return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER); -} - -MODULE_PARM(io_port,"i"); -MODULE_PARM(mem_base,"i"); - -static void __exit shutdown_mediavision(void) -{ - release_region(io_port,3); - release_region(0x9A01, 1); -} - -static void __exit cleanup_pms_module(void) -{ - shutdown_mediavision(); - video_unregister_device((struct video_device *)&pms_device); -} - -module_init(init_pms_cards); -module_exit(cleanup_pms_module); - diff --git a/drivers/char/radio-aimslab.c b/drivers/char/radio-aimslab.c deleted file mode 100644 index d716c54bd..000000000 --- a/drivers/char/radio-aimslab.c +++ /dev/null @@ -1,390 +0,0 @@ -/* radiotrack (radioreveal) driver for Linux radio support - * (c) 1997 M. Kirkwood - * Coverted to new API by Alan Cox - * Various bugfixes and enhancements by Russell Kroll - * - * History: - * 1999-02-24 Russell Kroll - * Fine tuning/VIDEO_TUNER_LOW - * Frequency range expanded to start at 87 MHz - * - * TODO: Allow for more than one of these foolish entities :-) - * - * Notes on the hardware (reverse engineered from other peoples' - * reverse engineering of AIMS' code :-) - * - * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); - * - * The signal strength query is unsurprisingly inaccurate. And it seems - * to indicate that (on my card, at least) the frequency setting isn't - * too great. (I have to tune up .025MHz from what the freq should be - * to get a report that the thing is tuned.) - * - * Volume control is (ugh) analogue: - * out(port, start_increasing_volume); - * wait(a_wee_while); - * out(port, stop_changing_the_volume); - * - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_RTRACK_PORT */ -#include /* Lock for the I/O */ - -#ifndef CONFIG_RADIO_RTRACK_PORT -#define CONFIG_RADIO_RTRACK_PORT -1 -#endif - -static int io = CONFIG_RADIO_RTRACK_PORT; -static int users = 0; -static struct semaphore lock; - -struct rt_device -{ - int port; - int curvol; - unsigned long curfreq; - int muted; -}; - - -/* local things */ - -static void sleep_delay(long n) -{ - /* Sleep nicely for 'n' uS */ - int d=n/(1000000/HZ); - if(!d) - udelay(n); - else - { - /* Yield CPU time */ - unsigned long x=jiffies; - while((jiffies-x)<=d) - schedule(); - } -} - -static void rt_decvol(void) -{ - outb(0x58, io); /* volume down + sigstr + on */ - sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ -} - -static void rt_incvol(void) -{ - outb(0x98, io); /* volume up + sigstr + on */ - sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ -} - -static void rt_mute(struct rt_device *dev) -{ - dev->muted = 1; - down(&lock); - outb(0xd0, io); /* volume steady, off */ - up(&lock); -} - -static int rt_setvol(struct rt_device *dev, int vol) -{ - int i; - - down(&lock); - - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - outb (0xd8, io); /* enable card */ - } - up(&lock); - return 0; - } - - if(vol == 0) { /* volume = 0 means mute the card */ - outb(0x48, io); /* volume down but still "on" */ - sleep_delay(2000000); /* make sure it's totally down */ - outb(0xd0, io); /* volume steady, off */ - dev->curvol = 0; /* track the volume state! */ - up(&lock); - return 0; - } - - dev->muted = 0; - if(vol > dev->curvol) - for(i = dev->curvol; i < vol; i++) - rt_incvol(); - else - for(i = dev->curvol; i > vol; i--) - rt_decvol(); - - dev->curvol = vol; - up(&lock); - return 0; -} - -/* the 128+64 on these outb's is to keep the volume stable while tuning - * without them, the volume _will_ creep up with each frequency change - * and bit 4 (+16) is to keep the signal strength meter enabled - */ - -void send_0_byte(int port, struct rt_device *dev) -{ - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+ 1, port); /* wr-enable + data low */ - outb_p(128+64+16+2+1, port); /* clock */ - } - else { - outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */ - outb_p(128+64+16+8+2+1, port); /* clock */ - } - sleep_delay(1000); -} - -void send_1_byte(int port, struct rt_device *dev) -{ - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+4 +1, port); /* wr-enable+data high */ - outb_p(128+64+16+4+2+1, port); /* clock */ - } - else { - outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */ - outb_p(128+64+16+8+4+2+1, port); /* clock */ - } - - sleep_delay(1000); -} - -static int rt_setfreq(struct rt_device *dev, unsigned long freq) -{ - int i; - - /* adapted from radio-aztech.c */ - - /* now uses VIDEO_TUNER_LOW for fine tuning */ - - freq += 171200; /* Add 10.7 MHz IF */ - freq /= 800; /* Convert to 50 kHz units */ - - down(&lock); /* Stop other ops interfering */ - - send_0_byte (io, dev); /* 0: LSB of frequency */ - - for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ - if (freq & (1 << i)) - send_1_byte (io, dev); - else - send_0_byte (io, dev); - - send_0_byte (io, dev); /* 14: test bit - always 0 */ - send_0_byte (io, dev); /* 15: test bit - always 0 */ - - send_0_byte (io, dev); /* 16: band data 0 - always 0 */ - send_0_byte (io, dev); /* 17: band data 1 - always 0 */ - send_0_byte (io, dev); /* 18: band data 2 - always 0 */ - send_0_byte (io, dev); /* 19: time base - always 0 */ - - send_0_byte (io, dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (io, dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 23: AM/FM (FM = 1, always) */ - - if ((dev->curvol == 0) || (dev->muted)) - outb (0xd0, io); /* volume steady + sigstr */ - else - outb (0xd8, io); /* volume steady + sigstr + on */ - - up(&lock); - - return 0; -} - -static int rt_getsigstr(struct rt_device *dev) -{ - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} - -static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct rt_device *rt=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - strcpy(v.name, "RadioTrack"); - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=(87*16000); - v.rangehigh=(108*16000); - v.flags=VIDEO_TUNER_LOW; - v.mode=VIDEO_MODE_AUTO; - strcpy(v.name, "FM"); - v.signal=0xFFFF*rt_getsigstr(rt); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq))) - return -EFAULT; - rt_setfreq(rt, rt->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; - v.volume=rt->curvol * 6554; - v.step=6554; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - if(v.flags&VIDEO_AUDIO_MUTE) - rt_mute(rt); - else - rt_setvol(rt,v.volume/6554); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int rt_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void rt_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct rt_device rtrack_unit; - -static struct video_device rtrack_radio= -{ - "RadioTrack radio", - VID_TYPE_TUNER, - VID_HARDWARE_RTRACK, - rt_open, - rt_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - rt_ioctl, - NULL, - NULL -}; - -static int __init rtrack_init(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - - if (check_region(io, 2)) - { - printk(KERN_ERR "rtrack: port 0x%x already in use\n", io); - return -EBUSY; - } - - rtrack_radio.priv=&rtrack_unit; - - if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 2, "rtrack"); - printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); - - /* Set up the I/O locking */ - - init_MUTEX(&lock); - - /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - outb(0x48, io); /* volume down but still "on" */ - sleep_delay(2000000); /* make sure it's totally down */ - outb(0xc0, io); /* steady volume, mute card */ - rtrack_unit.curvol = 0; - - return 0; -} - -MODULE_AUTHOR("M.Kirkwood"); -MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); - -EXPORT_NO_SYMBOLS; - -static void __exit cleanup_rtrack_module(void) -{ - video_unregister_device(&rtrack_radio); - release_region(io,2); -} - -module_init(rtrack_init); -module_exit(cleanup_rtrack_module); - diff --git a/drivers/char/radio-aztech.c b/drivers/char/radio-aztech.c deleted file mode 100644 index 2fb8714ad..000000000 --- a/drivers/char/radio-aztech.c +++ /dev/null @@ -1,330 +0,0 @@ -/* radio-aztech.c - Aztech radio card driver for Linux 2.2 - * - * Adapted to support the Video for Linux API by - * Russell Kroll . Based on original tuner code by: - * - * Quay Ly - * Donald Song - * Jason Lewis (jlewis@twilight.vtc.vsc.edu) - * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) - * William McGrath (wmcgrath@twilight.vtc.vsc.edu) - * - * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/ - * along with more information on the card itself. - * - * History: - * 1999-02-24 Russell Kroll - * Fine tuning/VIDEO_TUNER_LOW - * Range expanded to 87-108 MHz (from 87.9-107.8) - * - * Notable changes from the original source: - * - includes stripped down to the essentials - * - for loops used as delays replaced with udelay() - * - #defines removed, changed to static values - * - tuning structure changed - no more character arrays, other changes -*/ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_AZTECH_PORT */ - -/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ - -#ifndef CONFIG_RADIO_AZTECH_PORT -#define CONFIG_RADIO_AZTECH_PORT -1 -#endif - -static int io = CONFIG_RADIO_AZTECH_PORT; -static int radio_wait_time = 1000; -static int users = 0; -static struct semaphore lock; - -struct az_device -{ - int curvol; - unsigned long curfreq; - int stereo; -}; - -static int volconvert(int level) -{ - level>>=14; /* Map 16bits down to 2 bit */ - level&=3; - - /* convert to card-friendly values */ - switch (level) - { - case 0: - return 0; - case 1: - return 1; - case 2: - return 4; - case 3: - return 5; - } - return 0; /* Quieten gcc */ -} - -static void send_0_byte (struct az_device *dev) -{ - udelay(radio_wait_time); - outb_p(2+volconvert(dev->curvol), io); - outb_p(64+2+volconvert(dev->curvol), io); -} - -static void send_1_byte (struct az_device *dev) -{ - udelay (radio_wait_time); - outb_p(128+2+volconvert(dev->curvol), io); - outb_p(128+64+2+volconvert(dev->curvol), io); -} - -static int az_setvol(struct az_device *dev, int vol) -{ - down(&lock); - outb (volconvert(vol), io); - up(&lock); - return 0; -} - -/* thanks to Michael Dwyer for giving me a dose of clues in - * the signal strength department.. - * - * This card has a stereo bit - bit 0 set = mono, not set = stereo - * It also has a "signal" bit - bit 1 set = bad signal, not set = good - * - */ - -static int az_getsigstr(struct az_device *dev) -{ - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} - -static int az_getstereo(struct az_device *dev) -{ - if (inb(io) & 1) /* bit set = mono */ - return 0; - return 1; /* stereo */ -} - -static int az_setfreq(struct az_device *dev, unsigned long frequency) -{ - int i; - - frequency += 171200; /* Add 10.7 MHz IF */ - frequency /= 800; /* Convert to 50 kHz units */ - - down(&lock); - - send_0_byte (dev); /* 0: LSB of frequency */ - - for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ - if (frequency & (1 << i)) - send_1_byte (dev); - else - send_0_byte (dev); - - send_0_byte (dev); /* 14: test bit - always 0 */ - send_0_byte (dev); /* 15: test bit - always 0 */ - send_0_byte (dev); /* 16: band data 0 - always 0 */ - if (dev->stereo) /* 17: stereo (1 to enable) */ - send_1_byte (dev); - else - send_0_byte (dev); - - send_1_byte (dev); /* 18: band data 1 - unknown */ - send_0_byte (dev); /* 19: time base - always 0 */ - send_0_byte (dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 23: AM/FM (FM = 1, always) */ - - /* latch frequency */ - - udelay (radio_wait_time); - outb_p(128+64+volconvert(dev->curvol), io); - - up(&lock); - - return 0; -} - -static int az_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct az_device *az=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - strcpy(v.name, "Aztech Radio"); - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=(87*16000); - v.rangehigh=(108*16000); - v.flags=VIDEO_TUNER_LOW; - v.mode=VIDEO_MODE_AUTO; - v.signal=0xFFFF*az_getsigstr(az); - if(az_getstereo(az)) - v.flags|=VIDEO_TUNER_STEREO_ON; - strcpy(v.name, "FM"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &az->curfreq, sizeof(az->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&az->curfreq, arg,sizeof(az->curfreq))) - return -EFAULT; - az_setfreq(az, az->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; - if(az->stereo) - v.mode=VIDEO_SOUND_STEREO; - else - v.mode=VIDEO_SOUND_MONO; - v.volume=az->curvol; - v.step=16384; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - az->curvol=v.volume; - - az->stereo=(v.mode&VIDEO_SOUND_STEREO)?1:0; - if(v.flags&VIDEO_AUDIO_MUTE) - az_setvol(az,0); - else - az_setvol(az,az->curvol); - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int az_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void az_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct az_device aztech_unit; - -static struct video_device aztech_radio= -{ - "Aztech radio", - VID_TYPE_TUNER, - VID_HARDWARE_AZTECH, - az_open, - az_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - az_ioctl, - NULL, - NULL -}; - -static int __init aztech_init(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - - if (check_region(io, 2)) - { - printk(KERN_ERR "aztech: port 0x%x already in use\n", io); - return -EBUSY; - } - - init_MUTEX(&lock); - aztech_radio.priv=&aztech_unit; - - if(video_register_device(&aztech_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 2, "aztech"); - printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); - /* mute card - prevents noisy bootups */ - outb (0, io); - return 0; -} - -MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Aztech radio card."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); - -EXPORT_NO_SYMBOLS; - -static void __exit aztech_cleanup(void) -{ - video_unregister_device(&aztech_radio); - release_region(io,2); -} - -module_init(aztech_init); -module_exit(aztech_cleanup); diff --git a/drivers/char/radio-cadet.c b/drivers/char/radio-cadet.c deleted file mode 100644 index ed2056dea..000000000 --- a/drivers/char/radio-cadet.c +++ /dev/null @@ -1,603 +0,0 @@ -/* radio-cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card - * - * by Fred Gleason - * Version 0.3.3 - * - * (Loosely) based on code for the Aztech radio card by - * - * Russell Kroll (rkroll@exploits.org) - * Quay Ly - * Donald Song - * Jason Lewis (jlewis@twilight.vtc.vsc.edu) - * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) - * William McGrath (wmcgrath@twilight.vtc.vsc.edu) - * -*/ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_CADET_PORT */ -#include - -#ifndef CONFIG_RADIO_CADET_PORT -#define CONFIG_RADIO_CADET_PORT 0x330 -#endif -#define RDS_BUFFER 256 - -static int io=CONFIG_RADIO_CADET_PORT; -static int users=0; -static int curtuner=0; -static int tunestat=0; -static int sigstrength=0; -static wait_queue_head_t tunerq,rdsq,readq; -struct timer_list tunertimer,rdstimer,readtimer; -static __u8 rdsin=0,rdsout=0,rdsstat=0; -static unsigned char rdsbuf[RDS_BUFFER]; -static int cadet_lock=0; - -/* - * Signal Strength Threshold Values - * The V4L API spec does not define any particular unit for the signal - * strength value. These values are in microvolts of RF at the tuner's input. - */ -static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; - - - -void cadet_wake(unsigned long qnum) -{ - switch(qnum) { - case 0: /* cadet_setfreq */ - wake_up(&tunerq); - break; - case 1: /* cadet_getrds */ - wake_up(&rdsq); - break; - } -} - - - -static int cadet_getrds(void) -{ - int rdsstat=0; - - cadet_lock++; - outb(3,io); /* Select Decoder Control/Status */ - outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ - cadet_lock--; - init_timer(&rdstimer); - rdstimer.function=cadet_wake; - rdstimer.data=(unsigned long)1; - rdstimer.expires=jiffies+(HZ/10); - init_waitqueue_head(&rdsq); - add_timer(&rdstimer); - sleep_on(&rdsq); - - cadet_lock++; - outb(3,io); /* Select Decoder Control/Status */ - if((inb(io+1)&0x80)!=0) { - rdsstat|=VIDEO_TUNER_RDS_ON; - } - if((inb(io+1)&0x10)!=0) { - rdsstat|=VIDEO_TUNER_MBS_ON; - } - cadet_lock--; - return rdsstat; -} - - - - -static int cadet_getstereo(void) -{ - if(curtuner!=0) { /* Only FM has stereo capability! */ - return 0; - } - cadet_lock++; - outb(7,io); /* Select tuner control */ - if((inb(io+1)&0x40)==0) { - cadet_lock--; - return 1; /* Stereo pilot detected */ - } - else { - cadet_lock--; - return 0; /* Mono */ - } -} - - - -static unsigned cadet_gettune(void) -{ - int curvol,i; - unsigned fifo=0; - - /* - * Prepare for read - */ - cadet_lock++; - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); /* Save current volume/mute setting */ - outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ - tunestat=0xffff; - - /* - * Read the shift register - */ - for(i=0;i<25;i++) { - fifo=(fifo<<1)|((inb(io+1)>>7)&0x01); - if(i<24) { - outb(0x01,io+1); - tunestat&=inb(io+1); - outb(0x00,io+1); - } - } - - /* - * Restore volume/mute setting - */ - outb(curvol,io+1); - cadet_lock--; - - return fifo; -} - - - -static unsigned cadet_getfreq(void) -{ - int i; - unsigned freq=0,test,fifo=0; - - /* - * Read current tuning - */ - fifo=cadet_gettune(); - - /* - * Convert to actual frequency - */ - if(curtuner==0) { /* FM */ - test=12500; - for(i=0;i<14;i++) { - if((fifo&0x01)!=0) { - freq+=test; - } - test=test<<1; - fifo=fifo>>1; - } - freq-=10700000; /* IF frequency is 10.7 MHz */ - freq=(freq*16)/1000000; /* Make it 1/16 MHz */ - } - if(curtuner==1) { /* AM */ - freq=((fifo&0x7fff)-2010)*16; - } - - return freq; -} - - - -static void cadet_settune(unsigned fifo) -{ - int i; - unsigned test; - - cadet_lock++; - outb(7,io); /* Select tuner control */ - /* - * Write the shift register - */ - test=0; - test=(fifo>>23)&0x02; /* Align data for SDO */ - test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ - outb(7,io); /* Select tuner control */ - outb(test,io+1); /* Initialize for write */ - for(i=0;i<25;i++) { - test|=0x01; /* Toggle SCK High */ - outb(test,io+1); - test&=0xfe; /* Toggle SCK Low */ - outb(test,io+1); - fifo=fifo<<1; /* Prepare the next bit */ - test=0x1c|((fifo>>23)&0x02); - outb(test,io+1); - } - cadet_lock--; -} - - - -static void cadet_setfreq(unsigned freq) -{ - unsigned fifo; - int i,j,test; - int curvol; - - /* - * Formulate a fifo command - */ - fifo=0; - if(curtuner==0) { /* FM */ - test=102400; - freq=(freq*1000)/16; /* Make it kHz */ - freq+=10700; /* IF is 10700 kHz */ - for(i=0;i<14;i++) { - fifo=fifo<<1; - if(freq>=test) { - fifo|=0x01; - freq-=test; - } - test=test>>1; - } - } - if(curtuner==1) { /* AM */ - fifo=(freq/16)+2010; /* Make it kHz */ - fifo|=0x100000; /* Select AM Band */ - } - - /* - * Save current volume/mute setting - */ - cadet_lock++; - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); - - /* - * Tune the card - */ - for(j=3;j>-1;j--) { - cadet_settune(fifo|(j<<16)); - outb(7,io); /* Select tuner control */ - outb(curvol,io+1); - cadet_lock--; - init_timer(&tunertimer); - tunertimer.function=cadet_wake; - tunertimer.data=(unsigned long)0; - tunertimer.expires=jiffies+(HZ/10); - init_waitqueue_head(&tunerq); - add_timer(&tunertimer); - sleep_on(&tunerq); - cadet_gettune(); - if((tunestat&0x40)==0) { /* Tuned */ - sigstrength=sigtable[curtuner][j]; - return; - } - cadet_lock++; - } - cadet_lock--; - sigstrength=0; -} - - -static int cadet_getvol(void) -{ - cadet_lock++; - outb(7,io); /* Select tuner control */ - if((inb(io+1)&0x20)!=0) { - cadet_lock--; - return 0xffff; - } - else { - cadet_lock--; - return 0; - } -} - - -static void cadet_setvol(int vol) -{ - cadet_lock++; - outb(7,io); /* Select tuner control */ - if(vol>0) { - outb(0x20,io+1); - } - else { - outb(0x00,io+1); - } - cadet_lock--; -} - - - -void cadet_handler(unsigned long data) -{ - /* - * Service the RDS fifo - */ - if(cadet_lock==0) { - outb(0x3,io); /* Select RDS Decoder Control */ - if((inb(io+1)&0x20)!=0) { - printk(KERN_CRIT "cadet: RDS fifo overflow\n"); - } - outb(0x80,io); /* Select RDS fifo */ - while((inb(io)&0x80)!=0) { - rdsbuf[rdsin++]=inb(io+1); - if(rdsin==rdsout) { - printk(KERN_CRIT "cadet: RDS buffer overflow\n"); - } - } - } - - /* - * Service pending read - */ - if( rdsin!=rdsout) { - wake_up_interruptible(&readq); - } - - /* - * Clean up and exit - */ - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+(HZ/20); - add_timer(&readtimer); -} - - - -static long cadet_read(struct video_device *v,char *buf,unsigned long count, - int nonblock) -{ - int i=0; - unsigned char readbuf[RDS_BUFFER]; - - if(rdsstat==0) { - cadet_lock++; - rdsstat=1; - outb(0x80,io); /* Select RDS fifo */ - cadet_lock--; - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+(HZ/20); - add_timer(&readtimer); - } - if(rdsin==rdsout) { - if(nonblock) { - return -EWOULDBLOCK; - } - interruptible_sleep_on(&readq); - } - while((i1)) { - return -EINVAL; - } - switch(v.tuner) { - case 0: - strcpy(v.name,"FM"); - v.rangelow=1400; /* 87.5 MHz */ - v.rangehigh=1728; /* 108.0 MHz */ - v.flags=0; - v.mode=0; - v.mode|=VIDEO_MODE_AUTO; - v.signal=sigstrength; - if(cadet_getstereo()==1) { - v.flags|=VIDEO_TUNER_STEREO_ON; - } - v.flags|=cadet_getrds(); - if(copy_to_user(arg,&v, sizeof(v))) { - return -EFAULT; - } - break; - case 1: - strcpy(v.name,"AM"); - v.rangelow=8320; /* 520 kHz */ - v.rangehigh=26400; /* 1650 kHz */ - v.flags=0; - v.flags|=VIDEO_TUNER_LOW; - v.mode=0; - v.mode|=VIDEO_MODE_AUTO; - v.signal=sigstrength; - if(copy_to_user(arg,&v, sizeof(v))) { - return -EFAULT; - } - break; - } - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) { - return -EFAULT; - } - if((v.tuner<0)||(v.tuner>1)) { - return -EINVAL; - } - curtuner=v.tuner; - return 0; - } - case VIDIOCGFREQ: - freq=cadet_getfreq(); - if(copy_to_user(arg, &freq, sizeof(freq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&freq, arg,sizeof(freq))) - return -EFAULT; - if((curtuner==0)&&((freq<1400)||(freq>1728))) { - return -EINVAL; - } - if((curtuner==1)&&((freq<8320)||(freq>26400))) { - return -EINVAL; - } - cadet_setfreq(freq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; - if(cadet_getstereo()==0) { - v.mode=VIDEO_SOUND_MONO; - } - else { - v.mode=VIDEO_SOUND_STEREO; - } - v.volume=cadet_getvol(); - v.step=0xffff; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - cadet_setvol(v.volume); - if(v.flags&VIDEO_AUDIO_MUTE) - cadet_setvol(0); - else - cadet_setvol(0xffff); - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - - -static int cadet_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - init_waitqueue_head(&readq); - return 0; -} - -static void cadet_close(struct video_device *dev) -{ - if(rdsstat==1) { - del_timer(&readtimer); - rdsstat=0; - } - users--; - MOD_DEC_USE_COUNT; -} - - -static struct video_device cadet_radio= -{ - "Cadet radio", - VID_TYPE_TUNER, - VID_HARDWARE_CADET, - cadet_open, - cadet_close, - cadet_read, - NULL, /* Can't write */ - NULL, /* No poll */ - cadet_ioctl, - NULL, - NULL -}; - -#ifndef MODULE -static int cadet_probe(void) -{ - static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; - int i; - - for(i=0;i<8;i++) { - io=iovals[i]; - if(check_region(io,2)>=0) { - cadet_setfreq(1410); - if(cadet_getfreq()==1410) { - return io; - } - } - } - return -1; -} -#endif - -static int __init cadet_init(void) -{ -#ifndef MODULE - io = cadet_probe (); -#endif - - if(io < 0) { -#ifdef MODULE - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); -#endif - return -EINVAL; - } - if (!request_region(io,2,"cadet")) - return -EBUSY; - if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1) { - release_region(io,2); - return -EINVAL; - } - printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io); - return 0; -} - - - -MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); - -EXPORT_NO_SYMBOLS; - -static void __exit cadet_cleanup_module(void) -{ - video_unregister_device(&cadet_radio); - release_region(io,2); -} - -module_init(cadet_init); -module_exit(cadet_cleanup_module); - diff --git a/drivers/char/radio-gemtek.c b/drivers/char/radio-gemtek.c deleted file mode 100644 index 8b53dbd0d..000000000 --- a/drivers/char/radio-gemtek.c +++ /dev/null @@ -1,319 +0,0 @@ -/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin - * - * GemTek hasn't released any specs on the card, so the protocol had to - * be reverse engineered with dosemu. - * - * Besides the protocol changes, this is mostly a copy of: - * - * RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff - * - * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood - * Coverted to new API by Alan Cox - * Various bugfixes and enhancements by Russell Kroll - * - * TODO: Allow for more than one of these foolish entities :-) - * - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_GEMTEK_PORT */ -#include - -#ifndef CONFIG_RADIO_GEMTEK_PORT -#define CONFIG_RADIO_GEMTEK_PORT -1 -#endif - -static int io = CONFIG_RADIO_GEMTEK_PORT; -static int users = 0; -static spinlock_t lock; - -struct gemtek_device -{ - int port; - unsigned long curfreq; - int muted; -}; - - -/* local things */ - -/* the correct way to mute the gemtek may be to write the last written - * frequency || 0x10, but just writing 0x10 once seems to do it as well - */ -static void gemtek_mute(struct gemtek_device *dev) -{ - if(dev->muted) - return; - spin_lock(&lock); - outb(0x10, io); - spin_unlock(&lock); - dev->muted = 1; -} - -static void gemtek_unmute(struct gemtek_device *dev) -{ - if(dev->muted == 0) - return; - spin_lock(&lock); - outb(0x20, io); - spin_unlock(&lock); - dev->muted = 0; -} - -static void zero(void) -{ - outb_p(0x04, io); - udelay(5); - outb_p(0x05, io); - udelay(5); -} - -static void one(void) -{ - outb_p(0x06, io); - udelay(5); - outb_p(0x07, io); - udelay(5); -} - -static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) -{ - int i; - -/* freq = 78.25*((float)freq/16000.0 + 10.52); */ - - freq /= 16; - freq += 10520; - freq *= 7825; - freq /= 100000; - - spin_lock(&lock); - - /* 2 start bits */ - outb_p(0x03, io); - udelay(5); - outb_p(0x07, io); - udelay(5); - - /* 28 frequency bits (lsb first) */ - for (i = 0; i < 14; i++) - if (freq & (1 << i)) - one(); - else - zero(); - /* 36 unknown bits */ - for (i = 0; i < 11; i++) - zero(); - one(); - for (i = 0; i < 4; i++) - zero(); - one(); - zero(); - - /* 2 end bits */ - outb_p(0x03, io); - udelay(5); - outb_p(0x07, io); - udelay(5); - - spin_unlock(&lock); - - return 0; -} - -int gemtek_getsigstr(struct gemtek_device *dev) -{ - spin_lock(&lock); - inb(io); - udelay(5); - spin_unlock(&lock); - if (inb(io) & 8) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} - -static int gemtek_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct gemtek_device *rt=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - strcpy(v.name, "GemTek"); - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=87*16000; - v.rangehigh=108*16000; - v.flags=VIDEO_TUNER_LOW; - v.mode=VIDEO_MODE_AUTO; - v.signal=0xFFFF*gemtek_getsigstr(rt); - strcpy(v.name, "FM"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq))) - return -EFAULT; - /* needs to be called twice in order for getsigstr to work */ - gemtek_setfreq(rt, rt->curfreq); - gemtek_setfreq(rt, rt->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE; - v.volume=1; - v.step=65535; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - if(v.flags&VIDEO_AUDIO_MUTE) - gemtek_mute(rt); - else - gemtek_unmute(rt); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int gemtek_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void gemtek_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct gemtek_device gemtek_unit; - -static struct video_device gemtek_radio= -{ - "GemTek radio", - VID_TYPE_TUNER, - VID_HARDWARE_GEMTEK, - gemtek_open, - gemtek_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - gemtek_ioctl, - NULL, - NULL -}; - -static int __init gemtek_init(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (io=0x020c or io=0x248 for the combined sound/radiocard)\n"); - return -EINVAL; - } - - if (check_region(io, 4)) - { - printk(KERN_ERR "gemtek: port 0x%x already in use\n", io); - return -EBUSY; - } - - gemtek_radio.priv=&gemtek_unit; - - if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 4, "gemtek"); - printk(KERN_INFO "GemTek Radio Card driver.\n"); - - spin_lock_init(&lock); - /* mute card - prevents noisy bootups */ - outb(0x10, io); - udelay(5); - gemtek_unit.muted = 1; - - /* this is _maybe_ unnecessary */ - outb(0x01, io); - - return 0; -} - -MODULE_AUTHOR("Jonas Munsin"); -MODULE_DESCRIPTION("A driver for the GemTek Radio Card"); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard))."); - -EXPORT_NO_SYMBOLS; - -static void __exit gemtek_cleanup(void) -{ - video_unregister_device(&gemtek_radio); - release_region(io,4); -} - -module_init(gemtek_init); -module_exit(gemtek_cleanup); - -/* - Local variables: - compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c" - End: -*/ diff --git a/drivers/char/radio-miropcm20.c b/drivers/char/radio-miropcm20.c deleted file mode 100644 index 15985380b..000000000 --- a/drivers/char/radio-miropcm20.c +++ /dev/null @@ -1,239 +0,0 @@ -/* Miro PCM20 radio driver for Linux radio support - * (c) 1998 Ruurd Reitsma - * Thanks to Norberto Pellici for the ACI device interface specification - * The API part is based on the radiotrack driver by M. Kirkwood - * This driver relies on the aci mixer (drivers/sound/lowlevel/aci.c) - * Look there for further info... - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include "../sound/miroaci.h" /* ACI Control by acimixer */ - -static int users = 0; - -struct pcm20_device -{ - int port; - int curvol; - unsigned long curfreq; - int muted; -}; - - -/* local things */ - - -static void pcm20_mute(struct pcm20_device *dev) -{ - - dev->muted = 1; - aci_write_cmd(0xa3,0x01); - -} - -static int pcm20_setvol(struct pcm20_device *dev, int vol) -{ - - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - aci_write_cmd(0xa3,0x00); /* enable card */ - } - - return 0; - } - - if(vol == 0) { /* volume = 0 means mute the card */ - aci_write_cmd(0x3d, 0x20); - aci_write_cmd(0x35, 0x20); - return 0; - } - - dev->muted = 0; - aci_write_cmd(0x3d, 32-vol); /* Right Channel */ - aci_write_cmd(0x35, 32-vol); /* Left Channel */ - dev->curvol = vol; - - return 0; -} - -static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq) -{ - unsigned char freql; - unsigned char freqh; - - freq = (freq * 10) / 16; - freql = freq & 0xff; - freqh = freq >> 8; - - - aci_write_cmd_d(0xa7, freql, freqh); /* Tune to frequency */ - - return 0; -} - -int pcm20_getsigstr(struct pcm20_device *dev) -{ - unsigned char buf; - aci_indexed_cmd(0xf0, 0x32, &buf); - if ((buf & 0x80) == 0x80) - return 0; - return 1; /* signal present */ -} - -static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct pcm20_device *pcm20=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - strcpy(v.name, "Miro PCM20"); - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=(int)(87.5*16); - v.rangehigh=(int)(108.0*16); - v.flags=0; - v.mode=VIDEO_MODE_AUTO; - v.signal=0xFFFF*pcm20_getsigstr(pcm20); - strcpy(v.name, "FM"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &pcm20->curfreq, sizeof(pcm20->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&pcm20->curfreq, arg,sizeof(pcm20->curfreq))) - return -EFAULT; - pcm20_setfreq(pcm20, pcm20->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; - v.volume=pcm20->curvol * 2048; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - if(v.flags&VIDEO_AUDIO_MUTE) - pcm20_mute(pcm20); - else - pcm20_setvol(pcm20,v.volume/2048); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int pcm20_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void pcm20_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct pcm20_device pcm20_unit; - -static struct video_device pcm20_radio= -{ - "Miro PCM 20 radio", - VID_TYPE_TUNER, - VID_HARDWARE_RTRACK, - pcm20_open, - pcm20_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - pcm20_ioctl, - NULL, - NULL -}; - -static int __init pcm20_init(void) -{ - - pcm20_radio.priv=&pcm20_unit; - - if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - printk(KERN_INFO "Miro PCM20 radio card driver.\n"); - - /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - - pcm20_unit.curvol = 0; - - return 0; -} - -MODULE_AUTHOR("Ruurd Reitsma"); -MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card."); - -EXPORT_NO_SYMBOLS; - -static void __exit pcm20_cleanup(void) -{ - video_unregister_device(&pcm20_radio); -} - -module_init(pcm20_init); -module_exit(pcm20_cleanup); - diff --git a/drivers/char/radio-rtrack2.c b/drivers/char/radio-rtrack2.c deleted file mode 100644 index c060ded4a..000000000 --- a/drivers/char/radio-rtrack2.c +++ /dev/null @@ -1,280 +0,0 @@ -/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff - * - * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood - * Coverted to new API by Alan Cox - * Various bugfixes and enhancements by Russell Kroll - * - * TODO: Allow for more than one of these foolish entities :-) - * - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_RTRACK2_PORT */ -#include - -#ifndef CONFIG_RADIO_RTRACK2_PORT -#define CONFIG_RADIO_RTRACK2_PORT -1 -#endif - -static int io = CONFIG_RADIO_RTRACK2_PORT; -static int users = 0; -static spinlock_t lock; - -struct rt_device -{ - int port; - unsigned long curfreq; - int muted; -}; - - -/* local things */ - -static void rt_mute(struct rt_device *dev) -{ - if(dev->muted) - return; - spin_lock(&lock); - outb(1, io); - spin_unlock(&lock); - dev->muted = 1; -} - -static void rt_unmute(struct rt_device *dev) -{ - if(dev->muted == 0) - return; - spin_lock(&lock); - outb(0, io); - spin_unlock(&lock); - dev->muted = 0; -} - -static void zero(void) -{ - outb_p(1, io); - outb_p(3, io); - outb_p(1, io); -} - -static void one(void) -{ - outb_p(5, io); - outb_p(7, io); - outb_p(5, io); -} - -static int rt_setfreq(struct rt_device *dev, unsigned long freq) -{ - int i; - - freq = freq / 200 + 856; - - spin_lock(&lock); - - outb_p(0xc8, io); - outb_p(0xc9, io); - outb_p(0xc9, io); - - for (i = 0; i < 10; i++) - zero (); - - for (i = 14; i >= 0; i--) - if (freq & (1 << i)) - one (); - else - zero (); - - outb_p(0xc8, io); - if (!dev->muted) - outb_p(0, io); - - spin_unlock(&lock); - return 0; -} - -static int rt_getsigstr(struct rt_device *dev) -{ - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} - -static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct rt_device *rt=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - strcpy(v.name, "RadioTrack II"); - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=88*16000; - v.rangehigh=108*16000; - v.flags=VIDEO_TUNER_LOW; - v.mode=VIDEO_MODE_AUTO; - v.signal=0xFFFF*rt_getsigstr(rt); - strcpy(v.name, "FM"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq))) - return -EFAULT; - rt_setfreq(rt, rt->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE; - v.volume=1; - v.step=65535; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - if(v.flags&VIDEO_AUDIO_MUTE) - rt_mute(rt); - else - rt_unmute(rt); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int rt_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void rt_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct rt_device rtrack2_unit; - -static struct video_device rtrack2_radio= -{ - "RadioTrack II radio", - VID_TYPE_TUNER, - VID_HARDWARE_RTRACK2, - rt_open, - rt_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - rt_ioctl, - NULL, - NULL -}; - -static int __init rtrack2_init(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); - return -EINVAL; - } - if (check_region(io, 4)) - { - printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); - return -EBUSY; - } - - rtrack2_radio.priv=&rtrack2_unit; - - spin_lock_init(&lock); - if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 4, "rtrack2"); - printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); - - /* mute card - prevents noisy bootups */ - outb(1, io); - rtrack2_unit.muted = 1; - - return 0; -} - -MODULE_AUTHOR("Ben Pfaff"); -MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); - -EXPORT_NO_SYMBOLS; - -static void __exit rtrack2_cleanup_module(void) -{ - video_unregister_device(&rtrack2_radio); - release_region(io,4); -} - -module_init(rtrack2_init); -module_exit(rtrack2_cleanup_module); - -/* - Local variables: - compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c" - End: -*/ diff --git a/drivers/char/radio-sf16fmi.c b/drivers/char/radio-sf16fmi.c deleted file mode 100644 index 55328a96f..000000000 --- a/drivers/char/radio-sf16fmi.c +++ /dev/null @@ -1,339 +0,0 @@ -/* SF16FMI radio driver for Linux radio support - * heavily based on rtrack driver... - * (c) 1997 M. Kirkwood - * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz - * - * Fitted to new interface by Alan Cox - * Made working and cleaned up functions - * - * Notes on the hardware - * - * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); - * No volume control - only mute/unmute - you have to use line volume - * control on SB-part of SF16FMI - * - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_SF16MI_PORT */ -#include - -struct fmi_device -{ - int port; - int curvol; /* 1 or 0 */ - unsigned long curfreq; /* freq in kHz */ - __u32 flags; -}; - -#ifndef CONFIG_RADIO_SF16FMI_PORT -#define CONFIG_RADIO_SF16FMI_PORT -1 -#endif - -static int io = CONFIG_RADIO_SF16FMI_PORT; -static int users = 0; -static struct semaphore lock; - -/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ -/* It is only usefull to give freq in intervall of 800 (=0.05Mhz), - * other bits will be truncated, e.g 92.7400016 -> 92.7, but - * 92.7400017 -> 92.75 - */ -#define RSF16_ENCODE(x) ((x)/800+214) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 - -static void outbits(int bits, unsigned int data, int port) -{ - while(bits--) { - if(data & 1) { - outb(5, port); - udelay(6); - outb(7, port); - udelay(6); - } else { - outb(1, port); - udelay(6); - outb(3, port); - udelay(6); - } - data>>=1; - } -} - -static inline void fmi_mute(int port) -{ - down(&lock); - outb(0x00, port); - up(&lock); -} - -static inline void fmi_unmute(int port) -{ - down(&lock); - outb(0x08, port); - up(&lock); -} - -static inline int fmi_setfreq(struct fmi_device *dev) -{ - int myport = dev->port; - unsigned long freq = dev->curfreq; - int i; - - down(&lock); - - outbits(16, RSF16_ENCODE(freq), myport); - outbits(8, 0xC0, myport); - for(i=0; i< 100; i++) - { - udelay(1400); - if(current->need_resched) - schedule(); - } -/* If this becomes allowed use it ... - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/7); -*/ - - up(&lock); - if (dev->curvol) fmi_unmute(myport); - return 0; -} - -static inline int fmi_getsigstr(struct fmi_device *dev) -{ - int val; - int res; - int myport = dev->port; - int i; - - down(&lock); - val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ - outb(val, myport); - outb(val | 0x10, myport); - for(i=0; i< 100; i++) - { - udelay(1400); - if(current->need_resched) - schedule(); - } -/* If this becomes allowed use it ... - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/7); -*/ - res = (int)inb(myport+1); - outb(val, myport); - - up(&lock); - return (res & 2) ? 0 : 0xFFFF; -} - -static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct fmi_device *fmi=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - strcpy(v.name, "SF16-FMx radio"); - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - int mult; - - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - strcpy(v.name, "FM"); - mult = (fmi->flags & VIDEO_TUNER_LOW) ? 1 : 1000; - v.rangelow = RSF16_MINFREQ/mult; - v.rangehigh = RSF16_MAXFREQ/mult; - v.flags=fmi->flags; - v.mode=VIDEO_MODE_AUTO; - v.signal = fmi_getsigstr(fmi); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - fmi->flags = v.flags & VIDEO_TUNER_LOW; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - { - unsigned long tmp = fmi->curfreq; - if (!(fmi->flags & VIDEO_TUNER_LOW)) - tmp /= 1000; - if(copy_to_user(arg, &tmp, sizeof(tmp))) - return -EFAULT; - return 0; - } - case VIDIOCSFREQ: - { - unsigned long tmp; - if(copy_from_user(&tmp, arg, sizeof(tmp))) - return -EFAULT; - if (!(fmi->flags & VIDEO_TUNER_LOW)) - tmp *= 1000; - if ( tmpRSF16_MAXFREQ ) - return -EINVAL; - /*rounding in steps of 800 to match th freq - that will be used */ - fmi->curfreq = (tmp/800)*800; - fmi_setfreq(fmi); - return 0; - } - case VIDIOCGAUDIO: - { - struct video_audio v; - v.audio=0; - v.volume=0; - v.bass=0; - v.treble=0; - v.flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); - strcpy(v.name, "Radio"); - v.mode=VIDEO_SOUND_STEREO; - v.balance=0; - v.step=0; /* No volume, just (un)mute */ - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - fmi->curvol= v.flags&VIDEO_AUDIO_MUTE ? 0 : 1; - fmi->curvol ? - fmi_unmute(fmi->port) : fmi_mute(fmi->port); - return 0; - } - case VIDIOCGUNIT: - { - struct video_unit v; - v.video=VIDEO_NO_UNIT; - v.vbi=VIDEO_NO_UNIT; - v.radio=dev->minor; - v.audio=0; /* How do we find out this??? */ - v.teletext=VIDEO_NO_UNIT; - if(copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int fmi_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void fmi_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct fmi_device fmi_unit; - -static struct video_device fmi_radio= -{ - "SF16FMx radio", - VID_TYPE_TUNER, - VID_HARDWARE_SF16MI, - fmi_open, - fmi_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - fmi_ioctl, - NULL, - NULL -}; - -static int __init fmi_init(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - if (check_region(io, 2)) - { - printk(KERN_ERR "fmi: port 0x%x already in use\n", io); - return -EBUSY; - } - - fmi_unit.port = io; - fmi_unit.curvol = 0; - fmi_unit.curfreq = 0; - fmi_unit.flags = VIDEO_TUNER_LOW; - fmi_radio.priv = &fmi_unit; - - init_MUTEX(&lock); - - if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 2, "fmi"); - printk(KERN_INFO "SF16FMx radio card driver at 0x%x.\n", io); - printk(KERN_INFO "(c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz.\n"); - /* mute card - prevents noisy bootups */ - fmi_mute(io); - return 0; -} - -MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); -MODULE_DESCRIPTION("A driver for the SF16MI radio."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); - -EXPORT_NO_SYMBOLS; - -static void __exit fmi_cleanup_module(void) -{ - video_unregister_device(&fmi_radio); - release_region(io,2); -} - -module_init(fmi_init); -module_exit(fmi_cleanup_module); - diff --git a/drivers/char/radio-terratec.c b/drivers/char/radio-terratec.c deleted file mode 100644 index 1dda1618e..000000000 --- a/drivers/char/radio-terratec.c +++ /dev/null @@ -1,358 +0,0 @@ -/* Terratec ActiveRadio ISA Standalone card driver for Linux radio support - * (c) 1999 R. Offermanns (rolf@offermanns.de) - * based on the aimslab radio driver from M. Kirkwood - * many thanks to Michael Becker and Friedhelm Birth (from TerraTec) - * - * - * History: - * 1999-05-21 First preview release - * - * Notes on the hardware: - * There are two "main" chips on the card: - * - Philips OM5610 (http://www-us.semiconductors.philips.com/acrobat/datasheets/OM5610_2.pdf) - * - Philips SAA6588 (http://www-us.semiconductors.philips.com/acrobat/datasheets/SAA6588_1.pdf) - * (you can get the datasheet at the above links) - * - * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); - * Volume Control is done digitally - * - * there is a I2C controlled RDS decoder (SAA6588) onboard, which i would like to support someday - * (as soon i have understand how to get started :) - * If you can help me out with that, please contact me!! - * - * - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_TERRATEC_PORT */ -#include - -#ifndef CONFIG_RADIO_TERRATEC_PORT -#define CONFIG_RADIO_TERRATEC_PORT 0x590 -#endif - -/**************** this ones are for the terratec *******************/ -#define BASEPORT 0x590 -#define VOLPORT 0x591 -#define WRT_DIS 0x00 -#define CLK_OFF 0x00 -#define IIC_DATA 0x01 -#define IIC_CLK 0x02 -#define DATA 0x04 -#define CLK_ON 0x08 -#define WRT_EN 0x10 -/*******************************************************************/ - -static int io = CONFIG_RADIO_TERRATEC_PORT; -static int users = 0; -static spinlock_t lock; - -struct tt_device -{ - int port; - int curvol; - unsigned long curfreq; - int muted; -}; - - -/* local things */ - -static void cardWriteVol(int volume) -{ - int i; - volume = volume+(volume * 32); // change both channels - spin_lock(&lock); - for (i=0;i<8;i++) - { - if (volume & (0x80>>i)) - outb(0x80, VOLPORT); - else outb(0x00, VOLPORT); - } - spin_unlock(&lock); -} - - - -static void tt_mute(struct tt_device *dev) -{ - dev->muted = 1; - cardWriteVol(0); -} - -static int tt_setvol(struct tt_device *dev, int vol) -{ - -// printk(KERN_ERR "setvol called, vol = %d\n", vol); - - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - cardWriteVol(vol); /* enable card */ - } - - return 0; - } - - if(vol == 0) { /* volume = 0 means mute the card */ - cardWriteVol(0); /* "turn off card" by setting vol to 0 */ - dev->curvol = vol; /* track the volume state! */ - return 0; - } - - dev->muted = 0; - - cardWriteVol(vol); - - dev->curvol = vol; - - return 0; - -} - - -/* this is the worst part in this driver */ -/* many more or less strange things are going on here, but hey, it works :) */ - -static int tt_setfreq(struct tt_device *dev, unsigned long freq1) -{ - int freq; - int i; - int p; - int temp; - long rest; - - unsigned char buffer[25]; /* we have to bit shift 25 registers */ - freq = freq1/160; /* convert the freq. to a nice to handel value */ - for(i=24;i>-1;i--) - buffer[i]=0; - - rest = freq*10+10700; /* i once had understood what is going on here */ - /* maybe some wise guy (friedhelm?) can comment this stuff */ - i=13; - p=10; - temp=102400; - while (rest!=0) - { - if (rest%temp == rest) - buffer[i] = 0; - else - { - buffer[i] = 1; - rest = rest-temp; - } - i--; - p--; - temp = temp/2; - } - - spin_lock(&lock); - - for (i=24;i>-1;i--) /* bit shift the values to the radiocard */ - { - if (buffer[i]==1) - { - outb(WRT_EN|DATA, BASEPORT); - outb(WRT_EN|DATA|CLK_ON , BASEPORT); - outb(WRT_EN|DATA, BASEPORT); - } - else - { - outb(WRT_EN|0x00, BASEPORT); - outb(WRT_EN|0x00|CLK_ON , BASEPORT); - } - } - outb(0x00, BASEPORT); - - spin_unlock(&lock); - - return 0; -} - -int tt_getsigstr(struct tt_device *dev) /* TODO */ -{ - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} - - -/* implement the video4linux api */ - -static int tt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct tt_device *tt=dev->priv; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - strcpy(v.name, "ActiveRadio"); - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow=(87*16000); - v.rangehigh=(108*16000); - v.flags=VIDEO_TUNER_LOW; - v.mode=VIDEO_MODE_AUTO; - strcpy(v.name, "FM"); - v.signal=0xFFFF*tt_getsigstr(tt); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &tt->curfreq, sizeof(tt->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&tt->curfreq, arg,sizeof(tt->curfreq))) - return -EFAULT; - tt_setfreq(tt, tt->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v,0, sizeof(v)); - v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; - v.volume=tt->curvol * 6554; - v.step=6554; - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - if(v.flags&VIDEO_AUDIO_MUTE) - tt_mute(tt); - else - tt_setvol(tt,v.volume/6554); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int tt_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void tt_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct tt_device terratec_unit; - -static struct video_device terratec_radio= -{ - "TerraTec ActiveRadio", - VID_TYPE_TUNER, - VID_HARDWARE_TERRATEC, - tt_open, - tt_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - tt_ioctl, - NULL, - NULL -}; - -static int __init terratec_init(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - if (check_region(io, 2)) - { - printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io); - return -EBUSY; - } - - terratec_radio.priv=&terratec_unit; - - spin_lock_init(&lock); - - if(video_register_device(&terratec_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 2, "terratec"); - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n"); - - /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - cardWriteVol(0); - terratec_unit.curvol = 0; - - return 0; -} - -MODULE_AUTHOR("R.OFFERMANNS & others"); -MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); - -EXPORT_NO_SYMBOLS; - -static void __exit terratec_cleanup_module(void) -{ - video_unregister_device(&terratec_radio); - release_region(io,2); - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); -} - -module_init(terratec_init); -module_exit(terratec_cleanup_module); - diff --git a/drivers/char/radio-trust.c b/drivers/char/radio-trust.c deleted file mode 100644 index 4e86bda90..000000000 --- a/drivers/char/radio-trust.c +++ /dev/null @@ -1,350 +0,0 @@ -/* radio-trust.c - Trust FM Radio card driver for Linux 2.2 - * by Eric Lammerts - * - * Based on radio-aztech.c. Original notes: - * - * Adapted to support the Video for Linux API by - * Russell Kroll . Based on original tuner code by: - * - * Quay Ly - * Donald Song - * Jason Lewis (jlewis@twilight.vtc.vsc.edu) - * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) - * William McGrath (wmcgrath@twilight.vtc.vsc.edu) - * - * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/ - */ - -#include -#include -#include -#include -#include -#include -#include -#include /* CONFIG_RADIO_TRUST_PORT */ - -/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ - -#ifndef CONFIG_RADIO_TRUST_PORT -#define CONFIG_RADIO_TRUST_PORT -1 -#endif - -static int io = CONFIG_RADIO_TRUST_PORT; -static int ioval = 0xf; -static int users = 0; -static __u16 curvol; -static __u16 curbass; -static __u16 curtreble; -static unsigned long curfreq; -static int curstereo; -static int curmute; - -/* i2c addresses */ -#define TDA7318_ADDR 0x88 -#define TSA6060T_ADDR 0xc4 - -#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0) -#define TR_SET_SCL outb(ioval |= 2, io) -#define TR_CLR_SCL outb(ioval &= 0xfd, io) -#define TR_SET_SDA outb(ioval |= 1, io) -#define TR_CLR_SDA outb(ioval &= 0xfe, io) - -static void write_i2c(int n, ...) -{ - unsigned char val, mask; - va_list args; - - va_start(args, n); - - /* start condition */ - TR_SET_SDA; - TR_SET_SCL; - TR_DELAY; - TR_CLR_SDA; - TR_CLR_SCL; - TR_DELAY; - - for(; n; n--) { - val = va_arg(args, unsigned); - for(mask = 0x80; mask; mask >>= 1) { - if(val & mask) - TR_SET_SDA; - else - TR_CLR_SDA; - TR_SET_SCL; - TR_DELAY; - TR_CLR_SCL; - TR_DELAY; - } - /* acknowledge bit */ - TR_SET_SDA; - TR_SET_SCL; - TR_DELAY; - TR_CLR_SCL; - TR_DELAY; - } - - /* stop condition */ - TR_CLR_SDA; - TR_DELAY; - TR_SET_SCL; - TR_DELAY; - TR_SET_SDA; - TR_DELAY; - - va_end(args); -} - -static void tr_setvol(__u16 vol) -{ - curvol = vol / 2048; - write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f); -} - -static int basstreble2chip[15] = { - 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 -}; - -static void tr_setbass(__u16 bass) -{ - curbass = bass / 4370; - write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]); -} - -static void tr_settreble(__u16 treble) -{ - curtreble = treble / 4370; - write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]); -} - -static void tr_setstereo(int stereo) -{ - curstereo = !!stereo; - ioval = (ioval & 0xfb) | (!curstereo << 2); - outb(ioval, io); -} - -static void tr_setmute(int mute) -{ - curmute = !!mute; - ioval = (ioval & 0xf7) | (curmute << 3); - outb(ioval, io); -} - -static int tr_getsigstr(void) -{ - int i, v; - - for(i = 0, v = 0; i < 100; i++) v |= inb(io); - return (v & 1)? 0 : 0xffff; -} - -static int tr_getstereo(void) -{ - /* don't know how to determine it, just return the setting */ - return curstereo; -} - -static void tr_setfreq(unsigned long f) -{ - f /= 160; /* Convert to 10 kHz units */ - f += 1070; /* Add 10.7 MHz IF */ - - write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); -} - -static int tr_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability v; - - v.type=VID_TYPE_TUNER; - v.channels=1; - v.audios=1; - - /* No we don't do pictures */ - v.maxwidth=0; - v.maxheight=0; - v.minwidth=0; - v.minheight=0; - - strcpy(v.name, "Trust FM Radio"); - - if(copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - - if(copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - - if(v.tuner) /* Only 1 tuner */ - return -EINVAL; - - v.rangelow = 87500 * 16; - v.rangehigh = 108000 * 16; - v.flags = VIDEO_TUNER_LOW; - v.mode = VIDEO_MODE_AUTO; - - v.signal = tr_getsigstr(); - if(tr_getstereo()) - v.flags |= VIDEO_TUNER_STEREO_ON; - - strcpy(v.name, "FM"); - - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner != 0) - return -EINVAL; - - return 0; - } - case VIDIOCGFREQ: - if(copy_to_user(arg, &curfreq, sizeof(curfreq))) - return -EFAULT; - return 0; - - case VIDIOCSFREQ: - { - unsigned long f; - - if(copy_from_user(&f, arg, sizeof(curfreq))) - return -EFAULT; - tr_setfreq(f); - return 0; - } - case VIDIOCGAUDIO: - { - struct video_audio v; - - memset(&v,0, sizeof(v)); - v.flags = VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE; - v.mode = curstereo? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - v.volume = curvol * 2048; - v.step = 2048; - v.bass = curbass * 4370; - v.treble = curtreble * 4370; - - strcpy(v.name, "Trust FM Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.audio) - return -EINVAL; - - tr_setvol(v.volume); - tr_setbass(v.bass); - tr_settreble(v.treble); - tr_setstereo(v.mode & VIDEO_SOUND_STEREO); - tr_setmute(v.flags & VIDEO_AUDIO_MUTE); - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int tr_open(struct video_device *dev, int flags) -{ - if(users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void tr_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct video_device trust_radio= -{ - "Trust FM Radio", - VID_TYPE_TUNER, - VID_HARDWARE_TRUST, - tr_open, - tr_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - tr_ioctl, - NULL, - NULL -}; - -static int __init trust_init(void) -{ - if(io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - if(check_region(io, 2)) { - printk(KERN_ERR "trust: port 0x%x already in use\n", io); - return -EBUSY; - } - if(video_register_device(&trust_radio, VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io, 2, "Trust FM Radio"); - - printk(KERN_INFO "Trust FM Radio card driver v1.0.\n"); - - write_i2c(2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ - - tr_setvol(0x8000); - tr_setbass(0x8000); - tr_settreble(0x8000); - tr_setstereo(1); - - /* mute card - prevents noisy bootups */ - tr_setmute(1); - - return 0; -} - -MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); - -EXPORT_NO_SYMBOLS; - -static void __exit cleanup_trust_module(void) -{ - video_unregister_device(&trust_radio); - release_region(io, 2); -} - -module_init(trust_init); -module_exit(cleanup_trust_module); diff --git a/drivers/char/radio-typhoon.c b/drivers/char/radio-typhoon.c deleted file mode 100644 index a0bbf343f..000000000 --- a/drivers/char/radio-typhoon.c +++ /dev/null @@ -1,402 +0,0 @@ -/* Typhoon Radio Card driver for radio support - * (c) 1999 Dr. Henrik Seidel - * - * Card manufacturer: - * http://194.18.155.92/idc/prod2.idc?nr=50753&lang=e - * - * Notes on the hardware - * - * This card has two output sockets, one for speakers and one for line. - * The speaker output has volume control, but only in four discrete - * steps. The line output has neither volume control nor mute. - * - * The card has auto-stereo according to its manual, although it all - * sounds mono to me (even with the Win/DOS drivers). Maybe it's my - * antenna - I really don't know for sure. - * - * Frequency control is done digitally. - * - * Volume control is done digitally, but there are only four different - * possible values. So you should better always turn the volume up and - * use line control. I got the best results by connecting line output - * to the sound card microphone input. For such a configuration the - * volume control has no effect, since volume control only influences - * the speaker output. - * - * There is no explicit mute/unmute. So I set the radio frequency to a - * value where I do expect just noise and turn the speaker volume down. - * The frequency change is necessary since the card never seems to be - * completely silent. - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* radio card status report */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_TYPHOON_* */ - -#define BANNER "Typhoon Radio Card driver v0.1\n" - -#ifndef CONFIG_RADIO_TYPHOON_PORT -#define CONFIG_RADIO_TYPHOON_PORT -1 -#endif - -#ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ -#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0 -#endif - -#ifndef CONFIG_PROC_FS -#undef CONFIG_RADIO_TYPHOON_PROC_FS -#endif - -struct typhoon_device { - int users; - int iobase; - int curvol; - int muted; - unsigned long curfreq; - unsigned long mutefreq; -}; - -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol); -static int typhoon_setfreq_generic(struct typhoon_device *dev, - unsigned long frequency); -static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency); -static void typhoon_mute(struct typhoon_device *dev); -static void typhoon_unmute(struct typhoon_device *dev); -static int typhoon_setvol(struct typhoon_device *dev, int vol); -static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg); -static int typhoon_open(struct video_device *dev, int flags); -static void typhoon_close(struct video_device *dev); -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS -static int typhoon_get_info(char *buf, char **start, off_t offset, int len); -#endif - -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) -{ - vol >>= 14; /* Map 16 bit to 2 bit */ - vol &= 3; - outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */ - outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */ -} - -static int typhoon_setfreq_generic(struct typhoon_device *dev, - unsigned long frequency) -{ - unsigned long outval; - unsigned long x; - - /* - * The frequency transfer curve is not linear. The best fit I could - * get is - * - * outval = -155 + exp((f + 15.55) * 0.057)) - * - * where frequency f is in MHz. Since we don't have exp in the kernel, - * I approximate this function by a third order polynomial. - * - */ - - x = frequency / 160; - outval = (x * x + 2500) / 5000; - outval = (outval * x + 5000) / 10000; - outval -= (10 * x * x + 10433) / 20866; - outval += 4 * x - 11505; - - outb_p((outval >> 8) & 0x01, dev->iobase + 4); - outb_p(outval >> 9, dev->iobase + 6); - outb_p(outval & 0xff, dev->iobase + 8); - - return 0; -} - -static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency) -{ - typhoon_setfreq_generic(dev, frequency); - dev->curfreq = frequency; - return 0; -} - -static void typhoon_mute(struct typhoon_device *dev) -{ - if (dev->muted == 1) - return; - typhoon_setvol_generic(dev, 0); - typhoon_setfreq_generic(dev, dev->mutefreq); - dev->muted = 1; -} - -static void typhoon_unmute(struct typhoon_device *dev) -{ - if (dev->muted == 0) - return; - typhoon_setfreq_generic(dev, dev->curfreq); - typhoon_setvol_generic(dev, dev->curvol); - dev->muted = 0; -} - -static int typhoon_setvol(struct typhoon_device *dev, int vol) -{ - if (dev->muted && vol != 0) { /* user is unmuting the card */ - dev->curvol = vol; - typhoon_unmute(dev); - return 0; - } - if (vol == dev->curvol) /* requested volume == current */ - return 0; - - if (vol == 0) { /* volume == 0 means mute the card */ - typhoon_mute(dev); - dev->curvol = vol; - return 0; - } - typhoon_setvol_generic(dev, vol); - dev->curvol = vol; - return 0; -} - - -static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct typhoon_device *typhoon = dev->priv; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability v; - v.type = VID_TYPE_TUNER; - v.channels = 1; - v.audios = 1; - /* No we don't do pictures */ - v.maxwidth = 0; - v.maxheight = 0; - v.minwidth = 0; - v.minheight = 0; - strcpy(v.name, "Typhoon Radio"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg, sizeof(v)) != 0) - return -EFAULT; - if (v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow = 875 * 1600; - v.rangehigh = 1080 * 1600; - v.flags = VIDEO_TUNER_LOW; - v.mode = VIDEO_MODE_AUTO; - v.signal = 0xFFFF; /* We can't get the signal strength */ - strcpy(v.name, "FM"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.tuner != 0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if (copy_to_user(arg, &typhoon->curfreq, - sizeof(typhoon->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if (copy_from_user(&typhoon->curfreq, arg, - sizeof(typhoon->curfreq))) - return -EFAULT; - typhoon_setfreq(typhoon, typhoon->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v, 0, sizeof(v)); - v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; - v.mode |= VIDEO_SOUND_MONO; - v.volume = typhoon->curvol; - v.step = 1 << 14; - strcpy(v.name, "Typhoon Radio"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.audio) - return -EINVAL; - - if (v.flags & VIDEO_AUDIO_MUTE) - typhoon_mute(typhoon); - else - typhoon_unmute(typhoon); - - if (v.flags & VIDEO_AUDIO_VOLUME) - typhoon_setvol(typhoon, v.volume); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int typhoon_open(struct video_device *dev, int flags) -{ - struct typhoon_device *typhoon = dev->priv; - if (typhoon->users) - return -EBUSY; - typhoon->users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void typhoon_close(struct video_device *dev) -{ - struct typhoon_device *typhoon = dev->priv; - typhoon->users--; - MOD_DEC_USE_COUNT; -} - -static struct typhoon_device typhoon_unit = -{ - 0, /* users */ - CONFIG_RADIO_TYPHOON_PORT, /* iobase */ - 0, /* curvol */ - 0, /* muted */ - CONFIG_RADIO_TYPHOON_MUTEFREQ, /* curfreq */ - CONFIG_RADIO_TYPHOON_MUTEFREQ /* mutefreq */ -}; - -static struct video_device typhoon_radio = -{ - "Typhoon Radio", - VID_TYPE_TUNER, - VID_HARDWARE_TYPHOON, - typhoon_open, - typhoon_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - typhoon_ioctl, - NULL, - NULL -}; - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - -static int typhoon_get_info(char *buf, char **start, off_t offset, int len) -{ - char *out = buf; - - #ifdef MODULE - #define MODULEPROCSTRING "Driver loaded as a module" - #else - #define MODULEPROCSTRING "Driver compiled into kernel" - #endif - - /* output must be kept under PAGE_SIZE */ - out += sprintf(out, BANNER); - out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n"); - out += sprintf(out, "frequency = %lu kHz\n", - typhoon_unit.curfreq >> 4); - out += sprintf(out, "volume = %d\n", typhoon_unit.curvol); - out += sprintf(out, "mute = %s\n", typhoon_unit.muted ? - "on" : "off"); - out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase); - out += sprintf(out, "mute frequency = %lu kHz\n", - typhoon_unit.mutefreq >> 4); - return out - buf; -} - -#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ - -MODULE_AUTHOR("Dr. Henrik Seidel"); -MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); -MODULE_PARM(mutefreq, "i"); -MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); - -EXPORT_NO_SYMBOLS; - -static int io = -1; - -#ifdef MODULE -static unsigned long mutefreq = 0; -#endif - -static int __init typhoon_init(void) -{ -#ifdef MODULE - if (io == -1) { - printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n"); - return -EINVAL; - } - typhoon_unit.iobase = io; - - if (mutefreq < 87000 || mutefreq > 108500) { - printk(KERN_ERR "radio-typhoon: You must set a frequency (in kHz) used when muting the card,\n"); - printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); - return -EINVAL; - } - typhoon_unit.mutefreq = mutefreq; -#endif /* MODULE */ - - printk(KERN_INFO BANNER); - io = typhoon_unit.iobase; - if (check_region(io, 8)) { - printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", - typhoon_unit.iobase); - return -EBUSY; - } - - typhoon_radio.priv = &typhoon_unit; - if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1) - return -EINVAL; - - request_region(typhoon_unit.iobase, 8, "typhoon"); - printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase); - printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n", - typhoon_unit.mutefreq); - typhoon_unit.mutefreq <<= 4; - - /* mute card - prevents noisy bootups */ - typhoon_mute(&typhoon_unit); - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL, - typhoon_get_info)) - printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); -#endif - - return 0; -} - -static void __exit typhoon_cleanup_module(void) -{ - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - remove_proc_entry("driver/radio-typhoon", NULL); -#endif - - video_unregister_device(&typhoon_radio); - release_region(io, 8); -} - -module_init(typhoon_init); -module_exit(typhoon_cleanup_module); - diff --git a/drivers/char/radio-zoltrix.c b/drivers/char/radio-zoltrix.c deleted file mode 100644 index dd688935a..000000000 --- a/drivers/char/radio-zoltrix.c +++ /dev/null @@ -1,412 +0,0 @@ -/* zoltrix radio plus driver for Linux radio support - * (c) 1998 C. van Schaik - * - * BUGS - * Due to the inconsistancy in reading from the signal flags - * it is difficult to get an accurate tuned signal. - * - * It seems that the card is not linear to 0 volume. It cuts off - * at a low volume, and it is not possible (at least I have not found) - * to get fine volume control over the low volume range. - * - * Some code derived from code by Romolo Manfredini - * romolo@bicnet.it - * - * 1999-05-06 - (C. van Schaik) - * - Make signal strength and stereo scans - * kinder to cpu while in delay - * 1999-01-05 - (C. van Schaik) - * - Changed tuning to 1/160Mhz accuracy - * - Added stereo support - * (card defaults to stereo) - * (can explicitly force mono on the card) - * (can detect if station is in stereo) - * - Added unmute function - * - Reworked ioctl functions - */ - -#include /* Modules */ -#include /* Initdata */ -#include /* check_region, request_region */ -#include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_ZOLTRIX_PORT */ - -#ifndef CONFIG_RADIO_ZOLTRIX_PORT -#define CONFIG_RADIO_ZOLTRIX_PORT -1 -#endif - -static int io = CONFIG_RADIO_ZOLTRIX_PORT; -static int users = 0; - -struct zol_device { - int port; - int curvol; - unsigned long curfreq; - int muted; - unsigned int stereo; - struct semaphore lock; -}; - - -/* local things */ - -static void sleep_delay(void) -{ - /* Sleep nicely for +/- 10 mS */ - schedule(); -} - -static int zol_setvol(struct zol_device *dev, int vol) -{ - dev->curvol = vol; - if (dev->muted) - return 0; - - down(&dev->lock); - if (vol == 0) { - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); - return 0; - } - - outb(dev->curvol-1, io); - sleep_delay(); - inb(io + 2); - up(&dev->lock); - return 0; -} - -static void zol_mute(struct zol_device *dev) -{ - dev->muted = 1; - down(&dev->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); -} - -static void zol_unmute(struct zol_device *dev) -{ - dev->muted = 0; - zol_setvol(dev, dev->curvol); -} - -static int zol_setfreq(struct zol_device *dev, unsigned long freq) -{ - /* tunes the radio to the desired frequency */ - unsigned long long bitmask, f, m; - unsigned int stereo = dev->stereo; - int i; - - if (freq == 0) - return 1; - m = (freq / 160 - 8800) * 2; - f = (unsigned long long) m + 0x4d1c; - - bitmask = 0xc480402c10080000ull; - i = 45; - - down(&dev->lock); - - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - - outb(0x40, io); - outb(0xc0, io); - - bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31)); - while (i--) { - if ((bitmask & 0x8000000000000000ull) != 0) { - outb(0x80, io); - udelay(50); - outb(0x00, io); - udelay(50); - outb(0x80, io); - udelay(50); - } else { - outb(0xc0, io); - udelay(50); - outb(0x40, io); - udelay(50); - outb(0xc0, io); - udelay(50); - } - bitmask *= 2; - } - /* termination sequence */ - outb(0x80, io); - outb(0xc0, io); - outb(0x40, io); - udelay(1000); - inb(io+2); - - udelay(1000); - - if (dev->muted) - { - outb(0, io); - outb(0, io); - inb(io + 3); - udelay(1000); - } - - up(&dev->lock); - - if(!dev->muted) - { - zol_setvol(dev, dev->curvol); - } - return 0; -} - -/* Get signal strength */ - -int zol_getsigstr(struct zol_device *dev) -{ - int a, b; - - down(&dev->lock); - outb(0x00, io); /* This stuff I found to do nothing */ - outb(dev->curvol, io); - sleep_delay(); - sleep_delay(); - - a = inb(io); - sleep_delay(); - b = inb(io); - - up(&dev->lock); - - if (a != b) - return (0); - - if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ - || (a == 0xef)) /* with a binary scanner on the card io */ - return (1); - return (0); -} - -int zol_is_stereo (struct zol_device *dev) -{ - int x1, x2; - - down(&dev->lock); - - outb(0x00, io); - outb(dev->curvol, io); - sleep_delay(); - sleep_delay(); - - x1 = inb(io); - sleep_delay(); - x2 = inb(io); - - up(&dev->lock); - - if ((x1 == x2) && (x1 == 0xcf)) - return 1; - return 0; -} - -static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct zol_device *zol = dev->priv; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability v; - v.type = VID_TYPE_TUNER; - v.channels = 1 + zol->stereo; - v.audios = 1; - /* No we don't do pictures */ - v.maxwidth = 0; - v.maxheight = 0; - v.minwidth = 0; - v.minheight = 0; - strcpy(v.name, "Zoltrix Radio"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.tuner) - return -EINVAL; - strcpy(v.name, "FM"); - v.rangelow = (int) (88.0 * 16000); - v.rangehigh = (int) (108.0 * 16000); - v.flags = zol_is_stereo(zol) - ? VIDEO_TUNER_STEREO_ON : 0; - v.flags |= VIDEO_TUNER_LOW; - v.mode = VIDEO_MODE_AUTO; - v.signal = 0xFFFF * zol_getsigstr(zol); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.tuner != 0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - if (copy_to_user(arg, &zol->curfreq, sizeof(zol->curfreq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if (copy_from_user(&zol->curfreq, arg, sizeof(zol->curfreq))) - return -EFAULT; - zol_setfreq(zol, zol->curfreq); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v, 0, sizeof(v)); - v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; - v.mode != zol_is_stereo(zol) - ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - v.volume = zol->curvol * 4096; - v.step = 4096; - strcpy(v.name, "Zoltrix Radio"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.audio) - return -EINVAL; - - if (v.flags & VIDEO_AUDIO_MUTE) - zol_mute(zol); - else - { - zol_unmute(zol); - zol_setvol(zol, v.volume / 4096); - } - - if (v.mode & VIDEO_SOUND_STEREO) - { - zol->stereo = 1; - zol_setfreq(zol, zol->curfreq); - } - if (v.mode & VIDEO_SOUND_MONO) - { - zol->stereo = 0; - zol_setfreq(zol, zol->curfreq); - } - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int zol_open(struct video_device *dev, int flags) -{ - if (users) - return -EBUSY; - users++; - MOD_INC_USE_COUNT; - return 0; -} - -static void zol_close(struct video_device *dev) -{ - users--; - MOD_DEC_USE_COUNT; -} - -static struct zol_device zoltrix_unit; - -static struct video_device zoltrix_radio = -{ - "Zoltrix Radio Plus", - VID_TYPE_TUNER, - VID_HARDWARE_ZOLTRIX, - zol_open, - zol_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, - zol_ioctl, - NULL, - NULL -}; - -static int __init zoltrix_init(void) -{ - if (io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - if (check_region(io, 2)) { - printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); - return -EBUSY; - } - if ((io != 0x20c) && (io != 0x30c)) { - printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n"); - return -ENXIO; - } - zoltrix_radio.priv = &zoltrix_unit; - - if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1) - return -EINVAL; - - request_region(io, 2, "zoltrix"); - printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); - - init_MUTEX(&zoltrix_unit.lock); - - /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - - outb(0, io); - outb(0, io); - sleep_delay(); - sleep_delay(); - inb(io + 3); - - zoltrix_unit.curvol = 0; - zoltrix_unit.stereo = 1; - - return 0; -} - -MODULE_AUTHOR("C.van Schaik"); -MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); - -EXPORT_NO_SYMBOLS; - -static void __exit zoltrix_cleanup_module(void) -{ - video_unregister_device(&zoltrix_radio); - release_region(io, 2); -} - -module_init(zoltrix_init); -module_exit(zoltrix_cleanup_module); - diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h index 3b6d2f3b1..ca1649f1e 100644 --- a/drivers/char/rio/linux_compat.h +++ b/drivers/char/rio/linux_compat.h @@ -72,8 +72,6 @@ struct ttystatics { extern int rio_debug; -#define rio_dprint(f, p) do {if (rio_debug & f) printk p;} while (0) - #define RIO_DEBUG_INIT 0x000001 #define RIO_DEBUG_BOOT 0x000002 #define RIO_DEBUG_CMD 0x000004 @@ -92,7 +90,7 @@ extern int rio_debug; #define RIO_DEBUG_REC 0x008000 #define RIO_DEBUG_SPINLOCK 0x010000 #define RIO_DEBUG_DELAY 0x020000 - +#define RIO_DEBUG_MOD_COUNT 0x040000 /* Copied over from riowinif.h . This is ugly. The winif file declares also much other stuff which is incompatible with the headers from diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 01865a09d..93d1e1c46 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -249,6 +249,8 @@ long rio_irqmask = -1; #ifndef TWO_ZERO #ifdef MODULE +MODULE_AUTHOR("Rogier Wolff , Patrick van de Lageweg "); +MODULE_DESCRIPTION("RIO driver"); MODULE_PARM(rio_poll, "i"); MODULE_PARM(rio_debug, "i"); MODULE_PARM(rio_irqmask, "i"); @@ -394,26 +396,37 @@ void rio_udelay (int usecs) void rio_inc_mod_count (void) { +#ifdef MODULE func_enter (); + rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_inc_mod_count\n"); MOD_INC_USE_COUNT; func_exit (); +#endif } void rio_dec_mod_count (void) { +#ifdef MODULE func_enter (); + rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_dec_mod_count\n"); MOD_DEC_USE_COUNT; func_exit (); +#endif } static int rio_set_real_termios (void *ptr) { - int rv; + int rv, modem; + struct tty_struct *tty; func_enter(); - rv = RIOParam( (struct Port *) ptr, CONFIG, 0, 1); + tty = ((struct Port *)ptr)->gs.tty; + + modem = (MAJOR(tty->device) == RIO_NORMAL_MAJOR0) || (MAJOR(tty->device) == RIO_NORMAL_MAJOR1); + + rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1); func_exit (); @@ -631,6 +644,7 @@ static void rio_shutdown_port (void * ptr) func_exit(); } + /* I haven't the foggiest why the decrement use count has to happen here. The whole linux serial drivers stuff needs to be redesigned. My guess is that this is a hack to minimize the impact of a bug @@ -641,7 +655,7 @@ static void rio_shutdown_port (void * ptr) static void rio_hungup (void *ptr) { func_enter (); - /* rio_dec_mod_count (); */ + rio_dec_mod_count (); func_exit (); } @@ -652,9 +666,22 @@ static void rio_hungup (void *ptr) */ static void rio_close (void *ptr) { + struct Port *PortP; + func_enter (); + + PortP = (struct Port *)ptr; + riotclose (ptr); + + if(PortP->gs.count) { + printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count); + PortP->gs.count = 0; + } + + rio_dec_mod_count (); + func_exit (); } @@ -974,13 +1001,12 @@ static int rio_init_datastructures (void) port->gs.close_delay = HZ/2; port->gs.closing_wait = 30 * HZ; port->gs.rd = &rio_real_driver; - + port->portSem = SPIN_LOCK_UNLOCKED; /* * Initializing wait queue */ init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); - + init_waitqueue_head(&port->gs.close_wait); } #else /* We could postpone initializing them to when they are configured. */ @@ -1010,7 +1036,7 @@ static int rio_init_datastructures (void) return -ENOMEM; } - +#ifdef MODULE static void rio_release_drivers(void) { func_enter(); @@ -1020,6 +1046,7 @@ static void rio_release_drivers(void) tty_unregister_driver (&rio_driver); func_exit(); } +#endif #ifdef TWO_ZERO #define PDEV unsigned char pci_bus, unsigned pci_fun @@ -1120,7 +1147,7 @@ int rio_init(void) while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { - if (pci_enable_device(pdev)) continue; + if (pci_enable_device(pdev)) continue; #else for (i=0;i< RIO_NBOARDS;i++) { if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, @@ -1157,6 +1184,7 @@ int rio_init(void) hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; hp->Mode = RIO_PCI_BOOT_FROM_RAM; + hp->HostLock = SPIN_LOCK_UNLOCKED; rio_reset_interrupt (hp); rio_start_card_running (hp); @@ -1206,7 +1234,7 @@ int rio_init(void) while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) { - if (pci_enable_device(pdev)) continue; + if (pci_enable_device(pdev)) continue; #else for (i=0;i< RIO_NBOARDS;i++) { if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h index c8b72bdce..4242197e5 100644 --- a/drivers/char/rio/rio_linux.h +++ b/drivers/char/rio/rio_linux.h @@ -29,6 +29,8 @@ #define RIO_PORTSPERBOARD 128 #define RIO_NPORTS (RIO_NBOARDS * RIO_PORTSPERBOARD) +#define MODEM_SUPPORT + #ifdef __KERNEL__ #define RIO_MAGIC 0x12345678 @@ -85,31 +87,34 @@ struct vpd_prom { #endif +void rio_dec_mod_count (void); +void rio_inc_mod_count (void); + /* Allow us to debug "in the field" without requiring clients to recompile.... */ #if 1 #define rio_spin_lock_irqsave(sem, flags) do { \ - rio_dprint(RIO_DEBUG_SPINLOCK, ("spinlockirqsave: %p %s:%d\n", \ - sem, __FILE__, __LINE__));\ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \ + sem, __FILE__, __LINE__);\ spin_lock_irqsave(sem, flags);\ } while (0) #define rio_spin_unlock_irqrestore(sem, flags) do { \ - rio_dprint(RIO_DEBUG_SPINLOCK, ("spinunlockirqrestore: %p %s:%d\n",\ - sem, __FILE__, __LINE__));\ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\ + sem, __FILE__, __LINE__);\ spin_unlock_irqrestore(sem, flags);\ } while (0) #define rio_spin_lock(sem) do { \ - rio_dprint(RIO_DEBUG_SPINLOCK, ("spinlock: %p %s:%d\n",\ - sem, __FILE__, __LINE__));\ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\ + sem, __FILE__, __LINE__);\ spin_lock(sem);\ } while (0) #define rio_spin_unlock(sem) do { \ - rio_dprint(RIO_DEBUG_SPINLOCK, ("spinunlock: %p %s:%d\n",\ - sem, __FILE__, __LINE__));\ + rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\ + sem, __FILE__, __LINE__);\ spin_unlock(sem);\ } while (0) #else @@ -173,7 +178,7 @@ static inline void *rio_memcpy_fromio (void *dest, void *source, int n) */ #ifdef DEBUG -#define rio_dprintk(f, str...) if (rio_debug & f) printk (str) +#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0) #define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n") #define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n") #define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \ diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index 8168f2133..d5ab5ba02 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -118,13 +118,13 @@ struct DownLoad * rbp; "copyin". (Crash when a pagefault occurs). */ /* disable(oldspl); */ - rio_dprint(RIO_DEBUG_BOOT, ("Data at user address 0x%x\n",(int)rbp->DataP)); + rio_dprintk (RIO_DEBUG_BOOT, "Data at user address 0x%x\n",(int)rbp->DataP); /* ** Check that we have set asside enough memory for this */ if ( rbp->Count > SIXTY_FOUR_K ) { - rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n")); + rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); p->RIOError.Error = HOST_FILE_TOO_LARGE; /* restore(oldspl); */ func_exit (); @@ -132,7 +132,7 @@ struct DownLoad * rbp; } if ( p->RIOBooting ) { - rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n")); + rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); p->RIOError.Error = BOOT_IN_PROGRESS; /* restore(oldspl); */ func_exit (); @@ -160,7 +160,7 @@ struct DownLoad * rbp; if ( copyin((int)rbp->DataP,((caddr_t)(p->RIOBootPackets))+offset, rbp->Count) ==COPYFAIL ) { - rio_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Bad data copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; /* restore(oldspl); */ func_exit (); @@ -185,7 +185,7 @@ void rio_start_card_running (struct Host * HostP) switch ( HostP->Type ) { case RIO_AT: - rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Start ISA card running\n"); WBYTE(HostP->Control, BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode @@ -198,7 +198,7 @@ void rio_start_card_running (struct Host * HostP) ** MCA handles IRQ vectors differently, so we don't write ** them to this register. */ - rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Start MCA card running\n"); WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); break; @@ -206,7 +206,7 @@ void rio_start_card_running (struct Host * HostP) /* ** EISA is totally different and expects OUTBZs to turn it on. */ - rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n"); + rio_dprintk (RIO_DEBUG_BOOT, "Start EISA card running\n"); OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); break; #endif @@ -217,11 +217,11 @@ void rio_start_card_running (struct Host * HostP) ** mapped, so we are writing to memory registers instead of io ** ports. */ - rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Start PCI card running\n"); WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); break; default: - rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type)); + rio_dprintk (RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); break; } /* @@ -260,15 +260,15 @@ register struct DownLoad *rbp; HostP = NULL; /* Assure the compiler we've initialized it */ for ( host=0; hostRIONumHosts; host++ ) { - rio_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host)); + rio_dprintk (RIO_DEBUG_BOOT, "Attempt to boot host %d\n",host); HostP = &p->RIOHosts[host]; - rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", - HostP->Type, HostP->Mode, HostP->Ivec ) ); + rio_dprintk (RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", + HostP->Type, HostP->Mode, HostP->Ivec); if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) { - rio_dprint(RIO_DEBUG_BOOT, ("%s %d already running\n","Host",host)); + rio_dprintk (RIO_DEBUG_BOOT, "%s %d already running\n","Host",host); continue; } @@ -285,13 +285,13 @@ register struct DownLoad *rbp; */ StartP = (caddr_t)&Cad[p->RIOConf.HostLoadBase-rbp->Count]; - rio_dprint(RIO_DEBUG_BOOT, ("kernel virtual address for host is 0x%x\n", (int)Cad ) ); - rio_dprint(RIO_DEBUG_BOOT, ("kernel virtual address for download is 0x%x\n", (int)StartP ) ); - rio_dprint(RIO_DEBUG_BOOT, ("host loadbase is 0x%x\n",p->RIOConf.HostLoadBase)); - rio_dprint(RIO_DEBUG_BOOT, ("size of download is 0x%x\n", rbp->Count ) ); + rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%x\n", (int)Cad ); + rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%x\n", (int)StartP); + rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase); + rio_dprintk (RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); if ( p->RIOConf.HostLoadBase < rbp->Count ) { - rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Bin too large\n"); p->RIOError.Error = HOST_FILE_TOO_LARGE; func_exit (); return EFBIG; @@ -307,7 +307,7 @@ register struct DownLoad *rbp; ** This ain't going to be none too clever if the download ** code is bigger than this segment. */ - rio_dprint(RIO_DEBUG_BOOT, ("Copy in code\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Copy in code\n"); /* ** PCI hostcard can't cope with 32 bit accesses and so need to copy @@ -318,7 +318,7 @@ register struct DownLoad *rbp; DownCode = sysbrk(rbp->Count); if ( !DownCode ) { - rio_dprint(RIO_DEBUG_BOOT, ("No system memory available\n")); + rio_dprintk (RIO_DEBUG_BOOT, "No system memory available\n"); p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; func_exit (); return ENOMEM; @@ -326,7 +326,7 @@ register struct DownLoad *rbp; bzero(DownCode, rbp->Count); if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) { - rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n"); p->RIOError.Error = COPYIN_FAILED; func_exit (); return EFAULT; @@ -337,13 +337,13 @@ register struct DownLoad *rbp; sysfree( DownCode, rbp->Count ); } else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) { - rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n"); p->RIOError.Error = COPYIN_FAILED; func_exit (); return EFAULT; } - rio_dprint(RIO_DEBUG_BOOT, ("Copy completed\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Copy completed\n"); /* ** S T O P ! @@ -444,8 +444,8 @@ register struct DownLoad *rbp; WBYTE( DestP[6] , NFIX(0) ); WBYTE( DestP[7] , JUMP(8) ); - rio_dprint(RIO_DEBUG_BOOT, ("host loadbase is 0x%x\n",p->RIOConf.HostLoadBase)); - rio_dprint(RIO_DEBUG_BOOT, ("startup offset is 0x%x\n",offset)); + rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase); + rio_dprintk (RIO_DEBUG_BOOT, "startup offset is 0x%x\n",offset); /* ** Flag what is going on @@ -459,19 +459,19 @@ register struct DownLoad *rbp; */ OldParmMap = RWORD(HostP->__ParmMapR); - rio_dprint(RIO_DEBUG_BOOT, ("Original parmmap is 0x%x\n",OldParmMap)); + rio_dprintk (RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n",OldParmMap); /* ** And start it running (I hope). ** As there is nothing dodgy or obscure about the ** above code, this is guaranteed to work every time. */ - rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", - HostP->Type, HostP->Mode, HostP->Ivec ) ); + rio_dprintk (RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", + HostP->Type, HostP->Mode, HostP->Ivec); rio_start_card_running(HostP); - rio_dprint(RIO_DEBUG_BOOT, ("Set control port\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Set control port\n"); /* ** Now, wait for upto five seconds for the Tp to setup the parmmap @@ -479,7 +479,7 @@ register struct DownLoad *rbp; */ for ( wait_count=0; (wait_countRIOConf.StartupTime)&& (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { - rio_dprint(RIO_DEBUG_BOOT, ("Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR))); + rio_dprintk (RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR)); delay(HostP, HUNDRED_MS); } @@ -489,8 +489,8 @@ register struct DownLoad *rbp; ** has crashed & burned in a really spectacular way */ if ( RWORD(HostP->__ParmMapR) == OldParmMap ) { - rio_dprint(RIO_DEBUG_BOOT, ("parmmap 0x%x\n", RWORD(HostP->__ParmMapR))); - rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail\n")); + rio_dprintk (RIO_DEBUG_BOOT, "parmmap 0x%x\n", RWORD(HostP->__ParmMapR)); + rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); #define HOST_DISABLE \ HostP->Flags &= ~RUN_STATE; \ @@ -501,7 +501,7 @@ register struct DownLoad *rbp; HOST_DISABLE; } - rio_dprint(RIO_DEBUG_BOOT, ("Running 0x%x\n",RWORD(HostP->__ParmMapR))); + rio_dprintk (RIO_DEBUG_BOOT, "Running 0x%x\n", RWORD(HostP->__ParmMapR)); /* ** Well, the board thought it was OK, and setup its parmmap @@ -513,10 +513,10 @@ register struct DownLoad *rbp; ** Grab a 32 bit pointer to the parmmap structure */ ParmMapP = (PARM_MAP *)RIO_PTR(Cad,RWORD(HostP->__ParmMapR)); - rio_dprint(RIO_DEBUG_BOOT, ("ParmMapP : %x\n", (int)ParmMapP)); + rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP); ParmMapP = (PARM_MAP *)((unsigned long)Cad + (unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); - rio_dprint(RIO_DEBUG_BOOT, ("ParmMapP : %x\n", (int)ParmMapP)); + rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP); /* ** The links entry should be 0xFFFF; we set it up @@ -524,8 +524,8 @@ register struct DownLoad *rbp; ** which links to use. */ if ( (RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF ) { - rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail %s\n", HostP->Name)); - rio_dprint(RIO_DEBUG_BOOT, ("Links = 0x%x\n",RWORD(ParmMapP->links))); + rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); + rio_dprintk (RIO_DEBUG_BOOT, "Links = 0x%x\n",RWORD(ParmMapP->links)); HOST_DISABLE; } @@ -535,28 +535,28 @@ register struct DownLoad *rbp; ** now wait for the card to set all the parmmap->XXX stuff ** this is a wait of upto two seconds.... */ - rio_dprint(RIO_DEBUG_BOOT, ("Looking for init_done - %d ticks\n",p->RIOConf.StartupTime)); + rio_dprintk (RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n",p->RIOConf.StartupTime); HostP->timeout_id = 0; for ( wait_count=0; (wait_countRIOConf.StartupTime) && !RWORD(ParmMapP->init_done); wait_count++ ) { - rio_dprint(RIO_DEBUG_BOOT, ("Waiting for init_done\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Waiting for init_done\n"); delay(HostP, HUNDRED_MS); } - rio_dprint(RIO_DEBUG_BOOT, ("OK! init_done!\n")); + rio_dprintk (RIO_DEBUG_BOOT, "OK! init_done!\n"); if (RWORD(ParmMapP->error) != E_NO_ERROR || !RWORD(ParmMapP->init_done) ) { - rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail %s\n", HostP->Name)); - rio_dprint(RIO_DEBUG_BOOT, ("Timedout waiting for init_done\n")); + rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); + rio_dprintk (RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); HOST_DISABLE; } - rio_dprint(RIO_DEBUG_BOOT, ("Got init_done\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Got init_done\n"); /* ** It runs! It runs! */ - rio_dprint(RIO_DEBUG_BOOT, ("Host ID %x Running\n",HostP->UniqueNum)); + rio_dprintk (RIO_DEBUG_BOOT, "Host ID %x Running\n",HostP->UniqueNum); /* ** set the time period between interrupts. @@ -580,12 +580,14 @@ register struct DownLoad *rbp; HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN]; HostP->UnixRups[RupN].Id = RupN+1; HostP->UnixRups[RupN].BaseSysPort = NO_PORT; + HostP->UnixRups[RupN].RupLock = SPIN_LOCK_UNLOCKED; } for ( RupN = 0; RupNUnixRups[RupN+MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup; HostP->UnixRups[RupN+MAX_RUP].Id = 0; HostP->UnixRups[RupN+MAX_RUP].BaseSysPort = NO_PORT; + HostP->UnixRups[RupN+MAX_RUP].RupLock = SPIN_LOCK_UNLOCKED; } /* @@ -622,7 +624,7 @@ register struct DownLoad *rbp; } } - rio_dprint(RIO_DEBUG_BOOT, ("Set the card running... \n")); + rio_dprintk (RIO_DEBUG_BOOT, "Set the card running... \n"); /* ** last thing - show the world that everything is in place */ @@ -638,7 +640,7 @@ register struct DownLoad *rbp; p->RIOSystemUp++; - rio_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec)); + rio_dprintk (RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec); func_exit (); return 0; } @@ -672,7 +674,7 @@ struct PKT *PacketP; ** If we haven't been told what to boot, we can't boot it. */ if ( p->RIONumBootPkts == 0 ) { - rio_dprint(RIO_DEBUG_BOOT, ("No RTA code to download yet\n")); + rio_dprintk (RIO_DEBUG_BOOT, "No RTA code to download yet\n"); return 0; } @@ -693,7 +695,7 @@ struct PKT *PacketP; ** try to unhook a command block from the command free list. */ if ( !(CmdBlkP = RIOGetCmdBlk()) ) { - rio_dprint(RIO_DEBUG_BOOT, ("No command blocks to boot RTA! come back later.\n")); + rio_dprintk (RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); return 0; } @@ -716,8 +718,8 @@ struct PKT *PacketP; ** We only expect one type of command - a BOOT_REQUEST! */ if ( RBYTE(PktCmdP->Command) != BOOT_REQUEST ) { - rio_dprint(RIO_DEBUG_BOOT, ("Unexpected command %d on BOOT RUP %d of host %d\n", - PktCmdP->Command,Rup,HostP-p->RIOHosts)); + rio_dprintk (RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %d\n", + PktCmdP->Command,Rup,HostP-p->RIOHosts); ShowPacket( DBG_BOOT, PacketP ); RIOFreeCmdBlk( CmdBlkP ); return 1; @@ -754,9 +756,9 @@ struct PKT *PacketP; bcopy("BOOT",(void *)&CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN],4); - rio_dprint(RIO_DEBUG_BOOT, ("Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n", + rio_dprintk (RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n", HostP-p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, - p->RIOConf.RtaLoadBase)); + p->RIOConf.RtaLoadBase); /* ** If this host is in slave mode, send the RTA an invalid boot @@ -775,11 +777,11 @@ struct PKT *PacketP; */ sequence = RWORD(PktCmdP->Sequence); - rio_dprint(RIO_DEBUG_BOOT, ("Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup)); + rio_dprintk (RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup); if ( sequence >= p->RIONumBootPkts ) { - rio_dprint(RIO_DEBUG_BOOT, ("Got a request for packet %d, max is %d\n", sequence, - p->RIONumBootPkts)); + rio_dprintk (RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, + p->RIONumBootPkts); ShowPacket( DBG_BOOT, PacketP ); } @@ -821,26 +823,26 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk driver will never think that the RTA has booted... -- REW */ p->RIOBooting = 0; - rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot completed - BootInProgress now %d\n", p->RIOBooting)); + rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); /* ** Determine type of unit (16/8 port RTA). */ RtaType = GetUnitType(RtaUniq); if ( Rup >= (ushort)MAX_RUP ) { - rio_dprint(RIO_DEBUG_BOOT, ("RIO: Host %s has booted an RTA(%d) on link %c\n", - HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A' )); + rio_dprintk (RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", + HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A'); } else { - rio_dprint(RIO_DEBUG_BOOT, ("RIO: RTA %s has booted an RTA(%d) on link %c\n", + rio_dprintk (RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, - RBYTE(PktCmdP->LinkNum)+'A')); + RBYTE(PktCmdP->LinkNum)+'A'); } - rio_dprint(RIO_DEBUG_BOOT, ("UniqNum is 0x%x\n",RtaUniq)); + rio_dprintk (RIO_DEBUG_BOOT, "UniqNum is 0x%x\n",RtaUniq); if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) ) { - rio_dprint(RIO_DEBUG_BOOT, ( "Illegal RTA Uniq Number\n")); + rio_dprintk (RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); return TRUE; } @@ -861,8 +863,8 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk */ if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) { - rio_dprint(RIO_DEBUG_BOOT, ("RTA failed to suspend booting on link %c\n", - 'A' + MyLink)); + rio_dprintk (RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", + 'A' + MyLink); } } else @@ -874,8 +876,8 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk */ WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30); } - rio_dprint(RIO_DEBUG_BOOT, ("RTA %x not owned - suspend booting down link %c on unit %x\n", - RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum)); + rio_dprintk (RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", + RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); return TRUE; } @@ -925,16 +927,16 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk } } if (RtaType == TYPE_RTA16) { - rio_dprint(RIO_DEBUG_BOOT, ("RTA will be given IDs %d+%d\n", - entry+1, entry2+1)); + rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", + entry+1, entry2+1); } else { - rio_dprint(RIO_DEBUG_BOOT, ("RTA will be given ID %d\n",entry+1)); + rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given ID %d\n",entry+1); } return TRUE; } } - rio_dprint(RIO_DEBUG_BOOT, ("RTA not configured for this host\n")); + rio_dprintk (RIO_DEBUG_BOOT, "RTA not configured for this host\n"); if ( Rup >= (ushort)MAX_RUP ) { @@ -978,13 +980,13 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk entry2 = HostP->Mapping[entry].ID2 - 1; if ( (HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq) ) - rio_dprint(RIO_DEBUG_BOOT, ("Found previous tentative slots (%d+%d)\n", - entry, entry2)); + rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", + entry, entry2); else continue; } else - rio_dprint(RIO_DEBUG_BOOT, ("Found previous tentative slot (%d)\n",entry)); + rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n",entry); if (! p->RIONoMessage) cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A'); return TRUE; @@ -1013,7 +1015,7 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk ** + Configure RTA on host A. We now have the same RTA configured ** with different ports on two different hosts. */ - rio_dprint(RIO_DEBUG_BOOT, ("Have we seen RTA %x before?\n", RtaUniq )); + rio_dprintk (RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq ); found = 0; Flag = 0; /* Convince the compiler this variable is initialized */ for ( host = 0; !found && (host < p->RIONumHosts); host++ ) @@ -1029,12 +1031,12 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk if (RtaType == TYPE_RTA16) { MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1]; - rio_dprint(RIO_DEBUG_BOOT, ("This RTA is units %d+%d from host %s\n", - rta+1, MapP->ID2, p->RIOHosts[host].Name )); + rio_dprintk (RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", + rta+1, MapP->ID2, p->RIOHosts[host].Name); } else - rio_dprint(RIO_DEBUG_BOOT, ("This RTA is unit %d from host %s\n", - rta+1, p->RIOHosts[host].Name )); + rio_dprintk (RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", + rta+1, p->RIOHosts[host].Name); found = 1; break; } @@ -1052,12 +1054,12 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk */ if ( !MapP ) { - rio_dprint(RIO_DEBUG_BOOT, ("Look for RTA %x in RIOSavedTable\n",RtaUniq)); + rio_dprintk (RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n",RtaUniq); for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ ) { - rio_dprint(RIO_DEBUG_BOOT, ("Check table entry %d (%x)", + rio_dprintk (RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, - p->RIOSavedTable[rta].RtaUniqueNum )); + p->RIOSavedTable[rta].RtaUniqueNum); if ( (p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq) ) @@ -1073,11 +1075,11 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk break; } MapP2 = &p->RIOSavedTable[entry2]; - rio_dprint(RIO_DEBUG_BOOT, ("This RTA is from table entries %d+%d\n", - rta, entry2)); + rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", + rta, entry2); } else - rio_dprint(RIO_DEBUG_BOOT, ("This RTA is from table entry %d\n", rta)); + rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta); break; } } @@ -1133,8 +1135,8 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk { if (Flag & SLOT_IN_USE) { - rio_dprint(RIO_DEBUG_BOOT, ( - "This RTA configured on another host - move entry to current host (1)\n")); + rio_dprintk (RIO_DEBUG_BOOT, + "This RTA configured on another host - move entry to current host (1)\n"); HostP->Mapping[entry].SysPort = MapP->SysPort; CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN ); HostP->Mapping[entry].Flags = @@ -1147,12 +1149,12 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; if ( HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted ) p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort; - rio_dprint(RIO_DEBUG_BOOT, ("SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name)); + rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name); } else { - rio_dprint(RIO_DEBUG_BOOT, ( - "This RTA has a tentative entry on another host - delete that entry (1)\n")); + rio_dprintk (RIO_DEBUG_BOOT, + "This RTA has a tentative entry on another host - delete that entry (1)\n"); HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; #if NEED_TO_FIX @@ -1177,9 +1179,9 @@ int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct Pk p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort; if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted) p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort; - rio_dprint(RIO_DEBUG_BOOT, ("SysPort %d, Name %s\n", + rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int)HostP->Mapping[entry2].SysPort, - HostP->Mapping[entry].Name)); + HostP->Mapping[entry].Name); } else HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | @@ -1272,7 +1274,7 @@ struct Host *HostP; { int link; - rio_dprint(RIO_DEBUG_BOOT, ("FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq)); + rio_dprintk (RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq); HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); HostP->Mapping[entry].SysPort = NO_PORT; diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 835d815d3..3a330a07c 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -91,12 +91,12 @@ struct Map * MapP; { struct CmdBlk *CmdBlkP; - rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA\n")); + rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA\n"); CmdBlkP = RIOGetCmdBlk(); if ( !CmdBlkP ) { - rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA: GetCmdBlk failed\n")); + rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n"); return ENXIO; } @@ -111,7 +111,7 @@ struct Map * MapP; CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF; if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA: Failed to queue foad command\n")); + rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n"); return EIO; } return 0; @@ -124,12 +124,12 @@ struct Map * MapP; { struct CmdBlk *CmdBlkP; - rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA\n")); + rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA\n"); CmdBlkP = RIOGetCmdBlk(); if ( !CmdBlkP ) { - rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA: GetCmdBlk failed\n")); + rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n"); return ENXIO; } @@ -144,7 +144,7 @@ struct Map * MapP; CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF; if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA: Failed to queue zombie command\n")); + rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n"); return EIO; } return 0; @@ -158,7 +158,7 @@ int (* func)( struct Host *HostP, struct Map *MapP ); { uint Host; - rio_dprint(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); @@ -203,7 +203,7 @@ caddr_t arg; uint Host; if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("RIO_IDENTIFY_RTA copy failed\n")); + rio_dprintk (RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } @@ -231,12 +231,12 @@ caddr_t arg; */ struct CmdBlk *CmdBlkP; - rio_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA\n")); + rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA\n"); CmdBlkP = RIOGetCmdBlk(); if ( !CmdBlkP ) { - rio_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA: GetCmdBlk failed\n")); + rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n"); return ENXIO; } @@ -249,9 +249,8 @@ caddr_t arg; CmdBlkP->Packet.data[1] = 0; CmdBlkP->Packet.data[2] = IdRta.ID; - if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) - == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA: Failed to queue command\n")); + 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; @@ -274,11 +273,10 @@ caddr_t arg; struct Host *HostP; struct CmdBlk *CmdBlkP; - rio_dprint(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_dprint(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; } @@ -289,7 +287,7 @@ caddr_t arg; CmdBlkP = RIOGetCmdBlk(); if ( !CmdBlkP ) { - rio_dprint(RIO_DEBUG_CMD, ("UFOAD: GetCmdBlk failed\n")); + rio_dprintk (RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n"); return ENXIO; } @@ -310,7 +308,7 @@ caddr_t arg; if ( HostP->UniqueNum == KillUnit.UniqueNum ) { if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link, CmdBlkP) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("UFOAD: Failed queue command\n")); + rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); return EIO; } return 0; @@ -320,7 +318,7 @@ caddr_t arg; if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) { CmdBlkP->Packet.dest_unit = ID+1; if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("UFOAD: Failed queue command\n")); + rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); return EIO; } return 0; @@ -339,12 +337,12 @@ int Link; { struct CmdBlk *CmdBlkP; - rio_dprint(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_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA: GetCmdBlk failed\n")); + rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n"); return ENXIO; } @@ -359,7 +357,7 @@ int Link; CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF; if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA: Failed to queue iwait command\n")); + rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n"); return EIO; } return 0; @@ -416,6 +414,7 @@ PKT *PacketP; ushort subCommand; unsigned long flags; + func_enter (); #ifdef CHECK CheckHost( Host ); @@ -435,34 +434,35 @@ PKT *PacketP; UnixRupP = &HostP->UnixRups[rup]; SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA); - rio_dprint(RIO_DEBUG_CMD, ("Command on rup %d, port %d\n", rup, SysPort)); + rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); #ifdef CHECK CheckRup( rup ); CheckUnixRupP( UnixRupP ); #endif if ( UnixRupP->BaseSysPort == NO_PORT ) { - rio_dprint(RIO_DEBUG_CMD, ("OBSCURE ERROR!\n")); - rio_dprint(RIO_DEBUG_CMD, ("Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n")); - rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: Host number %d, name ``%s''\n", - HostP-p->RIOHosts, HostP->Name )); - rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: Rup number 0x%x\n", rup)); - - if ( Rup >= (ushort)MAX_RUP ) - rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: This is the RUP for RTA ``%s''\n", - HostP->Mapping[Rup].Name )); - else - rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", 'A' + Rup - MAX_RUP, HostP->Name )); - - rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Destination 0x%x:0x%x\n", - PacketP->dest_unit, PacketP->dest_port )); - rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Source 0x%x:0x%x\n", - PacketP->src_unit, PacketP->src_port )); - rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len )); - rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control)); - rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum )); - rio_dprint(RIO_DEBUG_CMD, ("COMMAND information: Host Port Number 0x%x, - Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command )); + 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 ); return TRUE; } @@ -470,13 +470,10 @@ PKT *PacketP; CheckSysPort( SysPort ); #endif PortP = p->RIOPortp[ SysPort ]; -#if 0 - ttyP = PortP->TtyP; -#endif rio_spin_lock_irqsave(&PortP->portSem, flags); switch( RBYTE(PktCmdP->Command) ) { case BREAK_RECEIVED: - rio_dprint(RIO_DEBUG_CMD, ("Received a break!\n")); + 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 @@ -486,16 +483,16 @@ PKT *PacketP; break; case COMPLETE: - rio_dprint(RIO_DEBUG_CMD, ("Command complete on phb %d host %d\n", - RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts)); + 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_dprint(RIO_DEBUG_CMD, ("Memory dump cmd (0x%x) from addr 0x%x\n", - RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr))); + 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_dprint(RIO_DEBUG_CMD, ("Read register (0x%x)\n", RWORD(PktCmdP->SubAddr))); + rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr)); p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST); break; default : @@ -504,18 +501,16 @@ PKT *PacketP; } if (subCommand) break; - rio_dprint(RIO_DEBUG_CMD, ("New status is 0x%x was 0x%x\n", - RBYTE(PktCmdP->PortStatus),PortP->PortState)); + 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_dprint(RIO_DEBUG_CMD, ("Mark status & wakeup\n")); + rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n"); PortP->PortState = RBYTE(PktCmdP->PortStatus); /* What should we do here ... wakeup( &PortP->PortState ); */ - } - else { - rio_dprint(RIO_DEBUG_CMD, ("No change\n")); - } + } else + rio_dprintk (RIO_DEBUG_CMD, "No change\n"); /* FALLTHROUGH */ case MODEM_STATUS: @@ -527,7 +522,7 @@ PKT *PacketP; ReportedModemStatus = RBYTE(PktCmdP->ModemStatus); if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) { - rio_dprint(RIO_DEBUG_CMD, ("Modem status unchanged 0x%x\n", PortP->ModemState)); + rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); /* ** Update ModemState just in case tbusy or tstop states have ** changed. @@ -535,8 +530,8 @@ PKT *PacketP; PortP->ModemState = ReportedModemStatus; } else { - rio_dprint(RIO_DEBUG_CMD, ("Modem status change from 0x%x to 0x%x\n", - PortP->ModemState, ReportedModemStatus)); + 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 ) { @@ -551,50 +546,41 @@ PKT *PacketP; ** If the device is a modem, then check the modem ** carrier. */ - if(!(ttyP->t_cflag & CLOCAL) && - ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) - { + if (PortP->gs.tty == 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 ) - { + if ( PortP->ModemState & MSVR1_CD ) { /* ** Has carrier just appeared? */ - if (!(ttyP->t_state & CARR_ON)) - { - rio_dprint(RIO_DEBUG_CMD, PortP,DBG_MODEM,"Carrier just came up.\n"); - ttyP->t_state |=CARR_ON; + if (!(PortP->State & RIO_CARR_ON)) { + rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n"); + PortP->State |= RIO_CARR_ON; /* ** wakeup anyone in WOPEN */ - if ( ttyP->t_state & (ISOPEN|WOPEN) ) - wakeup((caddr_t)&ttyP->t_canq); + if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) ) + wake_up_interruptible (&PortP->gs.open_wait); #ifdef STATS PortP->Stat.ModemOnCnt++; #endif } - } - else - { + } else { /* ** Has carrier just dropped? */ - if (ttyP->t_state & CARR_ON) - { - /* - ** send SIGHUP to the process group - */ - if ( ttyP->t_state & (ISOPEN|WOPEN) ) - { - signal(ttyP->t_pgrp,SIGHUP); - ttyflush(ttyP,(FREAD|FWRITE)); - } - ttyP->t_state &= ~CARR_ON; - wakeup( (caddr_t)&PortP->TxBufferOut ); - wakeup( (caddr_t)&PortP->TxBufferIn ); - rio_dprint(RIO_DEBUG_CMD, PortP,DBG_MODEM,"Carrier just went down.\n"); + if (PortP->State & RIO_CARR_ON) { + 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"); #ifdef STATS PortP->Stat.ModemOffCnt++; #endif @@ -607,11 +593,14 @@ PKT *PacketP; break; default: - rio_dprint(RIO_DEBUG_CMD, ("Unknown command %d on CMD_RUP of host %d\n", - RBYTE(PktCmdP->Command),HostP-p->RIOHosts)); + 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 (); + return TRUE; } /* @@ -667,11 +656,8 @@ struct CmdBlk *CmdBlkP; CheckRup( Rup ); CheckCmdBlkP( CmdBlkP ); #endif - - rio_dprint(RIO_DEBUG_CMD, ("RIOQueueCmdBlk(Host, Rup %d, 0x%x)\n", Rup, (int)CmdBlkP )); - if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) { - rio_dprint(RIO_DEBUG_CMD, ("Illegal rup number %d in RIOQueueCmdBlk\n",Rup)); + rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup); RIOFreeCmdBlk( CmdBlkP ); return RIO_FAIL; } @@ -685,11 +671,12 @@ struct CmdBlk *CmdBlkP; ** straight on the RUP.... */ if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && + (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP) :TRUE)) { - rio_dprint(RIO_DEBUG_CMD, ("RUP inactive-placing command straight on. Cmd byte is 0x%x\n", - CmdBlkP->Packet.data[0])); + 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! @@ -711,28 +698,27 @@ struct CmdBlk *CmdBlkP; return RIO_SUCCESS; } - - rio_dprint(RIO_DEBUG_CMD, ("RUP active - en-queing\n")); + rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n"); if ( UnixRupP->CmdsWaitingP != NULL) - rio_dprint(RIO_DEBUG_CMD, ("Rup active - command waiting\n")); + rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n"); if ( UnixRupP->CmdPendingP != NULL ) - rio_dprint(RIO_DEBUG_CMD, ("Rup active - command pending\n")); + rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n"); if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE ) - rio_dprint(RIO_DEBUG_CMD, ("Rup active - command rup not ready\n")); + rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); Base = &UnixRupP->CmdsWaitingP; - rio_dprint(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_dprint(RIO_DEBUG_CMD, ("Command cmdblk 0x%x here\n",(int)(*Base))); + rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base)); Base = &((*Base)->NextP); - rio_dprint(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_dprint(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; @@ -775,17 +761,15 @@ struct Host * HostP; if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) { int FreeMe; - /* rio_dprint(RIO_DEBUG_CMD, ("RIORupCmd( %d, %d )\n", HostP-p->RIOHosts, Rup )); */ - PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt)); ShowPacket( DBG_CMD, PacketP ); switch ( RBYTE(PacketP->dest_port) ) { case BOOT_RUP: - rio_dprint(RIO_DEBUG_CMD, ("Incoming Boot %s packet '%x'\n", + rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", RBYTE(PacketP->len) & 0x80 ? "Command":"Data", - RBYTE(PacketP->data[0]) )); + RBYTE(PacketP->data[0])); rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe= RIOBootRup(p, Rup,HostP,PacketP); rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); @@ -800,8 +784,8 @@ struct Host * HostP; rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe= RIOCommandRup(p, Rup,HostP,PacketP); if (PacketP->data[5] == MEMDUMP) { - rio_dprint(RIO_DEBUG_CMD, ("Memdump from 0x%x complete\n", - *(ushort *) &(PacketP->data[6]))); + 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 ); } @@ -815,19 +799,19 @@ struct Host * HostP; break; default: - rio_dprint(RIO_DEBUG_CMD, ("Unknown RUP %d\n", RBYTE(PacketP->dest_port))); + rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port)); FreeMe = 1; break; } if ( FreeMe ) { - rio_dprint(RIO_DEBUG_CMD, ("Free processed incoming command packet\n")); + rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n"); put_free_end(HostP,PacketP); WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE); if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) { - rio_dprint(RIO_DEBUG_CMD, ("Handshake rup %d\n",Rup)); + rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup); WWORD(UnixRupP->RupP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); } @@ -839,7 +823,7 @@ struct Host * HostP; ** and it has completed, then tidy it up. */ if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) ) { + (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { /* ** we are idle. ** there is a command in pending. @@ -848,11 +832,11 @@ struct Host * HostP; ** what happened). */ if ( CmdBlkP->Packet.dest_port == BOOT_RUP ) - rio_dprint(RIO_DEBUG_CMD, ("Free Boot %s Command Block '%x'\n", + rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command":"Data", - CmdBlkP->Packet.data[0] )); + CmdBlkP->Packet.data[0]); - rio_dprint(RIO_DEBUG_CMD, ("Command 0x%x completed\n",(int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP); /* ** Clear the Rup lock to prevent mutual exclusion. @@ -880,27 +864,27 @@ struct Host * HostP; */ if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ (UnixRupP->CmdPendingP == NULL) && - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) ) { + (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { /* ** if the pre-function is non-zero, call it. ** If it returns RIO_FAIL then don't ** send this command yet! */ #ifdef CHECK -CheckCmdBlkP( CmdBlkP ); + CheckCmdBlkP (CmdBlkP); #endif if ( !(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) { - rio_dprint(RIO_DEBUG_CMD, ("Not ready to start command 0x%x\n",(int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP); } else { - rio_dprint(RIO_DEBUG_CMD, ("Start new command 0x%x Cmd byte is 0x%x\n", - (int)CmdBlkP, CmdBlkP->Packet.data[0])); + rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", + (int)CmdBlkP, CmdBlkP->Packet.data[0]); /* ** Whammy! blat that pack! */ #ifdef CHECK -CheckPacketP( (PKT *)RIO_PTR(HostP->Caddr,UnixRupP->RupP->txpkt) ); + 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)); @@ -1026,7 +1010,7 @@ struct CmdBlk *CmdBlkP; ** MAGIC! (Basically, handshake the RX buffer, so that ** the RTAs upstream can be re-enabled.) */ - rio_dprint(RIO_DEBUG_CMD, ("Util: Set RX handshake bit\n")); + 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); @@ -1046,7 +1030,7 @@ struct CmdBlk *CmdBlkP; #ifdef CHECK CheckPortP( PortP ); #endif - rio_dprint(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 ) { diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index fa68646d5..af61dc997 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -137,7 +137,7 @@ int copyin (int arg, caddr_t dp, int siz) { int rv; - rio_dprint (RIO_DEBUG_CTRL, ("Copying %d bytes from user %p to %p.\n", siz, (void *) arg, dp)); + 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 < 0) return COPYFAIL; else return rv; @@ -148,7 +148,7 @@ int copyout (caddr_t dp, int arg, int siz) { int rv; - rio_dprint (RIO_DEBUG_CTRL, ("Copying %d bytes to user %p from %p.\n", siz, (void *) arg, dp)); + 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 < 0) return COPYFAIL; else return rv; @@ -207,7 +207,7 @@ int su; Host=0; PortP = NULL; - rio_dprint(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) { /* @@ -218,7 +218,7 @@ int su; ** otherwise just the specified host card will be changed. */ case RIO_SET_TIMER: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_TIMER to %dms\n", (uint)arg)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint)arg); { int host, value; host = (uint)arg >> 16; @@ -296,42 +296,42 @@ int su; */ case RIO_FOAD_RTA: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_FOAD_RTA\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); return RIOCommandRta(p, (uint)arg, RIOFoadRta); case RIO_ZOMBIE_RTA: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_ZOMBIE_RTA\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); return RIOCommandRta(p, (uint)arg, RIOZombieRta); case RIO_IDENTIFY_RTA: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_IDENTIFY_RTA\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); return RIOIdentifyRta(p, arg); case RIO_KILL_NEIGHBOUR: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_KILL_NEIGHBOUR\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n"); return RIOKillNeighbour(p, arg); case SPECIAL_RUP_CMD: { struct CmdBlk *CmdBlkP; - rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD\n")); + rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); if (copyin((int)arg, (caddr_t)&SpecialRupCmd, sizeof(SpecialRupCmd)) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } CmdBlkP = RIOGetCmdBlk(); if ( !CmdBlkP ) { - rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD GetCmdBlk failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("Queue special rup command for host %d rup %d\n", - SpecialRupCmd.Host, SpecialRupCmd.RupNum)); + 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"); @@ -348,7 +348,7 @@ RIO_DEBUG_CTRL, if (su) return EPERM; case RIO_ALL_MODEM: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_ALL_MODEM\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n"); p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; return EINVAL; @@ -356,44 +356,44 @@ RIO_DEBUG_CTRL, if (su) /* ** Read the routing table from the device driver to user space */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_TABLE\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_GET_TABLE copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } { int entry; - rio_dprint(RIO_DEBUG_CTRL, ("*****\nMAP ENTRIES\n") ); + rio_dprintk (RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n"); for ( entry=0; entryRIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue; - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) ); - rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) ); + 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_dprint(RIO_DEBUG_CTRL, ("*****\nEND MAP ENTRIES\n") ); + rio_dprintk (RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n"); } p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */ return 0; @@ -402,16 +402,16 @@ RIO_DEBUG_CTRL, if (su) /* ** Write the routing table to the device driver from user space */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE !Root\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } @@ -449,17 +449,17 @@ RIO_DEBUG_CTRL, if (su) ** Send bindings table, containing unique numbers of RTAs owned ** by this system to user space */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS !Root\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -470,17 +470,17 @@ RIO_DEBUG_CTRL, if (su) ** Receive a bindings table, containing unique numbers of RTAs owned ** by this system */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS !Root\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } @@ -493,10 +493,10 @@ RIO_DEBUG_CTRL, if (su) ** Bind this RTA to host, so that it will be booted by ** host in 'boot owned RTAs' mode. */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_BIND_RTA\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_BIND_RTA !Root\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n"); p->RIOError.Error = NOT_SUPER_USER; return EPERM; } @@ -508,8 +508,8 @@ RIO_DEBUG_CTRL, if (su) ** Already exists - delete */ p->RIOBindTab[Entry] = 0L; - rio_dprint(RIO_DEBUG_CTRL, ("Removing Rta %x from p->RIOBindTab\n", - (int) arg)); + rio_dprintk (RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n", + (int) arg); return 0; } } @@ -518,90 +518,90 @@ RIO_DEBUG_CTRL, if (su) */ if (EmptySlot != -1) { p->RIOBindTab[EmptySlot] = (int) arg; - rio_dprint(RIO_DEBUG_CTRL, ("Adding Rta %x to p->RIOBindTab\n", - (int) arg)); + rio_dprintk (RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n", + (int) arg); } else { - rio_dprint(RIO_DEBUG_CTRL, ("p->RIOBindTab full! - Rta %x not added\n", - (int) arg)); + rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", + (int) arg); return 1; } return 0; } case RIO_RESUME : - rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME\n"); port = (uint) arg; if ((port < 0) || (port > 511)) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Bad port number %d\n", port)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Port %d not mapped\n", port)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Port %d not open\n", port)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME failed\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); return EBUSY; } else { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME: Port %d resumed\n", port)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_ASSIGN_RTA\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_ASSIGN_RTA !Root\n")); + 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_dprint(RIO_DEBUG_CTRL, ("Copy from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_CHANGE_NAME\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_CHANGE_NAME !Root\n")); + 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_dprint(RIO_DEBUG_CTRL, ("Copy from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_DELETE_RTA\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_DELETE_RTA !Root\n")); + 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_dprint(RIO_DEBUG_CTRL, ("Copy from data space failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Copy from data space failed\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } @@ -638,7 +638,7 @@ RIO_DEBUG_CTRL, if (su) return 0; case RIO_GET_LOG: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_LOG\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_LOG\n"); #ifdef LOGGING RIOGetLog(arg); return 0; @@ -653,17 +653,17 @@ RIO_DEBUG_CTRL, if (su) p->RIOError.Error = COPYIN_FAILED; return EFAULT; } - rio_dprint(RIO_DEBUG_CTRL, ("Get module type for port %d\n", port)); + rio_dprintk (RIO_DEBUG_CTRL, "Get module type for port %d\n", port); if ( port < 0 || port > 511 ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_MODTYPE: Bad port number %d\n", port)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_GET_MODTYPE: Port %d not mapped\n", port)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port); p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; return EINVAL; } @@ -703,7 +703,7 @@ RIO_DEBUG_CTRL, if (su) */ case RIO_BLOCK_OPENS: - rio_dprint(RIO_DEBUG_CTRL, ("Opens block until booted\n")); + 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; @@ -712,33 +712,33 @@ RIO_DEBUG_CTRL, if (su) return 0; case RIO_SETUP_PORTS: - rio_dprint(RIO_DEBUG_CTRL, ("Setup ports\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Setup ports\n"); if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) == COPYFAIL ) { p->RIOError.Error = COPYIN_FAILED; - rio_dprint(RIO_DEBUG_CTRL, ("EFAULT")); + 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_dprint(RIO_DEBUG_CTRL, ("ENXIO")); + 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_dprint(RIO_DEBUG_CTRL, ("EINVAL")); + rio_dprintk (RIO_DEBUG_CTRL, "EINVAL"); return EINVAL; } if ( !p->RIOPortp ) { cprintf("No p->RIOPortp array!\n"); - rio_dprint(RIO_DEBUG_CTRL, ("No p->RIOPortp array!\n")); + rio_dprintk (RIO_DEBUG_CTRL, "No p->RIOPortp array!\n"); return EIO; } - rio_dprint(RIO_DEBUG_CTRL, ("entering loop (%d %d)!\n", PortSetup.From, PortSetup.To)); + rio_dprintk (RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To); for (loop=PortSetup.From; loop<=PortSetup.To; loop++) { - rio_dprint(RIO_DEBUG_CTRL, ("in loop (%d)!\n", loop)); + rio_dprintk (RIO_DEBUG_CTRL, "in loop (%d)!\n", loop); #if 0 PortP = p->RIOPortp[loop]; if ( !PortP->TtyP ) @@ -791,12 +791,12 @@ RIO_DEBUG_CTRL, if (su) rio_spin_unlock_irqrestore( &PortP->portSem , flags); #endif } - rio_dprint(RIO_DEBUG_CTRL, ("after loop (%d)!\n", loop)); - rio_dprint(RIO_DEBUG_CTRL, ("Retval:%x\n", retval ) ); + 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_dprint(RIO_DEBUG_CTRL, ("Get port setup\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Get port setup\n"); if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) == COPYFAIL ) { p->RIOError.Error = COPYIN_FAILED; @@ -832,7 +832,7 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_GET_PORT_PARAMS : - rio_dprint(RIO_DEBUG_CTRL, ("Get port params\n")); + 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; @@ -845,7 +845,7 @@ RIO_DEBUG_CTRL, if (su) PortP = (p->RIOPortp[PortParams.Port]); PortParams.Config = PortP->Config; PortParams.State = PortP->State; - rio_dprint(RIO_DEBUG_CTRL, ("Port %d\n", PortParams.Port)); + rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); if (copyout((caddr_t)&PortParams, (int)arg, sizeof(struct PortParams)) == COPYFAIL ) { @@ -855,7 +855,7 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_GET_PORT_TTY : - rio_dprint(RIO_DEBUG_CTRL, ("Get port tty\n")); + 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; @@ -866,7 +866,7 @@ RIO_DEBUG_CTRL, if (su) return ENXIO; } - rio_dprint(RIO_DEBUG_CTRL, ("Port %d\n", PortTty.port)); + 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; @@ -887,7 +887,7 @@ RIO_DEBUG_CTRL, if (su) p->RIOError.Error = COPYIN_FAILED; return EFAULT; } - rio_dprint(RIO_DEBUG_CTRL, ("Set port %d tty\n", PortTty.port)); + 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; @@ -906,7 +906,7 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_SET_PORT_PARAMS : - rio_dprint(RIO_DEBUG_CTRL, ("Set port params\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Set port params\n"); if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams)) == COPYFAIL ) { p->RIOError.Error = COPYIN_FAILED; @@ -923,7 +923,7 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_GET_PORT_STATS : - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GET_PORT_STATS\n")); + 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; @@ -949,7 +949,7 @@ RIO_DEBUG_CTRL, if (su) case RIO_RESET_PORT_STATS : port = (uint) arg; - rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESET_PORT_STATS\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); if ( port >= RIO_PORTS ) { p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; return ENXIO; @@ -965,7 +965,7 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_GATHER_PORT_STATS : - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GATHER_PORT_STATS\n")); + 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; @@ -985,22 +985,22 @@ RIO_DEBUG_CTRL, if (su) case RIO_READ_LEVELS: { int num; - rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_LEVELS\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n"); for ( num=0; RIODbInf[num].Flag; num++ ) ; - rio_dprint(RIO_DEBUG_CTRL, ("%d levels to copy\n",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_dprint(RIO_DEBUG_CTRL, ("ReadLevels Copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "ReadLevels Copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } - rio_dprint(RIO_DEBUG_CTRL, ("%d levels to copied\n",num)); + rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copied\n",num); return retval; } #endif case RIO_READ_CONFIG: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_CONFIG\n")); + 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; @@ -1009,7 +1009,7 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_SET_CONFIG: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_CONFIG\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n"); if ( !su ) { p->RIOError.Error = NOT_SUPER_USER; return EPERM; @@ -1029,11 +1029,11 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_START_POLLER: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_START_POLLER\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_START_POLLER\n"); return EINVAL; case RIO_STOP_POLLER: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_STOP_POLLER\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n"); if ( !su ) { p->RIOError.Error = NOT_SUPER_USER; return EPERM; @@ -1043,7 +1043,7 @@ RIO_DEBUG_CTRL, if (su) case RIO_SETDEBUG: case RIO_GETDEBUG: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SETDEBUG/RIO_GETDEBUG\n")); + 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; @@ -1057,18 +1057,18 @@ RIO_DEBUG_CTRL, if (su) } p->rio_debug = DebugCtrl.Debug; p->RIODebugWait = DebugCtrl.Wait; - rio_dprint(RIO_DEBUG_CTRL, ("Set global debug to 0x%x set wait to 0x%x\n", - p->rio_debug,p->RIODebugWait)); + rio_dprintk (RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", + p->rio_debug,p->RIODebugWait); } else { - rio_dprint(RIO_DEBUG_CTRL, ("Get global debug 0x%x wait 0x%x\n", - p->rio_debug,p->RIODebugWait)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_SET/GET DEBUG: bad port number %d\n", - DebugCtrl.SysPort)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", + DebugCtrl.SysPort); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1076,8 +1076,8 @@ RIO_DEBUG_CTRL, if (su) } else if ( DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET/GET DEBUG: bad port number %d\n", - DebugCtrl.SysPort)); + 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; } @@ -1089,16 +1089,16 @@ RIO_DEBUG_CTRL, if (su) rio_spin_lock_irqsave(&PortP->portSem, flags); p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug; rio_spin_unlock_irqrestore( &PortP->portSem , flags); - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SETDEBUG 0x%x\n", - p->RIOPortp[DebugCtrl.SysPort]->Debug)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", + p->RIOPortp[DebugCtrl.SysPort]->Debug); } else { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_GETDEBUG 0x%x\n", - p->RIOPortp[DebugCtrl.SysPort]->Debug)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_GETDEBUG: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1111,12 +1111,12 @@ RIO_DEBUG_CTRL, if (su) ** We return MAX_VERSION_LEN bytes, being a ** textual null terminated string. */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n") ); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID\n"); if ( copyout( (caddr_t)RIOVersid(), (int)arg, sizeof(struct rioVersion) ) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space (host=%d)\n",Host) ); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1150,10 +1150,10 @@ RIO_DEBUG_CTRL, if (su) ** Enquire as to the number of hosts located ** at init time. */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_NUM_HOSTS\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); if (copyout((caddr_t)&p->RIONumHosts, (int)arg, sizeof(p->RIONumHosts) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_NUM_HOSTS: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1163,9 +1163,9 @@ RIO_DEBUG_CTRL, if (su) /* ** Kill host. This may not be in the final version... */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_FOAD %d\n", (int)arg)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int)arg); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_FOAD: Not super user\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); p->RIOError.Error = NOT_SUPER_USER; return EPERM; } @@ -1213,27 +1213,27 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_DOWNLOAD: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n"); if ( !su ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Not super user\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Copy in from user space failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } - rio_dprint(RIO_DEBUG_CTRL, ("Copied in download code for product code 0x%x\n", - DownLoad.ProductCode ) ); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Bad product code %d passed\n", - DownLoad.ProductCode)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", + DownLoad.ProductCode); p->RIOError.Error = NO_SUCH_PRODUCT; return ENXIO; } @@ -1254,63 +1254,63 @@ RIO_DEBUG_CTRL, if (su) if (copyin((int)arg, (caddr_t)&host, sizeof(host) ) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ( - "RIO_HOST_REQ: Copy in from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_PARMS\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_PARMS: Copy out to user space failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); return EFAULT; } } return retval; case RIO_HOST_REQ: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); if (copyin((int)arg, (caddr_t)&HostReq, sizeof(HostReq) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Copy in from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Illegal host number %d\n", - HostReq.HostNum)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", + HostReq.HostNum); return ENXIO; } - rio_dprint(RIO_DEBUG_CTRL, ("Request for host %d\n", HostReq.HostNum)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n"); return EFAULT; } return retval; case RIO_HOST_DPRAM: - rio_dprint(RIO_DEBUG_CTRL, ("Request for DPRAM\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Request for DPRAM\n"); if ( copyin( (int)arg, (caddr_t)&HostDpRam, sizeof(HostDpRam) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Copy in from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Illegal host number %d\n", - HostDpRam.HostNum)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", + HostDpRam.HostNum); return ENXIO; } - rio_dprint(RIO_DEBUG_CTRL, ("Request for host %d\n", HostDpRam.HostNum)); + rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum); if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) { int off; @@ -1321,7 +1321,7 @@ RIO_DEBUG_CTRL, if (su) if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP, sizeof(struct DpRam) ) == COPYFAIL ) { p->RIOError.Error = COPYOUT_FAILED; - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); return EFAULT; } } @@ -1329,15 +1329,15 @@ RIO_DEBUG_CTRL, if (su) (int)HostDpRam.DpRamP, sizeof(struct DpRam) ) == COPYFAIL ) { p->RIOError.Error = COPYOUT_FAILED; - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); return EFAULT; } return retval; case RIO_SET_BUSY: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_BUSY\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); if ( (int)arg < 0 || (int)arg > 511 ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_BUSY: Bad port number %d\n",(int)arg)); + 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; } @@ -1351,26 +1351,26 @@ RIO_DEBUG_CTRL, if (su) ** The daemon want port information ** (probably for debug reasons) */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); if ( copyin((int)arg, (caddr_t)&PortReq, sizeof(PortReq) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Copy in from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Illegal port number %d\n", - PortReq.SysPort)); + 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_dprint(RIO_DEBUG_CTRL, ("Request for port %d\n", PortReq.SysPort)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n"); return EFAULT; } return retval; @@ -1380,40 +1380,40 @@ RIO_DEBUG_CTRL, if (su) ** The daemon want rup information ** (probably for debug reasons) */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); if (copyin((int)arg, (caddr_t)&RupReq, sizeof(RupReq) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Copy in from user space failed\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Illegal host number %d\n", - RupReq.HostNum)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Illegal rup number %d\n", - RupReq.RupNum)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Host %d not running\n", - RupReq.HostNum)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", + RupReq.HostNum); p->RIOError.Error = HOST_NOT_RUNNING; return EIO; } - rio_dprint(RIO_DEBUG_CTRL, ("Request for rup %d from host %d\n", - RupReq.RupNum,RupReq.HostNum)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); return EFAULT; } return retval; @@ -1423,39 +1423,39 @@ RIO_DEBUG_CTRL, if (su) ** The daemon want lpb information ** (probably for debug reasons) */ - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); if (copyin((int)arg, (caddr_t)&LpbReq, sizeof(LpbReq) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Bad copy from user space\n")); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Illegal host number %d\n", - LpbReq.Host)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Illegal link number %d\n", - LpbReq.Link)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Host %d not running\n", - LpbReq.Host)); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", + LpbReq.Host ); p->RIOError.Error = HOST_NOT_RUNNING; return EIO; } - rio_dprint(RIO_DEBUG_CTRL, ("Request for lpb %d from host %d\n", - LpbReq.Link, LpbReq.Host)); + 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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1494,7 +1494,7 @@ RIO_DEBUG_CTRL, if (su) p->RIOError.Error = NOT_RECEIVING_PROCESS; return EPERM; } - rio_dprint(RIO_DEBUG_CTRL, ("Clear signal process to zero\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Clear signal process to zero\n"); p->RIOSignalProcess = 0; return retval; @@ -1526,10 +1526,10 @@ RIO_DEBUG_CTRL, if (su) case RIO_MAP_B50_TO_57600: case RIO_MAP_B110_TO_110: case RIO_MAP_B110_TO_115200: - rio_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping\n"); port = (uint) arg; if ( port < 0 || port > 511 ) { - rio_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping: Bad port number %d\n", port)); + rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; return EINVAL; } @@ -1553,14 +1553,14 @@ RIO_DEBUG_CTRL, if (su) return retval; case RIO_STREAM_INFO: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_STREAM_INFO\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n"); return EINVAL; case RIO_SEND_PACKET: - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SEND_PACKET\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); if ( copyin( (int)arg, (caddr_t)&SendPack, sizeof(SendPack) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_SEND_PACKET: Bad copy from user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; return EFAULT; } @@ -1605,7 +1605,7 @@ RIO_DEBUG_CTRL, if (su) case RIO_WHAT_MESG: if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg, sizeof(p->RIONoMessage) )==COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_WHAT_MESG: Bad copy to user space\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1617,8 +1617,8 @@ RIO_DEBUG_CTRL, if (su) p->RIOError.Error = COPYIN_FAILED; return EFAULT; } - rio_dprint(RIO_DEBUG_CTRL, ("RIO_MEM_DUMP host %d rup %d addr %x\n", - SubCmd.Host, SubCmd.Rup, SubCmd.Addr)); + 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; @@ -1638,7 +1638,7 @@ RIO_DEBUG_CTRL, if (su) rio_spin_lock_irqsave(&PortP->portSem, flags); if ( RIOPreemptiveCmd(p, PortP, MEMDUMP ) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_MEM_DUMP failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n"); rio_spin_unlock_irqrestore( &PortP->portSem , flags); return EBUSY; } @@ -1648,7 +1648,7 @@ RIO_DEBUG_CTRL, if (su) rio_spin_unlock_irqrestore( &PortP->portSem , flags); if ( copyout( (caddr_t)p->RIOMemDump, (int)arg, MEMDUMP_SIZE) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_MEM_DUMP copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1657,14 +1657,14 @@ RIO_DEBUG_CTRL, if (su) case RIO_TICK: if ((int)arg < 0 || (int)arg >= p->RIONumHosts) return EINVAL; - rio_dprint(RIO_DEBUG_CTRL, ("Set interrupt for host %d\n", (int)arg )); + 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_dprint(RIO_DEBUG_CTRL, ("Clear interrupt for host %d\n", (int)arg )); + rio_dprintk (RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int)arg); WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff); return 0; @@ -1684,12 +1684,12 @@ RIO_DEBUG_CTRL, if (su) p->RIOError.Error = COPYIN_FAILED; return EFAULT; } - rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_REGISTER host %d rup %d port %d reg %x\n", - SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr)); + 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_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping: Bad port number %d\n", - SubCmd.Port)); + 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; } @@ -1711,7 +1711,7 @@ RIO_DEBUG_CTRL, if (su) rio_spin_lock_irqsave(&PortP->portSem, flags); if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_REGISTER failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n"); rio_spin_unlock_irqrestore( &PortP->portSem , flags); return EBUSY; } @@ -1721,7 +1721,7 @@ RIO_DEBUG_CTRL, if (su) rio_spin_unlock_irqrestore( &PortP->portSem , flags); if (copyout((caddr_t)&p->CdRegister, (int)arg, sizeof(uint)) == COPYFAIL ) { - rio_dprint(RIO_DEBUG_CTRL, ("RIO_READ_REGISTER copy failed\n")); + rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return EFAULT; } @@ -1738,18 +1738,18 @@ RIO_DEBUG_CTRL, if (su) switch ( (uint)arg & RIO_DEV_MASK ) { case RIO_DEV_DIRECT: arg = (caddr_t)drv_makedev(major(dev), port); - rio_dprint(RIO_DEBUG_CTRL, ("Makedev direct 0x%x is 0x%x\n",port, (int)arg )); + 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_dprint(RIO_DEBUG_CTRL, ("Makedev modem 0x%x is 0x%x\n",port, (int)arg )); + 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_dprint(RIO_DEBUG_CTRL, ("Makedev printer 0x%x is 0x%x\n",port, (int)arg )); + rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg); return (int)arg; } - rio_dprint(RIO_DEBUG_CTRL, ("MAKE Device is called\n")); + rio_dprintk (RIO_DEBUG_CTRL, "MAKE Device is called\n"); return EINVAL; } /* @@ -1766,17 +1766,17 @@ RIO_DEBUG_CTRL, if (su) mino = RIO_UNMODEM(dv); if ( RIO_ISMODEM(dv) ) { - rio_dprint(RIO_DEBUG_CTRL, ("Minor for device 0x%x: modem %d\n", dv, mino)); + rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino); arg = (caddr_t)(mino | RIO_DEV_MODEM); } else { - rio_dprint(RIO_DEBUG_CTRL, ("Minor for device 0x%x: direct %d\n", dv, mino)); + 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_dprint(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 (); @@ -1803,18 +1803,18 @@ uchar Cmd; #endif if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_CTRL, ("Preemptive command to deleted RTA ignored\n")); + rio_dprintk (RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n"); return RIO_FAIL; } if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) { - rio_dprint(RIO_DEBUG_CTRL, ("Cannot allocate command block for command %d on port %d\n", - Cmd, PortP->PortNum)); + rio_dprintk (RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", + Cmd, PortP->PortNum); return RIO_FAIL; } - rio_dprint(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]; @@ -1840,40 +1840,40 @@ uchar Cmd; switch ( Cmd ) { case MEMDUMP: - rio_dprint(RIO_DEBUG_CTRL, ("Queue MEMDUMP command blk 0x%x (addr 0x%x)\n", - (int)CmdBlkP, (int)SubCmd.Addr)); + 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_dprint(RIO_DEBUG_CTRL, ("Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP); break; case READ_REGISTER: - rio_dprint(RIO_DEBUG_CTRL, ("Queue READ_REGISTER (0x%x) command blk 0x%x\n", - (int)SubCmd.Addr, (int)CmdBlkP)); + 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_dprint(RIO_DEBUG_CTRL, ("Queue RESUME command blk 0x%x\n",(int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n",(int)CmdBlkP); break; case RFLUSH: - rio_dprint(RIO_DEBUG_CTRL, ("Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP); CmdBlkP->PostFuncP = RIORFlushEnable; break; case SUSPEND: - rio_dprint(RIO_DEBUG_CTRL, ("Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP); break; case MGET : - rio_dprint(RIO_DEBUG_CTRL, ("Queue MGET command blk 0x%x\n", (int)CmdBlkP)); + 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_dprint(RIO_DEBUG_CTRL, ("Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP); break; case WFLUSH: @@ -1883,12 +1883,12 @@ uchar Cmd; ** RTA. */ if ((int)((char)PortP->WflushFlag) == (int)-1) { - rio_dprint(RIO_DEBUG_CTRL, ("Trashed WFLUSH, WflushFlag about to wrap!")); + rio_dprintk (RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!"); RIOFreeCmdBlk(CmdBlkP); return(RIO_FAIL); } else { - rio_dprint(RIO_DEBUG_CTRL, ("Queue WFLUSH command blk 0x%x\n", - (int)CmdBlkP)); + rio_dprintk (RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n", + (int)CmdBlkP); CmdBlkP->PostFuncP = RIOWFlushMark; } break; diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 59cfdedd5..cbefdac2d 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -81,7 +81,7 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; #include "control.h" #include "cirrus.h" #include "rioioctl.h" - +#include "rio_linux.h" #undef bcopy #define bcopy rio_pcicopy @@ -109,7 +109,7 @@ struct RioHostInfo * info; */ if ( !p->RIOPortp ) { - rio_dprint(RIO_DEBUG_INIT, ("Allocating and setting up driver data structures\n") ); + rio_dprintk (RIO_DEBUG_INIT, "Allocating and setting up driver data structures\n"); RIOAllocDataStructs(p); /* allocate host/port structs */ RIOSetupDataStructs(p); /* setup topology structs */ @@ -155,16 +155,16 @@ struct RioHostInfo * info; if ( info->bus & ISA_BUS ) { - rio_dprint(RIO_DEBUG_INIT, ("initialising card %d (ISA)\n", p->RIONumHosts) ); + rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (ISA)\n", p->RIONumHosts); RIOISAinit(p, p->mode); } else { - rio_dprint(RIO_DEBUG_INIT, ("initialising card %d (PCI)\n", p->RIONumHosts) ); + rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (PCI)\n", p->RIONumHosts); RIOPCIinit(p, RIO_PCI_DEFAULT_MODE); } - rio_dprint(RIO_DEBUG_INIT, ("Total hosts initialised so far : %d\n", p->RIONumHosts) ); + rio_dprintk (RIO_DEBUG_INIT, "Total hosts initialised so far : %d\n", p->RIONumHosts); #ifdef FUTURE_RELEASE @@ -193,13 +193,13 @@ int mode; p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec, (int (*)())rio_intr, (char*)p->RIONumHosts); - rio_dprint(RIO_DEBUG_INIT, ("Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid ) ); + rio_dprintk (RIO_DEBUG_INIT, "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid ); if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) { return; } else { - rio_dprint(RIO_DEBUG_INIT, ("RIODoAT failed\n")); + rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n"); p->RIOFailed++; } #endif @@ -268,7 +268,7 @@ int Base; ** map it in in one 64K block. */ if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) { - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Couldn't map the board in!\n")); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n"); return((caddr_t)0); } @@ -285,8 +285,8 @@ int Base; ** Signature mismatch - card not at this address */ RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr); - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Couldn't match the signature 0x%x 0x%x!\n", - (int)cardp, off)); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n", + (int)cardp, off); return((caddr_t)0); } } @@ -356,10 +356,10 @@ int mode; ((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_dprint(RIO_DEBUG_INIT, ("RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum)); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum); p->RIONumHosts++; - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Tests Passed at 0x%x\n", Base)); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base); return(1); } #if 0 @@ -378,7 +378,7 @@ int RIOMCAinit(int Mode) ** is only FAST LINKS */ Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks; - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOMCAinit(%d)\n",Mode); + rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode); /* @@ -395,7 +395,7 @@ int RIOMCAinit(int Mode) */ if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId) { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Potential MCA card in slot %d\n",SlotNumber); + rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber); /* ** Card appears to be a RIO MCA card! @@ -417,48 +417,44 @@ int RIOMCAinit(int Mode) */ Ivec = inb(McaIrqEnable); - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Ivec is %x\n",Ivec); + rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec); switch ( Ivec & McaIrqMask ) { case McaIrq9: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ9\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n"); break; case McaIrq3: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ3\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n"); break; case McaIrq4: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ4\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n"); break; case McaIrq7: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ7\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n"); break; case McaIrq10: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ10\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n"); break; case McaIrq11: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ11\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n"); break; case McaIrq12: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ12\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n"); break; case McaIrq15: - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ15\n"); + rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n"); break; } /* ** If the card enable bit isn't set, then set it! */ - if ((Ivec & McaCardEnable) != McaCardEnable ) - { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"McaCardEnable not set - setting!\n"); - outb(McaIrqEnable,Ivec|McaCardEnable); - } - else - { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"McaCardEnable already set\n"); - } + if ((Ivec & McaCardEnable) != McaCardEnable) { + rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n"); + outb(McaIrqEnable,Ivec|McaCardEnable); + } else + rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n"); /* ** Convert the IRQ enable mask into something useful @@ -468,10 +464,10 @@ int RIOMCAinit(int Mode) /* ** Find the physical address */ - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"inb(McaMemory) is %x\n",inb(McaMemory)); + rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory)); Paddr = McaAddress(inb(McaMemory)); - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"MCA card has Ivec %d Addr %x\n",Ivec,Paddr); + rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr); if ( Paddr != 0 ) { @@ -482,21 +478,20 @@ int RIOMCAinit(int Mode) Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr ); if ( Handle == -1 ) { - rio_dprint(RIO_DEBUG_INIT, ("Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE,Paddr); + rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr; continue; } - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Board mapped to vaddr 0x%x\n",Caddr); + rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr); /* ** And check that it is actually there! */ if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS ) { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Board has passed test\n"); - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT, - "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", - SlotNumber,RIO_MCA,Paddr,Caddr,Mode); + rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n"); + rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", + SlotNumber, RIO_MCA, Paddr, Caddr, Mode); /* ** Board has passed its scrub test. Fill in all the @@ -524,25 +519,25 @@ int RIOMCAinit(int Mode) /* ** It failed the test, so ignore it. */ - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"TEST FAILED\n"); + rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n"); RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr ); } } else { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d - Paddr zero!\n",SlotNumber); + rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber); } } else { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d NOT RIO\n",SlotNumber); + rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber); } } /* ** Now we have checked all the slots, turn off the MCA slot selector */ outb(McaSlotSelect,0); - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d NOT RIO\n",SlotNumber); + rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber); return ret; } @@ -565,13 +560,13 @@ int RIOEISAinit( int Mode ) if ( EISADone ) { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOEISAinit() - already done, return.\n"); + rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n"); return(0); } EISADone++; - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOEISAinit()\n"); + rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n"); /* @@ -584,23 +579,21 @@ int RIOEISAinit( int Mode ) Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) | INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO); - /* rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT, "Check EISA slot %d, ID=%x\n",EisaSlot,Ident); */ - if ( Ident == RIO_EISA_IDENT ) { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Found Specialix product\n"); + rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n"); if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE ) { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Not Specialix RIO - Product number %x\n", - INBZ(EisaSlot,EISA_PRODUCT_NUMBER)); + rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n", + INBZ(EisaSlot, EISA_PRODUCT_NUMBER)); continue; /* next slot */ } /* ** Its a Specialix RIO! */ - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIO Revision %d\n", - INBZ(EisaSlot,EISA_REVISION_NUMBER)); + rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n", + INBZ(EisaSlot, EISA_REVISION_NUMBER)); RIOMachineType |= (1<RIOLastPCISearch != RIO_SUCCESS) ) { - rio_dprint(RIO_DEBUG_INIT, ("Currently testing slot %d\n", slot ) ); + rio_dprintk (RIO_DEBUG_INIT, "Currently testing slot %d\n", slot); if (read_config(0,slot,0) == RIO_PCI_JET_CARD) { p->RIOHosts[p->RIONumHosts].Ivec = 0; @@ -934,7 +927,7 @@ int Mode; Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */ if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) { - rio_dprint(RIO_DEBUG_INIT, ("Goofed up slot\n") ); /* what! */ + rio_dprintk (RIO_DEBUG_INIT, "Goofed up slot\n"); /* what! */ slot++; continue; } @@ -942,11 +935,11 @@ int Mode; p->RIOHosts[p->RIONumHosts].PaddrP = Paddr; Ivec = (read_config(0,slot,0x3c) & 0xff); - rio_dprint(RIO_DEBUG_INIT, ("PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec ) ); + rio_dprintk (RIO_DEBUG_INIT, "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec); Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr ); if (Handle == -1) { - rio_dprint(RIO_DEBUG_INIT, ("Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr ) ); + rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr); slot++; continue; } @@ -954,9 +947,8 @@ int Mode; p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec, (int (*)())rio_intr, (char *)p->RIONumHosts); if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { - rio_dprint(RIO_DEBUG_INIT, ("Board has passed test\n")); - rio_dprint(RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, - Mode)); + rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n"); + rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode); /* ** Board has passed its scrub test. Fill in all the @@ -991,8 +983,8 @@ int Mode; ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); - rio_dprint(RIO_DEBUG_INIT, ("Unique no 0x%x.\n", - p->RIOHosts[p->RIONumHosts].UniqueNum ) ); + rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n", + p->RIOHosts[p->RIONumHosts].UniqueNum); p->RIOLastPCISearch = RIO_SUCCESS; p->RIONumHosts++; @@ -1002,8 +994,8 @@ int Mode; } if ( slot >= MAX_PCI_SLOT ) { - rio_dprint(RIO_DEBUG_INIT, ("All %d PCI slots have tested for RIO cards !!!\n", - MAX_PCI_SLOT ) ); + rio_dprintk (RIO_DEBUG_INIT, "All %d PCI slots have tested for RIO cards !!!\n", + MAX_PCI_SLOT); } @@ -1025,7 +1017,7 @@ void riohalt( void ) int host; for ( host=0; hostRIONumHosts; host++ ) { - rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Stop host %d\n",host); + rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host); (void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot ); } } @@ -1058,8 +1050,8 @@ int slot; int op, bank; int nbanks; - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Reset host type=%d, DpRam=0x%x, slot=%d\n", - type,(int)DpRam,slot)); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=0x%x, slot=%d\n", + type,(int)DpRam, slot); RIOHostReset(type, DpRam, slot); @@ -1071,7 +1063,7 @@ int slot; ** scratch - 1000h bytes */ - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Setup ram/size arrays\n")); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n"); size[0] = DP_SRAM1_SIZE; size[1] = DP_SRAM2_SIZE; @@ -1087,12 +1079,12 @@ int slot; if (nbanks == 3) { - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: Memory: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", - (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2])); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", + (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2]); } else { - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2], (int)ram[3], - size[3])); + size[3]); } /* @@ -1103,14 +1095,14 @@ int slot; for (op=0; opRIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port)); if (!p->RIOPortp) { - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: No memory for port structures\n")); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n"); p->RIOFailed++; return; } bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS ); - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: allocated and cleared memory for port structs\n") ); - rio_dprint(RIO_DEBUG_INIT, ("First RIO port struct @0x%x, size=0x%x bytes\n", - (int)p->RIOPortp, sizeof(struct Port) ) ); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for port structs\n"); + rio_dprintk (RIO_DEBUG_INIT, "First RIO port struct @0x%x, size=0x%x bytes\n", + (int)p->RIOPortp, sizeof(struct Port)); for( port=0; portRIOPortp[port].PortNum = port; @@ -1404,14 +1396,14 @@ struct rio_info * p; p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host)); if (!p->RIOHosts) { - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: No memory for host structures\n")); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n"); p->RIOFailed++; return; } bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS); - rio_dprint(RIO_DEBUG_INIT, ("RIO-init: allocated and cleared memory for host structs\n")); - rio_dprint(RIO_DEBUG_INIT, ("First RIO host struct @0x%x, size=0x%x bytes\n", - (int)p->RIOHosts, sizeof(struct Host) ) ); + rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for host structs\n"); + rio_dprintk (RIO_DEBUG_INIT, "First RIO host struct @0x%x, size=0x%x bytes\n", + (int)p->RIOHosts, sizeof(struct Host)); for( host=0; hostRIOHosts[host].HostLock); @@ -1494,10 +1486,10 @@ struct rio_info * p; char * RIORelID = RELEASE_ID; int host; - rio_dprint(RIO_DEBUG_INIT, ("RIO : Release: %s ID: %s\n", RIORelease, RIORelID)); + rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID); if ( p->RIONumHosts==0 ) { - rio_dprint(RIO_DEBUG_INIT, ("\nNo Hosts configured\n")); + rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n"); return(0); } @@ -1505,7 +1497,7 @@ struct rio_info * p; struct Host *HostP = &p->RIOHosts[host]; switch ( HostP->Type ) { case RIO_AT: - rio_dprint(RIO_DEBUG_INIT, ("AT BUS : found the card at 0x%x\n", HostP->PaddrP)); + rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP); } } return 0; @@ -1587,17 +1579,17 @@ uint Slot; /* ** Reset the Tpu */ - rio_dprint(RIO_DEBUG_INIT, ("RIOHostReset: type 0x%x", Type ) ); + rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: type 0x%x", Type); switch ( Type ) { case RIO_AT: - rio_dprint(RIO_DEBUG_INIT, (" (RIO_AT)\n")); + rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS); WBYTE(DpRamP->DpResetTpu, 0xFF); rio_udelay (3); - rio_dprint(RIO_DEBUG_INIT, ("RIOHostReset: Don't know if it worked. Try reset again\n") ); + rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS); @@ -1630,7 +1622,7 @@ uint Slot; break; #endif case RIO_PCI: - rio_dprint(RIO_DEBUG_INIT, (" (RIO_PCI)\n") ); + rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM; DpRamP->DpResetInt = 0xFF; DpRamP->DpResetTpu = 0xFF; @@ -1645,7 +1637,7 @@ uint Slot; #endif default: - rio_dprint(RIO_DEBUG_INIT, (" (UNKNOWN)\n") ); + rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); break; } return; diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c index e92609839..f52124b78 100644 --- a/drivers/char/rio/riointr.c +++ b/drivers/char/rio/riointr.c @@ -190,8 +190,8 @@ char * en; tty = PortP->gs.tty; - rio_dprint (RIO_DEBUG_INTR, ("tx port %d: %d chars queued.\n", - PortP->PortNum, PortP->gs.xmit_cnt)); + rio_dprintk (RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", + PortP->PortNum, PortP->gs.xmit_cnt); if (!PortP->gs.xmit_cnt) return; @@ -215,10 +215,10 @@ char * en; { int t; t = (c > 10)?10:c; - rio_dprint (RIO_DEBUG_INTR, ("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))); + 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! */ @@ -244,14 +244,14 @@ char * en; rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2*PKT_MAX_DATA_LEN)) { - rio_dprint (RIO_DEBUG_INTR, ("Waking up.... ldisc:%d (%d/%d)....", + 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)); + 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_dprint (RIO_DEBUG_INTR, ("(%d/%d)\n", - PortP->gs.wakeup_chars, PortP->gs.xmit_cnt)); + rio_dprintk (RIO_DEBUG_INTR, "(%d/%d)\n", + PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); wake_up_interruptible(&PortP->gs.tty->write_wait); } @@ -273,7 +273,7 @@ struct rio_info * p; for ( host=0; hostRIONumHosts; host++ ) { struct Host *HostP = &p->RIOHosts[host]; - rio_dprint(RIO_DEBUG_INTR, ("riointr() doing host %d type %d\n", host, HostP->Type ) ); + rio_dprintk (RIO_DEBUG_INTR, "riointr() doing host %d type %d\n", host, HostP->Type); switch( HostP->Type ) { case RIO_AT: @@ -363,7 +363,7 @@ int From; static int t =0; rio_spin_unlock (&HostP->HostLock); if ((t++ % 200) == 0) - rio_dprint(RIO_DEBUG_INTR, ("Interrupt but host not running. flags=%x.\n", (int)HostP->Flags)); + rio_dprintk (RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int)HostP->Flags); return; } rio_spin_unlock (&HostP->HostLock); @@ -372,7 +372,7 @@ int From; WWORD( HostP->ParmMapP->rup_intr , 0 ); p->RIORupCount++; RupIntr++; - rio_dprint(RIO_DEBUG_INTR, ("RUP interrupt on host %d\n", HostP-p->RIOHosts )); + rio_dprintk (RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP-p->RIOHosts); RIOPollHostCommands(p, HostP ); } @@ -383,7 +383,7 @@ int From; p->RIORxCount++; RxIntr++; - rio_dprint(RIO_DEBUG_INTR, ("RX interrupt on host %d\n", HostP-p->RIOHosts)); + 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 @@ -451,7 +451,7 @@ int From; ** MAGIC! ( Basically, handshake the RX buffer, so that ** the RTAs upstream can be re-enabled. ) */ - rio_dprint(RIO_DEBUG_INTR, ("Set RX handshake bit\n" )); + rio_dprintk (RIO_DEBUG_INTR, "Set RX handshake bit\n"); WWORD( PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET ); } @@ -466,7 +466,7 @@ int From; p->RIOTxCount++; TxIntr++; - rio_dprint(RIO_DEBUG_INTR, ("TX interrupt on host %d\n", HostP-p->RIOHosts)); + rio_dprintk (RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP-p->RIOHosts); /* ** Loop through every port. @@ -504,7 +504,7 @@ int From; continue; } - rio_dprint (RIO_DEBUG_INTR, ("Looking into port %d.\n", port)); + rio_dprintk (RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port); /* ** Lock the port before we begin working on it. */ @@ -515,7 +515,7 @@ int From; ** we need do none of this processing. */ if ( !can_add_transmit( &PacketP, PortP ) ) { - rio_dprint (RIO_DEBUG_INTR, ("Can't add to port, so skipping.\n")); + rio_dprintk (RIO_DEBUG_INTR, "Can't add to port, so skipping.\n"); rio_spin_unlock(&PortP->portSem); continue; } @@ -527,7 +527,7 @@ int From; ttyP = PortP->gs.tty; /* If ttyP is NULL, the port is getting closed. Forget about it. */ if (!ttyP) { - rio_dprint (RIO_DEBUG_INTR, ("no tty, so skipping.\n")); + rio_dprintk (RIO_DEBUG_INTR, "no tty, so skipping.\n"); rio_spin_unlock(&PortP->portSem); continue; } @@ -603,10 +603,10 @@ int From; ** with WFLUSH */ if ( PortP->WflushFlag ) { - rio_dprint(RIO_DEBUG_INTR, ("Want to WFLUSH mark this port\n")); + rio_dprintk (RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n"); if ( PortP->InUse ) - rio_dprint(RIO_DEBUG_INTR, ("FAILS - PORT IS IN USE\n")); + rio_dprintk (RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n"); } while ( PortP->WflushFlag && @@ -615,7 +615,7 @@ int From; int p; struct PktCmd *PktCmdP; - rio_dprint(RIO_DEBUG_INTR, ("Add WFLUSH marker to data queue\n")); + rio_dprintk (RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n"); /* ** make it look just like a WFLUSH command */ @@ -670,8 +670,8 @@ int From; PortP->MagicFlags &= ~MAGIC_FLUSH; } - rio_dprint(RIO_DEBUG_INTR, ("Wflush count now stands at %d\n", - PortP->WflushFlag)); + 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 ) { @@ -747,12 +747,12 @@ struct Port * PortP; TtyP = PortP->gs.tty; if (!TtyP) { - rio_dprint (RIO_DEBUG_INTR, ("RIOReceive: tty is null. \n")); + rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: tty is null. \n"); return; } if (PortP->State & RIO_THROTTLE_RX) { - rio_dprint (RIO_DEBUG_INTR, ("RIOReceive: Throttled. Can't handle more input.\n")); + rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n"); return; } @@ -786,18 +786,18 @@ struct Port * PortP; ** check that it is not a command! */ if ( PacketP->len & PKT_CMD_BIT ) { - rio_dprint(RIO_DEBUG_INTR, ("RIO: unexpected command packet received on PHB\n")); + 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_dprint(RIO_DEBUG_INTR, (" dest_unit = %d\n", PacketP->dest_unit)); - rio_dprint(RIO_DEBUG_INTR, (" dest_port = %d\n", PacketP->dest_port)); - rio_dprint(RIO_DEBUG_INTR, (" src_unit = %d\n", PacketP->src_unit)); - rio_dprint(RIO_DEBUG_INTR, (" src_port = %d\n", PacketP->src_port)); - rio_dprint(RIO_DEBUG_INTR, (" len = %d\n", PacketP->len)); - rio_dprint(RIO_DEBUG_INTR, (" control = %d\n", PacketP->control)); - rio_dprint(RIO_DEBUG_INTR, (" csum = %d\n", PacketP->csum)); - rio_dprint(RIO_DEBUG_INTR, (" data bytes: ")); + 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; DataCntdata[DataCnt])); + rio_dprintk (RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]); remove_receive( PortP ); put_free_end( PortP->HostP, PacketP ); continue; /* with next packet */ @@ -820,8 +820,8 @@ struct Port * PortP; transCount = min(PacketP->len & PKT_LEN_MASK, TTY_FLIPBUF_SIZE - TtyP->flip.count); - rio_dprint(RIO_DEBUG_REC, ("port %d: Copy %d bytes\n", - PortP->PortNum, transCount ) ); + 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 @@ -880,7 +880,7 @@ struct Port * PortP; } } if (copied) { - rio_dprint ( RIO_DEBUG_REC, ("port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, 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); } @@ -906,25 +906,25 @@ int port; SysPort = port; /* Believe me, it works. */ if ( SysPort < 0 || SysPort >= RIO_PORTS ) { - rio_dprint(RIO_DEBUG_INTR, ("Illegal port %d derived from TTY in riotproc()\n",SysPort)); + 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_dprint(RIO_DEBUG_INTR, ("RIO: NULL or BAD PhbP on sys port %d in proc routine\n", - SysPort)); - rio_dprint(RIO_DEBUG_INTR, (" PortP = 0x%x\n",PortP)); - rio_dprint(RIO_DEBUG_INTR, (" PortP->PhbP = 0x%x\n",PortP->PhbP)); - rio_dprint(RIO_DEBUG_INTR, (" PortP->Caddr = 0x%x\n",PortP->PhbP)); - rio_dprint(RIO_DEBUG_INTR, (" PortP->HostPort = 0x%x\n",PortP->HostPort)); + 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_dprint(RIO_DEBUG_INTR, "T_WFLUSH\n"); + 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, @@ -941,14 +941,14 @@ int port; ** form a wflush packet - 1 byte long, no data */ if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_INTR, ("WFLUSH on deleted RTA\n")); + rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n"); } else { if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command failed\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n"); } else - rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n"); } /* ** WFLUSH operation - flush the data! @@ -956,7 +956,7 @@ int port; PortP->TxBufferIn = PortP->TxBufferOut = 0; } else { - rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command ignored\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n"); } /* ** sort out the line discipline @@ -966,16 +966,16 @@ int port; break; case T_RESUME: - rio_dprint(RIO_DEBUG_INTR, ("T_RESUME\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n"); /* ** send pre-emptive resume packet */ if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_INTR, ("RESUME on deleted RTA\n")); + rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n"); } else { if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_INTR, ("T_RESUME Command failed\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n"); } } /* @@ -986,7 +986,7 @@ int port; break; case T_TIME: - rio_dprint(RIO_DEBUG_INTR, ("T_TIME\n")); + 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 @@ -1008,16 +1008,16 @@ start: break; case T_SUSPEND: - rio_dprint(RIO_DEBUG_INTR, ("T_SUSPEND\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n"); /* ** send a suspend pre-emptive packet. */ if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_INTR, ("SUSPEND deleted RTA\n")); + rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n"); } else { if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_INTR, ("T_SUSPEND Command failed\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n"); } } /* @@ -1026,18 +1026,18 @@ start: break; case T_BLOCK: - rio_dprint(RIO_DEBUG_INTR, ("T_BLOCK\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n"); break; case T_RFLUSH: - rio_dprint(RIO_DEBUG_INTR, ("T_RFLUSH\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n"); if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_INTR, ("RFLUSH on deleted RTA\n")); + rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n"); PortP->RxDataStart = 0; } else { if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) { - rio_dprint(RIO_DEBUG_INTR, ("T_RFLUSH Command failed\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n"); return 0; } PortP->RxDataStart = 0; @@ -1050,14 +1050,14 @@ start: /* ** MAGIC! */ - rio_dprint(RIO_DEBUG_INTR, ("Set receive handshake bit\n")); + rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n"); PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET; } } break; /* FALLTHROUGH */ case T_UNBLOCK: - rio_dprint(RIO_DEBUG_INTR, ("T_UNBLOCK\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n"); /* ** If there is any data to receive set a timeout to service it. */ @@ -1065,7 +1065,7 @@ start: break; case T_BREAK: - rio_dprint(RIO_DEBUG_INTR, ("T_BREAK\n")); + rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n"); /* ** Send a break command. For Sys V ** this is a timed break, so we @@ -1075,12 +1075,12 @@ start: ** Build a BREAK command */ if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_INTR, ("BREAK on deleted RTA\n")); + rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n"); } else { if (RIOShortCommand(PortP,SBREAK,2, p->RIOConf.BreakInterval)==RIO_FAIL) { - rio_dprint(RIO_DEBUG_INTR, ("SBREAK RIOShortCommand failed\n")); + rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); } } @@ -1090,18 +1090,18 @@ start: break; case T_INPUT: - rio_dprint(RIO_DEBUG_INTR, ("Proc T_INPUT called - I don't know what to do!\n")); + rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n"); break; case T_PARM: - rio_dprint(RIO_DEBUG_INTR, ("Proc T_PARM called - I don't know what to do!\n")); + rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n"); break; case T_SWTCH: - rio_dprint(RIO_DEBUG_INTR, ("Proc T_SWTCH called - I don't know what to do!\n")); + rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n"); break; default: - rio_dprint(RIO_DEBUG_INTR, ("Proc UNKNOWN command %d\n",cmd)); + rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd); } /* ** T_OUTPUT returns without passing through this point! diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index 550e2c17d..4ce8443c3 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -176,13 +176,18 @@ int SleepFlag; int retries = 0xff; unsigned long flags; + func_enter (); + TtyP = PortP->gs.tty; - rio_dprint(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_dprint (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 (); + return RIO_FAIL; } rio_spin_lock_irqsave(&PortP->portSem, flags ); @@ -205,7 +210,7 @@ int SleepFlag; PortP->FirstOpen = 0; } else if (PortP->Store || PortP->Lock) { - rio_dprint(RIO_DEBUG_PARAM, ("OPEN: Restoring stored/locked params\n")); + 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; @@ -226,41 +231,49 @@ int SleepFlag; break; } if ( PortP->InUse != NOT_INUSE ) { - rio_dprint(RIO_DEBUG_PARAM, ("Port IN_USE for pre-emptive command\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n"); } if ( !res ) { - rio_dprint(RIO_DEBUG_PARAM, ("Port has no space on transmit queue\n")); + 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); + func_exit(); + return RIO_FAIL; } - rio_dprint(RIO_DEBUG_PARAM, ("wait for can_add_transmit\n")); + 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); if (retval == RIO_FAIL) { - rio_dprint(RIO_DEBUG_PARAM, ("wait for can_add_transmit broken by signal\n")); + 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 (); + return RIO_SUCCESS; } } if (!res) { rio_spin_unlock_irqrestore( &PortP->portSem, flags); + func_exit (); + return RIO_FAIL; } - rio_dprint(RIO_DEBUG_PARAM, ("can_add_transmit() returns %x\n",res)); - rio_dprint(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; @@ -270,7 +283,7 @@ int SleepFlag; ** COR 1 */ if ( TtyP->tm.c_iflag & INPCK ) { - rio_dprint(RIO_DEBUG_PARAM, ("Parity checking on input enabled\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Parity checking on input enabled\n"); Cor1 |= COR1_INPCK; } #endif @@ -278,53 +291,53 @@ int SleepFlag; switch ( TtyP->termios->c_cflag & CSIZE ) { case CS5: { - rio_dprint(RIO_DEBUG_PARAM, ("5 bit data\n")); + rio_dprintk (RIO_DEBUG_PARAM, "5 bit data\n"); Cor1 |= COR1_5BITS; break; } case CS6: { - rio_dprint(RIO_DEBUG_PARAM, ("6 bit data\n")); + rio_dprintk (RIO_DEBUG_PARAM, "6 bit data\n"); Cor1 |= COR1_6BITS; break; } case CS7: { - rio_dprint(RIO_DEBUG_PARAM, ("7 bit data\n")); + rio_dprintk (RIO_DEBUG_PARAM, "7 bit data\n"); Cor1 |= COR1_7BITS; break; } case CS8: { - rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("2 stop bits\n")); + rio_dprintk (RIO_DEBUG_PARAM, "2 stop bits\n"); Cor1 |= COR1_2STOP; } else { - rio_dprint(RIO_DEBUG_PARAM, ("1 stop bit\n")); + rio_dprintk (RIO_DEBUG_PARAM, "1 stop bit\n"); Cor1 |= COR1_1STOP; } if ( TtyP->termios->c_cflag & PARENB ) { - rio_dprint(RIO_DEBUG_PARAM, ("Enable parity\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable parity\n"); Cor1 |= COR1_NORMAL; } else { - rio_dprint(RIO_DEBUG_PARAM, ("Disable parity\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Disable parity\n"); Cor1 |= COR1_NOP; } if ( TtyP->termios->c_cflag & PARODD ) { - rio_dprint(RIO_DEBUG_PARAM, ("Odd parity\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Odd parity\n"); Cor1 |= COR1_ODD; } else { - rio_dprint(RIO_DEBUG_PARAM, ("Even parity\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Even parity\n"); Cor1 |= COR1_EVEN; } @@ -332,89 +345,89 @@ int SleepFlag; ** COR 2 */ if ( TtyP->termios->c_iflag & IXON ) { - rio_dprint(RIO_DEBUG_PARAM, ("Enable start/stop output control\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop output control\n"); Cor2 |= COR2_IXON; } else { if ( PortP->Config & RIO_IXON ) { - rio_dprint(RIO_DEBUG_PARAM, ("Force enable start/stop output control\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Force enable start/stop output control\n"); Cor2 |= COR2_IXON; } else - rio_dprint(RIO_DEBUG_PARAM, ("IXON has been disabled.\n")); + rio_dprintk (RIO_DEBUG_PARAM, "IXON has been disabled.\n"); } if (TtyP->termios->c_iflag & IXANY) { if ( PortP->Config & RIO_IXANY ) { - rio_dprint(RIO_DEBUG_PARAM, ("Enable any key to restart output\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable any key to restart output\n"); Cor2 |= COR2_IXANY; } else - rio_dprint(RIO_DEBUG_PARAM, ("IXANY has been disabled due to sanity reasons.\n")); + rio_dprintk (RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n"); } if ( TtyP->termios->c_iflag & IXOFF ) { - rio_dprint(RIO_DEBUG_PARAM, ("Enable start/stop input control 2\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop input control 2\n"); Cor2 |= COR2_IXOFF; } if ( TtyP->termios->c_cflag & HUPCL ) { - rio_dprint(RIO_DEBUG_PARAM, ("Hangup on last close\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Hangup on last close\n"); Cor2 |= COR2_HUPCL; } if ( C_CRTSCTS (TtyP)) { - rio_dprint(RIO_DEBUG_PARAM, ("Rx hardware flow control enabled\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n"); Cor2 |= COR2_CTSFLOW; Cor2 |= COR2_RTSFLOW; } else { - rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("Local line\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Local line\n"); } else { - rio_dprint(RIO_DEBUG_PARAM, ("Possible Modem line\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Possible Modem line\n"); } /* ** COR 4 (there is no COR 3) */ if ( TtyP->termios->c_iflag & IGNBRK ) { - rio_dprint(RIO_DEBUG_PARAM, ("Ignore break condition\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Ignore break condition\n"); Cor4 |= COR4_IGNBRK; } if ( !(TtyP->termios->c_iflag & BRKINT) ) { - rio_dprint(RIO_DEBUG_PARAM, ("Break generates NULL condition\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Break generates NULL condition\n"); Cor4 |= COR4_NBRKINT; } else { - rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("Map newline to carriage return on input\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage return on input\n"); Cor4 |= COR4_INLCR; } if ( TtyP->termios->c_iflag & IGNCR ) { - rio_dprint(RIO_DEBUG_PARAM, ("Ignore carriage return on input\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Ignore carriage return on input\n"); Cor4 |= COR4_IGNCR; } if ( TtyP->termios->c_iflag & ICRNL ) { - rio_dprint(RIO_DEBUG_PARAM, ("Map carriage return to newline on input\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on input\n"); Cor4 |= COR4_ICRNL; } if ( TtyP->termios->c_iflag & IGNPAR ) { - rio_dprint(RIO_DEBUG_PARAM, ("Ignore characters with parity errors\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Ignore characters with parity errors\n"); Cor4 |= COR4_IGNPAR; } if ( TtyP->termios->c_iflag & PARMRK ) { - rio_dprint(RIO_DEBUG_PARAM, ("Mark parity errors\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Mark parity errors\n"); Cor4 |= COR4_PARMRK; } @@ -444,24 +457,24 @@ int SleepFlag; ** Could set LNE here if you wanted LNext processing. SVR4 will use it. */ if ( TtyP->termios->c_iflag & ISTRIP ) { - rio_dprint(RIO_DEBUG_PARAM, ("Strip input characters\n")); + 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_dprint(RIO_DEBUG_PARAM, ("Map newline to carriage-return, newline on output\n")); + 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_dprint(RIO_DEBUG_PARAM, ("Map carriage return to newline on output\n")); + 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_dprint(RIO_DEBUG_PARAM, ("Tab delay 3 set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Tab delay 3 set\n"); if ( PortP->CookMode == COOK_MEDIUM ) Cor5 |= COR5_TAB3; } @@ -481,8 +494,8 @@ int SleepFlag; /* ** Baud rate bytes */ - rio_dprint(RIO_DEBUG_PARAM, ("Mapping of rx/tx baud %x (%x)\n", - TtyP->termios->c_cflag, CBAUD)); + 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 @@ -494,77 +507,77 @@ int SleepFlag; /* XXX MIssing conversion table. XXX */ /* (TtyP->termios->c_cflag & V_CBAUD); */ - rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("Enable receiver\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable receiver\n"); #ifdef RCV1EN if ( TtyP->termios->c_cflag & RCV1EN ) - rio_dprint(RIO_DEBUG_PARAM, ("RCV1EN (?)\n")); + rio_dprintk (RIO_DEBUG_PARAM, "RCV1EN (?)\n"); #endif #ifdef XMT1EN if ( TtyP->termios->c_cflag & XMT1EN ) - rio_dprint(RIO_DEBUG_PARAM, ("XMT1EN (?)\n")); + rio_dprintk (RIO_DEBUG_PARAM, "XMT1EN (?)\n"); #endif #if 0 if ( TtyP->termios->c_cflag & LOBLK ) - rio_dprint(RIO_DEBUG_PARAM, ("LOBLK - JCL output blocks when not current\n")); + rio_dprintk (RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n"); #endif if ( TtyP->termios->c_lflag & ISIG ) - rio_dprint(RIO_DEBUG_PARAM, ("Input character signal generating enabled\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Input character signal generating enabled\n"); if ( TtyP->termios->c_lflag & ICANON ) - rio_dprint(RIO_DEBUG_PARAM, ("Canonical input: erase and kill enabled\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n"); if ( TtyP->termios->c_lflag & XCASE ) - rio_dprint(RIO_DEBUG_PARAM, ("Canonical upper/lower presentation\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n"); if ( TtyP->termios->c_lflag & ECHO ) - rio_dprint(RIO_DEBUG_PARAM, ("Enable input echo\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable input echo\n"); if ( TtyP->termios->c_lflag & ECHOE ) - rio_dprint(RIO_DEBUG_PARAM, ("Enable echo erase\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable echo erase\n"); if ( TtyP->termios->c_lflag & ECHOK ) - rio_dprint(RIO_DEBUG_PARAM, ("Enable echo kill\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable echo kill\n"); if ( TtyP->termios->c_lflag & ECHONL ) - rio_dprint(RIO_DEBUG_PARAM, ("Enable echo newline\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable echo newline\n"); if ( TtyP->termios->c_lflag & NOFLSH ) - rio_dprint(RIO_DEBUG_PARAM, ("Disable flush after interrupt or quit\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n"); #ifdef TOSTOP if ( TtyP->termios->c_lflag & TOSTOP ) - rio_dprint(RIO_DEBUG_PARAM, ("Send SIGTTOU for background output\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n"); #endif #ifdef XCLUDE if ( TtyP->termios->c_lflag & XCLUDE ) - rio_dprint(RIO_DEBUG_PARAM, ("Exclusive use of this line\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Exclusive use of this line\n"); #endif if ( TtyP->termios->c_iflag & IUCLC ) - rio_dprint(RIO_DEBUG_PARAM, ("Map uppercase to lowercase on input\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n"); if ( TtyP->termios->c_oflag & OPOST ) - rio_dprint(RIO_DEBUG_PARAM, ("Enable output post-processing\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Enable output post-processing\n"); if ( TtyP->termios->c_oflag & OLCUC ) - rio_dprint(RIO_DEBUG_PARAM, ("Map lowercase to uppercase on output\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n"); if ( TtyP->termios->c_oflag & ONOCR ) - rio_dprint(RIO_DEBUG_PARAM, ("No carriage return output at column 0\n")); + rio_dprintk (RIO_DEBUG_PARAM, "No carriage return output at column 0\n"); if ( TtyP->termios->c_oflag & ONLRET ) - rio_dprint(RIO_DEBUG_PARAM, ("Newline performs carriage return function\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Newline performs carriage return function\n"); if ( TtyP->termios->c_oflag & OFILL ) - rio_dprint(RIO_DEBUG_PARAM, ("Use fill characters for delay\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Use fill characters for delay\n"); if ( TtyP->termios->c_oflag & OFDEL ) - rio_dprint(RIO_DEBUG_PARAM, ("Fill character is DEL\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Fill character is DEL\n"); if ( TtyP->termios->c_oflag & NLDLY ) - rio_dprint(RIO_DEBUG_PARAM, ("Newline delay set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Newline delay set\n"); if ( TtyP->termios->c_oflag & CRDLY ) - rio_dprint(RIO_DEBUG_PARAM, ("Carriage return delay set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Carriage return delay set\n"); if ( TtyP->termios->c_oflag & TABDLY ) - rio_dprint(RIO_DEBUG_PARAM, ("Tab delay set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Tab delay set\n"); #if 0 if ( TtyP->termios->c_oflag & BSDLY ) - rio_dprint(RIO_DEBUG_PARAM, ("Back-space delay set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Back-space delay set\n"); if ( TtyP->termios->c_oflag & VTDLY ) - rio_dprint(RIO_DEBUG_PARAM, ("Vertical tab delay set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Vertical tab delay set\n"); if ( TtyP->termios->c_oflag & FFDLY ) - rio_dprint(RIO_DEBUG_PARAM, ("Form-feed delay set\n")); + rio_dprintk (RIO_DEBUG_PARAM, "Form-feed delay set\n"); #endif /* ** These things are kind of useful in a later life! @@ -573,6 +586,8 @@ int SleepFlag; if ( PortP->State & RIO_DELETED ) { rio_spin_unlock_irqrestore( &PortP->portSem, flags); + func_exit (); + return RIO_FAIL; } @@ -610,10 +625,12 @@ int SleepFlag; rio_spin_unlock_irqrestore( &PortP->portSem, flags); - rio_dprint(RIO_DEBUG_PARAM, ("add_transmit returned.\n")); + rio_dprintk (RIO_DEBUG_PARAM, "add_transmit returned.\n"); /* ** job done. */ + func_exit (); + return RIO_SUCCESS; } @@ -644,7 +661,7 @@ add_transmit(PortP) struct Port *PortP; { if (RWORD(*PortP->TxAdd) & PKT_IN_USE) { - rio_dprint (RIO_DEBUG_PARAM, ("add_transmit: Packet has been stolen!")); + 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 : @@ -672,7 +689,7 @@ PKT *PktP; * ************************************************/ - rio_dprint(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); @@ -683,12 +700,13 @@ PKT *PktP; WWORD(HostP->ParmMapP->free_list_end, new_end); } else { /* First packet on the free list this should never happen! */ - rio_dprint(RIO_DEBUG_PFE, ("put_free_end(): This should never happen\n")); + 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); } diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index 2f13eb273..ab78ddf5d 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c @@ -178,8 +178,8 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP if ( Lies ) { - rio_dprint(RIO_DEBUG_ROUTE, ("LIES! DAMN LIES! %d LIES!\n",Lies)); - rio_dprint(RIO_DEBUG_ROUTE, ("%d:%c %d:%c %d:%c %d:%c\n", + 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), @@ -187,7 +187,7 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP RBYTE(PktCmdP->RouteTopology[2].Unit), 'A'+RBYTE(PktCmdP->RouteTopology[2].Link), RBYTE(PktCmdP->RouteTopology[3].Unit), - 'A'+RBYTE(PktCmdP->RouteTopology[3].Link))); + 'A'+RBYTE(PktCmdP->RouteTopology[3].Link)); return TRUE; } @@ -219,11 +219,11 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT ) { - rio_dprint(RIO_DEBUG_ROUTE, ("I have a link from %s %s to unit %d:%d - I don't like it.\n", + 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)); + NewLink); } else { @@ -248,8 +248,8 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT); if ( NewUnit == ROUTE_NO_ID ) - rio_dprint(RIO_DEBUG_ROUTE, ("%s %s (%c) is connected to an unconfigured unit.\n", - MyType,MyName,'A'+ThisLink)); + rio_dprintk (RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", + MyType,MyName,'A'+ThisLink); if ( NewUnit == ROUTE_INTERCONNECT ) { @@ -267,14 +267,14 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP if ( HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink ) { - rio_dprint(RIO_DEBUG_ROUTE, ("SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A')); + 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_dprint(RIO_DEBUG_ROUTE, ("HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", - OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A')); + 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 ) @@ -282,29 +282,29 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink ) { - rio_dprint(RIO_DEBUG_ROUTE, ("SETTING RTA %s (%c) TO DISCONNECTED!\n", - HostP->Mapping[OldUnit-1].Name,OldLink+'A')); + 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_dprint(RIO_DEBUG_ROUTE, ("RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", + 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')); + HostP->Mapping[ThisUnit-1].Name,ThisLink+'A'); } } if ( NewUnit == HOST_ID ) { - rio_dprint(RIO_DEBUG_ROUTE, ("MARKING HOST (%c) CONNECTED TO %s (%c)\n", - NewLink+'A',MyName,ThisLink+'A')); + 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_dprint(RIO_DEBUG_ROUTE, ("MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", - HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A')); + 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; } @@ -321,8 +321,8 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP */ if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST ) { - rio_dprint(RIO_DEBUG_ROUTE, ("Unknown command %d received on rup %d host %d ROUTE_RUP\n", - RBYTE(PktCmdP->Command),Rup,(int)HostP)); + 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; } @@ -336,7 +336,7 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP */ RtaType = GetUnitType(RtaUniq); - rio_dprint(RIO_DEBUG_ROUTE, ("Received a request for an ID for serial number %x\n", 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); @@ -347,14 +347,14 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP ** with 8 port, set 2nd ident in Mod2 to the same as Mod1. */ Mod2 = Mod1; - rio_dprint(RIO_DEBUG_ROUTE, ("Backplane type is %s (all ports)\n", - p->RIOModuleTypes[Mod1].Name )); + rio_dprintk (RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", + p->RIOModuleTypes[Mod1].Name); } else { Mod2 = HINYBLE(Mod); - rio_dprint(RIO_DEBUG_ROUTE, ("Module types are %s (ports 0-3) and %s (ports 4-7)\n", - p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name )); + 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 ) @@ -367,7 +367,7 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP */ if ( !(CmdBlkP = RIOGetCmdBlk()) ) { - rio_dprint(RIO_DEBUG_ROUTE, ("No command blocks to route RTA! come back later.\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n"); return 0; } @@ -384,8 +384,8 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP if (! RIOBootOk(p, HostP, RtaUniq)) { - rio_dprint(RIO_DEBUG_ROUTE, ("RTA %x tried to get an ID, but does not belong - FOAD it!\n", - 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); @@ -397,13 +397,13 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP */ for ( ThisUnit=0; ThisUnitMapping[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 )); + HostP->Mapping[ThisUnit].RtaUniqueNum); /* ** We have an entry for it. @@ -414,12 +414,12 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP if (RtaType == TYPE_RTA16) { ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1; - rio_dprint(RIO_DEBUG_ROUTE, ("Found unit 0x%x at slots %d+%d\n", - RtaUniq,ThisUnit,ThisUnit2)); + rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", + RtaUniq,ThisUnit,ThisUnit2); } else - rio_dprint(RIO_DEBUG_ROUTE, ("Found unit 0x%x at slot %d\n", - RtaUniq,ThisUnit)); + 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 @@ -458,14 +458,14 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP */ RIOFixPhbs(p, HostP, ThisUnit2); PktReplyP->IDNum2 = ThisUnit2+1; - rio_dprint(RIO_DEBUG_ROUTE, ("RTA '%s' has been allocated IDs %d+%d\n", - HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2)); + 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_dprint(RIO_DEBUG_ROUTE, ("RTA '%s' has been allocated ID %d\n", - HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum)); + 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); @@ -489,7 +489,7 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]; if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { - rio_dprint(RIO_DEBUG_ROUTE, ("Re-opened this port\n")); + 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); @@ -502,7 +502,7 @@ int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]; if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { - rio_dprint(RIO_DEBUG_ROUTE, ("Re-opened this port\n")); + 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); @@ -628,7 +628,7 @@ uint unit; unsigned long flags; int PortN = HostP->Mapping[unit].SysPort; - rio_dprint(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; @@ -656,7 +656,7 @@ uint unit; ** unset, so go no further. */ if (PortP->TxStart == 0) { - rio_dprint(RIO_DEBUG_ROUTE, ("Tx pkts not set up yet\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); break; } @@ -691,10 +691,10 @@ uint unit; WBYTE(Pkt->dest_unit, dest_unit); WBYTE(Pkt->dest_port, dest_port); } - rio_dprint(RIO_DEBUG_ROUTE, ("phb dest: Old %x:%x New %x:%x\n", + 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)); + dest_unit, dest_port); WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8)); WWORD(PortP->PhbP->link, link); @@ -706,7 +706,7 @@ uint unit; */ if (link > 3) return; if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) { - rio_dprint(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); } } @@ -732,7 +732,7 @@ uint UnitId; CheckUnitId( UnitId ); #endif if ( RIOCheck( HostP, UnitId ) ) { - rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated\n",UnitId)); + rio_dprintk (RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId); rio_spin_unlock_irqrestore(&HostP->HostLock, flags); return(0); } @@ -771,7 +771,7 @@ uint UnitId; HostP->Mapping[UnitId].Flags |= BEEN_HERE; if ( p->RIOPrintDisabled == DO_PRINT ) - rio_dprint(RIO_DEBUG_ROUTE, ("RIOMesgIsolated %s",HostP->Mapping[UnitId].Name)); + rio_dprintk (RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name); for ( link=0; linkMapping[UnitId].Topology[link].Unit; @@ -795,7 +795,7 @@ uint UnitId; CheckUnitId( UnitId ); #endif /* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */ - rio_dprint(RIO_DEBUG_ROUTE, ("RIOCheck : UnitID = %d\n",UnitId)); + rio_dprintk (RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId); if ( UnitId == HOST_ID ) { /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */ @@ -854,16 +854,16 @@ uint Uniq; case RIO_MCA: case RIO_EISA: case RIO_PCI: - rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: Host\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Host\n"); return(TYPE_HOST); case RIO_RTA_16: - rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: 16 port RTA\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n"); return(TYPE_RTA16); case RIO_RTA: - rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: 8 port RTA\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n"); return(TYPE_RTA8); default : - rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: Unrecognised\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n"); return(99); } } @@ -876,7 +876,7 @@ struct rio_info * p; return(0); p->RIOQuickCheck = CHANGED; if ( p->RIOSignalProcess ) { - rio_dprint(RIO_DEBUG_ROUTE, ("Send SIG-HUP")); + rio_dprintk (RIO_DEBUG_ROUTE, "Send SIG-HUP"); /* psignal( RIOSignalProcess, SIGHUP ); */ @@ -951,10 +951,10 @@ int Change; ToName = ToId ? HostP->Mapping[ToId-1].Name : HostP->Name; ToType = ToId ? "RTA" : "HOST"; - rio_dprint(RIO_DEBUG_ROUTE, ("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", + 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")); + (Change==CONNECT) ? "established" : "disconnected"); cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A'+FromLink, ToType, ToName, 'A'+ToLink, @@ -1000,7 +1000,7 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) int link; - rio_dprint(RIO_DEBUG_ROUTE, ("RIOFreeDisconnect unit %d\n",unit)); + 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 @@ -1023,17 +1023,17 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) ** made this slot tentative and not yet received a topology update. ** Lets check how long ago we made it tentative. */ - rio_dprint(RIO_DEBUG_ROUTE, ("Just about to check LBOLT on entry %d\n",unit)); + rio_dprintk (RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit); if (drv_getparm(LBOLT, (ulong_t *) ¤t_time)) - rio_dprint(RIO_DEBUG_ROUTE, ("drv_getparm(LBOLT,....) Failed.\n")); + rio_dprintk (RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n"); elapse_time = current_time - TentTime[unit]; - rio_dprint(RIO_DEBUG_ROUTE, ("elapse %d = current %d - tent %d (%d usec)\n", - elapse_time, current_time, TentTime[unit],drv_hztousec(elapse_time))); + 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_dprint(RIO_DEBUG_ROUTE, ("Skipping slot %d, not timed out yet %d\n" - ,unit,drv_hztousec(elapse_time))); + rio_dprintk (RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", + unit, drv_hztousec(elapse_time)); return 1; } #endif @@ -1046,7 +1046,7 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) { int nOther = (HostP->Mapping[unit].ID2) -1; - rio_dprint(RIO_DEBUG_ROUTE, ("RioFreedis second slot %d.\n",nOther)); + 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]); @@ -1082,19 +1082,19 @@ RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) */ for (unit = 0; unit < MAX_RUP; unit++) { - rio_dprint(RIO_DEBUG_ROUTE, ("Scanning unit %d\n",unit)); + rio_dprintk (RIO_DEBUG_ROUTE, "Scanning unit %d\n",unit); /* ** If the flags are zero then the slot is empty. */ if (HostP->Mapping[unit].Flags == 0) { - rio_dprint(RIO_DEBUG_ROUTE, (" This slot is empty.\n")); + 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_dprint(RIO_DEBUG_ROUTE, ("Make tentative entry for first unit %d\n", unit)); + rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit); *pID1 = unit; /* @@ -1109,7 +1109,7 @@ RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) /* ** Allocate the second slot and return. */ - rio_dprint(RIO_DEBUG_ROUTE, ("Make tentative entry for second unit %d\n", unit)); + rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit); *pID2 = unit; return 0; } @@ -1121,18 +1121,18 @@ RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) ** need to start all over again looking for tentative slots ** that we can re-use. */ - rio_dprint(RIO_DEBUG_ROUTE, ("Starting to scan for tentative slots\n")); + 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_dprint(RIO_DEBUG_ROUTE, (" Slot %d looks promising.\n",unit)); + rio_dprintk (RIO_DEBUG_ROUTE, " Slot %d looks promising.\n",unit); if(unit == *pID1) { - rio_dprint(RIO_DEBUG_ROUTE, (" No it isn't, its the 1st half\n")); + rio_dprintk (RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n"); continue; } @@ -1152,7 +1152,7 @@ RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) */ if (*pID1 == MAX_RUP) { - rio_dprint(RIO_DEBUG_ROUTE, ("Grab tentative entry for first unit %d\n", unit)); + rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit); *pID1 = unit; /* @@ -1172,8 +1172,8 @@ RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) /* ** Allocate the second slot and return. */ - rio_dprint(RIO_DEBUG_ROUTE, ("Grab tentative/empty entry for second unit %d\n", - unit)); + rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", + unit); *pID2 = unit; /* @@ -1190,7 +1190,7 @@ RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) if (*pID1 > *pID2) { - rio_dprint(RIO_DEBUG_ROUTE, ("Swapping IDS %d %d\n",*pID1,*pID2)); + rio_dprintk (RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2); tempID = *pID1; *pID1 = *pID2; *pID2 = tempID; diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index 6329a6e18..2b82c25ad 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -120,7 +120,7 @@ struct rio_info * p; ** (9) That names aren't duplicated ** xx (10) That hosts that actually exist are mentioned in the table. xx */ - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(1)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n"); if ( p->RIOSystemUp ) { /* (1) */ p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED; return EBUSY; @@ -133,7 +133,7 @@ struct rio_info * p; for ( Entry=0; EntryRIOConnectTable[Entry]; if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) { - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(2)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n"); cptr = MapP->Name; /* (2) */ cptr[MAX_NAME_LEN-1]='\0'; if ( cptr[0]=='\0' ) { @@ -161,19 +161,19 @@ struct rio_info * p; continue; } - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(3)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n"); if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */ if ( MapP->ID || MapP->SysPort || MapP->Flags ) { - rio_dprint(RIO_DEBUG_TABLE, ("%s pretending to be empty but isn't\n",MapP->Name)); + 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_dprint(RIO_DEBUG_TABLE, ("!RIO: Daemon: test (3) passes\n")); + rio_dprintk (RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n"); continue; } - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(4)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n"); for ( Host=0; HostRIONumHosts; Host++ ) { /* (4) */ if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) { HostP = &p->RIOHosts[Host]; @@ -187,8 +187,8 @@ struct rio_info * p; } if ( Host >= p->RIONumHosts ) { - rio_dprint(RIO_DEBUG_TABLE, ("RTA %s has unknown host unique number 0x%x\n", - MapP->Name,MapP->HostUniqueNum)); + 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; */ @@ -198,18 +198,18 @@ struct rio_info * p; continue; } - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(5)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n"); if ( MapP->RtaUniqueNum ) { /* (5) */ if ( !MapP->ID ) { - rio_dprint(RIO_DEBUG_TABLE, ("RIO: RTA %s has been allocated an ID of zero!\n", - MapP->Name)); + 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_dprint(RIO_DEBUG_TABLE, ("RIO: RTA %s has been allocated an illegal ID %d\n", - MapP->Name, MapP->ID)); + rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an illegal ID %d\n", + MapP->Name, MapP->ID); p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; p->RIOError.Entry = Entry; return ENXIO; @@ -218,8 +218,8 @@ struct rio_info * p; if ( MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID ) { - rio_dprint(RIO_DEBUG_TABLE, ("Dupl. ID number allocated to RTA %s and RTA %s\n", - MapP->Name,p->RIOConnectTable[SubEnt].Name)); + 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; @@ -232,29 +232,29 @@ struct rio_info * p; if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum) && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) { - rio_dprint(RIO_DEBUG_TABLE, ("RTA %s has duplicate unique number\n",MapP->Name)); - rio_dprint(RIO_DEBUG_TABLE, ("RTA %s has duplicate unique number\n", - p->RIOConnectTable[SubEnt].Name)); + 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_dprint(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_dprint(RIO_DEBUG_TABLE, ("TTY Port number %d-RTA %s is not a multiple of %d!\n", - (int)MapP->SysPort,MapP->Name,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_dprint(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_dprint(RIO_DEBUG_TABLE, ("TTY Port number %d for RTA %s is too big\n", - (int)MapP->SysPort,MapP->Name)); + 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; @@ -263,22 +263,22 @@ struct rio_info * p; if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT ) continue; if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) { - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(8)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n"); /* (8) */ if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort) ) { - rio_dprint(RIO_DEBUG_TABLE, ("RTA %s:same TTY port # as RTA %s (%d)\n", + rio_dprintk (RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, - (int)MapP->SysPort)); + (int)MapP->SysPort); p->RIOError.Error = TTY_NUMBER_IN_USE; p->RIOError.Entry = Entry; p->RIOError.Other = SubEnt; return ENXIO; } - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(9)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n"); if (RIOStrCmp(MapP->Name, p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */ - rio_dprint(RIO_DEBUG_TABLE, ("RTA name %s used twice\n",MapP->Name)); + 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; @@ -288,17 +288,17 @@ struct rio_info * p; } } else { /* (6) */ - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(6)\n")); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n"); if ( MapP->ID ) { - rio_dprint(RIO_DEBUG_TABLE, ("RIO:HOST %s has been allocated ID that isn't zero!\n", - MapP->Name)); + 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_dprint(RIO_DEBUG_TABLE, ("RIO: HOST %s has been allocated port numbers!\n", - MapP->Name)); + 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; @@ -326,7 +326,7 @@ struct rio_info * p; ** Copy in the new table entries */ for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) { - rio_dprint(RIO_DEBUG_TABLE, ("RIONewTable: Copy table for Host entry %d\n", Entry)); + rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry); MapP = &p->RIOConnectTable[Entry]; /* @@ -344,7 +344,7 @@ struct rio_info * p; ** If it is a host, then we only need to fill in the name field. */ if ( MapP->ID==0 ) { - rio_dprint(RIO_DEBUG_TABLE, ("Host entry found. Name %s\n",MapP->Name)); + rio_dprintk (RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name); bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN); continue; } @@ -357,7 +357,7 @@ struct rio_info * p; HostMapP = &HostP->Mapping[MapP->ID-1]; if (MapP->Flags & SLOT_IN_USE) { - rio_dprint(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 */ @@ -370,7 +370,7 @@ struct rio_info * p; RIOReMapPorts(p, HostP, HostMapP ); } else { - rio_dprint(RIO_DEBUG_TABLE, ("TENTATIVE Rta entry found. Name %s\n",MapP->Name)); + rio_dprintk (RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name); } } @@ -420,11 +420,11 @@ struct rio_info * p; */ if (Host1 != Host) { - rio_dprint(RIO_DEBUG_TABLE, ("Default name %s already used\n", p->RIOHosts[Host].Name)); + 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_dprint(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; } @@ -447,13 +447,13 @@ struct rio_info * p; disable(oldspl); /* strange but true! */ - rio_dprint(RIO_DEBUG_TABLE, ("Generating a table to return to config.rio\n")); + 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 ); for ( Host=0; HostRIOHosts[Host]; MapP = &p->RIOConnectTable[Next++]; MapP->HostUniqueNum = HostP->UniqueNum; @@ -501,8 +501,8 @@ struct Map *MapP; int work_done = 0; unsigned long flags; - rio_dprint(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++ ) { HostP = &p->RIOHosts[host]; @@ -517,15 +517,15 @@ struct Map *MapP; for ( entry=0; entryRtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) { HostMapP = &HostP->Mapping[entry]; - rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("Entry is in use and cannot be deleted!\n")); + 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, flags); return EBUSY; @@ -540,7 +540,7 @@ struct Map *MapP; if ( SysPort != NO_PORT ) { for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) { PortP = p->RIOPortp[port]; - rio_dprint(RIO_DEBUG_TABLE, ("Unmap port\n")); + rio_dprintk (RIO_DEBUG_TABLE, "Unmap port\n"); rio_spin_lock_irqsave( &PortP->portSem, flags ); @@ -548,7 +548,7 @@ struct Map *MapP; if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { - rio_dprint(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 ); @@ -585,25 +585,25 @@ struct Map *MapP; */ Pkt = (PKT *) RIO_PTR(HostP->Caddr, RWORD(*TxPktP)); - rio_dprint(RIO_DEBUG_TABLE, ( + 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)); + Pkt->dest_port, dest_unit, dest_port); WWORD(Pkt->dest_unit, dest_unit); WWORD(Pkt->dest_port, dest_port); } - rio_dprint(RIO_DEBUG_TABLE, ( + 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)); + dest_unit, dest_port); WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8)); } rio_spin_unlock_irqrestore(&PortP->portSem, flags); } } - rio_dprint(RIO_DEBUG_TABLE, ("Entry nulled.\n")); + rio_dprintk (RIO_DEBUG_TABLE, "Entry nulled.\n"); bzero((char *)HostMapP,sizeof(struct Map)); work_done++; } @@ -625,7 +625,7 @@ struct Map *MapP; if ( work_done ) return 0; - rio_dprint(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; } @@ -638,32 +638,32 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) int link; - rio_dprint(RIO_DEBUG_TABLE, ("Assign entry on host %x, rta %x, ID %d, Sysport %d\n", + 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 )); + MapP->ID, (int)MapP->SysPort); if ((MapP->ID != (ushort)-1) && ((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP )) { - rio_dprint(RIO_DEBUG_TABLE, ("Bad ID in map entry!\n")); + 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_dprint(RIO_DEBUG_TABLE, ("Rta Unique number zero!\n")); + 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_dprint(RIO_DEBUG_TABLE, ("Port %d not multiple of %d!\n",(int)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_dprint(RIO_DEBUG_TABLE, ("Port %d not valid!\n",(int)MapP->SysPort)); + rio_dprintk (RIO_DEBUG_TABLE, "Port %d not valid!\n",(int)MapP->SysPort); p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; return EINVAL; } @@ -677,7 +677,7 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) { if ( *sptr<' ' || *sptr>'~' ) { - rio_dprint(RIO_DEBUG_TABLE, ("Name entry contains non-printing characters!\n")); + rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); p->RIOError.Error = BAD_CHARACTER_IN_NAME; return EINVAL; } @@ -702,8 +702,8 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) { int nNewID; - rio_dprint(RIO_DEBUG_TABLE, ("Attempting to get a new ID for rta \"%s\"\n", - MapP->Name)); + 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. @@ -721,7 +721,7 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) return EBUSY; } MapP->ID = (ushort)nNewID + 1; - rio_dprint(RIO_DEBUG_TABLE, ("Allocated ID %d for this new RTA.\n",MapP->ID)); + 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; @@ -747,9 +747,9 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) HostMapP->Flags |= RTA16_SECOND_SLOT; HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID; p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID; - rio_dprint(RIO_DEBUG_TABLE, ("Cross referenced id %d to ID %d.\n", + rio_dprintk (RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, - p->RIOHosts[host].Mapping[unit].ID)); + p->RIOHosts[host].Mapping[unit].ID); } } @@ -757,7 +757,7 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) if ( HostMapP->Flags & SLOT_IN_USE ) { - rio_dprint(RIO_DEBUG_TABLE, ("Map table slot for ID %d is already in use.\n",MapP->ID)); + 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; } @@ -791,15 +791,15 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP ) p->RIOLastPortsBooted = HostMapP->SysPort; } if (MapP->Flags & RTA16_SECOND_SLOT) - rio_dprint(RIO_DEBUG_TABLE, ("Second map of RTA %s added to configuration\n", - p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name)); + rio_dprintk (RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", + p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name); else - rio_dprint(RIO_DEBUG_TABLE, ("RTA %s added to configuration\n",MapP->Name)); + rio_dprintk (RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name); return 0; } } p->RIOError.Error = UNKNOWN_HOST_NUMBER; - rio_dprint(RIO_DEBUG_TABLE, ("Unknown host %x\n",MapP->HostUniqueNum)); + rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); return ENXIO; } @@ -822,7 +822,7 @@ struct Map *HostMapP; CheckHostMapP( HostMapP ); #endif - rio_dprint(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 @@ -833,26 +833,26 @@ struct Map *HostMapP; return(0); RtaType = GetUnitType(HostMapP->RtaUniqueNum); - rio_dprint(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; SubEntSysPort = %d\n", - SubEnt, (int) HostMapP->SysPort)); + 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_dprint (RIO_DEBUG_TABLE, ("c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp)); + rio_dprintk (RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp); PortP = p->RIOPortp[SysPort]; #if 0 PortP->TtyP = &p->channel[SysPort]; #endif - rio_dprint(RIO_DEBUG_TABLE, ("Map port\n")); + rio_dprintk (RIO_DEBUG_TABLE, "Map port\n"); /* ** Point at all the real neat data structures @@ -1008,12 +1008,12 @@ struct Map* MapP; struct Map *HostMapP; char *sptr; - rio_dprint(RIO_DEBUG_TABLE, ("Change name entry on host %x, rta %x, ID %d, Sysport %d\n", + 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 )); + MapP->ID, (int)MapP->SysPort); if ( MapP->ID > MAX_RUP ) { - rio_dprint(RIO_DEBUG_TABLE, ("Bad ID in map entry!\n")); + rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; return EINVAL; } @@ -1023,7 +1023,7 @@ struct Map* MapP; while ( *sptr ) { if ( *sptr<' ' || *sptr>'~' ) { - rio_dprint(RIO_DEBUG_TABLE, ("Name entry contains non-printing characters!\n")); + rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); p->RIOError.Error = BAD_CHARACTER_IN_NAME; return EINVAL; } @@ -1052,6 +1052,6 @@ struct Map* MapP; } } p->RIOError.Error = UNKNOWN_HOST_NUMBER; - rio_dprint(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/riotty.c b/drivers/char/rio/riotty.c index cda417f3f..c9134e3fc 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -164,15 +164,15 @@ riotopen(struct tty_struct * tty, struct file * filp) Modem = rio_ismodem (tty->device); if ( p->RIOFailed ) { - rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n")); + rio_dprintk (RIO_DEBUG_TTY, "System initialisation failed\n"); pseterr(ENXIO); func_exit (); return -ENXIO; } - rio_dprint(RIO_DEBUG_TTY, ("port open SysPort %d (%s) (mapped:%d)\n", + rio_dprintk (RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n", SysPort, Modem ? "Modem" : "tty", - p->RIOPortp[SysPort]->Mapped ) ); + p->RIOPortp[SysPort]->Mapped); /* ** Validate that we have received a legitimate request. @@ -181,7 +181,7 @@ riotopen(struct tty_struct * tty, struct file * filp) ** has been mapped onto a host. */ if (SysPort >= RIO_PORTS) { /* out of range ? */ - rio_dprint(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; @@ -197,7 +197,7 @@ riotopen(struct tty_struct * tty, struct file * filp) ** The system doesn't know which RTA this port ** corresponds to. */ - rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n")); + rio_dprintk (RIO_DEBUG_TTY, "port not mapped into system\n"); func_exit (); pseterr(ENXIO); return -ENXIO; @@ -206,17 +206,26 @@ riotopen(struct tty_struct * tty, struct file * filp) tty->driver_data = PortP; PortP->gs.tty = tty; + if (!PortP->gs.count) + rio_inc_mod_count (); PortP->gs.count++; - rio_dprint(RIO_DEBUG_TTY, ("%d bytes in tx buffer\n", - PortP->gs.xmit_cnt)); - gs_init_port (&PortP->gs); + rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n", + PortP->gs.xmit_cnt); + + retval = gs_init_port (&PortP->gs); + if (retval) { + PortP->gs.count--; + if (PortP->gs.count) + rio_dec_mod_count (); + return -ENXIO; + } /* ** If the host hasn't been booted yet, then ** fail */ if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) { - rio_dprint(RIO_DEBUG_TTY, ("Host not running\n")); + rio_dprintk (RIO_DEBUG_TTY, "Host not running\n"); pseterr(ENXIO); func_exit (); return -ENXIO; @@ -230,24 +239,24 @@ riotopen(struct tty_struct * tty, struct file * filp) #if 0 if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { if (PortP->WaitUntilBooted) { - rio_dprint(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_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n")); + rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); func_exit (); return -EINTR; } if (repeat_this -- <= 0) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n")); + rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); RIOPreemptiveCmd(p, PortP, FCLOSE ); pseterr(EINTR); func_exit (); return -EIO; } } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)); - rio_dprint(RIO_DEBUG_TTY, ("RTA has been booted\n")); + rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n"); } else { - rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n")); + rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n"); pseterr(ENXIO); func_exit (); return 0; @@ -258,10 +267,10 @@ riotopen(struct tty_struct * tty, struct file * filp) easier to read and shorter. Now, if it works too that would be great... -- REW */ - rio_dprint(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_dprint(RIO_DEBUG_TTY, ("RTA never booted\n")); + rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n"); func_exit (); return -ENXIO; } @@ -271,17 +280,17 @@ riotopen(struct tty_struct * tty, struct file * filp) now. --REW */ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n")); + rio_dprintk (RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n"); func_exit (); return -EINTR; } if (repeat_this -- <= 0) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n")); + rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); func_exit (); return -EIO; } } - rio_dprint(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 */ @@ -304,9 +313,9 @@ riotopen(struct tty_struct * tty, struct file * filp) ** for it to finish, so that it doesn't close us! */ while ( (PortP->State & RIO_CLOSING) && !p->RIOHalted ) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for RIO_CLOSING to go away\n")); + rio_dprintk (RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n"); if (repeat_this -- <= 0) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for not idle closed broken by signal\n")); + rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); RIOPreemptiveCmd(p, PortP, FCLOSE ); retval = -EINTR; goto bombout; @@ -321,7 +330,7 @@ riotopen(struct tty_struct * tty, struct file * filp) } if ( !PortP->Mapped ) { - rio_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n")); + rio_dprintk (RIO_DEBUG_TTY, "Port unmapped while closing!\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); retval = -ENXIO; func_exit (); @@ -344,8 +353,8 @@ riotopen(struct tty_struct * tty, struct file * filp) } if (!(PortP->firstOpen)) { /* First time ? */ - rio_dprint(RIO_DEBUG_TTY, ("First open for this port\n")); - rio_inc_mod_count (); + rio_dprintk (RIO_DEBUG_TTY, "First open for this port\n"); + PortP->firstOpen++; PortP->CookMode = 0; /* XXX RIOCookMode(tp); */ @@ -375,7 +384,7 @@ riotopen(struct tty_struct * tty, struct file * filp) ** wait for the port to be not closed. */ while ( !(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted ) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for PORT_ISOPEN-currently %x\n",PortP->PortState)); + 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" @@ -392,7 +401,7 @@ riotopen(struct tty_struct * tty, struct file * filp) */ rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n")); + rio_dprintk (RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n"); RIOPreemptiveCmd(p, PortP, FCLOSE ); func_exit (); return -EINTR; @@ -407,52 +416,67 @@ bombout: rio_spin_unlock_irqrestore(&PortP->portSem, flags); return retval; } - rio_dprint(RIO_DEBUG_TTY, ("PORT_ISOPEN found\n")); + rio_dprintk (RIO_DEBUG_TTY, "PORT_ISOPEN found\n"); } #ifdef MODEM_SUPPORT if (Modem) { - rio_dprint(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 ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) + if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) { - rio_dprint(RIO_DEBUG_TTY, (PortP,DBG_OPEN,"open(%d) Modem carr on\n",SysPort)); + 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); + */ + PortP->State |= RIO_CARR_ON; + wake_up_interruptible (&PortP->gs.open_wait); } else /* no carrier - wait for DCD */ { - while (!(tp->tm.c_state&CARR_ON) && - !(filp->f_flags&O_NONBLOCK) && !p->RIOHalted ) - { - rio_dprint(RIO_DEBUG_TTY, (PortP,DBG_OPEN,"open(%d) sleeping for carr on\n",SysPort)); - tp->tm.c_state |= WOPEN; + /* + 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->State |= RIO_WOPEN; - if ( sleep((caddr_t)&tp->tm.c_canq, TTIPRI|PCATCH)) +#if 0 + if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH)) { /* ** ACTION: verify that this is a good thing ** to do here. -- ??? ** I think it's OK. -- REW */ - rio_dprint(RIO_DEBUG_TTY, ("open(%d) sleeping for carr broken by signal\n", - SysPort)); + 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; } +#endif } PortP->State &= ~RIO_WOPEN; } - if ( RIOHalted ) + if ( p->RIOHalted ) goto bombout; + rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); PortP->State |= RIO_MOPEN; } else @@ -470,7 +494,7 @@ bombout: goto bombout; } - rio_dprint(RIO_DEBUG_TTY, ("high level open done\n")); + rio_dprintk (RIO_DEBUG_TTY, "high level open done\n"); #ifdef STATS PortP->Stat.OpenCnt++; @@ -482,7 +506,7 @@ bombout: PortP->opens++; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprint(RIO_DEBUG_TTY, ("Returning from open\n")); + rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n"); func_exit (); return 0; } @@ -509,13 +533,13 @@ riotclose(void *ptr) int Modem; int rv =0; - rio_dprint(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_dprint(RIO_DEBUG_TTY, ("Port is at address 0x%x\n",(int)PortP)); + rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP); /* tp = PortP->TtyP;*/ /* Get tty */ tty = PortP->gs.tty; - rio_dprint(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); Modem = rio_ismodem(tty->device); #if 0 /* What F.CKING cache? Even then, a higly idle multiprocessor, @@ -533,7 +557,7 @@ riotclose(void *ptr) PortP->State |= RIO_CLOSING; if ( (PortP->State & RIO_DELETED) ) { - rio_dprint(RIO_DEBUG_TTY, ("Close on deleted RTA\n")); + rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n"); deleted = 1; } @@ -543,7 +567,7 @@ riotclose(void *ptr) goto close_end; } - rio_dprint(RIO_DEBUG_TTY, ("Clear bits\n")); + rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n"); /* ** clear the open bits for this device */ @@ -561,7 +585,7 @@ riotclose(void *ptr) ** The port is still open for the other task - ** return, pretending that we are still active. */ - rio_dprint(RIO_DEBUG_TTY, ("Channel %d still open !\n",PortP->PortNum)); + rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum); PortP->State &= ~RIO_CLOSING; if (PortP->firstOpen) PortP->firstOpen--; @@ -569,7 +593,7 @@ riotclose(void *ptr) return -EIO; } - rio_dprint(RIO_DEBUG_TTY, ("Closing down - everything must go!\n")); + rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n"); PortP->State &= ~RIO_DYNOROD; @@ -578,7 +602,7 @@ riotclose(void *ptr) ** to drain down before closing. Bye-bye.... ** (We never meant to do this) */ - rio_dprint(RIO_DEBUG_TTY, ("Timeout 1 starts\n")); + rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n"); #if 0 if (!deleted) @@ -587,14 +611,14 @@ riotclose(void *ptr) cprintf("Need to flush the ttyport\n"); if (repeat_this -- <= 0) { rv = -EINTR; - rio_dprint(RIO_DEBUG_TTY, ("Waiting for not idle closed broken by signal\n")); + rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); RIOPreemptiveCmd(p, PortP, FCLOSE ); goto close_end; } - rio_dprint(RIO_DEBUG_TTY, ("Calling timeout to flush in closing\n")); + 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_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n")); + rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); rv = -EINTR; rio_spin_lock_irqsave(&PortP->portSem, flags); goto close_end; @@ -611,7 +635,7 @@ riotclose(void *ptr) ** The port has been re-opened for the other task - ** return, pretending that we are still active. */ - rio_dprint(RIO_DEBUG_TTY, ("Channel %d re-open!\n", PortP->PortNum)); + 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) @@ -638,12 +662,12 @@ riotclose(void *ptr) while (try && (PortP->PortState & PORT_ISOPEN)) { try--; if (try == 0) { - rio_dprint(RIO_DEBUG_TTY, ("Run out of tries - force the bugger shut!\n" )); + rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" ); RIOPreemptiveCmd(p, PortP,FCLOSE); break; } - rio_dprint(RIO_DEBUG_TTY, ("Close: PortState:ISOPEN is %d\n", - PortP->PortState & PORT_ISOPEN)); + rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", + PortP->PortState & PORT_ISOPEN); if ( p->RIOHalted ) { RIOClearUp( PortP ); @@ -652,7 +676,7 @@ riotclose(void *ptr) RIODelay_ni(PortP, HUNDRED_MS); } rio_spin_lock_irqsave(&PortP->portSem, flags); - rio_dprint(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); */ @@ -682,7 +706,7 @@ close_end: if (PortP->firstOpen) PortP->firstOpen--; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprint(RIO_DEBUG_TTY, ("Return from close\n")); + rio_dprintk (RIO_DEBUG_TTY, "Return from close\n"); return rv; } @@ -731,7 +755,7 @@ static void RIOClearUp(PortP) struct Port *PortP; { - rio_dprint(RIO_DEBUG_TTY, ("RIOHalted set\n")); + rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n"); PortP->Config = 0; /* Direct semaphore */ PortP->PortState = 0; PortP->firstOpen = 0; @@ -761,7 +785,7 @@ static int RIOShortCommand(struct rio_info *p, struct Port *PortP, int retries = 20; /* at 10 per second -> 2 seconds */ unsigned long flags; - rio_dprint(RIO_DEBUG_TTY, ("entering shortcommand.\n")); + rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n"); #ifdef CHECK CheckPortP( PortP ); if ( len < 1 || len > 2 ) @@ -769,7 +793,7 @@ static int RIOShortCommand(struct rio_info *p, struct Port *PortP, #endif if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_TTY, ("Short command to deleted RTA ignored\n")); + rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); return RIO_FAIL; } rio_spin_lock_irqsave(&PortP->portSem, flags); @@ -779,8 +803,8 @@ static int RIOShortCommand(struct rio_info *p, struct Port *PortP, ** be free again. */ while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) { - rio_dprint(RIO_DEBUG_TTY, ("Waiting for not in use (%d)\n", - retries)); + 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; @@ -791,16 +815,16 @@ static int RIOShortCommand(struct rio_info *p, struct Port *PortP, rio_spin_lock_irqsave(&PortP->portSem, flags); } if ( PortP->State & RIO_DELETED ) { - rio_dprint(RIO_DEBUG_TTY, ("Short command to deleted RTA ignored\n")); + 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_dprint(RIO_DEBUG_TTY, ("Waiting to add short command to queue (%d)\n", retries)); + 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_dprint(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 ) { @@ -865,11 +889,11 @@ register caddr_t arg; int Modem = rio_ismodem(dev); int ioctl_processed; - rio_dprint(RIO_DEBUG_TTY, ("port ioctl SysPort %d command 0x%x argument 0x%x %s\n", - SysPort,cmd,arg,Modem?"Modem":"tty")); + 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_dprint(RIO_DEBUG_TTY, ("Bad port number %d\n",SysPort)); + rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort); return -ENXIO; } @@ -926,22 +950,22 @@ register caddr_t arg; return 0; case TCRIOTSTATE: - rio_dprint(RIO_DEBUG_TTY, ("tbusy/tstop monitoring %sabled\n", - arg ? "en" : "dis")); + 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_dprint(RIO_DEBUG_TTY, ("TCRIOSTATE\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE\n"); if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL) - rio_dprint(RIO_DEBUG_TTY, ("TCRIOSTATE command failed\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE command failed\n"); PortP->State |= RIO_BUSY; current = PortP->ModemState; if ( copyout((caddr_t)¤t, (int)arg, sizeof(current))==COPYFAIL ) { - rio_dprint(RIO_DEBUG_TTY, ("Copyout failed\n")); + rio_dprintk (RIO_DEBUG_TTY, "Copyout failed\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); } @@ -950,15 +974,15 @@ register caddr_t arg; case TCRIOMBIS: /* Set modem lines */ case TCRIOMBIC: /* Clear modem lines */ - rio_dprint(RIO_DEBUG_TTY, ("TCRIOMBIS/TCRIOMBIC\n")); + 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_dprint(RIO_DEBUG_TTY, ( - "TCRIOMBIS command failed\n")); + rio_dprintk (RIO_DEBUG_TTY, + "TCRIOMBIS command failed\n"); } else { uint state; @@ -967,17 +991,17 @@ register caddr_t arg; PortP->ModemState &= ~(ushort)state; PortP->ModemLines = (ulong) arg; if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL) - rio_dprint(RIO_DEBUG_TTY, ("TCRIOMBIC command failed\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIC command failed\n"); } PortP->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOXPON: /* set Xprint ON string */ - rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPON\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPON\n"); if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn, MAX_XP_CTRL_LEN)==COPYFAIL ) { - rio_dprint(RIO_DEBUG_TTY, ("Copyin failed\n")); + rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n"); PortP->Xprint.XpOn[0] = '\0'; rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); @@ -989,10 +1013,10 @@ register caddr_t arg; return 0; case TCRIOXPOFF: /* set Xprint OFF string */ - rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPOFF\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPOFF\n"); if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff, MAX_XP_CTRL_LEN)==COPYFAIL ) { - rio_dprint(RIO_DEBUG_TTY, ("Copyin failed\n")); + rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n"); PortP->Xprint.XpOff[0] = '\0'; rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); @@ -1004,10 +1028,10 @@ register caddr_t arg; return 0; case TCRIOXPCPS: /* set Xprint CPS string */ - rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPCPS\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPCPS\n"); if ( (uint)arg > p->RIOConf.MaxXpCps || (uint)arg < p->RIOConf.MinXpCps ) { - rio_dprint(RIO_DEBUG_TTY, ("%d CPS out of range\n",arg)); + rio_dprintk (RIO_DEBUG_TTY, "%d CPS out of range\n",arg); rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EINVAL); return 0; @@ -1017,7 +1041,7 @@ register caddr_t arg; return 0; case TCRIOXPRINT: - rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPRINT\n")); + 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); @@ -1027,25 +1051,25 @@ register caddr_t arg; return 0; case TCRIOIXANYON: - rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXANYON\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n"); PortP->Config |= RIO_IXANY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXANYOFF: - rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXANYOFF\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYOFF\n"); PortP->Config &= ~RIO_IXANY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXONON: - rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXONON\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONON\n"); PortP->Config |= RIO_IXON; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXONOFF: - rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXONOFF\n")); + rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONOFF\n"); PortP->Config &= ~RIO_IXON; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; @@ -1055,28 +1079,28 @@ register caddr_t arg; ** Added support for CTS and RTS flow control ioctls : */ case TCRIOCTSFLOWEN: - rio_dprint(RIO_DEBUG_TTY, ("TCRIOCTSFLOWEN\n")); + 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_dprint(RIO_DEBUG_TTY, ("TCRIOCTSFLOWDIS\n")); + 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_dprint(RIO_DEBUG_TTY, ("TCRIORTSFLOWEN\n")); + 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_dprint(RIO_DEBUG_TTY, ("TCRIORTSFLOWDIS\n")); + 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); @@ -1100,13 +1124,13 @@ register caddr_t arg; case TCSETAW: case TCSETAF: ioctl_processed++; - rio_dprint(RIO_DEBUG_TTY, ("NON POSIX ioctl\n")); + 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_dprint(RIO_DEBUG_TTY, ("NON POSIX SYSV ioctl\n")); + rio_dprintk (RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n"); ttyseth_pv(PortP, tp, (struct termios *)arg, 1); ioctl_processed++; break; @@ -1141,7 +1165,7 @@ register caddr_t arg; #endif case TIOCSETD: case TIOCSETN: - rio_dprint(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. @@ -1208,8 +1232,8 @@ register caddr_t arg; PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */ - rio_dprint(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 /* @@ -1232,7 +1256,7 @@ register caddr_t arg; */ if (changed || oldcook != PortP->CookMode || (ioctl_processed)) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprint(RIO_DEBUG_TTY, ("Ioctl changing the PORT settings\n")); + 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); } diff --git a/drivers/char/saa5249.c b/drivers/char/saa5249.c deleted file mode 100644 index 1213e2ee5..000000000 --- a/drivers/char/saa5249.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Cleaned up to use existing videodev interface and allow the idea - * of multiple teletext decoders on the video4linux iface. Changed i2c - * to cover addressing clashes on device busses. It's also rebuilt so - * you can add arbitary multiple teletext devices to Linux video4linux - * now (well 32 anyway). - * - * Alan Cox - * - * The original driver was heavily modified to match the i2c interface - * It was truncated to use the WinTV boards, too. - * - * Copyright (c) 1998 Richard Guenther - * - * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $ - * - * Derived From - * - * vtx.c: - * This is a loadable character-device-driver for videotext-interfaces - * (aka teletext). Please check the Makefile/README for a list of supported - * interfaces. - * - * Copyright (c) 1994-97 Martin Buck - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define VTX_VER_MAJ 1 -#define VTX_VER_MIN 7 - - - -#define NUM_DAUS 4 -#define NUM_BUFS 8 -#define IF_NAME "SAA5249" - -static const int disp_modes[8][3] = -{ - { 0x46, 0x03, 0x03 }, /* DISPOFF */ - { 0x46, 0xcc, 0xcc }, /* DISPNORM */ - { 0x44, 0x0f, 0x0f }, /* DISPTRANS */ - { 0x46, 0xcc, 0x46 }, /* DISPINS */ - { 0x44, 0x03, 0x03 }, /* DISPOFF, interlaced */ - { 0x44, 0xcc, 0xcc }, /* DISPNORM, interlaced */ - { 0x44, 0x0f, 0x0f }, /* DISPTRANS, interlaced */ - { 0x44, 0xcc, 0x46 } /* DISPINS, interlaced */ -}; - - - -#define PAGE_WAIT (300*HZ/1000) /* Time between requesting page and */ - /* checking status bits */ -#define PGBUF_EXPIRE (15*HZ) /* Time to wait before retransmitting */ - /* page regardless of infobits */ -typedef struct { - u8 pgbuf[VTX_VIRTUALSIZE]; /* Page-buffer */ - u8 laststat[10]; /* Last value of infobits for DAU */ - u8 sregs[7]; /* Page-request registers */ - unsigned long expire; /* Time when page will be expired */ - unsigned clrfound : 1; /* VTXIOCCLRFOUND has been called */ - unsigned stopped : 1; /* VTXIOCSTOPDAU has been called */ -} vdau_t; - -struct saa5249_device -{ - vdau_t vdau[NUM_DAUS]; /* Data for virtual DAUs (the 5249 only has one */ - /* real DAU, so we have to simulate some more) */ - int vtx_use_count; - int is_searching[NUM_DAUS]; - int disp_mode; - int virtual_mode; - struct i2c_client *client; -}; - - -#define CCTWR 34 /* I²C write/read-address of vtx-chip */ -#define CCTRD 35 -#define NOACK_REPEAT 10 /* Retry access this many times on failure */ -#define CLEAR_DELAY (HZ/20) /* Time required to clear a page */ -#define READY_TIMEOUT (30*HZ/1000) /* Time to wait for ready signal of I²C-bus interface */ -#define INIT_DELAY 500 /* Time in usec to wait at initialization of CEA interface */ -#define START_DELAY 10 /* Time in usec to wait before starting write-cycle (CEA) */ - -#define VTX_DEV_MINOR 0 - -/* General defines and debugging support */ - -#ifndef FALSE -#define FALSE 0 -#define TRUE 1 -#endif -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#define RESCHED \ - do { \ - if (current->need_resched) \ - schedule(); \ - } while (0) - -static struct video_device saa_template; /* Declared near bottom */ - -/* Addresses to scan */ -static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; - -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -static struct i2c_client client_template; - -static int saa5249_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind) -{ - int pgbuf; - int err; - struct i2c_client *client; - struct video_device *vd; - struct saa5249_device *t; - - printk(KERN_INFO "saa5249: teletext chip found.\n"); - client=kmalloc(sizeof(*client), GFP_KERNEL); - if(client==NULL) - return -ENOMEM; - client_template.adapter = adap; - client_template.addr = addr; - memcpy(client, &client_template, sizeof(*client)); - t = kmalloc(sizeof(*t), GFP_KERNEL); - if(t==NULL) - { - kfree(client); - return -ENOMEM; - } - memset(t, 0, sizeof(*t)); - strcpy(client->name, IF_NAME); - - /* - * Now create a video4linux device - */ - - client->data = vd=(struct video_device *)kmalloc(sizeof(struct video_device), GFP_KERNEL); - if(vd==NULL) - { - kfree(t); - kfree(client); - return -ENOMEM; - } - memcpy(vd, &saa_template, sizeof(*vd)); - - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) - { - memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); - memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); - memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); - t->vdau[pgbuf].expire = 0; - t->vdau[pgbuf].clrfound = TRUE; - t->vdau[pgbuf].stopped = TRUE; - t->is_searching[pgbuf] = FALSE; - } - vd->priv=t; - - /* - * Register it - */ - - if((err=video_register_device(vd, VFL_TYPE_VTX))<0) - { - kfree(t); - kfree(vd); - kfree(client); - return err; - } - t->client = client; - i2c_attach_client(client); - MOD_INC_USE_COUNT; - return 0; -} - -/* - * We do most of the hard work when we become a device on the i2c. - */ - -static int saa5249_probe(struct i2c_adapter *adap) -{ - /* Only attach these chips to the BT848 bus for now */ - - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - { - return i2c_probe(adap, &addr_data, saa5249_attach); - } - return 0; -} - -static int saa5249_detach(struct i2c_client *client) -{ - struct video_device *vd=client->data; - i2c_detach_client(client); - video_unregister_device(vd); - kfree(vd->priv); - kfree(vd); - kfree(client); - MOD_DEC_USE_COUNT; - 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 = -{ - IF_NAME, /* name */ - I2C_DRIVERID_SAA5249, /* in i2c.h */ - I2C_DF_NOTIFY, - saa5249_probe, - saa5249_detach, - saa5249_command -}; - -static struct i2c_client client_template = { - "(unset)", - -1, - 0, - 0, - NULL, - &i2c_driver_videotext -}; - -/* - * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual - * delay may be longer. - */ - -static void jdelay(unsigned long delay) -{ - sigset_t oldblocked = current->blocked; - - spin_lock_irq(¤t->sigmask_lock); - sigfillset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(delay); - - spin_lock_irq(¤t->sigmask_lock); - current->blocked = oldblocked; - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); -} - - -/* - * I2C interfaces - */ - -static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) -{ - char buf[64]; - - buf[0] = reg; - memcpy(buf+1, data, count); - - if(i2c_master_send(t->client, buf, count+1)==count+1) - return 0; - return -1; -} - -static int i2c_senddata(struct saa5249_device *t, ...) -{ - unsigned char buf[64]; - int v; - int ct=0; - va_list argp; - va_start(argp,t); - - while((v=va_arg(argp,int))!=-1) - buf[ct++]=v; - return i2c_sendbuf(t, buf[0], ct-1, buf+1); -} - -/* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop - * handshaking is done by this routine, ack will be sent after the last byte to inhibit further - * sending of data. If uaccess is TRUE, data is written to user-space with put_user. - * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise - */ - -static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) -{ - if(i2c_master_recv(t->client, buf, count)!=count) - return -1; - return 0; -} - - -/* - * Standard character-device-driver functions - */ - -static int saa5249_ioctl(struct video_device *vd, unsigned int cmd, void *arg) -{ - struct saa5249_device *t=vd->priv; - static int virtual_mode = FALSE; - - switch(cmd) - { - case VTXIOCGETINFO: - { - vtx_info_t info; - info.version_major = VTX_VER_MAJ; - info.version_minor = VTX_VER_MIN; - info.numpages = NUM_DAUS; - /*info.cct_type = CCT_TYPE;*/ - if(copy_to_user((void*)arg, &info, sizeof(vtx_info_t))) - return -EFAULT; - return 0; - } - - case VTXIOCCLRPAGE: - { - vtx_pagereq_t req; - - if(copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t))) - return -EFAULT; - if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS) - return -EINVAL; - memset(t->vdau[req.pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); - t->vdau[req.pgbuf].clrfound = TRUE; - return 0; - } - - case VTXIOCCLRFOUND: - { - vtx_pagereq_t req; - - if(copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t))) - return -EFAULT; - if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS) - return -EINVAL; - t->vdau[req.pgbuf].clrfound = TRUE; - return 0; - } - - case VTXIOCPAGEREQ: - { - vtx_pagereq_t req; - if(copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t))) - return -EFAULT; - if (!(req.pagemask & PGMASK_PAGE)) - req.page = 0; - if (!(req.pagemask & PGMASK_HOUR)) - req.hour = 0; - if (!(req.pagemask & PGMASK_MINUTE)) - req.minute = 0; - if (req.page < 0 || req.page > 0x8ff) /* 7FF ?? */ - return -EINVAL; - req.page &= 0x7ff; - if (req.hour < 0 || req.hour > 0x3f || req.minute < 0 || req.minute > 0x7f || - req.pagemask < 0 || req.pagemask >= PGMASK_MAX || req.pgbuf < 0 || req.pgbuf >= NUM_DAUS) - return -EINVAL; - t->vdau[req.pgbuf].sregs[0] = (req.pagemask & PG_HUND ? 0x10 : 0) | (req.page / 0x100); - t->vdau[req.pgbuf].sregs[1] = (req.pagemask & PG_TEN ? 0x10 : 0) | ((req.page / 0x10) & 0xf); - t->vdau[req.pgbuf].sregs[2] = (req.pagemask & PG_UNIT ? 0x10 : 0) | (req.page & 0xf); - t->vdau[req.pgbuf].sregs[3] = (req.pagemask & HR_TEN ? 0x10 : 0) | (req.hour / 0x10); - t->vdau[req.pgbuf].sregs[4] = (req.pagemask & HR_UNIT ? 0x10 : 0) | (req.hour & 0xf); - t->vdau[req.pgbuf].sregs[5] = (req.pagemask & MIN_TEN ? 0x10 : 0) | (req.minute / 0x10); - t->vdau[req.pgbuf].sregs[6] = (req.pagemask & MIN_UNIT ? 0x10 : 0) | (req.minute & 0xf); - t->vdau[req.pgbuf].stopped = FALSE; - t->vdau[req.pgbuf].clrfound = TRUE; - t->is_searching[req.pgbuf] = TRUE; - return 0; - } - - case VTXIOCGETSTAT: - { - vtx_pagereq_t req; - u8 infobits[10]; - vtx_pageinfo_t info; - int a; - - if(copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t))) - return -EFAULT; - if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS) - return -EINVAL; - if (!t->vdau[req.pgbuf].stopped) - { - if (i2c_senddata(t, 2, 0, -1) || - i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req.pgbuf].sregs) || - i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || - i2c_senddata(t, 2, 0, t->vdau[req.pgbuf].sregs[0] | 8, -1) || - i2c_senddata(t, 8, 0, 25, 0, -1)) - return -EIO; - jdelay(PAGE_WAIT); - if (i2c_getdata(t, 10, infobits)) - return -EIO; - - if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ - (memcmp(infobits, t->vdau[req.pgbuf].laststat, sizeof(infobits)) || - time_after_eq(jiffies, t->vdau[req.pgbuf].expire))) - { /* check if new page arrived */ - if (i2c_senddata(t, 8, 0, 0, 0, -1) || - i2c_getdata(t, VTX_PAGESIZE, t->vdau[req.pgbuf].pgbuf)) - return -EIO; - t->vdau[req.pgbuf].expire = jiffies + PGBUF_EXPIRE; - memset(t->vdau[req.pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); - if (t->virtual_mode) - { - /* Packet X/24 */ - if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || - i2c_getdata(t, 40, t->vdau[req.pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) - return -EIO; - /* Packet X/27/0 */ - if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || - i2c_getdata(t, 40, t->vdau[req.pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) - return -EIO; - /* Packet 8/30/0...8/30/15 - * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, - * so we should undo this here. - */ - if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || - i2c_getdata(t, 40, t->vdau[req.pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) - return -EIO; - } - t->vdau[req.pgbuf].clrfound = FALSE; - memcpy(t->vdau[req.pgbuf].laststat, infobits, sizeof(infobits)); - } - else - { - memcpy(infobits, t->vdau[req.pgbuf].laststat, sizeof(infobits)); - } - } - else - { - memcpy(infobits, t->vdau[req.pgbuf].laststat, sizeof(infobits)); - } - - info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); - if (info.pagenum < 0x100) - info.pagenum += 0x800; - info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); - info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); - info.charset = ((infobits[7] >> 1) & 7); - info.delete = !!(infobits[3] & 8); - info.headline = !!(infobits[5] & 4); - info.subtitle = !!(infobits[5] & 8); - info.supp_header = !!(infobits[6] & 1); - info.update = !!(infobits[6] & 2); - info.inter_seq = !!(infobits[6] & 4); - info.dis_disp = !!(infobits[6] & 8); - info.serial = !!(infobits[7] & 1); - info.notfound = !!(infobits[8] & 0x10); - info.pblf = !!(infobits[9] & 0x20); - info.hamming = 0; - for (a = 0; a <= 7; a++) - { - if (infobits[a] & 0xf0) - { - info.hamming = 1; - break; - } - } - if (t->vdau[req.pgbuf].clrfound) - info.notfound = 1; - if(copy_to_user(req.buffer, &info, sizeof(vtx_pageinfo_t))) - return -EFAULT; - if (!info.hamming && !info.notfound) - { - t->is_searching[req.pgbuf] = FALSE; - } - return 0; - } - - case VTXIOCGETPAGE: - { - vtx_pagereq_t req; - int start, end; - - if(copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t))) - return -EFAULT; - if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS || req.start < 0 || - req.start > req.end || req.end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) - return -EINVAL; - if(copy_to_user(req.buffer, &t->vdau[req.pgbuf].pgbuf[req.start], req.end - req.start + 1)) - return -EFAULT; - - /* - * Always read the time directly from SAA5249 - */ - - if (req.start <= 39 && req.end >= 32) - { - int len; - char buf[16]; - start = MAX(req.start, 32); - end = MIN(req.end, 39); - len=end-start+1; - if (i2c_senddata(t, 8, 0, 0, start, -1) || - i2c_getdata(t, len, buf)) - return -EIO; - if(copy_to_user(req.buffer+start-req.start, buf, len)) - return -EFAULT; - } - /* Insert the current header if DAU is still searching for a page */ - if (req.start <= 31 && req.end >= 7 && t->is_searching[req.pgbuf]) - { - char buf[32]; - int len; - start = MAX(req.start, 7); - end = MIN(req.end, 31); - len=end-start+1; - if (i2c_senddata(t, 8, 0, 0, start, -1) || - i2c_getdata(t, len, buf)) - return -EIO; - if(copy_to_user(req.buffer+start-req.start, buf, len)) - return -EFAULT; - } - return 0; - } - - case VTXIOCSTOPDAU: - { - vtx_pagereq_t req; - - if(copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t))) - return -EFAULT; - if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS) - return -EINVAL; - t->vdau[req.pgbuf].stopped = TRUE; - t->is_searching[req.pgbuf] = FALSE; - return 0; - } - - case VTXIOCPUTPAGE: - case VTXIOCSETDISP: - case VTXIOCPUTSTAT: - return 0; - - case VTXIOCCLRCACHE: - { - if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, - ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', - ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1)) - return -EIO; - if (i2c_senddata(t, 3, 0x20, -1)) - return -EIO; - jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ - return 0; - } - - case VTXIOCSETVIRT: - { - /* The SAA5249 has virtual-row reception turned on always */ - t->virtual_mode = (int)arg; - return 0; - } - } - return -EINVAL; -} - - -static int saa5249_open(struct video_device *vd, int nb) -{ - struct saa5249_device *t=vd->priv; - int pgbuf; - - if (t->client==NULL) - return -ENODEV; - - if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ - /* Turn off parity checks (we do this ourselves) */ - i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || - /* Display TV-picture, no virtual rows */ - i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */ - - { - return -EIO; - } - - for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) - { - memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); - memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); - memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); - t->vdau[pgbuf].expire = 0; - t->vdau[pgbuf].clrfound = TRUE; - t->vdau[pgbuf].stopped = TRUE; - t->is_searching[pgbuf] = FALSE; - } - t->virtual_mode=FALSE; - MOD_INC_USE_COUNT; - return 0; -} - - - -static void saa5249_release(struct video_device *vd) -{ - struct saa5249_device *t=vd->priv; - i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ - i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ - MOD_DEC_USE_COUNT; - return; -} - -static long saa5249_write(struct video_device *v, const char *buf, unsigned long l, int nb) -{ - return -EINVAL; -} - -static int __init init_saa_5249 (void) -{ - printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n", - VTX_VER_MAJ, VTX_VER_MIN); - return i2c_add_driver(&i2c_driver_videotext); -} - -static void __exit cleanup_saa_5249 (void) -{ - i2c_del_driver(&i2c_driver_videotext); -} - -module_init(init_saa_5249); -module_exit(cleanup_saa_5249); - -static struct video_device saa_template = -{ - IF_NAME, - VID_TYPE_TELETEXT, /*| VID_TYPE_TUNER ?? */ - VID_HARDWARE_SAA5249, - saa5249_open, - saa5249_release, - NULL, /* read */ - saa5249_write, - NULL, /* poll */ - saa5249_ioctl, - /* the rest are null */ -}; - diff --git a/drivers/char/saa7110.c b/drivers/char/saa7110.c deleted file mode 100644 index 6146b84b9..000000000 --- a/drivers/char/saa7110.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - saa7110 - Philips SAA7110(A) video decoder driver - - Copyright (C) 1998 Pauline Middelink - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include -#include -#include -#include - -#include -#include -#include "linux/video_decoder.h" - -#define DEBUG(x...) /* remove when no long debugging */ - -#define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ -#define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ - -#define I2C_SAA7110 0x9C /* or 0x9E */ - -#define I2C_DELAY 10 /* 10 us or 100khz */ - -struct saa7110 { - struct i2c_bus *bus; - int addr; - unsigned char reg[36]; - - int norm; - int input; - int enable; - int bright; - int contrast; - int hue; - int sat; -}; - -/* ----------------------------------------------------------------------- */ -/* I2C support functions */ -/* ----------------------------------------------------------------------- */ -static -int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data) -{ - int ack; - - LOCK_I2C_BUS(decoder->bus); - i2c_start(decoder->bus); - i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY); - i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY); - ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY); - i2c_stop(decoder->bus); - decoder->reg[subaddr] = data; - UNLOCK_I2C_BUS(decoder->bus); - return ack; -} - -static -int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len) -{ - unsigned subaddr = *data; - - LOCK_I2C_BUS(decoder->bus); - i2c_start(decoder->bus); - i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY); - while (len-- > 0) { - if (i2c_sendbyte(decoder->bus,*data,0)) { - i2c_stop(decoder->bus); - return -EAGAIN; - } - decoder->reg[subaddr++] = *data++; - } - i2c_stop(decoder->bus); - UNLOCK_I2C_BUS(decoder->bus); - - return 0; -} - -static -int saa7110_read(struct saa7110* decoder) -{ - int data; - - LOCK_I2C_BUS(decoder->bus); - i2c_start(decoder->bus); - i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY); - i2c_start(decoder->bus); - i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY); - data = i2c_readbyte(decoder->bus, 1); - i2c_stop(decoder->bus); - UNLOCK_I2C_BUS(decoder->bus); - return data; -} - -/* ----------------------------------------------------------------------- */ -/* SAA7110 functions */ -/* ----------------------------------------------------------------------- */ -static -int saa7110_selmux(struct i2c_device *device, int chan) -{ -static const unsigned char modes[9][8] = { -/* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 }, -/* mode 1 */ { 0x00, 0xD8, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 }, -/* mode 2 */ { 0x00, 0xBA, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 }, -/* mode 3 */ { 0x00, 0xB8, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 }, -/* mode 4 */ { 0x00, 0x7C, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 }, -/* mode 5 */ { 0x00, 0x78, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 }, -/* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 }, -/* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 }, -/* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } }; - struct saa7110* decoder = device->data; - const unsigned char* ptr = modes[chan]; - - saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */ - saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */ - saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */ - saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */ - saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */ - saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */ - saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */ - saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */ - - return 0; -} - -static -int determine_norm(struct i2c_device* dev) -{ - struct saa7110* decoder = dev->data; - int status; - - /* mode changed, start automatic detection */ - status = saa7110_read(decoder); - if ((status & 3) == 0) { - saa7110_write(decoder,0x06,0x80); - if (status & 0x20) { - DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name)); - saa7110_write(decoder,0x2E,0x81); - return VIDEO_MODE_NTSC; - } - DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name)); - saa7110_write(decoder,0x2E,0x9A); - return VIDEO_MODE_PAL; - } - - saa7110_write(decoder,0x06,0x00); - if (status & 0x20) { /* 60Hz */ - DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name)); - saa7110_write(decoder,0x0D,0x06); - saa7110_write(decoder,0x11,0x2C); - saa7110_write(decoder,0x2E,0x81); - return VIDEO_MODE_NTSC; - } - - /* 50Hz -> PAL/SECAM */ - saa7110_write(decoder,0x0D,0x06); - saa7110_write(decoder,0x11,0x59); - saa7110_write(decoder,0x2E,0x9A); - - mdelay(150); /* pause 150 ms */ - - status = saa7110_read(decoder); - if ((status & 0x03) == 0x01) { - DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name)); - saa7110_write(decoder,0x0D,0x07); - return VIDEO_MODE_SECAM; - } - DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name)); - return VIDEO_MODE_PAL; -} - -static -int saa7110_attach(struct i2c_device *device) -{ -static const unsigned char initseq[] = { - 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00, - 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x06, 0x18, 0x90, - 0x00, 0x2C, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA, - 0xF0, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F, - 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03, - 0x40, 0x75, 0x01, 0x8C, 0x03}; - struct saa7110* decoder; - int rv; - - device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL); - if (device->data == 0) - return -ENOMEM; - - MOD_INC_USE_COUNT; - - /* clear our private data */ - memset(decoder, 0, sizeof(struct saa7110)); - strcpy(device->name, "saa7110"); - decoder->bus = device->bus; - decoder->addr = device->addr; - decoder->norm = VIDEO_MODE_PAL; - decoder->input = 0; - decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; - - rv = saa7110_write_block(decoder, initseq, sizeof(initseq)); - if (rv < 0) - printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv); - else { - saa7110_write(decoder,0x21,0x16); - saa7110_write(decoder,0x0D,0x04); - DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder))); - saa7110_write(decoder,0x0D,0x06); - } - - /* setup and implicit mode 0 select has been performed */ - return 0; -} - -static -int saa7110_detach(struct i2c_device *device) -{ - struct saa7110* decoder = device->data; - - DEBUG(printk(KERN_INFO "%s_detach\n",device->name)); - - /* stop further output */ - saa7110_write(decoder,0x0E,0x00); - - kfree(device->data); - - MOD_DEC_USE_COUNT; - return 0; -} - -static -int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg) -{ - struct saa7110* decoder = device->data; - int v; - - switch (cmd) { - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *dc = arg; - dc->flags = VIDEO_DECODER_PAL - | VIDEO_DECODER_NTSC - | VIDEO_DECODER_SECAM - | VIDEO_DECODER_AUTO - | VIDEO_DECODER_CCIR; - dc->inputs = SAA7110_MAX_INPUT; - dc->outputs = SAA7110_MAX_OUTPUT; - } - break; - - case DECODER_GET_STATUS: - { - struct saa7110* decoder = device->data; - int status; - int res = 0; - - status = i2c_read(device->bus,device->addr|1); - if (status & 0x40) - res |= DECODER_STATUS_GOOD; - if (status & 0x03) - res |= DECODER_STATUS_COLOR; - - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - } - *(int*)arg = res; - } - break; - - case DECODER_SET_NORM: - v = *(int*)arg; - if (decoder->norm != v) { - decoder->norm = v; - saa7110_write(decoder, 0x06, 0x00); - switch (v) { - case VIDEO_MODE_NTSC: - saa7110_write(decoder, 0x0D, 0x06); - saa7110_write(decoder, 0x11, 0x2C); - saa7110_write(decoder, 0x30, 0x81); -saa7110_write(decoder, 0x2A, 0xDF); - break; - case VIDEO_MODE_PAL: - saa7110_write(decoder, 0x0D, 0x06); - saa7110_write(decoder, 0x11, 0x59); - saa7110_write(decoder, 0x2E, 0x9A); - break; - case VIDEO_MODE_SECAM: - saa7110_write(decoder, 0x0D, 0x07); - saa7110_write(decoder, 0x11, 0x59); - saa7110_write(decoder, 0x2E, 0x9A); - break; - case VIDEO_MODE_AUTO: - *(int*)arg = determine_norm(device); - break; - default: - return -EPERM; - } - } - break; - - case DECODER_SET_INPUT: - v = *(int*)arg; - if (v<0 || v>SAA7110_MAX_INPUT) - return -EINVAL; - if (decoder->input != v) { - decoder->input = v; - saa7110_selmux(device, v); - } - break; - - case DECODER_SET_OUTPUT: - v = *(int*)arg; - /* not much choice of outputs */ - if (v != 0) - return -EINVAL; - break; - - case DECODER_ENABLE_OUTPUT: - v = *(int*)arg; - if (decoder->enable != v) { - decoder->enable = v; - saa7110_write(decoder,0x0E, v ? 0x18 : 0x00); - } - break; - - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7110_write(decoder, 0x19, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7110_write(decoder, 0x13, decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7110_write(decoder, 0x12, decoder->sat >> 9); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7110_write(decoder, 0x07, (decoder->hue>>8)-128); - } - } - break; - - case DECODER_DUMP: - for (v=0; v<34; v+=16) { - int j; - DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v)); - for (j=0; j<16; j++) { - DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j])); - } - DEBUG(printk(KERN_INFO "\n")); - } - break; - - default: - DEBUG(printk(KERN_INFO "unknown saa7110_command??(%d)\n",cmd)); - return -EINVAL; - } - return 0; -} - -/* ----------------------------------------------------------------------- */ - -struct i2c_driver i2c_driver_saa7110 = -{ - "saa7110", /* name */ - - I2C_DRIVERID_VIDEODECODER, /* in i2c.h */ - I2C_SAA7110, I2C_SAA7110+1, /* Addr range */ - - saa7110_attach, - saa7110_detach, - saa7110_command -}; - -EXPORT_NO_SYMBOLS; - -#ifdef MODULE -int init_module(void) -#else -int saa7110_init(void) -#endif -{ - return i2c_register_driver(&i2c_driver_saa7110); -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_unregister_driver(&i2c_driver_saa7110); -} -#endif diff --git a/drivers/char/saa7111.c b/drivers/char/saa7111.c deleted file mode 100644 index 1eeeca352..000000000 --- a/drivers/char/saa7111.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - saa7111 - Philips SAA7111A video decoder driver version 0.0.3 - - Copyright (C) 1998 Dave Perks - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define DEBUG(x) /* Debug driver */ - -/* ----------------------------------------------------------------------- */ - -struct saa7111 { - struct i2c_bus *bus; - int addr; - unsigned char reg[32]; - - int norm; - int input; - int enable; - int bright; - int contrast; - int hue; - int sat; -}; - -#define I2C_SAA7111 0x48 - -#define I2C_DELAY 10 - -/* ----------------------------------------------------------------------- */ - -static int saa7111_write(struct saa7111 *dev, unsigned char subaddr, unsigned char data) -{ - int ack; - - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, data, I2C_DELAY); - dev->reg[subaddr] = data; - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return ack; -} - -static int saa7111_write_block(struct saa7111 *dev, unsigned const char *data, unsigned int len) -{ - int ack = 0; - unsigned subaddr; - - while (len > 1) { - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - while (len > 1 && *data == ++subaddr) { - data++; - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - } - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - } - return ack; -} - -static int saa7111_read(struct saa7111 *dev, unsigned char subaddr) -{ - int data; - - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY); - data = i2c_readbyte(dev->bus, 1); - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return data; -} - -/* ----------------------------------------------------------------------- */ - -static int saa7111_attach(struct i2c_device *device) -{ - int i; - struct saa7111 *decoder; - - static const unsigned char init[] = - { - 0x00, 0x00, /* 00 - ID byte */ - 0x01, 0x00, /* 01 - reserved */ - - /*front end */ - 0x02, 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */ - 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x04, 0x00, /* 04 - GAI1=256 */ - 0x05, 0x00, /* 05 - GAI2=256 */ - - /* decoder */ - 0x06, 0xf6, /* 06 - HSB at 13(50Hz) / 17(60Hz) pixels after end of last line */ - 0x07, 0xdd, /* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */ - 0x08, 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, HPLL=0, VNOI=0 */ - 0x09, 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, UPTCV=0, APER=1 */ - 0x0a, 0x80, /* 0a - BRIG=128 */ - 0x0b, 0x47, /* 0b - CONT=1.109 */ - 0x0c, 0x40, /* 0c - SATN=1.0 */ - 0x0d, 0x00, /* 0d - HUE=0 */ - 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ - 0x0f, 0x00, /* 0f - reserved */ - 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */ - 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ - 0x12, 0x00, /* 12 - output control 2 */ - 0x13, 0x00, /* 13 - output control 3 */ - 0x14, 0x00, /* 14 - reserved */ - 0x15, 0x00, /* 15 - VBI */ - 0x16, 0x00, /* 16 - VBI */ - 0x17, 0x00, /* 17 - VBI */ - }; - - device->data = decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL); - if (decoder == NULL) { - return -ENOMEM; - } - MOD_INC_USE_COUNT; - - memset(decoder, 0, sizeof(struct saa7111)); - strcpy(device->name, "saa7111"); - decoder->bus = device->bus; - decoder->addr = device->addr; - decoder->norm = VIDEO_MODE_NTSC; - decoder->input = 0; - decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; - - i = saa7111_write_block(decoder, init, sizeof(init)); - if (i < 0) { - printk(KERN_ERR "%s_attach: init status %d\n", device->name, i); - } else { - printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7111_read(decoder, 0x00)); - } - return 0; -} - - -static int saa7111_detach(struct i2c_device *device) -{ - kfree(device->data); - MOD_DEC_USE_COUNT; - return 0; -} - -static int saa7111_command(struct i2c_device *device, unsigned int cmd, void *arg) -{ - struct saa7111 *decoder = device->data; - - switch (cmd) { - -#if defined(DECODER_DUMP) - case DECODER_DUMP: - { - int i; - - for (i = 0; i < 32; i += 16) { - int j; - - printk("KERN_DEBUG %s: %03x", device->name, i); - for (j = 0; j < 16; ++j) { - printk(" %02x", saa7111_read(decoder, i + j)); - } - printk("\n"); - } - } - break; -#endif /* defined(DECODER_DUMP) */ - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - cap->flags - = VIDEO_DECODER_PAL - | VIDEO_DECODER_NTSC - | VIDEO_DECODER_AUTO - | VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - } - break; - - case DECODER_GET_STATUS: - { - int *iarg = arg; - int status; - int res; - - status = saa7111_read(decoder, 0x1f); - res = 0; - if ((status & (1 << 6)) == 0) { - res |= DECODER_STATUS_GOOD; - } - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & (1 << 5)) != 0) { - res |= DECODER_STATUS_NTSC; - } else { - res |= DECODER_STATUS_PAL; - } - break; - } - if ((status & (1 << 0)) != 0) { - res |= DECODER_STATUS_COLOR; - } - *iarg = res; - } - break; - - case DECODER_SET_NORM: - { - int *iarg = arg; - - switch (*iarg) { - - case VIDEO_MODE_NTSC: - saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x40); - break; - - case VIDEO_MODE_PAL: - saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x00); - break; - - case VIDEO_MODE_AUTO: - saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x80); - break; - - default: - return -EINVAL; - - } - decoder->norm = *iarg; - } - break; - - case DECODER_SET_INPUT: - { - int *iarg = arg; - - if (*iarg < 0 || *iarg > 7) { - return -EINVAL; - } - if (decoder->input != *iarg) { - decoder->input = *iarg; - /* select mode */ - saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8) | decoder->input); - /* bypass chrominance trap for modes 4..7 */ - saa7111_write(decoder, 0x09, (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0)); - } - } - break; - - case DECODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - } - break; - - case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; - int enable = (*iarg != 0); - - if (decoder->enable != enable) { - decoder->enable = enable; - -// RJ: If output should be disabled (for playing videos), we also need a open PLL. - // The input is set to 0 (where no input source is connected), although this - // is not necessary. - // - // If output should be enabled, we have to reverse the above. - - if (decoder->enable) { - saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8) | decoder->input); - saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0xfb)); - saa7111_write(decoder, 0x11, (decoder->reg[0x11] & 0xf3) | 0x0c); - } else { - saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8)); - saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0xfb) | 0x04); - saa7111_write(decoder, 0x11, (decoder->reg[0x11] & 0xf3)); - } - } - } - break; - - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7111_write(decoder, 0x0a, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7111_write(decoder, 0x0b, decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7111_write(decoder, 0x0c, decoder->sat >> 9); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7111_write(decoder, 0x0d, (decoder->hue - 32768) >> 8); - } - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -struct i2c_driver i2c_driver_saa7111 = -{ - "saa7111", /* name */ - I2C_DRIVERID_VIDEODECODER, /* ID */ - I2C_SAA7111, I2C_SAA7111 + 1, - - saa7111_attach, - saa7111_detach, - saa7111_command -}; - -EXPORT_NO_SYMBOLS; - -#ifdef MODULE -int init_module(void) -#else -int saa7111_init(void) -#endif -{ - return i2c_register_driver(&i2c_driver_saa7111); -} - - - -#ifdef MODULE - -void cleanup_module(void) -{ - i2c_unregister_driver(&i2c_driver_saa7111); -} - -#endif diff --git a/drivers/char/saa7121.h b/drivers/char/saa7121.h deleted file mode 100644 index 74e37d405..000000000 --- a/drivers/char/saa7121.h +++ /dev/null @@ -1,132 +0,0 @@ -/* saa7121.h - saa7121 initializations - Copyright (C) 1999 Nathan Laredo (laredo@gnu.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. - - */ -#ifndef __SAA7121_H__ -#define __SAA7121_H__ - -#define NTSC_BURST_START 0x19 /* 28 */ -#define NTSC_BURST_END 0x1d /* 29 */ -#define NTSC_CHROMA_PHASE 0x67 /* 5a */ -#define NTSC_GAINU 0x76 /* 5b */ -#define NTSC_GAINV 0xa5 /* 5c */ -#define NTSC_BLACK_LEVEL 0x2a /* 5d */ -#define NTSC_BLANKING_LEVEL 0x2e /* 5e */ -#define NTSC_VBI_BLANKING 0x2e /* 5f */ -#define NTSC_DAC_CONTROL 0x11 /* 61 */ -#define NTSC_BURST_AMP 0x3f /* 62 */ -#define NTSC_SUBC3 0x1f /* 63 */ -#define NTSC_SUBC2 0x7c /* 64 */ -#define NTSC_SUBC1 0xf0 /* 65 */ -#define NTSC_SUBC0 0x21 /* 66 */ -#define NTSC_HTRIG 0x72 /* 6c */ -#define NTSC_VTRIG 0x00 /* 6c */ -#define NTSC_MULTI 0x30 /* 6e */ -#define NTSC_CCTTX 0x11 /* 6f */ -#define NTSC_FIRST_ACTIVE 0x12 /* 7a */ -#define NTSC_LAST_ACTIVE 0x02 /* 7b */ -#define NTSC_MSB_VERTICAL 0x40 /* 7c */ - -#define PAL_BURST_START 0x21 /* 28 */ -#define PAL_BURST_END 0x1d /* 29 */ -#define PAL_CHROMA_PHASE 0x3f /* 5a */ -#define PAL_GAINU 0x7d /* 5b */ -#define PAL_GAINV 0xaf /* 5c */ -#define PAL_BLACK_LEVEL 0x23 /* 5d */ -#define PAL_BLANKING_LEVEL 0x35 /* 5e */ -#define PAL_VBI_BLANKING 0x35 /* 5f */ -#define PAL_DAC_CONTROL 0x02 /* 61 */ -#define PAL_BURST_AMP 0x2f /* 62 */ -#define PAL_SUBC3 0xcb /* 63 */ -#define PAL_SUBC2 0x8a /* 64 */ -#define PAL_SUBC1 0x09 /* 65 */ -#define PAL_SUBC0 0x2a /* 66 */ -#define PAL_HTRIG 0x86 /* 6c */ -#define PAL_VTRIG 0x04 /* 6d */ -#define PAL_MULTI 0x20 /* 6e */ -#define PAL_CCTTX 0x15 /* 6f */ -#define PAL_FIRST_ACTIVE 0x16 /* 7a */ -#define PAL_LAST_ACTIVE 0x36 /* 7b */ -#define PAL_MSB_VERTICAL 0x40 /* 7c */ - -/* Initialization Sequence */ - -static __u8 init7121ntsc[] = { - 0x26, 0x0, 0x27, 0x0, - 0x28, NTSC_BURST_START, 0x29, NTSC_BURST_END, - 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, - 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, - 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, - 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, - 0x3a, 0x03, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, - 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, - 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, - 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, - 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, - 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, - 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, - 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, - 0x5a, NTSC_CHROMA_PHASE, 0x5b, NTSC_GAINU, - 0x5c, NTSC_GAINV, 0x5d, NTSC_BLACK_LEVEL, - 0x5e, NTSC_BLANKING_LEVEL, 0x5f, NTSC_VBI_BLANKING, - 0x60, 0x0, 0x61, NTSC_DAC_CONTROL, - 0x62, NTSC_BURST_AMP, 0x63, NTSC_SUBC3, - 0x64, NTSC_SUBC2, 0x65, NTSC_SUBC1, - 0x66, NTSC_SUBC0, 0x67, 0x80, 0x68, 0x80, - 0x69, 0x80, 0x6a, 0x80, 0x6b, 0x29, - 0x6c, NTSC_HTRIG, 0x6d, NTSC_VTRIG, - 0x6e, NTSC_MULTI, 0x6f, NTSC_CCTTX, - 0x70, 0xc9, 0x71, 0x68, 0x72, 0x60, 0x73, 0x0, - 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, - 0x78, 0x0, 0x79, 0x0, 0x7a, NTSC_FIRST_ACTIVE, - 0x7b, NTSC_LAST_ACTIVE, 0x7c, NTSC_MSB_VERTICAL, - 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 -}; -#define INIT7121LEN (sizeof(init7121ntsc)/2) - -static __u8 init7121pal[] = { - 0x26, 0x0, 0x27, 0x0, - 0x28, PAL_BURST_START, 0x29, PAL_BURST_END, - 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, - 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, - 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, - 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, - 0x3a, 0x03, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, - 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, - 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, - 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, - 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, - 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, - 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, - 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, - 0x5a, PAL_CHROMA_PHASE, 0x5b, PAL_GAINU, - 0x5c, PAL_GAINV, 0x5d, PAL_BLACK_LEVEL, - 0x5e, PAL_BLANKING_LEVEL, 0x5f, PAL_VBI_BLANKING, - 0x60, 0x0, 0x61, PAL_DAC_CONTROL, - 0x62, PAL_BURST_AMP, 0x63, PAL_SUBC3, - 0x64, PAL_SUBC2, 0x65, PAL_SUBC1, - 0x66, PAL_SUBC0, 0x67, 0x80, 0x68, 0x80, - 0x69, 0x80, 0x6a, 0x80, 0x6b, 0x29, - 0x6c, PAL_HTRIG, 0x6d, PAL_VTRIG, - 0x6e, PAL_MULTI, 0x6f, PAL_CCTTX, - 0x70, 0xc9, 0x71, 0x68, 0x72, 0x60, 0x73, 0x0, - 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, - 0x78, 0x0, 0x79, 0x0, 0x7a, PAL_FIRST_ACTIVE, - 0x7b, PAL_LAST_ACTIVE, 0x7c, PAL_MSB_VERTICAL, - 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 -}; -#endif diff --git a/drivers/char/saa7146.h b/drivers/char/saa7146.h deleted file mode 100644 index 481308e6c..000000000 --- a/drivers/char/saa7146.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - saa7146.h - definitions philips saa7146 based cards - Copyright (C) 1999 Nathan Laredo (laredo@gnu.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. -*/ - -#ifndef __SAA7146__ -#define __SAA7146__ - -#define SAA7146_VERSION_CODE 0x000101 - -#include -#include - -#include -#include - -#ifndef O_NONCAP -#define O_NONCAP O_TRUNC -#endif - -#define MAX_GBUFFERS 2 -#define FBUF_SIZE 0x190000 - -#ifdef __KERNEL__ - -struct saa7146_window -{ - int x, y; - ushort width, height; - ushort bpp, bpl; - ushort swidth, sheight; - short cropx, cropy; - ushort cropwidth, cropheight; - unsigned long vidadr; - int color_fmt; - ushort depth; -}; - -/* Per-open data for handling multiple opens on one device */ -struct device_open -{ - int isopen; - int noncapturing; - struct saa7146 *dev; -}; -#define MAX_OPENS 3 - -struct saa7146 -{ - struct video_device video_dev; - struct video_picture picture; - struct video_audio audio_dev; - struct video_info vidinfo; - int user; - int cap; - int capuser; - int irqstate; /* irq routine is state driven */ - int writemode; - int playmode; - unsigned int nr; - unsigned long irq; /* IRQ used by SAA7146 card */ - unsigned short id; - struct i2c_bus i2c; - 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 */ - struct saa7146_window win; - unsigned char *saa7146_mem; /* pointer to mapped IO memory */ - struct device_open open_data[MAX_OPENS]; -#define MAX_MARKS 16 - /* for a/v sync */ - int endmark[MAX_MARKS], endmarkhead, endmarktail; - u32 *dmaRPS1, *pageRPS1, *dmaRPS2, *pageRPS2, *dmavid1, *dmavid2, - *dmavid3, *dmaa1in, *dmaa1out, *dmaa2in, *dmaa2out, - *pagedebi, *pagevid1, *pagevid2, *pagevid3, *pagea1in, - *pagea1out, *pagea2in, *pagea2out; - wait_queue_head_t i2cq, debiq, audq, vidq; - u8 *vidbuf, *audbuf, *osdbuf, *dmadebi; - int audhead, vidhead, osdhead, audtail, vidtail, osdtail; - spinlock_t lock; /* the device lock */ -}; -#endif - -#ifdef _ALPHA_SAA7146 -#define saawrite(dat,adr) writel((dat),(char *) (saa->saa7146_adr+(adr))) -#define saaread(adr) readl(saa->saa7146_adr+(adr)) -#else -#define saawrite(dat,adr) writel((dat), (char *) (saa->saa7146_mem+(adr))) -#define saaread(adr) readl(saa->saa7146_mem+(adr)) -#endif - -#define saaand(dat,adr) saawrite((dat) & saaread(adr), adr) -#define saaor(dat,adr) saawrite((dat) | saaread(adr), adr) -#define saaaor(dat,mask,adr) saawrite((dat) | ((mask) & saaread(adr)), adr) - -/* bitmask of attached hardware found */ -#define SAA7146_UNKNOWN 0x00000000 -#define SAA7146_SAA7111 0x00000001 -#define SAA7146_SAA7121 0x00000002 -#define SAA7146_IBMMPEG 0x00000004 - -#endif diff --git a/drivers/char/saa7146reg.h b/drivers/char/saa7146reg.h deleted file mode 100644 index 6cc910f50..000000000 --- a/drivers/char/saa7146reg.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - saa7146.h - definitions philips saa7146 based cards - Copyright (C) 1999 Nathan Laredo (laredo@gnu.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. -*/ - -#ifndef __SAA7146_REG__ -#define __SAA7146_REG__ -#define SAA7146_BASE_ODD1 0x00 -#define SAA7146_BASE_EVEN1 0x04 -#define SAA7146_PROT_ADDR1 0x08 -#define SAA7146_PITCH1 0x0c -#define SAA7146_PAGE1 0x10 -#define SAA7146_NUM_LINE_BYTE1 0x14 -#define SAA7146_BASE_ODD2 0x18 -#define SAA7146_BASE_EVEN2 0x1c -#define SAA7146_PROT_ADDR2 0x20 -#define SAA7146_PITCH2 0x24 -#define SAA7146_PAGE2 0x28 -#define SAA7146_NUM_LINE_BYTE2 0x2c -#define SAA7146_BASE_ODD3 0x30 -#define SAA7146_BASE_EVEN3 0x34 -#define SAA7146_PROT_ADDR3 0x38 -#define SAA7146_PITCH3 0x3c -#define SAA7146_PAGE3 0x40 -#define SAA7146_NUM_LINE_BYTE3 0x44 -#define SAA7146_PCI_BT_V1 0x48 -#define SAA7146_PCI_BT_V2 0x49 -#define SAA7146_PCI_BT_V3 0x4a -#define SAA7146_PCI_BT_DEBI 0x4b -#define SAA7146_PCI_BT_A 0x4c -#define SAA7146_DD1_INIT 0x50 -#define SAA7146_DD1_STREAM_B 0x54 -#define SAA7146_DD1_STREAM_A 0x56 -#define SAA7146_BRS_CTRL 0x58 -#define SAA7146_HPS_CTRL 0x5c -#define SAA7146_HPS_V_SCALE 0x60 -#define SAA7146_HPS_V_GAIN 0x64 -#define SAA7146_HPS_H_PRESCALE 0x68 -#define SAA7146_HPS_H_SCALE 0x6c -#define SAA7146_BCS_CTRL 0x70 -#define SAA7146_CHROMA_KEY_RANGE 0x74 -#define SAA7146_CLIP_FORMAT_CTRL 0x78 -#define SAA7146_DEBI_CONFIG 0x7c -#define SAA7146_DEBI_COMMAND 0x80 -#define SAA7146_DEBI_PAGE 0x84 -#define SAA7146_DEBI_AD 0x88 -#define SAA7146_I2C_TRANSFER 0x8c -#define SAA7146_I2C_STATUS 0x90 -#define SAA7146_BASE_A1_IN 0x94 -#define SAA7146_PROT_A1_IN 0x98 -#define SAA7146_PAGE_A1_IN 0x9C -#define SAA7146_BASE_A1_OUT 0xa0 -#define SAA7146_PROT_A1_OUT 0xa4 -#define SAA7146_PAGE_A1_OUT 0xa8 -#define SAA7146_BASE_A2_IN 0xac -#define SAA7146_PROT_A2_IN 0xb0 -#define SAA7146_PAGE_A2_IN 0xb4 -#define SAA7146_BASE_A2_OUT 0xb8 -#define SAA7146_PROT_A2_OUT 0xbc -#define SAA7146_PAGE_A2_OUT 0xc0 -#define SAA7146_RPS_PAGE0 0xc4 -#define SAA7146_RPS_PAGE1 0xc8 -#define SAA7146_RPS_THRESH0 0xcc -#define SAA7146_RPS_THRESH1 0xd0 -#define SAA7146_RPS_TOV0 0xd4 -#define SAA7146_RPS_TOV1 0xd8 -#define SAA7146_IER 0xdc -#define SAA7146_GPIO_CTRL 0xe0 -#define SAA7146_EC1SSR 0xe4 -#define SAA7146_EC2SSR 0xe8 -#define SAA7146_ECT1R 0xec -#define SAA7146_ECT2R 0xf0 -#define SAA7146_ACON1 0xf4 -#define SAA7146_ACON2 0xf8 -#define SAA7146_MC1 0xfc -#define SAA7146_MC2 0x100 -#define SAA7146_RPS_ADDR0 0x104 -#define SAA7146_RPS_ADDR1 0x108 -#define SAA7146_ISR 0x10c -#define SAA7146_PSR 0x110 -#define SAA7146_SSR 0x114 -#define SAA7146_EC1R 0x118 -#define SAA7146_EC2R 0x11c -#define SAA7146_VDP1 0x120 -#define SAA7146_VDP2 0x124 -#define SAA7146_VDP3 0x128 -#define SAA7146_ADP1 0x12c -#define SAA7146_ADP2 0x130 -#define SAA7146_ADP3 0x134 -#define SAA7146_ADP4 0x138 -#define SAA7146_DDP 0x13c -#define SAA7146_LEVEL_REP 0x140 -#define SAA7146_FB_BUFFER1 0x144 -#define SAA7146_FB_BUFFER2 0x148 -#define SAA7146_A_TIME_SLOT1 0x180 -#define SAA7146_A_TIME_SLOT2 0x1C0 - -/* bitfield defines */ -#define MASK_31 0x80000000 -#define MASK_30 0x40000000 -#define MASK_29 0x20000000 -#define MASK_28 0x10000000 -#define MASK_27 0x08000000 -#define MASK_26 0x04000000 -#define MASK_25 0x02000000 -#define MASK_24 0x01000000 -#define MASK_23 0x00800000 -#define MASK_22 0x00400000 -#define MASK_21 0x00200000 -#define MASK_20 0x00100000 -#define MASK_19 0x00080000 -#define MASK_18 0x00040000 -#define MASK_17 0x00020000 -#define MASK_16 0x00010000 -#define MASK_15 0x00008000 -#define MASK_14 0x00004000 -#define MASK_13 0x00002000 -#define MASK_12 0x00001000 -#define MASK_11 0x00000800 -#define MASK_10 0x00000400 -#define MASK_09 0x00000200 -#define MASK_08 0x00000100 -#define MASK_07 0x00000080 -#define MASK_06 0x00000040 -#define MASK_05 0x00000020 -#define MASK_04 0x00000010 -#define MASK_03 0x00000008 -#define MASK_02 0x00000004 -#define MASK_01 0x00000002 -#define MASK_00 0x00000001 -#define MASK_B0 0x000000ff -#define MASK_B1 0x0000ff00 -#define MASK_B2 0x00ff0000 -#define MASK_B3 0xff000000 -#define MASK_W0 0x0000ffff -#define MASK_W1 0xffff0000 -#define MASK_PA 0xfffffffc -#define MASK_PR 0xfffffffe -#define MASK_ER 0xffffffff -#define MASK_NONE 0x00000000 - -#define SAA7146_PAGE_MAP_EN MASK_11 -/* main control register 1 */ -#define SAA7146_MC1_MRST_N MASK_15 -#define SAA7146_MC1_ERPS1 MASK_13 -#define SAA7146_MC1_ERPS0 MASK_12 -#define SAA7146_MC1_EDP MASK_11 -#define SAA7146_MC1_EVP MASK_10 -#define SAA7146_MC1_EAP MASK_09 -#define SAA7146_MC1_EI2C MASK_08 -#define SAA7146_MC1_TR_E_DEBI MASK_07 -#define SAA7146_MC1_TR_E_1 MASK_06 -#define SAA7146_MC1_TR_E_2 MASK_05 -#define SAA7146_MC1_TR_E_3 MASK_04 -#define SAA7146_MC1_TR_E_A2_OUT MASK_03 -#define SAA7146_MC1_TR_E_A2_IN MASK_02 -#define SAA7146_MC1_TR_E_A1_OUT MASK_01 -#define SAA7146_MC1_TR_E_A1_IN MASK_00 -/* main control register 2 */ -#define SAA7146_MC2_RPS_SIG4 MASK_15 -#define SAA7146_MC2_RPS_SIG3 MASK_14 -#define SAA7146_MC2_RPS_SIG2 MASK_13 -#define SAA7146_MC2_RPS_SIG1 MASK_12 -#define SAA7146_MC2_RPS_SIG0 MASK_11 -#define SAA7146_MC2_UPLD_D1_B MASK_10 -#define SAA7146_MC2_UPLD_D1_A MASK_09 -#define SAA7146_MC2_UPLD_BRS MASK_08 -#define SAA7146_MC2_UPLD_HPS_H MASK_06 -#define SAA7146_MC2_UPLD_HPS_V MASK_05 -#define SAA7146_MC2_UPLD_DMA3 MASK_04 -#define SAA7146_MC2_UPLD_DMA2 MASK_03 -#define SAA7146_MC2_UPLD_DMA1 MASK_02 -#define SAA7146_MC2_UPLD_DEBI MASK_01 -#define SAA7146_MC2_UPLD_I2C MASK_00 -/* Primary Status Register and Interrupt Enable/Status Registers */ -#define SAA7146_PSR_PPEF MASK_31 -#define SAA7146_PSR_PABO MASK_30 -#define SAA7146_PSR_PPED MASK_29 -#define SAA7146_PSR_RPS_I1 MASK_28 -#define SAA7146_PSR_RPS_I0 MASK_27 -#define SAA7146_PSR_RPS_LATE1 MASK_26 -#define SAA7146_PSR_RPS_LATE0 MASK_25 -#define SAA7146_PSR_RPS_E1 MASK_24 -#define SAA7146_PSR_RPS_E0 MASK_23 -#define SAA7146_PSR_RPS_TO1 MASK_22 -#define SAA7146_PSR_RPS_TO0 MASK_21 -#define SAA7146_PSR_UPLD MASK_20 -#define SAA7146_PSR_DEBI_S MASK_19 -#define SAA7146_PSR_DEBI_E MASK_18 -#define SAA7146_PSR_I2C_S MASK_17 -#define SAA7146_PSR_I2C_E MASK_16 -#define SAA7146_PSR_A2_IN MASK_15 -#define SAA7146_PSR_A2_OUT MASK_14 -#define SAA7146_PSR_A1_IN MASK_13 -#define SAA7146_PSR_A1_OUT MASK_12 -#define SAA7146_PSR_AFOU MASK_11 -#define SAA7146_PSR_V_PE MASK_10 -#define SAA7146_PSR_VFOU MASK_09 -#define SAA7146_PSR_FIDA MASK_08 -#define SAA7146_PSR_FIDB MASK_07 -#define SAA7146_PSR_PIN3 MASK_06 -#define SAA7146_PSR_PIN2 MASK_05 -#define SAA7146_PSR_PIN1 MASK_04 -#define SAA7146_PSR_PIN0 MASK_03 -#define SAA7146_PSR_ECS MASK_02 -#define SAA7146_PSR_EC3S MASK_01 -#define SAA7146_PSR_EC0S MASK_00 -/* Secondary Status Register */ -#define SAA7146_SSR_PRQ MASK_31 -#define SAA7146_SSR_PMA MASK_30 -#define SAA7146_SSR_RPS_RE1 MASK_29 -#define SAA7146_SSR_RPS_PE1 MASK_28 -#define SAA7146_SSR_RPS_A1 MASK_27 -#define SAA7146_SSR_RPS_RE0 MASK_26 -#define SAA7146_SSR_RPS_PE0 MASK_25 -#define SAA7146_SSR_RPS_A0 MASK_24 -#define SAA7146_SSR_DEBI_TO MASK_23 -#define SAA7146_SSR_DEBI_EF MASK_22 -#define SAA7146_SSR_I2C_EA MASK_21 -#define SAA7146_SSR_I2C_EW MASK_20 -#define SAA7146_SSR_I2C_ER MASK_19 -#define SAA7146_SSR_I2C_EL MASK_18 -#define SAA7146_SSR_I2C_EF MASK_17 -#define SAA7146_SSR_V3P MASK_16 -#define SAA7146_SSR_V2P MASK_15 -#define SAA7146_SSR_V1P MASK_14 -#define SAA7146_SSR_VF3 MASK_13 -#define SAA7146_SSR_VF2 MASK_12 -#define SAA7146_SSR_VF1 MASK_11 -#define SAA7146_SSR_AF2_IN MASK_10 -#define SAA7146_SSR_AF2_OUT MASK_09 -#define SAA7146_SSR_AF1_IN MASK_08 -#define SAA7146_SSR_AF1_OUT MASK_07 -#define SAA7146_SSR_VGT MASK_05 -#define SAA7146_SSR_LNQG MASK_04 -#define SAA7146_SSR_EC5S MASK_03 -#define SAA7146_SSR_EC4S MASK_02 -#define SAA7146_SSR_EC2S MASK_01 -#define SAA7146_SSR_EC1S MASK_00 -/* I2C status register */ -#define SAA7146_I2C_ABORT MASK_07 -#define SAA7146_I2C_SPERR MASK_06 -#define SAA7146_I2C_APERR MASK_05 -#define SAA7146_I2C_DTERR MASK_04 -#define SAA7146_I2C_DRERR MASK_03 -#define SAA7146_I2C_AL MASK_02 -#define SAA7146_I2C_ERR MASK_01 -#define SAA7146_I2C_BUSY MASK_00 -/* output formats */ -#define SAA7146_YUV422 0 -#define SAA7146_RGB16 0 -#define SAA7146_YUV444 1 -#define SAA7146_RGB24 1 -#define SAA7146_ARGB32 2 -#define SAA7146_YUV411 3 -#define SAA7146_ARGB15 3 -#define SAA7146_YUV2 4 -#define SAA7146_RGAB15 4 -#define SAA7146_Y8 6 -#define SAA7146_YUV8 7 -#define SAA7146_RGB8 7 -#define SAA7146_YUV444p 8 -#define SAA7146_YUV422p 9 -#define SAA7146_YUV420p 10 -#define SAA7146_YUV1620 11 -#define SAA7146_Y1 13 -#define SAA7146_Y2 14 -#define SAA7146_YUV1 15 -#endif diff --git a/drivers/char/saa7185.c b/drivers/char/saa7185.c deleted file mode 100644 index c30e6353b..000000000 --- a/drivers/char/saa7185.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - saa7185 - Philips SAA7185B video encoder driver version 0.0.3 - - Copyright (C) 1998 Dave Perks - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define DEBUG(x) x /* Debug driver */ - -/* ----------------------------------------------------------------------- */ - -struct saa7185 { - struct i2c_bus *bus; - int addr; - unsigned char reg[128]; - - int norm; - int enable; - int bright; - int contrast; - int hue; - int sat; -}; - -#define I2C_SAA7185 0x88 - -#define I2C_DELAY 10 - -/* ----------------------------------------------------------------------- */ - -static int saa7185_write(struct saa7185 *dev, unsigned char subaddr, unsigned char data) -{ - int ack; - - LOCK_I2C_BUS(dev->bus); - - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, data, I2C_DELAY); - dev->reg[subaddr] = data; - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - return ack; -} - -static int saa7185_write_block(struct saa7185 *dev, unsigned const char *data, unsigned int len) -{ - int ack = 0; - unsigned subaddr; - - while (len > 1) { - LOCK_I2C_BUS(dev->bus); - i2c_start(dev->bus); - i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY); - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - while (len > 1 && *data == ++subaddr) { - data++; - ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); - len -= 2; - } - i2c_stop(dev->bus); - UNLOCK_I2C_BUS(dev->bus); - } - return ack; -} - -/* ----------------------------------------------------------------------- */ - -static const unsigned char init_common[] = -{ - 0x3a, 0x0f, /* CBENB=0, V656=0, VY2C=1, YUV2C=1, MY2C=1, MUV2C=1 */ - - 0x42, 0x6b, /* OVLY0=107 */ - 0x43, 0x00, /* OVLU0=0 white */ - 0x44, 0x00, /* OVLV0=0 */ - 0x45, 0x22, /* OVLY1=34 */ - 0x46, 0xac, /* OVLU1=172 yellow */ - 0x47, 0x0e, /* OVLV1=14 */ - 0x48, 0x03, /* OVLY2=3 */ - 0x49, 0x1d, /* OVLU2=29 cyan */ - 0x4a, 0xac, /* OVLV2=172 */ - 0x4b, 0xf0, /* OVLY3=240 */ - 0x4c, 0xc8, /* OVLU3=200 green */ - 0x4d, 0xb9, /* OVLV3=185 */ - 0x4e, 0xd4, /* OVLY4=212 */ - 0x4f, 0x38, /* OVLU4=56 magenta */ - 0x50, 0x47, /* OVLV4=71 */ - 0x51, 0xc1, /* OVLY5=193 */ - 0x52, 0xe3, /* OVLU5=227 red */ - 0x53, 0x54, /* OVLV5=84 */ - 0x54, 0xa3, /* OVLY6=163 */ - 0x55, 0x54, /* OVLU6=84 blue */ - 0x56, 0xf2, /* OVLV6=242 */ - 0x57, 0x90, /* OVLY7=144 */ - 0x58, 0x00, /* OVLU7=0 black */ - 0x59, 0x00, /* OVLV7=0 */ - - 0x5a, 0x00, /* CHPS=0 */ - 0x5b, 0x76, /* GAINU=118 */ - 0x5c, 0xa5, /* GAINV=165 */ - 0x5d, 0x3c, /* BLCKL=60 */ - 0x5e, 0x3a, /* BLNNL=58 */ - 0x5f, 0x3a, /* CCRS=0, BLNVB=58 */ - 0x60, 0x00, /* NULL */ - -/* 0x61 - 0x66 set according to norm */ - - 0x67, 0x00, /* 0 : caption 1st byte odd field */ - 0x68, 0x00, /* 0 : caption 2nd byte odd field */ - 0x69, 0x00, /* 0 : caption 1st byte even field */ - 0x6a, 0x00, /* 0 : caption 2nd byte even field */ - - 0x6b, 0x91, /* MODIN=2, PCREF=0, SCCLN=17 */ - 0x6c, 0x20, /* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0, CBLF=0, ORCV2=0, PRCV2=0 */ - 0x6d, 0x00, /* SRCM1=0, CCEN=0 */ - - 0x6e, 0x0e, /* HTRIG=0x00e, approx. centered, at least for PAL */ - 0x6f, 0x00, /* HTRIG upper bits */ - 0x70, 0x20, /* PHRES=0, SBLN=1, VTRIG=0 */ - -/* The following should not be needed */ - - 0x71, 0x15, /* BMRQ=0x115 */ - 0x72, 0x90, /* EMRQ=0x690 */ - 0x73, 0x61, /* EMRQ=0x690, BMRQ=0x115 */ - 0x74, 0x00, /* NULL */ - 0x75, 0x00, /* NULL */ - 0x76, 0x00, /* NULL */ - 0x77, 0x15, /* BRCV=0x115 */ - 0x78, 0x90, /* ERCV=0x690 */ - 0x79, 0x61, /* ERCV=0x690, BRCV=0x115 */ - -/* Field length controls */ - - 0x7a, 0x70, /* FLC=0 */ - -/* The following should not be needed if SBLN = 1 */ - - 0x7b, 0x16, /* FAL=22 */ - 0x7c, 0x35, /* LAL=244 */ - 0x7d, 0x20, /* LAL=244, FAL=22 */ -}; - -static const unsigned char init_pal[] = -{ - 0x61, 0x1e, /* FISE=0, PAL=1, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */ - 0x62, 0xc8, /* DECTYP=1, BSTA=72 */ - 0x63, 0xcb, /* FSC0 */ - 0x64, 0x8a, /* FSC1 */ - 0x65, 0x09, /* FSC2 */ - 0x66, 0x2a, /* FSC3 */ -}; - -static const unsigned char init_ntsc[] = -{ - 0x61, 0x1d, /* FISE=1, PAL=0, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */ - 0x62, 0xe6, /* DECTYP=1, BSTA=102 */ - 0x63, 0x1f, /* FSC0 */ - 0x64, 0x7c, /* FSC1 */ - 0x65, 0xf0, /* FSC2 */ - 0x66, 0x21, /* FSC3 */ -}; - -static int saa7185_attach(struct i2c_device *device) -{ - int i; - struct saa7185 *encoder; - - device->data = encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL); - if (encoder == NULL) { - return -ENOMEM; - } - MOD_INC_USE_COUNT; - - memset(encoder, 0, sizeof(struct saa7185)); - strcpy(device->name, "saa7185"); - encoder->bus = device->bus; - encoder->addr = device->addr; - encoder->norm = VIDEO_MODE_NTSC; - encoder->enable = 1; - - i = saa7185_write_block(encoder, init_common, sizeof(init_common)); - if (i >= 0) { - i = saa7185_write_block(encoder, init_ntsc, sizeof(init_ntsc)); - } - if (i < 0) { - printk(KERN_ERR "%s_attach: init error %d\n", device->name, i); - } - return 0; -} - - -static int saa7185_detach(struct i2c_device *device) -{ - kfree(device->data); - MOD_DEC_USE_COUNT; - return 0; -} - -static int saa7185_command(struct i2c_device *device, unsigned int cmd, void *arg) -{ - struct saa7185 *encoder = device->data; - - switch (cmd) { - - case ENCODER_GET_CAPABILITIES: - { - struct video_encoder_capability *cap = arg; - - cap->flags - = VIDEO_ENCODER_PAL - | VIDEO_ENCODER_NTSC - | VIDEO_ENCODER_SECAM - | VIDEO_ENCODER_CCIR; - cap->inputs = 1; - cap->outputs = 1; - } - break; - - case ENCODER_SET_NORM: - { - int *iarg = arg; - - switch (*iarg) { - - case VIDEO_MODE_NTSC: - saa7185_write_block(encoder, init_ntsc, sizeof(init_ntsc)); - break; - - case VIDEO_MODE_PAL: - saa7185_write_block(encoder, init_pal, sizeof(init_pal)); - break; - - case VIDEO_MODE_SECAM: - default: - return -EINVAL; - - } - encoder->norm = *iarg; - } - break; - - case ENCODER_SET_INPUT: - { - int *iarg = arg; - -#if 0 - /* not much choice of inputs */ - if (*iarg != 0) { - return -EINVAL; - } -#else - /* RJ: *iarg = 0: input is from SA7111 - *iarg = 1: input is from ZR36060 */ - - switch (*iarg) { - - case 0: - /* Switch RTCE to 1 */ - saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); - break; - - case 1: - /* Switch RTCE to 0 */ - saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); - break; - - default: - return -EINVAL; - - } -#endif - } - break; - - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - } - break; - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; - saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xbf) | (encoder->enable ? 0x00 : 0x40)); - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -struct i2c_driver i2c_driver_saa7185 = -{ - "saa7185", /* name */ - I2C_DRIVERID_VIDEOENCODER, /* ID */ - I2C_SAA7185, I2C_SAA7185 + 1, - - saa7185_attach, - saa7185_detach, - saa7185_command -}; - -EXPORT_NO_SYMBOLS; - -#ifdef MODULE -int init_module(void) -#else -int saa7185_init(void) -#endif -{ - return i2c_register_driver(&i2c_driver_saa7185); -} - - - -#ifdef MODULE - -void cleanup_module(void) -{ - i2c_unregister_driver(&i2c_driver_saa7185); -} - -#endif diff --git a/drivers/char/saa7196.h b/drivers/char/saa7196.h deleted file mode 100644 index f92f21cfb..000000000 --- a/drivers/char/saa7196.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - Definitions for the Philips SAA7196 digital video decoder, - scaler, and clock generator circuit (DESCpro), as used in - the PlanB video input of the Powermac 7x00/8x00 series. - - Copyright (C) 1998 Michel Lanners (mlan@cpu.lu) - - The register defines are shamelessly copied from the meteor - driver out of NetBSD (with permission), - and are copyrighted (c) 1995 Mark Tinguely and Jim Lowe - (Thanks !) - - Additional debugging and coding by Takashi Oe (toe@unlinfo.unl.edu) - - The default values used for PlanB are my mistakes. -*/ - -/* $Id: saa7196.h,v 1.5 1999/03/26 23:28:47 mlan Exp $ */ - -#ifndef _SAA7196_H_ -#define _SAA7196_H_ - -#define SAA7196_NUMREGS 0x31 /* Number of registers (used)*/ -#define NUM_SUPPORTED_NORM 3 /* Number of supported norms by PlanB */ - -/* Decoder part: */ -#define SAA7196_IDEL 0x00 /* Increment delay */ -#define SAA7196_HSB5 0x01 /* H-sync begin; 50 hz */ -#define SAA7196_HSS5 0x02 /* H-sync stop; 50 hz */ -#define SAA7196_HCB5 0x03 /* H-clamp begin; 50 hz */ -#define SAA7196_HCS5 0x04 /* H-clamp stop; 50 hz */ -#define SAA7196_HSP5 0x05 /* H-sync after PHI1; 50 hz */ -#define SAA7196_LUMC 0x06 /* Luminance control */ -#define SAA7196_HUEC 0x07 /* Hue control */ -#define SAA7196_CKTQ 0x08 /* Colour Killer Threshold QAM (PAL, NTSC) */ -#define SAA7196_CKTS 0x09 /* Colour Killer Threshold SECAM */ -#define SAA7196_PALS 0x0a /* PAL switch sensitivity */ -#define SAA7196_SECAMS 0x0b /* SECAM switch sensitivity */ -#define SAA7196_CGAINC 0x0c /* Chroma gain control */ -#define SAA7196_STDC 0x0d /* Standard/Mode control */ -#define SAA7196_IOCC 0x0e /* I/O and Clock Control */ -#define SAA7196_CTRL1 0x0f /* Control #1 */ -#define SAA7196_CTRL2 0x10 /* Control #2 */ -#define SAA7196_CGAINR 0x11 /* Chroma Gain Reference */ -#define SAA7196_CSAT 0x12 /* Chroma Saturation */ -#define SAA7196_CONT 0x13 /* Luminance Contrast */ -#define SAA7196_HSB6 0x14 /* H-sync begin; 60 hz */ -#define SAA7196_HSS6 0x15 /* H-sync stop; 60 hz */ -#define SAA7196_HCB6 0x16 /* H-clamp begin; 60 hz */ -#define SAA7196_HCS6 0x17 /* H-clamp stop; 60 hz */ -#define SAA7196_HSP6 0x18 /* H-sync after PHI1; 60 hz */ -#define SAA7196_BRIG 0x19 /* Luminance Brightness */ - -/* Scaler part: */ -#define SAA7196_FMTS 0x20 /* Formats and sequence */ -#define SAA7196_OUTPIX 0x21 /* Output data pixel/line */ -#define SAA7196_INPIX 0x22 /* Input data pixel/line */ -#define SAA7196_HWS 0x23 /* Horiz. window start */ -#define SAA7196_HFILT 0x24 /* Horiz. filter */ -#define SAA7196_OUTLINE 0x25 /* Output data lines/field */ -#define SAA7196_INLINE 0x26 /* Input data lines/field */ -#define SAA7196_VWS 0x27 /* Vertical window start */ -#define SAA7196_VYP 0x28 /* AFS/vertical Y processing */ -#define SAA7196_VBS 0x29 /* Vertical Bypass start */ -#define SAA7196_VBCNT 0x2a /* Vertical Bypass count */ -#define SAA7196_VBP 0x2b /* veritcal Bypass Polarity */ -#define SAA7196_VLOW 0x2c /* Colour-keying lower V limit */ -#define SAA7196_VHIGH 0x2d /* Colour-keying upper V limit */ -#define SAA7196_ULOW 0x2e /* Colour-keying lower U limit */ -#define SAA7196_UHIGH 0x2f /* Colour-keying upper U limit */ -#define SAA7196_DPATH 0x30 /* Data path setting */ - -/* Initialization default values: */ - -unsigned char saa_regs[NUM_SUPPORTED_NORM][SAA7196_NUMREGS] = { - -/* PAL, 768x576 (no scaling), composite video-in */ -/* Decoder: */ - { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x63, 0xff, - 0xfe, 0xf0, 0xfe, 0xe0, 0x20, 0x06, 0x3b, 0x98, - 0x00, 0x59, 0x41, 0x45, 0x34, 0x0a, 0xf4, 0xd2, - 0xe9, 0xa2, -/* Padding */ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* Scaler: */ - 0x72, 0x80, 0x00, 0x03, 0x8d, 0x20, 0x20, 0x12, - 0xa5, 0x12, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, - 0x87 }, - -/* NTSC, 640x480? (no scaling), composite video-in */ -/* Decoder: */ - { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x50, 0x00, - 0xf8, 0xf0, 0xfe, 0xe0, 0x00, 0x06, 0x3b, 0x98, - 0x00, 0x2c, 0x3d, 0x40, 0x34, 0x0a, 0xf4, 0xd2, - 0xe9, 0x98, -/* Padding */ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* Scaler: */ - 0x72, 0x80, 0x80, 0x03, 0x89, 0xf0, 0xf0, 0x0d, - 0xa0, 0x0d, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, - 0x87 }, - -/* SECAM, 768x576 (no scaling), composite video-in */ -/* Decoder: */ - { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x63, 0xff, - 0xfe, 0xf0, 0xfe, 0xe0, 0x20, 0x07, 0x3b, 0x98, - 0x00, 0x59, 0x41, 0x45, 0x34, 0x0a, 0xf4, 0xd2, - 0xe9, 0xa2, -/* Padding */ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* Scaler: */ - 0x72, 0x80, 0x00, 0x03, 0x8d, 0x20, 0x20, 0x12, - 0xa5, 0x12, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, - 0x87 } - }; - -#endif /* _SAA7196_H_ */ diff --git a/drivers/char/scan_keyb.c b/drivers/char/scan_keyb.c index 1936e0b6e..f2435e9ec 100644 --- a/drivers/char/scan_keyb.c +++ b/drivers/char/scan_keyb.c @@ -82,18 +82,21 @@ int register_scan_keyboard(void (*scan)(unsigned char *buffer), { struct scan_keyboard *kbd; - if((kbd=kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL))==NULL) + kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL); + if (kbd == NULL) goto error_out; kbd->scan=scan; kbd->table=table; kbd->length=length; - kbd->s0=kbd->s1=NULL; - if((kbd->s0=kmalloc(length, GFP_KERNEL))==NULL) - goto error_mem_free; - if((kbd->s1=kmalloc(length, GFP_KERNEL))==NULL) - goto error_mem_free; + kbd->s0 = kmalloc(length, GFP_KERNEL); + if (kbd->s0 == NULL) + goto error_free_kbd; + + kbd->s1 = kmalloc(length, GFP_KERNEL); + if (kbd->s1 == NULL) + goto error_free_s0; kbd->scan(kbd->s0); kbd->scan(kbd->s1); @@ -103,11 +106,10 @@ int register_scan_keyboard(void (*scan)(unsigned char *buffer), return 0; - error_mem_free: - if(kbd->s0) - kfree(kbd->s0); - if(kbd->s1) - kfree(kbd->s1); + error_free_s0: + kfree(kbd->s0); + + error_free_kbd: kfree(kbd); error_out: diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 8ec857e06..f23f911ad 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -51,13 +51,16 @@ * * 7/00: Support Timedia/Sunix/Exsys PCI cards * + * 7/00: fix some returns on failure not using MOD_DEC_USE_COUNT. + * Arnaldo Carvalho de Melo + * * This module exports the following rs232 io functions: * * int rs_init(void); */ -static char *serial_version = "5.01"; -static char *serial_revdate = "2000-05-29"; +static char *serial_version = "5.02"; +static char *serial_revdate = "2000-08-09"; /* * Serial driver configuration section. Here are the various options: @@ -142,6 +145,10 @@ static char *serial_revdate = "2000-05-29"; #endif #endif +#ifdef MODULE +#undef CONFIG_SERIAL_CONSOLE +#endif + #define CONFIG_SERIAL_RSA #define RS_STROBE_TIME (10*HZ) @@ -260,8 +267,9 @@ static struct rs_multiport_struct rs_multiport[NR_IRQS]; static int IRQ_timeout[NR_IRQS]; #ifdef CONFIG_SERIAL_CONSOLE static struct console sercons; +static int lsr_break_flag = 0; #endif -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) static unsigned long break_pressed; /* break, really ... */ #endif @@ -281,7 +289,7 @@ static struct serial_uart_config uart_config[] = { { "16550", 1, 0 }, { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, { "cirrus", 1, 0 }, /* usurped by cyclades.c */ - { "ST16650", 1, UART_CLEAR_FIFO |UART_STARTECH }, + { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, @@ -302,7 +310,9 @@ static int probe_rsa[PORT_RSA_MAX]; static int force_rsa[PORT_RSA_MAX]; MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); +MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); +MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA"); #endif /* CONFIG_SERIAL_RSA */ static struct serial_state rs_table[RS_TABLE_SIZE] = { @@ -313,7 +323,7 @@ static struct serial_state rs_table[RS_TABLE_SIZE] = { #if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)) #define NR_PCI_BOARDS 8 -/* We don't unregister PCI boards right now */ + static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS]; static int serial_pci_board_idx = 0; @@ -573,6 +583,23 @@ static _INLINE_ void receive_chars(struct async_struct *info, if (*status & UART_LSR_BI) { *status &= ~(UART_LSR_FE | UART_LSR_PE); icount->brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) + if (info->line == sercons.index) { + if (!break_pressed) { + break_pressed = jiffies; + goto ignore_char; + } + break_pressed = 0; + } +#endif + if (info->flags & ASYNC_SAK) + do_SAK(tty); } else if (*status & UART_LSR_PE) icount->parity++; else if (*status & UART_LSR_FE) @@ -591,23 +618,19 @@ static _INLINE_ void receive_chars(struct async_struct *info, goto ignore_char; } *status &= info->read_status_mask; - + +#ifdef CONFIG_SERIAL_CONSOLE + if (info->line == sercons.index) { + /* Recover the break flag from console xmit */ + *status |= lsr_break_flag; + lsr_break_flag = 0; + } +#endif if (*status & (UART_LSR_BI)) { #ifdef SERIAL_DEBUG_INTR printk("handling break...."); -#endif -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) - if (info->line == sercons.index) { - if (!break_pressed) { - break_pressed = jiffies; - goto ignore_char; - } - break_pressed = 0; - } #endif *tty->flip.flag_buf_ptr = TTY_BREAK; - if (info->flags & ASYNC_SAK) - do_SAK(tty); } else if (*status & UART_LSR_PE) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (*status & UART_LSR_FE) @@ -626,7 +649,7 @@ static _INLINE_ void receive_chars(struct async_struct *info, goto ignore_char; } } -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) if (break_pressed && info->line == sercons.index) { if (ch != 0 && time_before(jiffies, break_pressed + HZ*5)) { @@ -1068,19 +1091,15 @@ static void rs_timer(unsigned long dummy) mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); if (IRQ_ports[0]) { - unsigned long next; save_flags(flags); cli(); #ifdef CONFIG_SERIAL_SHARE_IRQ rs_interrupt(0, NULL, NULL); #else rs_interrupt_single(0, NULL, NULL); #endif - - next = jiffies + IRQ_timeout[0] - 2; - if (next < jiffies + 1) - next = jiffies + 1; - mod_timer(&serial_timer, next); restore_flags(flags); + + mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); } } @@ -1115,7 +1134,7 @@ static void figure_IRQ_timeout(int irq) } if (!irq) timeout = timeout / 2; - IRQ_timeout[irq] = timeout ? timeout : 1; + IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1; } #ifdef CONFIG_SERIAL_RSA @@ -2081,7 +2100,7 @@ static int set_serial_info(struct async_struct * info, new_serial.irq = irq_cannonicalize(new_serial.irq); - if ((new_serial.irq >= NR_IRQS) || + if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || (new_serial.type == PORT_STARTECH)) { @@ -2314,7 +2333,7 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd, static int do_autoconfig(struct async_struct * info) { - int retval; + int irq, retval; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -2327,8 +2346,11 @@ static int do_autoconfig(struct async_struct * info) autoconfig(info->state); if ((info->state->flags & ASYNC_AUTO_IRQ) && (info->state->port != 0) && - (info->state->type != PORT_UNKNOWN)) - info->state->irq = detect_uart_irq(info->state); + (info->state->type != PORT_UNKNOWN)) { + irq = detect_uart_irq(info->state); + if (irq > 0) + info->state->irq = irq; + } retval = startup(info); if (retval) @@ -3115,8 +3137,10 @@ static int rs_open(struct tty_struct *tty, struct file * filp) } tty->driver_data = info; info->tty = tty; - if (serial_paranoia_check(info, tty->device, "rs_open")) + if (serial_paranoia_check(info, tty->device, "rs_open")) { + MOD_DEC_USE_COUNT; return -ENODEV; + } #ifdef SERIAL_DEBUG_OPEN printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, @@ -3129,6 +3153,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); if (!page) { + MOD_DEC_USE_COUNT; return -ENOMEM; } if (tmp_buf) @@ -3144,6 +3169,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) (info->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait); + MOD_DEC_USE_COUNT; #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -3157,6 +3183,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) */ retval = startup(info); if (retval) { + MOD_DEC_USE_COUNT; return retval; } @@ -3166,6 +3193,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp) printk("rs_open returning after block_til_ready with %d\n", retval); #endif + MOD_DEC_USE_COUNT; return retval; } @@ -3490,6 +3518,7 @@ static void autoconfig_startech_uarts(struct async_struct *info, * (Exoray@isys.ca) claims that it's needed for 952 * dual UART's (which are not recommended for new designs). */ + info->ACR = 0; serial_out(info, UART_LCR, 0xBF); serial_out(info, UART_EFR, 0x10); serial_out(info, UART_LCR, 0x00); @@ -3808,10 +3837,11 @@ static _INLINE_ int get_pci_port(struct pci_dev *dev, if (idx >= max_port) return 1; } - + offset = board->first_uart_offset; /* Timedia/SUNIX uses a mixture of BARs and offsets */ + /* Ugh, this is ugly as all hell --- TYT */ if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */ switch(idx) { case 0: base_idx=0; @@ -4094,6 +4124,62 @@ pci_inteli960ni_fn(struct pci_dev *dev, return(0); } +/* + * Timedia has an explosion of boards, and to avoid the PCI table from + * growing *huge*, we use this function to collapse some 70 entries + * in the PCI table into one, for sanity's and compactness's sake. + */ +static unsigned short timedia_single_port[] = { + 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; +static unsigned short timedia_dual_port[] = { + 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, + 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, + 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, + 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079, + 0xD079, 0 }; +static unsigned short timedia_quad_port[] = { + 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, + 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, + 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, + 0xB157, 0 }; +static unsigned short timedia_eight_port[] = { + 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, + 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; +static struct timedia_struct { + int num; + unsigned short *ids; +} timedia_data[] = { + { 1, timedia_single_port }, + { 2, timedia_dual_port }, + { 4, timedia_quad_port }, + { 8, timedia_eight_port }, + { 0, 0 } +}; + +static int +#ifndef MODULE +__init +#endif +pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + int i, j; + unsigned short *ids; + + if (!enable) + return 0; + + for (i=0; timedia_data[i].num; i++) { + ids = timedia_data[i].ids; + for (j=0; ids[j]; j++) { + if (pci_get_subvendor(dev) == ids[j]) { + board->num_ports = timedia_data[i].num; + return 0; + } + } + } + return 0; +} + /* * This is the configuration table for all of the PCI serial boards @@ -4120,58 +4206,50 @@ static struct pci_board pci_boards[] __initdata = { PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, SPCI_FL_BASE1, 2, 1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, SPCI_FL_BASE1, 8, 1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, SPCI_FL_BASE1, 4, 1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, SPCI_FL_BASE1, 2, 1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, SPCI_FL_BASE1, 8, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, SPCI_FL_BASE1, 8, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, SPCI_FL_BASE1, 4, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, SPCI_FL_BASE1, 4, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, SPCI_FL_BASE1, 2, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, SPCI_FL_BASE1, 8, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, SPCI_FL_BASE1, 8, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, SPCI_FL_BASE1, 4, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, - SPCI_FL_BASE1, 4, 921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, - SPCI_FL_BASE1, 2, 921600 }, { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, @@ -4200,6 +4278,9 @@ static struct pci_board pci_boards[] __initdata = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE2, 8, 921600 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE2, 4, 921600 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_SUBVENDOR_ID_KEYSPAN, PCI_SUBDEVICE_ID_KEYSPAN_SX2, @@ -4269,75 +4350,10 @@ static struct pci_board pci_boards[] __initdata = { { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, - /* PCI_VENDOR_ID_TIMEDIA/Sunix, PCI_DEVICE_ID_TIMEDIA_1889, */ - { 0x1409, 0x7168, 0x1409, 0x0002, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4036A*/ - { 0x1409, 0x7168, 0x1409, 0x4025, SPCI_FL_BASE_TABLE, 1, 921600 }, /*4025A*/ - { 0x1409, 0x7168, 0x1409, 0x4027, SPCI_FL_BASE_TABLE, 1, 921600 }, /*4027A*/ - { 0x1409, 0x7168, 0x1409, 0x4028, SPCI_FL_BASE_TABLE, 1, 921600 }, /*4028D*/ - { 0x1409, 0x7168, 0x1409, 0x4036, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4036D*/ - { 0x1409, 0x7168, 0x1409, 0x4037, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4037A*/ - { 0x1409, 0x7168, 0x1409, 0x4038, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4038D*/ - { 0x1409, 0x7168, 0x1409, 0x4055, SPCI_FL_BASE_TABLE, 4, 921600 }, /*4055A*/ - { 0x1409, 0x7168, 0x1409, 0x4056, SPCI_FL_BASE_TABLE, 4, 921600 }, /*4056A*/ - { 0x1409, 0x7168, 0x1409, 0x4065, SPCI_FL_BASE_TABLE, 8, 921600 }, /*4065A*/ - { 0x1409, 0x7168, 0x1409, 0x4066, SPCI_FL_BASE_TABLE, 8, 921600 }, /*4066A*/ - { 0x1409, 0x7168, 0x1409, 0x4078, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4078A*/ - { 0x1409, 0x7168, 0x1409, 0x4079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079H*/ - { 0x1409, 0x7168, 0x1409, 0x4085, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4085H*/ - { 0x1409, 0x7168, 0x1409, 0x4088, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4088A*/ - { 0x1409, 0x7168, 0x1409, 0x4089, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4089A*/ - { 0x1409, 0x7168, 0x1409, 0x4095, SPCI_FL_BASE_TABLE, 4, 921600 }, /*4095A*/ - { 0x1409, 0x7168, 0x1409, 0x4096, SPCI_FL_BASE_TABLE, 4, 921600 }, /*4096A*/ - { 0x1409, 0x7168, 0x1409, 0x5025, SPCI_FL_BASE_TABLE, 1, 921600 }, /*4025D*/ - { 0x1409, 0x7168, 0x1409, 0x5027, SPCI_FL_BASE_TABLE, 1, 921600 }, /*4027D*/ - { 0x1409, 0x7168, 0x1409, 0x5037, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4037D*/ - { 0x1409, 0x7168, 0x1409, 0x5056, SPCI_FL_BASE_TABLE, 4, 921600 }, /*4056R*/ - { 0x1409, 0x7168, 0x1409, 0x5065, SPCI_FL_BASE_TABLE, 8, 921600 }, /*4065R*/ - { 0x1409, 0x7168, 0x1409, 0x5066, SPCI_FL_BASE_TABLE, 8, 921600 }, /*4066R*/ - { 0x1409, 0x7168, 0x1409, 0x5078, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4078U*/ - { 0x1409, 0x7168, 0x1409, 0x5079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079A*/ - { 0x1409, 0x7168, 0x1409, 0x5085, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4085U*/ - { 0x1409, 0x7168, 0x1409, 0x6079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079R*/ - { 0x1409, 0x7168, 0x1409, 0x7079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079S*/ - { 0x1409, 0x7168, 0x1409, 0x8079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079D*/ - { 0x1409, 0x7168, 0x1409, 0x8137, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8137*/ - { 0x1409, 0x7168, 0x1409, 0x8138, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8138*/ - { 0x1409, 0x7168, 0x1409, 0x8156, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8156*/ - { 0x1409, 0x7168, 0x1409, 0x8157, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8157*/ - { 0x1409, 0x7168, 0x1409, 0x8166, SPCI_FL_BASE_TABLE, 8, 921600 }, /*8166*/ - { 0x1409, 0x7168, 0x1409, 0x8237, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8237*/ - { 0x1409, 0x7168, 0x1409, 0x8238, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8238*/ - { 0x1409, 0x7168, 0x1409, 0x8256, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8256*/ - { 0x1409, 0x7168, 0x1409, 0x8257, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8257*/ - { 0x1409, 0x7168, 0x1409, 0x9056, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9056A*/ - { 0x1409, 0x7168, 0x1409, 0x9066, SPCI_FL_BASE_TABLE, 8, 921600 }, /*9066A*/ - { 0x1409, 0x7168, 0x1409, 0x9079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079E*/ - { 0x1409, 0x7168, 0x1409, 0x9137, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8137S*/ - { 0x1409, 0x7168, 0x1409, 0x9138, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8138S*/ - { 0x1409, 0x7168, 0x1409, 0x9156, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8156S*/ - { 0x1409, 0x7168, 0x1409, 0x9157, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8157S*/ - { 0x1409, 0x7168, 0x1409, 0x9158, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9158*/ - { 0x1409, 0x7168, 0x1409, 0x9159, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9159*/ - { 0x1409, 0x7168, 0x1409, 0x9166, SPCI_FL_BASE_TABLE, 8, 921600 }, /*8166S*/ - { 0x1409, 0x7168, 0x1409, 0x9167, SPCI_FL_BASE_TABLE, 8, 921600 }, /*9167*/ - { 0x1409, 0x7168, 0x1409, 0x9168, SPCI_FL_BASE_TABLE, 8, 921600 }, /*9168*/ - { 0x1409, 0x7168, 0x1409, 0x9237, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8237S*/ - { 0x1409, 0x7168, 0x1409, 0x9238, SPCI_FL_BASE_TABLE, 2, 921600 }, /*8238S*/ - { 0x1409, 0x7168, 0x1409, 0x9256, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8256S*/ - { 0x1409, 0x7168, 0x1409, 0x9257, SPCI_FL_BASE_TABLE, 4, 921600 }, /*8257S*/ - { 0x1409, 0x7168, 0x1409, 0xA056, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9056B*/ - { 0x1409, 0x7168, 0x1409, 0xA066, SPCI_FL_BASE_TABLE, 8, 921600 }, /*9066B*/ - { 0x1409, 0x7168, 0x1409, 0xA079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*4079F*/ - { 0x1409, 0x7168, 0x1409, 0xA157, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9157*/ - { 0x1409, 0x7168, 0x1409, 0xA158, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9158S*/ - { 0x1409, 0x7168, 0x1409, 0xA159, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9159S*/ - { 0x1409, 0x7168, 0x1409, 0xA167, SPCI_FL_BASE_TABLE, 8, 921600 }, /*9167S*/ - { 0x1409, 0x7168, 0x1409, 0xA168, SPCI_FL_BASE_TABLE, 8, 921600 }, /*9168S*/ - { 0x1409, 0x7168, 0x1409, 0xB056, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9056C*/ - { 0x1409, 0x7168, 0x1409, 0xB079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*9079A*/ - { 0x1409, 0x7168, 0x1409, 0xB157, SPCI_FL_BASE_TABLE, 4, 921600 }, /*9157S*/ - { 0x1409, 0x7168, 0x1409, 0xC079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*9079B*/ - { 0x1409, 0x7168, 0x1409, 0xD079, SPCI_FL_BASE_TABLE, 2, 921600 }, /*9079C*/ + { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, + SPCI_FL_BASE_TABLE, 1, 921600, + 0, 0, pci_timedia_fn }, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, @@ -4544,7 +4560,7 @@ static struct pci_board pci_boards[] __initdata = { { PCI_VENDOR_ID_ROCKWELL, 0x1004, 0x1048, 0x1500, SPCI_FL_BASE1, 1, 115200 }, -#ifdef CONFIG_DDB5074 +#if CONFIG_DDB5074 /* * NEC Vrc-5074 (Nile 4) builtin UART. * Conditionally compiled in since this is a motherboard device. @@ -4584,7 +4600,7 @@ static int _INLINE_ serial_pci_guess_board(struct pci_dev *dev, for (i=0; i < 6; i++) { if (IS_PCI_REGION_IOPORT(dev, i)) { - num_port = 0; + num_port++; if (first_port == -1) first_port = i; } else { @@ -5081,16 +5097,6 @@ static int __init rs_init(void) int i; struct serial_state * state; - if (serial_timer.function) { - printk("RS_TIMER already set, another serial driver " - "already loaded?\n"); -#ifdef MODULE - printk("Can't load serial driver module over built-in " - "serial driver\n"); -#endif - return -EBUSY; - } - init_bh(SERIAL_BH, do_serial_bh); init_timer(&serial_timer); serial_timer.function = rs_timer; @@ -5423,6 +5429,8 @@ static void __exit rs_fini(void) module_init(rs_init); module_exit(rs_fini); +MODULE_DESCRIPTION("Standard/generic (dumb) serial driver"); +MODULE_AUTHOR("Theodore Ts'o "); /* @@ -5441,10 +5449,17 @@ static struct async_struct async_sercons; */ static inline void wait_for_xmitr(struct async_struct *info) { - unsigned int tmout = 1000000; + unsigned int status, tmout = 1000000; + + do { + status = serial_in(info, UART_LSR); - while (--tmout && - ((serial_in(info, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)); + if (status & UART_LSR_BI) + lsr_break_flag = UART_LSR_BI; + + if (--tmout == 0) + break; + } while((status & BOTH_EMPTY) != BOTH_EMPTY); } diff --git a/drivers/char/serial_21285.c b/drivers/char/serial_21285.c new file mode 100644 index 000000000..575cf0bc0 --- /dev/null +++ b/drivers/char/serial_21285.c @@ -0,0 +1,511 @@ +/* + * linux/drivers/char/serial_21285.c + * + * Driver for the serial port on the 21285 StrongArm-110 core logic chip. + * + * Based on drivers/char/serial.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define BAUD_BASE (mem_fclk_21285/64) + +#define SERIAL_21285_NAME "ttyFB" +#define SERIAL_21285_MAJOR 204 +#define SERIAL_21285_MINOR 4 + +#define SERIAL_21285_AUXNAME "cuafb" +#define SERIAL_21285_AUXMAJOR 205 +#define SERIAL_21285_AUXMINOR 4 + +static struct tty_driver rs285_driver, callout_driver; +static int rs285_refcount; +static struct tty_struct *rs285_table[1]; + +static struct termios *rs285_termios[1]; +static struct termios *rs285_termios_locked[1]; + +static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char; +static struct tty_struct *rs285_tty; +static int rs285_use_count; + +static int rs285_write_room(struct tty_struct *tty) +{ + return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1); +} + +static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs) +{ + if (!rs285_tty) { + disable_irq(IRQ_CONRX); + return; + } + while (!(*CSR_UARTFLG & 0x10)) { + int ch, flag; + ch = *CSR_UARTDR; + flag = *CSR_RXSTAT; + if (flag & 4) + tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN); + if (flag & 2) + flag = TTY_PARITY; + else if (flag & 1) + flag = TTY_FRAME; + tty_insert_flip_char(rs285_tty, ch, flag); + } + tty_flip_buffer_push(rs285_tty); +} + +static void rs285_send_xchar(struct tty_struct *tty, char ch) +{ + x_char = ch; + enable_irq(IRQ_CONTX); +} + +static void rs285_throttle(struct tty_struct *tty) +{ + if (I_IXOFF(tty)) + rs285_send_xchar(tty, STOP_CHAR(tty)); +} + +static void rs285_unthrottle(struct tty_struct *tty) +{ + if (I_IXOFF(tty)) { + if (x_char) + x_char = 0; + else + rs285_send_xchar(tty, START_CHAR(tty)); + } +} + +static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs) +{ + while (!(*CSR_UARTFLG & 0x20)) { + if (x_char) { + *CSR_UARTDR = x_char; + x_char = 0; + continue; + } + if (putp == getp) { + disable_irq(IRQ_CONTX); + break; + } + *CSR_UARTDR = *getp; + if (++getp >= wbuf + sizeof(wbuf)) + getp = wbuf; + } + if (rs285_tty) + wake_up_interruptible(&rs285_tty->write_wait); +} + +static inline int rs285_xmit(int ch) +{ + if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf)) + return 0; + *putp = ch; + if (++putp >= wbuf + sizeof(wbuf)) + putp = wbuf; + enable_irq(IRQ_CONTX); + return 1; +} + +static int rs285_write(struct tty_struct *tty, int from_user, + const u_char * buf, int count) +{ + int i; + + if (from_user && verify_area(VERIFY_READ, buf, count)) + return -EINVAL; + + for (i = 0; i < count; i++) { + char ch; + if (from_user) + __get_user(ch, buf + i); + else + ch = buf[i]; + if (!rs285_xmit(ch)) + break; + } + return i; +} + +static void rs285_put_char(struct tty_struct *tty, u_char ch) +{ + rs285_xmit(ch); +} + +static int rs285_chars_in_buffer(struct tty_struct *tty) +{ + return sizeof(wbuf) - rs285_write_room(tty); +} + +static void rs285_flush_buffer(struct tty_struct *tty) +{ + disable_irq(IRQ_CONTX); + putp = getp = wbuf; + if (x_char) + enable_irq(IRQ_CONTX); +} + +static inline void rs285_set_cflag(int cflag) +{ + int h_lcr, baud, quot; + + switch (cflag & CSIZE) { + case CS5: + h_lcr = 0x10; + break; + case CS6: + h_lcr = 0x30; + break; + case CS7: + h_lcr = 0x50; + break; + default: /* CS8 */ + h_lcr = 0x70; + break; + + } + if (cflag & CSTOPB) + h_lcr |= 0x08; + if (cflag & PARENB) + h_lcr |= 0x02; + if (!(cflag & PARODD)) + h_lcr |= 0x04; + + switch (cflag & CBAUD) { + case B200: baud = 200; break; + case B300: baud = 300; break; + case B1200: baud = 1200; break; + case B1800: baud = 1800; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + default: + case B9600: baud = 9600; break; + case B19200: baud = 19200; break; + case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + } + + /* + * The documented expression for selecting the divisor is: + * BAUD_BASE / baud - 1 + * However, typically BAUD_BASE is not divisible by baud, so + * we want to select the divisor that gives us the minimum + * error. Therefore, we want: + * int(BAUD_BASE / baud - 0.5) -> + * int(BAUD_BASE / baud - (baud >> 1) / baud) -> + * int((BAUD_BASE - (baud >> 1)) / baud) + */ + quot = (BAUD_BASE - (baud >> 1)) / baud; + + *CSR_UARTCON = 0; + *CSR_L_UBRLCR = quot & 0xff; + *CSR_M_UBRLCR = (quot >> 8) & 0x0f; + *CSR_H_UBRLCR = h_lcr; + *CSR_UARTCON = 1; +} + +static void rs285_set_termios(struct tty_struct *tty, struct termios *old) +{ + if (old && tty->termios->c_cflag == old->c_cflag) + return; + rs285_set_cflag(tty->termios->c_cflag); +} + + +static void rs285_stop(struct tty_struct *tty) +{ + disable_irq(IRQ_CONTX); +} + +static void rs285_start(struct tty_struct *tty) +{ + enable_irq(IRQ_CONTX); +} + +static void rs285_wait_until_sent(struct tty_struct *tty, int timeout) +{ + int orig_jiffies = jiffies; + while (*CSR_UARTFLG & 8) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + current->state = TASK_RUNNING; +} + +static int rs285_open(struct tty_struct *tty, struct file *filp) +{ + int line; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if (line) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + + tty->driver_data = NULL; + if (!rs285_tty) + rs285_tty = tty; + + enable_irq(IRQ_CONRX); + rs285_use_count++; + return 0; +} + +static void rs285_close(struct tty_struct *tty, struct file *filp) +{ + if (!--rs285_use_count) { + rs285_wait_until_sent(tty, 0); + disable_irq(IRQ_CONRX); + disable_irq(IRQ_CONTX); + rs285_tty = NULL; + } + MOD_DEC_USE_COUNT; +} + +static int __init rs285_init(void) +{ + int baud = B9600; + + if (machine_is_personal_server()) + baud = B57600; + + rs285_driver.magic = TTY_DRIVER_MAGIC; + rs285_driver.driver_name = "serial_21285"; + rs285_driver.name = SERIAL_21285_NAME; + rs285_driver.major = SERIAL_21285_MAJOR; + rs285_driver.minor_start = SERIAL_21285_MINOR; + rs285_driver.num = 1; + rs285_driver.type = TTY_DRIVER_TYPE_SERIAL; + rs285_driver.subtype = SERIAL_TYPE_NORMAL; + rs285_driver.init_termios = tty_std_termios; + rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL; + rs285_driver.flags = TTY_DRIVER_REAL_RAW; + rs285_driver.refcount = &rs285_refcount; + rs285_driver.table = rs285_table; + rs285_driver.termios = rs285_termios; + rs285_driver.termios_locked = rs285_termios_locked; + + rs285_driver.open = rs285_open; + rs285_driver.close = rs285_close; + rs285_driver.write = rs285_write; + rs285_driver.put_char = rs285_put_char; + rs285_driver.write_room = rs285_write_room; + rs285_driver.chars_in_buffer = rs285_chars_in_buffer; + rs285_driver.flush_buffer = rs285_flush_buffer; + rs285_driver.throttle = rs285_throttle; + rs285_driver.unthrottle = rs285_unthrottle; + rs285_driver.send_xchar = rs285_send_xchar; + rs285_driver.set_termios = rs285_set_termios; + rs285_driver.stop = rs285_stop; + rs285_driver.start = rs285_start; + rs285_driver.wait_until_sent = rs285_wait_until_sent; + + callout_driver = rs285_driver; + callout_driver.name = SERIAL_21285_AUXNAME; + callout_driver.major = SERIAL_21285_AUXMAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL)) + panic("Couldn't get rx irq for rs285"); + + if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL)) + panic("Couldn't get tx irq for rs285"); + + if (tty_register_driver(&rs285_driver)) + printk(KERN_ERR "Couldn't register 21285 serial driver\n"); + if (tty_register_driver(&callout_driver)) + printk(KERN_ERR "Couldn't register 21285 callout driver\n"); + + return 0; +} + +static void __exit rs285_fini(void) +{ + unsigned long flags; + int ret; + + save_flags(flags); + cli(); + ret = tty_unregister_driver(&callout_driver); + if (ret) + printk(KERN_ERR "Unable to unregister 21285 callout driver " + "(%d)\n", ret); + ret = tty_unregister_driver(&rs285_driver); + if (ret) + printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n", + ret); + free_irq(IRQ_CONTX, NULL); + free_irq(IRQ_CONRX, NULL); + restore_flags(flags); +} + +module_init(rs285_init); +module_exit(rs285_fini); + +#ifdef CONFIG_SERIAL_21285_CONSOLE +/************** console driver *****************/ + +static void rs285_console_write(struct console *co, const char *s, u_int count) +{ + int i; + + disable_irq(IRQ_CONTX); + for (i = 0; i < count; i++) { + while (*CSR_UARTFLG & 0x20); + *CSR_UARTDR = s[i]; + if (s[i] == '\n') { + while (*CSR_UARTFLG & 0x20); + *CSR_UARTDR = '\r'; + } + } + enable_irq(IRQ_CONTX); +} + +static int rs285_console_wait_key(struct console *co) +{ + int c; + + disable_irq(IRQ_CONRX); + while (*CSR_UARTFLG & 0x10); + c = *CSR_UARTDR; + enable_irq(IRQ_CONRX); + return c; +} + +static kdev_t rs285_console_device(struct console *c) +{ + return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR); +} + +static int __init rs285_console_setup(struct console *co, char *options) +{ + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + + if (machine_is_personal_server()) + baud = 57600; + + if (options) { + char *s = options; + baud = simple_strtoul(options, NULL, 10); + while (*s >= '0' && *s <= '9') + s++; + if (*s) + parity = *s++; + if (*s) + bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch (baud) { + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 9600: + cflag |= B9600; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + default: + cflag |= B9600; + break; + } + switch (bits) { + case 7: + cflag |= CS7; + break; + default: + cflag |= CS8; + break; + } + switch (parity) { + case 'o': + case 'O': + cflag |= PARODD; + break; + case 'e': + case 'E': + cflag |= PARENB; + break; + } + co->cflag = cflag; + rs285_set_cflag(cflag); + rs285_console_write(NULL, "\e[2J\e[Hboot ", 12); + if (options) + rs285_console_write(NULL, options, strlen(options)); + else + rs285_console_write(NULL, "no options", 10); + rs285_console_write(NULL, "\n", 1); + + return 0; +} + +static struct console rs285_cons = +{ + SERIAL_21285_NAME, + rs285_console_write, + NULL, + rs285_console_device, + rs285_console_wait_key, + NULL, + rs285_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +void __init rs285_console_init(void) +{ + register_console(&rs285_cons); +} + +#endif /* CONFIG_SERIAL_21285_CONSOLE */ diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c deleted file mode 100644 index a0faeada4..000000000 --- a/drivers/char/stallion.c +++ /dev/null @@ -1,5329 +0,0 @@ -/*****************************************************************************/ - -/* - * stallion.c -- stallion multiport serial driver. - * - * Copyright (C) 1996-1999 Stallion Technologies (support@stallion.oz.au). - * Copyright (C) 1994-1996 Greg Ungerer. - * - * This code is loosely based on the Linux serial driver, written by - * Linus Torvalds, Theodore T'so and others. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 -#include -#include /* for linux/stallion.h */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_PCI -#include -#endif - -/*****************************************************************************/ - -/* - * Define different board types. Use the standard Stallion "assigned" - * board numbers. Boards supported in this driver are abbreviated as - * EIO = EasyIO and ECH = EasyConnection 8/32. - */ -#define BRD_EASYIO 20 -#define BRD_ECH 21 -#define BRD_ECHMC 22 -#define BRD_ECHPCI 26 -#define BRD_ECH64PCI 27 -#define BRD_EASYIOPCI 28 - -/* - * Define a configuration structure to hold the board configuration. - * Need to set this up in the code (for now) with the boards that are - * to be configured into the system. This is what needs to be modified - * when adding/removing/modifying boards. Each line entry in the - * stl_brdconf[] array is a board. Each line contains io/irq/memory - * ranges for that board (as well as what type of board it is). - * Some examples: - * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, - * This line would configure an EasyIO board (4 or 8, no difference), - * at io address 2a0 and irq 10. - * Another example: - * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 }, - * This line will configure an EasyConnection 8/32 board at primary io - * address 2a8, secondary io address 280 and irq 12. - * Enter as many lines into this array as you want (only the first 4 - * will actually be used!). Any combination of EasyIO and EasyConnection - * boards can be specified. EasyConnection 8/32 boards can share their - * secondary io addresses between each other. - * - * NOTE: there is no need to put any entries in this table for PCI - * boards. They will be found automatically by the driver - provided - * PCI BIOS32 support is compiled into the kernel. - */ - -typedef struct { - int brdtype; - int ioaddr1; - int ioaddr2; - unsigned long memaddr; - int irq; - int irqtype; -} stlconf_t; - -static stlconf_t stl_brdconf[] = { - /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/ -}; - -static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); - -/*****************************************************************************/ - -/* - * Define some important driver characteristics. Device major numbers - * allocated as per Linux Device Registry. - */ -#ifndef STL_SIOMEMMAJOR -#define STL_SIOMEMMAJOR 28 -#endif -#ifndef STL_SERIALMAJOR -#define STL_SERIALMAJOR 24 -#endif -#ifndef STL_CALLOUTMAJOR -#define STL_CALLOUTMAJOR 25 -#endif - -#define STL_DRVTYPSERIAL 1 -#define STL_DRVTYPCALLOUT 2 - -/* - * Set the TX buffer size. Bigger is better, but we don't want - * to chew too much memory with buffers! - */ -#define STL_TXBUFLOW 512 -#define STL_TXBUFSIZE 4096 - -/*****************************************************************************/ - -/* - * Define our local driver identity first. Set up stuff to deal with - * all the local structures required by a serial tty driver. - */ -static char *stl_drvtitle = "Stallion Multiport Serial Driver"; -static char *stl_drvname = "stallion"; -static char *stl_drvversion = "5.6.0"; -static char *stl_serialname = "ttyE"; -static char *stl_calloutname = "cue"; - -static struct tty_driver stl_serial; -static struct tty_driver stl_callout; -static struct tty_struct *stl_ttys[STL_MAXDEVS]; -static struct termios *stl_termios[STL_MAXDEVS]; -static struct termios *stl_termioslocked[STL_MAXDEVS]; -static int stl_refcount = 0; - -/* - * We will need to allocate a temporary write buffer for chars that - * come direct from user space. The problem is that a copy from user - * space might cause a page fault (typically on a system that is - * swapping!). All ports will share one buffer - since if the system - * is already swapping a shared buffer won't make things any worse. - */ -static char *stl_tmpwritebuf; -static DECLARE_MUTEX(stl_tmpwritesem); - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. Basically all it defines is a raw port - * at 9600, 8 data bits, 1 stop bit. - */ -static struct termios stl_deftermios = { - 0, - 0, - (B9600 | CS8 | CREAD | HUPCL | CLOCAL), - 0, - 0, - INIT_C_CC -}; - -/* - * Define global stats structures. Not used often, and can be - * re-used for each stats call. - */ -static comstats_t stl_comstats; -static combrd_t stl_brdstats; -static stlbrd_t stl_dummybrd; -static stlport_t stl_dummyport; - -/* - * Define global place to put buffer overflow characters. - */ -static char stl_unwanted[SC26198_RXFIFOSIZE]; - -/* - * Keep track of what interrupts we have requested for us. - * We don't need to request an interrupt twice if it is being - * shared with another Stallion board. - */ -static int stl_gotintrs[STL_MAXBRDS]; -static int stl_numintrs = 0; - -/*****************************************************************************/ - -static stlbrd_t *stl_brds[STL_MAXBRDS]; - -/* - * Per board state flags. Used with the state field of the board struct. - * Not really much here! - */ -#define BRD_FOUND 0x1 - -/* - * Define the port structure istate flags. These set of flags are - * modified at interrupt time - so setting and reseting them needs - * to be atomic. Use the bit clear/setting routines for this. - */ -#define ASYI_TXBUSY 1 -#define ASYI_TXLOW 2 -#define ASYI_DCDCHANGE 3 -#define ASYI_TXFLOWED 4 - -/* - * Define an array of board names as printable strings. Handy for - * referencing boards when printing trace and stuff. - */ -static char *stl_brdnames[] = { - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - "EasyIO", - "EC8/32-AT", - "EC8/32-MC", - (char *) NULL, - (char *) NULL, - (char *) NULL, - "EC8/32-PCI", - "EC8/64-PCI", - "EasyIO-PCI", -}; - -/*****************************************************************************/ - -#ifdef MODULE -/* - * Define some string labels for arguments passed from the module - * load line. These allow for easy board definitions, and easy - * modification of the io, memory and irq resoucres. - */ - -static char *board0[4]; -static char *board1[4]; -static char *board2[4]; -static char *board3[4]; - -static char **stl_brdsp[] = { - (char **) &board0, - (char **) &board1, - (char **) &board2, - (char **) &board3 -}; - -/* - * Define a set of common board names, and types. This is used to - * parse any module arguments. - */ - -typedef struct stlbrdtype { - char *name; - int type; -} stlbrdtype_t; - -static stlbrdtype_t stl_brdstr[] = { - { "easyio", BRD_EASYIO }, - { "eio", BRD_EASYIO }, - { "20", BRD_EASYIO }, - { "ec8/32", BRD_ECH }, - { "ec8/32-at", BRD_ECH }, - { "ec8/32-isa", BRD_ECH }, - { "ech", BRD_ECH }, - { "echat", BRD_ECH }, - { "21", BRD_ECH }, - { "ec8/32-mc", BRD_ECHMC }, - { "ec8/32-mca", BRD_ECHMC }, - { "echmc", BRD_ECHMC }, - { "echmca", BRD_ECHMC }, - { "22", BRD_ECHMC }, - { "ec8/32-pc", BRD_ECHPCI }, - { "ec8/32-pci", BRD_ECHPCI }, - { "26", BRD_ECHPCI }, - { "ec8/64-pc", BRD_ECH64PCI }, - { "ec8/64-pci", BRD_ECH64PCI }, - { "ech-pci", BRD_ECH64PCI }, - { "echpci", BRD_ECH64PCI }, - { "echpc", BRD_ECH64PCI }, - { "27", BRD_ECH64PCI }, - { "easyio-pc", BRD_EASYIOPCI }, - { "easyio-pci", BRD_EASYIOPCI }, - { "eio-pci", BRD_EASYIOPCI }, - { "eiopci", BRD_EASYIOPCI }, - { "28", BRD_EASYIOPCI }, -}; - -/* - * Define the module agruments. - */ -MODULE_AUTHOR("Greg Ungerer"); -MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); - -MODULE_PARM(board0, "1-4s"); -MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); -MODULE_PARM(board1, "1-4s"); -MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]"); -MODULE_PARM(board2, "1-4s"); -MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]"); -MODULE_PARM(board3, "1-4s"); -MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]"); - -#endif - -/*****************************************************************************/ - -/* - * Hardware ID bits for the EasyIO and ECH boards. These defines apply - * to the directly accessible io ports of these boards (not the uarts - - * they are in cd1400.h and sc26198.h). - */ -#define EIO_8PORTRS 0x04 -#define EIO_4PORTRS 0x05 -#define EIO_8PORTDI 0x00 -#define EIO_8PORTM 0x06 -#define EIO_MK3 0x03 -#define EIO_IDBITMASK 0x07 - -#define EIO_BRDMASK 0xf0 -#define ID_BRD4 0x10 -#define ID_BRD8 0x20 -#define ID_BRD16 0x30 - -#define EIO_INTRPEND 0x08 -#define EIO_INTEDGE 0x00 -#define EIO_INTLEVEL 0x08 -#define EIO_0WS 0x10 - -#define ECH_ID 0xa0 -#define ECH_IDBITMASK 0xe0 -#define ECH_BRDENABLE 0x08 -#define ECH_BRDDISABLE 0x00 -#define ECH_INTENABLE 0x01 -#define ECH_INTDISABLE 0x00 -#define ECH_INTLEVEL 0x02 -#define ECH_INTEDGE 0x00 -#define ECH_INTRPEND 0x01 -#define ECH_BRDRESET 0x01 - -#define ECHMC_INTENABLE 0x01 -#define ECHMC_BRDRESET 0x02 - -#define ECH_PNLSTATUS 2 -#define ECH_PNL16PORT 0x20 -#define ECH_PNLIDMASK 0x07 -#define ECH_PNLXPID 0x40 -#define ECH_PNLINTRPEND 0x80 - -#define ECH_ADDR2MASK 0x1e0 - -/* - * Define the vector mapping bits for the programmable interrupt board - * hardware. These bits encode the interrupt for the board to use - it - * is software selectable (except the EIO-8M). - */ -static unsigned char stl_vecmap[] = { - 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07, - 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03 -}; - -/* - * Set up enable and disable macros for the ECH boards. They require - * the secondary io address space to be activated and deactivated. - * This way all ECH boards can share their secondary io region. - * If this is an ECH-PCI board then also need to set the page pointer - * to point to the correct page. - */ -#define BRDENABLE(brdnr,pagenr) \ - if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ - outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \ - stl_brds[(brdnr)]->ioctrl); \ - else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \ - outb((pagenr), stl_brds[(brdnr)]->ioctrl); - -#define BRDDISABLE(brdnr) \ - if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \ - outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \ - stl_brds[(brdnr)]->ioctrl); - -#define STL_CD1400MAXBAUD 230400 -#define STL_SC26198MAXBAUD 460800 - -#define STL_BAUDBASE 115200 -#define STL_CLOSEDELAY (5 * HZ / 10) - -/*****************************************************************************/ - -#ifdef CONFIG_PCI - -/* - * Define the Stallion PCI vendor and device IDs. - */ -#ifndef PCI_VENDOR_ID_STALLION -#define PCI_VENDOR_ID_STALLION 0x124d -#endif -#ifndef PCI_DEVICE_ID_ECHPCI832 -#define PCI_DEVICE_ID_ECHPCI832 0x0000 -#endif -#ifndef PCI_DEVICE_ID_ECHPCI864 -#define PCI_DEVICE_ID_ECHPCI864 0x0002 -#endif -#ifndef PCI_DEVICE_ID_EIOPCI -#define PCI_DEVICE_ID_EIOPCI 0x0003 -#endif - -/* - * Define structure to hold all Stallion PCI boards. - */ -typedef struct stlpcibrd { - unsigned short vendid; - unsigned short devid; - int brdtype; -} stlpcibrd_t; - -static stlpcibrd_t stl_pcibrds[] = { - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI }, - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI }, - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI }, - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI }, -}; - -static int stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t); - -#endif - -/*****************************************************************************/ - -/* - * Define macros to extract a brd/port number from a minor number. - */ -#define MINOR2BRD(min) (((min) & 0xc0) >> 6) -#define MINOR2PORT(min) ((min) & 0x3f) - -/* - * Define a baud rate table that converts termios baud rate selector - * into the actual baud rate value. All baud rate calculations are - * based on the actual baud rate required. - */ -static unsigned int stl_baudrates[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 -}; - -/* - * Define some handy local macros... - */ -#undef MIN -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) - -#undef TOLOWER -#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x)) - -/*****************************************************************************/ - -/* - * Declare all those functions in this driver! - */ - -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -static void stl_argbrds(void); -static int stl_parsebrd(stlconf_t *confp, char **argp); - -static unsigned long stl_atol(char *str); -#endif - -int stl_init(void); -static int stl_open(struct tty_struct *tty, struct file *filp); -static void stl_close(struct tty_struct *tty, struct file *filp); -static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); -static void stl_putchar(struct tty_struct *tty, unsigned char ch); -static void stl_flushchars(struct tty_struct *tty); -static int stl_writeroom(struct tty_struct *tty); -static int stl_charsinbuffer(struct tty_struct *tty); -static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void stl_settermios(struct tty_struct *tty, struct termios *old); -static void stl_throttle(struct tty_struct *tty); -static void stl_unthrottle(struct tty_struct *tty); -static void stl_stop(struct tty_struct *tty); -static void stl_start(struct tty_struct *tty); -static void stl_flushbuffer(struct tty_struct *tty); -static void stl_breakctl(struct tty_struct *tty, int state); -static void stl_waituntilsent(struct tty_struct *tty, int timeout); -static void stl_sendxchar(struct tty_struct *tty, char ch); -static void stl_hangup(struct tty_struct *tty); -static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -static int stl_portinfo(stlport_t *portp, int portnr, char *pos); -static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data); - -static int stl_brdinit(stlbrd_t *brdp); -static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp); -static int stl_mapirq(int irq, char *name); -static void stl_getserial(stlport_t *portp, struct serial_struct *sp); -static int stl_setserial(stlport_t *portp, struct serial_struct *sp); -static int stl_getbrdstats(combrd_t *bp); -static int stl_getportstats(stlport_t *portp, comstats_t *cp); -static int stl_clrportstats(stlport_t *portp, comstats_t *cp); -static int stl_getportstruct(unsigned long arg); -static int stl_getbrdstruct(unsigned long arg); -static int stl_waitcarrier(stlport_t *portp, struct file *filp); -static void stl_delay(int len); -static void stl_intr(int irq, void *dev_id, struct pt_regs *regs); -static void stl_eiointr(stlbrd_t *brdp); -static void stl_echatintr(stlbrd_t *brdp); -static void stl_echmcaintr(stlbrd_t *brdp); -static void stl_echpciintr(stlbrd_t *brdp); -static void stl_echpci64intr(stlbrd_t *brdp); -static void stl_offintr(void *private); -static void *stl_memalloc(int len); -static stlbrd_t *stl_allocbrd(void); -static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); - -static inline int stl_initbrds(void); -static inline int stl_initeio(stlbrd_t *brdp); -static inline int stl_initech(stlbrd_t *brdp); -static inline int stl_getbrdnr(void); - -#ifdef CONFIG_PCI -static inline int stl_findpcibrds(void); -static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp); -#endif - -/* - * CD1400 uart specific handling functions. - */ -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value); -static int stl_cd1400getreg(stlport_t *portp, int regnr); -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value); -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp); -static int stl_cd1400getsignals(stlport_t *portp); -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts); -static void stl_cd1400ccrwait(stlport_t *portp); -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400disableintrs(stlport_t *portp); -static void stl_cd1400sendbreak(stlport_t *portp, int len); -static void stl_cd1400flowctrl(stlport_t *portp, int state); -static void stl_cd1400sendflow(stlport_t *portp, int state); -static void stl_cd1400flush(stlport_t *portp); -static int stl_cd1400datastate(stlport_t *portp); -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr); - -static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr); - -/* - * SC26198 uart specific handling functions. - */ -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getreg(stlport_t *portp, int regnr); -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getglobreg(stlport_t *portp, int regnr); -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp); -static int stl_sc26198getsignals(stlport_t *portp); -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts); -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198disableintrs(stlport_t *portp); -static void stl_sc26198sendbreak(stlport_t *portp, int len); -static void stl_sc26198flowctrl(stlport_t *portp, int state); -static void stl_sc26198sendflow(stlport_t *portp, int state); -static void stl_sc26198flush(stlport_t *portp); -static int stl_sc26198datastate(stlport_t *portp); -static void stl_sc26198wait(stlport_t *portp); -static void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty); -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase); -static void stl_sc26198txisr(stlport_t *port); -static void stl_sc26198rxisr(stlport_t *port, unsigned int iack); -static void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch); -static void stl_sc26198rxbadchars(stlport_t *portp); -static void stl_sc26198otherisr(stlport_t *port, unsigned int iack); - -/*****************************************************************************/ - -/* - * Generic UART support structure. - */ -typedef struct uart { - int (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp); - void (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); - void (*setport)(stlport_t *portp, struct termios *tiosp); - int (*getsignals)(stlport_t *portp); - void (*setsignals)(stlport_t *portp, int dtr, int rts); - void (*enablerxtx)(stlport_t *portp, int rx, int tx); - void (*startrxtx)(stlport_t *portp, int rx, int tx); - void (*disableintrs)(stlport_t *portp); - void (*sendbreak)(stlport_t *portp, int len); - void (*flowctrl)(stlport_t *portp, int state); - void (*sendflow)(stlport_t *portp, int state); - void (*flush)(stlport_t *portp); - int (*datastate)(stlport_t *portp); - void (*intr)(stlpanel_t *panelp, unsigned int iobase); -} uart_t; - -/* - * Define some macros to make calling these functions nice and clean. - */ -#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit) -#define stl_portinit (* ((uart_t *) portp->uartp)->portinit) -#define stl_setport (* ((uart_t *) portp->uartp)->setport) -#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals) -#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals) -#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx) -#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx) -#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs) -#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak) -#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl) -#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow) -#define stl_flush (* ((uart_t *) portp->uartp)->flush) -#define stl_datastate (* ((uart_t *) portp->uartp)->datastate) - -/*****************************************************************************/ - -/* - * CD1400 UART specific data initialization. - */ -static uart_t stl_cd1400uart = { - stl_cd1400panelinit, - stl_cd1400portinit, - stl_cd1400setport, - stl_cd1400getsignals, - stl_cd1400setsignals, - stl_cd1400enablerxtx, - stl_cd1400startrxtx, - stl_cd1400disableintrs, - stl_cd1400sendbreak, - stl_cd1400flowctrl, - stl_cd1400sendflow, - stl_cd1400flush, - stl_cd1400datastate, - stl_cd1400eiointr -}; - -/* - * Define the offsets within the register bank of a cd1400 based panel. - * These io address offsets are common to the EasyIO board as well. - */ -#define EREG_ADDR 0 -#define EREG_DATA 4 -#define EREG_RXACK 5 -#define EREG_TXACK 6 -#define EREG_MDACK 7 - -#define EREG_BANKSIZE 8 - -#define CD1400_CLK 25000000 -#define CD1400_CLK8M 20000000 - -/* - * Define the cd1400 baud rate clocks. These are used when calculating - * what clock and divisor to use for the required baud rate. Also - * define the maximum baud rate allowed, and the default base baud. - */ -static int stl_cd1400clkdivs[] = { - CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4 -}; - -/*****************************************************************************/ - -/* - * SC26198 UART specific data initization. - */ -static uart_t stl_sc26198uart = { - stl_sc26198panelinit, - stl_sc26198portinit, - stl_sc26198setport, - stl_sc26198getsignals, - stl_sc26198setsignals, - stl_sc26198enablerxtx, - stl_sc26198startrxtx, - stl_sc26198disableintrs, - stl_sc26198sendbreak, - stl_sc26198flowctrl, - stl_sc26198sendflow, - stl_sc26198flush, - stl_sc26198datastate, - stl_sc26198intr -}; - -/* - * Define the offsets within the register bank of a sc26198 based panel. - */ -#define XP_DATA 0 -#define XP_ADDR 1 -#define XP_MODID 2 -#define XP_STATUS 2 -#define XP_IACK 3 - -#define XP_BANKSIZE 4 - -/* - * Define the sc26198 baud rate table. Offsets within the table - * represent the actual baud rate selector of sc26198 registers. - */ -static unsigned int sc26198_baudtable[] = { - 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600, - 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, - 230400, 460800, 921600 -}; - -#define SC26198_NRBAUDS (sizeof(sc26198_baudtable) / sizeof(unsigned int)) - -/*****************************************************************************/ - -/* - * Define the driver info for a user level control device. Used mainly - * to get at port stats - only not using the port device itself. - */ -static struct file_operations stl_fsiomem = { - owner: THIS_MODULE, - ioctl: stl_memioctl, -}; - -/*****************************************************************************/ - -static devfs_handle_t devfs_handle = NULL; - -#ifdef MODULE - -/* - * Loadable module initialization stuff. - */ - -int init_module() -{ - unsigned long flags; - -#if DEBUG - printk("init_module()\n"); -#endif - - save_flags(flags); - cli(); - stl_init(); - restore_flags(flags); - - return(0); -} - -/*****************************************************************************/ - -void cleanup_module() -{ - stlbrd_t *brdp; - stlpanel_t *panelp; - stlport_t *portp; - unsigned long flags; - int i, j, k; - -#if DEBUG - printk("cleanup_module()\n"); -#endif - - printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, - stl_drvversion); - - save_flags(flags); - cli(); - -/* - * Free up all allocated resources used by the ports. This includes - * memory and interrupts. As part of this process we will also do - * a hangup on every open port - to try to flush out any processes - * hanging onto ports. - */ - i = tty_unregister_driver(&stl_serial); - j = tty_unregister_driver(&stl_callout); - if (i || j) { - printk("STALLION: failed to un-register tty driver, " - "errno=%d,%d\n", -i, -j); - restore_flags(flags); - return; - } - devfs_unregister (devfs_handle); - if ((i = devfs_unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) - printk("STALLION: failed to un-register serial memory device, " - "errno=%d\n", -i); - - if (stl_tmpwritebuf != (char *) NULL) - kfree(stl_tmpwritebuf); - - for (i = 0; (i < stl_nrbrds); i++) { - if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) - continue; - for (j = 0; (j < STL_MAXPANELS); j++) { - panelp = brdp->panels[j]; - if (panelp == (stlpanel_t *) NULL) - continue; - for (k = 0; (k < STL_PORTSPERPANEL); k++) { - portp = panelp->ports[k]; - if (portp == (stlport_t *) NULL) - continue; - if (portp->tty != (struct tty_struct *) NULL) - stl_hangup(portp->tty); - if (portp->tx.buf != (char *) NULL) - kfree(portp->tx.buf); - kfree(portp); - } - kfree(panelp); - } - - release_region(brdp->ioaddr1, brdp->iosize1); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); - - kfree(brdp); - stl_brds[i] = (stlbrd_t *) NULL; - } - - for (i = 0; (i < stl_numintrs); i++) - free_irq(stl_gotintrs[i], NULL); - - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Check for any arguments passed in on the module load command line. - */ - -static void stl_argbrds() -{ - stlconf_t conf; - stlbrd_t *brdp; - int nrargs, i; - -#if DEBUG - printk("stl_argbrds()\n"); -#endif - - nrargs = sizeof(stl_brdsp) / sizeof(char **); - - for (i = stl_nrbrds; (i < nrargs); i++) { - memset(&conf, 0, sizeof(conf)); - if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) - continue; - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - continue; - stl_nrbrds = i + 1; - brdp->brdnr = i; - brdp->brdtype = conf.brdtype; - brdp->ioaddr1 = conf.ioaddr1; - brdp->ioaddr2 = conf.ioaddr2; - brdp->irq = conf.irq; - brdp->irqtype = conf.irqtype; - stl_brdinit(brdp); - } -} - -/*****************************************************************************/ - -/* - * Convert an ascii string number into an unsigned long. - */ - -static unsigned long stl_atol(char *str) -{ - unsigned long val; - int base, c; - char *sp; - - val = 0; - sp = str; - if ((*sp == '0') && (*(sp+1) == 'x')) { - base = 16; - sp += 2; - } else if (*sp == '0') { - base = 8; - sp++; - } else { - base = 10; - } - - for (; (*sp != 0); sp++) { - c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); - if ((c < 0) || (c >= base)) { - printk("STALLION: invalid argument %s\n", str); - val = 0; - break; - } - val = (val * base) + c; - } - return(val); -} - -/*****************************************************************************/ - -/* - * Parse the supplied argument string, into the board conf struct. - */ - -static int stl_parsebrd(stlconf_t *confp, char **argp) -{ - char *sp; - int nrbrdnames, i; - -#if DEBUG - printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp); -#endif - - if ((argp[0] == (char *) NULL) || (*argp[0] == 0)) - return(0); - - for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) - *sp = TOLOWER(*sp); - - nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t); - for (i = 0; (i < nrbrdnames); i++) { - if (strcmp(stl_brdstr[i].name, argp[0]) == 0) - break; - } - if (i >= nrbrdnames) { - printk("STALLION: unknown board name, %s?\n", argp[0]); - return(0); - } - - confp->brdtype = stl_brdstr[i].type; - - i = 1; - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->ioaddr1 = stl_atol(argp[i]); - i++; - if (confp->brdtype == BRD_ECH) { - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->ioaddr2 = stl_atol(argp[i]); - i++; - } - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->irq = stl_atol(argp[i]); - return(1); -} - -#endif - -/*****************************************************************************/ - -/* - * Local driver kernel memory allocation routine. - */ - -static void *stl_memalloc(int len) -{ - return((void *) kmalloc(len, GFP_KERNEL)); -} - -/*****************************************************************************/ - -/* - * Allocate a new board structure. Fill out the basic info in it. - */ - -static stlbrd_t *stl_allocbrd() -{ - stlbrd_t *brdp; - - brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t)); - if (brdp == (stlbrd_t *) NULL) { - printk("STALLION: failed to allocate memory (size=%d)\n", - sizeof(stlbrd_t)); - return((stlbrd_t *) NULL); - } - - memset(brdp, 0, sizeof(stlbrd_t)); - brdp->magic = STL_BOARDMAGIC; - return(brdp); -} - -/*****************************************************************************/ - -static int stl_open(struct tty_struct *tty, struct file *filp) -{ - stlport_t *portp; - stlbrd_t *brdp; - unsigned int minordev; - int brdnr, panelnr, portnr, rc; - -#if DEBUG - printk("stl_open(tty=%x,filp=%x): device=%x\n", (int) tty, - (int) filp, tty->device); -#endif - - minordev = MINOR(tty->device); - brdnr = MINOR2BRD(minordev); - if (brdnr >= stl_nrbrds) - return(-ENODEV); - brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) - return(-ENODEV); - minordev = MINOR2PORT(minordev); - for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) { - if (brdp->panels[panelnr] == (stlpanel_t *) NULL) - break; - if (minordev < brdp->panels[panelnr]->nrports) { - portnr = minordev; - break; - } - minordev -= brdp->panels[panelnr]->nrports; - } - if (portnr < 0) - return(-ENODEV); - - portp = brdp->panels[panelnr]->ports[portnr]; - if (portp == (stlport_t *) NULL) - return(-ENODEV); - - MOD_INC_USE_COUNT; - -/* - * On the first open of the device setup the port hardware, and - * initialize the per port data structure. - */ - portp->tty = tty; - tty->driver_data = portp; - portp->refcount++; - - if ((portp->flags & ASYNC_INITIALIZED) == 0) { - if (portp->tx.buf == (char *) NULL) { - portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE); - if (portp->tx.buf == (char *) NULL) - return(-ENOMEM); - portp->tx.head = portp->tx.buf; - portp->tx.tail = portp->tx.buf; - } - stl_setport(portp, tty->termios); - portp->sigs = stl_getsignals(portp); - stl_setsignals(portp, 1, 1); - stl_enablerxtx(portp, 1, 1); - stl_startrxtx(portp, 1, 0); - clear_bit(TTY_IO_ERROR, &tty->flags); - portp->flags |= ASYNC_INITIALIZED; - } - -/* - * Check if this port is in the middle of closing. If so then wait - * until it is closed then return error status, based on flag settings. - * The sleep here does not need interrupt protection since the wakeup - * for it is done with the same context. - */ - if (portp->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&portp->close_wait); - if (portp->flags & ASYNC_HUP_NOTIFY) - return(-EAGAIN); - return(-ERESTARTSYS); - } - -/* - * Based on type of open being done check if it can overlap with any - * previous opens still in effect. If we are a normal serial device - * then also we might have to wait for carrier. - */ - if (tty->driver.subtype == STL_DRVTYPCALLOUT) { - if (portp->flags & ASYNC_NORMAL_ACTIVE) - return(-EBUSY); - if (portp->flags & ASYNC_CALLOUT_ACTIVE) { - if ((portp->flags & ASYNC_SESSION_LOCKOUT) && - (portp->session != current->session)) - return(-EBUSY); - if ((portp->flags & ASYNC_PGRP_LOCKOUT) && - (portp->pgrp != current->pgrp)) - return(-EBUSY); - } - portp->flags |= ASYNC_CALLOUT_ACTIVE; - } else { - if (filp->f_flags & O_NONBLOCK) { - if (portp->flags & ASYNC_CALLOUT_ACTIVE) - return(-EBUSY); - } else { - if ((rc = stl_waitcarrier(portp, filp)) != 0) - return(rc); - } - portp->flags |= ASYNC_NORMAL_ACTIVE; - } - - if ((portp->refcount == 1) && (portp->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == STL_DRVTYPSERIAL) - *tty->termios = portp->normaltermios; - else - *tty->termios = portp->callouttermios; - stl_setport(portp, tty->termios); - } - - portp->session = current->session; - portp->pgrp = current->pgrp; - return(0); -} - -/*****************************************************************************/ - -/* - * Possibly need to wait for carrier (DCD signal) to come high. Say - * maybe because if we are clocal then we don't need to wait... - */ - -static int stl_waitcarrier(stlport_t *portp, struct file *filp) -{ - unsigned long flags; - int rc, doclocal; - -#if DEBUG - printk("stl_waitcarrier(portp=%x,filp=%x)\n", (int) portp, (int) filp); -#endif - - rc = 0; - doclocal = 0; - - if (portp->flags & ASYNC_CALLOUT_ACTIVE) { - if (portp->normaltermios.c_cflag & CLOCAL) - doclocal++; - } else { - if (portp->tty->termios->c_cflag & CLOCAL) - doclocal++; - } - - save_flags(flags); - cli(); - portp->openwaitcnt++; - if (! tty_hung_up_p(filp)) - portp->refcount--; - - for (;;) { - if ((portp->flags & ASYNC_CALLOUT_ACTIVE) == 0) - stl_setsignals(portp, 1, 1); - if (tty_hung_up_p(filp) || - ((portp->flags & ASYNC_INITIALIZED) == 0)) { - if (portp->flags & ASYNC_HUP_NOTIFY) - rc = -EBUSY; - else - rc = -ERESTARTSYS; - break; - } - if (((portp->flags & ASYNC_CALLOUT_ACTIVE) == 0) && - ((portp->flags & ASYNC_CLOSING) == 0) && - (doclocal || (portp->sigs & TIOCM_CD))) { - break; - } - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - interruptible_sleep_on(&portp->open_wait); - } - - if (! tty_hung_up_p(filp)) - portp->refcount++; - portp->openwaitcnt--; - restore_flags(flags); - - return(rc); -} - -/*****************************************************************************/ - -static void stl_close(struct tty_struct *tty, struct file *filp) -{ - stlport_t *portp; - unsigned long flags; - -#if DEBUG - printk("stl_close(tty=%x,filp=%x)\n", (int) tty, (int) filp); -#endif - - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - save_flags(flags); - cli(); - if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - if ((tty->count == 1) && (portp->refcount != 1)) - portp->refcount = 1; - if (portp->refcount-- > 1) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - - portp->refcount = 0; - portp->flags |= ASYNC_CLOSING; - - if (portp->flags & ASYNC_NORMAL_ACTIVE) - portp->normaltermios = *tty->termios; - if (portp->flags & ASYNC_CALLOUT_ACTIVE) - portp->callouttermios = *tty->termios; - -/* - * May want to wait for any data to drain before closing. The BUSY - * flag keeps track of whether we are still sending or not - it is - * very accurate for the cd1400, not quite so for the sc26198. - * (The sc26198 has no "end-of-data" interrupt only empty FIFO) - */ - tty->closing = 1; - if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, portp->closing_wait); - stl_waituntilsent(tty, (HZ / 2)); - - portp->flags &= ~ASYNC_INITIALIZED; - stl_disableintrs(portp); - if (tty->termios->c_cflag & HUPCL) - stl_setsignals(portp, 0, 0); - stl_enablerxtx(portp, 0, 0); - stl_flushbuffer(tty); - portp->istate = 0; - if (portp->tx.buf != (char *) NULL) { - kfree(portp->tx.buf); - portp->tx.buf = (char *) NULL; - portp->tx.head = (char *) NULL; - portp->tx.tail = (char *) NULL; - } - set_bit(TTY_IO_ERROR, &tty->flags); - if (tty->ldisc.flush_buffer) - (tty->ldisc.flush_buffer)(tty); - - tty->closing = 0; - portp->tty = (struct tty_struct *) NULL; - - if (portp->openwaitcnt) { - if (portp->close_delay) - stl_delay(portp->close_delay); - wake_up_interruptible(&portp->open_wait); - } - - portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE | - ASYNC_CLOSING); - wake_up_interruptible(&portp->close_wait); - MOD_DEC_USE_COUNT; - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Wait for a specified delay period, this is not a busy-loop. It will - * give up the processor while waiting. Unfortunately this has some - * rather intimate knowledge of the process management stuff. - */ - -static void stl_delay(int len) -{ -#if DEBUG - printk("stl_delay(len=%d)\n", len); -#endif - if (len > 0) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(len); - current->state = TASK_RUNNING; - } -} - -/*****************************************************************************/ - -/* - * Write routine. Take data and stuff it in to the TX ring queue. - * If transmit interrupts are not running then start them. - */ - -static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) -{ - stlport_t *portp; - unsigned int len, stlen; - unsigned char *chbuf; - char *head, *tail; - -#if DEBUG - printk("stl_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - (int) tty, from_user, (int) buf, count); -#endif - - if ((tty == (struct tty_struct *) NULL) || - (stl_tmpwritebuf == (char *) NULL)) - return(0); - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return(0); - if (portp->tx.buf == (char *) NULL) - return(0); - -/* - * If copying direct from user space we must cater for page faults, - * causing us to "sleep" here for a while. To handle this copy in all - * the data we need now, into a local buffer. Then when we got it all - * copy it into the TX buffer. - */ - chbuf = (unsigned char *) buf; - if (from_user) { - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : - (tail - head - 1); - count = MIN(len, count); - - down(&stl_tmpwritesem); - copy_from_user(stl_tmpwritebuf, chbuf, count); - chbuf = &stl_tmpwritebuf[0]; - } - - head = portp->tx.head; - tail = portp->tx.tail; - if (head >= tail) { - len = STL_TXBUFSIZE - (head - tail) - 1; - stlen = STL_TXBUFSIZE - (head - portp->tx.buf); - } else { - len = tail - head - 1; - stlen = len; - } - - len = MIN(len, count); - count = 0; - while (len > 0) { - stlen = MIN(len, stlen); - memcpy(head, chbuf, stlen); - len -= stlen; - chbuf += stlen; - count += stlen; - head += stlen; - if (head >= (portp->tx.buf + STL_TXBUFSIZE)) { - head = portp->tx.buf; - stlen = tail - head; - } - } - portp->tx.head = head; - - clear_bit(ASYI_TXLOW, &portp->istate); - stl_startrxtx(portp, -1, 1); - - if (from_user) - up(&stl_tmpwritesem); - - return(count); -} - -/*****************************************************************************/ - -static void stl_putchar(struct tty_struct *tty, unsigned char ch) -{ - stlport_t *portp; - unsigned int len; - char *head, *tail; - -#if DEBUG - printk("stl_putchar(tty=%x,ch=%x)\n", (int) tty, (int) ch); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - if (portp->tx.buf == (char *) NULL) - return; - - head = portp->tx.head; - tail = portp->tx.tail; - - len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head); - len--; - - if (len > 0) { - *head++ = ch; - if (head >= (portp->tx.buf + STL_TXBUFSIZE)) - head = portp->tx.buf; - } - portp->tx.head = head; -} - -/*****************************************************************************/ - -/* - * If there are any characters in the buffer then make sure that TX - * interrupts are on and get'em out. Normally used after the putchar - * routine has been called. - */ - -static void stl_flushchars(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_flushchars(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - if (portp->tx.buf == (char *) NULL) - return; - -#if 0 - if (tty->stopped || tty->hw_stopped || - (portp->tx.head == portp->tx.tail)) - return; -#endif - stl_startrxtx(portp, -1, 1); -} - -/*****************************************************************************/ - -static int stl_writeroom(struct tty_struct *tty) -{ - stlport_t *portp; - char *head, *tail; - -#if DEBUG - printk("stl_writeroom(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return(0); - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return(0); - if (portp->tx.buf == (char *) NULL) - return(0); - - head = portp->tx.head; - tail = portp->tx.tail; - return((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1)); -} - -/*****************************************************************************/ - -/* - * Return number of chars in the TX buffer. Normally we would just - * calculate the number of chars in the buffer and return that, but if - * the buffer is empty and TX interrupts are still on then we return - * that the buffer still has 1 char in it. This way whoever called us - * will not think that ALL chars have drained - since the UART still - * must have some chars in it (we are busy after all). - */ - -static int stl_charsinbuffer(struct tty_struct *tty) -{ - stlport_t *portp; - unsigned int size; - char *head, *tail; - -#if DEBUG - printk("stl_charsinbuffer(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return(0); - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return(0); - if (portp->tx.buf == (char *) NULL) - return(0); - - head = portp->tx.head; - tail = portp->tx.tail; - size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); - if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate)) - size = 1; - return(size); -} - -/*****************************************************************************/ - -/* - * Generate the serial struct info. - */ - -static void stl_getserial(stlport_t *portp, struct serial_struct *sp) -{ - struct serial_struct sio; - stlbrd_t *brdp; - -#if DEBUG - printk("stl_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); -#endif - - memset(&sio, 0, sizeof(struct serial_struct)); - sio.line = portp->portnr; - sio.port = portp->ioaddr; - sio.flags = portp->flags; - sio.baud_base = portp->baud_base; - sio.close_delay = portp->close_delay; - sio.closing_wait = portp->closing_wait; - sio.custom_divisor = portp->custom_divisor; - sio.hub6 = 0; - if (portp->uartp == &stl_cd1400uart) { - sio.type = PORT_CIRRUS; - sio.xmit_fifo_size = CD1400_TXFIFOSIZE; - } else { - sio.type = PORT_UNKNOWN; - sio.xmit_fifo_size = SC26198_TXFIFOSIZE; - } - - brdp = stl_brds[portp->brdnr]; - if (brdp != (stlbrd_t *) NULL) - sio.irq = brdp->irq; - - copy_to_user(sp, &sio, sizeof(struct serial_struct)); -} - -/*****************************************************************************/ - -/* - * Set port according to the serial struct info. - * At this point we do not do any auto-configure stuff, so we will - * just quietly ignore any requests to change irq, etc. - */ - -static int stl_setserial(stlport_t *portp, struct serial_struct *sp) -{ - struct serial_struct sio; - -#if DEBUG - printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); -#endif - - copy_from_user(&sio, sp, sizeof(struct serial_struct)); - if (!capable(CAP_SYS_ADMIN)) { - if ((sio.baud_base != portp->baud_base) || - (sio.close_delay != portp->close_delay) || - ((sio.flags & ~ASYNC_USR_MASK) != - (portp->flags & ~ASYNC_USR_MASK))) - return(-EPERM); - } - - portp->flags = (portp->flags & ~ASYNC_USR_MASK) | - (sio.flags & ASYNC_USR_MASK); - portp->baud_base = sio.baud_base; - portp->close_delay = sio.close_delay; - portp->closing_wait = sio.closing_wait; - portp->custom_divisor = sio.custom_divisor; - stl_setport(portp, portp->tty->termios); - return(0); -} - -/*****************************************************************************/ - -static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) -{ - stlport_t *portp; - unsigned int ival; - int rc; - -#if DEBUG - printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n", - (int) tty, (int) file, cmd, (int) arg); -#endif - - if (tty == (struct tty_struct *) NULL) - return(-ENODEV); - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return(-ENODEV); - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return(-EIO); - } - - rc = 0; - - switch (cmd) { - case TIOCGSOFTCAR: - rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), - (unsigned int *) arg); - break; - case TIOCSSOFTCAR: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(int))) == 0) { - get_user(ival, (unsigned int *) arg); - tty->termios->c_cflag = - (tty->termios->c_cflag & ~CLOCAL) | - (ival ? CLOCAL : 0); - } - break; - case TIOCMGET: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) == 0) { - ival = stl_getsignals(portp); - put_user(ival, (unsigned int *) arg); - } - break; - case TIOCMBIS: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : -1), - ((ival & TIOCM_RTS) ? 1 : -1)); - } - break; - case TIOCMBIC: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 0 : -1), - ((ival & TIOCM_RTS) ? 0 : -1)); - } - break; - case TIOCMSET: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : 0), - ((ival & TIOCM_RTS) ? 1 : 0)); - } - break; - case TIOCGSERIAL: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct))) == 0) - stl_getserial(portp, (struct serial_struct *) arg); - break; - case TIOCSSERIAL: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(struct serial_struct))) == 0) - rc = stl_setserial(portp, (struct serial_struct *) arg); - break; - case COM_GETPORTSTATS: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(comstats_t))) == 0) - rc = stl_getportstats(portp, (comstats_t *) arg); - break; - case COM_CLRPORTSTATS: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(comstats_t))) == 0) - rc = stl_clrportstats(portp, (comstats_t *) arg); - break; - case TIOCSERCONFIG: - case TIOCSERGWILD: - case TIOCSERSWILD: - case TIOCSERGETLSR: - case TIOCSERGSTRUCT: - case TIOCSERGETMULTI: - case TIOCSERSETMULTI: - default: - rc = -ENOIOCTLCMD; - break; - } - - return(rc); -} - -/*****************************************************************************/ - -static void stl_settermios(struct tty_struct *tty, struct termios *old) -{ - stlport_t *portp; - struct termios *tiosp; - -#if DEBUG - printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - tiosp = tty->termios; - if ((tiosp->c_cflag == old->c_cflag) && - (tiosp->c_iflag == old->c_iflag)) - return; - - stl_setport(portp, tiosp); - stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0), - -1); - if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) { - tty->hw_stopped = 0; - stl_start(tty); - } - if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL)) - wake_up_interruptible(&portp->open_wait); -} - -/*****************************************************************************/ - -/* - * Attempt to flow control who ever is sending us data. Based on termios - * settings use software or/and hardware flow control. - */ - -static void stl_throttle(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_throttle(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - stl_flowctrl(portp, 0); -} - -/*****************************************************************************/ - -/* - * Unflow control the device sending us data... - */ - -static void stl_unthrottle(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_unthrottle(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - stl_flowctrl(portp, 1); -} - -/*****************************************************************************/ - -/* - * Stop the transmitter. Basically to do this we will just turn TX - * interrupts off. - */ - -static void stl_stop(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_stop(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - stl_startrxtx(portp, -1, 0); -} - -/*****************************************************************************/ - -/* - * Start the transmitter again. Just turn TX interrupts back on. - */ - -static void stl_start(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_start(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - stl_startrxtx(portp, -1, 1); -} - -/*****************************************************************************/ - -/* - * Hangup this port. This is pretty much like closing the port, only - * a little more brutal. No waiting for data to drain. Shutdown the - * port and maybe drop signals. - */ - -static void stl_hangup(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_hangup(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - portp->flags &= ~ASYNC_INITIALIZED; - stl_disableintrs(portp); - if (tty->termios->c_cflag & HUPCL) - stl_setsignals(portp, 0, 0); - stl_enablerxtx(portp, 0, 0); - stl_flushbuffer(tty); - portp->istate = 0; - set_bit(TTY_IO_ERROR, &tty->flags); - if (portp->tx.buf != (char *) NULL) { - kfree(portp->tx.buf); - portp->tx.buf = (char *) NULL; - portp->tx.head = (char *) NULL; - portp->tx.tail = (char *) NULL; - } - portp->tty = (struct tty_struct *) NULL; - portp->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); - portp->refcount = 0; - wake_up_interruptible(&portp->open_wait); -} - -/*****************************************************************************/ - -static void stl_flushbuffer(struct tty_struct *tty) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_flushbuffer(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - stl_flush(portp); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/*****************************************************************************/ - -static void stl_breakctl(struct tty_struct *tty, int state) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - stl_sendbreak(portp, ((state == -1) ? 1 : 2)); -} - -/*****************************************************************************/ - -static void stl_waituntilsent(struct tty_struct *tty, int timeout) -{ - stlport_t *portp; - unsigned long tend; - -#if DEBUG - printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - if (timeout == 0) - timeout = HZ; - tend = jiffies + timeout; - - while (stl_datastate(portp)) { - if (signal_pending(current)) - break; - stl_delay(2); - if (time_after_eq(jiffies, tend)) - break; - } -} - -/*****************************************************************************/ - -static void stl_sendxchar(struct tty_struct *tty, char ch) -{ - stlport_t *portp; - -#if DEBUG - printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - if (ch == STOP_CHAR(tty)) - stl_sendflow(portp, 0); - else if (ch == START_CHAR(tty)) - stl_sendflow(portp, 1); - else - stl_putchar(tty, ch); -} - -/*****************************************************************************/ - -#define MAXLINE 80 - -/* - * Format info for a specified port. The line is deliberately limited - * to 80 characters. (If it is too long it will be truncated, if too - * short then padded with spaces). - */ - -static int stl_portinfo(stlport_t *portp, int portnr, char *pos) -{ - char *sp; - int sigs, cnt; - - sp = pos; - sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d", - portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", - (int) portp->stats.txtotal, (int) portp->stats.rxtotal); - - if (portp->stats.rxframing) - sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing); - if (portp->stats.rxparity) - sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity); - if (portp->stats.rxbreaks) - sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks); - if (portp->stats.rxoverrun) - sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun); - - sigs = stl_getsignals(portp); - cnt = sprintf(sp, "%s%s%s%s%s ", - (sigs & TIOCM_RTS) ? "|RTS" : "", - (sigs & TIOCM_CTS) ? "|CTS" : "", - (sigs & TIOCM_DTR) ? "|DTR" : "", - (sigs & TIOCM_CD) ? "|DCD" : "", - (sigs & TIOCM_DSR) ? "|DSR" : ""); - *sp = ' '; - sp += cnt; - - for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++) - *sp++ = ' '; - if (cnt >= MAXLINE) - pos[(MAXLINE - 2)] = '+'; - pos[(MAXLINE - 1)] = '\n'; - - return(MAXLINE); -} - -/*****************************************************************************/ - -/* - * Port info, read from the /proc file system. - */ - -static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - stlbrd_t *brdp; - stlpanel_t *panelp; - stlport_t *portp; - int brdnr, panelnr, portnr, totalport; - int curoff, maxoff; - char *pos; - -#if DEBUG - printk("stl_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x," - "data=%x\n", (int) page, (int) start, (int) off, count, - (int) eof, (int) data); -#endif - - pos = page; - totalport = 0; - curoff = 0; - - if (off == 0) { - pos += sprintf(pos, "%s: version %s", stl_drvtitle, - stl_drvversion); - while (pos < (page + MAXLINE - 1)) - *pos++ = ' '; - *pos++ = '\n'; - } - curoff = MAXLINE; - -/* - * We scan through for each board, panel and port. The offset is - * calculated on the fly, and irrelevant ports are skipped. - */ - for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) { - brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) - continue; - if (brdp->state == 0) - continue; - - maxoff = curoff + (brdp->nrports * MAXLINE); - if (off >= maxoff) { - curoff = maxoff; - continue; - } - - totalport = brdnr * STL_MAXPORTS; - for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) { - panelp = brdp->panels[panelnr]; - if (panelp == (stlpanel_t *) NULL) - continue; - - maxoff = curoff + (panelp->nrports * MAXLINE); - if (off >= maxoff) { - curoff = maxoff; - totalport += panelp->nrports; - continue; - } - - for (portnr = 0; (portnr < panelp->nrports); portnr++, - totalport++) { - portp = panelp->ports[portnr]; - if (portp == (stlport_t *) NULL) - continue; - if (off >= (curoff += MAXLINE)) - continue; - if ((pos - page + MAXLINE) > count) - goto stl_readdone; - pos += stl_portinfo(portp, totalport, pos); - } - } - } - - *eof = 1; - -stl_readdone: - *start = page; - return(pos - page); -} - -/*****************************************************************************/ - -/* - * All board interrupts are vectored through here first. This code then - * calls off to the approrpriate board interrupt handlers. - */ - -static void stl_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - stlbrd_t *brdp; - int i; - -#if DEBUG - printk("stl_intr(irq=%d,regs=%x)\n", irq, (int) regs); -#endif - - for (i = 0; (i < stl_nrbrds); i++) { - if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) - continue; - if (brdp->state == 0) - continue; - (* brdp->isr)(brdp); - } -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for EasyIO board types. - */ - -static void stl_eiointr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int iobase; - - panelp = brdp->panels[0]; - iobase = panelp->iobase; - while (inb(brdp->iostatus) & EIO_INTRPEND) - (* panelp->isr)(panelp, iobase); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-AT board types. - */ - -static void stl_echatintr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; - - outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); - - while (inb(brdp->iostatus) & ECH_INTRPEND) { - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } - - outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-MCA board types. - */ - -static void stl_echmcaintr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; - - while (inb(brdp->iostatus) & ECH_INTRPEND) { - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-PCI board types. - */ - -static void stl_echpciintr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr, recheck; - - while (1) { - recheck = 0; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl); - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - recheck++; - } - } - if (! recheck) - break; - } -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-8/64-PCI board types. - */ - -static void stl_echpci64intr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; - - while (inb(brdp->ioctrl) & 0x1) { - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } -} - -/*****************************************************************************/ - -/* - * Service an off-level request for some channel. - */ -static void stl_offintr(void *private) -{ - stlport_t *portp; - struct tty_struct *tty; - unsigned int oldsigs; - - portp = private; - -#if DEBUG - printk("stl_offintr(portp=%x)\n", (int) portp); -#endif - - if (portp == (stlport_t *) NULL) - return; - - tty = portp->tty; - if (tty == (struct tty_struct *) NULL) - return; - - lock_kernel(); - if (test_bit(ASYI_TXLOW, &portp->istate)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); - } - if (test_bit(ASYI_DCDCHANGE, &portp->istate)) { - clear_bit(ASYI_DCDCHANGE, &portp->istate); - oldsigs = portp->sigs; - portp->sigs = stl_getsignals(portp); - if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) - wake_up_interruptible(&portp->open_wait); - if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) { - if (portp->flags & ASYNC_CHECK_CD) { - if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) && - (portp->flags & ASYNC_CALLOUT_NOHUP))) { - tty_hangup(tty); - } - } - } - } - unlock_kernel(); -} - -/*****************************************************************************/ - -/* - * Map in interrupt vector to this driver. Check that we don't - * already have this vector mapped, we might be sharing this - * interrupt across multiple boards. - */ - -static int __init stl_mapirq(int irq, char *name) -{ - int rc, i; - -#if DEBUG - printk("stl_mapirq(irq=%d,name=%s)\n", irq, name); -#endif - - rc = 0; - for (i = 0; (i < stl_numintrs); i++) { - if (stl_gotintrs[i] == irq) - break; - } - if (i >= stl_numintrs) { - if (request_irq(irq, stl_intr, SA_SHIRQ, name, NULL) != 0) { - printk("STALLION: failed to register interrupt " - "routine for %s irq=%d\n", name, irq); - rc = -ENODEV; - } else { - stl_gotintrs[stl_numintrs++] = irq; - } - } - return(rc); -} - -/*****************************************************************************/ - -/* - * Initialize all the ports on a panel. - */ - -static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) -{ - stlport_t *portp; - int chipmask, i; - -#if DEBUG - printk("stl_initports(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); -#endif - - chipmask = stl_panelinit(brdp, panelp); - -/* - * All UART's are initialized (if found!). Now go through and setup - * each ports data structures. - */ - for (i = 0; (i < panelp->nrports); i++) { - portp = (stlport_t *) stl_memalloc(sizeof(stlport_t)); - if (portp == (stlport_t *) NULL) { - printk("STALLION: failed to allocate memory " - "(size=%d)\n", sizeof(stlport_t)); - break; - } - memset(portp, 0, sizeof(stlport_t)); - - portp->magic = STL_PORTMAGIC; - portp->portnr = i; - portp->brdnr = panelp->brdnr; - portp->panelnr = panelp->panelnr; - portp->uartp = panelp->uartp; - portp->clk = brdp->clk; - portp->baud_base = STL_BAUDBASE; - portp->close_delay = STL_CLOSEDELAY; - portp->closing_wait = 30 * HZ; - portp->normaltermios = stl_deftermios; - portp->callouttermios = stl_deftermios; - portp->tqueue.routine = stl_offintr; - portp->tqueue.data = portp; - init_waitqueue_head(&portp->open_wait); - init_waitqueue_head(&portp->close_wait); - portp->stats.brd = portp->brdnr; - portp->stats.panel = portp->panelnr; - portp->stats.port = portp->portnr; - panelp->ports[i] = portp; - stl_portinit(brdp, panelp, portp); - } - - return(0); -} - -/*****************************************************************************/ - -/* - * Try to find and initialize an EasyIO board. - */ - -static inline int stl_initeio(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int status; - char *name; - int rc; - -#if DEBUG - printk("stl_initeio(brdp=%x)\n", (int) brdp); -#endif - - brdp->ioctrl = brdp->ioaddr1 + 1; - brdp->iostatus = brdp->ioaddr1 + 2; - - status = inb(brdp->iostatus); - if ((status & EIO_IDBITMASK) == EIO_MK3) - brdp->ioctrl++; - -/* - * Handle board specific stuff now. The real difference is PCI - * or not PCI. - */ - if (brdp->brdtype == BRD_EASYIOPCI) { - brdp->iosize1 = 0x80; - brdp->iosize2 = 0x80; - name = "serial(EIO-PCI)"; - outb(0x41, (brdp->ioaddr2 + 0x4c)); - } else { - brdp->iosize1 = 8; - name = "serial(EIO)"; - if ((brdp->irq < 0) || (brdp->irq > 15) || - (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { - printk("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - return(-EINVAL); - } - outb((stl_vecmap[brdp->irq] | EIO_0WS | - ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), - brdp->ioctrl); - } - - if (check_region(brdp->ioaddr1, brdp->iosize1)) { - printk("STALLION: Warning, board %d I/O address %x conflicts " - "with another device\n", brdp->brdnr, brdp->ioaddr1); - } - if (brdp->iosize2 > 0) { - if (check_region(brdp->ioaddr2, brdp->iosize2)) { - printk("STALLION: Warning, board %d I/O address %x " - "conflicts with another device\n", - brdp->brdnr, brdp->ioaddr2); - } - } - -/* - * Everything looks OK, so let's go ahead and probe for the hardware. - */ - brdp->clk = CD1400_CLK; - brdp->isr = stl_eiointr; - - switch (status & EIO_IDBITMASK) { - case EIO_8PORTM: - brdp->clk = CD1400_CLK8M; - /* fall thru */ - case EIO_8PORTRS: - case EIO_8PORTDI: - brdp->nrports = 8; - break; - case EIO_4PORTRS: - brdp->nrports = 4; - break; - case EIO_MK3: - switch (status & EIO_BRDMASK) { - case ID_BRD4: - brdp->nrports = 4; - break; - case ID_BRD8: - brdp->nrports = 8; - break; - case ID_BRD16: - brdp->nrports = 16; - break; - default: - return(-ENODEV); - } - break; - default: - return(-ENODEV); - } - -/* - * We have verfied that the board is actually present, so now we - * can complete the setup. - */ - request_region(brdp->ioaddr1, brdp->iosize1, name); - if (brdp->iosize2 > 0) - request_region(brdp->ioaddr2, brdp->iosize2, name); - - panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); - if (panelp == (stlpanel_t *) NULL) { - printk("STALLION: failed to allocate memory (size=%d)\n", - sizeof(stlpanel_t)); - return(-ENOMEM); - } - memset(panelp, 0, sizeof(stlpanel_t)); - - panelp->magic = STL_PANELMAGIC; - panelp->brdnr = brdp->brdnr; - panelp->panelnr = 0; - panelp->nrports = brdp->nrports; - panelp->iobase = brdp->ioaddr1; - panelp->hwid = status; - if ((status & EIO_IDBITMASK) == EIO_MK3) { - panelp->uartp = (void *) &stl_sc26198uart; - panelp->isr = stl_sc26198intr; - } else { - panelp->uartp = (void *) &stl_cd1400uart; - panelp->isr = stl_cd1400eiointr; - } - - brdp->panels[0] = panelp; - brdp->nrpanels = 1; - brdp->state |= BRD_FOUND; - brdp->hwid = status; - rc = stl_mapirq(brdp->irq, name); - return(rc); -} - -/*****************************************************************************/ - -/* - * Try to find an ECH board and initialize it. This code is capable of - * dealing with all types of ECH board. - */ - -static int inline stl_initech(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int status, nxtid, ioaddr, conflict; - int panelnr, banknr, i; - char *name; - -#if DEBUG - printk("stl_initech(brdp=%x)\n", (int) brdp); -#endif - - status = 0; - conflict = 0; - -/* - * Set up the initial board register contents for boards. This varies a - * bit between the different board types. So we need to handle each - * separately. Also do a check that the supplied IRQ is good. - */ - switch (brdp->brdtype) { - - case BRD_ECH: - brdp->isr = stl_echatintr; - brdp->ioctrl = brdp->ioaddr1 + 1; - brdp->iostatus = brdp->ioaddr1 + 1; - status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) - return(-ENODEV); - if ((brdp->irq < 0) || (brdp->irq > 15) || - (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { - printk("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - return(-EINVAL); - } - status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); - status |= (stl_vecmap[brdp->irq] << 1); - outb((status | ECH_BRDRESET), brdp->ioaddr1); - brdp->ioctrlval = ECH_INTENABLE | - ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE); - for (i = 0; (i < 10); i++) - outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); - brdp->iosize1 = 2; - brdp->iosize2 = 32; - name = "serial(EC8/32)"; - outb(status, brdp->ioaddr1); - break; - - case BRD_ECHMC: - brdp->isr = stl_echmcaintr; - brdp->ioctrl = brdp->ioaddr1 + 0x20; - brdp->iostatus = brdp->ioctrl; - status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) - return(-ENODEV); - if ((brdp->irq < 0) || (brdp->irq > 15) || - (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { - printk("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - return(-EINVAL); - } - outb(ECHMC_BRDRESET, brdp->ioctrl); - outb(ECHMC_INTENABLE, brdp->ioctrl); - brdp->iosize1 = 64; - name = "serial(EC8/32-MC)"; - break; - - case BRD_ECHPCI: - brdp->isr = stl_echpciintr; - brdp->ioctrl = brdp->ioaddr1 + 2; - brdp->iosize1 = 4; - brdp->iosize2 = 8; - name = "serial(EC8/32-PCI)"; - break; - - case BRD_ECH64PCI: - brdp->isr = stl_echpci64intr; - brdp->ioctrl = brdp->ioaddr2 + 0x40; - outb(0x43, (brdp->ioaddr1 + 0x4c)); - brdp->iosize1 = 0x80; - brdp->iosize2 = 0x80; - name = "serial(EC8/64-PCI)"; - break; - - default: - printk("STALLION: unknown board type=%d\n", brdp->brdtype); - return(-EINVAL); - break; - } - -/* - * Check boards for possible IO address conflicts. We won't actually - * do anything about it here, just issue a warning... - */ - conflict = check_region(brdp->ioaddr1, brdp->iosize1) ? - brdp->ioaddr1 : 0; - if ((conflict == 0) && (brdp->iosize2 > 0)) - conflict = check_region(brdp->ioaddr2, brdp->iosize2) ? - brdp->ioaddr2 : 0; - if (conflict) { - printk("STALLION: Warning, board %d I/O address %x conflicts " - "with another device\n", brdp->brdnr, conflict); - } - - request_region(brdp->ioaddr1, brdp->iosize1, name); - if (brdp->iosize2 > 0) - request_region(brdp->ioaddr2, brdp->iosize2, name); - -/* - * Scan through the secondary io address space looking for panels. - * As we find'em allocate and initialize panel structures for each. - */ - brdp->clk = CD1400_CLK; - brdp->hwid = status; - - ioaddr = brdp->ioaddr2; - banknr = 0; - panelnr = 0; - nxtid = 0; - - for (i = 0; (i < STL_MAXPANELS); i++) { - if (brdp->brdtype == BRD_ECHPCI) { - outb(nxtid, brdp->ioctrl); - ioaddr = brdp->ioaddr2; - } - status = inb(ioaddr + ECH_PNLSTATUS); - if ((status & ECH_PNLIDMASK) != nxtid) - break; - panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); - if (panelp == (stlpanel_t *) NULL) { - printk("STALLION: failed to allocate memory " - "(size=%d)\n", sizeof(stlpanel_t)); - break; - } - memset(panelp, 0, sizeof(stlpanel_t)); - panelp->magic = STL_PANELMAGIC; - panelp->brdnr = brdp->brdnr; - panelp->panelnr = panelnr; - panelp->iobase = ioaddr; - panelp->pagenr = nxtid; - panelp->hwid = status; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; - - if (status & ECH_PNLXPID) { - panelp->uartp = (void *) &stl_sc26198uart; - panelp->isr = stl_sc26198intr; - if (status & ECH_PNL16PORT) { - panelp->nrports = 16; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + 4 + - ECH_PNLSTATUS; - } else { - panelp->nrports = 8; - } - } else { - panelp->uartp = (void *) &stl_cd1400uart; - panelp->isr = stl_cd1400echintr; - if (status & ECH_PNL16PORT) { - panelp->nrports = 16; - panelp->ackmask = 0x80; - if (brdp->brdtype != BRD_ECHPCI) - ioaddr += EREG_BANKSIZE; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = ++nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + - ECH_PNLSTATUS; - } else { - panelp->nrports = 8; - panelp->ackmask = 0xc0; - } - } - - nxtid++; - ioaddr += EREG_BANKSIZE; - brdp->nrports += panelp->nrports; - brdp->panels[panelnr++] = panelp; - if ((brdp->brdtype != BRD_ECHPCI) && - (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) - break; - } - - brdp->nrpanels = panelnr; - brdp->nrbnks = banknr; - if (brdp->brdtype == BRD_ECH) - outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl); - - brdp->state |= BRD_FOUND; - i = stl_mapirq(brdp->irq, name); - return(i); -} - -/*****************************************************************************/ - -/* - * Initialize and configure the specified board. - * Scan through all the boards in the configuration and see what we - * can find. Handle EIO and the ECH boards a little differently here - * since the initial search and setup is very different. - */ - -static int __init stl_brdinit(stlbrd_t *brdp) -{ - int i; - -#if DEBUG - printk("stl_brdinit(brdp=%x)\n", (int) brdp); -#endif - - switch (brdp->brdtype) { - case BRD_EASYIO: - case BRD_EASYIOPCI: - stl_initeio(brdp); - break; - case BRD_ECH: - case BRD_ECHMC: - case BRD_ECHPCI: - case BRD_ECH64PCI: - stl_initech(brdp); - break; - default: - printk("STALLION: board=%d is unknown board type=%d\n", - brdp->brdnr, brdp->brdtype); - return(ENODEV); - } - - stl_brds[brdp->brdnr] = brdp; - if ((brdp->state & BRD_FOUND) == 0) { - printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", - stl_brdnames[brdp->brdtype], brdp->brdnr, - brdp->ioaddr1, brdp->irq); - return(ENODEV); - } - - for (i = 0; (i < STL_MAXPANELS); i++) - if (brdp->panels[i] != (stlpanel_t *) NULL) - stl_initports(brdp, brdp->panels[i]); - - printk("STALLION: %s found, board=%d io=%x irq=%d " - "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], - brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, - brdp->nrports); - return(0); -} - -/*****************************************************************************/ - -/* - * Find the next available board number that is free. - */ - -static inline int stl_getbrdnr() -{ - int i; - - for (i = 0; (i < STL_MAXBRDS); i++) { - if (stl_brds[i] == (stlbrd_t *) NULL) { - if (i >= stl_nrbrds) - stl_nrbrds = i + 1; - return(i); - } - } - return(-1); -} - -/*****************************************************************************/ - -#ifdef CONFIG_PCI - -/* - * We have a Stallion board. Allocate a board structure and - * initialize it. Read its IO and IRQ resources from PCI - * configuration space. - */ - -static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp) -{ - stlbrd_t *brdp; - -#if DEBUG - printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype, - devp->bus->number, devp->devfn); -#endif - - if (pci_enable_device(devp)) - return(-EIO); - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - return(-ENOMEM); - if ((brdp->brdnr = stl_getbrdnr()) < 0) { - printk("STALLION: too many boards found, " - "maximum supported %d\n", STL_MAXBRDS); - return(0); - } - brdp->brdtype = brdtype; - -/* - * Different Stallion boards use the BAR registers in different ways, - * so set up io addresses based on board type. - */ -#if DEBUG - printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__, - pci_resource_start(devp, 0), pci_resource_start(devp, 1), - pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq); -#endif - -/* - * We have all resources from the board, so let's setup the actual - * board structure now. - */ - switch (brdtype) { - case BRD_ECHPCI: - brdp->ioaddr2 = pci_resource_start(devp, 0); - brdp->ioaddr1 = pci_resource_start(devp, 1); - break; - case BRD_ECH64PCI: - brdp->ioaddr2 = pci_resource_start(devp, 2); - brdp->ioaddr1 = pci_resource_start(devp, 1); - break; - case BRD_EASYIOPCI: - brdp->ioaddr1 = pci_resource_start(devp, 2); - brdp->ioaddr2 = pci_resource_start(devp, 1); - break; - default: - printk("STALLION: unknown PCI board type=%d\n", brdtype); - break; - } - - brdp->irq = devp->irq; - stl_brdinit(brdp); - - return(0); -} - -/*****************************************************************************/ - -/* - * Find all Stallion PCI boards that might be installed. Initialize each - * one as it is found. - */ - - -static inline int stl_findpcibrds() -{ - struct pci_dev *dev = NULL; - int i, rc; - -#if DEBUG - printk("stl_findpcibrds()\n"); -#endif - - if (! pci_present()) - return(0); - - for (i = 0; (i < stl_nrpcibrds); i++) - while ((dev = pci_find_device(stl_pcibrds[i].vendid, - stl_pcibrds[i].devid, dev))) { - -/* - * Found a device on the PCI bus that has our vendor and - * device ID. Need to check now that it is really us. - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) - continue; - - rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev); - if (rc) - return(rc); - } - - return(0); -} - -#endif - -/*****************************************************************************/ - -/* - * Scan through all the boards in the configuration and see what we - * can find. Handle EIO and the ECH boards a little differently here - * since the initial search and setup is too different. - */ - -static inline int stl_initbrds() -{ - stlbrd_t *brdp; - stlconf_t *confp; - int i; - -#if DEBUG - printk("stl_initbrds()\n"); -#endif - - if (stl_nrbrds > STL_MAXBRDS) { - printk("STALLION: too many boards in configuration table, " - "truncating to %d\n", STL_MAXBRDS); - stl_nrbrds = STL_MAXBRDS; - } - -/* - * Firstly scan the list of static boards configured. Allocate - * resources and initialize the boards as found. - */ - for (i = 0; (i < stl_nrbrds); i++) { - confp = &stl_brdconf[i]; -#ifdef MODULE - stl_parsebrd(confp, stl_brdsp[i]); -#endif - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - return(-ENOMEM); - brdp->brdnr = i; - brdp->brdtype = confp->brdtype; - brdp->ioaddr1 = confp->ioaddr1; - brdp->ioaddr2 = confp->ioaddr2; - brdp->irq = confp->irq; - brdp->irqtype = confp->irqtype; - stl_brdinit(brdp); - } - -/* - * Find any dynamically supported boards. That is via module load - * line options or auto-detected on the PCI bus. - */ -#ifdef MODULE - stl_argbrds(); -#endif -#ifdef CONFIG_PCI - stl_findpcibrds(); -#endif - - return(0); -} - -/*****************************************************************************/ - -/* - * Return the board stats structure to user app. - */ - -static int stl_getbrdstats(combrd_t *bp) -{ - stlbrd_t *brdp; - stlpanel_t *panelp; - int i; - - copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)); - if (stl_brdstats.brd >= STL_MAXBRDS) - return(-ENODEV); - brdp = stl_brds[stl_brdstats.brd]; - if (brdp == (stlbrd_t *) NULL) - return(-ENODEV); - - memset(&stl_brdstats, 0, sizeof(combrd_t)); - stl_brdstats.brd = brdp->brdnr; - stl_brdstats.type = brdp->brdtype; - stl_brdstats.hwid = brdp->hwid; - stl_brdstats.state = brdp->state; - stl_brdstats.ioaddr = brdp->ioaddr1; - stl_brdstats.ioaddr2 = brdp->ioaddr2; - stl_brdstats.irq = brdp->irq; - stl_brdstats.nrpanels = brdp->nrpanels; - stl_brdstats.nrports = brdp->nrports; - for (i = 0; (i < brdp->nrpanels); i++) { - panelp = brdp->panels[i]; - stl_brdstats.panels[i].panel = i; - stl_brdstats.panels[i].hwid = panelp->hwid; - stl_brdstats.panels[i].nrports = panelp->nrports; - } - - copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)); - return(0); -} - -/*****************************************************************************/ - -/* - * Resolve the referenced port number into a port struct pointer. - */ - -static stlport_t *stl_getport(int brdnr, int panelnr, int portnr) -{ - stlbrd_t *brdp; - stlpanel_t *panelp; - - if ((brdnr < 0) || (brdnr >= STL_MAXBRDS)) - return((stlport_t *) NULL); - brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) - return((stlport_t *) NULL); - if ((panelnr < 0) || (panelnr >= brdp->nrpanels)) - return((stlport_t *) NULL); - panelp = brdp->panels[panelnr]; - if (panelp == (stlpanel_t *) NULL) - return((stlport_t *) NULL); - if ((portnr < 0) || (portnr >= panelp->nrports)) - return((stlport_t *) NULL); - return(panelp->ports[portnr]); -} - -/*****************************************************************************/ - -/* - * Return the port stats structure to user app. A NULL port struct - * pointer passed in means that we need to find out from the app - * what port to get stats for (used through board control device). - */ - -static int stl_getportstats(stlport_t *portp, comstats_t *cp) -{ - unsigned char *head, *tail; - unsigned long flags; - - if (portp == (stlport_t *) NULL) { - copy_from_user(&stl_comstats, cp, sizeof(comstats_t)); - portp = stl_getport(stl_comstats.brd, stl_comstats.panel, - stl_comstats.port); - if (portp == (stlport_t *) NULL) - return(-ENODEV); - } - - portp->stats.state = portp->istate; - portp->stats.flags = portp->flags; - portp->stats.hwid = portp->hwid; - - portp->stats.ttystate = 0; - portp->stats.cflags = 0; - portp->stats.iflags = 0; - portp->stats.oflags = 0; - portp->stats.lflags = 0; - portp->stats.rxbuffered = 0; - - save_flags(flags); - cli(); - 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; - if (portp->tty->termios != (struct termios *) NULL) { - portp->stats.cflags = portp->tty->termios->c_cflag; - portp->stats.iflags = portp->tty->termios->c_iflag; - portp->stats.oflags = portp->tty->termios->c_oflag; - portp->stats.lflags = portp->tty->termios->c_lflag; - } - } - } - restore_flags(flags); - - head = portp->tx.head; - tail = portp->tx.tail; - portp->stats.txbuffered = ((head >= tail) ? (head - tail) : - (STL_TXBUFSIZE - (tail - head))); - - portp->stats.signals = (unsigned long) stl_getsignals(portp); - - copy_to_user(cp, &portp->stats, sizeof(comstats_t)); - return(0); -} - -/*****************************************************************************/ - -/* - * Clear the port stats structure. We also return it zeroed out... - */ - -static int stl_clrportstats(stlport_t *portp, comstats_t *cp) -{ - if (portp == (stlport_t *) NULL) { - copy_from_user(&stl_comstats, cp, sizeof(comstats_t)); - portp = stl_getport(stl_comstats.brd, stl_comstats.panel, - stl_comstats.port); - if (portp == (stlport_t *) NULL) - return(-ENODEV); - } - - memset(&portp->stats, 0, sizeof(comstats_t)); - portp->stats.brd = portp->brdnr; - portp->stats.panel = portp->panelnr; - portp->stats.port = portp->portnr; - copy_to_user(cp, &portp->stats, sizeof(comstats_t)); - return(0); -} - -/*****************************************************************************/ - -/* - * Return the entire driver ports structure to a user app. - */ - -static int stl_getportstruct(unsigned long arg) -{ - stlport_t *portp; - - copy_from_user(&stl_dummyport, (void *) arg, sizeof(stlport_t)); - portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, - stl_dummyport.portnr); - if (portp == (stlport_t *) NULL) - return(-ENODEV); - copy_to_user((void *) arg, portp, sizeof(stlport_t)); - return(0); -} - -/*****************************************************************************/ - -/* - * Return the entire driver board structure to a user app. - */ - -static int stl_getbrdstruct(unsigned long arg) -{ - stlbrd_t *brdp; - - copy_from_user(&stl_dummybrd, (void *) arg, sizeof(stlbrd_t)); - if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS)) - return(-ENODEV); - brdp = stl_brds[stl_dummybrd.brdnr]; - if (brdp == (stlbrd_t *) NULL) - return(-ENODEV); - copy_to_user((void *) arg, brdp, sizeof(stlbrd_t)); - return(0); -} - -/*****************************************************************************/ - -/* - * The "staliomem" device is also required to do some special operations - * on the board and/or ports. In this driver it is mostly used for stats - * collection. - */ - -static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) -{ - int brdnr, rc; - -#if DEBUG - printk("stl_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip, - (int) fp, cmd, (int) arg); -#endif - - brdnr = MINOR(ip->i_rdev); - if (brdnr >= STL_MAXBRDS) - return(-ENODEV); - rc = 0; - - switch (cmd) { - case COM_GETPORTSTATS: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(comstats_t))) == 0) - rc = stl_getportstats((stlport_t *) NULL, - (comstats_t *) arg); - break; - case COM_CLRPORTSTATS: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(comstats_t))) == 0) - rc = stl_clrportstats((stlport_t *) NULL, - (comstats_t *) arg); - break; - case COM_GETBRDSTATS: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(combrd_t))) == 0) - rc = stl_getbrdstats((combrd_t *) arg); - break; - case COM_READPORT: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(stlport_t))) == 0) - rc = stl_getportstruct(arg); - break; - case COM_READBOARD: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(stlbrd_t))) == 0) - rc = stl_getbrdstruct(arg); - break; - default: - rc = -ENOIOCTLCMD; - break; - } - - return(rc); -} - -/*****************************************************************************/ - -int __init stl_init(void) -{ - printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); - - stl_initbrds(); - -/* - * Allocate a temporary write buffer. - */ - stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE); - if (stl_tmpwritebuf == (char *) NULL) - printk("STALLION: failed to allocate memory (size=%d)\n", - STL_TXBUFSIZE); - -/* - * Set up a character driver for per board stuff. This is mainly used - * to do stats ioctls on the ports. - */ - if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) - printk("STALLION: failed to register serial board device\n"); - devfs_handle = devfs_mk_dir (NULL, "staliomem", NULL); - devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT, - STL_SIOMEMMAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &stl_fsiomem, NULL); - -/* - * Set up the tty driver structure and register us as a driver. - * Also setup the callout tty device. - */ - memset(&stl_serial, 0, sizeof(struct tty_driver)); - stl_serial.magic = TTY_DRIVER_MAGIC; - stl_serial.driver_name = stl_drvname; - stl_serial.name = stl_serialname; - stl_serial.major = STL_SERIALMAJOR; - stl_serial.minor_start = 0; - stl_serial.num = STL_MAXBRDS * STL_MAXPORTS; - stl_serial.type = TTY_DRIVER_TYPE_SERIAL; - stl_serial.subtype = STL_DRVTYPSERIAL; - stl_serial.init_termios = stl_deftermios; - stl_serial.flags = TTY_DRIVER_REAL_RAW; - stl_serial.refcount = &stl_refcount; - stl_serial.table = stl_ttys; - stl_serial.termios = stl_termios; - stl_serial.termios_locked = stl_termioslocked; - - stl_serial.open = stl_open; - stl_serial.close = stl_close; - stl_serial.write = stl_write; - stl_serial.put_char = stl_putchar; - stl_serial.flush_chars = stl_flushchars; - stl_serial.write_room = stl_writeroom; - stl_serial.chars_in_buffer = stl_charsinbuffer; - stl_serial.ioctl = stl_ioctl; - stl_serial.set_termios = stl_settermios; - stl_serial.throttle = stl_throttle; - stl_serial.unthrottle = stl_unthrottle; - stl_serial.stop = stl_stop; - stl_serial.start = stl_start; - stl_serial.hangup = stl_hangup; - stl_serial.flush_buffer = stl_flushbuffer; - stl_serial.break_ctl = stl_breakctl; - stl_serial.wait_until_sent = stl_waituntilsent; - stl_serial.send_xchar = stl_sendxchar; - stl_serial.read_proc = stl_readproc; - - stl_callout = stl_serial; - stl_callout.name = stl_calloutname; - stl_callout.major = STL_CALLOUTMAJOR; - stl_callout.subtype = STL_DRVTYPCALLOUT; - stl_callout.read_proc = 0; - - if (tty_register_driver(&stl_serial)) - printk("STALLION: failed to register serial driver\n"); - if (tty_register_driver(&stl_callout)) - printk("STALLION: failed to register callout driver\n"); - - return(0); -} - -/*****************************************************************************/ -/* CD1400 HARDWARE FUNCTIONS */ -/*****************************************************************************/ - -/* - * These functions get/set/update the registers of the cd1400 UARTs. - * Access to the cd1400 registers is via an address/data io port pair. - * (Maybe should make this inline...) - */ - -static int stl_cd1400getreg(stlport_t *portp, int regnr) -{ - outb((regnr + portp->uartaddr), portp->ioaddr); - return(inb(portp->ioaddr + EREG_DATA)); -} - -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value) -{ - outb((regnr + portp->uartaddr), portp->ioaddr); - outb(value, portp->ioaddr + EREG_DATA); -} - -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value) -{ - outb((regnr + portp->uartaddr), portp->ioaddr); - if (inb(portp->ioaddr + EREG_DATA) != value) { - outb(value, portp->ioaddr + EREG_DATA); - return(1); - } - return(0); -} - -/*****************************************************************************/ - -/* - * Inbitialize the UARTs in a panel. We don't care what sort of board - * these ports are on - since the port io registers are almost - * identical when dealing with ports. - */ - -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) -{ - unsigned int gfrcr; - int chipmask, i, j; - int nrchips, uartaddr, ioaddr; - -#if DEBUG - printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); -#endif - - BRDENABLE(panelp->brdnr, panelp->pagenr); - -/* - * Check that each chip is present and started up OK. - */ - chipmask = 0; - nrchips = panelp->nrports / CD1400_PORTS; - for (i = 0; (i < nrchips); i++) { - if (brdp->brdtype == BRD_ECHPCI) { - outb((panelp->pagenr + (i >> 1)), brdp->ioctrl); - ioaddr = panelp->iobase; - } else { - ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1)); - } - uartaddr = (i & 0x01) ? 0x080 : 0; - outb((GFRCR + uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); - outb((CCR + uartaddr), ioaddr); - outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); - outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); - outb((GFRCR + uartaddr), ioaddr); - for (j = 0; (j < CCR_MAXWAIT); j++) { - if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) - break; - } - if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { - printk("STALLION: cd1400 not responding, " - "brd=%d panel=%d chip=%d\n", - panelp->brdnr, panelp->panelnr, i); - continue; - } - chipmask |= (0x1 << i); - outb((PPR + uartaddr), ioaddr); - outb(PPR_SCALAR, (ioaddr + EREG_DATA)); - } - - BRDDISABLE(panelp->brdnr); - return(chipmask); -} - -/*****************************************************************************/ - -/* - * Initialize hardware specific port registers. - */ - -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) -{ -#if DEBUG - printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif - - if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) || - (portp == (stlport_t *) NULL)) - return; - - portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) || - (portp->portnr < 8)) ? 0 : EREG_BANKSIZE); - portp->uartaddr = (portp->portnr & 0x04) << 5; - portp->pagenr = panelp->pagenr + (portp->portnr >> 3); - - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, LIVR, (portp->portnr << 3)); - portp->hwid = stl_cd1400getreg(portp, GFRCR); - BRDDISABLE(portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Wait for the command register to be ready. We will poll this, - * since it won't usually take too long to be ready. - */ - -static void stl_cd1400ccrwait(stlport_t *portp) -{ - int i; - - for (i = 0; (i < CCR_MAXWAIT); i++) { - if (stl_cd1400getreg(portp, CCR) == 0) { - return; - } - } - - printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n", - portp->portnr, portp->panelnr, portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Set up the cd1400 registers for a port based on the termios port - * settings. - */ - -static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) -{ - stlbrd_t *brdp; - unsigned long flags; - unsigned int clkdiv, baudrate; - unsigned char cor1, cor2, cor3; - unsigned char cor4, cor5, ccr; - unsigned char srer, sreron, sreroff; - unsigned char mcor1, mcor2, rtpr; - unsigned char clk, div; - - cor1 = 0; - cor2 = 0; - cor3 = 0; - cor4 = 0; - cor5 = 0; - ccr = 0; - rtpr = 0; - clk = 0; - div = 0; - mcor1 = 0; - mcor2 = 0; - sreron = 0; - sreroff = 0; - - brdp = stl_brds[portp->brdnr]; - if (brdp == (stlbrd_t *) NULL) - return; - -/* - * Set up the RX char ignore mask with those RX error types we - * can ignore. We can get the cd1400 to help us out a little here, - * it will ignore parity errors and breaks for us. - */ - portp->rxignoremsk = 0; - if (tiosp->c_iflag & IGNPAR) { - portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN); - cor1 |= COR1_PARIGNORE; - } - if (tiosp->c_iflag & IGNBRK) { - portp->rxignoremsk |= ST_BREAK; - cor4 |= COR4_IGNBRK; - } - - portp->rxmarkmsk = ST_OVERRUN; - if (tiosp->c_iflag & (INPCK | PARMRK)) - portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING); - if (tiosp->c_iflag & BRKINT) - portp->rxmarkmsk |= ST_BREAK; - -/* - * Go through the char size, parity and stop bits and set all the - * option register appropriately. - */ - switch (tiosp->c_cflag & CSIZE) { - case CS5: - cor1 |= COR1_CHL5; - break; - case CS6: - cor1 |= COR1_CHL6; - break; - case CS7: - cor1 |= COR1_CHL7; - break; - default: - cor1 |= COR1_CHL8; - break; - } - - if (tiosp->c_cflag & CSTOPB) - cor1 |= COR1_STOP2; - else - cor1 |= COR1_STOP1; - - if (tiosp->c_cflag & PARENB) { - if (tiosp->c_cflag & PARODD) - cor1 |= (COR1_PARENB | COR1_PARODD); - else - cor1 |= (COR1_PARENB | COR1_PAREVEN); - } else { - cor1 |= COR1_PARNONE; - } - -/* - * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing - * space for hardware flow control and the like. This should be set to - * VMIN. Also here we will set the RX data timeout to 10ms - this should - * really be based on VTIME. - */ - cor3 |= FIFO_RXTHRESHOLD; - rtpr = 2; - -/* - * Calculate the baud rate timers. For now we will just assume that - * the input and output baud are the same. Could have used a baud - * table here, but this way we can generate virtually any baud rate - * we like! - */ - baudrate = tiosp->c_cflag & CBAUD; - if (baudrate & CBAUDEX) { - baudrate &= ~CBAUDEX; - if ((baudrate < 1) || (baudrate > 4)) - tiosp->c_cflag &= ~CBAUDEX; - else - baudrate += 15; - } - baudrate = stl_baudrates[baudrate]; - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baudrate = 57600; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baudrate = 115200; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baudrate = 230400; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baudrate = 460800; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - baudrate = (portp->baud_base / portp->custom_divisor); - } - if (baudrate > STL_CD1400MAXBAUD) - baudrate = STL_CD1400MAXBAUD; - - if (baudrate > 0) { - for (clk = 0; (clk < CD1400_NUMCLKS); clk++) { - clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate); - if (clkdiv < 0x100) - break; - } - div = (unsigned char) clkdiv; - } - -/* - * Check what form of modem signaling is required and set it up. - */ - if ((tiosp->c_cflag & CLOCAL) == 0) { - mcor1 |= MCOR1_DCD; - mcor2 |= MCOR2_DCD; - sreron |= SRER_MODEM; - portp->flags |= ASYNC_CHECK_CD; - } else { - portp->flags &= ~ASYNC_CHECK_CD; - } - -/* - * Setup cd1400 enhanced modes if we can. In particular we want to - * handle as much of the flow control as possible automatically. As - * well as saving a few CPU cycles it will also greatly improve flow - * control reliability. - */ - if (tiosp->c_iflag & IXON) { - cor2 |= COR2_TXIBE; - cor3 |= COR3_SCD12; - if (tiosp->c_iflag & IXANY) - cor2 |= COR2_IXM; - } - - if (tiosp->c_cflag & CRTSCTS) { - cor2 |= COR2_CTSAE; - mcor1 |= FIFO_RTSTHRESHOLD; - } - -/* - * All cd1400 register values calculated so go through and set - * them all up. - */ - -#if DEBUG - printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", - portp->portnr, portp->panelnr, portp->brdnr); - printk(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", - cor1, cor2, cor3, cor4, cor5); - printk(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", - mcor1, mcor2, rtpr, sreron, sreroff); - printk(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); - printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n", - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - srer = stl_cd1400getreg(portp, SRER); - stl_cd1400setreg(portp, SRER, 0); - if (stl_cd1400updatereg(portp, COR1, cor1)) - ccr = 1; - if (stl_cd1400updatereg(portp, COR2, cor2)) - ccr = 1; - if (stl_cd1400updatereg(portp, COR3, cor3)) - ccr = 1; - if (ccr) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_CORCHANGE); - } - stl_cd1400setreg(portp, COR4, cor4); - stl_cd1400setreg(portp, COR5, cor5); - stl_cd1400setreg(portp, MCOR1, mcor1); - stl_cd1400setreg(portp, MCOR2, mcor2); - if (baudrate > 0) { - stl_cd1400setreg(portp, TCOR, clk); - stl_cd1400setreg(portp, TBPR, div); - stl_cd1400setreg(portp, RCOR, clk); - stl_cd1400setreg(portp, RBPR, div); - } - stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]); - stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]); - stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]); - stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]); - stl_cd1400setreg(portp, RTPR, rtpr); - mcor1 = stl_cd1400getreg(portp, MSVR1); - if (mcor1 & MSVR1_DCD) - portp->sigs |= TIOCM_CD; - else - portp->sigs &= ~TIOCM_CD; - stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron)); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Set the state of the DTR and RTS signals. - */ - -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) -{ - unsigned char msvr1, msvr2; - unsigned long flags; - -#if DEBUG - printk("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif - - msvr1 = 0; - msvr2 = 0; - if (dtr > 0) - msvr1 = MSVR1_DTR; - if (rts > 0) - msvr2 = MSVR2_RTS; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - if (rts >= 0) - stl_cd1400setreg(portp, MSVR2, msvr2); - if (dtr >= 0) - stl_cd1400setreg(portp, MSVR1, msvr1); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Return the state of the signals. - */ - -static int stl_cd1400getsignals(stlport_t *portp) -{ - unsigned char msvr1, msvr2; - unsigned long flags; - int sigs; - -#if DEBUG - printk("stl_cd1400getsignals(portp=%x)\n", (int) portp); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - msvr1 = stl_cd1400getreg(portp, MSVR1); - msvr2 = stl_cd1400getreg(portp, MSVR2); - BRDDISABLE(portp->brdnr); - restore_flags(flags); - - sigs = 0; - sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0; - sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0; - sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0; - sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0; -#if 0 - sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0; - sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0; -#else - sigs |= TIOCM_DSR; -#endif - return(sigs); -} - -/*****************************************************************************/ - -/* - * Enable/Disable the Transmitter and/or Receiver. - */ - -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char ccr; - unsigned long flags; - -#if DEBUG - printk("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif - ccr = 0; - - if (tx == 0) - ccr |= CCR_TXDISABLE; - else if (tx > 0) - ccr |= CCR_TXENABLE; - if (rx == 0) - ccr |= CCR_RXDISABLE; - else if (rx > 0) - ccr |= CCR_RXENABLE; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, ccr); - stl_cd1400ccrwait(portp); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Start/stop the Transmitter and/or Receiver. - */ - -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char sreron, sreroff; - unsigned long flags; - -#if DEBUG - printk("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif - - sreron = 0; - sreroff = 0; - if (tx == 0) - sreroff |= (SRER_TXDATA | SRER_TXEMPTY); - else if (tx == 1) - sreron |= SRER_TXDATA; - else if (tx >= 2) - sreron |= SRER_TXEMPTY; - if (rx == 0) - sreroff |= SRER_RXDATA; - else if (rx > 0) - sreron |= SRER_RXDATA; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, SRER, - ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron)); - BRDDISABLE(portp->brdnr); - if (tx > 0) - set_bit(ASYI_TXBUSY, &portp->istate); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Disable all interrupts from this port. - */ - -static void stl_cd1400disableintrs(stlport_t *portp) -{ - unsigned long flags; - -#if DEBUG - printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp); -#endif - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, SRER, 0); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -static void stl_cd1400sendbreak(stlport_t *portp, int len) -{ - unsigned long flags; - -#if DEBUG - printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400setreg(portp, SRER, - ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) | - SRER_TXEMPTY)); - BRDDISABLE(portp->brdnr); - portp->brklen = len; - if (len == 1) - portp->stats.txbreaks++; - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Take flow control actions... - */ - -static void stl_cd1400flowctrl(stlport_t *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - -#if DEBUG - printk("stl_cd1400flowctrl(portp=%x,state=%x)\n", (int) portp, state); -#endif - - if (portp == (stlport_t *) NULL) - return; - tty = portp->tty; - if (tty == (struct tty_struct *) NULL) - return; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - - if (state) { - if (tty->termios->c_iflag & IXOFF) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); - portp->stats.rxxon++; - stl_cd1400ccrwait(portp); - } -/* - * Question: should we return RTS to what it was before? It may - * have been set by an ioctl... Suppose not, since if you have - * hardware flow control set then it is pretty silly to go and - * set the RTS line by hand. - */ - if (tty->termios->c_cflag & CRTSCTS) { - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) | - FIFO_RTSTHRESHOLD)); - stl_cd1400setreg(portp, MSVR2, MSVR2_RTS); - portp->stats.rxrtson++; - } - } else { - if (tty->termios->c_iflag & IXOFF) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); - portp->stats.rxxoff++; - stl_cd1400ccrwait(portp); - } - if (tty->termios->c_cflag & CRTSCTS) { - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) & 0xf0)); - stl_cd1400setreg(portp, MSVR2, 0); - portp->stats.rxrtsoff++; - } - } - - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Send a flow control character... - */ - -static void stl_cd1400sendflow(stlport_t *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - -#if DEBUG - printk("stl_cd1400sendflow(portp=%x,state=%x)\n", (int) portp, state); -#endif - - if (portp == (stlport_t *) NULL) - return; - tty = portp->tty; - if (tty == (struct tty_struct *) NULL) - return; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - if (state) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); - portp->stats.rxxon++; - stl_cd1400ccrwait(portp); - } else { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); - portp->stats.rxxoff++; - stl_cd1400ccrwait(portp); - } - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -static void stl_cd1400flush(stlport_t *portp) -{ - unsigned long flags; - -#if DEBUG - printk("stl_cd1400flush(portp=%x)\n", (int) portp); -#endif - - if (portp == (stlport_t *) NULL) - return; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO); - stl_cd1400ccrwait(portp); - portp->tx.tail = portp->tx.head; - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Return the current state of data flow on this port. This is only - * really interresting when determining if data has fully completed - * transmission or not... This is easy for the cd1400, it accurately - * maintains the busy port flag. - */ - -static int stl_cd1400datastate(stlport_t *portp) -{ -#if DEBUG - printk("stl_cd1400datastate(portp=%x)\n", (int) portp); -#endif - - if (portp == (stlport_t *) NULL) - return(0); - - return(test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for cd1400 EasyIO boards. - */ - -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) -{ - unsigned char svrtype; - -#if DEBUG - printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", - (int) panelp, iobase); -#endif - - outb(SVRR, iobase); - svrtype = inb(iobase + EREG_DATA); - if (panelp->nrports > 4) { - outb((SVRR + 0x80), iobase); - svrtype |= inb(iobase + EREG_DATA); - } - - if (svrtype & SVRR_RX) - stl_cd1400rxisr(panelp, iobase); - else if (svrtype & SVRR_TX) - stl_cd1400txisr(panelp, iobase); - else if (svrtype & SVRR_MDM) - stl_cd1400mdmisr(panelp, iobase); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for cd1400 panels. - */ - -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) -{ - unsigned char svrtype; - -#if DEBUG - printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp, - iobase); -#endif - - outb(SVRR, iobase); - svrtype = inb(iobase + EREG_DATA); - outb((SVRR + 0x80), iobase); - svrtype |= inb(iobase + EREG_DATA); - if (svrtype & SVRR_RX) - stl_cd1400rxisr(panelp, iobase); - else if (svrtype & SVRR_TX) - stl_cd1400txisr(panelp, iobase); - else if (svrtype & SVRR_MDM) - stl_cd1400mdmisr(panelp, iobase); -} - - -/*****************************************************************************/ - -/* - * Unfortunately we need to handle breaks in the TX data stream, since - * this is the only way to generate them on the cd1400. - */ - -static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr) -{ - if (portp->brklen == 1) { - outb((COR2 + portp->uartaddr), ioaddr); - outb((inb(ioaddr + EREG_DATA) | COR2_ETC), - (ioaddr + EREG_DATA)); - outb((TDR + portp->uartaddr), ioaddr); - outb(ETC_CMD, (ioaddr + EREG_DATA)); - outb(ETC_STARTBREAK, (ioaddr + EREG_DATA)); - outb((SRER + portp->uartaddr), ioaddr); - outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)), - (ioaddr + EREG_DATA)); - return(1); - } else if (portp->brklen > 1) { - outb((TDR + portp->uartaddr), ioaddr); - outb(ETC_CMD, (ioaddr + EREG_DATA)); - outb(ETC_STOPBREAK, (ioaddr + EREG_DATA)); - portp->brklen = -1; - return(1); - } else { - outb((COR2 + portp->uartaddr), ioaddr); - outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC), - (ioaddr + EREG_DATA)); - portp->brklen = 0; - } - return(0); -} - -/*****************************************************************************/ - -/* - * Transmit interrupt handler. This has gotta be fast! Handling TX - * chars is pretty simple, stuff as many as possible from the TX buffer - * into the cd1400 FIFO. Must also handle TX breaks here, since they - * are embedded as commands in the data stream. Oh no, had to use a goto! - * This could be optimized more, will do when I get time... - * In practice it is possible that interrupts are enabled but that the - * port has been hung up. Need to handle not having any TX buffer here, - * this is done by using the side effect that head and tail will also - * be NULL if the buffer has been freed. - */ - -static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) -{ - stlport_t *portp; - int len, stlen; - char *head, *tail; - unsigned char ioack, srer; - -#if DEBUG - printk("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif - - ioack = inb(ioaddr + EREG_TXACK); - if (((ioack & panelp->ackmask) != 0) || - ((ioack & ACK_TYPMASK) != ACK_TYPTX)) { - printk("STALLION: bad TX interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - -/* - * Unfortunately we need to handle breaks in the data stream, since - * this is the only way to generate them on the cd1400. Do it now if - * a break is to be sent. - */ - if (portp->brklen != 0) - if (stl_cd1400breakisr(portp, ioaddr)) - goto stl_txalldone; - - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); - if ((len == 0) || ((len < STL_TXBUFLOW) && - (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { - set_bit(ASYI_TXLOW, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); - } - - if (len == 0) { - outb((SRER + portp->uartaddr), ioaddr); - srer = inb(ioaddr + EREG_DATA); - if (srer & SRER_TXDATA) { - srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY; - } else { - srer &= ~(SRER_TXDATA | SRER_TXEMPTY); - clear_bit(ASYI_TXBUSY, &portp->istate); - } - outb(srer, (ioaddr + EREG_DATA)); - } else { - len = MIN(len, CD1400_TXFIFOSIZE); - portp->stats.txtotal += len; - stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); - outb((TDR + portp->uartaddr), ioaddr); - outsb((ioaddr + EREG_DATA), tail, stlen); - len -= stlen; - tail += stlen; - if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) - tail = portp->tx.buf; - if (len > 0) { - outsb((ioaddr + EREG_DATA), tail, len); - tail += len; - } - portp->tx.tail = tail; - } - -stl_txalldone: - outb((EOSRR + portp->uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ - -/* - * Receive character interrupt handler. Determine if we have good chars - * or bad chars and then process appropriately. Good chars are easy - * just shove the lot into the RX buffer and set all status byte to 0. - * If a bad RX char then process as required. This routine needs to be - * fast! In practice it is possible that we get an interrupt on a port - * that is closed. This can happen on hangups - since they completely - * shutdown a port not in user context. Need to handle this case. - */ - -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) -{ - stlport_t *portp; - struct tty_struct *tty; - unsigned int ioack, len, buflen; - unsigned char status; - char ch; - -#if DEBUG - printk("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif - - ioack = inb(ioaddr + EREG_RXACK); - if ((ioack & panelp->ackmask) != 0) { - printk("STALLION: bad RX interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - tty = portp->tty; - - 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)) { - len = MIN(len, sizeof(stl_unwanted)); - outb((RDSR + portp->uartaddr), ioaddr); - insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); - portp->stats.rxlost += len; - portp->stats.rxtotal += len; - } else { - len = MIN(len, buflen); - if (len > 0) { - 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_schedule_flip(tty); - portp->stats.rxtotal += len; - } - } - } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) { - outb((RDSR + portp->uartaddr), ioaddr); - status = inb(ioaddr + EREG_DATA); - ch = inb(ioaddr + EREG_DATA); - if (status & ST_PARITY) - portp->stats.rxparity++; - if (status & ST_FRAMING) - portp->stats.rxframing++; - if (status & ST_OVERRUN) - portp->stats.rxoverrun++; - if (status & ST_BREAK) - portp->stats.rxbreaks++; - if (status & ST_SCHARMASK) { - if ((status & ST_SCHARMASK) == ST_SCHAR1) - portp->stats.txxon++; - if ((status & ST_SCHARMASK) == ST_SCHAR2) - portp->stats.txxoff++; - goto stl_rxalldone; - } - if ((tty != (struct tty_struct *) NULL) && - ((portp->rxignoremsk & status) == 0)) { - if (portp->rxmarkmsk & status) { - if (status & ST_BREAK) { - status = TTY_BREAK; - if (portp->flags & ASYNC_SAK) { - do_SAK(tty); - BRDENABLE(portp->brdnr, portp->pagenr); - } - } else if (status & ST_PARITY) { - status = TTY_PARITY; - } else if (status & ST_FRAMING) { - status = TTY_FRAME; - } else if(status & ST_OVERRUN) { - status = TTY_OVERRUN; - } else { - status = 0; - } - } 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); - } - } - } else { - printk("STALLION: bad RX interrupt ack value=%x\n", ioack); - return; - } - -stl_rxalldone: - outb((EOSRR + portp->uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ - -/* - * Modem interrupt handler. The is called when the modem signal line - * (DCD) has changed state. Leave most of the work to the off-level - * processing routine. - */ - -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) -{ - stlport_t *portp; - unsigned int ioack; - unsigned char misr; - -#if DEBUG - printk("stl_cd1400mdmisr(panelp=%x)\n", (int) panelp); -#endif - - ioack = inb(ioaddr + EREG_MDACK); - if (((ioack & panelp->ackmask) != 0) || - ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) { - printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - - outb((MISR + portp->uartaddr), ioaddr); - misr = inb(ioaddr + EREG_DATA); - if (misr & MISR_DCD) { - set_bit(ASYI_DCDCHANGE, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); - portp->stats.modem++; - } - - outb((EOSRR + portp->uartaddr), ioaddr); - outb(0, (ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ -/* SC26198 HARDWARE FUNCTIONS */ -/*****************************************************************************/ - -/* - * These functions get/set/update the registers of the sc26198 UARTs. - * Access to the sc26198 registers is via an address/data io port pair. - * (Maybe should make this inline...) - */ - -static int stl_sc26198getreg(stlport_t *portp, int regnr) -{ - outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - return(inb(portp->ioaddr + XP_DATA)); -} - -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value) -{ - outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - outb(value, (portp->ioaddr + XP_DATA)); -} - -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) -{ - outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - if (inb(portp->ioaddr + XP_DATA) != value) { - outb(value, (portp->ioaddr + XP_DATA)); - return(1); - } - return(0); -} - -/*****************************************************************************/ - -/* - * Functions to get and set the sc26198 global registers. - */ - -static int stl_sc26198getglobreg(stlport_t *portp, int regnr) -{ - outb(regnr, (portp->ioaddr + XP_ADDR)); - return(inb(portp->ioaddr + XP_DATA)); -} - -#if 0 -static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value) -{ - outb(regnr, (portp->ioaddr + XP_ADDR)); - outb(value, (portp->ioaddr + XP_DATA)); -} -#endif - -/*****************************************************************************/ - -/* - * Inbitialize the UARTs in a panel. We don't care what sort of board - * these ports are on - since the port io registers are almost - * identical when dealing with ports. - */ - -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) -{ - int chipmask, i; - int nrchips, ioaddr; - -#if DEBUG - printk("stl_sc26198panelinit(brdp=%x,panelp=%x)\n", - (int) brdp, (int) panelp); -#endif - - BRDENABLE(panelp->brdnr, panelp->pagenr); - -/* - * Check that each chip is present and started up OK. - */ - chipmask = 0; - nrchips = (panelp->nrports + 4) / SC26198_PORTS; - if (brdp->brdtype == BRD_ECHPCI) - outb(panelp->pagenr, brdp->ioctrl); - - for (i = 0; (i < nrchips); i++) { - ioaddr = panelp->iobase + (i * 4); - outb(SCCR, (ioaddr + XP_ADDR)); - outb(CR_RESETALL, (ioaddr + XP_DATA)); - outb(TSTR, (ioaddr + XP_ADDR)); - if (inb(ioaddr + XP_DATA) != 0) { - printk("STALLION: sc26198 not responding, " - "brd=%d panel=%d chip=%d\n", - panelp->brdnr, panelp->panelnr, i); - continue; - } - chipmask |= (0x1 << i); - outb(GCCR, (ioaddr + XP_ADDR)); - outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA)); - outb(WDTRCR, (ioaddr + XP_ADDR)); - outb(0xff, (ioaddr + XP_DATA)); - } - - BRDDISABLE(panelp->brdnr); - return(chipmask); -} - -/*****************************************************************************/ - -/* - * Initialize hardware specific port registers. - */ - -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) -{ -#if DEBUG - printk("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif - - if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) || - (portp == (stlport_t *) NULL)) - return; - - portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); - portp->uartaddr = (portp->portnr & 0x07) << 4; - portp->pagenr = panelp->pagenr; - portp->hwid = 0x1; - - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS); - BRDDISABLE(portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Set up the sc26198 registers for a port based on the termios port - * settings. - */ - -static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) -{ - stlbrd_t *brdp; - unsigned long flags; - unsigned int baudrate; - unsigned char mr0, mr1, mr2, clk; - unsigned char imron, imroff, iopr, ipr; - - mr0 = 0; - mr1 = 0; - mr2 = 0; - clk = 0; - iopr = 0; - imron = 0; - imroff = 0; - - brdp = stl_brds[portp->brdnr]; - if (brdp == (stlbrd_t *) NULL) - return; - -/* - * Set up the RX char ignore mask with those RX error types we - * can ignore. - */ - portp->rxignoremsk = 0; - if (tiosp->c_iflag & IGNPAR) - portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING | - SR_RXOVERRUN); - if (tiosp->c_iflag & IGNBRK) - portp->rxignoremsk |= SR_RXBREAK; - - portp->rxmarkmsk = SR_RXOVERRUN; - if (tiosp->c_iflag & (INPCK | PARMRK)) - portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING); - if (tiosp->c_iflag & BRKINT) - portp->rxmarkmsk |= SR_RXBREAK; - -/* - * Go through the char size, parity and stop bits and set all the - * option register appropriately. - */ - switch (tiosp->c_cflag & CSIZE) { - case CS5: - mr1 |= MR1_CS5; - break; - case CS6: - mr1 |= MR1_CS6; - break; - case CS7: - mr1 |= MR1_CS7; - break; - default: - mr1 |= MR1_CS8; - break; - } - - if (tiosp->c_cflag & CSTOPB) - mr2 |= MR2_STOP2; - else - mr2 |= MR2_STOP1; - - if (tiosp->c_cflag & PARENB) { - if (tiosp->c_cflag & PARODD) - mr1 |= (MR1_PARENB | MR1_PARODD); - else - mr1 |= (MR1_PARENB | MR1_PAREVEN); - } else { - mr1 |= MR1_PARNONE; - } - - mr1 |= MR1_ERRBLOCK; - -/* - * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing - * space for hardware flow control and the like. This should be set to - * VMIN. - */ - mr2 |= MR2_RXFIFOHALF; - -/* - * Calculate the baud rate timers. For now we will just assume that - * the input and output baud are the same. The sc26198 has a fixed - * baud rate table, so only discrete baud rates possible. - */ - baudrate = tiosp->c_cflag & CBAUD; - if (baudrate & CBAUDEX) { - baudrate &= ~CBAUDEX; - if ((baudrate < 1) || (baudrate > 4)) - tiosp->c_cflag &= ~CBAUDEX; - else - baudrate += 15; - } - baudrate = stl_baudrates[baudrate]; - if ((tiosp->c_cflag & CBAUD) == B38400) { - if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baudrate = 57600; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baudrate = 115200; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - baudrate = 230400; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - baudrate = 460800; - else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) - baudrate = (portp->baud_base / portp->custom_divisor); - } - if (baudrate > STL_SC26198MAXBAUD) - baudrate = STL_SC26198MAXBAUD; - - if (baudrate > 0) { - for (clk = 0; (clk < SC26198_NRBAUDS); clk++) { - if (baudrate <= sc26198_baudtable[clk]) - break; - } - } - -/* - * Check what form of modem signaling is required and set it up. - */ - if (tiosp->c_cflag & CLOCAL) { - portp->flags &= ~ASYNC_CHECK_CD; - } else { - iopr |= IOPR_DCDCOS; - imron |= IR_IOPORT; - portp->flags |= ASYNC_CHECK_CD; - } - -/* - * Setup sc26198 enhanced modes if we can. In particular we want to - * handle as much of the flow control as possible automatically. As - * well as saving a few CPU cycles it will also greatly improve flow - * control reliability. - */ - if (tiosp->c_iflag & IXON) { - mr0 |= MR0_SWFTX | MR0_SWFT; - imron |= IR_XONXOFF; - } else { - imroff |= IR_XONXOFF; - } - if (tiosp->c_iflag & IXOFF) - mr0 |= MR0_SWFRX; - - if (tiosp->c_cflag & CRTSCTS) { - mr2 |= MR2_AUTOCTS; - mr1 |= MR1_AUTORTS; - } - -/* - * All sc26198 register values calculated so go through and set - * them all up. - */ - -#if DEBUG - printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", - portp->portnr, portp->panelnr, portp->brdnr); - printk(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); - printk(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); - printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n", - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], - tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IMR, 0); - stl_sc26198updatereg(portp, MR0, mr0); - stl_sc26198updatereg(portp, MR1, mr1); - stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK); - stl_sc26198updatereg(portp, MR2, mr2); - stl_sc26198updatereg(portp, IOPIOR, - ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr)); - - if (baudrate > 0) { - stl_sc26198setreg(portp, TXCSR, clk); - stl_sc26198setreg(portp, RXCSR, clk); - } - - stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]); - stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); - - ipr = stl_sc26198getreg(portp, IPR); - if (ipr & IPR_DCD) - portp->sigs &= ~TIOCM_CD; - else - portp->sigs |= TIOCM_CD; - - portp->imr = (portp->imr & ~imroff) | imron; - stl_sc26198setreg(portp, IMR, portp->imr); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Set the state of the DTR and RTS signals. - */ - -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) -{ - unsigned char iopioron, iopioroff; - unsigned long flags; - -#if DEBUG - printk("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif - - iopioron = 0; - iopioroff = 0; - if (dtr == 0) - iopioroff |= IPR_DTR; - else if (dtr > 0) - iopioron |= IPR_DTR; - if (rts == 0) - iopioroff |= IPR_RTS; - else if (rts > 0) - iopioron |= IPR_RTS; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IOPIOR, - ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron)); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Return the state of the signals. - */ - -static int stl_sc26198getsignals(stlport_t *portp) -{ - unsigned char ipr; - unsigned long flags; - int sigs; - -#if DEBUG - printk("stl_sc26198getsignals(portp=%x)\n", (int) portp); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - ipr = stl_sc26198getreg(portp, IPR); - BRDDISABLE(portp->brdnr); - restore_flags(flags); - - sigs = 0; - sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD; - sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS; - sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR; - sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS; - sigs |= TIOCM_DSR; - return(sigs); -} - -/*****************************************************************************/ - -/* - * Enable/Disable the Transmitter and/or Receiver. - */ - -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char ccr; - unsigned long flags; - -#if DEBUG - printk("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif - - ccr = portp->crenable; - if (tx == 0) - ccr &= ~CR_TXENABLE; - else if (tx > 0) - ccr |= CR_TXENABLE; - if (rx == 0) - ccr &= ~CR_RXENABLE; - else if (rx > 0) - ccr |= CR_RXENABLE; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, SCCR, ccr); - BRDDISABLE(portp->brdnr); - portp->crenable = ccr; - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Start/stop the Transmitter and/or Receiver. - */ - -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char imr; - unsigned long flags; - -#if DEBUG - printk("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif - - imr = portp->imr; - if (tx == 0) - imr &= ~IR_TXRDY; - else if (tx == 1) - imr |= IR_TXRDY; - if (rx == 0) - imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG); - else if (rx > 0) - imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IMR, imr); - BRDDISABLE(portp->brdnr); - portp->imr = imr; - if (tx > 0) - set_bit(ASYI_TXBUSY, &portp->istate); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Disable all interrupts from this port. - */ - -static void stl_sc26198disableintrs(stlport_t *portp) -{ - unsigned long flags; - -#if DEBUG - printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - portp->imr = 0; - stl_sc26198setreg(portp, IMR, 0); - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -static void stl_sc26198sendbreak(stlport_t *portp, int len) -{ - unsigned long flags; - -#if DEBUG - printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len); -#endif - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - if (len == 1) { - stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); - portp->stats.txbreaks++; - } else { - stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); - } - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Take flow control actions... - */ - -static void stl_sc26198flowctrl(stlport_t *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - unsigned char mr0; - -#if DEBUG - printk("stl_sc26198flowctrl(portp=%x,state=%x)\n", (int) portp, state); -#endif - - if (portp == (stlport_t *) NULL) - return; - tty = portp->tty; - if (tty == (struct tty_struct *) NULL) - return; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - - if (state) { - if (tty->termios->c_iflag & IXOFF) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); - mr0 |= MR0_SWFRX; - portp->stats.rxxon++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } -/* - * Question: should we return RTS to what it was before? It may - * have been set by an ioctl... Suppose not, since if you have - * hardware flow control set then it is pretty silly to go and - * set the RTS line by hand. - */ - if (tty->termios->c_cflag & CRTSCTS) { - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS)); - portp->stats.rxrtson++; - } - } else { - if (tty->termios->c_iflag & IXOFF) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); - mr0 &= ~MR0_SWFRX; - portp->stats.rxxoff++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } - if (tty->termios->c_cflag & CRTSCTS) { - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS)); - portp->stats.rxrtsoff++; - } - } - - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Send a flow control character. - */ - -static void stl_sc26198sendflow(stlport_t *portp, int state) -{ - struct tty_struct *tty; - unsigned long flags; - unsigned char mr0; - -#if DEBUG - printk("stl_sc26198sendflow(portp=%x,state=%x)\n", (int) portp, state); -#endif - - if (portp == (stlport_t *) NULL) - return; - tty = portp->tty; - if (tty == (struct tty_struct *) NULL) - return; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - if (state) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); - mr0 |= MR0_SWFRX; - portp->stats.rxxon++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } else { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); - mr0 &= ~MR0_SWFRX; - portp->stats.rxxoff++; - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } - BRDDISABLE(portp->brdnr); - restore_flags(flags); -} - -/*****************************************************************************/ - -static void stl_sc26198flush(stlport_t *portp) -{ - unsigned long flags; - -#if DEBUG - printk("stl_sc26198flush(portp=%x)\n", (int) portp); -#endif - - if (portp == (stlport_t *) NULL) - return; - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, SCCR, CR_TXRESET); - stl_sc26198setreg(portp, SCCR, portp->crenable); - BRDDISABLE(portp->brdnr); - portp->tx.tail = portp->tx.head; - restore_flags(flags); -} - -/*****************************************************************************/ - -/* - * Return the current state of data flow on this port. This is only - * really interresting when determining if data has fully completed - * transmission or not... The sc26198 interrupt scheme cannot - * determine when all data has actually drained, so we need to - * check the port statusy register to be sure. - */ - -static int stl_sc26198datastate(stlport_t *portp) -{ - unsigned long flags; - unsigned char sr; - -#if DEBUG - printk("stl_sc26198datastate(portp=%x)\n", (int) portp); -#endif - - if (portp == (stlport_t *) NULL) - return(0); - if (test_bit(ASYI_TXBUSY, &portp->istate)) - return(1); - - save_flags(flags); - cli(); - BRDENABLE(portp->brdnr, portp->pagenr); - sr = stl_sc26198getreg(portp, SR); - BRDDISABLE(portp->brdnr); - restore_flags(flags); - - return((sr & SR_TXEMPTY) ? 0 : 1); -} - -/*****************************************************************************/ - -/* - * Delay for a small amount of time, to give the sc26198 a chance - * to process a command... - */ - -static void stl_sc26198wait(stlport_t *portp) -{ - int i; - -#if DEBUG - printk("stl_sc26198wait(portp=%x)\n", (int) portp); -#endif - - if (portp == (stlport_t *) NULL) - return; - - for (i = 0; (i < 20); i++) - stl_sc26198getglobreg(portp, TSTR); -} - -/*****************************************************************************/ - -/* - * If we are TX flow controlled and in IXANY mode then we may - * need to unflow control here. We gotta do this because of the - * automatic flow control modes of the sc26198. - */ - -static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty) -{ - unsigned char mr0; - - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_HOSTXON); - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - clear_bit(ASYI_TXFLOWED, &portp->istate); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for sc26198 panels. - */ - -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) -{ - stlport_t *portp; - unsigned int iack; - -/* - * Work around bug in sc26198 chip... Cannot have A6 address - * line of UART high, else iack will be returned as 0. - */ - outb(0, (iobase + 1)); - - iack = inb(iobase + XP_IACK); - portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)]; - - if (iack & IVR_RXDATA) - stl_sc26198rxisr(portp, iack); - else if (iack & IVR_TXDATA) - stl_sc26198txisr(portp); - else - stl_sc26198otherisr(portp, iack); -} - -/*****************************************************************************/ - -/* - * Transmit interrupt handler. This has gotta be fast! Handling TX - * chars is pretty simple, stuff as many as possible from the TX buffer - * into the sc26198 FIFO. - * In practice it is possible that interrupts are enabled but that the - * port has been hung up. Need to handle not having any TX buffer here, - * this is done by using the side effect that head and tail will also - * be NULL if the buffer has been freed. - */ - -static void stl_sc26198txisr(stlport_t *portp) -{ - unsigned int ioaddr; - unsigned char mr0; - int len, stlen; - char *head, *tail; - -#if DEBUG - printk("stl_sc26198txisr(portp=%x)\n", (int) portp); -#endif - - ioaddr = portp->ioaddr; - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); - if ((len == 0) || ((len < STL_TXBUFLOW) && - (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { - set_bit(ASYI_TXLOW, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); - } - - if (len == 0) { - outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR)); - mr0 = inb(ioaddr + XP_DATA); - if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) { - portp->imr &= ~IR_TXRDY; - outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR)); - outb(portp->imr, (ioaddr + XP_DATA)); - clear_bit(ASYI_TXBUSY, &portp->istate); - } else { - mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY); - outb(mr0, (ioaddr + XP_DATA)); - } - } else { - len = MIN(len, SC26198_TXFIFOSIZE); - portp->stats.txtotal += len; - stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); - outb(GTXFIFO, (ioaddr + XP_ADDR)); - outsb((ioaddr + XP_DATA), tail, stlen); - len -= stlen; - tail += stlen; - if (tail >= (portp->tx.buf + STL_TXBUFSIZE)) - tail = portp->tx.buf; - if (len > 0) { - outsb((ioaddr + XP_DATA), tail, len); - tail += len; - } - portp->tx.tail = tail; - } -} - -/*****************************************************************************/ - -/* - * Receive character interrupt handler. Determine if we have good chars - * or bad chars and then process appropriately. Good chars are easy - * just shove the lot into the RX buffer and set all status byte to 0. - * If a bad RX char then process as required. This routine needs to be - * fast! In practice it is possible that we get an interrupt on a port - * that is closed. This can happen on hangups - since they completely - * shutdown a port not in user context. Need to handle this case. - */ - -static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) -{ - struct tty_struct *tty; - unsigned int len, buflen, ioaddr; - -#if DEBUG - printk("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif - - tty = portp->tty; - ioaddr = portp->ioaddr; - outb(GIBCR, (ioaddr + XP_ADDR)); - 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)) { - len = MIN(len, sizeof(stl_unwanted)); - outb(GRXFIFO, (ioaddr + XP_ADDR)); - insb((ioaddr + XP_DATA), &stl_unwanted[0], len); - portp->stats.rxlost += len; - portp->stats.rxtotal += len; - } else { - len = MIN(len, buflen); - if (len > 0) { - 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_schedule_flip(tty); - portp->stats.rxtotal += len; - } - } - } else { - stl_sc26198rxbadchars(portp); - } - -/* - * If we are TX flow controlled and in IXANY mode then we may need - * to unflow control here. We gotta do this because of the automatic - * flow control modes of the sc26198. - */ - if (test_bit(ASYI_TXFLOWED, &portp->istate)) { - if ((tty != (struct tty_struct *) NULL) && - (tty->termios != (struct termios *) NULL) && - (tty->termios->c_iflag & IXANY)) { - stl_sc26198txunflow(portp, tty); - } - } -} - -/*****************************************************************************/ - -/* - * Process an RX bad character. - */ - -static void inline stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch) -{ - struct tty_struct *tty; - unsigned int ioaddr; - - tty = portp->tty; - ioaddr = portp->ioaddr; - - if (status & SR_RXPARITY) - portp->stats.rxparity++; - if (status & SR_RXFRAMING) - portp->stats.rxframing++; - if (status & SR_RXOVERRUN) - portp->stats.rxoverrun++; - if (status & SR_RXBREAK) - portp->stats.rxbreaks++; - - if ((tty != (struct tty_struct *) NULL) && - ((portp->rxignoremsk & status) == 0)) { - if (portp->rxmarkmsk & status) { - if (status & SR_RXBREAK) { - status = TTY_BREAK; - if (portp->flags & ASYNC_SAK) { - do_SAK(tty); - BRDENABLE(portp->brdnr, portp->pagenr); - } - } else if (status & SR_RXPARITY) { - status = TTY_PARITY; - } else if (status & SR_RXFRAMING) { - status = TTY_FRAME; - } else if(status & SR_RXOVERRUN) { - status = TTY_OVERRUN; - } else { - status = 0; - } - } 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); - } - - if (status == 0) - portp->stats.rxtotal++; - } -} - -/*****************************************************************************/ - -/* - * Process all characters in the RX FIFO of the UART. Check all char - * status bytes as well, and process as required. We need to check - * all bytes in the FIFO, in case some more enter the FIFO while we - * are here. To get the exact character error type we need to switch - * into CHAR error mode (that is why we need to make sure we empty - * the FIFO). - */ - -static void stl_sc26198rxbadchars(stlport_t *portp) -{ - unsigned char status, mr1; - char ch; - -/* - * To get the precise error type for each character we must switch - * back into CHAR error mode. - */ - mr1 = stl_sc26198getreg(portp, MR1); - stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); - - while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { - stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR); - ch = stl_sc26198getreg(portp, RXFIFO); - stl_sc26198rxbadch(portp, status, ch); - } - -/* - * To get correct interrupt class we must switch back into BLOCK - * error mode. - */ - stl_sc26198setreg(portp, MR1, mr1); -} - -/*****************************************************************************/ - -/* - * Other interrupt handler. This includes modem signals, flow - * control actions, etc. Most stuff is left to off-level interrupt - * processing time. - */ - -static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack) -{ - unsigned char cir, ipr, xisr; - -#if DEBUG - printk("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif - - cir = stl_sc26198getglobreg(portp, CIR); - - switch (cir & CIR_SUBTYPEMASK) { - case CIR_SUBCOS: - ipr = stl_sc26198getreg(portp, IPR); - if (ipr & IPR_DCDCHANGE) { - set_bit(ASYI_DCDCHANGE, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); - portp->stats.modem++; - } - break; - case CIR_SUBXONXOFF: - xisr = stl_sc26198getreg(portp, XISR); - if (xisr & XISR_RXXONGOT) { - set_bit(ASYI_TXFLOWED, &portp->istate); - portp->stats.txxoff++; - } - if (xisr & XISR_RXXOFFGOT) { - clear_bit(ASYI_TXFLOWED, &portp->istate); - portp->stats.txxon++; - } - break; - case CIR_SUBBREAK: - stl_sc26198setreg(portp, SCCR, CR_BREAKRESET); - stl_sc26198rxbadchars(portp); - break; - default: - break; - } -} - -/*****************************************************************************/ diff --git a/drivers/char/stradis.c b/drivers/char/stradis.c deleted file mode 100644 index 03ca27a25..000000000 --- a/drivers/char/stradis.c +++ /dev/null @@ -1,2287 +0,0 @@ -/* - * stradis.c - stradis 4:2:2 mpeg decoder driver - * - * Stradis 4:2:2 MPEG-2 Decoder Driver - * Copyright (C) 1999 Nathan Laredo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "saa7146.h" -#include "saa7146reg.h" -#include "ibmmpeg2.h" -#include "saa7121.h" -#include "cs8420.h" - -#define DEBUG(x) /* debug driver */ -#undef IDEBUG(x) /* debug irq handler */ -#undef MDEBUG(x) /* debug memory management */ - -#define SAA7146_MAX 6 - -static struct saa7146 saa7146s[SAA7146_MAX]; - -static int saa_num = 0; /* number of SAA7146s in use */ - -#define nDebNormal 0x00480000 -#define nDebNoInc 0x00480000 -#define nDebVideo 0xd0480000 -#define nDebAudio 0xd0400000 -#define nDebDMA 0x02c80000 - -#define oDebNormal 0x13c80000 -#define oDebNoInc 0x13c80000 -#define oDebVideo 0xd1080000 -#define oDebAudio 0xd1080000 -#define oDebDMA 0x03080000 - -#define NewCard (saa->boardcfg[3]) -#define ChipControl (saa->boardcfg[1]) -#define NTSCFirstActive (saa->boardcfg[4]) -#define PALFirstActive (saa->boardcfg[5]) -#define NTSCLastActive (saa->boardcfg[54]) -#define PALLastActive (saa->boardcfg[55]) -#define Have2MB (saa->boardcfg[18] & 0x40) -#define HaveCS8420 (saa->boardcfg[18] & 0x04) -#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20) -#define HaveCS3310 (saa->boardcfg[18] & 0x01) -#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31]) -#define HaveCS4341 (saa->boardcfg[40] == 2) -#define SDIType (saa->boardcfg[27]) -#define CurrentMode (saa->boardcfg[2]) - -#define debNormal (NewCard ? nDebNormal : oDebNormal) -#define debNoInc (NewCard ? nDebNoInc : oDebNoInc) -#define debVideo (NewCard ? nDebVideo : oDebVideo) -#define debAudio (NewCard ? nDebAudio : oDebAudio) -#define debDMA (NewCard ? nDebDMA : oDebDMA) - -#ifdef DEBUG -int stradis_driver(void) /* for the benefit of ksymoops */ -{ - return 1; -} -#endif - -#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, -}; -#endif - -/* ----------------------------------------------------------------------- */ -/* Hardware I2C functions */ -static void I2CWipe(struct saa7146 *saa) -{ - int i; - /* set i2c to ~=100kHz, abort transfer, clear busy */ - saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - saawrite(0x600, SAA7146_I2C_STATUS); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - saawrite(0x600, SAA7146_I2C_STATUS); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); -} -/* read I2C */ -static int I2CRead(struct i2c_bus *bus, unsigned char addr, - unsigned char subaddr, int dosub) -{ - struct saa7146 *saa = (struct saa7146 *) bus->data; - int i; - - - if (saaread(SAA7146_I2C_STATUS) & 0x3c) - I2CWipe(saa); - 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); - else - saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) | - 0xf1, SAA7146_I2C_TRANSFER); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - /* wait for valid data */ - for (i = 0; i < 1000 && - (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) - schedule(); - if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR) - return -1; - if (i == 1000) - printk("i2c setup read timeout\n"); - saawrite(0x41, SAA7146_I2C_TRANSFER); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - /* wait for valid data */ - for (i = 0; i < 1000 && - (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++) - schedule(); - if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR) - return -1; - if (i == 1000) - printk("i2c read timeout\n"); - return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff); -} -static int I2CReadOld(struct i2c_bus *bus, unsigned char addr) -{ - return I2CRead(bus, addr, 0, 0); -} - -/* set both to write both bytes, reset it to write only b1 */ - -static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1, - unsigned char b2, int both) -{ - struct saa7146 *saa = (struct saa7146 *) bus->data; - int i; - u32 data; - - if (saaread(SAA7146_I2C_STATUS) & 0x3c) - I2CWipe(saa); - for (i = 0; i < 1000 && - (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) - schedule(); - if (i == 1000) - I2CWipe(saa); - data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16); - if (both) - data |= ((b2 & 0xff) << 8) | 0xe5; - else - data |= 0xd1; - saawrite(data, SAA7146_I2C_TRANSFER); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, - SAA7146_MC2); - return 0; -} - -static void attach_inform(struct i2c_bus *bus, int id) -{ - struct saa7146 *saa = (struct saa7146 *) bus->data; - 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 */ - for (i = 0; i < 64; i++) - saa->boardcfg[i] = I2CRead(bus, 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); - 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("\n"); - } -} - -static void detach_inform(struct i2c_bus *bus, int id) -{ - struct saa7146 *saa = (struct saa7146 *) bus->data; - int i; - i = saa->nr; -} - -static void I2CBusScan(struct i2c_bus *bus) -{ - int i; - for (i = 0; i < 0xff; i += 2) - if ((I2CRead(bus, i, 0, 0)) >= 0) - attach_inform(bus, i); -} - -static struct i2c_bus saa7146_i2c_bus_template = -{ - "saa7146", - I2C_BUSID_BT848, - NULL, - SPIN_LOCK_UNLOCKED, - attach_inform, - detach_inform, - NULL, - NULL, - I2CReadOld, - I2CWrite, -}; - -static int debiwait_maxwait = 0; - -static int wait_for_debi_done(struct saa7146 *saa) -{ - int i; - - /* wait for registers to be programmed */ - for (i = 0; i < 100000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++) - saaread(SAA7146_MC2); - /* wait for transfer to complete */ - 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 cmd; - if (count <= 0 || count > 32764) - return -1; - if (wait_for_debi_done(saa) < 0) - return -1; - saawrite(config, SAA7146_DEBI_CONFIG); - if (count <= 4) /* immediate transfer */ - saawrite(val, SAA7146_DEBI_AD); - else /* block transfer */ - saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); - saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND); - saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, - SAA7146_MC2); - return 0; -} - -static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count) -{ - u32 result = 0; - - if (count > 32764 || count <= 0) - return 0; - if (wait_for_debi_done(saa) < 0) - return 0; - saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); - saawrite((count << 17) | 0x10000 | (addr & 0xffff), - SAA7146_DEBI_COMMAND); - saawrite(config, SAA7146_DEBI_CONFIG); - saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, - SAA7146_MC2); - if (count > 4) /* not an immediate transfer */ - return count; - wait_for_debi_done(saa); - result = saaread(SAA7146_DEBI_AD); - if (count == 1) - result &= 0xff; - if (count == 2) - result &= 0xffff; - if (count == 3) - result &= 0xffffff; - 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; - - saawrite(SAA7146_PSR_PIN1, SAA7146_IER); - /* if special feature mode in effect, disable audio sending */ - if (saa->playmode != VID_PLAY_NORMAL) - saa->audtail = saa->audhead = 0; - if (saa->audhead <= saa->audtail) - audbytes = saa->audtail - saa->audhead; - else - audbytes = 65536 - (saa->audhead - saa->audtail); - if (saa->vidhead <= saa->vidtail) - vidbytes = saa->vidtail - saa->vidhead; - else - vidbytes = 524288 - (saa->vidhead - saa->vidtail); - if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) { - saawrite(0, SAA7146_IER); - 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 (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); - saa->audhead = 0; - audbytes -= split; - } else - split = 0; - memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead, - audbytes); - saa->audhead += audbytes; - saa->audhead &= 0xffff; - 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 */ - } else if (vidbytes >= 30720 && (debiread(saa, debNormal, - 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); - saa->vidhead = 0; - vidbytes -= split; - } else - split = 0; - memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead, - vidbytes); - saa->vidhead += vidbytes; - saa->vidhead &= 0x7ffff; - debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO : - IBM_MP2_FIFOW), 0, 30720); - wake_up_interruptible(&saa->vidq); - } - saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); -} - -static void send_osd_data(struct saa7146 *saa) -{ - int size = saa->osdtail - saa->osdhead; - if (size > 30720) - size = 30720; - /* ensure some multiple of 8 bytes is transferred */ - size = 8 * ((size + 8)>>3); - if (size) { - debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, - (saa->osdhead>>3), 2); - memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size); - saa->osdhead += size; - /* block transfer of next 8 bytes to ~32k bytes */ - debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size); - } - if (saa->osdhead >= saa->osdtail) { - saa->osdhead = saa->osdtail = 0; - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); - } -} - -static void saa7146_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct saa7146 *saa = (struct saa7146 *) dev_id; - u32 stat, astat; - int count; - - count = 0; - while (1) { - /* get/clear interrupt status bits */ - stat = saaread(SAA7146_ISR); - astat = stat & saaread(SAA7146_IER); - if (!astat) - return; - saawrite(astat, SAA7146_ISR); - if (astat & SAA7146_PSR_DEBI_S) { - do_irq_send_data(saa); - } - if (astat & SAA7146_PSR_PIN1) { - int istat; - /* the following read will trigger DEBI_S */ - istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); - if (istat & 1) { - saawrite(0, SAA7146_IER); - send_osd_data(saa); - saawrite(SAA7146_PSR_DEBI_S | - SAA7146_PSR_PIN1, SAA7146_IER); - } - if (istat & 0x20) { /* Video Start */ - saa->vidinfo.frame_count++; - } - if (istat & 0x400) { /* Picture Start */ - /* update temporal reference */ - } - if (istat & 0x200) { /* Picture Resolution Change */ - /* read new resolution */ - } - if (istat & 0x100) { /* New User Data found */ - /* read new user data */ - } - if (istat & 0x1000) { /* new GOP/SMPTE */ - /* read new SMPTE */ - } - if (istat & 0x8000) { /* Sequence Start Code */ - /* reset frame counter, load sizes */ - saa->vidinfo.frame_count = 0; - saa->vidinfo.h_size = 704; - saa->vidinfo.v_size = 480; -#if 0 - if (saa->endmarkhead != saa->endmarktail) { - saa->audhead = - saa->endmark[saa->endmarkhead]; - saa->endmarkhead++; - if (saa->endmarkhead >= MAX_MARKS) - saa->endmarkhead = 0; - } -#endif - } - if (istat & 0x4000) { /* Sequence Error Code */ - if (saa->endmarkhead != saa->endmarktail) { - saa->audhead = - saa->endmark[saa->endmarkhead]; - saa->endmarkhead++; - if (saa->endmarkhead >= MAX_MARKS) - saa->endmarkhead = 0; - } - } - } -#ifdef IDEBUG - if (astat & SAA7146_PSR_PPEF) { - IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr)); - } - if (astat & SAA7146_PSR_PABO) { - IDEBUG(printk("stradis%d irq: PABO\n", saa->nr)); - } - if (astat & SAA7146_PSR_PPED) { - IDEBUG(printk("stradis%d irq: PPED\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_I1) { - IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_I0) { - IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_LATE1) { - IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_LATE0) { - IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_E1) { - IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_E0) { - IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_TO1) { - IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_TO0) { - IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr)); - } - if (astat & SAA7146_PSR_UPLD) { - IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr)); - } - if (astat & SAA7146_PSR_DEBI_E) { - IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr)); - } - if (astat & SAA7146_PSR_I2C_S) { - IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr)); - } - if (astat & SAA7146_PSR_I2C_E) { - IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr)); - } - if (astat & SAA7146_PSR_A2_IN) { - IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr)); - } - if (astat & SAA7146_PSR_A2_OUT) { - IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr)); - } - if (astat & SAA7146_PSR_A1_IN) { - IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr)); - } - if (astat & SAA7146_PSR_A1_OUT) { - IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr)); - } - if (astat & SAA7146_PSR_AFOU) { - IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr)); - } - if (astat & SAA7146_PSR_V_PE) { - IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr)); - } - if (astat & SAA7146_PSR_VFOU) { - IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr)); - } - if (astat & SAA7146_PSR_FIDA) { - IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr)); - } - if (astat & SAA7146_PSR_FIDB) { - IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr)); - } - if (astat & SAA7146_PSR_PIN3) { - IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr)); - } - if (astat & SAA7146_PSR_PIN2) { - IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr)); - } - if (astat & SAA7146_PSR_PIN0) { - IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr)); - } - if (astat & SAA7146_PSR_ECS) { - IDEBUG(printk("stradis%d irq: ECS\n", saa->nr)); - } - if (astat & SAA7146_PSR_EC3S) { - IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr)); - } - if (astat & SAA7146_PSR_EC0S) { - IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr)); - } -#endif - count++; - if (count > 15) - printk(KERN_WARNING "stradis%d: irq loop %d\n", - saa->nr, count); - if (count > 20) { - saawrite(0, SAA7146_IER); - printk(KERN_ERR - "stradis%d: IRQ loop cleared\n", saa->nr); - } - } -} - -static int ibm_send_command(struct saa7146 *saa, - int command, int data, int chain) -{ - int i; - - if (chain) - 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); - debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2); - for (i = 0; i < 100 && - (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++) - schedule(); - if (i == 100) - return -1; - return 0; -} - -static void cs4341_setlevel(struct saa7146 *saa, int left, int right) -{ - I2CWrite(&(saa->i2c), 0x22, 0x03, - left > 94 ? 94 : left, 2); - I2CWrite(&(saa->i2c), 0x22, 0x04, - right > 94 ? 94 : right, 2); -} - -static void initialize_cs4341(struct saa7146 *saa) -{ - int i; - for (i = 0; i < 200; i++) { - /* auto mute off, power on, no de-emphasis */ - /* I2S data up to 24-bit 64xFs internal SCLK */ - I2CWrite(&(saa->i2c), 0x22, 0x01, 0x11, 2); - /* ATAPI mixer setings */ - I2CWrite(&(saa->i2c), 0x22, 0x02, 0x49, 2); - /* attenuation left 3db */ - I2CWrite(&(saa->i2c), 0x22, 0x03, 0x00, 2); - /* attenuation right 3db */ - I2CWrite(&(saa->i2c), 0x22, 0x04, 0x00, 2); - I2CWrite(&(saa->i2c), 0x22, 0x01, 0x10, 2); - if (I2CRead(&(saa->i2c), 0x22, 0x02, 1) == 0x49) - break; - schedule(); - } - printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i); - return; -} - -static void initialize_cs8420(struct saa7146 *saa, int pro) -{ - int i; - u8 *sequence; - if (pro) - sequence = mode8420pro; - else - sequence = mode8420con; - for (i = 0; i < INIT8420LEN; i++) - I2CWrite(&(saa->i2c), 0x20, init8420[i * 2], - init8420[i * 2 + 1], 2); - for (i = 0; i < MODE8420LEN; i++) - I2CWrite(&(saa->i2c), 0x20, sequence[i * 2], - sequence[i * 2 + 1], 2); - printk("stradis%d: CS8420 initialized\n", saa->nr); -} - -static void initialize_saa7121(struct saa7146 *saa, int dopal) -{ - int i, mod; - u8 *sequence; - if (dopal) - sequence = init7121pal; - else - sequence = init7121ntsc; - mod = saaread(SAA7146_PSR) & 0x08; - /* initialize PAL/NTSC video encoder */ - for (i = 0; i < INIT7121LEN; i++) { - if (NewCard) { /* handle new card encoder differences */ - if (sequence[i*2] == 0x3a) - I2CWrite(&(saa->i2c), 0x88, 0x3a, 0x13, 2); - else if (sequence[i*2] == 0x6b) - I2CWrite(&(saa->i2c), 0x88, 0x6b, 0x20, 2); - else if (sequence[i*2] == 0x6c) - I2CWrite(&(saa->i2c), 0x88, 0x6c, - dopal ? 0x09 : 0xf5, 2); - else if (sequence[i*2] == 0x6d) - I2CWrite(&(saa->i2c), 0x88, 0x6d, - dopal ? 0x20 : 0x00, 2); - else if (sequence[i*2] == 0x7a) - I2CWrite(&(saa->i2c), 0x88, 0x7a, - dopal ? (PALFirstActive - 1) : - (NTSCFirstActive - 4), 2); - else if (sequence[i*2] == 0x7b) - I2CWrite(&(saa->i2c), 0x88, 0x7b, - dopal ? PALLastActive : - NTSCLastActive, 2); - else I2CWrite(&(saa->i2c), 0x88, sequence[i * 2], - sequence[i * 2 + 1], 2); - } else { - if (sequence[i*2] == 0x6b && mod) - I2CWrite(&(saa->i2c), 0x88, 0x6b, - (sequence[i * 2 + 1] ^ 0x09), 2); - else if (sequence[i*2] == 0x7a) - I2CWrite(&(saa->i2c), 0x88, 0x7a, - dopal ? (PALFirstActive - 1) : - (NTSCFirstActive - 4), 2); - else if (sequence[i*2] == 0x7b) - I2CWrite(&(saa->i2c), 0x88, 0x7b, - dopal ? PALLastActive : - NTSCLastActive, 2); - else - I2CWrite(&(saa->i2c), 0x88, sequence[i * 2], - sequence[i * 2 + 1], 2); - } - } -} - -static void set_genlock_offset(struct saa7146 *saa, int noffset) -{ - int nCode; - int PixelsPerLine = 858; - if (CurrentMode == VIDEO_MODE_PAL) - PixelsPerLine = 864; - if (noffset > 500) - noffset = 500; - else if (noffset < -500) - noffset = -500; - nCode = noffset + 0x100; - if (nCode == 1) - nCode = 0x401; - else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode; - debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2); -} - -static void set_out_format(struct saa7146 *saa, int mode) -{ - initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1)); - 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 */ - 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); - mdelay(50); - } - debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, - NewCard ? 0xe500: 0x6500, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, - (1 << 8) | - (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); - debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, - (1 << 8) | - (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 - * transfer FPGA code, init IBM chip, transfer IBM microcode - * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0 - */ -static u16 bitmangler[256]; - -static int initialize_fpga(struct video_code *bitdata) -{ - int i, num, startindex, failure = 0, loadtwo, loadfile = 0; - u16 *dmabuf; - u8 *newdma; - struct saa7146 *saa; - - /* verify fpga code */ - for (startindex = 0; startindex < bitdata->datasize; startindex++) - if (bitdata->data[startindex] == 255) - break; - if (startindex == bitdata->datasize) { - printk(KERN_INFO "stradis: bad fpga code\n"); - return -1; - } - /* initialize all detected cards */ - for (num = 0; num < saa_num; num++) { - saa = &saa7146s[num]; - if (saa->boardcfg[0] > 20) - 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 */ - 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); - - 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)) { - loadfile = 1; - } 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 - continue; /* fpga not for this card */ - if (loadfile != 1 && loadfile != 2) { - continue; /* skip to next card */ - } - if (saa->boardcfg[0] && loadfile == 1 ) - continue; /* skip to next card */ - if (saa->boardcfg[0] != 1 && loadfile == 2) - continue; /* skip to next card */ - saa->boardcfg[0]++; /* mark fpga handled */ - printk("stradis%d: loading %s\n", saa->nr, - bitdata->loadwhat); - if (loadtwo && loadfile == 2) - goto send_fpga_stuff; - /* turn on the Audio interface to set PROG low */ - saawrite(0x00400040, SAA7146_GPIO_CTRL); - saaread(SAA7146_PSR); /* ensure posted write */ - /* wait for everyone to reset */ - mdelay(10); - saawrite(0x00400000, SAA7146_GPIO_CTRL); - } else { /* original card */ - if (strncmp(bitdata->loadwhat, "decoder2", 8)) - continue; /* fpga not for this card */ - /* Pull the Xilinx PROG signal WS3 low */ - saawrite(0x02000200, SAA7146_MC1); - /* Turn on the Audio interface so can set PROG low */ - saawrite(0x000000c0, SAA7146_ACON1); - /* Pull the Xilinx INIT signal (GPIO2) low */ - saawrite(0x00400000, SAA7146_GPIO_CTRL); - /* Make sure everybody resets */ - saaread(SAA7146_PSR); /* ensure posted write */ - mdelay(10); - /* Release the Xilinx PROG signal */ - saawrite(0x00000000, SAA7146_ACON1); - /* Turn off the Audio interface */ - saawrite(0x02000000, SAA7146_MC1); - } - /* 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++) - schedule(); - if (i == 1000) { - printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr); - return -1; - } -send_fpga_stuff: - if (NewCard) { - for (i = startindex; i < bitdata->datasize; i++) - newdma[i - startindex] = - 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 */ - } - - } - } else { - for (i = startindex; i < bitdata->datasize; i++) - dmabuf[i - startindex] = - bitmangler[bitdata->data[i]]; - debiwrite(saa, 0x014a0000, 0, 0, - ((bitdata->datasize - startindex) + 5) * 2); - } - 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", - saa->nr); - failure++; - continue; - } - if (!NewCard) { - /* Pull the Xilinx INIT signal (GPIO2) low */ - saawrite(0x00400000, SAA7146_GPIO_CTRL); - saaread(SAA7146_PSR); /* ensure posted write */ - mdelay(2); - saawrite(0x00000000, SAA7146_GPIO_CTRL); - mdelay(2); - } - printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr); - saa->boardcfg[0] = 26; /* mark fpga programmed */ - /* set VXCO to its lowest frequency */ - debiwrite(saa, debNormal, XILINX_PWM, 0, 2); - if (NewCard) { - /* mute CS3310 */ - if (HaveCS3310) - debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, - 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); - } - /* set source Black */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); - saa->boardcfg[4] = 22; /* set NTSC First Active Line */ - saa->boardcfg[5] = 23; /* set PAL First Active Line */ - saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */ - saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */ - set_out_format(saa, VIDEO_MODE_NTSC); - mdelay(50); - /* begin IBM chip init */ - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); - saaread(SAA7146_PSR); /* wait for reset */ - mdelay(5); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); - debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2); - debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); - if (NewCard) { - mdelay(5); - /* set i2s rate converter to 48KHz */ - debiwrite(saa, debNormal, 0x80c0, 6, 2); - /* 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) { - /* 0=consumer, 1=pro */ - initialize_cs8420(saa, 0); - } - mdelay(5); - if (HaveCS4341) - initialize_cs4341(saa); - } - debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); - debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); - if (NewCard) - set_genlock_offset(saa, 0); - debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); -#if 0 - /* enable genlock */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2); -#else - /* disable genlock */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2); -#endif - } - return failure; -} - -static int do_ibm_reset(struct saa7146 *saa) -{ - /* failure if decoder not previously programmed */ - if (saa->boardcfg[0] < 37) - return -EIO; - /* mute CS3310 */ - if (HaveCS3310) - debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2); - /* disable interrupts */ - saawrite(0, SAA7146_IER); - saa->audhead = saa->audtail = 0; - saa->vidhead = saa->vidtail = 0; - /* tristate debi bus, disable debi transfers */ - saawrite(0x00880000, SAA7146_MC1); - /* ensure posted write */ - saaread(SAA7146_MC1); - mdelay(50); - /* re-enable debi transfers */ - saawrite(0x00880088, SAA7146_MC1); - /* set source Black */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); - /* begin IBM chip init */ - set_out_format(saa, CurrentMode); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); - saaread(SAA7146_PSR); /* wait for reset */ - mdelay(5); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); - debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); - if (NewCard) { - mdelay(5); - /* set i2s rate converter to 48KHz */ - debiwrite(saa, debNormal, 0x80c0, 6, 2); - /* 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) { - /* 0=consumer, 1=pro */ - initialize_cs8420(saa, 1); - } - mdelay(5); - if (HaveCS4341) - initialize_cs4341(saa); - } - debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); - debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); - if (NewCard) - set_genlock_offset(saa, 0); - debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); - 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)) { - 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); - } - /* start video decoder */ - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); - /* 256k vid, 3520 bytes aud */ - debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2); - debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); - ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); - /* enable buffer threshold irq */ - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); - /* clear pending interrupts */ - debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); - debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); - return 0; -} - -/* load the decoder microcode */ -static int initialize_ibmmpeg2(struct video_code *microcode) -{ - int i, num; - struct saa7146 *saa; - - for (num = 0; num < saa_num; num++) { - 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) { - printk(KERN_INFO "stradis%d: %04x != 0xa55a\n", - saa->nr, i); -#if 0 - return -1; -#endif - } - if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) { - if (saa->boardcfg[0] > 27) - continue; /* skip to next card */ - /* load video control store */ - 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); - 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); - saa->boardcfg[0] = 28; - } - if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) { - if (saa->boardcfg[0] > 35) - continue; /* skip to next card */ - /* load audio control store */ - debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); - debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); - for (i = 0; i < microcode->datasize; i++) - debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA, - microcode->data[i], 1); - debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); - 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); - return -1; - } - /* set PWM to center value */ - if (NewCard) { - debiwrite(saa, debNormal, XILINX_PWM, - saa->boardcfg[14] + - (saa->boardcfg[13]<<8), 2); - } else - debiwrite(saa, debNormal, XILINX_PWM, - 0x46, 2); - if (HaveCS3310) { - i = CS3310MaxLvl; - 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)); - /* 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_AUD_CTL, 0x4573, 2); - ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); - /* enable buffer threshold irq */ - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); - debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); - /* enable gpio irq */ - saawrite(0x00002000, SAA7146_GPIO_CTRL); - /* enable decoder output to HPS */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); - 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 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 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; - int offset, yacl, ysci; - saa->win.color_fmt = format = - (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] : - palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]]; - offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl; - saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1); - saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1); - saawrite(saa->win.bpl * 2, SAA7146_PITCH1); - saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight, - SAA7146_PROT_ADDR1); - saawrite(0, SAA7146_PAGE1); - 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); - if (CurrentMode == VIDEO_MODE_NTSC) { - yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0; - ysci = 1024 - (saa->win.height * 1024 / 480); - } else { - 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(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); -} - -/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area - * bitmap is fixed width, 128 bytes (1024 pixels represented) - * arranged most-sigificant-bit-left in 32-bit words - * based on saa7146 clipping hardware, it swaps bytes if LE - * much of this makes up for egcs brain damage -- so if you - * are wondering "why did he do this?" it is because the C - * was adjusted to generate the optimal asm output without - * writing non-portable __asm__ directives. - */ - -static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h) -{ - register int startword, endword; - register u32 bitsleft, bitsright; - u32 *temp; - if (x < 0) { - w += x; - x = 0; - } - if (y < 0) { - h += y; - y = 0; - } - if (w <= 0 || h <= 0 || x > 1023 || y > 639) - return; /* throw away bad clips */ - if (x + w > 1024) - w = 1024 - x; - if (y + h > 640) - h = 640 - y; - startword = (x >> 5); - endword = ((x + w) >> 5); - bitsleft = (0xffffffff >> (x & 31)); - bitsright = (0xffffffff << (~((x + w) - (endword<<5)))); - temp = &clipmap[(y<<5) + startword]; - w = endword - startword; - if (!w) { - bitsleft |= bitsright; - for (y = 0; y < h; y++) { - *temp |= bitsleft; - temp += 32; - } - } else { - for (y = 0; y < h; y++) { - *temp++ |= bitsleft; - for (x = 1; x < w; x++) - *temp++ = 0xffffffff; - *temp |= bitsright; - temp += (32 - w); - } - } -} - -static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) -{ - int i, width, height; - 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 */ - /* convert rectangular clips to a bitmap */ - 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); - } - /* 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)); -} - -static int saa_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct saa7146 *saa = (struct saa7146 *) dev; - switch (cmd) { - case VIDIOCGCAP: - { - 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.channels = 1; - b.audios = 1; - b.maxwidth = 768; - b.maxheight = 576; - b.minwidth = 32; - b.minheight = 32; - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture p = saa->picture; - if (saa->win.depth == 8) - p.palette = VIDEO_PALETTE_HI240; - if (saa->win.depth == 15) - p.palette = VIDEO_PALETTE_RGB555; - if (saa->win.depth == 16) - p.palette = VIDEO_PALETTE_RGB565; - if (saa->win.depth == 24) - p.palette = VIDEO_PALETTE_RGB24; - if (saa->win.depth == 32) - p.palette = VIDEO_PALETTE_RGB32; - if (copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - u32 format; - if (copy_from_user(&p, arg, sizeof(p))) - return -EFAULT; - if (p.palette < sizeof(palette2fmt) / sizeof(u32)) { - format = palette2fmt[p.palette]; - saa->win.color_fmt = format; - saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); - } - saawrite(((p.brightness & 0xff00) << 16) | - ((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); - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - struct video_clip *vcp = NULL; - - 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); - return -EINVAL; - } - if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */ - int i = vw.x; - vw.x = (vw.x + 3) & ~3; - i = vw.x - i; - vw.width -= i; - } - saa->win.x = vw.x; - saa->win.y = vw.y; - saa->win.width = vw.width; - if (saa->win.width > 768) - saa->win.width = 768; - saa->win.height = vw.height; - if (CurrentMode == VIDEO_MODE_NTSC) { - if (saa->win.height > 480) - saa->win.height = 480; - } else { - if (saa->win.height > 576) - saa->win.height = 576; - } - - /* stop capture */ - saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); - saa7146_set_winsize(saa); - - /* - * Do any clips. - */ - if (vw.clipcount < 0) { - if (copy_from_user(saa->dmavid2, vw.clips, - VIDEO_CLIPMAP_SIZE)) - return -EFAULT; - } else if (vw.clipcount > 0) { - if ((vcp = vmalloc(sizeof(struct video_clip) * - (vw.clipcount))) == NULL) - return -ENOMEM; - if (copy_from_user(vcp, vw.clips, - 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); - - /* start capture & clip dma if we have an address */ - if ((saa->cap & 3) && saa->win.vidadr != 0) - saawrite(((SAA7146_MC1_TR_E_1 | - SAA7146_MC1_TR_E_2) << 16) | 0xffff, - SAA7146_MC1); - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - vw.x = saa->win.x; - vw.y = saa->win.y; - vw.width = saa->win.width; - vw.height = saa->win.height; - vw.chromakey = 0; - vw.flags = 0; - if (copy_to_user(arg, &vw, sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - { - int v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v == 0) { - saa->cap &= ~1; - saawrite((SAA7146_MC1_TR_E_1 << 16), - SAA7146_MC1); - } else { - if (saa->win.vidadr == 0 || saa->win.width == 0 - || saa->win.height == 0) - return -EINVAL; - saa->cap |= 1; - saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff, - SAA7146_MC1); - } - return 0; - } - case VIDIOCGFBUF: - { - struct video_buffer v; - v.base = (void *) saa->win.vidadr; - v.height = saa->win.sheight; - v.width = saa->win.swidth; - v.depth = saa->win.depth; - v.bytesperline = saa->win.bpl; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - - } - case VIDIOCSFBUF: - { - struct video_buffer v; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - 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.height > 16 && v.bytesperline > 16) - return -EINVAL; - if (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)); - saa7146_set_winsize(saa); - return 0; - } - case VIDIOCKEY: - { - /* Will be handled higher up .. */ - return 0; - } - - case VIDIOCGAUDIO: - { - struct video_audio v; - v = saa->audio_dev; - v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); - v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; - strcpy(v.name, "MPEG"); - v.mode = VIDEO_SOUND_STEREO; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - int i; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - i = (~(v.volume>>8))&0xff; - if (!HaveCS4341) { - if (v.flags & VIDEO_AUDIO_MUTE) { - debiwrite(saa, debNormal, - IBM_MP2_FRNT_ATTEN, - 0xffff, 2); - } - if (!(v.flags & VIDEO_AUDIO_MUTE)) - debiwrite(saa, debNormal, - IBM_MP2_FRNT_ATTEN, - 0x0000, 2); - if (v.flags & VIDEO_AUDIO_VOLUME) - debiwrite(saa, debNormal, - IBM_MP2_FRNT_ATTEN, - (i<<8)|i, 2); - } else { - if (v.flags & VIDEO_AUDIO_MUTE) - cs4341_setlevel(saa, 0xff, 0xff); - if (!(v.flags & VIDEO_AUDIO_MUTE)) - cs4341_setlevel(saa, 0, 0); - if (v.flags & VIDEO_AUDIO_VOLUME) - cs4341_setlevel(saa, i, i); - } - saa->audio_dev = v; - return 0; - } - - case VIDIOCGUNIT: - { - struct video_unit vu; - vu.video = saa->video_dev.minor; - vu.vbi = VIDEO_NO_UNIT; - vu.radio = VIDEO_NO_UNIT; - vu.audio = VIDEO_NO_UNIT; - vu.teletext = VIDEO_NO_UNIT; - if (copy_to_user((void *) arg, (void *) &vu, sizeof(vu))) - return -EFAULT; - return 0; - } - case VIDIOCSPLAYMODE: - { - struct video_play_mode pmode; - 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 && - 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); - 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; - 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; - } - return -EINVAL; - } - case VIDIOCSWRITEMODE: - { - int mode; - 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) { - saa->writemode = mode; - return 0; - } - return -EINVAL; - } - case VIDIOCSMICROCODE: - { - struct video_code ucode; - __u8 *udata; - int i; - if (copy_from_user((void *) &ucode, arg, - sizeof(ucode))) - return -EFAULT; - if (ucode.datasize > 65536 || ucode.datasize < 1024 || - strncmp(ucode.loadwhat, "dec", 3)) - return -EINVAL; - if ((udata = vmalloc(ucode.datasize)) == NULL) - return -ENOMEM; - if (copy_from_user((void *) udata, ucode.data, - ucode.datasize)) { - vfree(udata); - return -EFAULT; - } - ucode.data = udata; - if (!strncmp(ucode.loadwhat, "decoder.aud", 11) - || !strncmp(ucode.loadwhat, "decoder.vid", 11)) - i = initialize_ibmmpeg2(&ucode); - else - i = initialize_fpga(&ucode); - vfree(udata); - if (i) - return -EINVAL; - return 0; - - } - case VIDIOCGCHAN: /* this makes xawtv happy */ - { - struct video_channel v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - v.flags = VIDEO_VC_AUDIO; - v.tuners = 0; - v.type = VID_TYPE_MPEG_DECODER; - v.norm = CurrentMode; - strcpy(v.name, "MPEG2"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSCHAN: /* this makes xawtv happy */ - { - struct video_channel v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - /* do nothing */ - return 0; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int saa_init_done(struct video_device *dev) -{ - return 0; -} - -static int saa_mmap(struct video_device *dev, const char *adr, - unsigned long size) -{ - struct saa7146 *saa = (struct saa7146 *) dev; - printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr); - return -EINVAL; -} - -static long saa_read(struct video_device *dev, char *buf, - unsigned long count, int nonblock) -{ - return -EINVAL; -} - -static long saa_write(struct video_device *dev, const char *buf, - unsigned long count, int nonblock) -{ - struct saa7146 *saa = (struct saa7146 *) dev; - unsigned long todo = count; - int blocksize, split; - unsigned long flags; - - while (todo > 0) { - if (saa->writemode == VID_WRITE_MPEG_AUD) { - spin_lock_irqsave(&saa->lock, flags); - if (saa->audhead <= saa->audtail) - 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); - 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); - split = 65536 - saa->audtail; - } else { - blocksize = saa->audhead - saa->audtail; - split = 65536; - } - spin_unlock_irqrestore(&saa->lock, flags); - blocksize--; - if (blocksize > todo) - blocksize = todo; - /* double check that we really have space */ - if (!blocksize) - return -ENOSPC; - if (split < blocksize) { - if (copy_from_user(saa->audbuf + - saa->audtail, buf, split)) - return -EFAULT; - buf += split; - todo -= split; - blocksize -= split; - saa->audtail = 0; - } - if (copy_from_user(saa->audbuf + saa->audtail, buf, - blocksize)) - return -EFAULT; - saa->audtail += blocksize; - todo -= blocksize; - buf += blocksize; - saa->audtail &= 0xffff; - } 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); - 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); - 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); - split = 524288 - saa->vidtail; - } else { - blocksize = saa->vidhead - saa->vidtail; - split = 524288; - } - spin_unlock_irqrestore(&saa->lock, flags); - blocksize--; - if (blocksize > todo) - blocksize = todo; - /* double check that we really have space */ - if (!blocksize) - return -ENOSPC; - if (split < blocksize) { - if (copy_from_user(saa->vidbuf + - saa->vidtail, buf, split)) - return -EFAULT; - buf += split; - todo -= split; - blocksize -= split; - saa->vidtail = 0; - } - if (copy_from_user(saa->vidbuf + saa->vidtail, buf, - blocksize)) - return -EFAULT; - saa->vidtail += blocksize; - todo -= blocksize; - buf += blocksize; - saa->vidtail &= 0x7ffff; - } else if (saa->writemode == VID_WRITE_OSD) { - if (count > 131072) - return -ENOSPC; - if (copy_from_user(saa->osdbuf, buf, count)) - return -EFAULT; - buf += count; - saa->osdhead = 0; - saa->osdtail = count; - debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2); - 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); - /* trigger osd data transfer */ - saawrite(SAA7146_PSR_DEBI_S | - SAA7146_PSR_PIN1, SAA7146_IER); - saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); - } - } - return count; -} - -static int saa_open(struct video_device *dev, int flags) -{ - struct saa7146 *saa = (struct saa7146 *) dev; - - saa->video_dev.busy = 0; - saa->user++; - if (saa->user > 1) - return 0; /* device open already, don't reset */ - saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ - return 0; -} - -static void saa_close(struct video_device *dev) -{ - struct saa7146 *saa = (struct saa7146 *) dev; - saa->user--; - saa->video_dev.busy = 0; - if (saa->user > 0) /* still someone using device */ - return; - saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */ -} - -/* template for video_device-structure */ -static struct video_device saa_template = -{ - "SAA7146A", - VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, - VID_HARDWARE_SAA7146, - saa_open, - saa_close, - saa_read, - saa_write, - NULL, /* poll */ - saa_ioctl, - saa_mmap, - saa_init_done, - NULL, - 0, - 0 -}; - -static int configure_saa7146(struct pci_dev *dev, int num) -{ - int result; - struct saa7146 *saa; - - saa = &saa7146s[num]; - - saa->endmarkhead = saa->endmarktail = 0; - saa->win.x = saa->win.y = 0; - saa->win.width = saa->win.cropwidth = 720; - saa->win.height = saa->win.cropheight = 480; - saa->win.cropx = saa->win.cropy = 0; - saa->win.bpp = 2; - saa->win.depth = 16; - saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565]; - saa->win.bpl = 1024 * saa->win.bpp; - saa->win.swidth = 1024; - saa->win.sheight = 768; - saa->picture.brightness = 32768; - 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 */ - saa->saa7146_mem = NULL; - saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in = - saa->dmaa1out = saa->dmaa2in = saa->dmaa2out = - saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in = - saa->pagea1out = saa->pagea2in = saa->pagea2out = - saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 = - saa->pageRPS2 = NULL; - saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL; - saa->audhead = saa->vidtail = 0; - - init_waitqueue_head(&saa->i2cq); - init_waitqueue_head(&saa->audq); - init_waitqueue_head(&saa->debiq); - 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; - 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_mem = ioremap(saa->saa7146_adr, 0x200); - if (!saa->saa7146_mem) - return -EIO; - - memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus)); - memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); - sprintf(saa->i2c.name, "stradis%d", num); - saa->i2c.data = saa; - 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) - return result; - pci_set_master(dev); - if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0) - return -1; -#if 0 - /* i2c generic interface is currently BROKEN */ - i2c_register_bus(&saa->i2c); -#endif - return 0; -} - -static int init_saa7146(int i) -{ - struct saa7146 *saa = &saa7146s[i]; - - saa->user = 0; - /* reset the saa7146 */ - saawrite(0xffff0000, SAA7146_MC1); - mdelay(5); - /* enable debi and i2c transfers and pins */ - saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C | - SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1); - /* ensure proper state of chip */ - saawrite(0x00000000, SAA7146_PAGE1); - saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1); - saawrite(0x00000000, SAA7146_PAGE2); - saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2); - saawrite(0x00000000, SAA7146_DD1_INIT); - saawrite(0x00000000, SAA7146_DD1_STREAM_B); - saawrite(0x00000000, SAA7146_DD1_STREAM_A); - saawrite(0x00000000, SAA7146_BRS_CTRL); - saawrite(0x80400040, SAA7146_BCS_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); - /* 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; - } -#if 0 - saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */ - saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE); - for (i = 0; i < 12; i++) /* setup mmu page table */ - saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096)); -#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; - } - /* 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; - } - 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); - saawrite(256, SAA7146_PITCH2); - saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */ - saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2, - SAA7146_MC2); - I2CBusScan(&(saa->i2c)); - return 0; -} - -static void release_saa(void) -{ - u8 command; - int i; - struct saa7146 *saa; - - 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); -#if 0 - /* unregister i2c_bus */ - i2c_unregister_bus((&saa->i2c)); -#endif - - /* disable PCI bus-mastering */ - pci_read_config_byte(saa->dev, PCI_COMMAND, &command); - /* Should this be &=~ ?? */ - 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; - if (saa->vidbuf) - vfree(saa->vidbuf); - if (saa->audbuf) - vfree(saa->audbuf); - if (saa->osdbuf) - vfree(saa->osdbuf); - if (saa->dmavid2) - kfree((void *) saa->dmavid2); - saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; - saa->dmavid2 = NULL; - if (saa->dmadebi) - kfree((void *) saa->dmadebi); - if (saa->dmavid1) - kfree((void *) saa->dmavid1); - if (saa->dmavid2) - kfree((void *) saa->dmavid2); - if (saa->dmavid3) - kfree((void *) saa->dmavid3); - if (saa->dmaa1in) - kfree((void *) saa->dmaa1in); - if (saa->dmaa1out) - kfree((void *) saa->dmaa1out); - if (saa->dmaa2in) - kfree((void *) saa->dmaa2in); - if (saa->dmaa2out) - kfree((void *) saa->dmaa2out); - if (saa->dmaRPS1) - kfree((void *) saa->dmaRPS1); - if (saa->dmaRPS2) - kfree((void *) saa->dmaRPS2); - 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 __init stradis_init (void) -{ - struct pci_dev *dev = NULL; - int result = 0, i; - - 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; -} - - -static void __exit stradis_exit (void) -{ - release_saa(); - printk(KERN_INFO "stradis: module cleanup complete\n"); -} - - -module_init(stradis_init); -module_exit(stradis_exit); - diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 82e3cae1e..e6336fc03 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1518,9 +1518,14 @@ static int sx_open (struct tty_struct * tty, struct file * filp) exit minicom. I expect an "oops". -- REW */ static void sx_hungup (void *ptr) { + /* struct sx_port *port = ptr; + */ func_enter (); + /* Don't force the SX card to close. mgetty doesn't like it !!!!!! -- pvdl */ + /* For some reson we added this code. Don't know why anymore ;-( -- pvdl */ + /* sx_setsignals (port, 0, 0); sx_reconfigure_port(port); sx_send_command (port, HS_CLOSE, 0, 0); @@ -1532,7 +1537,7 @@ static void sx_hungup (void *ptr) } else sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n"); } - + */ MOD_DEC_USE_COUNT; func_exit (); } @@ -2368,7 +2373,7 @@ static int sx_init_portstructs (int nboards, int nports) return 0; } - +#ifdef MODULE static void sx_release_drivers(void) { func_enter(); @@ -2376,6 +2381,7 @@ static void sx_release_drivers(void) tty_unregister_driver(&sx_callout_driver); func_exit(); } +#endif #ifdef TWO_ZERO #define PDEV unsigned char pci_bus, unsigned pci_fun diff --git a/drivers/char/tda7432.c b/drivers/char/tda7432.c deleted file mode 100644 index 488091310..000000000 --- a/drivers/char/tda7432.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * For the STS-Thompson TDA7432 audio processor chip - * - * Handles audio functions: volume, balance, tone, loudness - * This driver will not complain if used with any - * other i2c device with the same address. - * - * Copyright (c) 2000 Eric Sandeen - * This code is placed under the terms of the GNU General Public License - * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) - * Which was based on tda8425.c by Greg Alexander (c) 1998 - * - * OPTIONS: - * debug - set to 1 if you'd like to see debug messages - * set to 2 if you'd like to be inundated with debug messages - * - * loudness - set between 0 and 15 for varying degrees of loudness effect - * - * TODO: - * Implement tone controls - * - * Revision: 0.3 - Fixed silly reversed volume controls. :) - * Revision: 0.2 - Cleaned up #defines - * fixed volume control - * Added I2C_DRIVERID_TDA7432 - * added loudness insmod control - * Revision: 0.1 - initial version - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - -/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ -#ifndef I2C_DRIVERID_TDA7432 - #define I2C_DRIVERID_TDA7432 27 -#endif - - -MODULE_AUTHOR("Eric Sandeen "); -MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip"); - -MODULE_PARM(debug,"i"); -MODULE_PARM(loudness,"i"); -static int loudness = 0; /* disable loudness by default */ -static int debug = 0; /* insmod parameter */ - - -/* Address to scan (I2C address of this chip) */ -static unsigned short normal_i2c[] = { - I2C_TDA7432 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -/* Structure of address and subaddresses for the tda7432 */ - -struct tda7432 { - int addr; - int input; - int volume; - int tone; - int lf, lr, rf, rr; - int loud; -}; - -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 - * - * TDA7432: I2C-bus controlled basic audio processor - * - * The TDA7432 controls basic audio functions like volume, balance, - * and tone control (including loudness). It also has four channel - * output (for front and rear). Since most vidcap cards probably - * don't have 4 channel output, this driver will set front & rear - * together (no independent control). - */ - - /* Subaddresses for TDA7432 */ - -#define TDA7432_IN 0x00 /* Input select */ -#define TDA7432_VL 0x01 /* Volume */ -#define TDA7432_TN 0x02 /* Bass, Treble (Tone) */ -#define TDA7432_LF 0x03 /* Attenuation LF (Left Front) */ -#define TDA7432_LR 0x04 /* Attenuation LR (Left Rear) */ -#define TDA7432_RF 0x05 /* Attenuation RF (Right Front) */ -#define TDA7432_RR 0x06 /* Attenuation RR (Right Rear) */ -#define TDA7432_LD 0x07 /* Loudness */ - - - /* Masks for bits in TDA7432 subaddresses */ - -/* Many of these not used - just for documentation */ - -/* Subaddress 0x00 - Input selection and bass control */ - -/* Bits 0,1,2 control input: - * 0x00 - Stereo input - * 0x02 - Mono input - * 0x03 - Mute - * Mono probably isn't used - I'm guessing only the stereo - * input is connected on most cards, so we'll set it to stereo. - * - * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut - * Bit 4 controls bass range: 0/1 is extended/standard bass range - * - * Highest 3 bits not used - */ - -#define TDA7432_STEREO_IN 0 -#define TDA7432_MONO_IN 2 /* Probably won't be used */ -#define TDA7432_MUTE 3 /* Probably won't be used */ -#define TDA7432_BASS_SYM 1 << 3 -#define TDA7432_BASS_NORM 1 << 4 - -/* Subaddress 0x01 - Volume */ - -/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps - * Recommended maximum is +20 dB - * - * +32dB: 0x00 - * +20dB: 0x0c - * 0dB: 0x20 - * -79dB: 0x6f - * - * MSB (bit 7) controls loudness: 1/0 is loudness on/off - */ - -#define TDA7432_VOL_0DB 0x20 -#define TDA7432_LD_ON 1 << 7 - - -/* Subaddress 0x02 - Tone control */ - -/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB - * 0x0 is 14dB, 0x7 is 0dB - * - * Bit 3 controls treble attenuation/gain (sign) - * 1 = gain (+) - * 0 = attenuation (-) - * - * Bits 4,5,6 control absolute bass gain from 0dB to 14dB - * (This is only true for normal base range, set in 0x00) - * 0x0 << 4 is 14dB, 0x7 is 0dB - * - * Bit 7 controls bass attenuation/gain (sign) - * 1 << 7 = gain (+) - * 0 << 7 = attenuation (-) - * - * Example: - * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble - */ - -#define TDA7432_TREBLE_0DB 0xf -#define TDA7432_TREBLE 7 -#define TDA7432_TREBLE_GAIN 1 << 3 -#define TDA7432_BASS_0DB 0xf << 4 -#define TDA7432_BASS 7 << 4 -#define TDA7432_BASS_GAIN 1 << 7 - - -/* Subaddress 0x03 - Left Front attenuation */ -/* Subaddress 0x04 - Left Rear attenuation */ -/* Subaddress 0x05 - Right Front attenuation */ -/* Subaddress 0x06 - Right Rear attenuation */ - -/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB - * in 1.5dB steps. - * - * 0x00 is 0dB - * 0x1f is -37.5dB - * - * Bit 5 mutes that channel when set (1 = mute, 0 = unmute) - * We'll use the mute on the input, though (above) - * Bits 6,7 unused - */ - -#define TDA7432_ATTEN_0DB 0x00 - - -/* Subaddress 0x07 - Loudness Control */ - -/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps - * when bit 4 is NOT set - * - * 0x0 is 0dB - * 0xf is -15dB - * - * If bit 4 is set, then there is a flat attenuation according to - * the lower 4 bits, as above. - * - * Bits 5,6,7 unused - */ - - - -/* Begin code */ - -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); - 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", - subaddr, val); - return -1; - } - return 0; -} - -/* I don't think we ever actually _read_ the chip... */ -#if 0 -static int tda7432_read(struct i2c_client *client) -{ - unsigned char buffer; - d2printk("tda7432: In tda7432_read\n"); - if (1 != i2c_master_recv(client,&buffer,1)) { - printk(KERN_WARNING "tda7432: I/O error, trying (read)\n"); - return -1; - } - dprintk("tda7432: Read 0x%02x\n", buffer); - return buffer; -} -#endif - -static int tda7432_set(struct i2c_client *client) -{ - struct tda7432 *t = client->data; - unsigned char buf[16]; - d2printk("tda7432: In tda7432_set\n"); - - dprintk(KERN_INFO - "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - t->input,t->volume,t->tone,t->lf,t->lr,t->rf,t->rr,t->loud); - buf[0] = TDA7432_IN; - buf[1] = t->input; - buf[2] = t->volume; - buf[3] = t->tone; - buf[4] = t->lf; - buf[5] = t->lr; - buf[6] = t->rf; - buf[7] = t->rr; - buf[8] = t->loud; - if (9 != i2c_master_send(client,buf,9)) { - printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n"); - return -1; - } - - return 0; -} - -static void do_tda7432_init(struct i2c_client *client) -{ - struct tda7432 *t = client->data; - d2printk("tda7432: In tda7432_init\n"); - - t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ - TDA7432_BASS_SYM | /* Symmetric bass cut */ - TDA7432_BASS_NORM; /* Normal bass range */ - t->volume = TDA7432_VOL_0DB; /* 0dB Volume */ - if (loudness) /* Turn loudness on? */ - t->volume |= TDA7432_LD_ON; - t->tone = TDA7432_TREBLE_0DB | /* 0dB Treble */ - TDA7432_BASS_0DB; /* 0dB Bass */ - t->lf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ - t->lr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ - t->rf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ - t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ - t->loud = loudness; /* insmod parameter */ - - tda7432_set(client); -} - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda7432_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda7432 *t; - struct i2c_client *client; - d2printk("tda7432: In tda7432_attach\n"); - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) - return -ENOMEM; - memset(t,0,sizeof *t); - do_tda7432_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA7432"); - printk(KERN_INFO "tda7432: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda7432_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda7432_attach); - return 0; -} - -static int tda7432_detach(struct i2c_client *client) -{ - struct tda7432 *t = client->data; - - do_tda7432_init(client); - i2c_detach_client(client); - - kfree(t); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda7432_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda7432 *t = client->data; - d2printk("tda7432: In tda7432_command\n"); -#if 0 - __u16 *sarg = arg; -#endif - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - - /* Query card - scale from TDA7432 settings to V4L settings */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - dprintk("tda7432: VIDIOCGAUDIO\n"); - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - - /* Master volume control - * V4L volume is min 0, max 65535 - * TDA7432 Volume: - * Min (-79dB) is 0x6f - * Max (+20dB) is 0x07 - * (Mask out bit 7 of vol - it's for the loudness setting) - */ - - va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630; - - /* Balance depends on L,R attenuation - * V4L balance is 0 to 65535, middle is 32768 - * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f - * to scale up to V4L numbers, mult by 1057 - * attenuation exists for lf, lr, rf, rr - * we use only lf and rf (front channels) - */ - - if ( (t->lf) < (t->rf) ) - /* right is attenuated, balance shifted left */ - va->balance = (32768 - 1057*(t->rf)); - else - /* left is attenuated, balance shifted right */ - va->balance = (32768 + 1057*(t->lf)); - - /* Bass/treble */ - va->bass = 32768; /* brain hurts... set to middle for now */ - va->treble = 32768; /* brain hurts... set to middle for now */ - - break; /* VIDIOCGAUDIO case */ - } - - /* Set card - scale from V4L settings to TDA7432 settings */ - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - dprintk("tda7432: VIDEOCSAUDIO\n"); - - t->volume = 0x6f - ( (va->volume)/630 ); - - if (loudness) /* Turn on the loudness bit */ - t->volume |= TDA7432_LD_ON; - - if (va->balance < 32768) { - /* shifted to left, attenuate right */ - t->rr = (32768 - va->balance)/1057; - t->rf = t->rr; - } - else { - /* shifted to right, attenuate left */ - t->lf = (va->balance - 32768)/1057; - t->lr = t->lf; - } - - /* t->tone = 0xff; */ /* Brain hurts - no tone control for now... */ - - tda7432_write(client,TDA7432_VL, t->volume); - /* tda7432_write(client,TDA7432_TN, t->tone); */ - tda7432_write(client,TDA7432_LF, t->lf); - tda7432_write(client,TDA7432_LR, t->lr); - tda7432_write(client,TDA7432_RF, t->rf); - tda7432_write(client,TDA7432_RR, t->rr); - - break; - - } /* 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 = { - "i2c tda7432 driver", - I2C_DRIVERID_TDA7432, - I2C_DF_NOTIFY, - tda7432_probe, - tda7432_detach, - tda7432_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda7432_init(void) -#endif -{ - - if ( (loudness < 0) || (loudness > 15) ) - { - printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n"); - return -EINVAL; - } - - - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/tda8425.c b/drivers/char/tda8425.c deleted file mode 100644 index a1dec22eb..000000000 --- a/drivers/char/tda8425.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * for the TDA8425 chip (I don't know which cards have this) - * WARNING: THIS DRIVER WILL LOAD WITHOUT COMPLAINTS EVEN IF A DIFFERENT - * CHIP IS AT ADDRESS 0x82 (it relies on i2c to make sure that there is a - * device acknowledging that address) - * - * Copyright (c) 1998 Greg Alexander - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from msp3400.c, which is by Gerd Knorr - * - * All of this should work, though it would be nice to eventually support - * balance (different left,right values). Also, the chip seems (?) to have - * two stereo inputs, so if someone has this card, could they tell me if the - * second one can be used for anything (i.e., does it have an external input - * that you can't hear even if you set input to composite?) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - I2C_TDA8425 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ -#define dprintk if (debug) printk - - -struct tda8425 { - int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ - int stereo; - __u16 left,right; - __u16 bass,treble; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - - -#define TDA8425_VL 0x00 /* volume left */ -#define TDA8425_VR 0x01 /* volume right */ -#define TDA8425_BA 0x02 /* bass */ -#define TDA8425_TR 0x03 /* treble */ -#define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ -#define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ -#define TDA8425_S1_ON 0xCE /* audio on (mute off) - "linear stereo" mode */ - - -/* ******************************** * - * functions for talking to TDA8425 * - * ******************************** */ - -static int tda8425_write(struct i2c_client *client, int addr, int val) -{ - unsigned char buffer[2]; - - buffer[0] = addr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda8425: I/O error, trying (write %d 0x%x)\n", - addr, val); - return -1; - } - return 0; -} - -static void tda8425_set(struct i2c_client *client) -{ - struct tda8425 *tda = client->data; - - /* mode is ignored today */ - dprintk(KERN_DEBUG "tda8425_set(%04x,%04x,%04x,%04x)\n",tda->left>>10,tda->right>>10,tda->bass>>12,tda->treble>>12); - tda8425_write(client, TDA8425_VL, tda->left>>10 |0xC0); - tda8425_write(client, TDA8425_VR, tda->right>>10 |0xC0); - tda8425_write(client, TDA8425_BA, tda->bass>>12 |0xF0); - tda8425_write(client, TDA8425_TR, tda->treble>>12|0xF0); -} - -static void do_tda8425_init(struct i2c_client *client) -{ - struct tda8425 *tda = client->data; - - tda->left=tda->right =61440; /* 0dB */ - tda->bass=tda->treble=24576; /* 0dB */ - tda->mode=AUDIO_OFF; - tda->stereo=1; - /* left=right=0x27<<10, bass=treble=0x07<<12 */ - tda8425_write(client, TDA8425_S1, TDA8425_S1_OFF); /* mute */ - tda8425_set(client); -} - -static void tda8425_audio(struct i2c_client *client, int mode) -{ - struct tda8425 *tda = client->data; - - /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ - dprintk(KERN_DEBUG "tda8425_audio:%d (T,R,E,I,O)\n",mode); - tda->mode=mode; - tda8425_write(client, TDA8425_S1, - (mode==AUDIO_OFF)?TDA8425_S1_OFF:TDA8425_S1_ON); - /* this is the function we'll need to change if it turns out the - * input-selecting capabilities should be used. */ -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda8425_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda8425 *tda; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = tda = kmalloc(sizeof *tda,GFP_KERNEL); - if (!tda) - return -ENOMEM; - memset(tda,0,sizeof *tda); - do_tda8425_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA8425"); - printk(KERN_INFO "tda8425: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda8425_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda8425_attach); - return 0; -} - - -static int tda8425_detach(struct i2c_client *client) -{ - struct tda8425 *tda = client->data; - - do_tda8425_init(client); - i2c_detach_client(client); - - kfree(tda); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda8425_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda8425 *tda = client->data; - __u16 *sarg = arg; - - switch (cmd) { - case AUDC_SET_RADIO: - tda8425_audio(client,AUDIO_RADIO); - break; - case AUDC_SET_INPUT: - tda8425_audio(client,*sarg); - 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_BASS | - VIDEO_AUDIO_TREBLE; - va->volume=MAX(tda->left,tda->right); - va->balance=(32768*MIN(tda->left,tda->right))/ - (va->volume ? va->volume : 1); - va->balance=(tda->leftright)? - (65535-va->balance) : va->balance; - va->bass = tda->bass; - va->treble = tda->treble; - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - tda->left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - tda->right = (MIN(va->balance,32768) * - va->volume) / 32768; - tda->bass = va->bass; - tda->treble = va->treble; - tda8425_set(client); - break; - } - -#if 0 - /* --- old, obsolete interface --- */ - case AUDC_GET_VOLUME_LEFT: - *sarg = tda->left; - break; - case AUDC_GET_VOLUME_RIGHT: - *sarg = tda->right; - break; - case AUDC_SET_VOLUME_LEFT: - tda->left = *sarg; - tda8425_set(client); - break; - case AUDC_SET_VOLUME_RIGHT: - tda->right = *sarg; - tda8425_set(client); - break; - - case AUDC_GET_BASS: - *sarg = tda->bass; - break; - case AUDC_SET_BASS: - tda->bass = *sarg; - tda8425_set(client); - break; - - case AUDC_GET_TREBLE: - *sarg = tda->treble; - break; - case AUDC_SET_TREBLE: - tda->treble = *sarg; - tda8425_set(client); - break; - - case AUDC_GET_STEREO: - *sarg = tda->stereo?VIDEO_SOUND_STEREO:VIDEO_SOUND_MONO; - break; - case AUDC_SET_STEREO: - tda->stereo=(*sarg==VIDEO_SOUND_MONO)?0:1; - /* TODO: make this write to the TDA9850? */ - break; - -/* case AUDC_SWITCH_MUTE: someday, maybe -- not a lot of point to - case AUDC_NEWCHANNEL: it and it would require preserving state - case AUDC_GET_DC: huh?? (not used by bttv.c) -*/ -#endif - default: - /* nothing */ - } - return 0; -} - - -static struct i2c_driver driver = { - "i2c tda8424 driver", - I2C_DRIVERID_TDA8425, - I2C_DF_NOTIFY, - tda8425_probe, - tda8425_detach, - tda8425_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda8425_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/tda985x.c b/drivers/char/tda985x.c deleted file mode 100644 index 73fb9bd52..000000000 --- a/drivers/char/tda985x.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * For the TDA9850 and TDA9855 chips - * (The TDA9855 is used on the Diamond DTV2000 and the TDA9850 is used - * on STB cards. Other cards probably use these chips as well.) - * This driver will not complain if used with any - * other i2c device with the same address. - * - * Copyright (c) 1999 Gerd Knorr - * TDA9850 code and TDA9855.c merger by Eric Sandeen (eric_sandeen@bigfoot.com) - * This code is placed under the terms of the GNU General Public License - * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) - * Which was based on tda8425.c by Greg Alexander (c) 1998 - * - * OPTIONS: - * debug - set to 1 if you'd like to see debug messages - * - set to 2 if you'd like to be flooded with debug messages - * chip - set to 9850 or 9855 to select your chip (default 9855) - * - * TODO: - * Fix channel change bug - sound goes out when changeing channels, mute - * and unmote to fix. - Is this still here? - * Fine tune sound - * Get rest of capabilities into video_audio struct... - * - * Revision 0.5 - cleaned up debugging messages, added debug level=2 - * Revision: 0.4 - check for correct chip= insmod value - * also cleaned up comments a bit - * Revision: 0.3 - took out extraneous tda985x_write in tda985x_command - * Revision: 0.2 - added insmod option chip= - * Revision: 0.1 - original version - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - -MODULE_PARM(debug,"i"); -MODULE_PARM(chip,"i"); -MODULE_PARM_DESC(chip, "Type of chip to handle: 9850 or 9855"); - -static int debug = 0; /* insmod parameter */ -static int chip = 9855; /* insmod parameter */ - -/* Addresses to scan */ -#define I2C_TDA985x_L 0xb4 -#define I2C_TDA985x_H 0xb6 -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = { - I2C_TDA985x_L >> 1, - I2C_TDA985x_H >> 1, - I2C_CLIENT_END -}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -/* This is a superset of the TDA9850 and TDA9855 members */ - -struct tda985x { - int addr; - int rvol, lvol; - int bass, treble, sub; - int c4, c5, c6, c7; - int a1, a2, a3; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define dprintk if (debug) printk -#define d2printk if (debug == 2) printk - -/* The TDA9850 and TDA9855 are both made by Philips Semiconductor - * http://www.semiconductors.philips.com - * TDA9850: I2C-bus controlled BTSC stereo/SAP decoder - * TDA9855: I2C-bus controlled BTSC stereo/SAP decoder and audio processor - * - * The TDA9850 has more or less a subset of the functions that the TDA9855 - * has. As a result, we can re-use many of these defines. Anything with - * TDA9855 is specific to that chip, anything with TDA9850 is specific - * to that chip, and anything with TDA985x is valid for either. - * - * To complicate things further, the TDA9850 uses labels C1 through C4 - * for subaddresses 0x04 through 0x07, while the TDA9855 uses - * C1 through C3 for subadresses 0x05 through 0x07 - quite confusing. - * To help keep things straight, I have renamed the various C[1,4] labels - * to C[4,7] so that the numerical label matches the hex value of the - * subaddress for both chips. At least the A[1,3] labels line up. :) - */ - - /* subaddresses for TDA9855 */ -#define TDA9855_VR 0x00 /* Volume, right */ -#define TDA9855_VL 0x01 /* Volume, left */ -#define TDA9855_BA 0x02 /* Bass */ -#define TDA9855_TR 0x03 /* Treble */ -#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */ - - /* subaddresses for TDA9850 */ -#define TDA9850_C4 0x04 /* Control 1 for TDA9850 */ - - /* subaddesses for both chips */ -#define TDA985x_C5 0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */ -#define TDA985x_C6 0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */ -#define TDA985x_C7 0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */ -#define TDA985x_A1 0x08 /* Alignment 1 for both chips */ -#define TDA985x_A2 0x09 /* Alignment 2 for both chips */ -#define TDA985x_A3 0x0a /* Alignment 3 for both chips */ - - /* Masks for bits in TDA9855 subaddresses */ -/* 0x00 - VR in TDA9855 */ -/* 0x01 - VL in TDA9855 */ -/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f) - * in 1dB steps - mute is 0x27 */ - - -/* 0x02 - BA in TDA9855 */ -/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19) - * in .5dB steps - 0 is 0x0E */ - - -/* 0x03 - TR in TDA9855 */ -/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb) - * in 3dB steps - 0 is 0x7 */ - - /* Masks for bits in both chips' subaddresses */ -/* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */ -/* Unique to TDA9855: */ -/* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf) - * in 3dB steps - mute is 0x0 */ - -/* Unique to TDA9850: */ -/* lower 4 bits control stereo noise threshold, over which stereo turns off - * set to values of 0x00 through 0x0f for Ster1 through Ster16 */ - - -/* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/ -/* Unique to TDA9855: */ -#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */ -#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */ -#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ -#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ - /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ -#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ -#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ - -/* Unique to TDA9850: */ -/* lower 4 bits contol SAP noise threshold, over which SAP turns off - * set to values of 0x00 through 0x0f for SAP1 through SAP16 */ - - -/* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */ -/* Common to TDA9855 and TDA9850: */ -#define TDA985x_SAP 3<<6 /* Selects SAP output, mute if not received */ -#define TDA985x_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */ -#define TDA985x_MONO 0 /* Forces Mono output */ -#define TDA985x_LMU 1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */ - -/* Unique to TDA9855: */ -#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */ -#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/ -#define TDA9855_LINEAR 0 /* Linear Stereo */ -#define TDA9855_PSEUDO 1 /* Pseudo Stereo */ -#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */ -#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */ -#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/ - - -/* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */ -/* Common to both TDA9855 and TDA9850: */ -/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF) - * in .5dB steps - 0dB is 0x7 */ - - -/* 0x08, 0x09 - A1 and A2 (read/write) */ -/* Common to both TDA9855 and TDA9850: */ -/* lower 5 bites are wideband and spectral expander alignment - * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */ -#define TDA985x_STP 1<<5 /* Stereo Pilot/detect (read-only) */ -#define TDA985x_SAPP 1<<6 /* SAP Pilot/detect (read-only) */ -#define TDA985x_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/ - - -/* 0x0a - A3 */ -/* Common to both TDA9855 and TDA9850: */ -/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1), - * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */ -#define TDA985x_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral */ - -/* Unique to TDA9855: */ -/* 2 bits << 5 control AVL attack time: 420ohm (0x0), 730ohm (0x2), - * 1200ohm (0x1), 2100ohm (0x3) */ - - -/* Begin code */ - -static int tda985x_write(struct i2c_client *client, int subaddr, int val) -{ - unsigned char buffer[2]; - d2printk("tda985x: In tda985x_write\n"); - dprintk("tda985x: Writing %d 0x%x\n", subaddr, val); - buffer[0] = subaddr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda985x: I/O error, trying (write %d 0x%x)\n", - subaddr, val); - return -1; - } - return 0; -} - -static int tda985x_read(struct i2c_client *client) -{ - unsigned char buffer; - d2printk("tda985x: In tda985x_read\n"); - if (1 != i2c_master_recv(client,&buffer,1)) { - printk(KERN_WARNING "tda985x: I/O error, trying (read)\n"); - return -1; - } - dprintk("tda985x: Read 0x%02x\n", buffer); - return buffer; -} - -static int tda985x_set(struct i2c_client *client) -{ - struct tda985x *t = client->data; - unsigned char buf[16]; - d2printk("tda985x: In tda985x_set\n"); - - if (chip == 9855) - { - dprintk(KERN_INFO - "tda985x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - t->rvol,t->lvol,t->bass,t->treble,t->sub, - t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); - buf[0] = TDA9855_VR; - buf[1] = t->rvol; - buf[2] = t->lvol; - buf[3] = t->bass; - buf[4] = t->treble; - buf[5] = t->sub; - buf[6] = t->c5; - buf[7] = t->c6; - buf[8] = t->c7; - buf[9] = t->a1; - buf[10] = t->a2; - buf[11] = t->a3; - if (12 != i2c_master_send(client,buf,12)) { - printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); - return -1; - } - } - - else if (chip == 9850) - { - dprintk(KERN_INFO - "tda986x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - t->c4,t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); - buf[0] = TDA9850_C4; - buf[1] = t->c4; - buf[2] = t->c5; - buf[3] = t->c6; - buf[4] = t->c7; - buf[5] = t->a1; - buf[6] = t->a2; - buf[7] = t->a3; - if (8 != i2c_master_send(client,buf,8)) { - printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); - return -1; - } - } - - return 0; -} - -static void do_tda985x_init(struct i2c_client *client) -{ - struct tda985x *t = client->data; - d2printk("tda985x: In tda985x_init\n"); - - if (chip == 9855) - { - printk("tda985x: Using tda9855 options\n"); - t->rvol = 0x6f; /* 0dB */ - t->lvol = 0x6f; /* 0dB */ - t->bass = 0x0e; /* 0dB */ - t->treble = (0x07 << 1); /* 0dB */ - t->sub = 0x8 << 2; /* 0dB */ - t->c5 = TDA9855_MUTE | TDA9855_AVL | - TDA9855_LOUD | TDA9855_INT; - /* Set Mute, AVL, Loudness off, Internal sound */ - t->c6 = TDA985x_STEREO | TDA9855_LINEAR | - TDA9855_TZCM | TDA9855_VZCM; - /* Stereo linear mode, also wait til zero crossings */ - t->c7 = 0x07; /* 0dB input gain */ - } - - else if (chip == 9850) - { - printk("tda985x: Using tda9850 options\n"); - t->c4 = 0x08; /* Set stereo noise thresh to nominal */ - t->c5 = 0x08; /* Set SAP noise threshold to nominal */ - t->c6 = TDA985x_STEREO; /* Select Stereo mode for decoder */ - t->c7 = 0x07; /* 0dB input gain */ - } - - /* The following is valid for both chip types */ - t->a1 = 0x10; /* Select nominal wideband expander */ - t->a2 = 0x10; /* Select nominal spectral expander and 30mV trigger */ - t->a3 = 0x3; /* Set: nominal timing current, 420ohm AVL attack */ - - tda985x_set(client); -} - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda985x_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda985x *t; - struct i2c_client *client; - d2printk("tda985x: In tda985x_attach\n"); - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) - return -ENOMEM; - memset(t,0,sizeof *t); - do_tda985x_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA985x"); - printk(KERN_INFO "tda985x: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda985x_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda985x_attach); - return 0; -} - -static int tda985x_detach(struct i2c_client *client) -{ - struct tda985x *t = client->data; - - do_tda985x_init(client); - i2c_detach_client(client); - - kfree(t); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda985x_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda985x *t = client->data; - d2printk("tda985x: In tda985x_command\n"); -#if 0 - __u16 *sarg = arg; -#endif - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - dprintk("tda985x: VIDIOCGAUDIO\n"); - if (chip == 9855) - { - int left,right; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - - /* min is 0x27 max is 0x7f, vstep is 2e8 */ - left = (t->lvol-0x27)*0x2e8; - right = (t->rvol-0x27)*0x2e8; - va->volume=MAX(left,right); - va->balance=(32768*MIN(left,right))/ - (va->volume ? va->volume : 1); - va->balance=(leftbalance) : va->balance; - va->bass = (t->bass-0x6)*0xccc; /* min 0x6 max 0x19 */ - va->treble = ((t->treble>>1)-0x3)*0x1c71; - } - - /* Valid for both chips: */ - { - va->mode = ((TDA985x_STP | TDA985x_SAPP) & - tda985x_read(client)) >> 4; - /* Add mono mode regardless of SAP and stereo */ - /* Allows forced mono */ - va->mode |= VIDEO_SOUND_MONO; - } - - break; /* VIDIOCGAUDIO case */ - } - - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - dprintk("tda985x: VIDEOCSAUDIO\n"); - if (chip == 9855) - { - int left,right; - - left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - right = (MIN(va->balance,32768) * - va->volume) / 32768; - t->lvol = left/0x2e8+0x27; - t->rvol = right/0x2e8+0x27; - t->bass = va->bass/0xccc+0x6; - t->treble = (va->treble/0x1c71+0x3)<<1; - tda985x_write(client,TDA9855_VL,t->lvol); - tda985x_write(client,TDA9855_VR,t->rvol); - tda985x_write(client,TDA9855_BA, t->bass); - tda985x_write(client,TDA9855_TR,t->treble); - } - - /* The following is valid for both chips */ - - switch (va->mode) { - case VIDEO_SOUND_MONO: - dprintk("tda985x: VIDEO_SOUND_MONO\n"); - t->c6= TDA985x_MONO | (t->c6 & 0x3f); - tda985x_write(client,TDA985x_C6,t->c6); - break; - case VIDEO_SOUND_STEREO: - dprintk("tda985x: VIDEO_SOUND_STEREO\n"); - t->c6= TDA985x_STEREO | (t->c6 & 0x3f); - tda985x_write(client,TDA985x_C6,t->c6); - break; - case VIDEO_SOUND_LANG1: - dprintk("tda985x: VIDEO_SOUND_LANG1\n"); - t->c6= TDA985x_SAP | (t->c6 & 0x3f); - tda985x_write(client,TDA985x_C6,t->c6); - break; - } /* End of (va->mode) switch */ - - break; - - } /* end of VIDEOCSAUDIO case */ - - default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ - - /* nothing */ - d2printk("tda985x: Default\n"); - - } /* end of (cmd) switch */ - - return 0; -} - - -static struct i2c_driver driver = { - "i2c tda985x driver", - I2C_DRIVERID_TDA9855, /* Get new one for TDA985x? */ - I2C_DF_NOTIFY, - tda985x_probe, - tda985x_detach, - tda985x_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda985x_init(void) -#endif -{ - if ( (chip != 9850) && (chip != 9855) ) - { - printk(KERN_ERR "tda985x: chip parameter must be 9850 or 9855\n"); - return -EINVAL; - } - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/tda9875.c b/drivers/char/tda9875.c deleted file mode 100644 index 9f6ecd332..000000000 --- a/drivers/char/tda9875.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * For the TDA9875 chip - * (The TDA9875 is used on the Diamond DTV2000 french version - * Other cards probably use these chips as well.) - * This driver will not complain if used with any - * other i2c device with the same address. - * - * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and - * Eric Sandeen - * This code is placed under the terms of the GNU General Public License - * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) - * Which was based on tda8425.c by Greg Alexander (c) 1998 - * - * OPTIONS: - * debug - set to 1 if you'd like to see debug messages - * - * Revision: 0.1 - original version - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - -/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ -#ifndef I2C_DRIVERID_TDA9875 - #define I2C_DRIVERID_TDA9875 28 -#endif - - -MODULE_PARM(debug,"i"); - -static int debug = 0; /* insmod parameter */ - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - I2C_TDA9875 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -/* This is a superset of the TDA9875 */ -struct tda9875 { - int mode; - int rvol, lvol; - int bass, treble; -}; - - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define dprintk if (debug) printk - -/* The TDA9875 is made by Philips Semiconductor - * http://www.semiconductors.philips.com - * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator - * - */ - - /* subaddresses for TDA9875 */ -#define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ -#define TDA9875_CFG 0x01 /* Config register (value --> 0b00000000 */ -#define TDA9875_DACOS 0x13 /*DAC i/o select (ADC) 0b0000100*/ -#define TDA9875_LOSR 0x16 /*Line output select regirter 0b0100 0001*/ - -#define TDA9875_CH1V 0x0c /*Chanel 1 volume (mute)*/ -#define TDA9875_CH2V 0x0d /*Chanel 2 volume (mute)*/ -#define TDA9875_SC1 0x14 /*SCART 1 in (mono)*/ -#define TDA9875_SC2 0x15 /*SCART 2 in (mono)*/ - -#define TDA9875_ADCIS 0x17 /*ADC input select (mono) 0b0110 000*/ -#define TDA9875_AER 0x19 /*Audio effect (AVL+Pseudo) 0b0000 0110*/ -#define TDA9875_MCS 0x18 /*Main channel select (DAC) 0b0000100*/ -#define TDA9875_MVL 0x1a /* Main volume gauche */ -#define TDA9875_MVR 0x1b /* Main volume droite */ -#define TDA9875_MBA 0x1d /* Main Basse */ -#define TDA9875_MTR 0x1e /* Main treble */ -#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ -#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ -#define TDA9875_AVR 0x21 /* Auxilary volume droite */ -#define TDA9875_ABA 0x22 /* Auxilary Basse */ -#define TDA9875_ATR 0x23 /* Auxilary treble */ - -#define TDA9875_MSR 0x02 /* Monitor select register */ -#define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ -#define TDA9875_C1MIB 0x04 /* Carrier 1 (FM) frequency register (16-8]b */ -#define TDA9875_C1LSB 0x05 /* Carrier 1 (FM) frequency register LSB */ -#define TDA9875_C2MSB 0x06 /* Carrier 2 (nicam) frequency register MSB */ -#define TDA9875_C2MIB 0x07 /* Carrier 2 (nicam) frequency register (16-8]b */ -#define TDA9875_C2LSB 0x08 /* Carrier 2 (nicam) frequency register LSB */ -#define TDA9875_DCR 0x09 /* Demodulateur configuration regirter*/ -#define TDA9875_DEEM 0x0a /* FM de-emphasis regirter*/ -#define TDA9875_FMAT 0x0b /* FM Matrix regirter*/ - -/* values */ -#define TDA9875_MUTE_ON 0xff /* general mute */ -#define TDA9875_MUTE_OFF 0xcc /* general no mute */ - - - -/* Begin code */ - -static int tda9875_write(struct i2c_client *client, int subaddr, unsigned char val) -{ - unsigned char buffer[2]; - dprintk("In tda9875_write\n"); - dprintk("Writing %d 0x%x\n", subaddr, val); - buffer[0] = subaddr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda9875: I/O error, trying (write %d 0x%x)\n", - subaddr, val); - return -1; - } - return 0; -} - -#if 0 -static int tda9875_read(struct i2c_client *client) -{ - unsigned char buffer; - dprintk("In tda9875_read\n"); - if (1 != i2c_master_recv(client,&buffer,1)) { - printk(KERN_WARNING "tda9875: I/O error, trying (read)\n"); - return -1; - } - dprintk("Read 0x%02x\n", buffer); - return buffer; -} -#endif - -static void tda9875_set(struct i2c_client *client) -{ - struct tda9875 *tda = client->data; - unsigned char a; - - dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble); - - - a = tda->lvol & 0xff; - tda9875_write(client, TDA9875_MVL, a); - a =tda->rvol & 0xff; - tda9875_write(client, TDA9875_MVR, a); - a =tda->bass & 0xff; - tda9875_write(client, TDA9875_MBA, a); - a =tda->treble & 0xff; - tda9875_write(client, TDA9875_MTR, a); -} - -static void do_tda9875_init(struct i2c_client *client) -{ - struct tda9875 *t = client->data; - dprintk("In tda9875_init\n"); - tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ - tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ - tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ - tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ - tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ - tda9875_write(client, TDA9875_C2MSB, 0x00 ); /*Car2(NICAM) MSB XMHz*/ - tda9875_write(client, TDA9875_C2MIB, 0x00 ); /*Car2(NICAM) MIB XMHz*/ - tda9875_write(client, TDA9875_C2LSB, 0x00 ); /*Car2(NICAM) LSB XMHz*/ - tda9875_write(client, TDA9875_DCR, 0x00 ); /*Demod config 0x00*/ - tda9875_write(client, TDA9875_DEEM, 0x44 ); /*DE-Emph 0b0100 0100*/ - tda9875_write(client, TDA9875_FMAT, 0x00 ); /*FM Matrix reg 0x00*/ - tda9875_write(client, TDA9875_SC1, 0x00 ); /* SCART 1 (SC1)*/ - tda9875_write(client, TDA9875_SC2, 0x01 ); /* SCART 2 (sc2)*/ - - tda9875_write(client, TDA9875_CH1V, 0x10 ); /* Chanel volume 1 mute*/ - tda9875_write(client, TDA9875_CH2V, 0x10 ); /* Chanel volume 2 mute */ - tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ - tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ - tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ - tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ - tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ - tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ - tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ - tda9875_write(client, TDA9875_MBA, 0x00 ); /* Main Bass Main 0dB*/ - tda9875_write(client, TDA9875_MTR, 0x00 ); /* Main Treble Main 0dB*/ - tda9875_write(client, TDA9875_ACS, 0x44 ); /* Aux chan select (dac)*/ - tda9875_write(client, TDA9875_AVL, 0x00 ); /* Vol Aux left 0dB*/ - tda9875_write(client, TDA9875_AVR, 0x00 ); /* Vol Aux right 0dB*/ - tda9875_write(client, TDA9875_ABA, 0x00 ); /* Aux Bass Main 0dB*/ - tda9875_write(client, TDA9875_ATR, 0x00 ); /* Aux Aigus Main 0dB*/ - - tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ - - t->mode=AUDIO_UNMUTE; - t->lvol=t->rvol =0; /* 0dB */ - t->bass=0; /* 0dB */ - t->treble=0; /* 0dB */ - tda9875_set(client); - -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda9875_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda9875 *t; - struct i2c_client *client; - dprintk("In tda9875_attach\n"); - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) - return -ENOMEM; - memset(t,0,sizeof *t); - do_tda9875_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA9875"); - printk(KERN_INFO "tda9875: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda9875_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda9875_attach); - return 0; -} - -static int tda9875_detach(struct i2c_client *client) -{ - struct tda9875 *t = client->data; - - do_tda9875_init(client); - i2c_detach_client(client); - - kfree(t); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda9875_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda9875 *t = client->data; - - dprintk("In tda9875_command...\n"); - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - int left,right; - - dprintk("VIDIOCGAUDIO\n"); - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - - /* min is -84 max is 24 */ - left = (t->lvol+84)*606; - right = (t->rvol+84)*606; - va->volume=MAX(left,right); - va->balance=(32768*MIN(left,right))/ - (va->volume ? va->volume : 1); - va->balance=(leftbalance) : va->balance; - va->bass = (t->bass+12)*2427; /* min -12 max +15 */ - va->treble = (t->treble+12)*2730;/* min -12 max +12 */ - - va->mode |= VIDEO_SOUND_MONO; - - - break; /* VIDIOCGAUDIO case */ - } - - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - int left,right; - - dprintk("VIDEOCSAUDIO...\n"); - left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - right = (MIN(va->balance,32768) * - va->volume) / 32768; - t->lvol = ((left/606)-84) & 0xff; - if (t->lvol > 24) - t->lvol = 24; - if (t->lvol < -84) - t->lvol = -84 & 0xff; - - t->rvol = ((right/606)-84) & 0xff; - if (t->rvol > 24) - t->rvol = 24; - if (t->rvol < -84) - t->rvol = -84 & 0xff; - - t->bass = ((va->bass/2400)-12) & 0xff; - if (t->bass > 15) - t->bass = 15; - if (t->bass < -12) - t->bass = -12 & 0xff; - - t->treble = ((va->treble/2700)-12) & 0xff; - if (t->treble > 12) - t->treble = 12; - if (t->treble < -12) - t->treble = -12 & 0xff; - - - -//printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); - - - tda9875_set(client); - - break; - - } /* end of VIDEOCSAUDIO case */ - - default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ - - /* nothing */ - dprintk("Default\n"); - - } /* end of (cmd) switch */ - - return 0; -} - - -static struct i2c_driver driver = { - "i2c tda9875 driver", - I2C_DRIVERID_TDA9875, /* Get new one for TDA9875 */ - I2C_DF_NOTIFY, - tda9875_probe, - tda9875_detach, - tda9875_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda9875_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ - diff --git a/drivers/char/tea6300.c b/drivers/char/tea6300.c deleted file mode 100644 index f5949c94f..000000000 --- a/drivers/char/tea6300.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * for the TEA6300 chip (only found on Gateway STB TV/FM cards tho the best - * of my knowledge) - * WARNING: THIS DRIVER WILL LOAD WITHOUT COMPLAINTS EVEN IF THE WRONG - * CHIP (i.e., an MSP3400) IS ON I2C ADDRESS 0x80 (it relies on i2c to - * make sure that there is a device acknowledging that address). This - * is a potential problem because the MSP3400 is very popular and does - * use this address! You have been warned! - * - * Copyright (c) 1998 Greg Alexander - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from msp3400.c, which is by Gerd Knorr - * - * All of this should work, though it would be nice to eventually support - * balance (different left,right values) and, if someone ever finds a card - * with the support (or if you're careful with a soldering iron), fade - * (front/back). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - - -/* Addresses to scan */ -#define I2C_TEA6300 0x80 -static unsigned short normal_i2c[] = { - I2C_TEA6300 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ - -#define dprintk if (debug) printk - - -struct tea6300 { - int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ - int stereo; - __u16 left,right; - __u16 bass,treble; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define TEA6300_VL 0x00 /* volume left */ -#define TEA6300_VR 0x01 /* volume right */ -#define TEA6300_BA 0x02 /* bass */ -#define TEA6300_TR 0x03 /* treble */ -#define TEA6300_FA 0x04 /* fader control */ -#define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ -#define TEA6300_S_SA 0x01 /* stereo A input */ -#define TEA6300_S_SB 0x02 /* stereo B */ -#define TEA6300_S_SC 0x04 /* stereo C */ -#define TEA6300_S_GMU 0x80 /* general mute */ - - -/* ******************************** * - * functions for talking to TEA6300 * - * ******************************** */ - -static int tea6300_write(struct i2c_client *client, int addr, int val) -{ - unsigned char buffer[2]; - - buffer[0] = addr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tea6300: I/O error, trying (write %d 0x%x)\n", - addr, val); - return -1; - } - return 0; -} - -static void tea6300_set(struct i2c_client *client) -{ - struct tea6300 *tea = client->data; - - /* mode is ignored today */ - dprintk(KERN_DEBUG "tea6300_set(%04x,%04x,%04x,%04x)\n",tea->left>>10,tea->right>>10,tea->bass>>12,tea->treble>>12); - tea6300_write(client, TEA6300_VL, tea->left>>10 ); - tea6300_write(client, TEA6300_VR, tea->right>>10 ); - tea6300_write(client, TEA6300_BA, tea->bass>>12 ); - tea6300_write(client, TEA6300_TR, tea->treble>>12); -} - -static void do_tea6300_init(struct i2c_client *client) -{ - struct tea6300 *tea = client->data; - - tea->left=tea->right =49152; /* -10dB (loud enough, but not beyond - normal line levels - so as to avoid - clipping */ - tea->bass=tea->treble=28672; /* 0dB */ - tea->mode=AUDIO_OFF; - tea->stereo=1; - /* left=right=0x27<<10, bass=treble=0x07<<12 */ - tea6300_write(client, TEA6300_FA, 0x3f ); /* fader off */ - tea6300_write(client, TEA6300_S , TEA6300_S_GMU); /* mute */ - tea6300_set(client); -} - -static void tea6300_audio(struct i2c_client *client, int mode) -{ - struct tea6300 *tea = client->data; - - /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ - dprintk(KERN_DEBUG "tea6300_audio:%d (T,R,E,I,O)\n",mode); - tea->mode=mode; - if (mode==AUDIO_OFF) { /* just mute it */ - tea6300_write(client, TEA6300_S, TEA6300_S_GMU); - return; - } - switch(mode) { - case AUDIO_TUNER: - tea6300_write(client, TEA6300_S, TEA6300_S_SA); - break; - case AUDIO_RADIO: - tea6300_write(client, TEA6300_S, TEA6300_S_SB); - break; - case AUDIO_EXTERN: - tea6300_write(client, TEA6300_S, TEA6300_S_SC); - break; - } -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tea6300_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tea6300 *tea; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = tea = kmalloc(sizeof *tea,GFP_KERNEL); - if (!tea) - return -ENOMEM; - memset(tea,0,sizeof *tea); - do_tea6300_init(client); - - MOD_INC_USE_COUNT; - strcpy(client->name,"TEA6300T"); - printk(KERN_INFO "tea6300: initialized\n"); - - i2c_attach_client(client); - return 0; -} - -static int tea6300_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tea6300_attach); - return 0; -} - -static int tea6300_detach(struct i2c_client *client) -{ - struct tea6300 *tea = client->data; - - do_tea6300_init(client); - i2c_detach_client(client); - - kfree(tea); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int -tea6300_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct tea6300 *tea = client->data; - __u16 *sarg = arg; - - switch (cmd) { - case AUDC_SET_RADIO: - tea6300_audio(client,AUDIO_RADIO); - break; - case AUDC_SET_INPUT: - tea6300_audio(client,*sarg); - 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_BASS | - VIDEO_AUDIO_TREBLE; - va->volume=MAX(tea->left,tea->right); - va->balance=(32768*MIN(tea->left,tea->right))/ - (va->volume ? va->volume : 1); - va->balance=(tea->leftright)? - (65535-va->balance) : va->balance; - va->bass = tea->bass; - va->treble = tea->treble; - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - tea->left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - tea->right = (MIN(va->balance,32768) * - va->volume) / 32768; - tea->bass = va->bass; - tea->treble = va->treble; - tea6300_set(client); - break; - } -#if 0 - /* --- old, obsolete interface --- */ - case AUDC_GET_VOLUME_LEFT: - *sarg = tea->left; - break; - case AUDC_GET_VOLUME_RIGHT: - *sarg = tea->right; - break; - case AUDC_SET_VOLUME_LEFT: - tea->left = *sarg; - tea6300_set(client); - break; - case AUDC_SET_VOLUME_RIGHT: - tea->right = *sarg; - tea6300_set(client); - break; - - case AUDC_GET_BASS: - *sarg = tea->bass; - break; - case AUDC_SET_BASS: - tea->bass = *sarg; - tea6300_set(client); - break; - - case AUDC_GET_TREBLE: - *sarg = tea->treble; - break; - case AUDC_SET_TREBLE: - tea->treble = *sarg; - tea6300_set(client); - break; - - case AUDC_GET_STEREO: - *sarg = tea->stereo?VIDEO_SOUND_STEREO:VIDEO_SOUND_MONO; - break; - case AUDC_SET_STEREO: - tea->stereo=(*sarg==VIDEO_SOUND_MONO)?0:1; - /* TODO: make this write to the TDA9850? */ - break; - -/* case AUDC_SWITCH_MUTE: someday, maybe -- not a lot of point to - case AUDC_NEWCHANNEL: it and it would require preserving state - case AUDC_GET_DC: huh?? (not used by bttv.c) -*/ -#endif - default: - /* nothing */ - } - return 0; -} - -static struct i2c_driver driver = { - "i2c tea6300 driver", - I2C_DRIVERID_TEA6300, - I2C_DF_NOTIFY, - tea6300_probe, - tea6300_detach, - tea6300_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tea6300_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/tea6420.c b/drivers/char/tea6420.c deleted file mode 100644 index 231ed9e4e..000000000 --- a/drivers/char/tea6420.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * for the TEA6420 chip (only found on 3DFX (STB) TV/FM cards to the best - * of my knowledge) - * Copyright (C) 2000 Dave Stuart - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from tea6300 by . . . - * - * Copyright (c) 1998 Greg Alexander - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from msp3400.c, which is by Gerd Knorr - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - - -/* Addresses to scan */ -#define I2C_TEA6420 0x98 -static unsigned short normal_i2c[] = { - I2C_TEA6420 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ - -#define dprintk if (debug) printk - - -struct tea6420 { - int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ - int stereo; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define TEA6420_S_SA 0x00 /* stereo A input */ -#define TEA6420_S_SB 0x01 /* stereo B */ -#define TEA6420_S_SC 0x02 /* stereo C */ -#define TEA6420_S_SD 0x03 /* stereo D */ -#define TEA6420_S_SE 0x04 /* stereo E */ -#define TEA6420_S_GMU 0x05 /* general mute */ - - -/* ******************************** * - * functions for talking to TEA6420 * - * ******************************** */ - -static int tea6420_write(struct i2c_client *client, int val) -{ - unsigned char buffer[2]; - int result; - -/* buffer[0] = addr; */ - buffer[0] = val; - result = i2c_master_send(client,buffer,1); - if (1 != result) { - printk(KERN_WARNING "tea6420: I/O error, trying (write -0x%x) result = %d\n", val, result); - return -1; - } - return 0; -} - - -static void do_tea6420_init(struct i2c_client *client) -{ - struct tea6420 *tea = client->data; - - tea->mode=AUDIO_OFF; - tea->stereo=1; - tea6420_write(client, TEA6420_S_GMU); /* mute */ -} - -static void tea6420_audio(struct i2c_client *client, int mode) -{ - struct tea6420 *tea = client->data; - - /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ - dprintk(KERN_DEBUG "tea6420_audio:%d (T,R,E,I,O)\n",mode); - tea->mode=mode; - if (mode==AUDIO_OFF) { /* just mute it */ - tea6420_write(client, TEA6420_S_GMU); - return; - } - switch(mode) { - case AUDIO_TUNER: - tea6420_write(client, TEA6420_S_SA); - break; - case AUDIO_RADIO: - tea6420_write(client, TEA6420_S_SB); - break; - case AUDIO_EXTERN: - tea6420_write(client, TEA6420_S_SC); - break; - } -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tea6420_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tea6420 *tea; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = tea = kmalloc(sizeof *tea,GFP_KERNEL); - if (!tea) - return -ENOMEM; - memset(tea,0,sizeof *tea); - do_tea6420_init(client); - - MOD_INC_USE_COUNT; - strcpy(client->name,"TEA6420"); - printk(KERN_INFO "tea6420: initialized\n"); - - i2c_attach_client(client); - return 0; -} - -static int tea6420_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tea6420_attach); - return 0; -} - -static int tea6420_detach(struct i2c_client *client) -{ - struct tea6420 *tea = client->data; - - do_tea6420_init(client); - i2c_detach_client(client); - - kfree(tea); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int -tea6420_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - __u16 *sarg = arg; - - switch (cmd) { - case AUDC_SET_RADIO: - tea6420_audio(client,AUDIO_RADIO); - break; - case AUDC_SET_INPUT: - tea6420_audio(client,*sarg); - 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_BASS | - VIDEO_AUDIO_TREBLE; -/* va->volume=MAX(tea->left,tea->right); - va->balance=(32768*MIN(tea->left,tea->right))/ - (va->volume ? va->volume : 1); - va->balance=(tea->leftright)? - (65535-va->balance) : va->balance; - va->bass = tea->bass; - va->treble = tea->treble; -*/ break; - } - case VIDIOCSAUDIO: - { - -/* tea->left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - tea->right = (MIN(va->balance,32768) * - va->volume) / 32768; - tea->bass = va->bass; - tea->treble = va->treble; - tea6420_set(client); -*/ break; - } - -default: - /* nothing */ - } - return 0; -} - -static struct i2c_driver driver = { - "i2c tea6420 driver", - I2C_DRIVERID_TEA6420, - I2C_DF_NOTIFY, - tea6420_probe, - tea6420_detach, - tea6420_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tea6420_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0d6e6f3fa..17fce4ddf 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1839,9 +1839,12 @@ void do_SAK( struct tty_struct *tty) read_lock(&tasklist_lock); for_each_task(p) { if ((p->tty == tty) || - ((session > 0) && (p->session == session))) + ((session > 0) && (p->session == session))) { send_sig(SIGKILL, p, 1); - else if (p->files) { + continue; + } + task_lock(p); + if (p->files) { read_lock(&p->files->file_lock); /* FIXME: p->files could change */ for (i=0; i < p->files->max_fds; i++) { @@ -1854,6 +1857,7 @@ void do_SAK( struct tty_struct *tty) } read_unlock(&p->files->file_lock); } + task_unlock(p); } read_unlock(&tasklist_lock); #endif diff --git a/drivers/char/tuner-3036.c b/drivers/char/tuner-3036.c deleted file mode 100644 index 807ae339b..000000000 --- a/drivers/char/tuner-3036.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Driver for Philips SAB3036 "CITAC" tuner control chip. - * - * Author: Phil Blundell - * - * The SAB3036 is just about different enough from the chips that - * tuner.c copes with to make it not worth the effort to crowbar - * the support into that file. So instead we have a separate driver. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "tuner.h" - -static int debug; /* insmod parameter */ -static int this_adap; - -static struct i2c_client client_template; - -/* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {0x60, 0x61, I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; - -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -/* ---------------------------------------------------------------------- */ - -static unsigned char -tuner_getstatus (struct i2c_client *c) -{ - unsigned char byte; - if (i2c_master_recv(c, &byte, 1) != 1) - printk(KERN_ERR "tuner-3036: I/O error.\n"); - return byte; -} - -#define TUNER_FL 0x80 - -static int -tuner_islocked (struct i2c_client *c) -{ - return (tuner_getstatus(c) & TUNER_FL); -} - -/* ---------------------------------------------------------------------- */ - -static void -set_tv_freq(struct i2c_client *c, int freq) -{ - u16 div = ((freq * 20) / 16); - unsigned long give_up = jiffies + HZ; - unsigned char buffer[2]; - - if (debug) - printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div); - - /* Select high tuning current */ - buffer[0] = 0x29; - buffer[1] = 0x3e; - - if (i2c_master_send(c, buffer, 2) != 2) - printk("tuner: i2c i/o error 1\n"); - - buffer[0] = 0x80 | ((div>>8) & 0x7f); - buffer[1] = div & 0xff; - - if (i2c_master_send(c, buffer, 2) != 2) - printk("tuner: i2c i/o error 2\n"); - - while (!tuner_islocked(c) && time_before(jiffies, give_up)) - schedule(); - - if (!tuner_islocked(c)) - printk(KERN_WARNING "tuner: failed to achieve PLL lock\n"); - - /* Select low tuning current and engage AFC */ - buffer[0] = 0x29; - buffer[1] = 0xb2; - - if (i2c_master_send(c, buffer, 2) != 2) - printk("tuner: i2c i/o error 3\n"); - - if (debug) - printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c)); -} - -/* ---------------------------------------------------------------------- */ - -static int -tuner_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 }; - - struct i2c_client *client; - - if (this_adap > 0) - return -1; - this_adap++; - - client_template.adapter = adap; - client_template.addr = addr; - - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &client_template, sizeof(struct i2c_client)); - - printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client)); - - i2c_attach_client(client); - MOD_INC_USE_COUNT; - - if (i2c_master_send(client, buffer, 2) != 2) - printk("tuner: i2c i/o error 1\n"); - if (i2c_master_send(client, buffer+2, 2) != 2) - printk("tuner: i2c i/o error 2\n"); - if (i2c_master_send(client, buffer+4, 2) != 2) - printk("tuner: i2c i/o error 3\n"); - return 0; -} - -static int -tuner_detach(struct i2c_client *c) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -static int -tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - int *iarg = (int*)arg; - - switch (cmd) - { - case TUNER_SET_TVFREQ: - set_tv_freq(client, *iarg); - break; - - default: - return -EINVAL; - } - return 0; -} - -static int -tuner_probe(struct i2c_adapter *adap) -{ - this_adap = 0; - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_LP)) - return i2c_probe(adap, &addr_data, tuner_attach); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver -i2c_driver_tuner = -{ - "sab3036", /* name */ - I2C_DRIVERID_SAB3036, /* ID */ - I2C_DF_NOTIFY, - tuner_probe, - tuner_detach, - tuner_command -}; - -static struct i2c_client client_template = -{ - "SAB3036", /* name */ - -1, - 0, - 0, - NULL, - &i2c_driver_tuner -}; - -EXPORT_NO_SYMBOLS; - -int __init -tuner3036_init(void) -{ - i2c_add_driver(&i2c_driver_tuner); - return 0; -} - -void __exit -tuner3036_exit(void) -{ - i2c_del_driver(&i2c_driver_tuner); -} - -MODULE_DESCRIPTION("SAB3036 tuner driver"); -MODULE_AUTHOR("Philip Blundell "); -MODULE_PARM(debug,"i"); -MODULE_PARM_DESC(debug,"Enable debugging output"); - -module_init(tuner3036_init); -module_exit(tuner3036_exit); diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c deleted file mode 100644 index dfbf0f6af..000000000 --- a/drivers/char/tuner.c +++ /dev/null @@ -1,451 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tuner.h" -#include "audiochip.h" - -/* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -static int debug = 0; /* insmod parameter */ -static int type = -1; /* insmod parameter */ - -static int addr = 0; -static int this_adap; - -#define dprintk if (debug) printk - -MODULE_PARM(debug,"i"); -MODULE_PARM(type,"i"); -MODULE_PARM(addr,"i"); - -struct tuner -{ - int type; /* chip type */ - int freq; /* keep track of the current settings */ - int std; - - int radio; - int mode; /* PAL(0)/SECAM(1) mode (PHILIPS_SECAM only) */ -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -/* ---------------------------------------------------------------------- */ - -struct tunertype -{ - char *name; - unsigned char Vendor; - unsigned char Type; - - unsigned short thresh1; /* frequency Range for UHF,VHF-L, VHF_H */ - unsigned short thresh2; - unsigned char VHF_L; - unsigned char VHF_H; - unsigned char UHF; - unsigned char config; - unsigned short IFPCoff; - unsigned char mode; /* mode change value (tested PHILIPS_SECAM only) */ - /* 0x01 -> ??? no change ??? */ - /* 0x02 -> PAL BDGHI / SECAM L */ - /* 0x04 -> ??? PAL others / SECAM others ??? */ - int capability; -}; - -/* - * The floats in the tuner struct are computed at compile time - * by gcc and cast back to integers. Thus we don't violate the - * "no float in kernel" rule. - */ -static struct tunertype tuners[] = { - { "Temic PAL", TEMIC, PAL, - 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623}, - { "Philips PAL_I", Philips, PAL_I, - 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, - { "Philips NTSC", Philips, NTSC, - 16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732}, - { "Philips SECAM", Philips, SECAM, - 16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623,0x02}, - { "NoTuner", NoTuner, NOTUNER, - 0,0,0x00,0x00,0x00,0x00,0x00,000}, - { "Philips PAL", Philips, PAL, - 16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623}, - { "Temic NTSC", TEMIC, NTSC, - 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, - { "Temic PAL_I", TEMIC, PAL_I, - 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, - { "Temic 4036 FY5 NTSC", TEMIC, NTSC, - 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, - { "Alps HSBH1", TEMIC, NTSC, - 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, - { "Alps TSBE1",TEMIC,PAL, - 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, - { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modtec 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 4006FH5", TEMIC, PAL_I, - 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, -}; -#define TUNERS (sizeof(tuners)/sizeof(struct tunertype)) - -/* ---------------------------------------------------------------------- */ - -static int tuner_getstatus(struct i2c_client *c) -{ - unsigned char byte; - - if (1 != i2c_master_recv(c,&byte,1)) - return 0; - return byte; -} - -#define TUNER_POR 0x80 -#define TUNER_FL 0x40 -#define TUNER_MODE 0x38 -#define TUNER_AFC 0x07 - -static int tuner_islocked (struct i2c_client *c) -{ - return (tuner_getstatus (c) & TUNER_FL); -} - -static int tuner_afcstatus (struct i2c_client *c) -{ - return (tuner_getstatus (c) & TUNER_AFC) - 2; -} - -#if 0 /* unused */ -static int tuner_mode (struct i2c_client *c) -{ - return (tuner_getstatus (c) & TUNER_MODE) >> 3; -} -#endif - -static void set_tv_freq(struct i2c_client *c, int freq) -{ - u8 config; - u16 div; - struct tunertype *tun; - struct tuner *t = c->data; - unsigned char buffer[4]; - int rc; - - if (t->type == -1) { - printk("tuner: tuner type not set\n"); - return; - } - - tun=&tuners[t->type]; - if (freq < tun->thresh1) - config = tun->VHF_L; - else if (freq < tun->thresh2) - config = tun->VHF_H; - else - config = tun->UHF; - -#if 1 // Fix colorstandard mode change - if (t->type == TUNER_PHILIPS_SECAM && t->mode) - config |= tun->mode; - else - config &= ~tun->mode; -#else - config &= ~tun->mode; -#endif - - div=freq + tun->IFPCoff; - - /* - * Philips FI1216MK2 remark from specification : - * for channel selection involving band switching, and to ensure - * smooth tuning to the desired channel without causing - * unnecessary charge pump action, it is recommended to consider - * the difference between wanted channel frequency and the - * current channel frequency. Unnecessary charge pump action - * will result in very low tuning voltage which may drive the - * oscillator to extreme conditions. - */ - /* - * Progfou: specification says to send config data before - * frequency in case (wanted frequency < current frequency). - */ - - if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { - buffer[0] = tun->config; - buffer[1] = config; - buffer[2] = (div>>8) & 0x7f; - buffer[3] = div & 0xff; - } else { - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; - buffer[2] = tun->config; - buffer[3] = config; - } - - if (4 != (rc = i2c_master_send(c,buffer,4))) - printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); - -} - -static void set_radio_freq(struct i2c_client *c, int freq) -{ - u8 config; - u16 div; - struct tunertype *tun; - struct tuner *t = (struct tuner*)c->data; - unsigned char buffer[4]; - int rc; - - if (t->type == -1) { - printk("tuner: tuner type not set\n"); - return; - } - - tun=&tuners[t->type]; - config = 0xa5; - div=freq + (int)(16*10.7); - div&=0x7fff; - - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; - buffer[2] = tun->config; - buffer[3] = config; - if (4 != (rc = i2c_master_send(c,buffer,4))) - printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); - - if (debug) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); - - if (tuner_islocked (c)) - printk ("tuner: PLL locked\n"); - else - printk ("tuner: PLL not locked\n"); - - printk ("tuner: AFC: %d\n", tuner_afcstatus (c)); - } -} -/* ---------------------------------------------------------------------- */ - - -static int tuner_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tuner *t; - struct i2c_client *client; - - if (this_adap > 0) - return -1; - this_adap++; - - client_template.adapter = adap; - client_template.addr = addr; - - printk("tuner: chip found @ 0x%x\n",addr); - - if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL); - if (NULL == t) { - kfree(client); - return -ENOMEM; - } - memset(t,0,sizeof(struct tuner)); - if (type >= 0 && type < TUNERS) { - t->type = type; - strncpy(client->name, tuners[t->type].name, sizeof(client->name)); - } else { - t->type = -1; - } - i2c_attach_client(client); - MOD_INC_USE_COUNT; - - return 0; -} - -static int tuner_probe(struct i2c_adapter *adap) -{ - if (0 != addr) { - normal_i2c_range[0] = addr; - normal_i2c_range[1] = addr; - } - this_adap = 0; - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tuner_attach); - return 0; -} - -static int tuner_detach(struct i2c_client *client) -{ - struct tuner *t = (struct tuner*)client->data; - - i2c_detach_client(client); - kfree(t); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int -tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct tuner *t = (struct tuner*)client->data; - int *iarg = (int*)arg; -#if 0 - __u16 *sarg = (__u16*)arg; -#endif - - switch (cmd) { - - /* --- configuration --- */ - case TUNER_SET_TYPE: - if (t->type != -1) - return 0; - if (*iarg < 0 || *iarg >= TUNERS) - return 0; - t->type = *iarg; - dprintk("tuner: type set to %d (%s)\n", - t->type,tuners[t->type].name); - strncpy(client->name, tuners[t->type].name, sizeof(client->name)); - break; - case AUDC_SET_RADIO: - t->radio = 1; - break; - - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCSCHAN: - { - struct video_channel *vc = arg; - - t->radio = 0; - if (t->type == TUNER_PHILIPS_SECAM) { - t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0; - set_tv_freq(client,t->freq); - } - return 0; - } - case VIDIOCSFREQ: - { - unsigned long *v = arg; - - t->freq = *v; - if (t->radio) { - dprintk("tuner: radio freq set to %d.%02d\n", - (*iarg)/16,(*iarg)%16*100/16); - set_radio_freq(client,t->freq); - } else { - dprintk("tuner: tv freq set to %d.%02d\n", - (*iarg)/16,(*iarg)%16*100/16); - set_tv_freq(client,t->freq); - } - return 0; - } -#if 0 - /* --- old, obsolete interface --- */ - case TUNER_SET_TVFREQ: - dprintk("tuner: tv freq set to %d.%02d\n", - (*iarg)/16,(*iarg)%16*100/16); - set_tv_freq(client,*iarg); - t->radio = 0; - t->freq = *iarg; - break; - - case TUNER_SET_RADIOFREQ: - dprintk("tuner: radio freq set to %d.%02d\n", - (*iarg)/16,(*iarg)%16*100/16); - set_radio_freq(client,*iarg); - t->radio = 1; - t->freq = *iarg; - break; - case TUNER_SET_MODE: - if (t->type != TUNER_PHILIPS_SECAM) { - dprintk("tuner: trying to change mode for other than TUNER_PHILIPS_SECAM\n"); - } else { - int mode=(*sarg==VIDEO_MODE_SECAM)?1:0; - dprintk("tuner: mode set to %d\n", *sarg); - t->mode = mode; - set_tv_freq(client,t->freq); - } - break; -#endif - default: - /* nothing */ - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver driver = { - "i2c TV tuner driver", - I2C_DRIVERID_TUNER, - I2C_DF_NOTIFY, - tuner_probe, - tuner_detach, - tuner_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -EXPORT_NO_SYMBOLS; - -int tuner_init_module(void) -{ - i2c_add_driver(&driver); - return 0; -} - -void tuner_cleanup_module(void) -{ - i2c_del_driver(&driver); -} - -module_init(tuner_init_module); -module_exit(tuner_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/tuner.h b/drivers/char/tuner.h deleted file mode 100644 index 96fcd3021..000000000 --- a/drivers/char/tuner.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - tuner.h - definition for different tuners - - Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de) - minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _TUNER_H -#define _TUNER_H - -#define TUNER_TEMIC_PAL 0 /* Miro Gpio Coding -1 */ -#define TUNER_PHILIPS_PAL_I 1 -#define TUNER_PHILIPS_NTSC 2 -#define TUNER_PHILIPS_SECAM 3 -#define TUNER_ABSENT 4 -#define TUNER_PHILIPS_PAL 5 -#define TUNER_TEMIC_NTSC 6 -#define TUNER_TEMIC_PAL_I 7 -#define TUNER_TEMIC_4036FY5_NTSC 8 -#define TUNER_ALPS_TSBH1_NTSC 9 -#define TUNER_ALPS_TSBE1_PAL 10 -#define TUNER_ALPS_TSBB5_PAL_I 11 -#define TUNER_ALPS_TSBE5_PAL 12 -#define TUNER_ALPS_TSBC5_PAL 13 - -#define NOTUNER 0 -#define PAL 1 -#define PAL_I 2 -#define NTSC 3 -#define SECAM 4 - -#define NoTuner 0 -#define Philips 1 -#define TEMIC 2 -#define Sony 3 -#define Alps 4 - -#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ -#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ -#define TUNER_SET_RADIOFREQ _IOW('t',3,int) /* set radio freq */ -#define TUNER_SET_MODE _IOW('t',4,int) /* set tuner mode */ - -#endif diff --git a/drivers/char/tvmixer.c b/drivers/char/tvmixer.c deleted file mode 100644 index e1034a152..000000000 --- a/drivers/char/tvmixer.c +++ /dev/null @@ -1,353 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "audiochip.h" - -#define DEV_MAX 4 - -static int debug = 0; -static int devnr = -1; - -MODULE_PARM(debug,"i"); -MODULE_PARM(devnr,"i"); - -/* ----------------------------------------------------------------------- */ - -struct TVMIXER { - struct i2c_client *dev; - int minor; - int count; -}; - -static struct TVMIXER devices[DEV_MAX]; - -static int tvmixer_adapters(struct i2c_adapter *adap); -static int tvmixer_clients(struct i2c_client *client); - -static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int tvmixer_open(struct inode *inode, struct file *file); -static int tvmixer_release(struct inode *inode, struct file *file); -static loff_t tvmixer_llseek(struct file *file, loff_t offset, int origin); - - -static struct i2c_driver driver = { - "tv card mixer driver", - 42 /* I2C_DRIVERID_FIXME */, - I2C_DF_DUMMY, - tvmixer_adapters, - tvmixer_clients, -}; - -static struct file_operations tvmixer_fops = { - owner: THIS_MODULE, - llseek: tvmixer_llseek, - ioctl: tvmixer_ioctl, - open: tvmixer_open, - release: tvmixer_release, -}; - -/* ----------------------------------------------------------------------- */ - -static int mix_to_v4l(int i) -{ - int r; - - r = ((i & 0xff) * 65536 + 50) / 100; - if (r > 65535) r = 65535; - if (r < 0) r = 0; - return r; -} - -static int v4l_to_mix(int i) -{ - int r; - - r = (i * 100 + 32768) / 65536; - if (r > 100) r = 100; - if (r < 0) r = 0; - return r | (r << 8); -} - -static int v4l_to_mix2(int l, int r) -{ - r = (r * 100 + 32768) / 65536; - if (r > 100) r = 100; - if (r < 0) r = 0; - l = (l * 100 + 32768) / 65536; - if (l > 100) l = 100; - if (l < 0) l = 0; - return (r << 8) | l; -} - -static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct video_audio va; - int left,right,ret,val = 0; - struct TVMIXER *mix = file->private_data; - struct i2c_client *client = mix->dev; - - if (NULL == client) - return -ENODEV; - - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - strncpy(info.id, "tv card", sizeof(info.id)); - strncpy(info.name, client->name, sizeof(info.name)); - info.modify_counter = 42 /* FIXME */; - if (copy_to_user((void *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - strncpy(info.id, "tv card", sizeof(info.id)); - strncpy(info.name, client->name, sizeof(info.name)); - if (copy_to_user((void *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int *)arg); - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - if (get_user(val, (int *)arg)) - return -EFAULT; - - /* read state */ - memset(&va,0,sizeof(va)); - client->driver->command(client,VIDIOCGAUDIO,&va); - - switch (cmd) { - case MIXER_READ(SOUND_MIXER_RECMASK): - case MIXER_READ(SOUND_MIXER_CAPS): - case MIXER_READ(SOUND_MIXER_RECSRC): - case MIXER_WRITE(SOUND_MIXER_RECSRC): - ret = 0; - break; - - case MIXER_READ(SOUND_MIXER_STEREODEVS): - ret = SOUND_MASK_VOLUME; - break; - case MIXER_READ(SOUND_MIXER_DEVMASK): - ret = SOUND_MASK_VOLUME; - if (va.flags & VIDEO_AUDIO_BASS) - ret |= SOUND_MASK_BASS; - if (va.flags & VIDEO_AUDIO_TREBLE) - ret |= SOUND_MASK_TREBLE; - break; - - case MIXER_WRITE(SOUND_MIXER_VOLUME): - left = mix_to_v4l(val); - right = mix_to_v4l(val >> 8); - va.volume = MAX(left,right); - va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1); - va.balance = (leftdriver->command(client,VIDIOCSAUDIO,&va); - client->driver->command(client,VIDIOCGAUDIO,&va); - /* fall throuth */ - case MIXER_READ(SOUND_MIXER_VOLUME): - left = (MIN(65536 - va.balance,32768) * - va.volume) / 32768; - right = (MIN(va.balance,32768) * - va.volume) / 32768; - ret = v4l_to_mix2(left,right); - break; - - case MIXER_WRITE(SOUND_MIXER_BASS): - va.bass = mix_to_v4l(val); - client->driver->command(client,VIDIOCSAUDIO,&va); - client->driver->command(client,VIDIOCGAUDIO,&va); - /* fall throuth */ - case MIXER_READ(SOUND_MIXER_BASS): - ret = v4l_to_mix(va.bass); - break; - - case MIXER_WRITE(SOUND_MIXER_TREBLE): - va.treble = mix_to_v4l(val); - client->driver->command(client,VIDIOCSAUDIO,&va); - client->driver->command(client,VIDIOCGAUDIO,&va); - /* fall throuth */ - case MIXER_READ(SOUND_MIXER_TREBLE): - ret = v4l_to_mix(va.treble); - break; - - default: - return -EINVAL; - } - if (put_user(ret, (int *)arg)) - return -EFAULT; - return 0; -} - -static int tvmixer_open(struct inode *inode, struct file *file) -{ - int i, minor = MINOR(inode->i_rdev); - struct TVMIXER *mix = NULL; - struct i2c_client *client = NULL; - - for (i = 0; i < DEV_MAX; i++) { - if (devices[i].minor == minor) { - mix = devices+i; - client = mix->dev; - break; - } - } - - if (NULL == client) - return -ENODEV; - - /* lock bttv in memory while the mixer is in use */ - file->private_data = mix; - if (client->adapter->inc_use) - client->adapter->inc_use(client->adapter); - return 0; -} - -static int tvmixer_release(struct inode *inode, struct file *file) -{ - struct TVMIXER *mix = file->private_data; - struct i2c_client *client; - - client = mix->dev; - if (NULL == client) { - return -ENODEV; - } - - if (client->adapter->dec_use) - client->adapter->dec_use(client->adapter); - return 0; -} - -static loff_t tvmixer_llseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -/* ----------------------------------------------------------------------- */ - -static int tvmixer_adapters(struct i2c_adapter *adap) -{ - return 0; -} - -static int tvmixer_clients(struct i2c_client *client) -{ - struct video_audio va; - int i,minor; - - /* TV card ??? */ - if (client->adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848)) { - if (debug) - printk("tvmixer: %s is not a tv card\n", - client->adapter->name); - return -1; - } - printk("tvmixer: debug: %s\n",client->name); - - /* unregister ?? */ - for (i = 0; i < DEV_MAX; i++) { - if (devices[i].dev == client) { - /* unregister */ - unregister_sound_mixer(devices[i].minor); - devices[i].dev = NULL; - devices[i].minor = -1; - printk("tvmixer: %s unregistered (#1)\n",client->name); - return 0; - } - } - - /* look for a free slot */ - for (i = 0; i < DEV_MAX; i++) - if (NULL == devices[i].dev) - break; - if (i == DEV_MAX) { - printk(KERN_WARNING "tvmixer: DEV_MAX too small\n"); - return -1; - } - - /* audio chip with mixer ??? */ - if (NULL == client->driver->command) { - if (debug) - printk("tvmixer: %s: driver->command is NULL\n", - client->driver->name); - return -1; - } - memset(&va,0,sizeof(va)); - if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) { - if (debug) - printk("tvmixer: %s: VIDIOCGAUDIO failed\n", - client->name); - return -1; - } - if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) { - if (debug) - printk("tvmixer: %s: has no volume control\n", - client->name); - return -1; - } - - /* everything is fine, register */ - if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) { - printk(KERN_ERR "tvmixer: cannot allocate mixer device\n"); - return -1; - } - - devices[i].minor = minor; - devices[i].count = 0; - devices[i].dev = client; - printk("tvmixer: %s (%s) registered with minor %d\n", - client->name,client->adapter->name,minor); - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -int tvmixer_init_module(void) -{ - int i; - - for (i = 0; i < DEV_MAX; i++) - devices[i].minor = -1; - i2c_add_driver(&driver); - return 0; -} - -void tvmixer_cleanup_module(void) -{ - int i; - - i2c_del_driver(&driver); - for (i = 0; i < DEV_MAX; i++) { - if (devices[i].minor != -1) { - unregister_sound_mixer(devices[i].minor); - printk("tvmixer: %s unregistered (#2)\n", - devices[i].dev->name); - } - } -} - -module_init(tvmixer_init_module); -module_exit(tvmixer_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c deleted file mode 100644 index c806ff264..000000000 --- a/drivers/char/videodev.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Video capture interface for Linux - * - * A generic video device interface for the LINUX operating system - * using a set of device structures/vectors for low level operations. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Author: Alan Cox, - * - * Fixes: 20000516 Claudio Matsuoka - * - Added procfs support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - -#define VIDEO_NUM_DEVICES 256 - -/* - * Active devices - */ - -static struct video_device *video_device[VIDEO_NUM_DEVICES]; - - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - -#include - -struct videodev_proc_data { - struct list_head proc_list; - char name[16]; - struct video_device *vdev; - struct proc_dir_entry *proc_entry; -}; - -static struct proc_dir_entry *video_dev_proc_entry = NULL; -struct proc_dir_entry *video_proc_entry = NULL; -EXPORT_SYMBOL(video_proc_entry); -LIST_HEAD(videodev_proc_list); - -#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ - - -#ifdef CONFIG_VIDEO_BWQCAM -extern int init_bw_qcams(struct video_init *); -#endif -#ifdef CONFIG_VIDEO_CPIA -extern int cpia_init(struct video_init *); -#endif -#ifdef CONFIG_VIDEO_PLANB -extern int init_planbs(struct video_init *); -#endif -#ifdef CONFIG_VIDEO_ZORAN -extern int init_zoran_cards(struct video_init *); -#endif - -static struct video_init video_init_list[]={ -#ifdef CONFIG_VIDEO_BWQCAM - {"bw-qcam", init_bw_qcams}, -#endif -#ifdef CONFIG_VIDEO_CPIA - {"cpia", cpia_init}, -#endif -#ifdef CONFIG_VIDEO_PLANB - {"planb", init_planbs}, -#endif -#ifdef CONFIG_VIDEO_ZORAN - {"zoran", init_zoran_cards}, -#endif - {"end", NULL} -}; - -/* - * Read will do some smarts later on. Buffer pin etc. - */ - -static ssize_t video_read(struct file *file, - char *buf, size_t count, loff_t *ppos) -{ - struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)]; - if(vfl->read) - return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK); - else - return -EINVAL; -} - - -/* - * Write for now does nothing. No reason it shouldnt do overlay setting - * for some boards I guess.. - */ - -static ssize_t video_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)]; - if(vfl->write) - return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK); - else - return 0; -} - -/* - * Poll to see if we're readable, can probably be used for timing on incoming - * frames, etc.. - */ - -static unsigned int video_poll(struct file *file, poll_table * wait) -{ - struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)]; - if(vfl->poll) - return vfl->poll(vfl, file, wait); - else - return 0; -} - - -/* - * Open a video device. - */ - -static int video_open(struct inode *inode, struct file *file) -{ - unsigned int minor = MINOR(inode->i_rdev); - int err; - struct video_device *vfl; - - if(minor>=VIDEO_NUM_DEVICES) - return -ENODEV; - - vfl=video_device[minor]; - if(vfl==NULL) { - char modname[20]; - - sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor); - request_module(modname); - vfl=video_device[minor]; - if (vfl==NULL) - return -ENODEV; - } - if(vfl->busy) - return -EBUSY; - vfl->busy=1; /* In case vfl->open sleeps */ - - if(vfl->open) - { - err=vfl->open(vfl,0); /* Tell the device it is open */ - if(err) - { - vfl->busy=0; - return err; - } - } - return 0; -} - -/* - * Last close of a video for Linux device - */ - -static int video_release(struct inode *inode, struct file *file) -{ - struct video_device *vfl; - lock_kernel(); - vfl=video_device[MINOR(inode->i_rdev)]; - if(vfl->close) - vfl->close(vfl); - vfl->busy=0; - unlock_kernel(); - return 0; -} - -/* - * Question: Should we be able to capture and then seek around the - * image ? - */ - -static long long video_lseek(struct file * file, - long long offset, int origin) -{ - return -ESPIPE; -} - -static int video_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct video_device *vfl=video_device[MINOR(inode->i_rdev)]; - int err=vfl->ioctl(vfl, cmd, (void *)arg); - - if(err!=-ENOIOCTLCMD) - return err; - - switch(cmd) - { - default: - return -EINVAL; - } -} - -/* - * We need to do MMAP support - */ - - -int video_mmap(struct file *file, struct vm_area_struct *vma) -{ - int ret = -EINVAL; - struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)]; - if(vfl->mmap) { - lock_kernel(); - ret = vfl->mmap(vfl, (char *)vma->vm_start, - (unsigned long)(vma->vm_end-vma->vm_start)); - unlock_kernel(); - } - return ret; -} - -/* - * /proc support - */ - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - -/* Hmm... i'd like to see video_capability information here, but - * how can I access it (without changing the other drivers? -claudio - */ -static int videodev_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *out = page; - struct video_device *vfd = data; - struct videodev_proc_data *d; - struct list_head *tmp; - int len; - char c = ' '; - - list_for_each (tmp, &videodev_proc_list) { - d = list_entry(tmp, struct videodev_proc_data, proc_list); - if (vfd == d->vdev) - break; - } - - /* Sanity check */ - if (tmp == &videodev_proc_list) - goto skip; - -#define PRINT_VID_TYPE(x) do { if (vfd->type & x) \ - out += sprintf (out, "%c%s", c, #x); c='|';} while (0) - - out += sprintf (out, "name : %s\n", vfd->name); - out += sprintf (out, "type :"); - PRINT_VID_TYPE(VID_TYPE_CAPTURE); - PRINT_VID_TYPE(VID_TYPE_TUNER); - PRINT_VID_TYPE(VID_TYPE_TELETEXT); - PRINT_VID_TYPE(VID_TYPE_OVERLAY); - PRINT_VID_TYPE(VID_TYPE_CHROMAKEY); - PRINT_VID_TYPE(VID_TYPE_CLIPPING); - PRINT_VID_TYPE(VID_TYPE_FRAMERAM); - PRINT_VID_TYPE(VID_TYPE_SCALES); - PRINT_VID_TYPE(VID_TYPE_MONOCHROME); - PRINT_VID_TYPE(VID_TYPE_SUBCAPTURE); - PRINT_VID_TYPE(VID_TYPE_MPEG_DECODER); - PRINT_VID_TYPE(VID_TYPE_MPEG_ENCODER); - PRINT_VID_TYPE(VID_TYPE_MJPEG_DECODER); - PRINT_VID_TYPE(VID_TYPE_MJPEG_ENCODER); - out += sprintf (out, "\n"); - out += sprintf (out, "hardware : 0x%x\n", vfd->hardware); -#if 0 - out += sprintf (out, "channels : %d\n", d->vcap.channels); - out += sprintf (out, "audios : %d\n", d->vcap.audios); - out += sprintf (out, "maxwidth : %d\n", d->vcap.maxwidth); - out += sprintf (out, "maxheight : %d\n", d->vcap.maxheight); - out += sprintf (out, "minwidth : %d\n", d->vcap.minwidth); - out += sprintf (out, "minheight : %d\n", d->vcap.minheight); -#endif - -skip: - len = out - page; - len -= off; - if (len < count) { - *eof = 1; - if (len <= 0) - return 0; - } else - len = count; - - *start = page + off; - - return len; -} - -static void videodev_proc_create(void) -{ - video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root); - - if (video_proc_entry == NULL) { - printk("video_dev: unable to initialise /proc/video\n"); - return; - } - - video_proc_entry->owner = THIS_MODULE; - video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry); - - if (video_dev_proc_entry == NULL) { - printk("video_dev: unable to initialise /proc/video/dev\n"); - return; - } - - video_dev_proc_entry->owner = THIS_MODULE; -} - -#ifdef MODULE -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) -static void videodev_proc_destroy(void) -{ - if (video_dev_proc_entry != NULL) - remove_proc_entry("dev", video_proc_entry); - - if (video_proc_entry != NULL) - remove_proc_entry("video", &proc_root); -} -#endif -#endif - -static void videodev_proc_create_dev (struct video_device *vfd, char *name) -{ - struct videodev_proc_data *d; - struct proc_dir_entry *p; - - if (video_dev_proc_entry == NULL) - return; - - d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL); - if (!d) - return; - - p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry); - p->data = vfd; - p->read_proc = videodev_proc_read; - - d->proc_entry = p; - d->vdev = vfd; - strcpy (d->name, name); - - /* How can I get capability information ? */ - - list_add (&d->proc_list, &videodev_proc_list); -} - -static void videodev_proc_destroy_dev (struct video_device *vfd) -{ - struct list_head *tmp; - struct videodev_proc_data *d; - - list_for_each (tmp, &videodev_proc_list) { - d = list_entry(tmp, struct videodev_proc_data, proc_list); - if (vfd == d->vdev) { - remove_proc_entry(d->name, video_dev_proc_entry); - list_del (&d->proc_list); - kfree (d); - break; - } - } -} - -#endif /* CONFIG_VIDEO_PROC_FS */ - -extern struct file_operations video_fops; - -/** - * video_register_device - register video4linux devices - * @vfd: video device structure we want to register - * @type: type of device to register - * FIXME: needs a semaphore on 2.3.x - * - * The registration code assigns minor numbers based on the type - * requested. -ENFILE is returned in all the device slots for this - * category are full. If not then the minor field is set and the - * driver initialize function is called (if non %NULL). - * - * Zero is returned on success. - * - * Valid types are - * - * %VFL_TYPE_GRABBER - A frame grabber - * - * %VFL_TYPE_VTX - A teletext device - * - * %VFL_TYPE_VBI - Vertical blank data (undecoded) - * - * %VFL_TYPE_RADIO - A radio card - */ - -int video_register_device(struct video_device *vfd, int type) -{ - int i=0; - int base; - int err; - int end; - char *name_base; - - switch(type) - { - case VFL_TYPE_GRABBER: - base=0; - end=64; - name_base = "video"; - break; - case VFL_TYPE_VTX: - base=192; - end=224; - name_base = "vtx"; - break; - case VFL_TYPE_VBI: - base=224; - end=240; - name_base = "vbi"; - break; - case VFL_TYPE_RADIO: - base=64; - end=128; - name_base = "radio"; - break; - default: - return -1; - } - - for(i=base;iminor=i; - /* The init call may sleep so we book the slot out - then call */ - MOD_INC_USE_COUNT; - if(vfd->initialize) - { - err=vfd->initialize(vfd); - if(err<0) - { - video_device[i]=NULL; - MOD_DEC_USE_COUNT; - return err; - } - } - sprintf (name, "v4l/%s%d", name_base, i - base); - /* - * Start the device root only. Anything else - * has serious privacy issues. - */ - vfd->devfs_handle = - devfs_register (NULL, name, DEVFS_FL_DEFAULT, - VIDEO_MAJOR, vfd->minor, - S_IFCHR | S_IRUSR | S_IWUSR, - &video_fops, NULL); - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - sprintf (name, "%s%d", name_base, i - base); - videodev_proc_create_dev (vfd, name); -#endif - - - return 0; - } - } - return -ENFILE; -} - -/** - * video_unregister_device - unregister a video4linux device - * @vfd: the device to unregister - * - * This unregisters the passed device and deassigns the minor - * number. Future open calls will be met with errors. - */ - -void video_unregister_device(struct video_device *vfd) -{ - if(video_device[vfd->minor]!=vfd) - panic("vfd: bad unregister"); - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - videodev_proc_destroy_dev (vfd); -#endif - - devfs_unregister (vfd->devfs_handle); - video_device[vfd->minor]=NULL; - MOD_DEC_USE_COUNT; -} - - -static struct file_operations video_fops= -{ - owner: THIS_MODULE, - llseek: video_lseek, - read: video_read, - write: video_write, - ioctl: video_ioctl, - mmap: video_mmap, - open: video_open, - release: video_release, - poll: video_poll, -}; - -/* - * Initialise video for linux - */ - -int __init videodev_init(void) -{ - struct video_init *vfli = video_init_list; - - printk(KERN_INFO "Linux video capture interface: v1.00\n"); - if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops)) - { - printk("video_dev: unable to get major %d\n", VIDEO_MAJOR); - return -EIO; - } - - /* - * Init kernel installed video drivers - */ - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - videodev_proc_create (); -#endif - - while(vfli->init!=NULL) - { - vfli->init(vfli); - vfli++; - } - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - return videodev_init(); -} - -void cleanup_module(void) -{ -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - videodev_proc_destroy (); -#endif - - devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture"); -} - -#endif - -EXPORT_SYMBOL(video_register_device); -EXPORT_SYMBOL(video_unregister_device); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("Device registrar for Video4Linux drivers"); diff --git a/drivers/char/vino.c b/drivers/char/vino.c deleted file mode 100644 index a9ac3086b..000000000 --- a/drivers/char/vino.c +++ /dev/null @@ -1,275 +0,0 @@ -/* $Id: vino.c,v 1.4 1999/02/09 23:59:36 ulfc Exp $ - * drivers/char/vino.c - * - * (incomplete) Driver for the Vino Video input system found in SGI Indys. - * - * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) - * - * This isn't complete yet, please don't expect any video until I've written - * some more code. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "vino.h" - -struct vino_device { - struct video_device vdev; - - unsigned long chan; -#define VINO_CHAN_A 0 -#define VINO_CHAN_B 1 - - unsigned long flags; -#define VINO_DMA_ACTIVE (1<<0) -}; - -/* We can actually receive TV and IndyCam input at the same time. Believe it or - * not.. - */ -static struct vino_device vino[2]; - -/* Those registers have to be accessed by either *one* 64 bit write or *one* 64 - * bit read. We need some asm to fix this. We can't use mips3 as standard - * because we just save 32 bits at context switch. - */ - -static __inline__ unsigned long long vino_reg_read(unsigned long addr) -{ - unsigned long long ret __attribute__ ((aligned (64))); - unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); - unsigned long flags; - - save_and_cli(flags); - __asm__ __volatile__( - ".set\tmips3\n\t" - ".set\tnoat\n\t" - "ld\t$1,(%0)\n\t" - "sd\t$1,(%1)\n\t" - ".set\tat\n\t" - ".set\tmips0" - : - :"r" (virt_addr), - "r" (&ret) - :"$1"); - restore_flags(flags); - - return ret; -} - -static __inline__ void vino_reg_write(unsigned long long value, - unsigned long addr) -{ - unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); - unsigned long flags; - - /* we might lose the upper parts of the registers which are not saved - * if there comes an interrupt in our way, play safe */ - - save_and_cli(flags); - __asm__ __volatile__( - ".set\tmips3\n\t" - ".set\tnoat\n\t" - "ld\t$1,(%0)\n\t" - "sd\t$1,(%1)\n\t" - ".set\tat\n\t" - ".set\tmips0" - : - :"r" (&value), - "r" (virt_addr) - :"$1"); - restore_flags(flags); -} - -static __inline__ void vino_reg_and(unsigned long long value, - unsigned long addr) -{ - unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); - unsigned long flags; - - save_and_cli(flags); - __asm__ __volatile__( - ".set\tmips3\n\t" - ".set\tnoat\n\t" - "ld\t$1,(%0)\n\t" - "ld\t$2,(%1)\n\t" - "and\t$1,$1,$2\n\t" - "sd\t$1,(%0)\n\t" - ".set\tat\n\t" - ".set\tmips0" - : - :"r" (virt_addr), - "r" (&value) - :"$1","$2"); - restore_flags(flags); -} - -static __inline__ void vino_reg_or(unsigned long long value, - unsigned long addr) -{ - unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); - unsigned long flags; - - save_and_cli(flags); - __asm__ __volatile__( - ".set\tmips3\n\t" - ".set\tnoat\n\t" - "ld\t$1,(%0)\n\t" - "ld\t$2,(%1)\n\t" - "or\t$1,$1,$2\n\t" - "sd\t$1,(%0)\n\t" - ".set\tat\n\t" - ".set\tmips0" - : - :"r" (virt_addr), - "r" (&value) - :"$1","$2"); - restore_flags(flags); -} - -static int vino_dma_setup(void) -{ - return 0; -} - -static void vino_dma_stop(void) -{ - -} - -static int vino_init(void) -{ - unsigned long ret; - unsigned short rev, id; - unsigned long long foo; - unsigned long *bar; - - bar = (unsigned long *) &foo; - - ret = vino_reg_read(VINO_REVID); - - rev = (ret & VINO_REVID_REV_MASK); - id = (ret & VINO_REVID_ID_MASK) >> 4; - - printk("Vino: ID:%02hx Rev:%02hx\n", id, rev); - - foo = vino_reg_read(VINO_A_DESC_DATA0); - printk("0x%lx", bar[0]); - printk("%lx ", bar[1]); - foo = vino_reg_read(VINO_A_DESC_DATA1); - printk("0x%lx", bar[0]); - printk("%lx ", bar[1]); - foo = vino_reg_read(VINO_A_DESC_DATA2); - printk("0x%lx", bar[0]); - printk("%lx ", bar[1]); - foo = vino_reg_read(VINO_A_DESC_DATA3); - printk("0x%lx", bar[0]); - printk("%lx\n", bar[1]); - foo = vino_reg_read(VINO_B_DESC_DATA0); - printk("0x%lx", bar[0]); - printk("%lx ", bar[1]); - foo = vino_reg_read(VINO_B_DESC_DATA1); - printk("0x%lx", bar[0]); - printk("%lx ", bar[1]); - foo = vino_reg_read(VINO_B_DESC_DATA2); - printk("0x%lx", bar[0]); - printk("%lx ", bar[1]); - foo = vino_reg_read(VINO_B_DESC_DATA3); - printk("0x%lx", bar[0]); - printk("%lx\n", bar[1]); - - return 0; -} - -static void vino_dma_go(struct vino_device *v) -{ - -} - -/* Reset the vino back to default state */ - -static void vino_setup(struct vino_device *v) -{ - -} - -static int vino_open(struct video_device *dev, int flags) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static void vino_close(struct video_device *dev) -{ - MOD_DEC_USE_COUNT; -} - -static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - return 0; -} - -static int vino_mmap(struct video_device *dev, const char *adr, - unsigned long size) -{ - return 0; -} - -static struct video_device vino_dev = { - "Vino IndyCam/TV", - VID_TYPE_CAPTURE, - VID_HARDWARE_VINO, - vino_open, - vino_close, - NULL, /* vino_read */ - NULL, /* vino_write */ - NULL, /* vino_poll */ - vino_ioctl, - vino_mmap, - NULL, /* vino_init */ - NULL, - 0, - 0 -}; - -int __init init_vino(struct video_device *dev) -{ - int err; - - err = vino_init(); - if (err) - return err; - -#if 0 - if (video_register_device(&vinodev, VFL_TYPE_GRABBER) == -1) { - return -ENODEV; - } -#endif - - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - int err; - - err = vino_init(); - if (err) - return err; - - return 0; -} - -void cleanup_module(void) -{ -} -#endif diff --git a/drivers/char/vino.h b/drivers/char/vino.h deleted file mode 100644 index 8caadc9aa..000000000 --- a/drivers/char/vino.h +++ /dev/null @@ -1,118 +0,0 @@ -/* $Id: vino.h,v 1.1 1999/02/08 18:29:32 ulfc Exp $ - * drivers/sgi/vino.h - * - * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) - */ - -#define VINO_BASE 0x0008000 - -#define VINO_REVID 0x0000 -#define VINO_CTRL 0x0008 -#define VINO_INTSTAT 0x0010 /* Interrupt status */ -#define VINO_I2C_CTRL 0x0018 -#define VINO_I2C_DATA 0x0020 -#define VINO_A_ALPHA 0x0028 /* Channel A ... */ -#define VINO_A_CLIPS 0x0030 /* Clipping start */ -#define VINO_A_CLIPE 0x0038 /* Clipping end */ -#define VINO_A_FRAMERT 0x0040 /* Framerate */ -#define VINO_A_FLDCNT 0x0048 /* Field counter */ -#define VINO_A_LNSZ 0x0050 -#define VINO_A_LNCNT 0x0058 -#define VINO_A_PGIX 0x0060 /* Page index */ -#define VINO_A_DESC_PTR 0x0068 /* Ptr to next four descriptors */ -#define VINO_A_DESC_TLB_PTR 0x0070 /* Ptr to start of descriptor table */ -#define VINO_A_DESC_DATA0 0x0078 /* Descriptor data 0 */ -#define VINO_A_DESC_DATA1 0x0080 /* ... */ -#define VINO_A_DESC_DATA2 0x0088 -#define VINO_A_DESC_DATA3 0x0090 -#define VINO_A_FIFO_THRESHOLD 0x0098 /* FIFO threshold */ -#define VINO_A_FIFO_RP 0x00a0 -#define VINO_A_FIFO_WP 0x00a8 -#define VINO_B_ALPHA 0x00b0 /* Channel B ... */ -#define VINO_B_CLIPS 0x00b8 -#define VINO_B_CLIPE 0x00c0 -#define VINO_B_FRAMERT 0x00c8 -#define VINO_B_FLDCNT 0x00d0 -#define VINO_B_LNSZ 0x00d8 -#define VINO_B_LNCNT 0x00e0 -#define VINO_B_PGIX 0x00e8 -#define VINO_B_DESC_PTR 0x00f0 -#define VINO_B_DESC_TLB_PTR 0x00f8 -#define VINO_B_DESC_DATA0 0x0100 -#define VINO_B_DESC_DATA1 0x0108 -#define VINO_B_DESC_DATA2 0x0110 -#define VINO_B_DESC_DATA3 0x0118 -#define VINO_B_FIFO_THRESHOLD 0x0120 -#define VINO_B_FIFO_RP 0x0128 -#define VINO_B_FIFO_WP 0x0130 - -/* Bits in the VINO_REVID register */ - -#define VINO_REVID_REV_MASK 0x000f /* bits 0:3 */ -#define VINO_REVID_ID_MASK 0x00f0 /* bits 4:7 */ - -/* Bits in the VINO_CTRL register */ - -#define VINO_CTRL_LITTLE_ENDIAN (1<<0) -#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */ -#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */ -#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */ -#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */ -#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */ -#define VINO_CTRL_B_END_DESC_TLB_INT (1<<6) /* End of desc table int */ -#define VINO_CTRL_A_DMA_ENBL (1<<7) -#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) -#define VINO_CTRL_A_SYNC_ENBL (1<<9) -#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */ -#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */ -#define VINO_CTRL_A_LUMA_ONLY (1<<12) -#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */ -#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */ -#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */ -#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */ -#define VINO_CTRL_B_DMA_ENBL (1<<19) -#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20) -#define VINO_CTRL_B_SYNC_ENBL (1<<21) -#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */ -#define VINO_CTRL_B_RGB (1<<22) /* 1=RGB 0=YUV */ -#define VINO_CTRL_B_LUMA_ONLY (1<<23) -#define VINO_CTRL_B_DEC_ENBL (1<<24) /* Decimation */ -#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 25:28 */ -#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */ -#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */ - -/* Bits in the Interrupt and Status register */ - -#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */ -#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */ -#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */ -#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */ -#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */ -#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */ - -/* Bits in the Clipping Start register */ - -#define VINO_CLIPS_START 0x3ff /* bits 0:9 */ -#define VINO_CLIPS_ODD_MASK 0x7fc00 /* bits 10:18 */ -#define VINO_CLIPS_EVEN_MASK 0xff80000 /* bits 19:27 */ - -/* Bits in the Clipping End register */ - -#define VINO_CLIPE_END 0x3ff /* bits 0:9 */ -#define VINO_CLIPE_ODD_MASK 0x7fc00 /* bits 10:18 */ -#define VINO_CLIPE_EVEN_MASK 0xff80000 /* bits 19:27 */ - -/* Bits in the Frame Rate register */ - -#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ -#define VINO_FRAMERT_RT_MASK 0x1ffe /* bits 1:12 */ - -/* Bits in the VINO_I2C_CTRL */ - -#define VINO_CTRL_I2C_IDLE (1<<0) /* write: 0=force idle - * read: 0=idle 1=not idle */ -#define VINO_CTRL_I2C_DIR (1<<1) /* 0=read 1=write */ -#define VINO_CTRL_I2C_MORE_BYTES (1<<2) /* 0=last byte 1=more bytes */ -#define VINO_CTRL_I2C_TRANS_BUSY (1<<4) /* 0=trans done 1=trans busy */ -#define VINO_CTRL_I2C_ACK (1<<5) /* 0=ack received 1=ack not */ -#define VINO_CTRL_I2C_BUS_ERROR (1<<7) /* 0=no bus err 1=bus err */ diff --git a/drivers/char/wdt285.c b/drivers/char/wdt285.c index 66633fd20..6745493de 100644 --- a/drivers/char/wdt285.c +++ b/drivers/char/wdt285.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include /* diff --git a/drivers/char/zr36057.h b/drivers/char/zr36057.h deleted file mode 100644 index b672357bc..000000000 --- a/drivers/char/zr36057.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - zr36057.h - zr36057 register offsets - - Copyright (C) 1998 Dave Perks - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 _ZR36057_H_ -#define _ZR36057_H_ - - -/* Zoran ZR36057 registers */ - -#define ZR36057_VFEHCR 0x000 /* Video Front End, Horizontal Configuration Register */ -#define ZR36057_VFEHCR_HSPol (1<<30) -#define ZR36057_VFEHCR_HStart 10 -#define ZR36057_VFEHCR_HEnd 0 -#define ZR36057_VFEHCR_Hmask 0x3ff - -#define ZR36057_VFEVCR 0x004 /* Video Front End, Vertical Configuration Register */ -#define ZR36057_VFEVCR_VSPol (1<<30) -#define ZR36057_VFEVCR_VStart 10 -#define ZR36057_VFEVCR_VEnd 0 -#define ZR36057_VFEVCR_Vmask 0x3ff - -#define ZR36057_VFESPFR 0x008 /* Video Front End, Scaler and Pixel Format Register */ -#define ZR36057_VFESPFR_ExtFl (1<<26) -#define ZR36057_VFESPFR_TopField (1<<25) -#define ZR36057_VFESPFR_VCLKPol (1<<24) -#define ZR36057_VFESPFR_HFilter 21 -#define ZR36057_VFESPFR_HorDcm 14 -#define ZR36057_VFESPFR_VerDcm 8 -#define ZR36057_VFESPFR_DispMode 6 -#define ZR36057_VFESPFR_YUV422 (0<<3) -#define ZR36057_VFESPFR_RGB888 (1<<3) -#define ZR36057_VFESPFR_RGB565 (2<<3) -#define ZR36057_VFESPFR_RGB555 (3<<3) -#define ZR36057_VFESPFR_ErrDif (1<<2) -#define ZR36057_VFESPFR_Pack24 (1<<1) -#define ZR36057_VFESPFR_LittleEndian (1<<0) - -#define ZR36057_VDTR 0x00c /* Video Display "Top" Register */ - -#define ZR36057_VDBR 0x010 /* Video Display "Bottom" Register */ - -#define ZR36057_VSSFGR 0x014 /* Video Stride, Status, and Frame Grab Register */ -#define ZR36057_VSSFGR_DispStride 16 -#define ZR36057_VSSFGR_VidOvf (1<<8) -#define ZR36057_VSSFGR_SnapShot (1<<1) -#define ZR36057_VSSFGR_FrameGrab (1<<0) - -#define ZR36057_VDCR 0x018 /* Video Display Configuration Register */ -#define ZR36057_VDCR_VidEn (1<<31) -#define ZR36057_VDCR_MinPix 24 -#define ZR36057_VDCR_Triton (1<<24) -#define ZR36057_VDCR_VidWinHt 12 -#define ZR36057_VDCR_VidWinWid 0 - -#define ZR36057_MMTR 0x01c /* Masking Map "Top" Register */ - -#define ZR36057_MMBR 0x020 /* Masking Map "Bottom" Register */ - -#define ZR36057_OCR 0x024 /* Overlay Control Register */ -#define ZR36057_OCR_OvlEnable (1 << 15) -#define ZR36057_OCR_MaskStride 0 - -#define ZR36057_SPGPPCR 0x028 /* System, PCI, and General Purpose Pins Control Register */ -#define ZR36057_SPGPPCR_SoftReset (1<<24) - -#define ZR36057_GPPGCR1 0x02c /* General Purpose Pins and GuestBus Control Register (1) */ - -#define ZR36057_MCSAR 0x030 /* MPEG Code Source Address Register */ - -#define ZR36057_MCTCR 0x034 /* MPEG Code Transfer Control Register */ -#define ZR36057_MCTCR_CodTime (1 << 30) -#define ZR36057_MCTCR_CEmpty (1 << 29) -#define ZR36057_MCTCR_CFlush (1 << 28) -#define ZR36057_MCTCR_CodGuestID 20 -#define ZR36057_MCTCR_CodGuestReg 16 - -#define ZR36057_MCMPR 0x038 /* MPEG Code Memory Pointer Register */ - -#define ZR36057_ISR 0x03c /* Interrupt Status Register */ -#define ZR36057_ISR_GIRQ1 (1<<30) -#define ZR36057_ISR_GIRQ0 (1<<29) -#define ZR36057_ISR_CodRepIRQ (1<<28) -#define ZR36057_ISR_JPEGRepIRQ (1<<27) - -#define ZR36057_ICR 0x040 /* Interrupt Control Register */ -#define ZR36057_ICR_GIRQ1 (1<<30) -#define ZR36057_ICR_GIRQ0 (1<<29) -#define ZR36057_ICR_CodRepIRQ (1<<28) -#define ZR36057_ICR_JPEGRepIRQ (1<<27) -#define ZR36057_ICR_IntPinEn (1<<24) - -#define ZR36057_I2CBR 0x044 /* I2C Bus Register */ -#define ZR36057_I2CBR_SDA (1<<1) -#define ZR36057_I2CBR_SCL (1<<0) - -#define ZR36057_JMC 0x100 /* JPEG Mode and Control */ -#define ZR36057_JMC_JPG (1 << 31) -#define ZR36057_JMC_JPGExpMode (0 << 29) -#define ZR36057_JMC_JPGCmpMode (1 << 29) -#define ZR36057_JMC_MJPGExpMode (2 << 29) -#define ZR36057_JMC_MJPGCmpMode (3 << 29) -#define ZR36057_JMC_RTBUSY_FB (1 << 6) -#define ZR36057_JMC_Go_en (1 << 5) -#define ZR36057_JMC_SyncMstr (1 << 4) -#define ZR36057_JMC_Fld_per_buff (1 << 3) -#define ZR36057_JMC_VFIFO_FB (1 << 2) -#define ZR36057_JMC_CFIFO_FB (1 << 1) -#define ZR36057_JMC_Stll_LitEndian (1 << 0) - -#define ZR36057_JPC 0x104 /* JPEG Process Control */ -#define ZR36057_JPC_P_Reset (1 << 7) -#define ZR36057_JPC_CodTrnsEn (1 << 5) -#define ZR36057_JPC_Active (1 << 0) - -#define ZR36057_VSP 0x108 /* Vertical Sync Parameters */ -#define ZR36057_VSP_VsyncSize 16 -#define ZR36057_VSP_FrmTot 0 - -#define ZR36057_HSP 0x10c /* Horizontal Sync Parameters */ -#define ZR36057_HSP_HsyncStart 16 -#define ZR36057_HSP_LineTot 0 - -#define ZR36057_FHAP 0x110 /* Field Horizontal Active Portion */ -#define ZR36057_FHAP_NAX 16 -#define ZR36057_FHAP_PAX 0 - -#define ZR36057_FVAP 0x114 /* Field Vertical Active Portion */ -#define ZR36057_FVAP_NAY 16 -#define ZR36057_FVAP_PAY 0 - -#define ZR36057_FPP 0x118 /* Field Process Parameters */ -#define ZR36057_FPP_Odd_Even (1 << 0) - -#define ZR36057_JCBA 0x11c /* JPEG Code Base Address */ - -#define ZR36057_JCFT 0x120 /* JPEG Code FIFO Threshold */ - -#define ZR36057_JCGI 0x124 /* JPEG Codec Guest ID */ -#define ZR36057_JCGI_JPEGuestID 4 -#define ZR36057_JCGI_JPEGuestReg 0 - -#define ZR36057_GCR2 0x12c /* GuestBus Control Register (2) */ - -#define ZR36057_POR 0x200 /* Post Office Register */ -#define ZR36057_POR_POPen (1<<25) -#define ZR36057_POR_POTime (1<<24) -#define ZR36057_POR_PODir (1<<23) - -#define ZR36057_STR 0x300 /* "Still" Transfer Register */ - -#endif diff --git a/drivers/char/zr36060.h b/drivers/char/zr36060.h deleted file mode 100644 index d94f56b0b..000000000 --- a/drivers/char/zr36060.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - zr36060.h - zr36060 register offsets - - Copyright (C) 1998 Dave Perks - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 _ZR36060_H_ -#define _ZR36060_H_ - - -/* Zoran ZR36060 registers */ - -#define ZR36060_LoadParameters 0x000 -#define ZR36060_Load (1<<7) -#define ZR36060_SyncRst (1<<0) - -#define ZR36060_CodeFifoStatus 0x001 -#define ZR36060_Load (1<<7) -#define ZR36060_SyncRst (1<<0) - -#endif diff --git a/drivers/char/zr36120.c b/drivers/char/zr36120.c deleted file mode 100644 index 6e860021e..000000000 --- a/drivers/char/zr36120.c +++ /dev/null @@ -1,2086 +0,0 @@ -/* - zr36120.c - Zoran 36120/36125 based framegrabbers - - Copyright (C) 1998-1999 Pauline Middelink - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "tuner.h" -#include "zr36120.h" -#include "zr36120_mem.h" - -/* mark an required function argument unused - lintism */ -#define UNUSED(x) (void)(x) - -/* sensible default */ -#ifndef CARDTYPE -#define CARDTYPE 0 -#endif - -/* Anybody who uses more than four? */ -#define ZORAN_MAX 4 - -static unsigned int triton1=0; /* triton1 chipset? */ -static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE }; - -MODULE_AUTHOR("Pauline Middelink "); -MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber"); -MODULE_PARM(triton1,"i"); -MODULE_PARM(cardtype,"1-" __MODULE_STRING(ZORAN_MAX) "i"); - -static int zoran_cards; -static struct zoran zorans[ZORAN_MAX]; - -/* - * the meaning of each element can be found in zr36120.h - * Determining the value of gpdir/gpval can be tricky. The - * best way is to run the card under the original software - * and read the values from the general purpose registers - * 0x28 and 0x2C. How you do that is left as an exercise - * to the impatient reader :) - */ -#define T 1 /* to seperate the bools from the ints */ -#define F 0 -static struct tvcard tvcards[] = { - /* reported working by */ -/*0*/ { "Trust Victor II", - 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, - /* reported working by */ -/*1*/ { "Aitech WaveWatcher TV-PCI", - 3, 0, T, F, T, T, 0x7F, 0x80, { 1, TUNER(3), SVHS(6) }, { 0 } }, - /* reported working by ? */ -/*2*/ { "Genius Video Wonder PCI Video Capture Card", - 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, - /* reported working by */ -/*3*/ { "Guillemot Maxi-TV PCI", - 2, 0, T, T, T, T, 0x7F, 0x80, { 1, SVHS(6) }, { 0 } }, - /* reported working by "Craig Whitmore */ -/*4*/ { "Quadrant Buster", - 3, 3, T, F, T, T, 0x7F, 0x80, { SVHS(1), TUNER(2), 3 }, { 1, 2, 3 } }, - /* a debug entry which has all inputs mapped */ -/*5*/ { "ZR36120 based framegrabber (all inputs enabled)", - 6, 0, T, T, T, T, 0x7F, 0x80, { 1, 2, 3, 4, 5, 6 }, { 0 } } -}; -#undef T -#undef F -#define NRTVCARDS (sizeof(tvcards)/sizeof(tvcards[0])) - -#ifdef __sparc__ -#define ENDIANESS 0 -#else -#define ENDIANESS ZORAN_VFEC_LE -#endif - -static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { -/* n/a */ { "n/a", 0, 0 }, -/* GREY */ { "GRAY", 0, 0 }, -/* HI240 */ { "HI240", 0, 0 }, -/* RGB565 */ { "RGB565", ZORAN_VFEC_RGB_RGB565|ENDIANESS, 2 }, -/* RGB24 */ { "RGB24", ZORAN_VFEC_RGB_RGB888|ENDIANESS|ZORAN_VFEC_PACK24, 3 }, -/* RGB32 */ { "RGB32", ZORAN_VFEC_RGB_RGB888|ENDIANESS, 4 }, -/* RGB555 */ { "RGB555", ZORAN_VFEC_RGB_RGB555|ENDIANESS, 2 }, -/* YUV422 */ { "YUV422", ZORAN_VFEC_RGB_YUV422|ENDIANESS, 2 }, -/* YUYV */ { "YUYV", 0, 0 }, -/* UYVY */ { "UYVY", 0, 0 }, -/* YUV420 */ { "YUV420", 0, 0 }, -/* YUV411 */ { "YUV411", 0, 0 }, -/* RAW */ { "RAW", 0, 0 }, -/* YUV422P */ { "YUV422P", 0, 0 }, -/* YUV411P */ { "YUV411P", 0, 0 }}; -#define NRPALETTES (sizeof(palette2fmt)/sizeof(palette2fmt[0])) -#undef ENDIANESS - -/* ----------------------------------------------------------------------- */ -/* ZORAN chipset detector */ -/* shamelessly stolen from bttv.c */ -/* Reason for beeing here: we need to detect if we are running on a */ -/* Triton based chipset, and if so, enable a certain bit */ -/* ----------------------------------------------------------------------- */ -static -void __init handle_chipset(void) -{ - struct pci_dev *dev = NULL; - - /* Just in case some nut set this to something dangerous */ - if (triton1) - triton1 = ZORAN_VDC_TRICOM; - - while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, dev))) - { - printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); - triton1 = ZORAN_VDC_TRICOM; - } -} - -/* ----------------------------------------------------------------------- */ -/* ZORAN functions */ -/* ----------------------------------------------------------------------- */ - -static void zoran_set_geo(struct zoran* ztv, struct vidinfo* i); - -#if 0 /* unused */ -static -void zoran_dump(struct zoran *ztv) -{ - char str[256]; - char *p=str; /* shut up, gcc! */ - int i; - - for (i=0; i<0x60; i+=4) { - if ((i % 16) == 0) { - if (i) printk("%s\n",str); - p = str; - p+= sprintf(str, KERN_DEBUG " %04x: ",i); - } - p += sprintf(p, "%08x ",zrread(i)); - } -} -#endif /* unused */ - -static -void reap_states(struct zoran* ztv) -{ - /* count frames */ - ztv->fieldnr++; - - /* - * Are we busy at all? - * This depends on if there is a workqueue AND the - * videotransfer is enabled on the chip... - */ - if (ztv->workqueue && (zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) - { - struct vidinfo* newitem; - - /* did we get a complete frame? */ - if (zrread(ZORAN_VSTR) & ZORAN_VSTR_GRAB) - return; - -DEBUG(printk(CARD_DEBUG "completed %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); - - /* we are done with this buffer, tell everyone */ - ztv->workqueue->status = FBUFFER_DONE; - ztv->workqueue->fieldnr = ztv->fieldnr; - /* not good, here for BTTV_FIELDNR reasons */ - ztv->lastfieldnr = ztv->fieldnr; - - switch (ztv->workqueue->kindof) { - case FBUFFER_GRAB: - wake_up_interruptible(&ztv->grabq); - break; - case FBUFFER_VBI: - wake_up_interruptible(&ztv->vbiq); - break; - default: - printk(CARD_INFO "somebody killed the workqueue (kindof=%d)!\n",CARD,ztv->workqueue->kindof); - } - - /* item completed, skip to next item in queue */ - write_lock(&ztv->lock); - newitem = ztv->workqueue->next; - ztv->workqueue->next = 0; /* mark completed */ - ztv->workqueue = newitem; - write_unlock(&ztv->lock); - } - - /* - * ok, so it seems we have nothing in progress right now. - * Lets see if we can find some work. - */ - if (ztv->workqueue) - { - struct vidinfo* newitem; -again: - -DEBUG(printk(CARD_DEBUG "starting %s at %p\n",CARD,ztv->workqueue->kindof==FBUFFER_GRAB?"grab":"read",ztv->workqueue)); - - /* loadup the frame settings */ - read_lock(&ztv->lock); - zoran_set_geo(ztv,ztv->workqueue); - read_unlock(&ztv->lock); - - switch (ztv->workqueue->kindof) { - case FBUFFER_GRAB: - case FBUFFER_VBI: - zrand(~ZORAN_OCR_OVLEN, ZORAN_OCR); - zror(ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); - zror(ZORAN_VDC_VIDEN,ZORAN_VDC); - - /* start single-shot grab */ - zror(ZORAN_VSTR_GRAB, ZORAN_VSTR); - break; - default: - printk(CARD_INFO "what is this doing on the queue? (kindof=%d)\n",CARD,ztv->workqueue->kindof); - write_lock(&ztv->lock); - newitem = ztv->workqueue->next; - ztv->workqueue->next = 0; - ztv->workqueue = newitem; - write_unlock(&ztv->lock); - if (newitem) - goto again; /* yeah, sure.. */ - } - /* bye for now */ - return; - } -DEBUG(printk(CARD_DEBUG "nothing in queue\n",CARD)); - - /* - * What? Even the workqueue is empty? Am i really here - * for nothing? Did i come all that way to... do nothing? - */ - - /* do we need to overlay? */ - if (test_bit(STATE_OVERLAY, &ztv->state)) - { - /* are we already overlaying? */ - if (!(zrread(ZORAN_OCR) & ZORAN_OCR_OVLEN) || - !(zrread(ZORAN_VDC) & ZORAN_VDC_VIDEN)) - { -DEBUG(printk(CARD_DEBUG "starting overlay\n",CARD)); - - read_lock(&ztv->lock); - zoran_set_geo(ztv,&ztv->overinfo); - read_unlock(&ztv->lock); - - zror(ZORAN_OCR_OVLEN, ZORAN_OCR); - zrand(~ZORAN_VSTR_SNAPSHOT,ZORAN_VSTR); - zror(ZORAN_VDC_VIDEN,ZORAN_VDC); - } - - /* - * leave overlaying on, but turn interrupts off. - */ - zrand(~ZORAN_ICR_EN,ZORAN_ICR); - return; - } - - /* do we have any VBI idle time processing? */ - if (test_bit(STATE_VBI, &ztv->state)) - { - struct vidinfo* item; - struct vidinfo* lastitem; - - /* protect the workqueue */ - write_lock(&ztv->lock); - lastitem = ztv->workqueue; - if (lastitem) - while (lastitem->next) lastitem = lastitem->next; - for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) - if (item->next == 0 && item->status == FBUFFER_FREE) - { -DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item)); - item->status = FBUFFER_BUSY; - if (!lastitem) - ztv->workqueue = item; - else - lastitem->next = item; - lastitem = item; - } - write_unlock(&ztv->lock); - if (ztv->workqueue) - goto again; /* hey, _i_ graduated :) */ - } - - /* - * Then we must be realy IDLE - */ -DEBUG(printk(CARD_DEBUG "turning off\n",CARD)); - /* nothing further to do, disable DMA and further IRQs */ - zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); - zrand(~ZORAN_ICR_EN,ZORAN_ICR); -} - -static -void zoran_irq(int irq, void *dev_id, struct pt_regs * regs) -{ - u32 stat,estat; - int count = 0; - struct zoran *ztv = (struct zoran *)dev_id; - - UNUSED(irq); UNUSED(regs); - for (;;) { - /* get/clear interrupt status bits */ - stat=zrread(ZORAN_ISR); - estat=stat & zrread(ZORAN_ICR); - if (!estat) - return; - zrwrite(estat,ZORAN_ISR); - IDEBUG(printk(CARD_DEBUG "estat %08x\n",CARD,estat)); - IDEBUG(printk(CARD_DEBUG " stat %08x\n",CARD,stat)); - - if (estat & ZORAN_ISR_CODE) - { - IDEBUG(printk(CARD_DEBUG "CodReplIRQ\n",CARD)); - } - if (estat & ZORAN_ISR_GIRQ0) - { - IDEBUG(printk(CARD_DEBUG "GIRQ0\n",CARD)); - if (!ztv->card->usegirq1) - reap_states(ztv); - } - if (estat & ZORAN_ISR_GIRQ1) - { - IDEBUG(printk(CARD_DEBUG "GIRQ1\n",CARD)); - if (ztv->card->usegirq1) - reap_states(ztv); - } - - count++; - if (count > 10) - printk(CARD_ERR "irq loop %d (%x)\n",CARD,count,estat); - if (count > 20) - { - zrwrite(0, ZORAN_ICR); - printk(CARD_ERR "IRQ lockup, cleared int mask\n",CARD); - } - } -} - -static -int zoran_muxsel(struct zoran* ztv, int channel, int norm) -{ - int rv; - - /* set the new video norm */ - rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); - if (rv) - return rv; - ztv->norm = norm; - - /* map the given channel to the cards decoder's channel */ - channel = ztv->card->video_mux[channel] & CHANNEL_MASK; - - /* set the new channel */ - rv = i2c_control_device(&(ztv->i2c), I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &channel); - return rv; -} - -/* Tell the interrupt handler what to to. */ -static -void zoran_cap(struct zoran* ztv, int on) -{ -DEBUG(printk(CARD_DEBUG "zoran_cap(%d) state=%x\n",CARD,on,ztv->state)); - - if (on) { - ztv->running = 1; - - /* - * turn interrupts (back) on. The DMA will be enabled - * inside the irq handler when it detects a restart. - */ - zror(ZORAN_ICR_EN,ZORAN_ICR); - } - else { - /* - * turn both interrupts and DMA off - */ - zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); - zrand(~ZORAN_ICR_EN,ZORAN_ICR); - - ztv->running = 0; - } -} - -static ulong dmask[] = { - 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, - 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, - 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, - 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, - 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, - 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000, - 0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000, - 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000 -}; - -static -void zoran_built_overlay(struct zoran* ztv, int count, struct video_clip *vcp) -{ - ulong* mtop; - int ystep = (ztv->vidXshift + ztv->vidWidth+31)/32; /* next DWORD */ - int i; - -DEBUG(printk(KERN_DEBUG " overlay at %p, ystep=%d, clips=%d\n",ztv->overinfo.overlay,ystep,count)); - - for (i=0; ix,vp->y,vp->width,vp->height)); - } - - /* - * activate the visible portion of the screen - * Note we take some shortcuts here, because we - * know the width can never be < 32. (I.e. a DWORD) - * We also assume the overlay starts somewhere in - * the FIRST dword. - */ - { - int start = ztv->vidXshift; - ulong firstd = dmask[start]; - ulong lastd = ~dmask[(start + ztv->overinfo.w) & 31]; - mtop = ztv->overinfo.overlay; - for (i=0; ioverinfo.h; i++) { - int w = ztv->vidWidth; - ulong* line = mtop; - if (start & 31) { - *line++ = firstd; - w -= 32-(start&31); - } - memset(line, ~0, w/8); - if (w & 31) - line[w/32] = lastd; - mtop += ystep; - } - } - - /* process clipping regions */ - for (i=0; ix < 0 || (uint)vcp->x > ztv->overinfo.w || - vcp->y < 0 || vcp->y > ztv->overinfo.h || - vcp->width < 0 || (uint)(vcp->x+vcp->width) > ztv->overinfo.w || - vcp->height < 0 || (vcp->y+vcp->height) > ztv->overinfo.h) - { - DEBUG(printk(CARD_DEBUG "illegal clipzone (%d,%d,%d,%d) not in (0,0,%d,%d), adapting\n",CARD,vcp->x,vcp->y,vcp->width,vcp->height,ztv->overinfo.w,ztv->overinfo.h)); - if (vcp->x < 0) vcp->x = 0; - if ((uint)vcp->x > ztv->overinfo.w) vcp->x = ztv->overinfo.w; - if (vcp->y < 0) vcp->y = 0; - if (vcp->y > ztv->overinfo.h) vcp->y = ztv->overinfo.h; - if (vcp->width < 0) vcp->width = 0; - if ((uint)(vcp->x+vcp->width) > ztv->overinfo.w) vcp->width = ztv->overinfo.w - vcp->x; - if (vcp->height < 0) vcp->height = 0; - if (vcp->y+vcp->height > ztv->overinfo.h) vcp->height = ztv->overinfo.h - vcp->y; -// continue; - } - - mtop = &ztv->overinfo.overlay[vcp->y*ystep]; - for (h=0; h<=vcp->height; h++) { - int w; - int x = ztv->vidXshift + vcp->x; - for (w=0; w<=vcp->width; w++) { - clear_bit(x&31, &mtop[x/32]); - x++; - } - mtop += ystep; - } - ++vcp; - } - - mtop = ztv->overinfo.overlay; - zrwrite(virt_to_bus(mtop), ZORAN_MTOP); - zrwrite(virt_to_bus(mtop+ystep), ZORAN_MBOT); - zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR); -} - -struct tvnorm -{ - u16 Wt, Wa, Ht, Ha, HStart, VStart; -}; - -static struct tvnorm tvnorms[] = { - /* PAL-BDGHI */ -/* { 864, 720, 625, 576, 131, 21 },*/ -/*00*/ { 864, 768, 625, 576, 81, 17 }, - /* NTSC */ -/*01*/ { 858, 720, 525, 480, 121, 10 }, - /* SECAM */ -/*02*/ { 864, 720, 625, 576, 131, 21 }, - /* BW50 */ -/*03*/ { 864, 720, 625, 576, 131, 21 }, - /* BW60 */ -/*04*/ { 858, 720, 525, 480, 121, 10 } -}; -#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) - -/* - * Program the chip for a setup as described in the vidinfo struct. - * - * Side-effects: calculates vidXshift, vidInterlace, - * vidHeight, vidWidth which are used in a later stage - * to calculate the overlay mask - * - * This is an internal function, as such it does not check the - * validity of the struct members... Spectaculair crashes will - * follow /very/ quick when you're wrong and the chip right :) - */ -static -void zoran_set_geo(struct zoran* ztv, struct vidinfo* i) -{ - ulong top, bot; - int stride; - int winWidth, winHeight; - int maxWidth, maxHeight, maxXOffset, maxYOffset; - long vfec; - -DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay)); - - /* - * make sure the DMA transfers are inhibited during our - * reprogramming of the chip - */ - zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC); - - maxWidth = tvnorms[ztv->norm].Wa; - maxHeight = tvnorms[ztv->norm].Ha/2; - maxXOffset = tvnorms[ztv->norm].HStart; - maxYOffset = tvnorms[ztv->norm].VStart; - - /* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */ - vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) | - (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24)); - - /* - * Set top, bottom ptrs. Since these must be DWORD aligned, - * possible adjust the x and the width of the window. - * so the endposition stay the same. The vidXshift will make - * sure we are not writing pixels before the requested x. - */ - ztv->vidXshift = 0; - winWidth = i->w; - if (winWidth < 0) - winWidth = -winWidth; - top = i->busadr + i->x*i->bpp + i->y*i->bpl; - if (top & 3) { - ztv->vidXshift = (top & 3) / i->bpp; - winWidth += ztv->vidXshift; - DEBUG(printk(KERN_DEBUG " window-x shifted %d pixels left\n",ztv->vidXshift)); - top &= ~3; - } - - /* - * bottom points to next frame but in interleaved mode we want - * to 'mix' the 2 frames to one capture, so 'bot' points to one - * (physical) line below the top line. - */ - bot = top + i->bpl; - zrwrite(top,ZORAN_VTOP); - zrwrite(bot,ZORAN_VBOT); - - /* - * Make sure the winWidth is DWORD aligned too, - * thereby automaticly making sure the stride to the - * next line is DWORD aligned too (as required by spec). - */ - if ((winWidth*i->bpp) & 3) { -DEBUG(printk(KERN_DEBUG " window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3)); - winWidth += (winWidth*i->bpp) & 3; - } - - /* determine the DispMode and stride */ - if (i->h >= 0 && i->h <= maxHeight) { - /* single frame grab suffices for this height. */ - vfec |= ZORAN_VFEC_DISPMOD; - ztv->vidInterlace = 0; - stride = i->bpl - (winWidth*i->bpp); - winHeight = i->h; - } - else { - /* interleaving needed for this height */ - ztv->vidInterlace = 1; - stride = i->bpl*2 - (winWidth*i->bpp); - winHeight = i->h/2; - } - if (winHeight < 0) /* can happen for VBI! */ - winHeight = -winHeight; - - /* safety net, sometimes bpl is too short??? */ - if (stride<0) { -DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride)); - stride = 0; - } - - zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC); - zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR); - - /* remember vidWidth, vidHeight for overlay calculations */ - ztv->vidWidth = winWidth; - ztv->vidHeight = winHeight; -DEBUG(printk(KERN_DEBUG " top=%08lx, bottom=%08lx\n",top,bot)); -DEBUG(printk(KERN_DEBUG " winWidth=%d, winHeight=%d\n",winWidth,winHeight)); -DEBUG(printk(KERN_DEBUG " maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight)); -DEBUG(printk(KERN_DEBUG " stride=%d\n",stride)); - - /* - * determine horizontal scales and crops - */ - if (i->w < 0) { - int Hstart = 1; - int Hend = Hstart + winWidth; -DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend)); - zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); - } - else { - int Wa = maxWidth; - int X = (winWidth*64+Wa-1)/Wa; - int We = winWidth*64/X; - int HorDcm = 64-X; - int hcrop1 = 2*(Wa-We)/4; - /* - * BUGFIX: Juha Nurmela - * found the solution to the color phase shift. - * See ChangeLog for the full explanation) - */ - int Hstart = (maxXOffset + hcrop1) | 1; - int Hend = Hstart + We - 1; - -DEBUG(printk(KERN_DEBUG " X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend)); - - zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH); - vfec |= HorDcm<<14; - - if (HorDcm<16) - vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */ - else if (HorDcm<32) - vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */ - else if (HorDcm<48) - vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */ - else vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */ - } - - /* - * Determine vertical scales and crops - * - * when height is negative, we want to read starting at line 0 - * One day someone might need access to these lines... - */ - if (i->h < 0) { - int Vstart = 0; - int Vend = Vstart + winHeight; -DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Vstart, Vend)); - zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); - } - else { - int Ha = maxHeight; - int Y = (winHeight*64+Ha-1)/Ha; - int He = winHeight*64/Y; - int VerDcm = 64-Y; - int vcrop1 = 2*(Ha-He)/4; - int Vstart = maxYOffset + vcrop1; - int Vend = Vstart + He - 1; - -DEBUG(printk(KERN_DEBUG " Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend)); - zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV); - vfec |= VerDcm<<8; - } - -DEBUG(printk(KERN_DEBUG " F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name)); - - /* setup the requested format */ - zrwrite(vfec, ZORAN_VFEC); -} - -static -void zoran_common_open(struct zoran* ztv, int flags) -{ - UNUSED(flags); - - /* already opened? */ - if (ztv->users++ != 0) - return; - - /* unmute audio */ - /* /what/ audio? */ - - ztv->state = 0; - - /* setup the encoder to the initial values */ - ztv->picture.colour=254<<7; - ztv->picture.brightness=128<<8; - ztv->picture.hue=128<<8; - ztv->picture.contrast=216<<7; - i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture); - - /* default to the composite input since my camera is there */ - zoran_muxsel(ztv, 0, VIDEO_MODE_PAL); -} - -static -void zoran_common_close(struct zoran* ztv) -{ - if (--ztv->users != 0) - return; - - /* mute audio */ - /* /what/ audio? */ - - /* stop the chip */ - zoran_cap(ztv, 0); -} - -/* - * Open a zoran card. Right now the flags are just a hack - */ -static int zoran_open(struct video_device *dev, int flags) -{ - struct zoran *ztv = (struct zoran*)dev; - struct vidinfo* item; - char* pos; - - DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags)); - - /********************************************* - * We really should be doing lazy allocing... - *********************************************/ - /* allocate a frame buffer */ - if (!ztv->fbuffer) - ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE); - if (!ztv->fbuffer) { - /* could not get a buffer, bail out */ - return -ENOBUFS; - } - /* at this time we _always_ have a framebuffer */ - memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE); - - if (!ztv->overinfo.overlay) - ztv->overinfo.overlay = (void*)kmalloc(1024*1024/8, GFP_KERNEL); - if (!ztv->overinfo.overlay) { - /* could not get an overlay buffer, bail out */ - bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE); - return -ENOBUFS; - } - /* at this time we _always_ have a overlay */ - - /* clear buffer status, and give them a DMAable address */ - pos = ztv->fbuffer; - for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) - { - item->status = FBUFFER_FREE; - item->memadr = pos; - item->busadr = virt_to_bus(pos); - pos += ZORAN_MAX_FBUFFER; - } - - /* do the common part of all open's */ - zoran_common_open(ztv, flags); - - MOD_INC_USE_COUNT; - return 0; -} - -static -void zoran_close(struct video_device* dev) -{ - struct zoran *ztv = (struct zoran*)dev; - - DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD)); - - /* driver specific closure */ - clear_bit(STATE_OVERLAY, &ztv->state); - - zoran_common_close(ztv); - - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ - - /* free the allocated framebuffer */ - if (ztv->fbuffer) - bfree( ztv->fbuffer, ZORAN_MAX_FBUFSIZE ); - ztv->fbuffer = 0; - if (ztv->overinfo.overlay) - kfree( ztv->overinfo.overlay ); - ztv->overinfo.overlay = 0; - - MOD_DEC_USE_COUNT; -} - -/* - * This read function could be used reentrant in a SMP situation. - * - * This is made possible by the spinlock which is kept till we - * found and marked a buffer for our own use. The lock must - * be released as soon as possible to prevent lock contention. - */ -static -long zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) -{ - struct zoran *ztv = (struct zoran*)dev; - unsigned long max; - struct vidinfo* unused = 0; - struct vidinfo* done = 0; - - DEBUG(printk(CARD_DEBUG "zoran_read(%p,%ld,%d)\n",CARD,buf,count,nonblock)); - - /* find ourself a free or completed buffer */ - for (;;) { - struct vidinfo* item; - - write_lock_irq(&ztv->lock); - for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) - { - if (!unused && item->status == FBUFFER_FREE) - unused = item; - if (!done && item->status == FBUFFER_DONE) - done = item; - } - if (done || unused) - break; - - /* no more free buffers, wait for them. */ - write_unlock_irq(&ztv->lock); - if (nonblock) - return -EWOULDBLOCK; - interruptible_sleep_on(&ztv->grabq); - if (signal_pending(current)) - return -EINTR; - } - - /* Do we have 'ready' data? */ - if (!done) { - /* no? than this will take a while... */ - if (nonblock) { - write_unlock_irq(&ztv->lock); - return -EWOULDBLOCK; - } - - /* mark the unused buffer as wanted */ - unused->status = FBUFFER_BUSY; - unused->w = 320; - unused->h = 240; - unused->format = VIDEO_PALETTE_RGB24; - unused->bpp = palette2fmt[unused->format].bpp; - unused->bpl = unused->w * unused->bpp; - unused->next = 0; - { /* add to tail of queue */ - struct vidinfo* oldframe = ztv->workqueue; - if (!oldframe) ztv->workqueue = unused; - else { - while (oldframe->next) oldframe = oldframe->next; - oldframe->next = unused; - } - } - write_unlock_irq(&ztv->lock); - - /* tell the state machine we want it filled /NOW/ */ - zoran_cap(ztv, 1); - - /* wait till this buffer gets grabbed */ - while (unused->status == FBUFFER_BUSY) { - interruptible_sleep_on(&ztv->grabq); - /* see if a signal did it */ - if (signal_pending(current)) - return -EINTR; - } - done = unused; - } - else - write_unlock_irq(&ztv->lock); - - /* Yes! we got data! */ - max = done->bpl * done->h; - if (count > max) - count = max; - if (copy_to_user((void*)buf, done->memadr, count)) - count = -EFAULT; - - /* keep the engine running */ - done->status = FBUFFER_FREE; -// zoran_cap(ztv,1); - - /* tell listeners this buffer became free */ - wake_up_interruptible(&ztv->grabq); - - /* goodbye */ - DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count)); - return count; -} - -static -long zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock) -{ - struct zoran *ztv = (struct zoran *)dev; - UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock); - DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD)); - return -EINVAL; -} - -#if LINUX_VERSION_CODE >= 0x020100 -static -unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) -{ - struct zoran *ztv = (struct zoran *)dev; - struct vidinfo* item; - unsigned int mask = 0; - - poll_wait(file, &ztv->grabq, wait); - - for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++) - if (item->status == FBUFFER_DONE) - { - mask |= (POLLIN | POLLRDNORM); - break; - } - - DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask)); - - return mask; -} -#endif - -/* append a new clipregion to the vector of video_clips */ -static -void new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h) -{ - vcp[vw->clipcount].x = x; - vcp[vw->clipcount].y = y; - vcp[vw->clipcount].width = w; - vcp[vw->clipcount].height = h; - vw->clipcount++; -} - -static -int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg) -{ - struct zoran* ztv = (struct zoran*)dev; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability c; - DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD)); - - strcpy(c.name,ztv->video_dev.name); - c.type = VID_TYPE_CAPTURE| - VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING| - VID_TYPE_FRAMERAM| - VID_TYPE_SCALES; - if (ztv->have_tuner) - c.type |= VID_TYPE_TUNER; - if (ztv->have_decoder) { - c.channels = ztv->card->video_inputs; - c.audios = ztv->card->audio_inputs; - } else - /* no decoder -> no channels */ - c.channels = c.audios = 0; - c.maxwidth = 768; - c.maxheight = 576; - c.minwidth = 32; - c.minheight = 32; - if (copy_to_user(arg,&c,sizeof(c))) - return -EFAULT; - break; - } - - case VIDIOCGCHAN: - { - struct video_channel v; - int mux; - if (copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel)); - v.flags=VIDEO_VC_AUDIO -#ifdef VIDEO_VC_NORM - |VIDEO_VC_NORM -#endif - ; - v.tuners=0; - v.type=VIDEO_TYPE_CAMERA; -#ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API - v.norm=VIDEO_MODE_PAL| - VIDEO_MODE_NTSC| - VIDEO_MODE_SECAM; -#else - v.norm=VIDEO_MODE_PAL; -#endif - /* too many inputs? no decoder -> no channels */ - if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs) - return -EINVAL; - - /* now determine the name of the channel */ - mux = ztv->card->video_mux[v.channel]; - if (mux & IS_TUNER) { - /* lets assume only one tuner, yes? */ - strcpy(v.name,"Television"); - v.type = VIDEO_TYPE_TV; - if (ztv->have_tuner) { - v.flags |= VIDEO_VC_TUNER; - v.tuners = 1; - } - } - else if (mux & IS_SVHS) - sprintf(v.name,"S-Video-%d",v.channel); - else - sprintf(v.name,"CVBS-%d",v.channel); - - if (copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - break; - } - case VIDIOCSCHAN: - { /* set video channel */ - struct video_channel v; - if (copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm)); - - /* too many inputs? no decoder -> no channels */ - if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs) - return -EINVAL; - - if (v.norm != VIDEO_MODE_PAL && - v.norm != VIDEO_MODE_NTSC && - v.norm != VIDEO_MODE_SECAM && - v.norm != VIDEO_MODE_AUTO) - return -EOPNOTSUPP; - - /* make it happen, nr1! */ - return zoran_muxsel(ztv,v.channel,v.norm); - } - - case VIDIOCGTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner)); - - /* Only no or one tuner for now */ - if (!ztv->have_tuner || v.tuner) - return -EINVAL; - - strcpy(v.name,"Television"); - v.rangelow = 0; - v.rangehigh = ~0; - v.flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; - v.mode = ztv->norm; - v.signal = 0xFFFF; /* unknown */ - - if (copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - break; - } - case VIDIOCSTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode)); - - /* Only no or one tuner for now */ - if (!ztv->have_tuner || v.tuner) - return -EINVAL; - - /* and it only has certain valid modes */ - if( v.mode != VIDEO_MODE_PAL && - v.mode != VIDEO_MODE_NTSC && - v.mode != VIDEO_MODE_SECAM) - return -EOPNOTSUPP; - - /* engage! */ - return zoran_muxsel(ztv,v.tuner,v.mode); - } - - case VIDIOCGPICT: - { - struct video_picture p = ztv->picture; - DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD)); - p.depth = ztv->depth; - switch (p.depth) { - case 8: p.palette=VIDEO_PALETTE_YUV422; - break; - case 15: p.palette=VIDEO_PALETTE_RGB555; - break; - case 16: p.palette=VIDEO_PALETTE_RGB565; - break; - case 24: p.palette=VIDEO_PALETTE_RGB24; - break; - case 32: p.palette=VIDEO_PALETTE_RGB32; - break; - } - if (copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - break; - } - case VIDIOCSPICT: - { - struct video_picture p; - if (copy_from_user(&p, arg,sizeof(p))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette)); - - /* depth must match with framebuffer */ - if (p.depth != ztv->depth) - return -EINVAL; - - /* check if palette matches this bpp */ - if (p.palette>NRPALETTES || - palette2fmt[p.palette].bpp != ztv->overinfo.bpp) - return -EINVAL; - - write_lock_irq(&ztv->lock); - ztv->overinfo.format = p.palette; - ztv->picture = p; - write_unlock_irq(&ztv->lock); - - /* tell the decoder */ - i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); - break; - } - - case VIDIOCGWIN: - { - struct video_window vw; - DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD)); - read_lock(&ztv->lock); - vw.x = ztv->overinfo.x; - vw.y = ztv->overinfo.y; - vw.width = ztv->overinfo.w; - vw.height = ztv->overinfo.h; - vw.chromakey= 0; - vw.flags = 0; - if (ztv->vidInterlace) - vw.flags|=VIDEO_WINDOW_INTERLACE; - read_unlock(&ztv->lock); - if (copy_to_user(arg,&vw,sizeof(vw))) - return -EFAULT; - break; - } - case VIDIOCSWIN: - { - struct video_window vw; - struct video_clip *vcp; - int on; - if (copy_from_user(&vw,arg,sizeof(vw))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount)); - - if (vw.flags) - return -EINVAL; - - if (vw.clipcount>256) - return -EDOM; /* Too many! */ - - /* - * Do any clips. - */ - vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4)); - if (vcp==NULL) - return -ENOMEM; - if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) - return -EFAULT; - - on = ztv->running; - if (on) - zoran_cap(ztv, 0); - - /* - * strange, it seems xawtv sometimes calls us with 0 - * width and/or height. Ignore these values - */ - if (vw.x == 0) - vw.x = ztv->overinfo.x; - if (vw.y == 0) - vw.y = ztv->overinfo.y; - - /* by now we are committed to the new data... */ - write_lock_irq(&ztv->lock); - ztv->overinfo.x = vw.x; - ztv->overinfo.y = vw.y; - ztv->overinfo.w = vw.width; - ztv->overinfo.h = vw.height; - write_unlock_irq(&ztv->lock); - - /* - * Impose display clips - */ - if (vw.x+vw.width > ztv->swidth) - new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1); - if (vw.y+vw.height > ztv->sheight) - new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1); - - /* built the requested clipping zones */ - zoran_set_geo(ztv, &ztv->overinfo); - zoran_built_overlay(ztv, vw.clipcount, vcp); - vfree(vcp); - - /* if we were on, restart the video engine */ - if (on) - zoran_cap(ztv, 1); - break; - } - - case VIDIOCCAPTURE: - { - int v; - get_user_ret(v,(int*)arg, -EFAULT); - DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v)); - - if (v==0) { - clear_bit(STATE_OVERLAY, &ztv->state); - zoran_cap(ztv, 1); - } - else { - /* is VIDIOCSFBUF, VIDIOCSWIN done? */ - if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0) - return -EINVAL; - - set_bit(STATE_OVERLAY, &ztv->state); - zoran_cap(ztv, 1); - } - break; - } - - case VIDIOCGFBUF: - { - struct video_buffer v; - DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD)); - read_lock(&ztv->lock); - v.base = (void *)ztv->overinfo.busadr; - v.height = ztv->sheight; - v.width = ztv->swidth; - v.depth = ztv->depth; - v.bytesperline = ztv->overinfo.bpl; - read_unlock(&ztv->lock); - if(copy_to_user(arg, &v,sizeof(v))) - return -EFAULT; - break; - } - case VIDIOCSFBUF: - { - struct video_buffer v; -#if LINUX_VERSION_CODE >= 0x020100 - if(!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_ADMIN)) -#else - if(!suser()) -#endif - return -EPERM; - if (copy_from_user(&v, arg,sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline)); - - if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32) - return -EINVAL; - if (v.bytesperline<1) - return -EINVAL; - if (ztv->running) - return -EBUSY; - write_lock_irq(&ztv->lock); - ztv->overinfo.busadr = (ulong)v.base; - ztv->sheight = v.height; - ztv->swidth = v.width; - ztv->depth = v.depth; /* bits per pixel */ - ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */ - ztv->overinfo.bpl = v.bytesperline; /* bytes per line */ - write_unlock_irq(&ztv->lock); - break; - } - - case VIDIOCKEY: - { - /* Will be handled higher up .. */ - break; - } - - case VIDIOCSYNC: - { - int i; - get_user_ret(i,(int*)arg, -EFAULT); - DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i)); - if (i<0 || i>ZORAN_MAX_FBUFFERS) - return -EINVAL; - switch (ztv->grabinfo[i].status) { - case FBUFFER_FREE: - return -EINVAL; - case FBUFFER_BUSY: - /* wait till this buffer gets grabbed */ - while (ztv->grabinfo[i].status == FBUFFER_BUSY) { - interruptible_sleep_on(&ztv->grabq); - /* see if a signal did it */ - if (signal_pending(current)) - return -EINTR; - } - /* don't fall through; a DONE buffer is not UNUSED */ - break; - case FBUFFER_DONE: - ztv->grabinfo[i].status = FBUFFER_FREE; - /* tell ppl we have a spare buffer */ - wake_up_interruptible(&ztv->grabq); - break; - } - DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i)); - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - struct vidinfo* frame; - if (copy_from_user(&vm,arg,sizeof(vm))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format)); - if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS || - vm.width<32 || vm.width>768 || - vm.height<32 || vm.height>576 || - vm.format>NRPALETTES || - palette2fmt[vm.format].mode == 0) - return -EINVAL; - - /* we are allowed to take over UNUSED and DONE buffers */ - frame = &ztv->grabinfo[vm.frame]; - if (frame->status == FBUFFER_BUSY) - return -EBUSY; - - /* setup the other parameters if they are given */ - write_lock_irq(&ztv->lock); - frame->w = vm.width; - frame->h = vm.height; - frame->format = vm.format; - frame->bpp = palette2fmt[frame->format].bpp; - frame->bpl = frame->w*frame->bpp; - frame->status = FBUFFER_BUSY; - frame->next = 0; - { /* add to tail of queue */ - struct vidinfo* oldframe = ztv->workqueue; - if (!oldframe) ztv->workqueue = frame; - else { - while (oldframe->next) oldframe = oldframe->next; - oldframe->next = frame; - } - } - write_unlock_irq(&ztv->lock); - zoran_cap(ztv, 1); - break; - } - - case VIDIOCGMBUF: - { - struct video_mbuf mb; - int i; - DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD)); - mb.size = ZORAN_MAX_FBUFSIZE; - mb.frames = ZORAN_MAX_FBUFFERS; - for (i=0; ivideo_dev.minor; - vu.vbi = ztv->vbi_dev.minor; - vu.radio = VIDEO_NO_UNIT; - vu.audio = VIDEO_NO_UNIT; - vu.teletext = VIDEO_NO_UNIT; - if(copy_to_user(arg, &vu,sizeof(vu))) - return -EFAULT; - break; - } - - case VIDIOCGFREQ: - { - unsigned long v = ztv->tuner_freq; - if (copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD)); - break; - } - case VIDIOCSFREQ: - { - unsigned long v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD)); - - if (ztv->have_tuner) { - int fixme = v; - if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0) - return -EAGAIN; - } - ztv->tuner_freq = v; - break; - } - - /* Why isn't this in the API? - * And why doesn't it take a buffer number? - case BTTV_FIELDNR: - { - unsigned long v = ztv->lastfieldnr; - if (copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD)); - break; - } - */ - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static -int zoran_mmap(struct video_device* dev, const char* adr, unsigned long size) -{ - struct zoran* ztv = (struct zoran*)dev; - unsigned long start = (unsigned long)adr; - unsigned long pos; - - DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size)); - - /* sanity checks */ - if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer) - return -EINVAL; - - /* start mapping the whole shabang to user memory */ - pos = (unsigned long)ztv->fbuffer; - while (size>0) { - unsigned long page = virt_to_phys((void*)pos); - if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - return 0; -} - -static struct video_device zr36120_template= -{ - "UNSET", - VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, - VID_HARDWARE_ZR36120, - - zoran_open, - zoran_close, - zoran_read, - zoran_write, -#if LINUX_VERSION_CODE >= 0x020100 - zoran_poll, /* poll */ -#endif - zoran_ioctl, - zoran_mmap, - NULL, /* initialize */ - NULL, - 0, - -1 -}; - -static -int vbi_open(struct video_device *dev, int flags) -{ - struct zoran *ztv = (struct zoran*)dev->priv; - struct vidinfo* item; - - DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags)); - - /* - * During VBI device open, we continiously grab VBI-like - * data in the vbi buffer when we have nothing to do. - * Only when there is an explicit request for VBI data - * (read call) we /force/ a read. - */ - - /* allocate buffers */ - for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) - { - item->status = FBUFFER_FREE; - - /* alloc */ - if (!item->memadr) { - item->memadr = bmalloc(ZORAN_VBI_BUFSIZE); - if (!item->memadr) { - /* could not get a buffer, bail out */ - while (item != ztv->readinfo) { - item--; - bfree(item->memadr, ZORAN_VBI_BUFSIZE); - item->memadr = 0; - item->busadr = 0; - } - return -ENOBUFS; - } - } - - /* determine the DMAable address */ - item->busadr = virt_to_bus(item->memadr); - } - - /* do the common part of all open's */ - zoran_common_open(ztv, flags); - - set_bit(STATE_VBI, &ztv->state); - /* start read-ahead */ - zoran_cap(ztv, 1); - - MOD_INC_USE_COUNT; - return 0; -} - -static -void vbi_close(struct video_device *dev) -{ - struct zoran *ztv = (struct zoran*)dev->priv; - struct vidinfo* item; - - DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD)); - - /* driver specific closure */ - clear_bit(STATE_VBI, &ztv->state); - - zoran_common_close(ztv); - - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ - - for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) - { - if (item->memadr) - bfree(item->memadr, ZORAN_VBI_BUFSIZE); - item->memadr = 0; - } - - MOD_DEC_USE_COUNT; -} - -/* - * This read function could be used reentrant in a SMP situation. - * - * This is made possible by the spinlock which is kept till we - * found and marked a buffer for our own use. The lock must - * be released as soon as possible to prevent lock contention. - */ -static -long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock) -{ - struct zoran *ztv = (struct zoran*)dev->priv; - unsigned long max; - struct vidinfo* unused = 0; - struct vidinfo* done = 0; - - DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock)); - - /* find ourself a free or completed buffer */ - for (;;) { - struct vidinfo* item; - - write_lock_irq(&ztv->lock); - for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { - if (!unused && item->status == FBUFFER_FREE) - unused = item; - if (!done && item->status == FBUFFER_DONE) - done = item; - } - if (done || unused) - break; - - /* no more free buffers, wait for them. */ - write_unlock_irq(&ztv->lock); - if (nonblock) - return -EWOULDBLOCK; - interruptible_sleep_on(&ztv->vbiq); - if (signal_pending(current)) - return -EINTR; - } - - /* Do we have 'ready' data? */ - if (!done) { - /* no? than this will take a while... */ - if (nonblock) { - write_unlock_irq(&ztv->lock); - return -EWOULDBLOCK; - } - - /* mark the unused buffer as wanted */ - unused->status = FBUFFER_BUSY; - unused->next = 0; - { /* add to tail of queue */ - struct vidinfo* oldframe = ztv->workqueue; - if (!oldframe) ztv->workqueue = unused; - else { - while (oldframe->next) oldframe = oldframe->next; - oldframe->next = unused; - } - } - write_unlock_irq(&ztv->lock); - - /* tell the state machine we want it filled /NOW/ */ - zoran_cap(ztv, 1); - - /* wait till this buffer gets grabbed */ - while (unused->status == FBUFFER_BUSY) { - interruptible_sleep_on(&ztv->vbiq); - /* see if a signal did it */ - if (signal_pending(current)) - return -EINTR; - } - done = unused; - } - else - write_unlock_irq(&ztv->lock); - - /* Yes! we got data! */ - max = done->bpl * -done->h; - if (count > max) - count = max; - - /* check if the user gave us enough room to write the data */ - if (!access_ok(VERIFY_WRITE, buf, count)) { - count = -EFAULT; - goto out; - } - - /* - * Now transform/strip the data from YUV to Y-only - * NB. Assume the Y is in the LSB of the YUV data. - */ - { - unsigned char* optr = buf; - unsigned char* eptr = buf+count; - - /* are we beeing accessed from an old driver? */ - if (count == 2*19*2048) { - /* - * Extreme HACK, old VBI programs expect 2048 points - * of data, and we only got 864 orso. Double each - * datapoint and clear the rest of the line. - * This way we have appear to have a - * sample_frequency of 29.5 Mc. - */ - int x,y; - unsigned char* iptr = done->memadr+1; - for (y=done->h; optrw; x++) - { - unsigned char a = iptr[x*2]; - *optr++ = a; - *optr++ = a; - } - /* and clear the rest of the line */ - for (x*=2; optrbpl; x++) - *optr++ = 0; - /* next line */ - iptr += done->bpl; - } - } - else { - /* - * Other (probably newer) programs asked - * us what geometry we are using, and are - * reading the correct size. - */ - int x,y; - unsigned char* iptr = done->memadr+1; - for (y=done->h; optrw; x++) - *optr++ = iptr[x*2]; - /* and clear the rest of the line */ - for (;optrbpl; x++) - *optr++ = 0; - /* next line */ - iptr += done->bpl; - } - } - - /* API compliance: - * place the framenumber (half fieldnr) in the last long - */ - ((ulong*)eptr)[-1] = done->fieldnr/2; - } - - /* keep the engine running */ - done->status = FBUFFER_FREE; - zoran_cap(ztv, 1); - - /* tell listeners this buffer just became free */ - wake_up_interruptible(&ztv->vbiq); - - /* goodbye */ -out: - DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count)); - return count; -} - -#if LINUX_VERSION_CODE >= 0x020100 -static -unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) -{ - struct zoran *ztv = (struct zoran*)dev->priv; - struct vidinfo* item; - unsigned int mask = 0; - - poll_wait(file, &ztv->vbiq, wait); - - for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) - if (item->status == FBUFFER_DONE) - { - mask |= (POLLIN | POLLRDNORM); - break; - } - - DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask)); - - return mask; -} -#endif - -static -int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) -{ - struct zoran* ztv = (struct zoran*)dev->priv; - - switch (cmd) { - case VIDIOCGVBIFMT: - { - struct vbi_format f; - DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD)); - f.sampling_rate = 14750000UL; - f.samples_per_line = -ztv->readinfo[0].w; - f.sample_format = VIDEO_PALETTE_RAW; - f.start[0] = f.start[1] = ztv->readinfo[0].y; - f.start[1] += 312; - f.count[0] = f.count[1] = -ztv->readinfo[0].h; - f.flags = VBI_INTERLACED; - if (copy_to_user(arg,&f,sizeof(f))) - return -EFAULT; - break; - } - case VIDIOCSVBIFMT: - { - struct vbi_format f; - int i; - if (copy_from_user(&f, arg,sizeof(f))) - return -EFAULT; - DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags)); - - /* lots of parameters are fixed... (PAL) */ - if (f.sampling_rate != 14750000UL || - f.samples_per_line > 864 || - f.sample_format != VIDEO_PALETTE_RAW || - f.start[0] < 0 || - f.start[0] != f.start[1]-312 || - f.count[0] != f.count[1] || - f.start[0]+f.count[0] >= 288 || - f.flags != VBI_INTERLACED) - return -EINVAL; - - write_lock_irq(&ztv->lock); - ztv->readinfo[0].y = f.start[0]; - ztv->readinfo[0].w = -f.samples_per_line; - ztv->readinfo[0].h = -f.count[0]; - ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp; - for (i=1; ireadinfo[i] = ztv->readinfo[i]; - write_unlock_irq(&ztv->lock); - break; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static struct video_device vbi_template= -{ - "UNSET", - VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, - VID_HARDWARE_ZR36120, - - vbi_open, - vbi_close, - vbi_read, - zoran_write, -#if LINUX_VERSION_CODE >= 0x020100 - vbi_poll, /* poll */ -#endif - vbi_ioctl, - NULL, /* no mmap */ - NULL, /* no initialize */ - NULL, /* priv */ - 0, /* busy */ - -1 /* minor */ -}; - -/* - * Scan for a Zoran chip, request the irq and map the io memory - */ -static -int __init find_zoran(void) -{ - int result; - struct zoran *ztv; - struct pci_dev *dev = NULL; - unsigned char revision; - int zoran_num=0; - - while ((dev = pci_find_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev))) - { - /* Ok, a ZR36120/ZR36125 found! */ - ztv = &zorans[zoran_num]; - ztv->dev = dev; - - if (pci_enable_device(dev)) - return -EIO; - - pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision); - printk(KERN_INFO "zoran: Zoran %x (rev %d) ", - dev->device, revision); - printk("bus: %d, devfn: %d, irq: %d, ", - dev->bus->number, dev->devfn, dev->irq); - printk("memory: 0x%08lx.\n", ztv->zoran_adr); - - ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000); - DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem)); - - result = request_irq(dev->irq, zoran_irq, - SA_SHIRQ|SA_INTERRUPT,"zoran",(void *)ztv); - if (result==-EINVAL) - { - printk(KERN_ERR "zoran: Bad irq number or handler\n"); - return -EINVAL; - } - if (result==-EBUSY) - printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq); - if (result < 0) - return result; - - /* Enable bus-mastering */ - pci_set_master(dev); - - zoran_num++; - } - if(zoran_num) - printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num); - return zoran_num; -} - -static -int __init init_zoran(int card) -{ - struct zoran *ztv = &zorans[card]; - int i; - - /* if the given cardtype valid? */ - if (cardtype[card]>=NRTVCARDS) { - printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]); - return -1; - } - - /* reset the zoran */ - zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI); - udelay(10); - zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI); - udelay(10); - - /* zoran chip specific details */ - ztv->card = tvcards+cardtype[card]; /* point to the selected card */ - ztv->norm = 0; /* PAL */ - ztv->tuner_freq = 0; - - /* videocard details */ - ztv->swidth = 800; - ztv->sheight = 600; - ztv->depth = 16; - - /* State details */ - ztv->fbuffer = 0; - ztv->overinfo.kindof = FBUFFER_OVERLAY; - ztv->overinfo.status = FBUFFER_FREE; - ztv->overinfo.x = 0; - ztv->overinfo.y = 0; - ztv->overinfo.w = 768; /* 640 */ - ztv->overinfo.h = 576; /* 480 */ - ztv->overinfo.format = VIDEO_PALETTE_RGB565; - ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp; - ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth; - ztv->overinfo.busadr = 0; - ztv->overinfo.memadr = 0; - ztv->overinfo.overlay = 0; - for (i=0; igrabinfo[i] = ztv->overinfo; - ztv->grabinfo[i].kindof = FBUFFER_GRAB; - } - init_waitqueue_head(&ztv->grabq); - - /* VBI details */ - ztv->readinfo[0] = ztv->overinfo; - ztv->readinfo[0].kindof = FBUFFER_VBI; - ztv->readinfo[0].w = -864; - ztv->readinfo[0].h = -38; - ztv->readinfo[0].format = VIDEO_PALETTE_YUV422; - ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp; - ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp; - for (i=1; ireadinfo[i] = ztv->readinfo[0]; - init_waitqueue_head(&ztv->vbiq); - - /* maintenance data */ - ztv->have_decoder = 0; - ztv->have_tuner = 0; - ztv->tuner_type = 0; - ztv->running = 0; - ztv->users = 0; - ztv->lock = RW_LOCK_UNLOCKED; - ztv->workqueue = 0; - ztv->fieldnr = 0; - ztv->lastfieldnr = 0; - - if (triton1) - zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC); - - /* external FL determines TOP frame */ - zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); - - /* set HSpol */ - if (ztv->card->hsync_pos) - zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH); - /* set VSpol */ - if (ztv->card->vsync_pos) - zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV); - - /* Set the proper General Purpuse register bits */ - /* implicit: no softreset, 0 waitstates */ - zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI); - /* implicit: 3 duration and recovery PCI clocks on guest 0-3 */ - zrwrite(ztv->card->gpval<<24,ZORAN_GUEST); - - /* clear interrupt status */ - zrwrite(~0, ZORAN_ISR); - - /* - * i2c template - */ - ztv->i2c = zoran_i2c_bus_template; - sprintf(ztv->i2c.name,"zoran-%d",card); - ztv->i2c.data = ztv; - - /* - * Now add the template and register the device unit - */ - ztv->video_dev = zr36120_template; - strcpy(ztv->video_dev.name, ztv->i2c.name); - ztv->video_dev.priv = ztv; - if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER) < 0) - return -1; - - ztv->vbi_dev = vbi_template; - strcpy(ztv->vbi_dev.name, ztv->i2c.name); - ztv->vbi_dev.priv = ztv; - if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI) < 0) { - video_unregister_device(&ztv->video_dev); - return -1; - } - i2c_register_bus(&ztv->i2c); - - /* set interrupt mask - the PIN enable will be set later */ - zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR); - - printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name); - return 0; -} - -static -void __exit release_zoran(int max) -{ - struct zoran *ztv; - int i; - - for (i=0;idev->irq,ztv); - - /* unregister i2c_bus */ - i2c_unregister_bus((&ztv->i2c)); - - /* unmap and free memory */ - if (ztv->zoran_mem) - iounmap(ztv->zoran_mem); - - video_unregister_device(&ztv->video_dev); - video_unregister_device(&ztv->vbi_dev); - } -} - -void __exit zr36120_exit(void) -{ - release_zoran(zoran_cards); -} - -int __init zr36120_init(void) -{ - int card; - - handle_chipset(); - zoran_cards = find_zoran(); - if (zoran_cards<0) - /* no cards found, no need for a driver */ - return -EIO; - - /* initialize Zorans */ - for (card=0; card -#include - -#include -#include - -#include - -/* - * Debug macro's, place an x behind the ) for actual debug-compilation - * E.g. #define DEBUG(x...) x - */ -#define DEBUG(x...) /* Debug driver */ -#define IDEBUG(x...) /* Debug interrupt handler */ -#define PDEBUG 0 /* Debug PCI writes */ - -/* defined in zr36120_i2c */ -extern struct i2c_bus zoran_i2c_bus_template; - -#define ZORAN_MAX_FBUFFERS 2 -#define ZORAN_MAX_FBUFFER (768*576*2) -#define ZORAN_MAX_FBUFSIZE (ZORAN_MAX_FBUFFERS*ZORAN_MAX_FBUFFER) - -#define ZORAN_VBI_BUFFERS 2 -#define ZORAN_VBI_BUFSIZE (22*1024*2) - -struct tvcard { - char* name; /* name of the cardtype */ - int video_inputs; /* number of channels defined in video_mux */ - int audio_inputs; /* number of channels defined in audio_mux */ - __u32 swapi2c:1, /* need to swap i2c wires SDA/SCL? */ - usegirq1:1, /* VSYNC at GIRQ1 instead of GIRQ0? */ - vsync_pos:1, /* positive VSYNC signal? */ - hsync_pos:1, /* positive HSYNC signal? */ - gpdir:8, /* General Purpose Direction register */ - gpval:8; /* General Purpose Value register */ - int video_mux[6]; /* mapping channel number to physical input */ -#define IS_TUNER 0x80 -#define IS_SVHS 0x40 -#define CHANNEL_MASK 0x3F - int audio_mux[6]; /* mapping channel number to physical input */ -}; -#define TUNER(x) ((x)|IS_TUNER) -#define SVHS(x) ((x)|IS_SVHS) - -struct vidinfo { - struct vidinfo* next; /* next active buffer */ - uint kindof; -#define FBUFFER_OVERLAY 0 -#define FBUFFER_GRAB 1 -#define FBUFFER_VBI 2 - uint status; -#define FBUFFER_FREE 0 -#define FBUFFER_BUSY 1 -#define FBUFFER_DONE 2 - ulong fieldnr; /* # of field, not framer! */ - uint x,y; - int w,h; /* w,h can be negative! */ - uint format; /* index in palette2fmt[] */ - uint bpp; /* lookup from palette2fmt[] */ - uint bpl; /* calc: width * bpp */ - ulong busadr; /* bus addr for DMA engine */ - char* memadr; /* kernel addr for making copies */ - ulong* overlay; /* kernel addr of overlay mask */ -}; - -struct zoran -{ - struct video_device video_dev; -#define CARD_DEBUG KERN_DEBUG "%s(%lu): " -#define CARD_INFO KERN_INFO "%s(%lu): " -#define CARD_ERR KERN_ERR "%s(%lu): " -#define CARD ztv->video_dev.name,ztv->fieldnr - - /* zoran chip specific details */ - struct i2c_bus i2c; /* i2c registration data */ - struct pci_dev* dev; /* ptr to PCI device */ - ulong zoran_adr; /* bus address of IO memory */ - char* zoran_mem; /* kernel address of IO memory */ - struct tvcard* card; /* the cardtype */ - uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */ - uint tuner_freq; /* Current freq in kHz */ - struct video_picture picture; /* Current picture params */ - - /* videocard details */ - uint swidth; /* screen width */ - uint sheight; /* screen height */ - uint depth; /* depth in bits */ - - /* State details */ - char* fbuffer; /* framebuffers for mmap */ - struct vidinfo overinfo; /* overlay data */ - struct vidinfo grabinfo[ZORAN_MAX_FBUFFERS]; /* grabbing data*/ - wait_queue_head_t grabq; /* grabbers queue */ - - /* VBI details */ - struct video_device vbi_dev; - struct vidinfo readinfo[2]; /* VBI data - flip buffers */ - wait_queue_head_t vbiq; /* vbi queue */ - - /* maintenance data */ - int have_decoder; /* did we detect a mux? */ - int have_tuner; /* did we detect a tuner? */ - int users; /* howmany video/vbi open? */ - int tuner_type; /* tuner type, when found */ - int running; /* are we rolling? */ - rwlock_t lock; - int state; /* what is requested of us? */ -#define STATE_OVERLAY 0 -#define STATE_VBI 1 - struct vidinfo* workqueue; /* buffers to grab, head is active */ - ulong fieldnr; /* #field, ticked every VSYNC */ - ulong lastfieldnr; /* #field, ticked every GRAB */ - - int vidInterlace; /* calculated */ - int vidXshift; /* calculated */ - uint vidWidth; /* calculated */ - uint vidHeight; /* calculated */ -}; - -#define zrwrite(dat,adr) writel((dat),(char *) (ztv->zoran_mem+(adr))) -#define zrread(adr) readl(ztv->zoran_mem+(adr)) - -#if PDEBUG == 0 -#define zrand(dat,adr) zrwrite((dat) & zrread(adr), adr) -#define zror(dat,adr) zrwrite((dat) | zrread(adr), adr) -#define zraor(dat,mask,adr) zrwrite( ((dat)&~(mask)) | ((mask)&zrread(adr)), adr) -#else -#define zrand(dat, adr) \ -do { \ - ulong data = (dat) & zrread((adr)); \ - zrwrite(data, (adr)); \ - if (0 != (~(dat) & zrread((adr)))) \ - printk(KERN_DEBUG "zoran: zrand at %d(%d) detected set bits(%x)\n", __LINE__, (adr), (dat)); \ -} while(0) - -#define zror(dat, adr) \ -do { \ - ulong data = (dat) | zrread((adr)); \ - zrwrite(data, (adr)); \ - if ((dat) != ((dat) & zrread(adr))) \ - printk(KERN_DEBUG "zoran: zror at %d(%d) detected unset bits(%x)\n", __LINE__, (adr), (dat)); \ -} while(0) - -#define zraor(dat, mask, adr) \ -do { \ - ulong data; \ - if ((dat) & (mask)) \ - printk(KERN_DEBUG "zoran: zraor at %d(%d) detected bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ - data = ((dat)&~(mask)) | ((mask) & zrread((adr))); \ - zrwrite(data,(adr)); \ - if ( (dat) != (~(mask) & zrread((adr))) ) \ - printk(KERN_DEBUG "zoran: zraor at %d(%d) could not set all bits(%x:%x)\n", __LINE__, (adr), (dat), (mask)); \ -} while(0) -#endif - -#endif - -/* zoran PCI address space */ -#define ZORAN_VFEH 0x000 /* Video Front End Horizontal Conf. */ -#define ZORAN_VFEH_HSPOL (1<<30) -#define ZORAN_VFEH_HSTART (0x3FF<<10) -#define ZORAN_VFEH_HEND (0x3FF<<0) - -#define ZORAN_VFEV 0x004 /* Video Front End Vertical Conf. */ -#define ZORAN_VFEV_VSPOL (1<<30) -#define ZORAN_VFEV_VSTART (0x3FF<<10) -#define ZORAN_VFEV_VEND (0x3FF<<0) - -#define ZORAN_VFEC 0x008 /* Video Front End Scaler and Pixel */ -#define ZORAN_VFEC_EXTFL (1<<26) -#define ZORAN_VFEC_TOPFIELD (1<<25) -#define ZORAN_VFEC_VCLKPOL (1<<24) -#define ZORAN_VFEC_HFILTER (7<<21) -#define ZORAN_VFEC_HFILTER_1 (0<<21) /* no lumi, 3-tap chromo */ -#define ZORAN_VFEC_HFILTER_2 (1<<21) /* 3-tap lumi, 3-tap chromo */ -#define ZORAN_VFEC_HFILTER_3 (2<<21) /* 4-tap lumi, 4-tap chromo */ -#define ZORAN_VFEC_HFILTER_4 (3<<21) /* 5-tap lumi, 4-tap chromo */ -#define ZORAN_VFEC_HFILTER_5 (4<<21) /* 4-tap lumi, 4-tap chromo */ -#define ZORAN_VFEC_DUPFLD (1<<20) -#define ZORAN_VFEC_HORDCM (63<<14) -#define ZORAN_VFEC_VERDCM (63<<8) -#define ZORAN_VFEC_DISPMOD (1<<6) -#define ZORAN_VFEC_RGB (3<<3) -#define ZORAN_VFEC_RGB_YUV422 (0<<3) -#define ZORAN_VFEC_RGB_RGB888 (1<<3) -#define ZORAN_VFEC_RGB_RGB565 (2<<3) -#define ZORAN_VFEC_RGB_RGB555 (3<<3) -#define ZORAN_VFEC_ERRDIF (1<<2) -#define ZORAN_VFEC_PACK24 (1<<1) -#define ZORAN_VFEC_LE (1<<0) - -#define ZORAN_VTOP 0x00C /* Video Display "Top" */ - -#define ZORAN_VBOT 0x010 /* Video Display "Bottom" */ - -#define ZORAN_VSTR 0x014 /* Video Display Stride */ -#define ZORAN_VSTR_DISPSTRIDE (0xFFFF<<16) -#define ZORAN_VSTR_VIDOVF (1<<8) -#define ZORAN_VSTR_SNAPSHOT (1<<1) -#define ZORAN_VSTR_GRAB (1<<0) - -#define ZORAN_VDC 0x018 /* Video Display Conf. */ -#define ZORAN_VDC_VIDEN (1<<31) -#define ZORAN_VDC_MINPIX (0x1F<<25) -#define ZORAN_VDC_TRICOM (1<<24) -#define ZORAN_VDC_VIDWINHT (0x3FF<<12) -#define ZORAN_VDC_VIDWINWID (0x3FF<<0) - -#define ZORAN_MTOP 0x01C /* Masking Map "Top" */ - -#define ZORAN_MBOT 0x020 /* Masking Map "Bottom" */ - -#define ZORAN_OCR 0x024 /* Overlay Control */ -#define ZORAN_OCR_OVLEN (1<<15) -#define ZORAN_OCR_MASKSTRIDE (0xFF<<0) - -#define ZORAN_PCI 0x028 /* System, PCI and GPP Control */ -#define ZORAN_PCI_SOFTRESET (1<<24) -#define ZORAN_PCI_WAITSTATE (3<<16) -#define ZORAN_PCI_GENPURDIR (0xFF<<0) - -#define ZORAN_GUEST 0x02C /* GuestBus Control */ - -#define ZORAN_CSOURCE 0x030 /* Code Source Address */ - -#define ZORAN_CTRANS 0x034 /* Code Transfer Control */ - -#define ZORAN_CMEM 0x038 /* Code Memory Pointer */ - -#define ZORAN_ISR 0x03C /* Interrupt Status Register */ -#define ZORAN_ISR_CODE (1<<28) -#define ZORAN_ISR_GIRQ0 (1<<29) -#define ZORAN_ISR_GIRQ1 (1<<30) - -#define ZORAN_ICR 0x040 /* Interrupt Control Register */ -#define ZORAN_ICR_EN (1<<24) -#define ZORAN_ICR_CODE (1<<28) -#define ZORAN_ICR_GIRQ0 (1<<29) -#define ZORAN_ICR_GIRQ1 (1<<30) - -#define ZORAN_I2C 0x044 /* I2C-Bus */ -#define ZORAN_I2C_SCL (1<<1) -#define ZORAN_I2C_SDA (1<<0) - -#define ZORAN_POST 0x48 /* PostOffice */ -#define ZORAN_POST_PEN (1<<25) -#define ZORAN_POST_TIME (1<<24) -#define ZORAN_POST_DIR (1<<23) -#define ZORAN_POST_GUESTID (3<<20) -#define ZORAN_POST_GUEST (7<<16) -#define ZORAN_POST_DATA (0xFF<<0) - -#endif diff --git a/drivers/char/zr36120_i2c.c b/drivers/char/zr36120_i2c.c deleted file mode 100644 index 0de59b9f1..000000000 --- a/drivers/char/zr36120_i2c.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - zr36120_i2c.c - Zoran 36120/36125 based framegrabbers - - Copyright (C) 1998-1999 Pauline Middelink - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include - -#include -#include -#include - -#include "tuner.h" -#include "zr36120.h" - -/* ----------------------------------------------------------------------- */ -/* I2C functions */ -/* ----------------------------------------------------------------------- */ - -/* software I2C functions */ - -#define I2C_DELAY 10 - -static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data) -{ - struct zoran *ztv = (struct zoran*)bus->data; - unsigned int b = 0; - if (data) b |= ztv->card->swapi2c ? ZORAN_I2C_SCL : ZORAN_I2C_SDA; - if (ctrl) b |= ztv->card->swapi2c ? ZORAN_I2C_SDA : ZORAN_I2C_SCL; - zrwrite(b, ZORAN_I2C); - udelay(I2C_DELAY); -} - -static int i2c_getdataline(struct i2c_bus *bus) -{ - struct zoran *ztv = (struct zoran*)bus->data; - if (ztv->card->swapi2c) - return zrread(ZORAN_I2C) & ZORAN_I2C_SCL; - return zrread(ZORAN_I2C) & ZORAN_I2C_SDA; -} - -static -void attach_inform(struct i2c_bus *bus, int id) -{ - struct zoran *ztv = (struct zoran*)bus->data; - struct video_decoder_capability dc; - int rv; - - switch (id) { - case I2C_DRIVERID_VIDEODECODER: - DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); - - /* fetch the capabilites of the decoder */ - rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); - if (rv) { - DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); - break; - } - DEBUG(printk(CARD_DEBUG "capabilities %d %d %d\n",CARD,dc.flags,dc.inputs,dc.outputs)); - - /* Test if the decoder can de VBI transfers */ - if (dc.flags & 16 /*VIDEO_DECODER_VBI*/) - ztv->have_decoder = 2; - else - ztv->have_decoder = 1; - break; - case I2C_DRIVERID_TUNER: - ztv->have_tuner = 1; - DEBUG(printk(CARD_INFO "tuner attached\n",CARD)); - if (ztv->tuner_type >= 0) - { - if (i2c_control_device(&ztv->i2c,I2C_DRIVERID_TUNER,TUNER_SET_TYPE,&ztv->tuner_type)<0) - DEBUG(printk(CARD_INFO "attach_inform; tuner wont be set to type %d\n",CARD,ztv->tuner_type)); - } - break; - default: - DEBUG(printk(CARD_INFO "attach_inform; unknown device id=%d\n",CARD,id)); - break; - } -} - -static -void detach_inform(struct i2c_bus *bus, int id) -{ - struct zoran *ztv = (struct zoran*)bus->data; - - switch (id) { - case I2C_DRIVERID_VIDEODECODER: - ztv->have_decoder = 0; - DEBUG(printk(CARD_INFO "decoder detached\n",CARD)); - break; - case I2C_DRIVERID_TUNER: - ztv->have_tuner = 0; - DEBUG(printk(CARD_INFO "tuner detached\n",CARD)); - break; - default: - DEBUG(printk(CARD_INFO "detach_inform; unknown device id=%d\n",CARD,id)); - break; - } -} - -struct i2c_bus zoran_i2c_bus_template = -{ - "ZR36120", - I2C_BUSID_ZORAN, - NULL, - - SPIN_LOCK_UNLOCKED, - - attach_inform, - detach_inform, - - i2c_setlines, - i2c_getdataline, - NULL, - NULL -}; diff --git a/drivers/char/zr36120_mem.c b/drivers/char/zr36120_mem.c deleted file mode 100644 index b4c6078d3..000000000 --- a/drivers/char/zr36120_mem.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - zr36120_mem.c - Zoran 36120/36125 based framegrabbers - - Copyright (C) 1998-1999 Pauline Middelink - - This program is free software; you can redistribute it and/or modify - it under the terms of the 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 -#include -#include -#include -#include -#include -#ifdef CONFIG_BIGPHYS_AREA -#include -#endif - -#include "zr36120.h" -#include "zr36120_mem.h" - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -void* bmalloc(unsigned long size) -{ - void* mem; -#ifdef CONFIG_BIGPHYS_AREA - mem = bigphysarea_alloc_pages(size/PAGE_SIZE, 1, GFP_KERNEL); -#else - /* - * The following function got a lot of memory at boottime, - * so we know its always there... - */ - mem = (void*)__get_free_pages(GFP_USER|GFP_DMA,get_order(size)); -#endif - if (mem) { - unsigned long adr = (unsigned long)mem; - while (size > 0) { - mem_map_reserve(virt_to_page(phys_to_virt(adr))); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - } - return mem; -} - -void bfree(void* mem, unsigned long size) -{ - if (mem) { - unsigned long adr = (unsigned long)mem; - unsigned long siz = size; - while (siz > 0) { - mem_map_unreserve(virt_to_page(phys_to_virt(adr))); - adr += PAGE_SIZE; - siz -= PAGE_SIZE; - } -#ifdef CONFIG_BIGPHYS_AREA - bigphysarea_free_pages(mem); -#else - free_pages((unsigned long)mem,get_order(size)); -#endif - } -} diff --git a/drivers/char/zr36120_mem.h b/drivers/char/zr36120_mem.h deleted file mode 100644 index aad117acc..000000000 --- a/drivers/char/zr36120_mem.h +++ /dev/null @@ -1,3 +0,0 @@ -/* either kmalloc() or bigphysarea() alloced memory - continuous */ -void* bmalloc(unsigned long size); -void bfree(void* mem, unsigned long size); -- cgit v1.2.3