main.c
来自「powerpc内核mpc8241linux系统下char驱动程序」· C语言 代码 · 共 734 行 · 第 1/2 页
C
734 行
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 >= 0x20115MODULE_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 obtained by refclock)");#ifdef __i386__MODULE_PARM(scale_rdtsc, "i");MODULE_PARM_DESC(scale_rdtsc, "Scaling value for the rdtsc counter (can be obtained 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__initfunc(int 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; 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;__initfunc(void 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]]);}__initfunc(void hfmodem_init(void)){ int i; printk(hfmodem_drvinfo); 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 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?