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 + -
显示快捷键?