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

📄 istallion.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 stli_parsebrd(stlconf_t *confp, char **argp){	char	*sp;	int	nrbrdnames, i;#if DEBUG	printk("stli_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(stli_brdstr) / sizeof(stlibrdtype_t);	for (i = 0; (i < nrbrdnames); i++) {		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)			break;	}	if (i >= nrbrdnames) {		printk("STALLION: unknown board name, %s?\n", argp[0]);		return(0);	}	confp->brdtype = stli_brdstr[i].type;	if ((argp[1] != (char *) NULL) && (*argp[1] != 0))		confp->ioaddr1 = stli_atol(argp[1]);	if ((argp[2] != (char *) NULL) && (*argp[2] != 0))		confp->memaddr = stli_atol(argp[2]);	return(1);}#endif/*****************************************************************************//* *	Local driver kernel malloc routine. */static void *stli_memalloc(int len){	return((void *) kmalloc(len, GFP_KERNEL));}/*****************************************************************************/static int stli_open(struct tty_struct *tty, struct file *filp){	stlibrd_t	*brdp;	stliport_t	*portp;	unsigned int	minordev;	int		brdnr, portnr, rc;#if DEBUG	printk("stli_open(tty=%x,filp=%x): device=%x\n", (int) tty,		(int) filp, tty->device);#endif	minordev = MINOR(tty->device);	brdnr = MINOR2BRD(minordev);	if (brdnr >= stli_nrbrds)		return(-ENODEV);	brdp = stli_brds[brdnr];	if (brdp == (stlibrd_t *) NULL)		return(-ENODEV);	if ((brdp->state & BST_STARTED) == 0)		return(-ENODEV);	portnr = MINOR2PORT(minordev);	if ((portnr < 0) || (portnr > brdp->nrports))		return(-ENODEV);	portp = brdp->ports[portnr];	if (portp == (stliport_t *) NULL)		return(-ENODEV);	if (portp->devnr < 1)		return(-ENODEV);	MOD_INC_USE_COUNT;/* *	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++;	while (test_bit(ST_INITIALIZING, &portp->state)) {		if (signal_pending(current))			return(-ERESTARTSYS);		interruptible_sleep_on(&portp->raw_wait);	}	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 (tty->driver.subtype == STL_DRVTYPCALLOUT) {		if (portp->flags & ASYNC_NORMAL_ACTIVE)			return(-EBUSY);		if (portp->flags & ASYNC_CALLOUT_ACTIVE) {			if ((portp->flags & ASYNC_SESSION_LOCKOUT) &&			    (portp->session != current->session))				return(-EBUSY);			if ((portp->flags & ASYNC_PGRP_LOCKOUT) &&			    (portp->pgrp != current->pgrp))				return(-EBUSY);		}		portp->flags |= ASYNC_CALLOUT_ACTIVE;	} else {		if (filp->f_flags & O_NONBLOCK) {			if (portp->flags & ASYNC_CALLOUT_ACTIVE)				return(-EBUSY);		} else {			if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)				return(rc);		}		portp->flags |= ASYNC_NORMAL_ACTIVE;	}	if ((portp->refcount == 1) && (portp->flags & ASYNC_SPLIT_TERMIOS)) {		if (tty->driver.subtype == STL_DRVTYPSERIAL)			*tty->termios = portp->normaltermios;		else			*tty->termios = portp->callouttermios;		stli_setport(portp);	}	portp->session = current->session;	portp->pgrp = current->pgrp;	return(0);}/*****************************************************************************/static void stli_close(struct tty_struct *tty, struct file *filp){	stlibrd_t	*brdp;	stliport_t	*portp;	unsigned long	flags;#if DEBUG	printk("stli_close(tty=%x,filp=%x)\n", (int) tty, (int) filp);#endif	portp = tty->driver_data;	if (portp == (stliport_t *) NULL)		return;	save_flags(flags);	cli();	if (tty_hung_up_p(filp)) {		MOD_DEC_USE_COUNT;		restore_flags(flags);		return;	}	if ((tty->count == 1) && (portp->refcount != 1))		portp->refcount = 1;	if (portp->refcount-- > 1) {		MOD_DEC_USE_COUNT;		restore_flags(flags);		return;	}	portp->flags |= ASYNC_CLOSING;	if (portp->flags & ASYNC_NORMAL_ACTIVE)		portp->normaltermios = *tty->termios;	if (portp->flags & ASYNC_CALLOUT_ACTIVE)		portp->callouttermios = *tty->termios;/* *	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;	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))			set_bit(ST_DOSIGS, &portp->state);		else			stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig,				sizeof(asysigs_t), 0);	}	clear_bit(ST_TXBUSY, &portp->state);	clear_bit(ST_RXSTOP, &portp->state);	set_bit(TTY_IO_ERROR, &tty->flags);	if (tty->ldisc.flush_buffer)		(tty->ldisc.flush_buffer)(tty);	set_bit(ST_DOFLUSHRX, &portp->state);	stli_flushbuffer(tty);	tty->closing = 0;	portp->tty = (struct tty_struct *) NULL;	if (portp->openwaitcnt) {		if (portp->close_delay)			stli_delay(portp->close_delay);		wake_up_interruptible(&portp->open_wait);	}	portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE |		ASYNC_CLOSING);	wake_up_interruptible(&portp->close_wait);	MOD_DEC_USE_COUNT;	restore_flags(flags);}/*****************************************************************************//* *	Carry out first open operations on a port. This involves a number of *	commands to be sent to the slave. We need to open the port, set the *	notification events, set the initial port settings, get and set the *	initial signal values. We sleep and wait in between each one. But *	this still all happens pretty quickly. */static int stli_initopen(stlibrd_t *brdp, stliport_t *portp){	struct tty_struct	*tty;	asynotify_t		nt;	asyport_t		aport;	int			rc;#if DEBUG	printk("stli_initopen(brdp=%x,portp=%x)\n", (int) brdp, (int) portp);#endif	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)		return(rc);	memset(&nt, 0, sizeof(asynotify_t));	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);	nt.signal = SG_DCD;	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,	    sizeof(asynotify_t), 0)) < 0)		return(rc);	tty = portp->tty;	if (tty == (struct tty_struct *) NULL)		return(-ENODEV);	stli_mkasyport(portp, &aport, tty->termios);	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,	    sizeof(asyport_t), 0)) < 0)		return(rc);	set_bit(ST_GETSIGS, &portp->state);	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,	    sizeof(asysigs_t), 1)) < 0)		return(rc);	if (test_and_clear_bit(ST_GETSIGS, &portp->state))		portp->sigs = stli_mktiocm(portp->asig.sigvalue);	stli_mkasysigs(&portp->asig, 1, 1);	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,	    sizeof(asysigs_t), 0)) < 0)		return(rc);	return(0);}/*****************************************************************************//* *	Send an open message to the slave. This will sleep waiting for the *	acknowledgement, so must have user context. We need to co-ordinate *	with close events here, since we don't want open and close events *	to overlap. */static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait){	volatile cdkhdr_t	*hdrp;	volatile cdkctrl_t	*cp;	volatile unsigned char	*bits;	unsigned long		flags;	int			rc;#if DEBUG	printk("stli_rawopen(brdp=%x,portp=%x,arg=%x,wait=%d)\n",		(int) brdp, (int) portp, (int) arg, wait);#endif/* *	Send a message to the slave to open this port. */	save_flags(flags);	cli();/* *	Slave is already closing this port. This can happen if a hangup *	occurs on this port. So we must wait until it is complete. The *	order of opens and closes may not be preserved across shared *	memory, so we must wait until it is complete. */	while (test_bit(ST_CLOSING, &portp->state)) {		if (signal_pending(current)) {			restore_flags(flags);			return(-ERESTARTSYS);		}		interruptible_sleep_on(&portp->raw_wait);	}/* *	Everything is ready now, so write the open message into shared *	memory. Once the message is in set the service bits to say that *	this port wants service. */	EBRDENABLE(brdp);	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;	cp->openarg = arg;	cp->open = 1;	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +		portp->portidx;	*bits |= portp->portbit;	EBRDDISABLE(brdp);	if (wait == 0) {		restore_flags(flags);		return(0);	}/* *	Slave is in action, so now we must wait for the open acknowledgment *	to come back. */	rc = 0;	set_bit(ST_OPENING, &portp->state);	while (test_bit(ST_OPENING, &portp->state)) {		if (signal_pending(current)) {			rc = -ERESTARTSYS;			break;		}		interruptible_sleep_on(&portp->raw_wait);	}	restore_flags(flags);	if ((rc == 0) && (portp->rc != 0))		rc = -EIO;	return(rc);}/*****************************************************************************//* *	Send a close message to the slave. Normally this will sleep waiting *	for the acknowledgement, but if wait parameter is 0 it will not. If *	wait is true then must have user context (to sleep). */static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait){	volatile cdkhdr_t	*hdrp;	volatile cdkctrl_t	*cp;	volatile unsigned char	*bits;	unsigned long		flags;	int			rc;#if DEBUG	printk("stli_rawclose(brdp=%x,portp=%x,arg=%x,wait=%d)\n",		(int) brdp, (int) portp, (int) arg, wait);#endif	save_flags(flags);	cli();/* *	Slave is already closing this port. This can happen if a hangup *	occurs on this port. */	if (wait) {		while (test_bit(ST_CLOSING, &portp->state)) {			if (signal_pending(current)) {				restore_flags(flags);				return(-ERESTARTSYS);			}			interruptible_sleep_on(&portp->raw_wait);		}	}/* *	Write the close command into shared memory. */	EBRDENABLE(brdp);	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;	cp->closearg = arg;	cp->close = 1;	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);

⌨️ 快捷键说明

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