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

📄 cx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cronyx-Sigma adapter driver for FreeBSD. * Supports PPP/HDLC protocol in synchronous mode, * and asyncronous channels with full modem control. * * Copyright (C) 1994 Cronyx Ltd. * Author: Serge Vakulenko, <vak@zebub.msk.su> * * This software is distributed with NO WARRANTIES, not even the implied * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Authors grant any other persons or organisations permission to use * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * * Version 1.9, Wed Oct  4 18:58:15 MSK 1995 */#undef DEBUG#include "cx.h"#if NCX > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/mbuf.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/conf.h>#include <sys/proc.h>#include <sys/tty.h>#include <sys/errno.h>#include <sys/syslog.h>#include <sys/socket.h>#include <net/if.h>#ifdef __FreeBSD__#   if __FreeBSD__ < 2#      include <machine/pio.h>#      define RB_GETC(q) getc(q)#   else /* BSD 4.4 Lite */#      include <machine/cpufunc.h>#      include <sys/devconf.h>#   endif#   define oproc_func_t void(*)(struct tty*)#endif#ifdef __bsdi__#   include <sys/ttystats.h>#   include <machine/inline.h>#   define tsleep(tp,pri,msg,x) ((tp)->t_state |= TS_WOPEN,\		ttysleep (tp, (caddr_t)&tp->t_rawq, pri, msg, x))#   define oproc_func_t int(*)()#   define timeout_func_t void(*)()#endif#if !defined (__FreeBSD__) || __FreeBSD__ >= 2#      define t_out t_outq#      define RB_LEN(q) ((q).c_cc)#      define RB_GETC(q) getc(&q)#ifndef TSA_CARR_ON /* FreeBSD 2.x before not long after 2.0.5 */#      define TSA_CARR_ON(tp) tp#      define TSA_OLOWAT(q) ((caddr_t)&(q)->t_out)#endif#endif#include <machine/cronyx.h>#include <i386/isa/cxreg.h>#ifdef DEBUG#   define print(s)     printf s#else#   define print(s)     {/*void*/}#endif#define DMABUFSZ        (6*256)         /* buffer size */#define BYTE            *(unsigned char*)&#define UNIT(u)         ((u) & 077)#define UNIT_CTL        077extern cx_board_t cxboard [NCX];        /* adapter state structures */extern cx_chan_t *cxchan [NCX*NCHAN];   /* unit to channel struct pointer */#if __FreeBSD__ >= 2extern struct kern_devconf kdc_cx [NCX];struct tty cx_tty [NCX*NCHAN];          /* tty data */#elsestruct tty *cx_tty [NCX*NCHAN];         /* tty data */#endifvoid cxoproc (struct tty *tp);int cxparam (struct tty *tp, struct termios *t);void cxswitch (cx_chan_t *c, cx_soft_opt_t new);int cxopen (dev_t dev, int flag, int mode, struct proc *p){	int unit = UNIT (dev);	cx_chan_t *c = cxchan[unit];	unsigned short port;	struct tty *tp;	int error = 0;	if (unit == UNIT_CTL) {		print (("cx: cxopen /dev/cronyx\n"));		return (0);	}	if (unit >= NCX*NCHAN || !c || c->type==T_NONE)		return (ENXIO);	port = c->chip->port;	print (("cx%d.%d: cxopen unit=%d\n", c->board->num, c->num, unit));	if (c->mode != M_ASYNC)		return (EBUSY);	if (! c->ttyp) {#ifdef __FreeBSD__#if __FreeBSD__ >= 2		c->ttyp = &cx_tty[unit];#else		c->ttyp = cx_tty[unit] = ttymalloc (cx_tty[unit]);#endif#else		MALLOC (cx_tty[unit], struct tty*, sizeof (struct tty), M_DEVBUF, M_WAITOK);		bzero (cx_tty[unit], sizeof (*cx_tty[unit]));		c->ttyp = cx_tty[unit];#endif		c->ttyp->t_oproc = (oproc_func_t) cxoproc;		c->ttyp->t_param = cxparam;	}#ifdef __bsdi__	if (! c->ttydev) {		MALLOC (c->ttydev, struct ttydevice_tmp*,			sizeof (struct ttydevice_tmp), M_DEVBUF, M_WAITOK);		bzero (c->ttydev, sizeof (*c->ttydev));		strcpy (c->ttydev->tty_name, "cx");		c->ttydev->tty_unit = unit;		c->ttydev->tty_base = unit;		c->ttydev->tty_count = 1;		c->ttydev->tty_ttys = c->ttyp;		tty_attach (c->ttydev);	}#endif	tp = c->ttyp;	tp->t_dev = dev;	if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE) &&	    p->p_ucred->cr_uid != 0)		return (EBUSY);	if (! (tp->t_state & TS_ISOPEN)) {		ttychars (tp);		if (tp->t_ispeed == 0) {#ifdef __bsdi__			tp->t_termios = deftermios;#else			tp->t_iflag = 0;			tp->t_oflag = 0;			tp->t_lflag = 0;			tp->t_cflag = CREAD | CS8 | HUPCL;			tp->t_ispeed = c->rxbaud;			tp->t_ospeed = c->txbaud;#endif		}		cxparam (tp, &tp->t_termios);		ttsetwater (tp);	}	spltty ();	if (! (tp->t_state & TS_ISOPEN)) {		/*		 * Compute optimal receiver buffer length.		 * The best choice is rxbaud/400.		 * Make it even, to avoid byte-wide DMA transfers.		 * --------------------------		 * Baud rate    Buffer length		 * --------------------------		 *      300     4		 *     1200     4		 *     9600     24		 *    19200     48		 *    38400     96		 *    57600     192		 *   115200     288		 * --------------------------		 */		int rbsz = (c->rxbaud + 800 - 1) / 800 * 2;		if (rbsz < 4)			rbsz = 4;		else if (rbsz > DMABUFSZ)			rbsz = DMABUFSZ;		/* Initialize channel, enable receiver. */		cx_cmd (port, CCR_INITCH | CCR_ENRX);		cx_cmd (port, CCR_INITCH | CCR_ENRX);		/* Start receiver. */		outw (ARBCNT(port), rbsz);		outw (BRBCNT(port), rbsz);		outw (ARBSTS(port), BSTS_OWN24);		outw (BRBSTS(port), BSTS_OWN24);		/* Enable interrupts. */		outb (IER(port), IER_RXD | IER_RET | IER_TXD | IER_MDM);		cx_chan_dtr (c, 1);		cx_chan_rts (c, 1);	}	if (cx_chan_cd (c))		(*linesw[tp->t_line].l_modem)(tp, 1);	if (! (flag & O_NONBLOCK)) {		/* Lock the channel against cxconfig while we are		 * waiting for carrier. */		c->sopt.lock = 1;		while (!(tp->t_cflag & CLOCAL) && !(tp->t_state & TS_CARR_ON))			if ((error = tsleep (TSA_CARR_ON(tp), TTIPRI | PCATCH,			    "cxdcd", 0)))				break;		c->sopt.lock = 0;       /* Unlock the channel. */	}	print (("cx%d.%d: cxopen done csr=%b\n", c->board->num, c->num,		inb(CSR(c->chip->port)), CSRA_BITS));	spl0 ();	if (error)		return (error);#if __FreeBSD__ >= 2	error = (*linesw[tp->t_line].l_open) (dev, tp);	if (tp->t_state & TS_ISOPEN)		/* Mark the board busy on the first startup.		 * Never goes idle. */		kdc_cx[c->board->num].kdc_state = DC_BUSY;#else	error = (*linesw[tp->t_line].l_open) (dev, tp, 0);#endif	return (error);}int cxclose (dev_t dev, int flag, int mode, struct proc *p){	int unit = UNIT (dev);	cx_chan_t *c = cxchan[unit];	struct tty *tp;	int s;	if (unit == UNIT_CTL)		return (0);	tp = c->ttyp;	(*linesw[tp->t_line].l_close) (tp, flag);	/* Disable receiver.	 * Transmitter continues sending the queued data. */	s = spltty ();	outb (CAR(c->chip->port), c->num & 3);	outb (IER(c->chip->port), IER_TXD | IER_MDM);	cx_cmd (c->chip->port, CCR_DISRX);	/* Clear DTR and RTS. */	if ((tp->t_cflag & HUPCL) || ! (tp->t_state & TS_ISOPEN)) {		cx_chan_dtr (c, 0);		cx_chan_rts (c, 0);	}	/* Stop sending break. */	if (c->brk == BRK_SEND) {		c->brk = BRK_STOP;		if (! (tp->t_state & TS_BUSY))			cxoproc (tp);	}	splx (s);	ttyclose (tp);	return (0);}int cxread (dev_t dev, struct uio *uio, int flag){	int unit = UNIT (dev);	struct tty *tp;	if (unit == UNIT_CTL)		return (EIO);	tp = cxchan[unit]->ttyp;	return ((*linesw[tp->t_line].l_read) (tp, uio, flag));}int cxwrite (dev_t dev, struct uio *uio, int flag){	int unit = UNIT (dev);	struct tty *tp;	if (unit == UNIT_CTL)		return (EIO);	tp = cxchan[unit]->ttyp;	return ((*linesw[tp->t_line].l_write) (tp, uio, flag));}int cxioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p){	int unit = UNIT (dev);	cx_chan_t *c, *m;	cx_stat_t *st;	struct tty *tp;	int error, s;	unsigned char msv;	struct ifnet *master;	if (unit == UNIT_CTL) {		/* Process an ioctl request on /dev/cronyx */		cx_options_t *o = (cx_options_t*) data;		if (o->board >= NCX || o->channel >= NCHAN)			return (EINVAL);		c = &cxboard[o->board].chan[o->channel];		if (c->type == T_NONE)			return (ENXIO);		switch (cmd) {		default:			return (EINVAL);		case CXIOCSETMODE:			print (("cx%d.%d: CXIOCSETMODE\n", o->board, o->channel));			if (c->type == T_NONE)				return (EINVAL);			if (c->type == T_ASYNC && o->mode != M_ASYNC)				return (EINVAL);			if (o->mode == M_ASYNC)				switch (c->type) {				case T_SYNC_RS232:				case T_SYNC_V35:				case T_SYNC_RS449:					return (EINVAL);				}			/* Somebody is waiting for carrier? */			if (c->sopt.lock)				return (EBUSY);			/* /dev/ttyXX is already opened by someone? */			if (c->mode == M_ASYNC && c->ttyp &&			    (c->ttyp->t_state & TS_ISOPEN))				return (EBUSY);			/* Network interface is up? */			if (c->mode != M_ASYNC && (c->ifp->if_flags & IFF_UP))				return (EBUSY);			/* Find the master interface. */			master = *o->master ? ifunit (o->master) : c->ifp;			if (! master)				return (EINVAL);			m = cxchan[master->if_unit];			/* Leave the previous master queue. */			if (c->master != c->ifp) {				cx_chan_t *p = cxchan[c->master->if_unit];				for (; p; p=p->slaveq)					if (p->slaveq == c)						p->slaveq = c->slaveq;			}			/* Set up new master. */			c->master = master;			c->slaveq = 0;			/* Join the new master queue. */			if (c->master != c->ifp) {				c->slaveq = m->slaveq;				m->slaveq = c;			}			c->mode   = o->mode;			c->rxbaud = o->rxbaud;			c->txbaud = o->txbaud;			c->opt    = o->opt;			c->aopt   = o->aopt;			c->hopt   = o->hopt;			c->bopt   = o->bopt;			c->xopt   = o->xopt;			switch (c->num) {			case 0: c->board->if0type = o->iftype; break;			case 8: c->board->if8type = o->iftype; break;			}			s = spltty ();			cxswitch (c, o->sopt);			cx_setup_chan (c);			outb (IER(c->chip->port), 0);			splx (s);			break;		case CXIOCGETSTAT:			st = (cx_stat_t*) data;			st->rintr  = c->stat->rintr;			st->tintr  = c->stat->tintr;			st->mintr  = c->stat->mintr;			st->ibytes = c->stat->ibytes;			st->ipkts  = c->stat->ipkts;			st->ierrs  = c->stat->ierrs;			st->obytes = c->stat->obytes;			st->opkts  = c->stat->opkts;			st->oerrs  = c->stat->oerrs;			break;		case CXIOCGETMODE:			print (("cx%d.%d: CXIOCGETMODE\n", o->board, o->channel));			o->type   = c->type;			o->mode   = c->mode;			o->rxbaud = c->rxbaud;			o->txbaud = c->txbaud;			o->opt    = c->opt;			o->aopt   = c->aopt;			o->hopt   = c->hopt;			o->bopt   = c->bopt;			o->xopt   = c->xopt;			o->sopt   = c->sopt;			switch (c->num) {			case 0: o->iftype = c->board->if0type; break;			case 8: o->iftype = c->board->if8type; break;			}			if (c->master != c->ifp)				sprintf (o->master, "%s%d", c->master->if_name,					c->master->if_unit);			else				*o->master = 0;			break;		}		return (0);	}	c = cxchan[unit];	tp = c->ttyp;	if (! tp)		return (EINVAL);#if __FreeBSD__ >= 2	error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);#else	error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag);#endif	if (error >= 0)		return (error);	error = ttioctl (tp, cmd, data, flag);	if (error >= 0)		return (error);	s = spltty ();	switch (cmd) {	default:		splx (s);		return (ENOTTY);	case TIOCSBRK:          /* Start sending line break */		c->brk = BRK_SEND;		if (! (tp->t_state & TS_BUSY))			cxoproc (tp);		break;	case TIOCCBRK:          /* Stop sending line break */		c->brk = BRK_STOP;		if (! (tp->t_state & TS_BUSY))			cxoproc (tp);		break;	case TIOCSDTR:          /* Set DTR */		cx_chan_dtr (c, 1);		break;	case TIOCCDTR:          /* Clear DTR */		cx_chan_dtr (c, 0);		break;	case TIOCMSET:          /* Set DTR/RTS */		cx_chan_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0);		cx_chan_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0);		break;	case TIOCMBIS:          /* Add DTR/RTS */		if (*(int*)data & TIOCM_DTR) cx_chan_dtr (c, 1);		if (*(int*)data & TIOCM_RTS) cx_chan_rts (c, 1);		break;	case TIOCMBIC:          /* Clear DTR/RTS */		if (*(int*)data & TIOCM_DTR) cx_chan_dtr (c, 0);		if (*(int*)data & TIOCM_RTS) cx_chan_rts (c, 0);		break;	case TIOCMGET:          /* Get modem status */		msv = inb (MSVR(c->chip->port));		*(int*)data = TIOCM_LE; /* always enabled while open */		if (msv & MSV_DSR) *(int*)data |= TIOCM_DSR;		if (msv & MSV_CTS) *(int*)data |= TIOCM_CTS;		if (msv & MSV_CD)  *(int*)data |= TIOCM_CD;		if (c->dtr)        *(int*)data |= TIOCM_DTR;		if (c->rts)        *(int*)data |= TIOCM_RTS;		break;	}	splx (s);	return (0);}/* * Fill transmitter buffer with data. */void cxout (cx_chan_t *c, char b){	unsigned char *buf, *p, sym;

⌨️ 快捷键说明

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