1 /*****************************************************************************/
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)
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>
46 #include <asm/segment.h>
47 #include <asm/system.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.
60 #include <linux/version.h>
62 #if LINUX_VERSION_CODE >= 0x20100
63 #include <asm/uaccess.h>
65 #include <asm/segment.h>
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
);
79 memcpy_fromfs(to
, from
, n
);
83 extern inline int copy_to_user(void *to
, const void *from
, unsigned long n
)
85 int i
= verify_area(VERIFY_WRITE
, to
, n
);
88 memcpy_tofs(to
, from
, n
);
93 #if LINUX_VERSION_CODE >= 0x20123
94 #include <linux/init.h>
98 #define __initfunc(x) x
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)
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
151 /* ---------------------------------------------------------------------- */
153 static int parptt_preempt(void *handle
)
155 /* we cannot relinquish the port in the middle of an operation */
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
)
179 if (!(dev
->ptt_out
.pardev
= parport_register_device(pp
, hfmodem_drvname
, parptt_preempt
, parptt_wakeup
,
180 NULL
, PARPORT_DEV_LURK
, dev
)))
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
;
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
));
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))
224 /* --------------------------------------------------------------------- */
226 __initfunc(static int check_midi(unsigned int iobase
))
228 unsigned long timeout
;
232 if (iobase
<= 0 || iobase
> 0x1000-MIDI_EXTENT
)
234 if (check_region(iobase
, MIDI_EXTENT
))
236 timeout
= jiffies
+ (HZ
/ 100);
237 while (inb(MIDI_STATUS(iobase
)) & MIDI_WRITE_EMPTY
)
238 if ((signed)(jiffies
- timeout
) > 0)
242 outb(0xff, MIDI_DATA(iobase
));
243 b
= inb(MIDI_STATUS(iobase
));
244 restore_flags(flags
);
245 if (!(b
& MIDI_WRITE_EMPTY
))
247 while (inb(MIDI_STATUS(iobase
)) & MIDI_WRITE_EMPTY
)
248 if ((signed)(jiffies
- timeout
) > 0)
253 /* --------------------------------------------------------------------- */
255 static void output_status(struct hfmodem_state
*dev
, int 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
]);
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
);
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
);
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 */
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
);
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
;
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
)
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
;
382 unsigned int curfrag
, nfrags
;
384 hfmodem_time_t l1time
;
386 dmaptr
= dev
->scops
->intack(dev
);
387 l1time
= hfmodem_refclock_current(dev
, ((SIZE
+dmaptr
-dev
->dma
.last_dmaptr
) % SIZE
) *
389 curfrag
= (dev
->dma
.last_dmaptr
= dmaptr
) / HFMODEM_FRAGSAMPLES
;
390 l1time
-= INC_SAMPLE
* (SIZE
+dmaptr
-dev
->dma
.fragptr
*HFMODEM_FRAGSAMPLES
) % SIZE
;
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
);
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
)
406 memcpy(dev
->sbuf
.kptr
, s
, i
* sizeof(s
[0]));
410 hfmodem_input_samples(dev
, l1time
, INC_SAMPLE
, s
);
411 l1time
+= INC_FRAGMENT
;
413 if (dev
->dma
.fragptr
>= HFMODEM_NUMFRAGS
)
414 dev
->dma
.fragptr
= 0;
419 if (hfmodem_next_tx_event(dev
, l1time
) > (long)INC_FRAGMENT
/2)
424 output_status(dev
, 1);
425 dev
->scops
->prepare_output(dev
);
426 dev
->dma
.last_dmaptr
= 0;
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
);
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)
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 */
479 /* --------------------------------------------------------------------- */
481 static int hfmodem_close(struct inode
*inode
, struct file
*file
)
483 struct hfmodem_state
*dev
= &hfmodem_state
[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;
505 /* --------------------------------------------------------------------- */
507 static int hfmodem_open(struct inode
*inode
, struct file
*file
)
509 struct hfmodem_state
*dev
= &hfmodem_state
[0];
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;
526 if (!(dev
->dma
.buf
= kmalloc(HFMODEM_FRAGSIZE
* (HFMODEM_NUMFRAGS
+HFMODEM_EXCESSFRAGS
), GFP_KERNEL
| GFP_DMA
)))
531 if (request_dma(dev
->io
.dma
, hfmodem_drvname
)) {
532 kfree_s(dev
->dma
.buf
, HFMODEM_FRAGSIZE
* (HFMODEM_NUMFRAGS
+HFMODEM_EXCESSFRAGS
));
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
));
540 request_region(dev
->io
.base_addr
, dev
->scops
->extent
, hfmodem_drvname
);
545 hfmodem_refclock_init(dev
);
547 dev
->scops
->init(dev
);
548 dev
->scops
->prepare_input(dev
);
549 dev
->scops
->trigger_input(dev
);
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 */
563 hfmodem_select
, /* hfmodem_select */
565 hfmodem_ioctl
, /* hfmodem_ioctl */
566 NULL
, /* hfmodem_mmap */
567 hfmodem_open
, /* hfmodem_open */
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 /* --------------------------------------------------------------------- */
587 * Command line parameters
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
626 MODULE_PARM(scale_rdtsc
, "i");
627 MODULE_PARM_DESC(scale_rdtsc
, "Scaling value for the rdtsc counter (can be obtai
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__ */
636 __initfunc(int init_module(void))
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)
653 i
= hfmodem_wssprobe(&hfmodem_state
[0]);
655 i
= hfmodem_sbcprobe(&hfmodem_state
[0]);
658 #ifdef CONFIG_HFMODEM_WSS
659 i
= hfmodem_wssprobe(&hfmodem_state
[0]);
661 #ifdef CONFIG_HFMODEM_SBC
662 i
= hfmodem_sbcprobe(&hfmodem_state
[0]);
667 if ((i
= misc_register(&hfmodem_device
))) {
668 printk(KERN_ERR
"%s: cannot register misc device\n", hfmodem_drvname
);
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
);
684 /* --------------------------------------------------------------------- */
688 __initfunc(void hfmodem_setup(char *str
, int *ints
))
691 printk(KERN_WARNING
"%s: setup: too few parameters\n", hfmodem_drvname
);
694 memset(hfmodem_state
, 0, sizeof(hfmodem_state
));
695 memset(hfmodem_correlator_cache
, 0, sizeof(hfmodem_correlator_cache
));
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];
701 hfmodem_state
[0].ptt_out
.seriobase
= ints
[5];
703 hfmodem_state
[0].ptt_out
.pariobase
= ints
[6];
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))
713 printk(hfmodem_drvinfo
);
714 hfmodem_refclock_probe();
715 output_check(&hfmodem_state
[0]);
716 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
718 i
= hfmodem_wssprobe(&hfmodem_state
[0]);
720 i
= hfmodem_sbcprobe(&hfmodem_state
[0]);
723 #ifdef CONFIG_HFMODEM_WSS
724 i
= hfmodem_wssprobe(&hfmodem_state
[0]);
726 #ifdef CONFIG_HFMODEM_SBC
727 i
= hfmodem_sbcprobe(&hfmodem_state
[0]);
731 printk(KERN_ERR
"%s: soundcard probe failed\n", hfmodem_drvname
);
734 if ((i
= misc_register(&hfmodem_device
))) {
735 printk(KERN_ERR
"%s: cannot register misc device\n", hfmodem_drvname
);
740 /* --------------------------------------------------------------------- */