diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /drivers/char/hfmodem | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'drivers/char/hfmodem')
-rw-r--r-- | drivers/char/hfmodem/Config.in | 6 | ||||
-rw-r--r-- | drivers/char/hfmodem/Makefile | 37 | ||||
-rw-r--r-- | drivers/char/hfmodem/gentbl.c | 69 | ||||
-rw-r--r-- | drivers/char/hfmodem/main.c | 734 | ||||
-rw-r--r-- | drivers/char/hfmodem/modem.c | 792 | ||||
-rw-r--r-- | drivers/char/hfmodem/refclock.c | 154 | ||||
-rw-r--r-- | drivers/char/hfmodem/sbc.c | 741 | ||||
-rw-r--r-- | drivers/char/hfmodem/wss.c | 437 |
8 files changed, 0 insertions, 2970 deletions
diff --git a/drivers/char/hfmodem/Config.in b/drivers/char/hfmodem/Config.in deleted file mode 100644 index 9d2799adb..000000000 --- a/drivers/char/hfmodem/Config.in +++ /dev/null @@ -1,6 +0,0 @@ -comment 'Misc. hamradio protocols' -dep_tristate 'Shortwave radio modem driver' CONFIG_HFMODEM $CONFIG_PARPORT -if [ "$CONFIG_HFMODEM" != "n" ]; then - bool ' HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC - bool ' HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS -fi diff --git a/drivers/char/hfmodem/Makefile b/drivers/char/hfmodem/Makefile deleted file mode 100644 index 2219cd52e..000000000 --- a/drivers/char/hfmodem/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# -# Makefile for the hfmodem device driver. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now inherited from the -# parent makes.. -# - -O_TARGET := hfmodem.o - -O_OBJS := refclock.o modem.o main.o -ifeq ($(CONFIG_HFMODEM_SBC),y) -O_OBJS += sbc.o -endif -ifeq ($(CONFIG_HFMODEM_WSS),y) -O_OBJS += wss.o -endif - -M_OBJS := $(O_TARGET) - -all: all_targets -.PHONY: all - -gentbl: gentbl.c - $(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm - -TBLHDR := tables.h - -tables.h: gentbl - ./gentbl > $@ - -fastdep: $(TBLHDR) - -include $(TOPDIR)/Rules.make diff --git a/drivers/char/hfmodem/gentbl.c b/drivers/char/hfmodem/gentbl.c deleted file mode 100644 index d60651b1b..000000000 --- a/drivers/char/hfmodem/gentbl.c +++ /dev/null @@ -1,69 +0,0 @@ -/*****************************************************************************/ - -/* - * gentbl.c -- Linux soundcard HF FSK driver, - * Table generator. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * - */ - -/*****************************************************************************/ - -/* This is compiled with HOSTCC - do not include any <linux/foo.h> headers. */ -#include <math.h> -#include <stdio.h> - -/* --------------------------------------------------------------------- */ - -#define SINTABBITS 9 -#define SINTABSIZE (1<<SINTABBITS) - -/* --------------------------------------------------------------------- */ - -static void gensintbl(void) -{ - int i; - - printf("#define SINTABBITS %d\n#define SINTABSIZE (1<<SINTABBITS)\n" - "\nstatic short isintab[SINTABSIZE+SINTABSIZE/4] = {\n\t", SINTABBITS); - for (i = 0; i < (SINTABSIZE+SINTABSIZE/4); i++) { - printf("%6d", (int)(32767.0 * sin(2.0 * M_PI / SINTABSIZE * i))); - if (i < (SINTABSIZE+SINTABSIZE/4)-1) { - if ((i & 7) == 7) - printf(",\n\t"); - else - printf(","); - } - } - printf("\n};\n\n"); -} - -/* --------------------------------------------------------------------- */ - -int main(int argc, char *argv[]) -{ - printf("/*\n * This file is automatically generated by %s, DO NOT EDIT!\n*/\n\n", - argv[0]); - gensintbl(); - exit(0); -} - -/* --------------------------------------------------------------------- */ - diff --git a/drivers/char/hfmodem/main.c b/drivers/char/hfmodem/main.c deleted file mode 100644 index a865689c1..000000000 --- a/drivers/char/hfmodem/main.c +++ /dev/null @@ -1,734 +0,0 @@ -/*****************************************************************************/ - -/* - * main.c -- Linux soundcard HF FSK driver. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the 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. - * - * Command line options (insmod command line) - * - * History: - * 0.1 15.04.97 Adapted from baycom.c and made network driver interface - * 0.2 05.07.97 All floating point stuff thrown out due to Linus' rantings :) - * - */ - -/*****************************************************************************/ - - -#include <linux/config.h> /* for CONFIG_HFMODEM_WSS and CONFIG_HFMODEM_SBC */ -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/malloc.h> -#include <linux/errno.h> -#include <linux/miscdevice.h> -#include <linux/ioport.h> -#include <linux/hfmodem.h> - -#include <asm/io.h> -#include <asm/segment.h> -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/dma.h> - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include <linux/version.h> - -#if LINUX_VERSION_CODE >= 0x20100 -#include <asm/uaccess.h> -#else -#include <linux/mm.h> - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include <linux/init.h> -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - -/*static*/ const char hfmodem_drvname[] = "hfmodem"; -static const char hfmodem_drvinfo[] = KERN_INFO "hfmodem: (C) 1997 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "hfmodem: version 0.2 compiled " __TIME__ " " __DATE__ "\n"; - -/* --------------------------------------------------------------------- */ -/* - * currently we support only one device - */ - -struct hfmodem_state hfmodem_state[NR_DEVICE]; - -/* --------------------------------------------------------------------- */ -/* - * ===================== port checking routines ======================== - */ - - -#define UART_RBR(iobase) (iobase+0) -#define UART_THR(iobase) (iobase+0) -#define UART_IER(iobase) (iobase+1) -#define UART_IIR(iobase) (iobase+2) -#define UART_FCR(iobase) (iobase+2) -#define UART_LCR(iobase) (iobase+3) -#define UART_MCR(iobase) (iobase+4) -#define UART_LSR(iobase) (iobase+5) -#define UART_MSR(iobase) (iobase+6) -#define UART_SCR(iobase) (iobase+7) -#define UART_DLL(iobase) (iobase+0) -#define UART_DLM(iobase) (iobase+1) - -#define SER_EXTENT 8 - -#define LPT_DATA(iobase) (iobase+0) -#define LPT_STATUS(iobase) (iobase+1) -#define LPT_CONTROL(iobase) (iobase+2) -#define LPT_IRQ_ENABLE 0x10 - -#define MIDI_DATA(iobase) (iobase) -#define MIDI_STATUS(iobase) (iobase+1) -#define MIDI_READ_FULL 0x80 /* attention: negative logic!! */ -#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */ - -#define MIDI_EXTENT 2 - -#define SP_SER 1 -#define SP_PAR 2 -#define SP_MIDI 4 - -/* --------------------------------------------------------------------- */ - -static void parptt_wakeup(void *handle) -{ - struct hfmodem_state *dev = (struct hfmodem_state *)handle; - - printk(KERN_DEBUG "%s: parptt: why am I being woken up?\n", hfmodem_drvname); - if (!parport_claim(dev->ptt_out.pardev)) - printk(KERN_DEBUG "%s: parptt: I'm broken.\n", hfmodem_drvname); -} - -/* --------------------------------------------------------------------- */ -static int __init check_lpt(struct hfmodem_state *dev, unsigned int iobase) -{ - struct parport *pp = parport_enumerate(); - - while (pp && pp->base != iobase) - pp = pp->next; - if (!pp) - return 0; - if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, NULL, parptt_wakeup, - NULL, PARPORT_DEV_EXCL, dev))) - return 0; - return 1; -} - -/* --------------------------------------------------------------------- */ - -enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A }; -static const char *uart_str[] __initdata = { "unknown", "8250", "16450", "16550", "16550A" }; - -static enum uart __init check_uart(unsigned int iobase) -{ - unsigned char b1,b2,b3; - enum uart u; - enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A }; - - if (iobase <= 0 || iobase > 0x1000-SER_EXTENT) - return c_uart_unknown; - if (check_region(iobase, SER_EXTENT)) - return c_uart_unknown; - b1 = inb(UART_MCR(iobase)); - outb(b1 | 0x10, UART_MCR(iobase)); /* loopback mode */ - b2 = inb(UART_MSR(iobase)); - outb(0x1a, UART_MCR(iobase)); - b3 = inb(UART_MSR(iobase)) & 0xf0; - outb(b1, UART_MCR(iobase)); /* restore old values */ - outb(b2, UART_MSR(iobase)); - if (b3 != 0x90) - return c_uart_unknown; - inb(UART_RBR(iobase)); - inb(UART_RBR(iobase)); - outb(0x01, UART_FCR(iobase)); /* enable FIFOs */ - u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3]; - if (u == c_uart_16450) { - outb(0x5a, UART_SCR(iobase)); - b1 = inb(UART_SCR(iobase)); - outb(0xa5, UART_SCR(iobase)); - b2 = inb(UART_SCR(iobase)); - if ((b1 != 0x5a) || (b2 != 0xa5)) - u = c_uart_8250; - } - return u; -} - -/* --------------------------------------------------------------------- */ - -static int __init check_midi(unsigned int iobase) -{ - unsigned long timeout; - unsigned long flags; - unsigned char b; - - if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT) - return 0; - if (check_region(iobase, MIDI_EXTENT)) - return 0; - timeout = jiffies + (HZ / 100); - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - save_flags(flags); - cli(); - outb(0xff, MIDI_DATA(iobase)); - b = inb(MIDI_STATUS(iobase)); - restore_flags(flags); - if (!(b & MIDI_WRITE_EMPTY)) - return 0; - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - return 1; -} - -/* --------------------------------------------------------------------- */ - -static void output_status(struct hfmodem_state *dev, int ptt) -{ - int dcd = 0; - - ptt = !!ptt; - if (dev->ptt_out.flags & SP_SER) { - outb(dcd | (ptt << 1), UART_MCR(dev->ptt_out.seriobase)); - outb(0x40 & (-ptt), UART_LCR(dev->ptt_out.seriobase)); - } - if (dev->ptt_out.flags & SP_PAR) { - outb(ptt | (dcd << 1), LPT_DATA(dev->ptt_out.pariobase)); - } - if (dev->ptt_out.flags & SP_MIDI && ptt) { - outb(0, MIDI_DATA(dev->ptt_out.midiiobase)); - } -} - -/* --------------------------------------------------------------------- */ - -static void __init output_check(struct hfmodem_state *dev) -{ - enum uart u = c_uart_unknown; - - if (((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown) - printk(KERN_INFO "%s: PTT output: uart found at address 0x%x type %s\n", - hfmodem_drvname, dev->ptt_out.seriobase, uart_str[u]); - else { - if (dev->ptt_out.seriobase > 0) - printk(KERN_WARNING "%s: PTT output: no uart found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.seriobase); - dev->ptt_out.seriobase = 0; - } - if (check_lpt(dev, dev->ptt_out.pariobase)) - printk(KERN_INFO "%s: PTT output: parallel port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.pariobase); - else { - if (dev->ptt_out.pariobase > 0) - printk(KERN_WARNING "%s: PTT output: no parallel port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.pariobase); - dev->ptt_out.pariobase = 0; - dev->ptt_out.pardev = NULL; - } - if (dev->ptt_out.midiiobase > 0 && dev->ptt_out.midiiobase <= 0x1000-MIDI_EXTENT && - check_midi(dev->ptt_out.midiiobase)) - printk(KERN_INFO "%s: PTT output: midi port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.midiiobase); - else { - if (dev->ptt_out.midiiobase > 0) - printk(KERN_WARNING "%s: PTT output: no midi port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.midiiobase); - dev->ptt_out.midiiobase = 0; - } -} - -/* --------------------------------------------------------------------- */ - -static void output_open(struct hfmodem_state *dev) -{ - dev->ptt_out.flags = 0; - if (dev->ptt_out.seriobase > 0) { - if (!check_region(dev->ptt_out.seriobase, SER_EXTENT)) { - request_region(dev->ptt_out.seriobase, SER_EXTENT, "hfmodem ser ptt"); - dev->ptt_out.flags |= SP_SER; - outb(0, UART_IER(dev->ptt_out.seriobase)); - /* 5 bits, 1 stop, no parity, no break, Div latch access */ - outb(0x80, UART_LCR(dev->ptt_out.seriobase)); - outb(0, UART_DLM(dev->ptt_out.seriobase)); - outb(1, UART_DLL(dev->ptt_out.seriobase)); /* as fast as possible */ - /* LCR and MCR set by output_status */ - } else - printk(KERN_WARNING "%s: PTT output: serial port at 0x%x busy\n", - hfmodem_drvname, dev->ptt_out.seriobase); - } - if (dev->ptt_out.pariobase > 0) { - if (parport_claim(dev->ptt_out.pardev)) - printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n", - hfmodem_drvname, dev->ptt_out.pariobase); - else - dev->ptt_out.flags |= SP_PAR; - } - if (dev->ptt_out.midiiobase > 0) { - if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) { - request_region(dev->ptt_out.midiiobase, MIDI_EXTENT, "hfmodem midi ptt"); - dev->ptt_out.flags |= SP_MIDI; - } else - printk(KERN_WARNING "%s: PTT output: midi port at 0x%x busy\n", - hfmodem_drvname, dev->ptt_out.midiiobase); - } - output_status(dev, 0); - printk(KERN_INFO "%s: PTT output:", hfmodem_drvname); - if (dev->ptt_out.flags & SP_SER) - printk(" serial interface at 0x%x", dev->ptt_out.seriobase); - if (dev->ptt_out.flags & SP_PAR) - printk(" parallel interface at 0x%x", dev->ptt_out.pariobase); - if (dev->ptt_out.flags & SP_MIDI) - printk(" mpu401 (midi) interface at 0x%x", dev->ptt_out.midiiobase); - if (!dev->ptt_out.flags) - printk(" none"); - printk("\n"); -} - -/* --------------------------------------------------------------------- */ - -static void output_close(struct hfmodem_state *dev) -{ - /* release regions used for PTT output */ - output_status(dev, 0); - if (dev->ptt_out.flags & SP_SER) - release_region(dev->ptt_out.seriobase, SER_EXTENT); - if (dev->ptt_out.flags & SP_PAR) - parport_release(dev->ptt_out.pardev); - if (dev->ptt_out.flags & SP_MIDI) - release_region(dev->ptt_out.midiiobase, MIDI_EXTENT); - dev->ptt_out.flags = 0; -} - -/* --------------------------------------------------------------------- */ - -#define INC_SAMPLE (1000000/HFMODEM_SRATE) -#define INC_FRAGMENT (HFMODEM_FRAGSAMPLES*1000000/HFMODEM_SRATE) -#define SIZE (HFMODEM_FRAGSAMPLES*HFMODEM_NUMFRAGS) - -static void hfmodem_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct hfmodem_state *dev = (struct hfmodem_state *)dev_id; - unsigned int dmaptr; - __s16 *s; - unsigned int curfrag, nfrags; - int i; - hfmodem_time_t l1time; - - dmaptr = dev->scops->intack(dev); - l1time = hfmodem_refclock_current(dev, ((SIZE+dmaptr-dev->dma.last_dmaptr) % SIZE) * - INC_SAMPLE, 1); - curfrag = (dev->dma.last_dmaptr = dmaptr) / HFMODEM_FRAGSAMPLES; - l1time -= INC_SAMPLE * (SIZE+dmaptr-dev->dma.fragptr*HFMODEM_FRAGSAMPLES) % SIZE; - sti(); - /* - * handle receiving - */ - if (dev->dma.ptt_frames <= 0) { - while (dev->dma.fragptr != curfrag) { - if (dev->dma.fragptr < HFMODEM_EXCESSFRAGS) { - s = dev->dma.buf + SIZE + HFMODEM_FRAGSAMPLES * dev->dma.fragptr; - memcpy(s, s - SIZE, HFMODEM_FRAGSIZE); - } else - s = dev->dma.buf + HFMODEM_FRAGSAMPLES * dev->dma.fragptr; - if (dev->sbuf.kbuf && dev->sbuf.kptr && dev->sbuf.rem > 0) { - i = HFMODEM_FRAGSAMPLES; - if (i > dev->sbuf.rem) - i = dev->sbuf.rem; - memcpy(dev->sbuf.kptr, s, i * sizeof(s[0])); - dev->sbuf.rem -= i; - dev->sbuf.kptr += i; - } - hfmodem_input_samples(dev, l1time, INC_SAMPLE, s); - l1time += INC_FRAGMENT; - dev->dma.fragptr++; - if (dev->dma.fragptr >= HFMODEM_NUMFRAGS) - dev->dma.fragptr = 0; - } - /* - * check for output - */ - if (hfmodem_next_tx_event(dev, l1time) > (long)INC_FRAGMENT/2) - goto int_return; - /* - * start output - */ - output_status(dev, 1); - dev->scops->prepare_output(dev); - dev->dma.last_dmaptr = 0; - /* - * clock adjust - */ - l1time = hfmodem_refclock_current(dev, 0, 0); - /* - * fill first two fragments - */ - dev->dma.ptt_frames = 1; - for (i = 0; i < 2 && i < HFMODEM_NUMFRAGS; i++) - if (hfmodem_output_samples(dev, l1time+i*INC_FRAGMENT, INC_SAMPLE, - dev->dma.buf+i*HFMODEM_FRAGSAMPLES)) - dev->dma.ptt_frames = i + 1; - dev->dma.lastfrag = 0; - dev->scops->trigger_output(dev); - /* - * finish already pending rx requests - */ - hfmodem_finish_pending_rx_requests(dev); - goto int_return; - } - /* - * handle transmitting - */ - nfrags = HFMODEM_NUMFRAGS + curfrag - dev->dma.lastfrag; - dev->dma.lastfrag = curfrag; - if (nfrags >= HFMODEM_NUMFRAGS) - nfrags -= HFMODEM_NUMFRAGS; - dev->dma.ptt_frames -= nfrags; - if (dev->dma.ptt_frames < 0) - dev->dma.ptt_frames = 0; - while (dev->dma.ptt_frames < HFMODEM_NUMFRAGS && dev->dma.ptt_frames < 4 && - hfmodem_output_samples(dev, l1time+dev->dma.ptt_frames*INC_FRAGMENT, - INC_SAMPLE, dev->dma.buf + HFMODEM_FRAGSAMPLES * - ((curfrag + dev->dma.ptt_frames) % HFMODEM_NUMFRAGS))) - dev->dma.ptt_frames++; - if (dev->dma.ptt_frames > 0) - goto int_return; - /* - * start receiving - */ - output_status(dev, 0); - dev->dma.last_dmaptr = 0; - dev->dma.lastfrag = 0; - dev->dma.fragptr = 0; - dev->dma.ptt_frames = 0; - dev->scops->prepare_input(dev); - dev->scops->trigger_input(dev); - hfmodem_refclock_current(dev, 0, 0); /* needed to reset the time difference */ -int_return: - hfmodem_wakeup(dev); -} - -/* --------------------------------------------------------------------- */ - -static int hfmodem_close(struct inode *inode, struct file *file) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - - if (!dev->active) - return -EPERM; - dev->active = 0; - dev->scops->stop(dev); - free_irq(dev->io.irq, dev); - disable_dma(dev->io.dma); - free_dma(dev->io.dma); - release_region(dev->io.base_addr, dev->scops->extent); - kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS)); - hfmodem_clear_rq(dev); - if (dev->sbuf.kbuf) { - kfree_s(dev->sbuf.kbuf, dev->sbuf.size); - dev->sbuf.kbuf = dev->sbuf.kptr = NULL; - dev->sbuf.size = dev->sbuf.rem = 0; - } - output_close(dev); - MOD_DEC_USE_COUNT; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int hfmodem_open(struct inode *inode, struct file *file) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - - if (dev->active) - return -EBUSY; - if (!dev->scops) - return -EPERM; - /* - * clear vars - */ - memset(&dev->l1, 0, sizeof(dev->l1)); - dev->dma.last_dmaptr = 0; - dev->dma.lastfrag = 0; - dev->dma.fragptr = 0; - dev->dma.ptt_frames = 0; - /* - * allocate memory - */ - if (!(dev->dma.buf = kmalloc(HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS), GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - /* - * allocate resources - */ - if (request_dma(dev->io.dma, hfmodem_drvname)) { - kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS)); - return -EBUSY; - } - if (request_irq(dev->io.irq, hfmodem_interrupt, SA_INTERRUPT, hfmodem_drvname, dev)) { - free_dma(dev->io.dma); - kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS)); - return -EBUSY; - } - request_region(dev->io.base_addr, dev->scops->extent, hfmodem_drvname); - - /* clear requests */ - dev->active++; - MOD_INC_USE_COUNT; - hfmodem_refclock_init(dev); - output_open(dev); - dev->scops->init(dev); - dev->scops->prepare_input(dev); - dev->scops->trigger_input(dev); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static struct file_operations hfmodem_fops = { - NULL, /* hfmodem_seek */ - NULL, /* hfmodem_read */ - NULL, /* hfmodem_write */ - NULL, /* hfmodem_readdir */ -#if LINUX_VERSION_CODE >= 0x20100 - hfmodem_poll, /* hfmodem_poll */ -#else - hfmodem_select, /* hfmodem_select */ -#endif - hfmodem_ioctl, /* hfmodem_ioctl */ - NULL, /* hfmodem_mmap */ - hfmodem_open, /* hfmodem_open */ - NULL, /* flush */ - hfmodem_close, /* hfmodem_close */ - NULL, /* hfmodem_fsync */ - NULL, /* hfmodem_fasync */ - NULL, /* hfmodem_check_media_change */ - NULL /* hfmodem_revalidate */ -}; - -/* --------------------------------------------------------------------- */ - -static struct miscdevice hfmodem_device = { - HFMODEM_MINOR, hfmodem_drvname, &hfmodem_fops -}; - -/* --------------------------------------------------------------------- */ - -#ifdef MODULE - -/* - * Command line parameters - */ - -static int hw = 0; -static unsigned int iobase = 0x220; -static unsigned int irq = 7; -static unsigned int dma = 1; - -static unsigned int serio = 0; -static unsigned int pario = 0; -static unsigned int midiio = 0; - -#if LINUX_VERSION_CODE >= 0x20115 - -MODULE_PARM(hw, "i"); -MODULE_PARM_DESC(hw, "hardware type: 0=SBC, 1=WSS"); -MODULE_PARM(iobase, "i"); -MODULE_PARM_DESC(iobase, "io base address"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(irq, "interrupt number"); -MODULE_PARM(dma, "i"); -MODULE_PARM_DESC(dma, "dma number (>=4 for SB16/32/64/etc, <=3 for the rest)"); -MODULE_PARM(serio, "i"); -MODULE_PARM_DESC(serio, "address of serial port to output PTT"); -MODULE_PARM(pario, "i"); -MODULE_PARM_DESC(pario, "address of parallel port to output PTT"); -MODULE_PARM(midiio, "i"); -MODULE_PARM_DESC(midiio, "address of midi (MPU401) port to output PTT"); - -MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); -MODULE_DESCRIPTION("HF FSK modem code"); - -/* these are the module parameters from refclock.c */ - -MODULE_PARM(scale_tvusec, "i"); -MODULE_PARM_DESC(scale_tvusec, "Scaling value for the tv_usec field (can be obta -ined by refclock)"); - -#ifdef __i386__ -MODULE_PARM(scale_rdtsc, "i"); -MODULE_PARM_DESC(scale_rdtsc, "Scaling value for the rdtsc counter (can be obtai -ned by refclock)"); -MODULE_PARM(rdtsc_ok, "i"); -MODULE_PARM_DESC(rdtsc_ok, "Set to 0 to disable the use of the rdtsc instruction -"); -#endif /* __i386__ */ - -#endif - -int __init init_module(void) -{ - int i; - - printk(hfmodem_drvinfo); - memset(hfmodem_state, 0, sizeof(hfmodem_state)); - memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache)); - hfmodem_state[0].io.base_addr = iobase; - hfmodem_state[0].io.irq = irq; - hfmodem_state[0].io.dma = dma; - hfmodem_state[0].ptt_out.seriobase = serio; - hfmodem_state[0].ptt_out.pariobase = pario; - hfmodem_state[0].ptt_out.midiiobase = midiio; - init_waitqueue_head(&hfmodem_state[0].wait); - hfmodem_refclock_probe(); - output_check(&hfmodem_state[0]); -#if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC) - if (hw) - i = hfmodem_wssprobe(&hfmodem_state[0]); - else - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#else - i = -EINVAL; -#ifdef CONFIG_HFMODEM_WSS - i = hfmodem_wssprobe(&hfmodem_state[0]); -#endif -#ifdef CONFIG_HFMODEM_SBC - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#endif -#endif - if (i) - return i; - if ((i = misc_register(&hfmodem_device))) { - printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname); - return i; - } - return 0; -} - -void cleanup_module(void) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - - if (dev->ptt_out.pariobase > 0) - parport_unregister_device(dev->ptt_out.pardev); - misc_deregister(&hfmodem_device); -} - -#else /* MODULE */ -/* --------------------------------------------------------------------- */ - -static int hw = 0; - -void __init hfmodem_setup(char *str, int *ints) -{ - if (ints[0] < 7) { - printk(KERN_WARNING "%s: setup: too few parameters\n", hfmodem_drvname); - return; - } - memset(hfmodem_state, 0, sizeof(hfmodem_state)); - memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache)); - hw = ints[1]; - hfmodem_state[0].io.base_addr = ints[2]; - hfmodem_state[0].io.irq = ints[3]; - hfmodem_state[0].io.dma = ints[4]; - if (ints[0] >= 8) - hfmodem_state[0].ptt_out.seriobase = ints[5]; - if (ints[0] >= 9) - hfmodem_state[0].ptt_out.pariobase = ints[6]; - if (ints[0] >= 10) - hfmodem_state[0].ptt_out.midiiobase = ints[7]; - hfmodem_refclock_setscale(ints[ints[0]-2], ints[ints[0]-1], ints[ints[0]]); -} - -void __init hfmodem_init(void) -{ - int i; - - printk(hfmodem_drvinfo); - init_waitqueue_head(&hfmode_state[0].wait); - hfmodem_refclock_probe(); - output_check(&hfmodem_state[0]); -#if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC) - if (hw) - i = hfmodem_wssprobe(&hfmodem_state[0]); - else - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#else - i = -EINVAL; -#ifdef CONFIG_HFMODEM_WSS - i = hfmodem_wssprobe(&hfmodem_state[0]); -#endif -#ifdef CONFIG_HFMODEM_SBC - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#endif -#endif - if (i) { - printk(KERN_ERR "%s: soundcard probe failed\n", hfmodem_drvname); - return; - } - if ((i = misc_register(&hfmodem_device))) { - printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname); - return; - } -} - -/* --------------------------------------------------------------------- */ -#endif /* MODULE */ diff --git a/drivers/char/hfmodem/modem.c b/drivers/char/hfmodem/modem.c deleted file mode 100644 index 02dcad5cc..000000000 --- a/drivers/char/hfmodem/modem.c +++ /dev/null @@ -1,792 +0,0 @@ -/*****************************************************************************/ - -/* - * modem.c -- Linux soundcard HF FSK driver, - * Modem code. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - - -#include <linux/wait.h> -#include <linux/malloc.h> -#include <linux/hfmodem.h> - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include <linux/version.h> - -#if LINUX_VERSION_CODE >= 0x20100 -#include <asm/uaccess.h> -#else -#include <asm/segment.h> -#include <linux/mm.h> - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include <linux/init.h> -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - -struct hfmodem_correlator_cache hfmodem_correlator_cache[HFMODEM_CORRELATOR_CACHE]; - -/* --------------------------------------------------------------------- */ - -#include "tables.h" - -#define M_PI 3.14159265358979323846 /* pi */ - -/* --------------------------------------------------------------------- */ - -extern __inline__ int isimplecos(unsigned int arg) -{ - return isintab[((arg+0x4000) >> (16-SINTABBITS)) & (SINTABSIZE-1)]; -} - -extern __inline__ int isimplesin(unsigned int arg) -{ - return isintab[(arg >> (16-SINTABBITS)) & (SINTABSIZE-1)]; -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ int itblcos(unsigned int arg) -{ - unsigned int x; - int dx; - int s, c; - - x = (arg + (0x8000 >> SINTABBITS)) & (0xffffu & (0xffffu << (16-SINTABBITS))); - dx = arg - x; - x >>= (16-SINTABBITS); - c = isintab[x+(0x4000 >> (16-SINTABBITS))]; - s = isintab[x]; - return c - ((s * dx * (int)(M_PI*64.0)) >> 21); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void itblcossin(unsigned int arg, int *cos, int *sin) -{ - unsigned int x; - int dx; - int s, c; - - x = (arg + (0x8000 >> SINTABBITS)) & (0xffffu & (0xffffu << (16-SINTABBITS))); - dx = arg - x; - x >>= (16-SINTABBITS); - c = isintab[x+(0x4000 >> (16-SINTABBITS))]; - s = isintab[x]; - *cos = c - ((s * dx * (int)(M_PI*64.0)) >> 21); - *sin = s + ((c * dx * (int)(M_PI*64.0)) >> 21); -} - -/* --------------------------------------------------------------------- */ - -static unsigned short random_seed; - -extern __inline__ unsigned short random_num(void) -{ - random_seed = 28629 * random_seed + 157; - return random_seed; -} - -/* --------------------------------------------------------------------- */ -/* - * correlator cache routines - */ - -extern __inline__ void cc_lock(unsigned int u) -{ - if (u >= HFMODEM_CORRELATOR_CACHE) - return; - hfmodem_correlator_cache[u].refcnt++; -} - -extern __inline__ void cc_unlock(unsigned int u) -{ - if (u >= HFMODEM_CORRELATOR_CACHE) - return; - if ((--hfmodem_correlator_cache[u].refcnt) <= 0) { - unsigned int i; - - for (i = 0; i < HFMODEM_CORRELATOR_CACHE; i++) - if (hfmodem_correlator_cache[i].lru < 32767) - hfmodem_correlator_cache[i].lru++; - hfmodem_correlator_cache[u].lru = 0; - hfmodem_correlator_cache[u].refcnt = 0; - } -} - - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int cc_lookup(unsigned short phinc0, unsigned short phinc1) -{ - unsigned int j; - - /* find correlator cache entry */ - for (j = 0; j < HFMODEM_CORRELATOR_CACHE; j++) - if (hfmodem_correlator_cache[j].phase_incs[0] == phinc0 && - hfmodem_correlator_cache[j].phase_incs[1] == phinc1) - return j; - return ~0; -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int cc_replace(void) -{ - unsigned int j, k = HFMODEM_CORRELATOR_CACHE; - int l = -1; - - for (j = 0; j < HFMODEM_CORRELATOR_CACHE; j++) - if (hfmodem_correlator_cache[j].refcnt <= 0 && hfmodem_correlator_cache[j].lru > l) { - k = j; - l = hfmodem_correlator_cache[j].lru; - } - if (k < HFMODEM_CORRELATOR_CACHE) - return k; - printk(KERN_ERR "%s: modem: out of filter coefficient cache entries\n", hfmodem_drvname); - return random_num() % HFMODEM_CORRELATOR_CACHE; -} - -/* --------------------------------------------------------------------- */ - -#define SH1 8 /* min. ceil(log2(L1CORR_LEN)) - (31-(2*15-1)) */ -#define SH2 (3*15-2*SH1) - -#ifdef __i386__ - -extern __inline__ int icorr(int n, const int *coeff, const short *inp) -{ - int ret, rethi, tmp1 = 0, tmp2 = 0; - - __asm__("\n1:\n\t" - "movswl (%0),%%eax\n\t" - "imull (%1)\n\t" - "subl $2,%0\n\t" - "addl $4,%1\n\t" - "addl %%eax,%3\n\t" - "adcl %%edx,%4\n\t" - "decl %2\n\t" - "jne 1b\n\t" - : "=&S" (inp), "=&D" (coeff), "=&c" (n), "=m" (tmp1), "=m" (tmp2) - : "0" (inp), "1" (coeff), "2" (n) - : "ax", "dx"); - __asm__("shrdl %2,%1,%0\n\t" - "# sarl %2,%1\n\t" - : "=&r" (ret), "=&r" (rethi) - : "i" (SH1), "0" (tmp1), "1" (tmp2)); - - - return ret; -} - -#else /* __i386__ */ - -extern __inline__ int icorr(int n, const int *coeff, const short *inp) -{ - long long sum = 0; - int i; - - for (i = n; i > 0; i--, coeff++, inp--) - sum += (*coeff) * (*inp); - sum >>= SH1; - return sum; -} - -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -extern __inline__ long long isqr(int x) __attribute__ ((const)); - -extern __inline__ long long isqr(int x) -{ - return ((long long)x) * ((long long)x); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ hfmodem_soft_t do_filter(struct hfmodem_l1_rxslot *slot, short *s) -{ - unsigned int cc = slot->corr_cache; - long long ll; - - if (cc >= HFMODEM_CORRELATOR_CACHE) { - printk(KERN_ERR "do_filter: correlator cache index overrange\n"); - return 0; - } - ll = isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[1][0], s)) + - isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[1][1], s)) - - isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[0][0], s)) - - isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[0][1], s)); - ll >>= SH2; - return (ll * slot->scale) >> 23; -} - -/* --------------------------------------------------------------------- */ - -static void cc_prepare(struct hfmodem_l1_rxslot *slot, unsigned short phinc0, unsigned short phinc1) -{ - unsigned int j, k, l, ph, phinc; - - slot->scale = (1<<23) / (slot->corrlen*slot->corrlen); - - j = cc_lookup(phinc0, phinc1); - if (j >= HFMODEM_CORRELATOR_CACHE) { - j = cc_replace(); - /* calculate the correlator values */ - printk(KERN_DEBUG "%s: corr cache calc: %u phases: 0x%04x 0x%04x\n", - hfmodem_drvname, j, phinc0, phinc1); - hfmodem_correlator_cache[j].phase_incs[0] = phinc0; - hfmodem_correlator_cache[j].phase_incs[1] = phinc1; - for (k = 0; k < 2; k++) { - phinc = hfmodem_correlator_cache[j].phase_incs[k]; - for (ph = l = 0; l < HFMODEM_MAXCORRLEN; l++, ph = (ph + phinc) & 0xffff) - itblcossin(ph, &hfmodem_correlator_cache[j].correlator[k][0][l], - &hfmodem_correlator_cache[j].correlator[k][1][l]); - } - hfmodem_correlator_cache[j].refcnt = 0; - -#if 0 - printk(KERN_DEBUG "%s: corr: %u ph: 0x%04x 0x%04x\n", hfmodem_drvname, j, - hfmodem_correlator_cache[j].phase_incs[0], - hfmodem_correlator_cache[j].phase_incs[1]); - for (l = 0; l < HFMODEM_MAXCORRLEN; l++) - printk(KERN_DEBUG "%s: corr: %6d %6d %6d %6d\n", hfmodem_drvname, - hfmodem_correlator_cache[j].correlator[0][0][l], - hfmodem_correlator_cache[j].correlator[0][1][l], - hfmodem_correlator_cache[j].correlator[1][0][l], - hfmodem_correlator_cache[j].correlator[1][1][l]); -#endif - } - slot->corr_cache = j; - cc_lock(j); -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_clear_rq(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned int i; - - save_flags(flags); - cli(); - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_unused) - continue; - dev->l1.rxslots[i].state = ss_unused; - kfree_s(dev->l1.rxslots[i].data, dev->l1.rxslots[i].nbits * sizeof(hfmodem_soft_t)); - } - for (i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_unused) - continue; - dev->l1.txslots[i].state = ss_unused; - kfree_s(dev->l1.txslots[i].data, (dev->l1.txslots[i].nbits + 7) >> 3); - } - for (i = 0; i < HFMODEM_CORRELATOR_CACHE; i++) - hfmodem_correlator_cache[i].refcnt = 0; - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - struct hfmodem_ioctl_fsk_tx_request txrq; - struct hfmodem_ioctl_fsk_rx_request rxrq; - struct hfmodem_ioctl_mixer_params mix; - struct hfmodem_ioctl_sample_params spar; - unsigned long flags; - unsigned int len; - int ret, i, idx; - void *data, *userdata; - hfmodem_id_t id; - hfmodem_time_t tm = 0; - - if (!dev->active) - return -EBUSY; - switch(cmd) { - default: - return -EINVAL; - - case HFMODEM_IOCTL_FSKTXREQUEST: - if ((ret = copy_from_user(&txrq, (void *)arg, sizeof(txrq)))) - return ret; - if (txrq.nbits > HFMODEM_MAXBITS) - return -EINVAL; - len = (txrq.nbits + 7) >> 3; - if (!(data = kmalloc(len, GFP_KERNEL))) - return -ENOMEM; - if (copy_from_user(data, txrq.data, len)) { - kfree_s(data, len); - return -EFAULT; - } - save_flags(flags); - cli(); - for (i = 0; i < HFMODEM_NUMTXSLOTS && dev->l1.txslots[i].state != ss_unused; i++); - if (i >= HFMODEM_NUMTXSLOTS) { - restore_flags(flags); - kfree_s(data, len); - return -EBUSY; - } - dev->l1.txslots[i].state = ss_ready; - dev->l1.txslots[i].tstart = txrq.tstart; - dev->l1.txslots[i].tinc = txrq.tinc; - dev->l1.txslots[i].data = data; - dev->l1.txslots[i].nbits = txrq.nbits; - dev->l1.txslots[i].cntbits = 0; - dev->l1.txslots[i].inv = txrq.inv ? 0xff : 0; - dev->l1.txslots[i].id = txrq.id; - dev->l1.txslots[i].phase_incs[0] = ((txrq.freq[0]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) - & 0xffff; - dev->l1.txslots[i].phase_incs[1] = ((txrq.freq[1]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) - & 0xffff; - restore_flags(flags); - return 0; - - case HFMODEM_IOCTL_FSKRXREQUEST: - if ((ret = copy_from_user(&rxrq, (void *)arg, sizeof(rxrq)))) - return ret; - if (rxrq.nbits > HFMODEM_MAXBITS) - return -EINVAL; - if (rxrq.baud < HFMODEM_MINBAUD || rxrq.baud > HFMODEM_MAXBAUD) - return -EINVAL; - len = rxrq.nbits * sizeof(hfmodem_soft_t); - if (verify_area(VERIFY_WRITE, rxrq.data, len)) - return -EFAULT; - if (!(data = kmalloc(len, GFP_KERNEL))) - return -ENOMEM; - save_flags(flags); - cli(); - for (i = 0; i < HFMODEM_NUMRXSLOTS && dev->l1.rxslots[i].state != ss_unused; i++); - if (i >= HFMODEM_NUMRXSLOTS) { - restore_flags(flags); - kfree_s(data, len); - return -EBUSY; - } - dev->l1.rxslots[i].state = ss_ready; - dev->l1.rxslots[i].tstart = rxrq.tstart; - dev->l1.rxslots[i].tinc = rxrq.tinc; - dev->l1.rxslots[i].data = data; - dev->l1.rxslots[i].userdata = rxrq.data; - dev->l1.rxslots[i].nbits = rxrq.nbits; - dev->l1.rxslots[i].cntbits = 0; - dev->l1.rxslots[i].id = rxrq.id; - dev->l1.rxslots[i].corrlen = HFMODEM_SRATE/rxrq.baud; - cc_prepare(dev->l1.rxslots+i, - ((rxrq.freq[0]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) & 0xffff, - ((rxrq.freq[1]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) & 0xffff); - restore_flags(flags); - return 0; - - case HFMODEM_IOCTL_CLEARRQ: - hfmodem_clear_rq(dev); - return 0; - - case HFMODEM_IOCTL_GETCURTIME: - return put_user(dev->l1.last_time + 20000L, (hfmodem_time_t *)arg); /* heuristic */ - - case HFMODEM_IOCTL_WAITRQ: - save_flags(flags); - cli(); - ret = 0; - for (idx = -1, i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_unused) - continue; - if (dev->l1.rxslots[i].state != ss_retired) { - ret++; - continue; - } - if (idx < 0 || (signed)(tm - dev->l1.rxslots[i].tstart) > 0) { - idx = i; - tm = dev->l1.rxslots[i].tstart; - } - } - if (idx >= 0) { - cc_unlock(dev->l1.rxslots[idx].corr_cache); - id = dev->l1.rxslots[idx].id; - data = dev->l1.rxslots[idx].data; - userdata = dev->l1.rxslots[idx].userdata; - len = dev->l1.rxslots[idx].nbits * sizeof(hfmodem_soft_t); - dev->l1.rxslots[idx].state = ss_unused; - restore_flags(flags); - ret = copy_to_user(userdata, data, len); - kfree_s(data, len); - return (put_user(id, (hfmodem_id_t *)arg)) ? -EFAULT : ret; - } - for (idx = -1, i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_unused) - continue; - if (dev->l1.txslots[i].state != ss_retired) { - ret++; - continue; - } - if (idx < 0 || (signed)(tm - dev->l1.txslots[i].tstart) > 0) { - idx = i; - tm = dev->l1.txslots[i].tstart; - } - } - if (idx >= 0) { - id = dev->l1.txslots[idx].id; - data = dev->l1.txslots[idx].data; - len = (dev->l1.txslots[idx].nbits + 7) >> 3; - dev->l1.txslots[idx].state = ss_unused; - restore_flags(flags); - kfree_s(data, len); - return put_user(id, (hfmodem_id_t *)arg); - } - restore_flags(flags); - return ret ? -EAGAIN : -EPIPE; - - case HFMODEM_IOCTL_MIXERPARAMS: - if ((ret = copy_from_user(&mix, (void *)arg, sizeof(mix)))) - return ret; - dev->scops->mixer(dev, mix.src, mix.igain, mix.ogain); - return 0; - - case HFMODEM_IOCTL_SAMPLESTART: - save_flags(flags); - cli(); - if (dev->sbuf.kbuf) - kfree_s(dev->sbuf.kbuf, dev->sbuf.size); - dev->sbuf.kbuf = dev->sbuf.kptr = NULL; - dev->sbuf.size = dev->sbuf.rem = 0; - restore_flags(flags); - if ((ret = copy_from_user(&spar, (void *)arg, sizeof(spar)))) - return ret; - if (spar.len == 0) - return 0; - if (spar.len < 2 || spar.len > 8192) - return -EINVAL; - if (verify_area(VERIFY_WRITE, spar.data, spar.len * sizeof(__s16))) - return -EFAULT; - if (!(dev->sbuf.kbuf = kmalloc(spar.len * sizeof(__s16), GFP_KERNEL))) - return -ENOMEM; - save_flags(flags); - cli(); - dev->sbuf.kptr = dev->sbuf.kbuf; - dev->sbuf.size = spar.len * sizeof(__s16); - dev->sbuf.rem = spar.len; - dev->sbuf.ubuf = spar.data; - restore_flags(flags); - return 0; - - case HFMODEM_IOCTL_SAMPLEFINISHED: - save_flags(flags); - cli(); - if (dev->sbuf.rem > 0) { - restore_flags(flags); - return -EAGAIN; - } - if (!dev->sbuf.kbuf || !dev->sbuf.size) { - restore_flags(flags); - return -EPIPE; - } - restore_flags(flags); - ret = copy_to_user(dev->sbuf.ubuf, dev->sbuf.kbuf, dev->sbuf.size); - kfree_s(dev->sbuf.kbuf, dev->sbuf.size); - dev->sbuf.kbuf = dev->sbuf.kptr = NULL; - dev->sbuf.size = dev->sbuf.rem = 0; - return ret; - } -} - -/* --------------------------------------------------------------------- */ - -#if LINUX_VERSION_CODE >= 0x20100 - -unsigned int hfmodem_poll(struct file *file, poll_table *wait) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - unsigned long flags; - int i, cnt1, cnt2; - - poll_wait(file, &dev->wait, wait); - save_flags(flags); - cli(); - for (i = cnt1 = cnt2 = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_retired) - cnt1++; - if (dev->l1.txslots[i].state != ss_unused) - cnt2++; - } - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_retired) - cnt1++; - if (dev->l1.rxslots[i].state != ss_unused) - cnt2++; - } - restore_flags(flags); - if (cnt1 || !cnt2) - return POLLIN | POLLRDNORM; - return 0; -} - -#else - -int hfmodem_select(struct inode *inode, struct file *file, int sel_type, select_table *wait) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - unsigned long flags; - int i, cnt1, cnt2; - - if (sel_type == SEL_IN) { - save_flags(flags); - cli(); - for (i = cnt1 = cnt2 = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_retired) - cnt1++; - if (dev->l1.txslots[i].state != ss_unused) - cnt2++; - } - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_retired) - cnt1++; - if (dev->l1.rxslots[i].state != ss_unused) - cnt2++; - } - restore_flags(flags); - if (cnt1 || !cnt2) - return 1; - select_wait(&dev->wait, wait); - } - return 0; -} - -#endif - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int l1fsk_phinc(struct hfmodem_l1_txslot *txs, unsigned int nbit) -{ - return txs->phase_incs[!!((txs->data[nbit >> 3] ^ txs->inv) & (1 << (nbit & 7)))]; -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_input_samples(struct hfmodem_state *dev, hfmodem_time_t tstart, - hfmodem_time_t tinc, __s16 *samples) -{ - hfmodem_time_t tst, tend; - __s16 *s; - int i, j; - hfmodem_soft_t sample; - - dev->l1.last_time = tstart + (HFMODEM_FRAGSAMPLES-1) * tinc; - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - struct hfmodem_l1_rxslot *rxs = dev->l1.rxslots + i; - - if (rxs->state == ss_unused || rxs->state == ss_retired) - continue; - tst = tstart - (rxs->corrlen-1) * tinc; - tend = tst + (HFMODEM_FRAGSAMPLES-1) * tinc; - if (rxs->state == ss_ready) { - if ((signed)(rxs->tstart - tend) > 0) - continue; - rxs->state = ss_oper; - } - for (s = samples, j = 0; j < HFMODEM_FRAGSAMPLES; j++, s++, tst += tinc) - if ((signed)(rxs->tstart - tst) <= 0) { - sample = do_filter(rxs, s); - while ((signed)(rxs->tstart - tst) <= 0 && - rxs->cntbits < rxs->nbits) { - rxs->data[rxs->cntbits] = sample; - rxs->cntbits++; - rxs->tstart += rxs->tinc; - } - if (rxs->cntbits >= rxs->nbits) { - rxs->state = ss_retired; - break; - } - } - } -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int output_one_sample(struct hfmodem_state *dev, hfmodem_time_t tm) -{ - int i, j, k; - struct hfmodem_l1_txslot *txs; - /* - * first activate new output slots - */ - for (j = -1, i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - txs = dev->l1.txslots + i; - if (txs->state == ss_ready && (signed)(txs->tstart - tm) <= 0) { - for (k = 0; k < HFMODEM_NUMTXSLOTS; k++) { - if (dev->l1.txslots[k].state != ss_oper) - continue; - dev->l1.txslots[k].state = ss_retired; - } - txs->state = ss_oper; - txs->tstart += txs->tinc; - txs->phinc = l1fsk_phinc(txs, 0); - txs->cntbits = 1; - }; - if (txs->state != ss_oper) - continue; - j = i; - } - if (j < 0 || j >= HFMODEM_NUMTXSLOTS) - return 0; - /* - * calculate the current slot - */ - txs = dev->l1.txslots + j; - while ((signed)(txs->tstart - tm) <= 0) { - if (txs->cntbits >= txs->nbits) { - txs->state = ss_retired; - return 0; - } - txs->tstart += txs->tinc; - txs->phinc = l1fsk_phinc(txs, txs->cntbits); - txs->cntbits++; - } - return txs->phinc; -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_output_samples(struct hfmodem_state *dev, hfmodem_time_t tstart, - hfmodem_time_t tinc, __s16 *samples) -{ - int i, j; - hfmodem_time_t tend = tstart + (HFMODEM_FRAGSAMPLES-1) * tinc; - - for (i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_oper) - break; - if (dev->l1.txslots[i].state == ss_ready && - (signed)(dev->l1.txslots[i].tstart - tend) <= 0) - break; - } - if (i >= HFMODEM_NUMTXSLOTS) - return 0; - for (j = 0; j < HFMODEM_FRAGSAMPLES; j++, tstart += tinc, samples++) { - *samples = isimplecos(dev->l1.tx_phase); - dev->l1.tx_phase += output_one_sample(dev, tstart); - } - return 1; -} - -/* --------------------------------------------------------------------- */ - -long hfmodem_next_tx_event(struct hfmodem_state *dev, hfmodem_time_t curr) -{ - long diff = LONG_MAX, t; - int i; - - for (i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_oper) - if (diff > 0) - diff = 0; - if (dev->l1.txslots[i].state == ss_ready) { - t = dev->l1.txslots[i].tstart - curr; - if (t < diff) - diff = t; - } - } - return diff; -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_finish_pending_rx_requests(struct hfmodem_state *dev) -{ - int i; - - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state != ss_oper) - continue; - while (dev->l1.rxslots[i].cntbits < dev->l1.rxslots[i].nbits) { - dev->l1.rxslots[i].data[dev->l1.rxslots[i].cntbits] = 0; - dev->l1.rxslots[i].cntbits++; - } - dev->l1.rxslots[i].state = ss_retired; - } -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_wakeup(struct hfmodem_state *dev) -{ - int i, cnt1, cnt2; - - for (i = cnt1 = cnt2 = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_retired) - cnt1++; - if (dev->l1.txslots[i].state != ss_unused) - cnt2++; - } - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_retired) - cnt1++; - if (dev->l1.rxslots[i].state != ss_unused) - cnt2++; - } - if (cnt1 || !cnt2) - wake_up_interruptible(&dev->wait); -} - -/* --------------------------------------------------------------------- */ diff --git a/drivers/char/hfmodem/refclock.c b/drivers/char/hfmodem/refclock.c deleted file mode 100644 index 20153c02b..000000000 --- a/drivers/char/hfmodem/refclock.c +++ /dev/null @@ -1,154 +0,0 @@ -/*****************************************************************************/ - -/* - * refclock.c -- Linux soundcard HF FSK driver, - * Reference clock routines. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/time.h> -#include <linux/hfmodem.h> -#include <asm/processor.h> - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include <linux/version.h> - -#if LINUX_VERSION_CODE >= 0x20123 -#include <linux/init.h> -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ -/* - * command line params - */ - -static unsigned int scale_tvusec = 1UL<<24; - -#ifdef __i386__ -static unsigned int scale_rdtsc = 0; -static int rdtsc_ok = 1; -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -#ifdef __i386__ -static void __init i386_capability(void) -{ - if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) - rdtsc_ok = 1; - else - printk(KERN_INFO "%s: cpu does not support the rdtsc instruction\n", hfmodem_drvname); -} -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -void __init hfmodem_refclock_probe(void) -{ -#ifdef __i386__ - if (rdtsc_ok) { - rdtsc_ok = 0; - i386_capability(); - if (rdtsc_ok) { - unsigned int tmp0, tmp1, tmp2, tmp3; - __asm__("rdtsc" : "=a" (tmp0), "=d" (tmp1)); - __asm__("rdtsc" : "=a" (tmp2), "=d" (tmp3)); - if (tmp0 == tmp2 && tmp1 == tmp3) { - rdtsc_ok = 0; - printk(KERN_WARNING "%s: rdtsc unusable, does not change\n", - hfmodem_drvname); - } - } - } - printk(KERN_INFO "%s: using %s as timing source\n", hfmodem_drvname, - rdtsc_ok ? "rdtsc" : "gettimeofday"); -#endif /* __i386__ */ -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_refclock_init(struct hfmodem_state *dev) -{ - struct timeval tv; - - dev->clk.lasttime = 0; -#ifdef __i386__ - if (rdtsc_ok) { - __asm__("rdtsc;" : "=&d" (dev->clk.starttime_hi), "=&a" (dev->clk.starttime_lo)); - return; - } -#endif /* __i386__ */ - do_gettimeofday(&tv); - dev->clk.last_tvusec = tv.tv_usec; - dev->clk.time_cnt = 0; -} - -/* --------------------------------------------------------------------- */ - -hfmodem_time_t hfmodem_refclock_current(struct hfmodem_state *dev, hfmodem_time_t expected, int exp_valid) -{ - struct timeval tv; - hfmodem_time_t curtime; - long diff; - -#ifdef __i386__ - if (rdtsc_ok) { - unsigned int tmp0, tmp1; - unsigned int tmp2, tmp3; - - __asm__("rdtsc;\n\t" - "subl %2,%%eax\n\t" - "sbbl %3,%%edx\n\t" : "=&a" (tmp0), "=&d" (tmp1) - : "m" (dev->clk.starttime_lo), "m" (dev->clk.starttime_hi) : "ax", "dx"); - __asm__("mull %1" : "=d" (tmp2) : "m" (scale_rdtsc), "a" (tmp0) : "ax"); - __asm__("mull %1" : "=a" (tmp3) : "m" (scale_rdtsc), "a" (tmp1) : "dx"); - curtime = tmp2 + tmp3; - goto time_known; - } -#endif /* __i386__ */ - do_gettimeofday(&tv); - dev->clk.time_cnt += (unsigned)(1000000 + tv.tv_usec - dev->clk.last_tvusec) % 1000000; - dev->clk.last_tvusec = tv.tv_usec; - curtime = (dev->clk.time_cnt * scale_tvusec) >> 24; - time_known: - if (exp_valid && abs(diff = (curtime - dev->clk.lasttime - expected)) >= 1000) - printk(KERN_DEBUG "%s: refclock adjustment %ld more than 1ms\n", - hfmodem_drvname, diff); - return (dev->clk.lasttime = curtime); -} - -/* --------------------------------------------------------------------- */ diff --git a/drivers/char/hfmodem/sbc.c b/drivers/char/hfmodem/sbc.c deleted file mode 100644 index 8e4010619..000000000 --- a/drivers/char/hfmodem/sbc.c +++ /dev/null @@ -1,741 +0,0 @@ -/*****************************************************************************/ - -/* - * sbc.c -- Linux soundcard HF FSK driver, - * Soundblaster specific functions. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include <linux/hfmodem.h> - -#include <asm/io.h> -#include <asm/dma.h> - -/* --------------------------------------------------------------------- */ -/* - * the sbc converter's registers - */ -#define DSP_RESET(iobase) (iobase+0x6) -#define DSP_READ_DATA(iobase) (iobase+0xa) -#define DSP_WRITE_DATA(iobase) (iobase+0xc) -#define DSP_WRITE_STATUS(iobase) (iobase+0xc) -#define DSP_DATA_AVAIL(iobase) (iobase+0xe) -#define DSP_MIXER_ADDR(iobase) (iobase+0x4) -#define DSP_MIXER_DATA(iobase) (iobase+0x5) -#define DSP_INTACK_16BIT(iobase) (iobase+0xf) -#define SBC_EXTENT 16 - -/* --------------------------------------------------------------------- */ -/* - * SBC commands - */ - -#define SBC_OUTPUT 0x14 -#define SBC_INPUT 0x24 -#define SBC_BLOCKSIZE 0x48 -#define SBC_HI_OUTPUT 0x91 -#define SBC_HI_INPUT 0x99 -#define SBC_LO_OUTPUT_AUTOINIT 0x1c -#define SBC_LO_INPUT_AUTOINIT 0x2c -#define SBC_HI_OUTPUT_AUTOINIT 0x90 -#define SBC_HI_INPUT_AUTOINIT 0x98 -#define SBC_IMMED_INT 0xf2 -#define SBC_GET_REVISION 0xe1 -#define ESS_GET_REVISION 0xe7 -#define ESS_EXTENDED_MODE 0xc6 -#define SBC_SPEAKER_ON 0xd1 -#define SBC_SPEAKER_OFF 0xd3 -#define SBC_DMA_ON 0xd0 -#define SBC_DMA_OFF 0xd4 -#define SBC_SAMPLE_RATE 0x40 -#define SBC_SAMPLE_RATE_OUT 0x41 -#define SBC_SAMPLE_RATE_IN 0x42 -#define SBC_MONO_8BIT 0xa0 -#define SBC_MONO_16BIT 0xa4 -#define SBC_STEREO_8BIT 0xa8 -#define SBC_STEREO_16BIT 0xac - -#define SBC4_OUT8_AI 0xc6 -#define SBC4_IN8_AI 0xce -#define SBC4_MODE_UNS_MONO 0x00 -#define SBC4_MODE_SIGN_MONO 0x10 - -#define SBC4_OUT16_AI 0xb6 -#define SBC4_IN16_AI 0xbe -#define SBC4_OUT16_AI_NO_FIFO 0xb4 -#define SBC4_IN16_AI_NO_FIFO 0xbc - -/* --------------------------------------------------------------------- */ - -extern const struct hfmodem_scops sbc4_scops; -extern const struct hfmodem_scops ess_scops; - -/* --------------------------------------------------------------------- */ - -static int reset_dsp(struct hfmodem_state *dev) -{ - int i; - - outb(1, DSP_RESET(dev->io.base_addr)); - udelay(3); - outb(0, DSP_RESET(dev->io.base_addr)); - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->io.base_addr)) & 0x80) - if (inb(DSP_READ_DATA(dev->io.base_addr)) == 0xaa) - return 1; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void write_dsp(struct hfmodem_state *dev, unsigned char data) -{ - int i; - - for (i = 0; i < 0xffff; i++) - if (!(inb(DSP_WRITE_STATUS(dev->io.base_addr)) & 0x80)) { - outb(data, DSP_WRITE_DATA(dev->io.base_addr)); - return; - } -} - -/* --------------------------------------------------------------------- */ - -static int read_dsp(struct hfmodem_state *dev, unsigned char *data) -{ - int i; - - if (!data) - return 0; - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->io.base_addr)) & 0x80) { - *data = inb(DSP_READ_DATA(dev->io.base_addr)); - return 1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void write_ess(struct hfmodem_state *dev, unsigned char reg, unsigned char data) -{ - write_dsp(dev, reg); - write_dsp(dev, data); -} - -/* --------------------------------------------------------------------- */ - -static int read_ess(struct hfmodem_state *dev, unsigned char reg, unsigned char *data) -{ - write_dsp(dev, 0xc0); - write_dsp(dev, reg); - return read_dsp(dev, data); -} - -/* --------------------------------------------------------------------- */ - -static int reset_ess(struct hfmodem_state *dev) -{ - int i; - - outb(3, DSP_RESET(dev->io.base_addr)); /* reset FIFOs too */ - udelay(3); - outb(0, DSP_RESET(dev->io.base_addr)); - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->io.base_addr)) & 0x80) - if (inb(DSP_READ_DATA(dev->io.base_addr)) == 0xaa) { - write_dsp(dev, ESS_EXTENDED_MODE); - return 1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int config_resources(struct hfmodem_state *dev) -{ - unsigned char irqreg = 0, dmareg = 0, realirq, realdma; - unsigned long flags; - - switch (dev->io.irq) { - case 2: - case 9: - irqreg |= 0x01; - break; - - case 5: - irqreg |= 0x02; - break; - - case 7: - irqreg |= 0x04; - break; - - case 10: - irqreg |= 0x08; - break; - - default: - return -ENODEV; - } - - switch (dev->io.dma) { - case 0: - dmareg |= 0x01; - break; - - case 1: - dmareg |= 0x02; - break; - - case 3: - dmareg |= 0x08; - break; - - case 5: - dmareg |= 0x20; - break; - - case 6: - dmareg |= 0x40; - break; - - case 7: - dmareg |= 0x80; - break; - - default: - return -ENODEV; - } - save_flags(flags); - cli(); - outb(0x80, DSP_MIXER_ADDR(dev->io.base_addr)); - outb(irqreg, DSP_MIXER_DATA(dev->io.base_addr)); - realirq = inb(DSP_MIXER_DATA(dev->io.base_addr)); - outb(0x81, DSP_MIXER_ADDR(dev->io.base_addr)); - outb(dmareg, DSP_MIXER_DATA(dev->io.base_addr)); - realdma = inb(DSP_MIXER_DATA(dev->io.base_addr)); - restore_flags(flags); - if ((~realirq) & irqreg || (~realdma) & dmareg) { - printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device " - "and IRQ/DMA specified wrongly?\n", hfmodem_drvname); - return -EINVAL; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void sbc_int_ack_8bit(struct hfmodem_state *dev) -{ - inb(DSP_DATA_AVAIL(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void sbc_int_ack_16bit(struct hfmodem_state *dev) -{ - inb(DSP_INTACK_16BIT(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static void set_mixer(struct hfmodem_state *dev, unsigned char reg, unsigned char data) -{ - outb(reg, DSP_MIXER_ADDR(dev->io.base_addr)); - outb(data, DSP_MIXER_DATA(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_sbcprobe(struct hfmodem_state *dev) -{ - unsigned char revhi, revlo, essrevhi, essrevlo, tmp; - int ret; - - if (dev->io.base_addr <= 0 || dev->io.base_addr > 0x1000-SBC_EXTENT || - dev->io.irq < 2 || dev->io.irq > 15 || dev->io.dma > 7 || dev->io.dma == 2) - return -ENXIO; - if (check_region(dev->io.base_addr, SBC_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%x\n", - hfmodem_drvname, dev->io.base_addr); - return -ENODEV; - } - set_mixer(dev, 0, 0); /* reset mixer */ - write_dsp(dev, SBC_GET_REVISION); - if (!read_dsp(dev, &revhi) || !read_dsp(dev, &revlo)) - return -ENODEV; - printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%02d\n", hfmodem_drvname, revhi, revlo); - if (revhi == 3 && revlo == 1) { - write_dsp(dev, ESS_GET_REVISION); - if (!read_dsp(dev, &essrevhi) || !read_dsp(dev, &essrevlo)) - return -ENODEV; - if (essrevhi == 0x48 && (essrevlo & 0xf0) == 0x80) { - printk(KERN_INFO "%s: ESS ES488 AudioDrive (rev %d): unsupported.\n", - hfmodem_drvname, essrevlo & 0x0f); - return -ENODEV; - } - if (essrevhi == 0x68 && (essrevlo & 0xf0) == 0x80) { - printk(KERN_INFO "%s: ESS ES%s688 AudioDrive (rev %d)\n", - hfmodem_drvname, ((essrevlo & 0x0f) >= 8) ? "1" : "", essrevlo & 0x0f); - if (dev->io.dma > 3) { - printk(KERN_INFO "%s: DMA number out of range\n", hfmodem_drvname); - return -ENXIO; - } - printk(KERN_INFO "%s: ess: irq: ", hfmodem_drvname); - read_ess(dev, 0xb1, &tmp); - switch (tmp & 0xf) { - case 0: - printk("2, 9, \"all others\""); - break; - - case 5: - printk("5"); - break; - - case 10: - printk("7"); - break; - - case 15: - printk("10"); - break; - - default: - printk("unknown (%d)", tmp & 0xf); - break; - } - printk(" dma: "); - read_ess(dev, 0xb2, &tmp); - switch (tmp & 0xf) { - case 0: - printk("\"all others\""); - break; - - case 5: - printk("0"); - break; - - case 10: - printk("1"); - break; - - case 15: - printk("3"); - break; - - default: - printk("unknown (%d)", tmp & 0xf); - break; - } - printk("\n"); - dev->scops = &ess_scops; - return 0; - } - } - if (revhi < 4) { - printk(KERN_INFO "%s: at least SB16 required\n", hfmodem_drvname); - return -ENODEV; - } - if (dev->io.dma < 4) { - printk(KERN_INFO "%s: DMA number out of range\n", hfmodem_drvname); - return -ENXIO; - } - if ((ret = config_resources(dev))) - return ret; - dev->scops = &sbc4_scops; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_init(struct hfmodem_state *dev) -{ -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_prepare_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC_SAMPLE_RATE_IN); /* set sampling rate */ - write_dsp(dev, HFMODEM_SRATE >> 8); - write_dsp(dev, HFMODEM_SRATE & 0xff); - write_dsp(dev, SBC_SPEAKER_OFF); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_trigger_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_dsp(dev, SBC4_IN16_AI_NO_FIFO); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_prepare_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC_SAMPLE_RATE_OUT); /* set sampling rate */ - write_dsp(dev, HFMODEM_SRATE >> 8); - write_dsp(dev, HFMODEM_SRATE & 0xff); - write_dsp(dev, SBC_SPEAKER_ON); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_trigger_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_dsp(dev, SBC4_OUT16_AI_NO_FIFO); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_stop(struct hfmodem_state *dev) -{ - reset_dsp(dev); -} - -/* --------------------------------------------------------------------- */ - -static unsigned int sbc4_intack(struct hfmodem_state *dev) -{ - unsigned int dmaptr; - unsigned long flags; - unsigned char intsrc; - - save_flags(flags); - cli(); - outb(0x82, DSP_MIXER_ADDR(dev->io.base_addr)); - intsrc = inb(DSP_MIXER_DATA(dev->io.base_addr)); - if (intsrc & 0x01) - sbc_int_ack_8bit(dev); - if (intsrc & 0x02) - sbc_int_ack_16bit(dev); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - dmaptr = get_dma_residue(dev->io.dma); - enable_dma(dev->io.dma); - restore_flags(flags); - if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2; -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_mixer(struct hfmodem_state *dev, int src, int igain, int ogain) -{ - unsigned long flags; - static const unsigned char srcbits[3] = { 0x18, 0x01, 0x06 }; - - save_flags(flags); - cli(); - if (src >= 0 && src <= 2) { - set_mixer(dev, 0x3d, srcbits[src]); - set_mixer(dev, 0x3e, srcbits[src]); - } - if (ogain >= 0 && ogain <= 255) { - set_mixer(dev, 0x30, ogain); - set_mixer(dev, 0x31, ogain); - } - if (igain >= 0 && igain <= 255) { - set_mixer(dev, 0x36, igain); - set_mixer(dev, 0x37, igain); - set_mixer(dev, 0x38, igain); - set_mixer(dev, 0x39, igain); - set_mixer(dev, 0x3a, igain); - } - set_mixer(dev, 0x32, 0xff); - set_mixer(dev, 0x33, 0xff); - set_mixer(dev, 0x34, 0); - set_mixer(dev, 0x35, 0); - set_mixer(dev, 0x3b, 0); /* pc spkr vol */ - set_mixer(dev, 0x3c, 0); /* output src */ - set_mixer(dev, 0x3f, 0); /* inp gain */ - set_mixer(dev, 0x40, 0); - set_mixer(dev, 0x41, 0); /* outp gain */ - set_mixer(dev, 0x42, 0); - set_mixer(dev, 0x43, 1); /* mic agc off */ - set_mixer(dev, 0x44, 8<<4); /* treble */ - set_mixer(dev, 0x45, 8<<4); - set_mixer(dev, 0x46, 8<<4); /* bass */ - set_mixer(dev, 0x47, 8<<4); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void ess_prepare_input(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - if (!reset_ess(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset ess dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_8bit(dev); - write_ess(dev, 0xa1, 128 - (397700 + HFMODEM_SRATE/2) / HFMODEM_SRATE); - /* - * Set filter divider register - * Rolloff at 90% of the half sampling rate - */ - write_ess(dev, 0xa2, 256-(7160000 / (82 * (HFMODEM_SRATE * 9 / 20)))); - write_dsp(dev, SBC_SPEAKER_OFF); - write_ess(dev, 0xb8, 0x0e); /* Auto init DMA mode */ - read_ess(dev, 0xa8, &tmp); - write_ess(dev, 0xa8, (tmp & ~0x03) | 2); /* Mono */ - write_ess(dev, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ - /* 16 bit mono */ - write_ess(dev, 0xb7, 0x71); - write_ess(dev, 0xb7, 0xf4); - - read_ess(dev, 0xb1, &tmp); - write_ess(dev, 0xb1, (tmp & 0x0f) | 0x50); - read_ess(dev, 0xb2, &tmp); - write_ess(dev, 0xb2, (tmp & 0x0f) | 0x50); - - write_ess(dev, 0xa4, (unsigned char) ((-HFMODEM_FRAGSIZE) & 0xff)); - write_ess(dev, 0xa5, (unsigned char) (((-HFMODEM_FRAGSIZE) >> 8) & 0xff)); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void ess_trigger_input(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - save_flags(flags); - cli(); - read_ess(dev, 0xb8, &tmp); - write_ess(dev, 0xb8, tmp | 0x0f); /* Go */ - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -void ess_prepare_output(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - if (!reset_ess(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset ess dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_8bit(dev); - write_ess(dev, 0xa1, 128 - (397700 + HFMODEM_SRATE/2) / HFMODEM_SRATE); - /* - * Set filter divider register - * Rolloff at 90% of the half sampling rate - */ - write_ess(dev, 0xa2, 256-(7160000 / (82 * (HFMODEM_SRATE * 9 / 20)))); - write_ess(dev, 0xb8, 0x04); /* Auto init DMA mode */ - read_ess(dev, 0xa8, &tmp); - write_ess(dev, 0xa8, (tmp & ~0x03) | 2); /* Mono */ - write_ess(dev, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ - /* 16 bit mono */ - write_ess(dev, 0xb6, 0x00); - write_ess(dev, 0xb7, 0x71); - write_ess(dev, 0xb7, 0xf4); - - read_ess(dev, 0xb1, &tmp); - write_ess(dev, 0xb1, (tmp & 0x0f) | 0x50); - read_ess(dev, 0xb2, &tmp); - write_ess(dev, 0xb2, (tmp & 0x0f) | 0x50); - - write_ess(dev, 0xa4, (unsigned char) ((-HFMODEM_FRAGSIZE) & 0xff)); - write_ess(dev, 0xa5, (unsigned char) (((-HFMODEM_FRAGSIZE) >> 8) & 0xff)); - - write_dsp(dev, SBC_SPEAKER_ON); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -void ess_trigger_output(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - save_flags(flags); - cli(); - read_ess(dev, 0xb8, &tmp); - write_ess(dev, 0xb8, tmp | 0x05); /* Go */ - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -unsigned int ess_intack(struct hfmodem_state *dev) -{ - unsigned int dmaptr; - unsigned long flags; - unsigned char st; -#if 0 - static unsigned int cnt = 0; -#endif - - save_flags(flags); - cli(); - st = inb(DSP_WRITE_STATUS(dev->io.base_addr)); - sbc_int_ack_8bit(dev); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - dmaptr = get_dma_residue(dev->io.dma); - enable_dma(dev->io.dma); - restore_flags(flags); -#if 0 - cnt = (cnt + 1) & 0x3f; - if (!cnt) - printk(KERN_DEBUG "%s: ess: FIFO: full:%c empty:%c half empty:%c IRQ: cpu:%c half empty:%c DMA:%c\n", - hfmodem_drvname, '1'-!(st&0x20), '1'-!(st&0x10), '1'-!(st&0x8), - '1'-!(st&0x4), '1'-!(st&0x2), '1'-!(st&0x1)); -#endif - if (st & 0x20) /* FIFO full, 256 bytes */ - dmaptr += 256; - else if (!(st & 0x10)) /* FIFO not empty, assume half full 128 bytes */ - dmaptr += 128; - if (dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr -= HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2; -} - -/* --------------------------------------------------------------------- */ - -static void ess_mixer(struct hfmodem_state *dev, int src, int igain, int ogain) -{ - unsigned long flags; - - save_flags(flags); - cli(); - if (src >= 0 && src <= 2) - set_mixer(dev, 0x0c, ((src+3) & 3) << 1); - if (ogain >= 0 && ogain <= 255) - set_mixer(dev, 0x22, (ogain & 0xf0) | ((ogain >> 4) & 0xf)); - if (igain >= 0 && igain <= 255) { - set_mixer(dev, 0x36, igain); - set_mixer(dev, 0x37, igain); - set_mixer(dev, 0x38, igain); - set_mixer(dev, 0x39, igain); - set_mixer(dev, 0x3a, igain); - } - set_mixer(dev, 0x4, 0xff); - set_mixer(dev, 0xe, 0x0); - set_mixer(dev, 0x26, 0); - set_mixer(dev, 0x28, 0); - set_mixer(dev, 0x2e, 0); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static const struct hfmodem_scops sbc4_scops = { - SBC_EXTENT, sbc4_init, sbc4_prepare_input, sbc4_trigger_input, - sbc4_prepare_output, sbc4_trigger_output, sbc4_stop, sbc4_intack, sbc4_mixer -}; - -static const struct hfmodem_scops ess_scops = { - SBC_EXTENT, sbc4_init, ess_prepare_input, ess_trigger_input, - ess_prepare_output, ess_trigger_output, sbc4_stop, ess_intack, ess_mixer -}; - -/* --------------------------------------------------------------------- */ diff --git a/drivers/char/hfmodem/wss.c b/drivers/char/hfmodem/wss.c deleted file mode 100644 index c54aeadee..000000000 --- a/drivers/char/hfmodem/wss.c +++ /dev/null @@ -1,437 +0,0 @@ -/*****************************************************************************/ - -/* - * wss.c -- Linux soundcard HF FSK driver, - * WindowsSoundSystem specific functions. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/ioport.h> - -#include <asm/io.h> -#include <asm/dma.h> - -#include <linux/hfmodem.h> - -/* --------------------------------------------------------------------- */ - -#define WSS_CONFIG(iobase) (iobase+0) -#define WSS_STATUS(iobase) (iobase+3) -#define WSS_CODEC_IA(iobase) (iobase+4) -#define WSS_CODEC_ID(iobase) (iobase+5) -#define WSS_CODEC_STATUS(iobase) (iobase+6) -#define WSS_CODEC_DATA(iobase) (iobase+7) - -#define WSS_EXTENT 8 - -/* --------------------------------------------------------------------- */ - -extern const struct hfmodem_scops wss_scops; - -/* --------------------------------------------------------------------- */ - -static void write_codec(struct hfmodem_state *dev, unsigned char idx, - unsigned char data) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->io.base_addr)) & 0x80) - timeout--; - outb(idx, WSS_CODEC_IA(dev->io.base_addr)); - outb(data, WSS_CODEC_ID(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static unsigned char read_codec(struct hfmodem_state *dev, unsigned char idx) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->io.base_addr)) & 0x80) - timeout--; - outb(idx & 0x1f, WSS_CODEC_IA(dev->io.base_addr)); - return inb(WSS_CODEC_ID(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void wss_ack_int(struct hfmodem_state *dev) -{ - outb(0, WSS_CODEC_STATUS(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static int wss_srate_tab[16] = { - 8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050, - -1, 37800, -1, 44100, 48000, 33075, 9600, 6620 -}; - -static int wss_srate_index(int srate) -{ - int i; - - for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++) - if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0) - return i; - return -1; -} - -/* --------------------------------------------------------------------- */ - -static int wss_set_codec_fmt(struct hfmodem_state *dev, unsigned char fmt) -{ - unsigned long time; - unsigned long flags; - - save_flags(flags); - cli(); - /* Clock and data format register */ - write_codec(dev, 0x48, fmt); - /* MCE and interface config reg */ - write_codec(dev, 0x49, 0xc); - outb(0xb, WSS_CODEC_IA(dev->io.base_addr)); /* leave MCE */ - /* - * wait for ACI start - */ - time = 1000; - while (!(read_codec(dev, 0x0b) & 0x20)) - if (!(--time)) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n", - hfmodem_drvname); - restore_flags(flags); - return -1; - } - /* - * wait for ACI end - */ - sti(); - time = jiffies + HZ/4; - while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0)); - restore_flags(flags); - if ((signed)(jiffies - time) >= 0) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n", - hfmodem_drvname); - return -1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_init_codec(struct hfmodem_state *dev) -{ - unsigned char tmp, revwss, revid; - static const signed char irqtab[16] = { - -1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1, -1, -1 - }; - static const signed char dmatab[4] = { 1, 2, -1, 3 }; - int fmt; - - if ((fmt = wss_srate_index(HFMODEM_SRATE)) < 0) { - printk(KERN_ERR "%s: WSS: sampling rate not supported\n", hfmodem_drvname); - return -1; - } - fmt &= 0x0f; -#ifdef __BIG_ENDIAN - fmt |= 0xc0; -#else /* __BIG_ENDIAN */ - fmt |= 0x40; -#endif /* __BIG_ENDIAN */ - tmp = inb(WSS_STATUS(dev->io.base_addr)); - if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 && - (tmp & 0x3f) != 0x0f) { - printk(KERN_WARNING "%s: WSS card id register not found, " - "address 0x%x, ID register 0x%02x\n", hfmodem_drvname, - dev->io.base_addr, (int)tmp); - /* return -1; */ - revwss = 0; - } else { - if ((tmp & 0x80) && ((dev->io.dma == 0) || ((dev->io.irq >= 8) && (dev->io.irq != 9)))) { - printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 " - "(except IRQ9) cannot be used on an 8bit " - "card\n", hfmodem_drvname); - return -1; - } - if (dev->io.irq > 15 || irqtab[dev->io.irq] == -1) { - printk(KERN_ERR "%s: WSS: invalid interrupt %d\n", - hfmodem_drvname, (int)dev->io.irq); - return -1; - } - if (dev->io.dma > 3 || dmatab[dev->io.dma] == -1) { - printk(KERN_ERR "%s: WSS: invalid dma channel %d\n", - hfmodem_drvname, (int)dev->io.dma); - return -1; - } - tmp = irqtab[dev->io.irq] | dmatab[dev->io.dma]; - /* irq probe */ - outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->io.base_addr)); - if (!(inb(WSS_STATUS(dev->io.base_addr)) & 0x40)) { - outb(0, WSS_CONFIG(dev->io.base_addr)); - printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n", - hfmodem_drvname, dev->io.irq); - } - outb(tmp, WSS_CONFIG(dev->io.base_addr)); - revwss = inb(WSS_STATUS(dev->io.base_addr)) & 0x3f; - } - /* - * initialize the codec - */ - write_codec(dev, 9, 0); - write_codec(dev, 12, 0); - write_codec(dev, 0, 0x45); - if (read_codec(dev, 0) != 0x45) - goto codec_err; - write_codec(dev, 0, 0xaa); - if (read_codec(dev, 0) != 0xaa) - goto codec_err; - if (wss_set_codec_fmt(dev, fmt)) - goto codec_err; - write_codec(dev, 0, 0x40); /* left input control */ - write_codec(dev, 1, 0x40); /* right input control */ - write_codec(dev, 2, 0x80); /* left aux#1 input control */ - write_codec(dev, 3, 0x80); /* right aux#1 input control */ - write_codec(dev, 4, 0x80); /* left aux#2 input control */ - write_codec(dev, 5, 0x80); /* right aux#2 input control */ - write_codec(dev, 6, 0x80); /* left dac control */ - write_codec(dev, 7, 0x80); /* right dac control */ - write_codec(dev, 0xa, 0x2); /* pin control register */ - write_codec(dev, 0xd, 0x0); /* digital mix control */ - revid = read_codec(dev, 0xc) & 0xf; - /* - * print revisions - */ - printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n", - hfmodem_drvname, (int)revwss, (int)revid); - return 0; - codec_err: - outb(0, WSS_CONFIG(dev->io.base_addr)); - printk(KERN_ERR "%s: no WSS soundcard found at address 0x%x\n", - hfmodem_drvname, dev->io.base_addr); - return -1; -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_wssprobe(struct hfmodem_state *dev) -{ - if (dev->io.base_addr <= 0 || dev->io.base_addr > 0x1000-WSS_EXTENT || - dev->io.irq < 2 || dev->io.irq > 15 || dev->io.dma > 3 || dev->io.dma == 2) - return -ENXIO; - if (check_region(dev->io.base_addr, WSS_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (wss_init_codec(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%x\n", - hfmodem_drvname, dev->io.base_addr); - return -ENODEV; - } - dev->scops = &wss_scops; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void wss_init(struct hfmodem_state *dev) -{ - wss_init_codec(dev); -} - -/* --------------------------------------------------------------------- */ - -static void wss_stop(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char oldcodecmode; - long abrt; - - save_flags(flags); - cli(); - /* - * perform the final DMA sequence to disable the codec request - */ - oldcodecmode = read_codec(dev, 9); - write_codec(dev, 9, 0xc); /* disable codec */ - wss_ack_int(dev); - if (read_codec(dev, 11) & 0x10) { - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, (oldcodecmode & 1) ? - (DMA_MODE_WRITE | DMA_MODE_AUTOINIT) : (DMA_MODE_READ | DMA_MODE_AUTOINIT)); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - abrt = 0; - while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000)); - } - disable_dma(dev->io.dma); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_prepare_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - wss_stop(dev); - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - write_codec(dev, 15, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_codec(dev, 14, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_trigger_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_codec(dev, 9, 0x0e); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_prepare_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - wss_stop(dev); - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - write_codec(dev, 15, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_codec(dev, 14, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_trigger_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_codec(dev, 9, 0x0d); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static unsigned int wss_intack(struct hfmodem_state *dev) -{ - unsigned int dmaptr, nums; - unsigned long flags; - - save_flags(flags); - cli(); - wss_ack_int(dev); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - dmaptr = get_dma_residue(dev->io.dma); - if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - nums = (((dmaptr - 1) % HFMODEM_FRAGSIZE) - 1) / 2; - write_codec(dev, 15, nums & 0xff); - write_codec(dev, 14, nums >> 8); - enable_dma(dev->io.dma); - restore_flags(flags); - return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2; -} - -/* --------------------------------------------------------------------- */ - -static void wss_mixer(struct hfmodem_state *dev, int src, int igain, int ogain) -{ - unsigned long flags; - static const unsigned char srctoreg[3] = { 1, 2, 0 }; - static const unsigned char regtosrc[4] = { 2, 0, 1, 0 }; - unsigned char tmp; - - save_flags(flags); - cli(); - tmp = read_codec(dev, 0x00); - if (src < 0 || src > 2) - src = regtosrc[(tmp >> 6) & 3]; - if (igain < 0 || igain > 255) { - if (src == 1) - igain = ((tmp & 0xf) + ((tmp & 0x20) ? 13 : 0)) << 3; - else - igain = (tmp & 0xf) << 4; - } - if (src == 1) { - if (igain > (28<<3)) - tmp = 0x2f; - else if (igain >= (13<<3)) - tmp = 0x20 + (((igain >> 3) - 13) & 0xf); - else - tmp = (igain >> 3) & 0xf; - } else - tmp = (igain >> 4) & 0xf; - tmp |= srctoreg[src] << 6; - write_codec(dev, 0, tmp); - write_codec(dev, 1, tmp); - if (ogain > 0 && ogain <= 255) { - tmp = 63 - (ogain >> 2); - write_codec(dev, 6, tmp); - write_codec(dev, 7, tmp); - } else if (ogain == 0) { - write_codec(dev, 6, 0x80); - write_codec(dev, 7, 0x80); - } - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static const struct hfmodem_scops wss_scops = { - WSS_EXTENT, wss_init, wss_prepare_input, wss_trigger_input, - wss_prepare_output, wss_trigger_output, wss_stop, wss_intack, wss_mixer -}; - -/* --------------------------------------------------------------------- */ |