00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <linux/config.h>
00035 #include <linux/module.h>
00036
00037 #include <linux/kernel.h>
00038 #include <linux/sched.h>
00039 #include <linux/malloc.h>
00040 #include <linux/errno.h>
00041 #include <linux/miscdevice.h>
00042 #include <linux/ioport.h>
00043 #include <linux/hfmodem.h>
00044
00045 #include <asm/io.h>
00046 #include <asm/segment.h>
00047 #include <asm/system.h>
00048 #include <asm/irq.h>
00049 #include <asm/dma.h>
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include <linux/version.h>
00061
00062 #if LINUX_VERSION_CODE >= 0x20100
00063 #include <asm/uaccess.h>
00064 #else
00065 #include <asm/segment.h>
00066 #include <linux/mm.h>
00067
00068 #undef put_user
00069 #undef get_user
00070
00071 #define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
00072 #define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
00073
00074 extern inline int copy_from_user(void *to, const void *from, unsigned long n)
00075 {
00076 int i = verify_area(VERIFY_READ, from, n);
00077 if (i)
00078 return i;
00079 memcpy_fromfs(to, from, n);
00080 return 0;
00081 }
00082
00083 extern inline int copy_to_user(void *to, const void *from, unsigned long n)
00084 {
00085 int i = verify_area(VERIFY_WRITE, to, n);
00086 if (i)
00087 return i;
00088 memcpy_tofs(to, from, n);
00089 return 0;
00090 }
00091 #endif
00092
00093 #if LINUX_VERSION_CODE >= 0x20123
00094 #include <linux/init.h>
00095 #else
00096 #define __init
00097 #define __initdata
00098 #define __initfunc(x) x
00099 #endif
00100
00101
00102
00103 const char hfmodem_drvname[] = "hfmodem";
00104 static const char hfmodem_drvinfo[] = KERN_INFO "hfmodem: (C) 1997 Thomas Sailer, HB9JNX/AE4WA\n"
00105 KERN_INFO "hfmodem: version 0.2 compiled " __TIME__ " " __DATE__ "\n";
00106
00107
00108
00109
00110
00111
00112 struct hfmodem_state hfmodem_state[NR_DEVICE];
00113
00114
00115
00116
00117
00118
00119
00120 #define UART_RBR(iobase) (iobase+0)
00121 #define UART_THR(iobase) (iobase+0)
00122 #define UART_IER(iobase) (iobase+1)
00123 #define UART_IIR(iobase) (iobase+2)
00124 #define UART_FCR(iobase) (iobase+2)
00125 #define UART_LCR(iobase) (iobase+3)
00126 #define UART_MCR(iobase) (iobase+4)
00127 #define UART_LSR(iobase) (iobase+5)
00128 #define UART_MSR(iobase) (iobase+6)
00129 #define UART_SCR(iobase) (iobase+7)
00130 #define UART_DLL(iobase) (iobase+0)
00131 #define UART_DLM(iobase) (iobase+1)
00132
00133 #define SER_EXTENT 8
00134
00135 #define LPT_DATA(iobase) (iobase+0)
00136 #define LPT_STATUS(iobase) (iobase+1)
00137 #define LPT_CONTROL(iobase) (iobase+2)
00138 #define LPT_IRQ_ENABLE 0x10
00139
00140 #define MIDI_DATA(iobase) (iobase)
00141 #define MIDI_STATUS(iobase) (iobase+1)
00142 #define MIDI_READ_FULL 0x80
00143 #define MIDI_WRITE_EMPTY 0x40
00144
00145 #define MIDI_EXTENT 2
00146
00147 #define SP_SER 1
00148 #define SP_PAR 2
00149 #define SP_MIDI 4
00150
00151
00152
00153 static void parptt_wakeup(void *handle)
00154 {
00155 struct hfmodem_state *dev = (struct hfmodem_state *)handle;
00156
00157 printk(KERN_DEBUG "%s: parptt: why am I being woken up?\n", hfmodem_drvname);
00158 if (!parport_claim(dev->ptt_out.pardev))
00159 printk(KERN_DEBUG "%s: parptt: I'm broken.\n", hfmodem_drvname);
00160 }
00161
00162
00163 __initfunc(static int check_lpt(struct hfmodem_state *dev, unsigned int iobase))
00164 {
00165 struct parport *pp = parport_enumerate();
00166
00167 while (pp && pp->base != iobase)
00168 pp = pp->next;
00169 if (!pp)
00170 return 0;
00171 if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, NULL, parptt_wakeup,
00172 NULL, PARPORT_DEV_EXCL, dev)))
00173 return 0;
00174 return 1;
00175 }
00176
00177
00178
00179 enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A };
00180 static const char *uart_str[] __initdata = { "unknown", "8250", "16450", "16550", "16550A" };
00181
00182 __initfunc(static enum uart check_uart(unsigned int iobase))
00183 {
00184 unsigned char b1,b2,b3;
00185 enum uart u;
00186 enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
00187
00188 if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)
00189 return c_uart_unknown;
00190 if (check_region(iobase, SER_EXTENT))
00191 return c_uart_unknown;
00192 b1 = inb(UART_MCR(iobase));
00193 outb(b1 | 0x10, UART_MCR(iobase));
00194 b2 = inb(UART_MSR(iobase));
00195 outb(0x1a, UART_MCR(iobase));
00196 b3 = inb(UART_MSR(iobase)) & 0xf0;
00197 outb(b1, UART_MCR(iobase));
00198 outb(b2, UART_MSR(iobase));
00199 if (b3 != 0x90)
00200 return c_uart_unknown;
00201 inb(UART_RBR(iobase));
00202 inb(UART_RBR(iobase));
00203 outb(0x01, UART_FCR(iobase));
00204 u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];
00205 if (u == c_uart_16450) {
00206 outb(0x5a, UART_SCR(iobase));
00207 b1 = inb(UART_SCR(iobase));
00208 outb(0xa5, UART_SCR(iobase));
00209 b2 = inb(UART_SCR(iobase));
00210 if ((b1 != 0x5a) || (b2 != 0xa5))
00211 u = c_uart_8250;
00212 }
00213 return u;
00214 }
00215
00216
00217
00218 __initfunc(static int check_midi(unsigned int iobase))
00219 {
00220 unsigned long timeout;
00221 unsigned long flags;
00222 unsigned char b;
00223
00224 if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT)
00225 return 0;
00226 if (check_region(iobase, MIDI_EXTENT))
00227 return 0;
00228 timeout = jiffies + (HZ / 100);
00229 while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
00230 if ((signed)(jiffies - timeout) > 0)
00231 return 0;
00232 save_flags(flags);
00233 cli();
00234 outb(0xff, MIDI_DATA(iobase));
00235 b = inb(MIDI_STATUS(iobase));
00236 restore_flags(flags);
00237 if (!(b & MIDI_WRITE_EMPTY))
00238 return 0;
00239 while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
00240 if ((signed)(jiffies - timeout) > 0)
00241 return 0;
00242 return 1;
00243 }
00244
00245
00246
00247 static void output_status(struct hfmodem_state *dev, int ptt)
00248 {
00249 int dcd = 0;
00250
00251 ptt = !!ptt;
00252 if (dev->ptt_out.flags & SP_SER) {
00253 outb(dcd | (ptt << 1), UART_MCR(dev->ptt_out.seriobase));
00254 outb(0x40 & (-ptt), UART_LCR(dev->ptt_out.seriobase));
00255 }
00256 if (dev->ptt_out.flags & SP_PAR) {
00257 outb(ptt | (dcd << 1), LPT_DATA(dev->ptt_out.pariobase));
00258 }
00259 if (dev->ptt_out.flags & SP_MIDI && ptt) {
00260 outb(0, MIDI_DATA(dev->ptt_out.midiiobase));
00261 }
00262 }
00263
00264
00265
00266 __initfunc(static void output_check(struct hfmodem_state *dev))
00267 {
00268 enum uart u = c_uart_unknown;
00269
00270 if (((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown)
00271 printk(KERN_INFO "%s: PTT output: uart found at address 0x%x type %s\n",
00272 hfmodem_drvname, dev->ptt_out.seriobase, uart_str[u]);
00273 else {
00274 if (dev->ptt_out.seriobase > 0)
00275 printk(KERN_WARNING "%s: PTT output: no uart found at address 0x%x\n",
00276 hfmodem_drvname, dev->ptt_out.seriobase);
00277 dev->ptt_out.seriobase = 0;
00278 }
00279 if (check_lpt(dev, dev->ptt_out.pariobase))
00280 printk(KERN_INFO "%s: PTT output: parallel port found at address 0x%x\n",
00281 hfmodem_drvname, dev->ptt_out.pariobase);
00282 else {
00283 if (dev->ptt_out.pariobase > 0)
00284 printk(KERN_WARNING "%s: PTT output: no parallel port found at address 0x%x\n",
00285 hfmodem_drvname, dev->ptt_out.pariobase);
00286 dev->ptt_out.pariobase = 0;
00287 dev->ptt_out.pardev = NULL;
00288 }
00289 if (dev->ptt_out.midiiobase > 0 && dev->ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&
00290 check_midi(dev->ptt_out.midiiobase))
00291 printk(KERN_INFO "%s: PTT output: midi port found at address 0x%x\n",
00292 hfmodem_drvname, dev->ptt_out.midiiobase);
00293 else {
00294 if (dev->ptt_out.midiiobase > 0)
00295 printk(KERN_WARNING "%s: PTT output: no midi port found at address 0x%x\n",
00296 hfmodem_drvname, dev->ptt_out.midiiobase);
00297 dev->ptt_out.midiiobase = 0;
00298 }
00299 }
00300
00301
00302
00303 static void output_open(struct hfmodem_state *dev)
00304 {
00305 dev->ptt_out.flags = 0;
00306 if (dev->ptt_out.seriobase > 0) {
00307 if (!check_region(dev->ptt_out.seriobase, SER_EXTENT)) {
00308 request_region(dev->ptt_out.seriobase, SER_EXTENT, "hfmodem ser ptt");
00309 dev->ptt_out.flags |= SP_SER;
00310 outb(0, UART_IER(dev->ptt_out.seriobase));
00311
00312 outb(0x80, UART_LCR(dev->ptt_out.seriobase));
00313 outb(0, UART_DLM(dev->ptt_out.seriobase));
00314 outb(1, UART_DLL(dev->ptt_out.seriobase));
00315
00316 } else
00317 printk(KERN_WARNING "%s: PTT output: serial port at 0x%x busy\n",
00318 hfmodem_drvname, dev->ptt_out.seriobase);
00319 }
00320 if (dev->ptt_out.pariobase > 0) {
00321 if (parport_claim(dev->ptt_out.pardev))
00322 printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n",
00323 hfmodem_drvname, dev->ptt_out.pariobase);
00324 else
00325 dev->ptt_out.flags |= SP_PAR;
00326 }
00327 if (dev->ptt_out.midiiobase > 0) {
00328 if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) {
00329 request_region(dev->ptt_out.midiiobase, MIDI_EXTENT, "hfmodem midi ptt");
00330 dev->ptt_out.flags |= SP_MIDI;
00331 } else
00332 printk(KERN_WARNING "%s: PTT output: midi port at 0x%x busy\n",
00333 hfmodem_drvname, dev->ptt_out.midiiobase);
00334 }
00335 output_status(dev, 0);
00336 printk(KERN_INFO "%s: PTT output:", hfmodem_drvname);
00337 if (dev->ptt_out.flags & SP_SER)
00338 printk(" serial interface at 0x%x", dev->ptt_out.seriobase);
00339 if (dev->ptt_out.flags & SP_PAR)
00340 printk(" parallel interface at 0x%x", dev->ptt_out.pariobase);
00341 if (dev->ptt_out.flags & SP_MIDI)
00342 printk(" mpu401 (midi) interface at 0x%x", dev->ptt_out.midiiobase);
00343 if (!dev->ptt_out.flags)
00344 printk(" none");
00345 printk("\n");
00346 }
00347
00348
00349
00350 static void output_close(struct hfmodem_state *dev)
00351 {
00352
00353 output_status(dev, 0);
00354 if (dev->ptt_out.flags & SP_SER)
00355 release_region(dev->ptt_out.seriobase, SER_EXTENT);
00356 if (dev->ptt_out.flags & SP_PAR)
00357 parport_release(dev->ptt_out.pardev);
00358 if (dev->ptt_out.flags & SP_MIDI)
00359 release_region(dev->ptt_out.midiiobase, MIDI_EXTENT);
00360 dev->ptt_out.flags = 0;
00361 }
00362
00363
00364
00365 #define INC_SAMPLE (1000000/HFMODEM_SRATE)
00366 #define INC_FRAGMENT (HFMODEM_FRAGSAMPLES*1000000/HFMODEM_SRATE)
00367 #define SIZE (HFMODEM_FRAGSAMPLES*HFMODEM_NUMFRAGS)
00368
00369 static void hfmodem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
00370 {
00371 struct hfmodem_state *dev = (struct hfmodem_state *)dev_id;
00372 unsigned int dmaptr;
00373 __s16 *s;
00374 unsigned int curfrag, nfrags;
00375 int i;
00376 hfmodem_time_t l1time;
00377
00378 dmaptr = dev->scops->intack(dev);
00379 l1time = hfmodem_refclock_current(dev, ((SIZE+dmaptr-dev->dma.last_dmaptr) % SIZE) *
00380 INC_SAMPLE, 1);
00381 curfrag = (dev->dma.last_dmaptr = dmaptr) / HFMODEM_FRAGSAMPLES;
00382 l1time -= INC_SAMPLE * (SIZE+dmaptr-dev->dma.fragptr*HFMODEM_FRAGSAMPLES) % SIZE;
00383 sti();
00384
00385
00386
00387 if (dev->dma.ptt_frames <= 0) {
00388 while (dev->dma.fragptr != curfrag) {
00389 if (dev->dma.fragptr < HFMODEM_EXCESSFRAGS) {
00390 s = dev->dma.buf + SIZE + HFMODEM_FRAGSAMPLES * dev->dma.fragptr;
00391 memcpy(s, s - SIZE, HFMODEM_FRAGSIZE);
00392 } else
00393 s = dev->dma.buf + HFMODEM_FRAGSAMPLES * dev->dma.fragptr;
00394 if (dev->sbuf.kbuf && dev->sbuf.kptr && dev->sbuf.rem > 0) {
00395 i = HFMODEM_FRAGSAMPLES;
00396 if (i > dev->sbuf.rem)
00397 i = dev->sbuf.rem;
00398 memcpy(dev->sbuf.kptr, s, i * sizeof(s[0]));
00399 dev->sbuf.rem -= i;
00400 dev->sbuf.kptr += i;
00401 }
00402 hfmodem_input_samples(dev, l1time, INC_SAMPLE, s);
00403 l1time += INC_FRAGMENT;
00404 dev->dma.fragptr++;
00405 if (dev->dma.fragptr >= HFMODEM_NUMFRAGS)
00406 dev->dma.fragptr = 0;
00407 }
00408
00409
00410
00411 if (hfmodem_next_tx_event(dev, l1time) > (long)INC_FRAGMENT/2)
00412 goto int_return;
00413
00414
00415
00416 output_status(dev, 1);
00417 dev->scops->prepare_output(dev);
00418 dev->dma.last_dmaptr = 0;
00419
00420
00421
00422 l1time = hfmodem_refclock_current(dev, 0, 0);
00423
00424
00425
00426 dev->dma.ptt_frames = 1;
00427 for (i = 0; i < 2 && i < HFMODEM_NUMFRAGS; i++)
00428 if (hfmodem_output_samples(dev, l1time+i*INC_FRAGMENT, INC_SAMPLE,
00429 dev->dma.buf+i*HFMODEM_FRAGSAMPLES))
00430 dev->dma.ptt_frames = i + 1;
00431 dev->dma.lastfrag = 0;
00432 dev->scops->trigger_output(dev);
00433
00434
00435
00436 hfmodem_finish_pending_rx_requests(dev);
00437 goto int_return;
00438 }
00439
00440
00441
00442 nfrags = HFMODEM_NUMFRAGS + curfrag - dev->dma.lastfrag;
00443 dev->dma.lastfrag = curfrag;
00444 if (nfrags >= HFMODEM_NUMFRAGS)
00445 nfrags -= HFMODEM_NUMFRAGS;
00446 dev->dma.ptt_frames -= nfrags;
00447 if (dev->dma.ptt_frames < 0)
00448 dev->dma.ptt_frames = 0;
00449 while (dev->dma.ptt_frames < HFMODEM_NUMFRAGS && dev->dma.ptt_frames < 4 &&
00450 hfmodem_output_samples(dev, l1time+dev->dma.ptt_frames*INC_FRAGMENT,
00451 INC_SAMPLE, dev->dma.buf + HFMODEM_FRAGSAMPLES *
00452 ((curfrag + dev->dma.ptt_frames) % HFMODEM_NUMFRAGS)))
00453 dev->dma.ptt_frames++;
00454 if (dev->dma.ptt_frames > 0)
00455 goto int_return;
00456
00457
00458
00459 output_status(dev, 0);
00460 dev->dma.last_dmaptr = 0;
00461 dev->dma.lastfrag = 0;
00462 dev->dma.fragptr = 0;
00463 dev->dma.ptt_frames = 0;
00464 dev->scops->prepare_input(dev);
00465 dev->scops->trigger_input(dev);
00466 hfmodem_refclock_current(dev, 0, 0);
00467 int_return:
00468 hfmodem_wakeup(dev);
00469 }
00470
00471
00472
00473 static int hfmodem_close(struct inode *inode, struct file *file)
00474 {
00475 struct hfmodem_state *dev = &hfmodem_state[0];
00476
00477 if (!dev->active)
00478 return -EPERM;
00479 dev->active = 0;
00480 dev->scops->stop(dev);
00481 free_irq(dev->io.irq, dev);
00482 disable_dma(dev->io.dma);
00483 free_dma(dev->io.dma);
00484 release_region(dev->io.base_addr, dev->scops->extent);
00485 kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS));
00486 hfmodem_clear_rq(dev);
00487 if (dev->sbuf.kbuf) {
00488 kfree_s(dev->sbuf.kbuf, dev->sbuf.size);
00489 dev->sbuf.kbuf = dev->sbuf.kptr = NULL;
00490 dev->sbuf.size = dev->sbuf.rem = 0;
00491 }
00492 output_close(dev);
00493 MOD_DEC_USE_COUNT;
00494 return 0;
00495 }
00496
00497
00498
00499 static int hfmodem_open(struct inode *inode, struct file *file)
00500 {
00501 struct hfmodem_state *dev = &hfmodem_state[0];
00502
00503 if (dev->active)
00504 return -EBUSY;
00505 if (!dev->scops)
00506 return -EPERM;
00507
00508
00509
00510 memset(&dev->l1, 0, sizeof(dev->l1));
00511 dev->dma.last_dmaptr = 0;
00512 dev->dma.lastfrag = 0;
00513 dev->dma.fragptr = 0;
00514 dev->dma.ptt_frames = 0;
00515
00516
00517
00518 if (!(dev->dma.buf = kmalloc(HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS), GFP_KERNEL | GFP_DMA)))
00519 return -ENOMEM;
00520
00521
00522
00523 if (request_dma(dev->io.dma, hfmodem_drvname)) {
00524 kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS));
00525 return -EBUSY;
00526 }
00527 if (request_irq(dev->io.irq, hfmodem_interrupt, SA_INTERRUPT, hfmodem_drvname, dev)) {
00528 free_dma(dev->io.dma);
00529 kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS));
00530 return -EBUSY;
00531 }
00532 request_region(dev->io.base_addr, dev->scops->extent, hfmodem_drvname);
00533
00534
00535 dev->active++;
00536 MOD_INC_USE_COUNT;
00537 hfmodem_refclock_init(dev);
00538 output_open(dev);
00539 dev->scops->init(dev);
00540 dev->scops->prepare_input(dev);
00541 dev->scops->trigger_input(dev);
00542 return 0;
00543 }
00544
00545
00546
00547 static struct file_operations hfmodem_fops = {
00548 NULL,
00549 NULL,
00550 NULL,
00551 NULL,
00552 #if LINUX_VERSION_CODE >= 0x20100
00553 hfmodem_poll,
00554 #else
00555 hfmodem_select,
00556 #endif
00557 hfmodem_ioctl,
00558 NULL,
00559 hfmodem_open,
00560 NULL,
00561 hfmodem_close,
00562 NULL,
00563 NULL,
00564 NULL,
00565 NULL
00566 };
00567
00568
00569
00570 static struct miscdevice hfmodem_device = {
00571 HFMODEM_MINOR, hfmodem_drvname, &hfmodem_fops
00572 };
00573
00574
00575
00576 #ifdef MODULE
00577
00578
00579
00580
00581
00582 static int hw = 0;
00583 static unsigned int iobase = 0x220;
00584 static unsigned int irq = 7;
00585 static unsigned int dma = 1;
00586
00587 static unsigned int serio = 0;
00588 static unsigned int pario = 0;
00589 static unsigned int midiio = 0;
00590
00591 #if LINUX_VERSION_CODE >= 0x20115
00592
00593 MODULE_PARM(hw, "i");
00594 MODULE_PARM_DESC(hw, "hardware type: 0=SBC, 1=WSS");
00595 MODULE_PARM(iobase, "i");
00596 MODULE_PARM_DESC(iobase, "io base address");
00597 MODULE_PARM(irq, "i");
00598 MODULE_PARM_DESC(irq, "interrupt number");
00599 MODULE_PARM(dma, "i");
00600 MODULE_PARM_DESC(dma, "dma number (>=4 for SB16/32/64/etc, <=3 for the rest)");
00601 MODULE_PARM(serio, "i");
00602 MODULE_PARM_DESC(serio, "address of serial port to output PTT");
00603 MODULE_PARM(pario, "i");
00604 MODULE_PARM_DESC(pario, "address of parallel port to output PTT");
00605 MODULE_PARM(midiio, "i");
00606 MODULE_PARM_DESC(midiio, "address of midi (MPU401) port to output PTT");
00607
00608 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
00609 MODULE_DESCRIPTION("HF FSK modem code");
00610
00611
00612
00613 MODULE_PARM(scale_tvusec, "i");
00614 MODULE_PARM_DESC(scale_tvusec, "Scaling value for the tv_usec field (can be obta
00615 ined by refclock)");
00616
00617 #ifdef __i386__
00618 MODULE_PARM(scale_rdtsc, "i");
00619 MODULE_PARM_DESC(scale_rdtsc, "Scaling value for the rdtsc counter (can be obtai
00620 ned by refclock)");
00621 MODULE_PARM(rdtsc_ok, "i");
00622 MODULE_PARM_DESC(rdtsc_ok, "Set to 0 to disable the use of the rdtsc instruction
00623 ");
00624 #endif
00625
00626 #endif
00627
00628 __initfunc(int init_module(void))
00629 {
00630 int i;
00631
00632 printk(hfmodem_drvinfo);
00633 memset(hfmodem_state, 0, sizeof(hfmodem_state));
00634 memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache));
00635 hfmodem_state[0].io.base_addr = iobase;
00636 hfmodem_state[0].io.irq = irq;
00637 hfmodem_state[0].io.dma = dma;
00638 hfmodem_state[0].ptt_out.seriobase = serio;
00639 hfmodem_state[0].ptt_out.pariobase = pario;
00640 hfmodem_state[0].ptt_out.midiiobase = midiio;
00641 hfmodem_refclock_probe();
00642 output_check(&hfmodem_state[0]);
00643 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
00644 if (hw)
00645 i = hfmodem_wssprobe(&hfmodem_state[0]);
00646 else
00647 i = hfmodem_sbcprobe(&hfmodem_state[0]);
00648 #else
00649 i = -EINVAL;
00650 #ifdef CONFIG_HFMODEM_WSS
00651 i = hfmodem_wssprobe(&hfmodem_state[0]);
00652 #endif
00653 #ifdef CONFIG_HFMODEM_SBC
00654 i = hfmodem_sbcprobe(&hfmodem_state[0]);
00655 #endif
00656 #endif
00657 if (i)
00658 return i;
00659 if ((i = misc_register(&hfmodem_device))) {
00660 printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname);
00661 return i;
00662 }
00663 return 0;
00664 }
00665
00666 void cleanup_module(void)
00667 {
00668 struct hfmodem_state *dev = &hfmodem_state[0];
00669
00670 if (dev->ptt_out.pariobase > 0)
00671 parport_unregister_device(dev->ptt_out.pardev);
00672 misc_deregister(&hfmodem_device);
00673 }
00674
00675 #else
00676
00677
00678 static int hw = 0;
00679
00680 __initfunc(void hfmodem_setup(char *str, int *ints))
00681 {
00682 if (ints[0] < 7) {
00683 printk(KERN_WARNING "%s: setup: too few parameters\n", hfmodem_drvname);
00684 return;
00685 }
00686 memset(hfmodem_state, 0, sizeof(hfmodem_state));
00687 memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache));
00688 hw = ints[1];
00689 hfmodem_state[0].io.base_addr = ints[2];
00690 hfmodem_state[0].io.irq = ints[3];
00691 hfmodem_state[0].io.dma = ints[4];
00692 if (ints[0] >= 8)
00693 hfmodem_state[0].ptt_out.seriobase = ints[5];
00694 if (ints[0] >= 9)
00695 hfmodem_state[0].ptt_out.pariobase = ints[6];
00696 if (ints[0] >= 10)
00697 hfmodem_state[0].ptt_out.midiiobase = ints[7];
00698 hfmodem_refclock_setscale(ints[ints[0]-2], ints[ints[0]-1], ints[ints[0]]);
00699 }
00700
00701 __initfunc(void hfmodem_init(void))
00702 {
00703 int i;
00704
00705 printk(hfmodem_drvinfo);
00706 hfmodem_refclock_probe();
00707 output_check(&hfmodem_state[0]);
00708 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
00709 if (hw)
00710 i = hfmodem_wssprobe(&hfmodem_state[0]);
00711 else
00712 i = hfmodem_sbcprobe(&hfmodem_state[0]);
00713 #else
00714 i = -EINVAL;
00715 #ifdef CONFIG_HFMODEM_WSS
00716 i = hfmodem_wssprobe(&hfmodem_state[0]);
00717 #endif
00718 #ifdef CONFIG_HFMODEM_SBC
00719 i = hfmodem_sbcprobe(&hfmodem_state[0]);
00720 #endif
00721 #endif
00722 if (i) {
00723 printk(KERN_ERR "%s: soundcard probe failed\n", hfmodem_drvname);
00724 return;
00725 }
00726 if ((i = misc_register(&hfmodem_device))) {
00727 printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname);
00728 return;
00729 }
00730 }
00731
00732
00733 #endif