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

📄 istallion.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */#define	ECP_PCIIREG	0#define	ECP_PCICONFR	1#define	ECP_PCISTOP	0x01/* *	Hardware configuration info for ONboard and Brumby boards. These *	defines apply to the directly accessible io ports of these boards. */#define	ONB_IOSIZE	16#define	ONB_MEMSIZE	(64 * 1024)#define	ONB_ATPAGESIZE	(64 * 1024)#define	ONB_MCPAGESIZE	(64 * 1024)#define	ONB_EIMEMSIZE	(128 * 1024)#define	ONB_EIPAGESIZE	(64 * 1024)/* *	Important defines for the ISA class of ONboard board. */#define	ONB_ATIREG	0#define	ONB_ATMEMAR	1#define	ONB_ATCONFR	2#define	ONB_ATSTOP	0x4#define	ONB_ATENABLE	0x01#define	ONB_ATDISABLE	0x00#define	ONB_ATADDRMASK	0xff0000#define	ONB_ATADDRSHFT	16#define	ONB_MEMENABLO	0#define	ONB_MEMENABHI	0x02/* *	Important defines for the EISA class of ONboard board. */#define	ONB_EIIREG	0#define	ONB_EIMEMARL	1#define	ONB_EICONFR	2#define	ONB_EIMEMARH	3#define	ONB_EIENABLE	0x1#define	ONB_EIDISABLE	0x0#define	ONB_EISTOP	0x4#define	ONB_EIEDGE	0x00#define	ONB_EILEVEL	0x80#define	ONB_EIADDRMASKL	0x00ff0000#define	ONB_EIADDRSHFTL	16#define	ONB_EIADDRMASKH	0xff000000#define	ONB_EIADDRSHFTH	24#define	ONB_EIBRDENAB	0xc84#define	ONB_EISAID	0x1/* *	Important defines for the Brumby boards. They are pretty simple, *	there is not much that is programmably configurable. */#define	BBY_IOSIZE	16#define	BBY_MEMSIZE	(64 * 1024)#define	BBY_PAGESIZE	(16 * 1024)#define	BBY_ATIREG	0#define	BBY_ATCONFR	1#define	BBY_ATSTOP	0x4/* *	Important defines for the Stallion boards. They are pretty simple, *	there is not much that is programmably configurable. */#define	STAL_IOSIZE	16#define	STAL_MEMSIZE	(64 * 1024)#define	STAL_PAGESIZE	(64 * 1024)/* *	Define the set of status register values for EasyConnection panels. *	The signature will return with the status value for each panel. From *	this we can determine what is attached to the board - before we have *	actually down loaded any code to it. */#define	ECH_PNLSTATUS	2#define	ECH_PNL16PORT	0x20#define	ECH_PNLIDMASK	0x07#define	ECH_PNLXPID	0x40#define	ECH_PNLINTRPEND	0x80/* *	Define some macros to do things to the board. Even those these boards *	are somewhat related there is often significantly different ways of *	doing some operation on it (like enable, paging, reset, etc). So each *	board class has a set of functions which do the commonly required *	operations. The macros below basically just call these functions, *	generally checking for a NULL function - which means that the board *	needs nothing done to it to achieve this operation! */#define	EBRDINIT(brdp)						\	if (brdp->init != NULL)					\		(* brdp->init)(brdp)#define	EBRDENABLE(brdp)					\	if (brdp->enable != NULL)				\		(* brdp->enable)(brdp);#define	EBRDDISABLE(brdp)					\	if (brdp->disable != NULL)				\		(* brdp->disable)(brdp);#define	EBRDINTR(brdp)						\	if (brdp->intr != NULL)					\		(* brdp->intr)(brdp);#define	EBRDRESET(brdp)						\	if (brdp->reset != NULL)				\		(* brdp->reset)(brdp);#define	EBRDGETMEMPTR(brdp,offset)				\	(* brdp->getmemptr)(brdp, offset, __LINE__)/* *	Define the maximal baud rate, and the default baud base for ports. */#define	STL_MAXBAUD	460800#define	STL_BAUDBASE	115200#define	STL_CLOSEDELAY	(5 * HZ / 10)/*****************************************************************************//* *	Define macros to extract a brd or port number from a minor number. */#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)#define	MINOR2PORT(min)		((min) & 0x3f)/*****************************************************************************//* *	Prototype all functions in this driver! */static int	stli_parsebrd(struct stlconf *confp, char **argp);static int	stli_open(struct tty_struct *tty, struct file *filp);static void	stli_close(struct tty_struct *tty, struct file *filp);static int	stli_write(struct tty_struct *tty, const unsigned char *buf, int count);static void	stli_putchar(struct tty_struct *tty, unsigned char ch);static void	stli_flushchars(struct tty_struct *tty);static int	stli_writeroom(struct tty_struct *tty);static int	stli_charsinbuffer(struct tty_struct *tty);static int	stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);static void	stli_settermios(struct tty_struct *tty, struct ktermios *old);static void	stli_throttle(struct tty_struct *tty);static void	stli_unthrottle(struct tty_struct *tty);static void	stli_stop(struct tty_struct *tty);static void	stli_start(struct tty_struct *tty);static void	stli_flushbuffer(struct tty_struct *tty);static void	stli_breakctl(struct tty_struct *tty, int state);static void	stli_waituntilsent(struct tty_struct *tty, int timeout);static void	stli_sendxchar(struct tty_struct *tty, char ch);static void	stli_hangup(struct tty_struct *tty);static int	stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos);static int	stli_brdinit(struct stlibrd *brdp);static int	stli_startbrd(struct stlibrd *brdp);static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);static int	stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);static void	stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);static void	stli_poll(unsigned long arg);static int	stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);static int	stli_initopen(struct stlibrd *brdp, struct stliport *portp);static int	stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);static int	stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);static int	stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);static void	stli_dohangup(struct work_struct *);static int	stli_setport(struct stliport *portp);static int	stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);static void	stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);static void	__stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);static void	stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);static void	stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);static long	stli_mktiocm(unsigned long sigvalue);static void	stli_read(struct stlibrd *brdp, struct stliport *portp);static int	stli_getserial(struct stliport *portp, struct serial_struct __user *sp);static int	stli_setserial(struct stliport *portp, struct serial_struct __user *sp);static int	stli_getbrdstats(combrd_t __user *bp);static int	stli_getportstats(struct stliport *portp, comstats_t __user *cp);static int	stli_portcmdstats(struct stliport *portp);static int	stli_clrportstats(struct stliport *portp, comstats_t __user *cp);static int	stli_getportstruct(struct stliport __user *arg);static int	stli_getbrdstruct(struct stlibrd __user *arg);static struct stlibrd *stli_allocbrd(void);static void	stli_ecpinit(struct stlibrd *brdp);static void	stli_ecpenable(struct stlibrd *brdp);static void	stli_ecpdisable(struct stlibrd *brdp);static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_ecpreset(struct stlibrd *brdp);static void	stli_ecpintr(struct stlibrd *brdp);static void	stli_ecpeiinit(struct stlibrd *brdp);static void	stli_ecpeienable(struct stlibrd *brdp);static void	stli_ecpeidisable(struct stlibrd *brdp);static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_ecpeireset(struct stlibrd *brdp);static void	stli_ecpmcenable(struct stlibrd *brdp);static void	stli_ecpmcdisable(struct stlibrd *brdp);static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_ecpmcreset(struct stlibrd *brdp);static void	stli_ecppciinit(struct stlibrd *brdp);static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_ecppcireset(struct stlibrd *brdp);static void	stli_onbinit(struct stlibrd *brdp);static void	stli_onbenable(struct stlibrd *brdp);static void	stli_onbdisable(struct stlibrd *brdp);static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_onbreset(struct stlibrd *brdp);static void	stli_onbeinit(struct stlibrd *brdp);static void	stli_onbeenable(struct stlibrd *brdp);static void	stli_onbedisable(struct stlibrd *brdp);static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_onbereset(struct stlibrd *brdp);static void	stli_bbyinit(struct stlibrd *brdp);static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_bbyreset(struct stlibrd *brdp);static void	stli_stalinit(struct stlibrd *brdp);static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);static void	stli_stalreset(struct stlibrd *brdp);static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);static int	stli_initecp(struct stlibrd *brdp);static int	stli_initonb(struct stlibrd *brdp);#if STLI_EISAPROBE != 0static int	stli_eisamemprobe(struct stlibrd *brdp);#endifstatic int	stli_initports(struct stlibrd *brdp);/*****************************************************************************//* *	Define the driver info for a user level shared memory device. This *	device will work sort of like the /dev/kmem device - except that it *	will give access to the shared memory on the Stallion intelligent *	board. This is also a very useful debugging tool. */static const struct file_operations	stli_fsiomem = {	.owner		= THIS_MODULE,	.read		= stli_memread,	.write		= stli_memwrite,	.ioctl		= stli_memioctl,};/*****************************************************************************//* *	Define a timer_list entry for our poll routine. The slave board *	is polled every so often to see if anything needs doing. This is *	much cheaper on host cpu than using interrupts. It turns out to *	not increase character latency by much either... */static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);static int	stli_timeron;/* *	Define the calculation for the timeout routine. */#define	STLI_TIMEOUT	(jiffies + 1)/*****************************************************************************/static struct class *istallion_class;static void stli_cleanup_ports(struct stlibrd *brdp){	struct stliport *portp;	unsigned int j;	for (j = 0; j < STL_MAXPORTS; j++) {		portp = brdp->ports[j];		if (portp != NULL) {			if (portp->tty != NULL)				tty_hangup(portp->tty);			kfree(portp);		}	}}/*****************************************************************************//* *	Parse the supplied argument string, into the board conf struct. */static int stli_parsebrd(struct stlconf *confp, char **argp){	unsigned int i;	char *sp;	if (argp[0] == NULL || *argp[0] == 0)		return 0;	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)		*sp = tolower(*sp);	for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)			break;	}	if (i == ARRAY_SIZE(stli_brdstr)) {		printk("STALLION: unknown board name, %s?\n", argp[0]);		return 0;	}	confp->brdtype = stli_brdstr[i].type;	if (argp[1] != NULL && *argp[1] != 0)		confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);	if (argp[2] !=  NULL && *argp[2] != 0)		confp->memaddr = simple_strtoul(argp[2], NULL, 0);	return(1);}/*****************************************************************************/static int stli_open(struct tty_struct *tty, struct file *filp){	struct stlibrd *brdp;	struct stliport *portp;	unsigned int minordev, brdnr, portnr;	int rc;	minordev = tty->index;	brdnr = MINOR2BRD(minordev);	if (brdnr >= stli_nrbrds)		return -ENODEV;	brdp = stli_brds[brdnr];	if (brdp == NULL)		return -ENODEV;	if ((brdp->state & BST_STARTED) == 0)		return -ENODEV;	portnr = MINOR2PORT(minordev);	if (portnr > brdp->nrports)		return -ENODEV;	portp = brdp->ports[portnr];	if (portp == NULL)		return -ENODEV;	if (portp->devnr < 1)		return -ENODEV;/* *	Check if this port is in the middle of closing. If so then wait *	until it is closed then return error status based on flag settings. *	The sleep here does not need interrupt protection since the wakeup *	for it is done with the same context. */	if (portp->flags & ASYNC_CLOSING) {		interruptible_sleep_on(&portp->close_wait);		if (portp->flags & ASYNC_HUP_NOTIFY)			return -EAGAIN;		return -ERESTARTSYS;	}/* *	On the first open of the device setup the port hardware, and *	initialize the per port data structure. Since initializing the port *	requires several commands to the board we will need to wait for any *	other open that is already initializing the port. */	portp->tty = tty;	tty->driver_data = portp;	portp->refcount++;	wait_event_interruptible(portp->raw_wait,			!test_bit(ST_INITIALIZING, &portp->state));	if (signal_pending(current))		return -ERESTARTSYS;	if ((portp->flags & ASYNC_INITIALIZED) == 0) {		set_bit(ST_INITIALIZING, &portp->state);		if ((rc = stli_initopen(brdp, portp)) >= 0) {			portp->flags |= ASYNC_INITIALIZED;			clear_bit(TTY_IO_ERROR, &tty->flags);		}		clear_bit(ST_INITIALIZING, &portp->state);		wake_up_interruptible(&portp->raw_wait);		if (rc < 0)			return rc;	}/* *	Check if this port is in the middle of closing. If so then wait *	until it is closed then return error status, based on flag settings. *	The sleep here does not need interrupt protection since the wakeup *	for it is done with the same context. */	if (portp->flags & ASYNC_CLOSING) {		interruptible_sleep_on(&portp->close_wait);		if (portp->flags & ASYNC_HUP_NOTIFY)			return -EAGAIN;		return -ERESTARTSYS;	}/* *	Based on type of open being done check if it can overlap with any *	previous opens still in effect. If we are a normal serial device *	then also we might have to wait for carrier. */	if (!(filp->f_flags & O_NONBLOCK)) {		if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)			return rc;	}	portp->flags |= ASYNC_NORMAL_ACTIVE;	return 0;}/*****************************************************************************/static void stli_close(struct tty_struct *tty, struct file *filp){	struct stlibrd *brdp;	struct stliport *portp;	unsigned long flags;	portp = tty->driver_data;	if (portp == NULL)		return;	spin_lock_irqsave(&stli_lock, flags);	if (tty_hung_up_p(filp)) {		spin_unlock_irqrestore(&stli_lock, flags);		return;	}	if ((tty->count == 1) && (portp->refcount != 1))		portp->refcount = 1;	if (portp->refcount-- > 1) {		spin_unlock_irqrestore(&stli_lock, flags);		return;	}	portp->flags |= ASYNC_CLOSING;/* *	May want to wait for data to drain before closing. The BUSY flag *	keeps track of whether we are still transmitting or not. It is *	updated by messages from the slave - indicating when all chars *	really have drained. */	if (tty == stli_txcooktty)		stli_flushchars(tty);	tty->closing = 1;	spin_unlock_irqrestore(&stli_lock, flags);	if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)		tty_wait_until_sent(tty, portp->closing_wait);	portp->flags &= ~ASYNC_INITIALIZED;	brdp = stli_brds[portp->brdnr];	stli_rawclose(brdp, portp, 0, 0);	if (tty->termios->c_cflag & HUPCL) {		stli_mkasysigs(&portp->asig, 0, 0);		if (test_bit(ST_CMDING, &portp->state))

⌨️ 快捷键说明

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