⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************//* *      main.c  --  Linux soundcard HF FSK driver. * *      Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch) *        Swiss Federal Institute of Technology (ETH), Electronics Lab * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. * *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. * *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  Command line options (insmod command line) * *  History: *   0.1  15.04.97  Adapted from baycom.c and made network driver interface *   0.2  05.07.97  All floating point stuff thrown out due to Linus' rantings :) * *//*****************************************************************************/      #include <linux/config.h> /* for CONFIG_HFMODEM_WSS and CONFIG_HFMODEM_SBC */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/malloc.h>#include <linux/errno.h>#include <linux/miscdevice.h>#include <linux/ioport.h>#include <linux/hfmodem.h>#include <asm/io.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/dma.h>/* --------------------------------------------------------------------- *//* * currently this module is supposed to support both module styles, i.e. * the old one present up to about 2.1.9, and the new one functioning * starting with 2.1.21. The reason is I have a kit allowing to compile * this module also under 2.0.x which was requested by several people. * This will go in 2.2 */#include <linux/version.h>#if LINUX_VERSION_CODE >= 0x20100#include <asm/uaccess.h>#else#include <asm/segment.h>#include <linux/mm.h>#undef put_user#undef get_user#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })extern inline int copy_from_user(void *to, const void *from, unsigned long n){        int i = verify_area(VERIFY_READ, from, n);        if (i)                return i;        memcpy_fromfs(to, from, n);        return 0;}extern inline int copy_to_user(void *to, const void *from, unsigned long n){        int i = verify_area(VERIFY_WRITE, to, n);        if (i)                return i;        memcpy_tofs(to, from, n);        return 0;}#endif#if LINUX_VERSION_CODE >= 0x20123#include <linux/init.h>#else#define __init#define __initdata#define __initfunc(x) x#endif/* --------------------------------------------------------------------- *//*static*/ const char hfmodem_drvname[] = "hfmodem";static const char hfmodem_drvinfo[] = KERN_INFO "hfmodem: (C) 1997 Thomas Sailer, HB9JNX/AE4WA\n"KERN_INFO "hfmodem: version 0.2 compiled " __TIME__ " " __DATE__ "\n";/* --------------------------------------------------------------------- *//* * currently we support only one device */struct hfmodem_state hfmodem_state[NR_DEVICE];/* --------------------------------------------------------------------- *//* * ===================== port checking routines ======================== */#define UART_RBR(iobase) (iobase+0)#define UART_THR(iobase) (iobase+0)#define UART_IER(iobase) (iobase+1)#define UART_IIR(iobase) (iobase+2)#define UART_FCR(iobase) (iobase+2)#define UART_LCR(iobase) (iobase+3)#define UART_MCR(iobase) (iobase+4)#define UART_LSR(iobase) (iobase+5)#define UART_MSR(iobase) (iobase+6)#define UART_SCR(iobase) (iobase+7)#define UART_DLL(iobase) (iobase+0)#define UART_DLM(iobase) (iobase+1)#define SER_EXTENT 8#define LPT_DATA(iobase)    (iobase+0)#define LPT_STATUS(iobase)  (iobase+1)#define LPT_CONTROL(iobase) (iobase+2)#define LPT_IRQ_ENABLE      0x10#define MIDI_DATA(iobase)     (iobase)#define MIDI_STATUS(iobase)   (iobase+1)#define MIDI_READ_FULL 0x80   /* attention: negative logic!! */#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */#define MIDI_EXTENT 2#define SP_SER  1#define SP_PAR  2#define SP_MIDI 4/* --------------------------------------------------------------------- */static void parptt_wakeup(void *handle){        struct hfmodem_state *dev = (struct hfmodem_state *)handle;	printk(KERN_DEBUG "%s: parptt: why am I being woken up?\n", hfmodem_drvname);	if (!parport_claim(dev->ptt_out.pardev))		printk(KERN_DEBUG "%s: parptt: I'm broken.\n", hfmodem_drvname);}/* --------------------------------------------------------------------- */__initfunc(static int check_lpt(struct hfmodem_state *dev, unsigned int iobase)){	struct parport *pp = parport_enumerate();	while (pp && pp->base != iobase)		pp = pp->next;	if (!pp)		return 0;	if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, NULL, parptt_wakeup, 							    NULL, PARPORT_DEV_EXCL, dev)))		return 0;	return 1;}/* --------------------------------------------------------------------- */enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A };static const char *uart_str[] __initdata = { "unknown", "8250", "16450", "16550", "16550A" };__initfunc(static enum uart check_uart(unsigned int iobase)){        unsigned char b1,b2,b3;        enum uart u;        enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };        if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)                return c_uart_unknown;        if (check_region(iobase, SER_EXTENT))                return c_uart_unknown;        b1 = inb(UART_MCR(iobase));        outb(b1 | 0x10, UART_MCR(iobase));      /* loopback mode */        b2 = inb(UART_MSR(iobase));        outb(0x1a, UART_MCR(iobase));        b3 = inb(UART_MSR(iobase)) & 0xf0;        outb(b1, UART_MCR(iobase));        /* restore old values */        outb(b2, UART_MSR(iobase));        if (b3 != 0x90)                return c_uart_unknown;        inb(UART_RBR(iobase));        inb(UART_RBR(iobase));        outb(0x01, UART_FCR(iobase));           /* enable FIFOs */        u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];        if (u == c_uart_16450) {                outb(0x5a, UART_SCR(iobase));                b1 = inb(UART_SCR(iobase));                outb(0xa5, UART_SCR(iobase));                b2 = inb(UART_SCR(iobase));                if ((b1 != 0x5a) || (b2 != 0xa5))                        u = c_uart_8250;        }        return u;}/* --------------------------------------------------------------------- */__initfunc(static int check_midi(unsigned int iobase)){        unsigned long timeout;        unsigned long flags;        unsigned char b;        if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT)                return 0;        if (check_region(iobase, MIDI_EXTENT))                return 0;        timeout = jiffies + (HZ / 100);        while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)                if ((signed)(jiffies - timeout) > 0)                        return 0;        save_flags(flags);        cli();        outb(0xff, MIDI_DATA(iobase));        b = inb(MIDI_STATUS(iobase));        restore_flags(flags);        if (!(b & MIDI_WRITE_EMPTY))                return 0;        while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)                if ((signed)(jiffies - timeout) > 0)                        return 0;        return 1;}/* --------------------------------------------------------------------- */static void output_status(struct hfmodem_state *dev, int ptt){        int dcd = 0;	ptt = !!ptt;        if (dev->ptt_out.flags & SP_SER) {                outb(dcd | (ptt << 1), UART_MCR(dev->ptt_out.seriobase));                outb(0x40 & (-ptt), UART_LCR(dev->ptt_out.seriobase));        }        if (dev->ptt_out.flags & SP_PAR) {                outb(ptt | (dcd << 1), LPT_DATA(dev->ptt_out.pariobase));        }        if (dev->ptt_out.flags & SP_MIDI && ptt) {                outb(0, MIDI_DATA(dev->ptt_out.midiiobase));        }}/* --------------------------------------------------------------------- */__initfunc(static void output_check(struct hfmodem_state *dev)){        enum uart u = c_uart_unknown;        if (((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown)		printk(KERN_INFO "%s: PTT output: uart found at address 0x%x type %s\n",		       hfmodem_drvname, dev->ptt_out.seriobase, uart_str[u]);	else {		if (dev->ptt_out.seriobase > 0)			printk(KERN_WARNING "%s: PTT output: no uart found at address 0x%x\n",			       hfmodem_drvname, dev->ptt_out.seriobase);		dev->ptt_out.seriobase = 0;	}        if (check_lpt(dev, dev->ptt_out.pariobase)) 		printk(KERN_INFO "%s: PTT output: parallel port found at address 0x%x\n",		       hfmodem_drvname, dev->ptt_out.pariobase);	else {		if (dev->ptt_out.pariobase > 0)			printk(KERN_WARNING "%s: PTT output: no parallel port found at address 0x%x\n",			       hfmodem_drvname, dev->ptt_out.pariobase);		dev->ptt_out.pariobase = 0;		dev->ptt_out.pardev = NULL;	}	if (dev->ptt_out.midiiobase > 0 && dev->ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&            check_midi(dev->ptt_out.midiiobase))		printk(KERN_INFO "%s: PTT output: midi port found at address 0x%x\n",		       hfmodem_drvname, dev->ptt_out.midiiobase);	else {		if (dev->ptt_out.midiiobase > 0)			printk(KERN_WARNING "%s: PTT output: no midi port found at address 0x%x\n",			       hfmodem_drvname, dev->ptt_out.midiiobase);		dev->ptt_out.midiiobase = 0;	}}/* --------------------------------------------------------------------- */static void output_open(struct hfmodem_state *dev){        dev->ptt_out.flags = 0;        if (dev->ptt_out.seriobase > 0) {		if (!check_region(dev->ptt_out.seriobase, SER_EXTENT)) {			request_region(dev->ptt_out.seriobase, SER_EXTENT, "hfmodem ser ptt");			dev->ptt_out.flags |= SP_SER;			outb(0, UART_IER(dev->ptt_out.seriobase));			/* 5 bits, 1 stop, no parity, no break, Div latch access */			outb(0x80, UART_LCR(dev->ptt_out.seriobase));			outb(0, UART_DLM(dev->ptt_out.seriobase));			outb(1, UART_DLL(dev->ptt_out.seriobase)); /* as fast as possible */			/* LCR and MCR set by output_status */		} else			printk(KERN_WARNING "%s: PTT output: serial port at 0x%x busy\n",			       hfmodem_drvname, dev->ptt_out.seriobase);	}        if (dev->ptt_out.pariobase > 0) {		if (parport_claim(dev->ptt_out.pardev)) 			printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n",			       hfmodem_drvname, dev->ptt_out.pariobase);		else 			dev->ptt_out.flags |= SP_PAR;	}        if (dev->ptt_out.midiiobase > 0) {		if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) {			request_region(dev->ptt_out.midiiobase, MIDI_EXTENT, "hfmodem midi ptt");			dev->ptt_out.flags |= SP_MIDI;		} else			printk(KERN_WARNING "%s: PTT output: midi port at 0x%x busy\n",			       hfmodem_drvname, dev->ptt_out.midiiobase);	}	output_status(dev, 0);        printk(KERN_INFO "%s: PTT output:", hfmodem_drvname);        if (dev->ptt_out.flags & SP_SER)                printk(" serial interface at 0x%x", dev->ptt_out.seriobase);        if (dev->ptt_out.flags & SP_PAR)                printk(" parallel interface at 0x%x", dev->ptt_out.pariobase);        if (dev->ptt_out.flags & SP_MIDI)                printk(" mpu401 (midi) interface at 0x%x", dev->ptt_out.midiiobase);        if (!dev->ptt_out.flags)                printk(" none");        printk("\n");}/* --------------------------------------------------------------------- */static void output_close(struct hfmodem_state *dev){        /* release regions used for PTT output */        output_status(dev, 0);        if (dev->ptt_out.flags & SP_SER)                release_region(dev->ptt_out.seriobase, SER_EXTENT);        if (dev->ptt_out.flags & SP_PAR)		parport_release(dev->ptt_out.pardev);        if (dev->ptt_out.flags & SP_MIDI)                release_region(dev->ptt_out.midiiobase, MIDI_EXTENT);        dev->ptt_out.flags = 0;}/* --------------------------------------------------------------------- */#define INC_SAMPLE   (1000000/HFMODEM_SRATE)#define INC_FRAGMENT (HFMODEM_FRAGSAMPLES*1000000/HFMODEM_SRATE)#define SIZE         (HFMODEM_FRAGSAMPLES*HFMODEM_NUMFRAGS)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -