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

📄 stallion.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
static void	stl_putchar(struct tty_struct *tty, unsigned char ch);static void	stl_flushchars(struct tty_struct *tty);static int	stl_writeroom(struct tty_struct *tty);static int	stl_charsinbuffer(struct tty_struct *tty);static int	stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);static void	stl_settermios(struct tty_struct *tty, struct termios *old);static void	stl_throttle(struct tty_struct *tty);static void	stl_unthrottle(struct tty_struct *tty);static void	stl_stop(struct tty_struct *tty);static void	stl_start(struct tty_struct *tty);static void	stl_flushbuffer(struct tty_struct *tty);static void	stl_breakctl(struct tty_struct *tty, int state);static void	stl_waituntilsent(struct tty_struct *tty, int timeout);static void	stl_sendxchar(struct tty_struct *tty, char ch);static void	stl_hangup(struct tty_struct *tty);static int	stl_memopen(struct inode *ip, struct file *fp);static int	stl_memclose(struct inode *ip, struct file *fp);static int	stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);static int	stl_portinfo(stlport_t *portp, int portnr, char *pos);static int	stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data);static int	stl_brdinit(stlbrd_t *brdp);static int	stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);static int	stl_mapirq(int irq, char *name);static void	stl_getserial(stlport_t *portp, struct serial_struct *sp);static int	stl_setserial(stlport_t *portp, struct serial_struct *sp);static int	stl_getbrdstats(combrd_t *bp);static int	stl_getportstats(stlport_t *portp, comstats_t *cp);static int	stl_clrportstats(stlport_t *portp, comstats_t *cp);static int	stl_getportstruct(unsigned long arg);static int	stl_getbrdstruct(unsigned long arg);static int	stl_waitcarrier(stlport_t *portp, struct file *filp);static void	stl_delay(int len);static void	stl_intr(int irq, void *dev_id, struct pt_regs *regs);static void	stl_eiointr(stlbrd_t *brdp);static void	stl_echatintr(stlbrd_t *brdp);static void	stl_echmcaintr(stlbrd_t *brdp);static void	stl_echpciintr(stlbrd_t *brdp);static void	stl_echpci64intr(stlbrd_t *brdp);static void	stl_offintr(void *private);static void	*stl_memalloc(int len);static stlbrd_t *stl_allocbrd(void);static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);static inline int	stl_initbrds(void);static inline int	stl_initeio(stlbrd_t *brdp);static inline int	stl_initech(stlbrd_t *brdp);static inline int	stl_getbrdnr(void);#ifdef	CONFIG_PCIstatic inline int	stl_findpcibrds(void);static inline int	stl_initpcibrd(int brdtype, struct pci_dev *devp);#endif/* *	CD1400 uart specific handling functions. */static void	stl_cd1400setreg(stlport_t *portp, int regnr, int value);static int	stl_cd1400getreg(stlport_t *portp, int regnr);static int	stl_cd1400updatereg(stlport_t *portp, int regnr, int value);static int	stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp);static void	stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);static void	stl_cd1400setport(stlport_t *portp, struct termios *tiosp);static int	stl_cd1400getsignals(stlport_t *portp);static void	stl_cd1400setsignals(stlport_t *portp, int dtr, int rts);static void	stl_cd1400ccrwait(stlport_t *portp);static void	stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx);static void	stl_cd1400startrxtx(stlport_t *portp, int rx, int tx);static void	stl_cd1400disableintrs(stlport_t *portp);static void	stl_cd1400sendbreak(stlport_t *portp, int len);static void	stl_cd1400flowctrl(stlport_t *portp, int state);static void	stl_cd1400sendflow(stlport_t *portp, int state);static void	stl_cd1400flush(stlport_t *portp);static int	stl_cd1400datastate(stlport_t *portp);static void	stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);static void	stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);static void	stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);static void	stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);static void	stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);static inline int	stl_cd1400breakisr(stlport_t *portp, int ioaddr);/* *	SC26198 uart specific handling functions. */static void	stl_sc26198setreg(stlport_t *portp, int regnr, int value);static int	stl_sc26198getreg(stlport_t *portp, int regnr);static int	stl_sc26198updatereg(stlport_t *portp, int regnr, int value);static int	stl_sc26198getglobreg(stlport_t *portp, int regnr);static int	stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp);static void	stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);static void	stl_sc26198setport(stlport_t *portp, struct termios *tiosp);static int	stl_sc26198getsignals(stlport_t *portp);static void	stl_sc26198setsignals(stlport_t *portp, int dtr, int rts);static void	stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx);static void	stl_sc26198startrxtx(stlport_t *portp, int rx, int tx);static void	stl_sc26198disableintrs(stlport_t *portp);static void	stl_sc26198sendbreak(stlport_t *portp, int len);static void	stl_sc26198flowctrl(stlport_t *portp, int state);static void	stl_sc26198sendflow(stlport_t *portp, int state);static void	stl_sc26198flush(stlport_t *portp);static int	stl_sc26198datastate(stlport_t *portp);static void	stl_sc26198wait(stlport_t *portp);static void	stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty);static void	stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase);static void	stl_sc26198txisr(stlport_t *port);static void	stl_sc26198rxisr(stlport_t *port, unsigned int iack);static void	stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch);static void	stl_sc26198rxbadchars(stlport_t *portp);static void	stl_sc26198otherisr(stlport_t *port, unsigned int iack);/*****************************************************************************//* *	Generic UART support structure. */typedef struct uart {	int	(*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp);	void	(*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);	void	(*setport)(stlport_t *portp, struct termios *tiosp);	int	(*getsignals)(stlport_t *portp);	void	(*setsignals)(stlport_t *portp, int dtr, int rts);	void	(*enablerxtx)(stlport_t *portp, int rx, int tx);	void	(*startrxtx)(stlport_t *portp, int rx, int tx);	void	(*disableintrs)(stlport_t *portp);	void	(*sendbreak)(stlport_t *portp, int len);	void	(*flowctrl)(stlport_t *portp, int state);	void	(*sendflow)(stlport_t *portp, int state);	void	(*flush)(stlport_t *portp);	int	(*datastate)(stlport_t *portp);	void	(*intr)(stlpanel_t *panelp, unsigned int iobase);} uart_t;/* *	Define some macros to make calling these functions nice and clean. */#define	stl_panelinit		(* ((uart_t *) panelp->uartp)->panelinit)#define	stl_portinit		(* ((uart_t *) portp->uartp)->portinit)#define	stl_setport		(* ((uart_t *) portp->uartp)->setport)#define	stl_getsignals		(* ((uart_t *) portp->uartp)->getsignals)#define	stl_setsignals		(* ((uart_t *) portp->uartp)->setsignals)#define	stl_enablerxtx		(* ((uart_t *) portp->uartp)->enablerxtx)#define	stl_startrxtx		(* ((uart_t *) portp->uartp)->startrxtx)#define	stl_disableintrs	(* ((uart_t *) portp->uartp)->disableintrs)#define	stl_sendbreak		(* ((uart_t *) portp->uartp)->sendbreak)#define	stl_flowctrl		(* ((uart_t *) portp->uartp)->flowctrl)#define	stl_sendflow		(* ((uart_t *) portp->uartp)->sendflow)#define	stl_flush		(* ((uart_t *) portp->uartp)->flush)#define	stl_datastate		(* ((uart_t *) portp->uartp)->datastate)/*****************************************************************************//* *	CD1400 UART specific data initialization. */static uart_t stl_cd1400uart = {	stl_cd1400panelinit,	stl_cd1400portinit,	stl_cd1400setport,	stl_cd1400getsignals,	stl_cd1400setsignals,	stl_cd1400enablerxtx,	stl_cd1400startrxtx,	stl_cd1400disableintrs,	stl_cd1400sendbreak,	stl_cd1400flowctrl,	stl_cd1400sendflow,	stl_cd1400flush,	stl_cd1400datastate,	stl_cd1400eiointr};/* *	Define the offsets within the register bank of a cd1400 based panel. *	These io address offsets are common to the EasyIO board as well. */#define	EREG_ADDR	0#define	EREG_DATA	4#define	EREG_RXACK	5#define	EREG_TXACK	6#define	EREG_MDACK	7#define	EREG_BANKSIZE	8#define	CD1400_CLK	25000000#define	CD1400_CLK8M	20000000/* *	Define the cd1400 baud rate clocks. These are used when calculating *	what clock and divisor to use for the required baud rate. Also *	define the maximum baud rate allowed, and the default base baud. */static int	stl_cd1400clkdivs[] = {	CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4};/*****************************************************************************//* *	SC26198 UART specific data initization. */static uart_t stl_sc26198uart = {	stl_sc26198panelinit,	stl_sc26198portinit,	stl_sc26198setport,	stl_sc26198getsignals,	stl_sc26198setsignals,	stl_sc26198enablerxtx,	stl_sc26198startrxtx,	stl_sc26198disableintrs,	stl_sc26198sendbreak,	stl_sc26198flowctrl,	stl_sc26198sendflow,	stl_sc26198flush,	stl_sc26198datastate,	stl_sc26198intr};/* *	Define the offsets within the register bank of a sc26198 based panel. */#define	XP_DATA		0#define	XP_ADDR		1#define	XP_MODID	2#define	XP_STATUS	2#define	XP_IACK		3#define	XP_BANKSIZE	4/* *	Define the sc26198 baud rate table. Offsets within the table *	represent the actual baud rate selector of sc26198 registers. */static unsigned int	sc26198_baudtable[] = {	50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,	4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,	230400, 460800, 921600};#define	SC26198_NRBAUDS		(sizeof(sc26198_baudtable) / sizeof(unsigned int))/*****************************************************************************//* *	Define the driver info for a user level control device. Used mainly *	to get at port stats - only not using the port device itself. */static struct file_operations	stl_fsiomem = {	NULL,		/* llseek */	NULL,		/* read */	NULL,		/* write */	NULL,		/* readdir */	NULL,		/* poll */	stl_memioctl,	/* ioctl */	NULL,		/* mmap */	stl_memopen,	/* open */	NULL,		/* flush */	stl_memclose,	/* release */	NULL,		/* fsync */	NULL,		/* fasync */	NULL,		/* check_media_change */	NULL,		/* revalidate */	NULL		/* lock */};/*****************************************************************************/#ifdef MODULE/* *	Loadable module initialization stuff. */int init_module(){	unsigned long	flags;#if DEBUG	printk("init_module()\n");#endif	save_flags(flags);	cli();	stl_init();	restore_flags(flags);	return(0);}/*****************************************************************************/void cleanup_module(){	stlbrd_t	*brdp;	stlpanel_t	*panelp;	stlport_t	*portp;	unsigned long	flags;	int		i, j, k;#if DEBUG	printk("cleanup_module()\n");#endif	printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,		stl_drvversion);	save_flags(flags);	cli();/* *	Free up all allocated resources used by the ports. This includes *	memory and interrupts. As part of this process we will also do *	a hangup on every open port - to try to flush out any processes *	hanging onto ports. */	i = tty_unregister_driver(&stl_serial);	j = tty_unregister_driver(&stl_callout);	if (i || j) {		printk("STALLION: failed to un-register tty driver, "			"errno=%d,%d\n", -i, -j);		restore_flags(flags);		return;	}	if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))		printk("STALLION: failed to un-register serial memory device, "			"errno=%d\n", -i);	if (stl_tmpwritebuf != (char *) NULL)		kfree_s(stl_tmpwritebuf, STL_TXBUFSIZE);	for (i = 0; (i < stl_nrbrds); i++) {		if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)			continue;		for (j = 0; (j < STL_MAXPANELS); j++) {			panelp = brdp->panels[j];			if (panelp == (stlpanel_t *) NULL)				continue;			for (k = 0; (k < STL_PORTSPERPANEL); k++) {				portp = panelp->ports[k];				if (portp == (stlport_t *) NULL)					continue;				if (portp->tty != (struct tty_struct *) NULL)					stl_hangup(portp->tty);				if (portp->tx.buf != (char *) NULL)					kfree_s(portp->tx.buf, STL_TXBUFSIZE);				kfree_s(portp, sizeof(stlport_t));			}			kfree_s(panelp, sizeof(stlpanel_t));		}		release_region(brdp->ioaddr1, brdp->iosize1);		if (brdp->iosize2 > 0)			release_region(brdp->ioaddr2, brdp->iosize2);		kfree_s(brdp, sizeof(stlbrd_t));		stl_brds[i] = (stlbrd_t *) NULL;	}	for (i = 0; (i < stl_numintrs); i++)		free_irq(stl_gotintrs[i], NULL);	restore_flags(flags);}/*****************************************************************************//* *	Check for any arguments passed in on the module load command line. */static void stl_argbrds(){	stlconf_t	conf;	stlbrd_t	*brdp;	int		nrargs, i;#if DEBUG	printk("stl_argbrds()\n");#endif	nrargs = sizeof(stl_brdsp) / sizeof(char **);	for (i = stl_nrbrds; (i < nrargs); i++) {		memset(&conf, 0, sizeof(conf));		if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)			continue;		if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)			continue;		stl_nrbrds = i + 1;		brdp->brdnr = i;		brdp->brdtype = conf.brdtype;		brdp->ioaddr1 = conf.ioaddr1;		brdp->ioaddr2 = conf.ioaddr2;		brdp->irq = conf.irq;		brdp->irqtype = conf.irqtype;		stl_brdinit(brdp);	}}/*****************************************************************************//* *	Convert an ascii string number into an unsigned long. */static unsigned long stl_atol(char *str){	unsigned long	val;	int		base, c;	char		*sp;	val = 0;	sp = str;	if ((*sp == '0') && (*(sp+1) == 'x')) {		base = 16;		sp += 2;	} else if (*sp == '0') {		base = 8;		sp++;	} else {		base = 10;	}	for (; (*sp != 0); sp++) {		c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');		if ((c < 0) || (c >= base)) {			printk("STALLION: invalid argument %s\n", str);			val = 0;			break;		}		val = (val * base) + c;	}	return(val);}/*****************************************************************************//* *	Parse the supplied argument string, into the board conf struct. */static int stl_parsebrd(stlconf_t *confp, char **argp){	char	*sp;	int	nrbrdnames, i;#if DEBUG	printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);#endif	if ((argp[0] == (char *) NULL) || (*argp[0] == 0))		return(0);	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)		*sp = TOLOWER(*sp);	nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);	for (i = 0; (i < nrbrdnames); i++) {		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)			break;	}	if (i >= nrbrdnames) {		printk("STALLION: unknown board name, %s?\n", argp[0]);		return(0);	}	confp->brdtype = stl_brdstr[i].type;	i = 1;	if ((argp[i] != (char *) NULL) && (*argp[i] != 0))		confp->ioaddr1 = stl_atol(argp[i]);	i++;	if (confp->brdtype == BRD_ECH) {		if ((argp[i] != (char *) NULL) && (*argp[i] != 0))			confp->ioaddr2 = stl_atol(argp[i]);		i++;	}	if ((argp[i] != (char *) NULL) && (*argp[i] != 0))		confp->irq = stl_atol(argp[i]);	return(1);}#endif/*****************************************************************************//* *	Local driver kernel memory allocation routine. */static void *stl_memalloc(int len){	return((void *) kmalloc(len, GFP_KERNEL));}/*****************************************************************************/

⌨️ 快捷键说明

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