Import 2.1.118
[davej-history.git] / drivers / char / hfmodem / main.c
blobde5ed5cc2e58e2a55d0961b37e60f4a0cf5c4a76
1 /*****************************************************************************/
3 /*
4 * main.c -- Linux soundcard HF FSK driver.
6 * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch)
7 * Swiss Federal Institute of Technology (ETH), Electronics Lab
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Command line options (insmod command line)
25 * History:
26 * 0.1 15.04.97 Adapted from baycom.c and made network driver interface
27 * 0.2 05.07.97 All floating point stuff thrown out due to Linus' rantings :)
31 /*****************************************************************************/
34 #include <linux/config.h> /* for CONFIG_HFMODEM_WSS and CONFIG_HFMODEM_SBC */
35 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/malloc.h>
40 #include <linux/errno.h>
41 #include <linux/miscdevice.h>
42 #include <linux/ioport.h>
43 #include <linux/hfmodem.h>
45 #include <asm/io.h>
46 #include <asm/segment.h>
47 #include <asm/system.h>
48 #include <asm/irq.h>
49 #include <asm/dma.h>
51 /* --------------------------------------------------------------------- */
54 * currently this module is supposed to support both module styles, i.e.
55 * the old one present up to about 2.1.9, and the new one functioning
56 * starting with 2.1.21. The reason is I have a kit allowing to compile
57 * this module also under 2.0.x which was requested by several people.
58 * This will go in 2.2
60 #include <linux/version.h>
62 #if LINUX_VERSION_CODE >= 0x20100
63 #include <asm/uaccess.h>
64 #else
65 #include <asm/segment.h>
66 #include <linux/mm.h>
68 #undef put_user
69 #undef get_user
71 #define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
72 #define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
74 extern inline int copy_from_user(void *to, const void *from, unsigned long n)
76 int i = verify_area(VERIFY_READ, from, n);
77 if (i)
78 return i;
79 memcpy_fromfs(to, from, n);
80 return 0;
83 extern inline int copy_to_user(void *to, const void *from, unsigned long n)
85 int i = verify_area(VERIFY_WRITE, to, n);
86 if (i)
87 return i;
88 memcpy_tofs(to, from, n);
89 return 0;
91 #endif
93 #if LINUX_VERSION_CODE >= 0x20123
94 #include <linux/init.h>
95 #else
96 #define __init
97 #define __initdata
98 #define __initfunc(x) x
99 #endif
101 /* --------------------------------------------------------------------- */
103 /*static*/ const char hfmodem_drvname[] = "hfmodem";
104 static const char hfmodem_drvinfo[] = KERN_INFO "hfmodem: (C) 1997 Thomas Sailer, HB9JNX/AE4WA\n"
105 KERN_INFO "hfmodem: version 0.2 compiled " __TIME__ " " __DATE__ "\n";
107 /* --------------------------------------------------------------------- */
109 * currently we support only one device
112 struct hfmodem_state hfmodem_state[NR_DEVICE];
114 /* --------------------------------------------------------------------- */
116 * ===================== port checking routines ========================
120 #define UART_RBR(iobase) (iobase+0)
121 #define UART_THR(iobase) (iobase+0)
122 #define UART_IER(iobase) (iobase+1)
123 #define UART_IIR(iobase) (iobase+2)
124 #define UART_FCR(iobase) (iobase+2)
125 #define UART_LCR(iobase) (iobase+3)
126 #define UART_MCR(iobase) (iobase+4)
127 #define UART_LSR(iobase) (iobase+5)
128 #define UART_MSR(iobase) (iobase+6)
129 #define UART_SCR(iobase) (iobase+7)
130 #define UART_DLL(iobase) (iobase+0)
131 #define UART_DLM(iobase) (iobase+1)
133 #define SER_EXTENT 8
135 #define LPT_DATA(iobase) (iobase+0)
136 #define LPT_STATUS(iobase) (iobase+1)
137 #define LPT_CONTROL(iobase) (iobase+2)
138 #define LPT_IRQ_ENABLE 0x10
140 #define MIDI_DATA(iobase) (iobase)
141 #define MIDI_STATUS(iobase) (iobase+1)
142 #define MIDI_READ_FULL 0x80 /* attention: negative logic!! */
143 #define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */
145 #define MIDI_EXTENT 2
147 #define SP_SER 1
148 #define SP_PAR 2
149 #define SP_MIDI 4
151 /* ---------------------------------------------------------------------- */
153 static int parptt_preempt(void *handle)
155 /* we cannot relinquish the port in the middle of an operation */
156 return 1;
159 /* --------------------------------------------------------------------- */
161 static void parptt_wakeup(void *handle)
163 struct hfmodem_state *dev = (struct hfmodem_state *)handle;
165 printk(KERN_DEBUG "%s: parptt: why am I being woken up?\n", hfmodem_drvname);
166 if (!parport_claim(dev->ptt_out.pardev))
167 printk(KERN_DEBUG "%s: parptt: I'm broken.\n", hfmodem_drvname);
170 /* --------------------------------------------------------------------- */
171 __initfunc(static int check_lpt(struct hfmodem_state *dev, unsigned int iobase))
173 struct parport *pp = parport_enumerate();
175 while (pp && pp->base != iobase)
176 pp = pp->next;
177 if (!pp)
178 return 0;
179 if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, parptt_preempt, parptt_wakeup,
180 NULL, PARPORT_DEV_LURK, dev)))
181 return 0;
182 return 1;
185 /* --------------------------------------------------------------------- */
187 enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A };
188 static const char *uart_str[] __initdata = { "unknown", "8250", "16450", "16550", "16550A" };
190 __initfunc(static enum uart check_uart(unsigned int iobase))
192 unsigned char b1,b2,b3;
193 enum uart u;
194 enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
196 if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)
197 return c_uart_unknown;
198 if (check_region(iobase, SER_EXTENT))
199 return c_uart_unknown;
200 b1 = inb(UART_MCR(iobase));
201 outb(b1 | 0x10, UART_MCR(iobase)); /* loopback mode */
202 b2 = inb(UART_MSR(iobase));
203 outb(0x1a, UART_MCR(iobase));
204 b3 = inb(UART_MSR(iobase)) & 0xf0;
205 outb(b1, UART_MCR(iobase)); /* restore old values */
206 outb(b2, UART_MSR(iobase));
207 if (b3 != 0x90)
208 return c_uart_unknown;
209 inb(UART_RBR(iobase));
210 inb(UART_RBR(iobase));
211 outb(0x01, UART_FCR(iobase)); /* enable FIFOs */
212 u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];
213 if (u == c_uart_16450) {
214 outb(0x5a, UART_SCR(iobase));
215 b1 = inb(UART_SCR(iobase));
216 outb(0xa5, UART_SCR(iobase));
217 b2 = inb(UART_SCR(iobase));
218 if ((b1 != 0x5a) || (b2 != 0xa5))
219 u = c_uart_8250;
221 return u;
224 /* --------------------------------------------------------------------- */
226 __initfunc(static int check_midi(unsigned int iobase))
228 unsigned long timeout;
229 unsigned long flags;
230 unsigned char b;
232 if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT)
233 return 0;
234 if (check_region(iobase, MIDI_EXTENT))
235 return 0;
236 timeout = jiffies + (HZ / 100);
237 while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
238 if ((signed)(jiffies - timeout) > 0)
239 return 0;
240 save_flags(flags);
241 cli();
242 outb(0xff, MIDI_DATA(iobase));
243 b = inb(MIDI_STATUS(iobase));
244 restore_flags(flags);
245 if (!(b & MIDI_WRITE_EMPTY))
246 return 0;
247 while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
248 if ((signed)(jiffies - timeout) > 0)
249 return 0;
250 return 1;
253 /* --------------------------------------------------------------------- */
255 static void output_status(struct hfmodem_state *dev, int ptt)
257 int dcd = 0;
259 ptt = !!ptt;
260 if (dev->ptt_out.flags & SP_SER) {
261 outb(dcd | (ptt << 1), UART_MCR(dev->ptt_out.seriobase));
262 outb(0x40 & (-ptt), UART_LCR(dev->ptt_out.seriobase));
264 if (dev->ptt_out.flags & SP_PAR) {
265 outb(ptt | (dcd << 1), LPT_DATA(dev->ptt_out.pariobase));
267 if (dev->ptt_out.flags & SP_MIDI && ptt) {
268 outb(0, MIDI_DATA(dev->ptt_out.midiiobase));
272 /* --------------------------------------------------------------------- */
274 __initfunc(static void output_check(struct hfmodem_state *dev))
276 enum uart u = c_uart_unknown;
278 if (((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown)
279 printk(KERN_INFO "%s: PTT output: uart found at address 0x%x type %s\n",
280 hfmodem_drvname, dev->ptt_out.seriobase, uart_str[u]);
281 else {
282 if (dev->ptt_out.seriobase > 0)
283 printk(KERN_WARNING "%s: PTT output: no uart found at address 0x%x\n",
284 hfmodem_drvname, dev->ptt_out.seriobase);
285 dev->ptt_out.seriobase = 0;
287 if (check_lpt(dev, dev->ptt_out.pariobase))
288 printk(KERN_INFO "%s: PTT output: parallel port found at address 0x%x\n",
289 hfmodem_drvname, dev->ptt_out.pariobase);
290 else {
291 if (dev->ptt_out.pariobase > 0)
292 printk(KERN_WARNING "%s: PTT output: no parallel port found at address 0x%x\n",
293 hfmodem_drvname, dev->ptt_out.pariobase);
294 dev->ptt_out.pariobase = 0;
295 dev->ptt_out.pardev = NULL;
297 if (dev->ptt_out.midiiobase > 0 && dev->ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&
298 check_midi(dev->ptt_out.midiiobase))
299 printk(KERN_INFO "%s: PTT output: midi port found at address 0x%x\n",
300 hfmodem_drvname, dev->ptt_out.midiiobase);
301 else {
302 if (dev->ptt_out.midiiobase > 0)
303 printk(KERN_WARNING "%s: PTT output: no midi port found at address 0x%x\n",
304 hfmodem_drvname, dev->ptt_out.midiiobase);
305 dev->ptt_out.midiiobase = 0;
309 /* --------------------------------------------------------------------- */
311 static void output_open(struct hfmodem_state *dev)
313 dev->ptt_out.flags = 0;
314 if (dev->ptt_out.seriobase > 0) {
315 if (!check_region(dev->ptt_out.seriobase, SER_EXTENT)) {
316 request_region(dev->ptt_out.seriobase, SER_EXTENT, "hfmodem ser ptt");
317 dev->ptt_out.flags |= SP_SER;
318 outb(0, UART_IER(dev->ptt_out.seriobase));
319 /* 5 bits, 1 stop, no parity, no break, Div latch access */
320 outb(0x80, UART_LCR(dev->ptt_out.seriobase));
321 outb(0, UART_DLM(dev->ptt_out.seriobase));
322 outb(1, UART_DLL(dev->ptt_out.seriobase)); /* as fast as possible */
323 /* LCR and MCR set by output_status */
324 } else
325 printk(KERN_WARNING "%s: PTT output: serial port at 0x%x busy\n",
326 hfmodem_drvname, dev->ptt_out.seriobase);
328 if (dev->ptt_out.pariobase > 0) {
329 if (parport_claim(dev->ptt_out.pardev))
330 printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n",
331 hfmodem_drvname, dev->ptt_out.pariobase);
332 else
333 dev->ptt_out.flags |= SP_PAR;
335 if (dev->ptt_out.midiiobase > 0) {
336 if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) {
337 request_region(dev->ptt_out.midiiobase, MIDI_EXTENT, "hfmodem midi ptt");
338 dev->ptt_out.flags |= SP_MIDI;
339 } else
340 printk(KERN_WARNING "%s: PTT output: midi port at 0x%x busy\n",
341 hfmodem_drvname, dev->ptt_out.midiiobase);
343 output_status(dev, 0);
344 printk(KERN_INFO "%s: PTT output:", hfmodem_drvname);
345 if (dev->ptt_out.flags & SP_SER)
346 printk(" serial interface at 0x%x", dev->ptt_out.seriobase);
347 if (dev->ptt_out.flags & SP_PAR)
348 printk(" parallel interface at 0x%x", dev->ptt_out.pariobase);
349 if (dev->ptt_out.flags & SP_MIDI)
350 printk(" mpu401 (midi) interface at 0x%x", dev->ptt_out.midiiobase);
351 if (!dev->ptt_out.flags)
352 printk(" none");
353 printk("\n");
356 /* --------------------------------------------------------------------- */
358 static void output_close(struct hfmodem_state *dev)
360 /* release regions used for PTT output */
361 output_status(dev, 0);
362 if (dev->ptt_out.flags & SP_SER)
363 release_region(dev->ptt_out.seriobase, SER_EXTENT);
364 if (dev->ptt_out.flags & SP_PAR)
365 parport_release(dev->ptt_out.pardev);
366 if (dev->ptt_out.flags & SP_MIDI)
367 release_region(dev->ptt_out.midiiobase, MIDI_EXTENT);
368 dev->ptt_out.flags = 0;
371 /* --------------------------------------------------------------------- */
373 #define INC_SAMPLE (1000000/HFMODEM_SRATE)
374 #define INC_FRAGMENT (HFMODEM_FRAGSAMPLES*1000000/HFMODEM_SRATE)
375 #define SIZE (HFMODEM_FRAGSAMPLES*HFMODEM_NUMFRAGS)
377 static void hfmodem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
379 struct hfmodem_state *dev = (struct hfmodem_state *)dev_id;
380 unsigned int dmaptr;
381 __s16 *s;
382 unsigned int curfrag, nfrags;
383 int i;
384 hfmodem_time_t l1time;
386 dmaptr = dev->scops->intack(dev);
387 l1time = hfmodem_refclock_current(dev, ((SIZE+dmaptr-dev->dma.last_dmaptr) % SIZE) *
388 INC_SAMPLE, 1);
389 curfrag = (dev->dma.last_dmaptr = dmaptr) / HFMODEM_FRAGSAMPLES;
390 l1time -= INC_SAMPLE * (SIZE+dmaptr-dev->dma.fragptr*HFMODEM_FRAGSAMPLES) % SIZE;
391 sti();
393 * handle receiving
395 if (dev->dma.ptt_frames <= 0) {
396 while (dev->dma.fragptr != curfrag) {
397 if (dev->dma.fragptr < HFMODEM_EXCESSFRAGS) {
398 s = dev->dma.buf + SIZE + HFMODEM_FRAGSAMPLES * dev->dma.fragptr;
399 memcpy(s, s - SIZE, HFMODEM_FRAGSIZE);
400 } else
401 s = dev->dma.buf + HFMODEM_FRAGSAMPLES * dev->dma.fragptr;
402 if (dev->sbuf.kbuf && dev->sbuf.kptr && dev->sbuf.rem > 0) {
403 i = HFMODEM_FRAGSAMPLES;
404 if (i > dev->sbuf.rem)
405 i = dev->sbuf.rem;
406 memcpy(dev->sbuf.kptr, s, i * sizeof(s[0]));
407 dev->sbuf.rem -= i;
408 dev->sbuf.kptr += i;
410 hfmodem_input_samples(dev, l1time, INC_SAMPLE, s);
411 l1time += INC_FRAGMENT;
412 dev->dma.fragptr++;
413 if (dev->dma.fragptr >= HFMODEM_NUMFRAGS)
414 dev->dma.fragptr = 0;
417 * check for output
419 if (hfmodem_next_tx_event(dev, l1time) > (long)INC_FRAGMENT/2)
420 goto int_return;
422 * start output
424 output_status(dev, 1);
425 dev->scops->prepare_output(dev);
426 dev->dma.last_dmaptr = 0;
428 * clock adjust
430 l1time = hfmodem_refclock_current(dev, 0, 0);
432 * fill first two fragments
434 dev->dma.ptt_frames = 1;
435 for (i = 0; i < 2 && i < HFMODEM_NUMFRAGS; i++)
436 if (hfmodem_output_samples(dev, l1time+i*INC_FRAGMENT, INC_SAMPLE,
437 dev->dma.buf+i*HFMODEM_FRAGSAMPLES))
438 dev->dma.ptt_frames = i + 1;
439 dev->dma.lastfrag = 0;
440 dev->scops->trigger_output(dev);
442 * finish already pending rx requests
444 hfmodem_finish_pending_rx_requests(dev);
445 goto int_return;
448 * handle transmitting
450 nfrags = HFMODEM_NUMFRAGS + curfrag - dev->dma.lastfrag;
451 dev->dma.lastfrag = curfrag;
452 if (nfrags >= HFMODEM_NUMFRAGS)
453 nfrags -= HFMODEM_NUMFRAGS;
454 dev->dma.ptt_frames -= nfrags;
455 if (dev->dma.ptt_frames < 0)
456 dev->dma.ptt_frames = 0;
457 while (dev->dma.ptt_frames < HFMODEM_NUMFRAGS && dev->dma.ptt_frames < 4 &&
458 hfmodem_output_samples(dev, l1time+dev->dma.ptt_frames*INC_FRAGMENT,
459 INC_SAMPLE, dev->dma.buf + HFMODEM_FRAGSAMPLES *
460 ((curfrag + dev->dma.ptt_frames) % HFMODEM_NUMFRAGS)))
461 dev->dma.ptt_frames++;
462 if (dev->dma.ptt_frames > 0)
463 goto int_return;
465 * start receiving
467 output_status(dev, 0);
468 dev->dma.last_dmaptr = 0;
469 dev->dma.lastfrag = 0;
470 dev->dma.fragptr = 0;
471 dev->dma.ptt_frames = 0;
472 dev->scops->prepare_input(dev);
473 dev->scops->trigger_input(dev);
474 hfmodem_refclock_current(dev, 0, 0); /* needed to reset the time difference */
475 int_return:
476 hfmodem_wakeup(dev);
479 /* --------------------------------------------------------------------- */
481 static int hfmodem_close(struct inode *inode, struct file *file)
483 struct hfmodem_state *dev = &hfmodem_state[0];
485 if (!dev->active)
486 return -EPERM;
487 dev->active = 0;
488 dev->scops->stop(dev);
489 free_irq(dev->io.irq, dev);
490 disable_dma(dev->io.dma);
491 free_dma(dev->io.dma);
492 release_region(dev->io.base_addr, dev->scops->extent);
493 kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS));
494 hfmodem_clear_rq(dev);
495 if (dev->sbuf.kbuf) {
496 kfree_s(dev->sbuf.kbuf, dev->sbuf.size);
497 dev->sbuf.kbuf = dev->sbuf.kptr = NULL;
498 dev->sbuf.size = dev->sbuf.rem = 0;
500 output_close(dev);
501 MOD_DEC_USE_COUNT;
502 return 0;
505 /* --------------------------------------------------------------------- */
507 static int hfmodem_open(struct inode *inode, struct file *file)
509 struct hfmodem_state *dev = &hfmodem_state[0];
511 if (dev->active)
512 return -EBUSY;
513 if (!dev->scops)
514 return -EPERM;
516 * clear vars
518 memset(&dev->l1, 0, sizeof(dev->l1));
519 dev->dma.last_dmaptr = 0;
520 dev->dma.lastfrag = 0;
521 dev->dma.fragptr = 0;
522 dev->dma.ptt_frames = 0;
524 * allocate memory
526 if (!(dev->dma.buf = kmalloc(HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS), GFP_KERNEL | GFP_DMA)))
527 return -ENOMEM;
529 * allocate resources
531 if (request_dma(dev->io.dma, hfmodem_drvname)) {
532 kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS));
533 return -EBUSY;
535 if (request_irq(dev->io.irq, hfmodem_interrupt, SA_INTERRUPT, hfmodem_drvname, dev)) {
536 free_dma(dev->io.dma);
537 kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS));
538 return -EBUSY;
540 request_region(dev->io.base_addr, dev->scops->extent, hfmodem_drvname);
542 /* clear requests */
543 dev->active++;
544 MOD_INC_USE_COUNT;
545 hfmodem_refclock_init(dev);
546 output_open(dev);
547 dev->scops->init(dev);
548 dev->scops->prepare_input(dev);
549 dev->scops->trigger_input(dev);
550 return 0;
553 /* --------------------------------------------------------------------- */
555 static struct file_operations hfmodem_fops = {
556 NULL, /* hfmodem_seek */
557 NULL, /* hfmodem_read */
558 NULL, /* hfmodem_write */
559 NULL, /* hfmodem_readdir */
560 #if LINUX_VERSION_CODE >= 0x20100
561 hfmodem_poll, /* hfmodem_poll */
562 #else
563 hfmodem_select, /* hfmodem_select */
564 #endif
565 hfmodem_ioctl, /* hfmodem_ioctl */
566 NULL, /* hfmodem_mmap */
567 hfmodem_open, /* hfmodem_open */
568 NULL, /* flush */
569 hfmodem_close, /* hfmodem_close */
570 NULL, /* hfmodem_fsync */
571 NULL, /* hfmodem_fasync */
572 NULL, /* hfmodem_check_media_change */
573 NULL /* hfmodem_revalidate */
576 /* --------------------------------------------------------------------- */
578 static struct miscdevice hfmodem_device = {
579 HFMODEM_MINOR, hfmodem_drvname, &hfmodem_fops
582 /* --------------------------------------------------------------------- */
584 #ifdef MODULE
587 * Command line parameters
590 static int hw = 0;
591 static unsigned int iobase = 0x220;
592 static unsigned int irq = 7;
593 static unsigned int dma = 1;
595 static unsigned int serio = 0;
596 static unsigned int pario = 0;
597 static unsigned int midiio = 0;
599 #if LINUX_VERSION_CODE >= 0x20115
601 MODULE_PARM(hw, "i");
602 MODULE_PARM_DESC(hw, "hardware type: 0=SBC, 1=WSS");
603 MODULE_PARM(iobase, "i");
604 MODULE_PARM_DESC(iobase, "io base address");
605 MODULE_PARM(irq, "i");
606 MODULE_PARM_DESC(irq, "interrupt number");
607 MODULE_PARM(dma, "i");
608 MODULE_PARM_DESC(dma, "dma number (>=4 for SB16/32/64/etc, <=3 for the rest)");
609 MODULE_PARM(serio, "i");
610 MODULE_PARM_DESC(serio, "address of serial port to output PTT");
611 MODULE_PARM(pario, "i");
612 MODULE_PARM_DESC(pario, "address of parial port to output PTT");
613 MODULE_PARM(midiio, "i");
614 MODULE_PARM_DESC(midiio, "address of midi (MPU401) port to output PTT");
616 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
617 MODULE_DESCRIPTION("HF FSK modem code");
619 /* these are the module parameters from refclock.c */
621 MODULE_PARM(scale_tvusec, "i");
622 MODULE_PARM_DESC(scale_tvusec, "Scaling value for the tv_usec field (can be obta
623 ined by refclock)");
625 #ifdef __i386__
626 MODULE_PARM(scale_rdtsc, "i");
627 MODULE_PARM_DESC(scale_rdtsc, "Scaling value for the rdtsc counter (can be obtai
628 ned by refclock)");
629 MODULE_PARM(rdtsc_ok, "i");
630 MODULE_PARM_DESC(rdtsc_ok, "Set to 0 to disable the use of the rdtsc instruction
632 #endif /* __i386__ */
634 #endif
636 __initfunc(int init_module(void))
638 int i;
640 printk(hfmodem_drvinfo);
641 memset(hfmodem_state, 0, sizeof(hfmodem_state));
642 memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache));
643 hfmodem_state[0].io.base_addr = iobase;
644 hfmodem_state[0].io.irq = irq;
645 hfmodem_state[0].io.dma = dma;
646 hfmodem_state[0].ptt_out.seriobase = serio;
647 hfmodem_state[0].ptt_out.pariobase = pario;
648 hfmodem_state[0].ptt_out.midiiobase = midiio;
649 hfmodem_refclock_probe();
650 output_check(&hfmodem_state[0]);
651 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
652 if (hw)
653 i = hfmodem_wssprobe(&hfmodem_state[0]);
654 else
655 i = hfmodem_sbcprobe(&hfmodem_state[0]);
656 #else
657 i = -EINVAL;
658 #ifdef CONFIG_HFMODEM_WSS
659 i = hfmodem_wssprobe(&hfmodem_state[0]);
660 #endif
661 #ifdef CONFIG_HFMODEM_SBC
662 i = hfmodem_sbcprobe(&hfmodem_state[0]);
663 #endif
664 #endif
665 if (i)
666 return i;
667 if ((i = misc_register(&hfmodem_device))) {
668 printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname);
669 return i;
671 return 0;
674 void cleanup_module(void)
676 struct hfmodem_state *dev = &hfmodem_state[0];
678 if (dev->ptt_out.pariobase > 0)
679 parport_unregister_device(dev->ptt_out.pardev);
680 misc_deregister(&hfmodem_device);
683 #else /* MODULE */
684 /* --------------------------------------------------------------------- */
686 static int hw = 0;
688 __initfunc(void hfmodem_setup(char *str, int *ints))
690 if (ints[0] < 7) {
691 printk(KERN_WARNING "%s: setup: too few parameters\n", hfmodem_drvname);
692 return;
694 memset(hfmodem_state, 0, sizeof(hfmodem_state));
695 memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache));
696 hw = ints[1];
697 hfmodem_state[0].io.base_addr = ints[2];
698 hfmodem_state[0].io.irq = ints[3];
699 hfmodem_state[0].io.dma = ints[4];
700 if (ints[0] >= 8)
701 hfmodem_state[0].ptt_out.seriobase = ints[5];
702 if (ints[0] >= 9)
703 hfmodem_state[0].ptt_out.pariobase = ints[6];
704 if (ints[0] >= 10)
705 hfmodem_state[0].ptt_out.midiiobase = ints[7];
706 hfmodem_refclock_setscale(ints[ints[0]-2], ints[ints[0]-1], ints[ints[0]]);
709 __initfunc(void hfmodem_init(void))
711 int i;
713 printk(hfmodem_drvinfo);
714 hfmodem_refclock_probe();
715 output_check(&hfmodem_state[0]);
716 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
717 if (hw)
718 i = hfmodem_wssprobe(&hfmodem_state[0]);
719 else
720 i = hfmodem_sbcprobe(&hfmodem_state[0]);
721 #else
722 i = -EINVAL;
723 #ifdef CONFIG_HFMODEM_WSS
724 i = hfmodem_wssprobe(&hfmodem_state[0]);
725 #endif
726 #ifdef CONFIG_HFMODEM_SBC
727 i = hfmodem_sbcprobe(&hfmodem_state[0]);
728 #endif
729 #endif
730 if (i) {
731 printk(KERN_ERR "%s: soundcard probe failed\n", hfmodem_drvname);
732 return;
734 if ((i = misc_register(&hfmodem_device))) {
735 printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname);
736 return;
740 /* --------------------------------------------------------------------- */
741 #endif /* MODULE */