svn commit: r191563 - head/sys/dev/rp

Doug Ambrisko ambrisko at FreeBSD.org
Mon Apr 27 15:58:39 UTC 2009


Author: ambrisko
Date: Mon Apr 27 15:58:38 2009
New Revision: 191563
URL: http://svn.freebsd.org/changeset/base/191563

Log:
  Start to convert this over to the new tty layer.  These changes allow
  this driver to compile and limp along with the new layer.  These changes
  do not deal with proper locking around access to the HW.  This is only
  a starting point.  I have not tested modem control but tip seems to work
  okay and I can send and receive characters which I needed for one of my
  -current boxes.  I have not tied this driver back up to the build since
  I don't want people to think it is ready for prime time.  If anyone
  else has some cycles to work on this feel free to!
  
  Also add support for a 16 port PCI interface I have at work.
  
  Glanced at by:	ed

Modified:
  head/sys/dev/rp/rp.c
  head/sys/dev/rp/rp_pci.c
  head/sys/dev/rp/rpreg.h

Modified: head/sys/dev/rp/rp.c
==============================================================================
--- head/sys/dev/rp/rp.c	Mon Apr 27 15:45:54 2009	(r191562)
+++ head/sys/dev/rp/rp.c	Mon Apr 27 15:58:38 2009	(r191563)
@@ -117,6 +117,8 @@ Byte_t rp_sBitMapSetTbl[8] =
    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
 };
 
+static void rpfree(void *);
+
 /***************************************************************************
 Function: sReadAiopID
 Purpose:  Read the AIOP idenfication number directly from an AIOP.
@@ -572,21 +574,19 @@ static	struct	rp_port *p_rp_table[MAX_RP
  * The top-level routines begin here
  */
 
-static	void	rpbreak(struct tty *, int);
 static	void	rpclose(struct tty *tp);
 static	void	rphardclose(struct tty *tp);
 static	int	rpmodem(struct tty *, int, int);
 static	int	rpparam(struct tty *, struct termios *);
 static	void	rpstart(struct tty *);
-static	void	rpstop(struct tty *, int);
-static	t_open_t	rpopen;
+static	int	rpioctl(struct tty *, u_long, caddr_t, struct thread *);
+static	int	rpopen(struct tty *);
 
 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
 			CHANNEL_t *cp, unsigned int ChanStatus)
 {
-	int	spl;
 	unsigned	int	CharNStat;
-	int	i, ToRecv, wRecv, ch, ttynocopy;
+	int	ToRecv, ch, err = 0;
 
 	ToRecv = sGetRxCnt(cp);
 	if(ToRecv == 0)
@@ -608,22 +608,22 @@ static void rp_do_receive(struct rp_port
 	FIFO one word at a time, pulling apart the character and
 	the status. Update error counters depending on status.
 */
+	tty_lock(tp);
 	if(ChanStatus & STATMODE) {
 		while(ToRecv) {
-			if(tp->t_state & TS_TBLOCK) {
-				break;
-			}
 			CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
 			ch = CharNStat & 0xff;
 
 			if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
-				ch |= TTY_FE;
+				err |= TRE_FRAMING;
 			else if (CharNStat & STMPARITYH)
-				ch |= TTY_PE;
-			else if (CharNStat & STMRCVROVRH)
+				err |= TRE_PARITY;
+			else if (CharNStat & STMRCVROVRH) {
 				rp->rp_overflows++;
+				err |= TRE_OVERRUN;
+			}
 
-			ttyld_rint(tp, ch);
+			ttydisc_rint(tp, ch, err);
 			ToRecv--;
 		}
 /*
@@ -634,42 +634,15 @@ static void rp_do_receive(struct rp_port
 			sDisRxStatusMode(cp);
 		}
 	} else {
-		/*
-		 * Avoid the grotesquely inefficient lineswitch routine
-		 * (ttyinput) in "raw" mode.  It usually takes about 450
-		 * instructions (that's without canonical processing or echo!).
-		 * slinput is reasonably fast (usually 40 instructions plus
-		 * call overhead).
-		 */
 		ToRecv = sGetRxCnt(cp);
-		if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
-			if ( ToRecv > RXFIFO_SIZE ) {
-				ToRecv = RXFIFO_SIZE;
-			}
-			for ( i = 0, wRecv = ToRecv >> 1; wRecv > 0; i += 2, wRecv-- ) {
-				le16enc(rp->RxBuf + i,rp_readch2(cp,sGetTxRxDataIO(cp)));
-			}
-			if ( ToRecv & 1 ) {
-				rp->RxBuf[(ToRecv-1)] = rp_readch1(cp,sGetTxRxDataIO(cp));
-			}
-			tk_nin += ToRecv;
-			tk_rawcc += ToRecv;
-			tp->t_rawcc += ToRecv;
-			ttynocopy = b_to_q(rp->RxBuf, ToRecv, &tp->t_rawq);
-			ttwakeup(tp);
-		} else {
-			while (ToRecv) {
-				if(tp->t_state & TS_TBLOCK) {
-					break;
-				}
-				ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
-				spl = spltty();
-				ttyld_rint(tp, ch);
-				splx(spl);
-				ToRecv--;
-			}
+		while (ToRecv) {
+			ch = rp_readch1(cp,sGetTxRxDataIO(cp));
+			ttydisc_rint(tp, ch & 0xff, err);
+			ToRecv--;
 		}
 	}
+        ttydisc_rint_done(tp);
+        tty_unlock(tp);
 }
 
 static void rp_handle_port(struct rp_port *rp)
@@ -687,21 +660,12 @@ static void rp_handle_port(struct rp_por
 	IntMask = IntMask & rp->rp_intmask;
 	ChanStatus = sGetChanStatus(cp);
 	if(IntMask & RXF_TRIG)
-		if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
-			rp_do_receive(rp, tp, cp, ChanStatus);
-		}
+		rp_do_receive(rp, tp, cp, ChanStatus);
 	if(IntMask & DELTA_CD) {
 		if(ChanStatus & CD_ACT) {
-			if(!(tp->t_state & TS_CARR_ON) ) {
-				(void)ttyld_modem(tp, 1);
-			}
+			(void)ttydisc_modem(tp, 1);
 		} else {
-			if((tp->t_state & TS_CARR_ON)) {
-				(void)ttyld_modem(tp, 0);
-				if(ttyld_modem(tp, 0) == 0) {
-					rphardclose(tp);
-				}
-			}
+			(void)ttydisc_modem(tp, 0);
 		}
 	}
 /*	oldcts = rp->rp_cts;
@@ -740,15 +704,13 @@ static void rp_do_poll(void *not_used)
 	for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
 			line++, rp++) {
 		tp = rp->rp_tty;
-		if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
-			count = sGetTxCnt(&rp->rp_channel);
-			if(count == 0)
-				tp->t_state &= ~(TS_BUSY);
-			if(!(tp->t_state & TS_TTSTOP) &&
-				(count <= rp->rp_restart)) {
-				ttyld_start(tp);
-			}
+		tty_lock(tp);
+		count = sGetTxCnt(&rp->rp_channel);
+		if (count >= 0  &&
+		    (count <= rp->rp_restart)) {
+			rpstart(tp);
 		}
+		tty_unlock(tp);
 	}
 	}
 	if(rp_num_ports_open)
@@ -756,10 +718,31 @@ static void rp_do_poll(void *not_used)
 					    (void *)NULL, POLL_INTERVAL);
 }
 
+static struct ttydevsw rp_tty_class = {
+	.tsw_flags	= TF_INITLOCK|TF_CALLOUT,
+	.tsw_open	= rpopen,
+	.tsw_close	= rpclose,
+	.tsw_outwakeup	= rpstart,
+	.tsw_ioctl	= rpioctl,
+	.tsw_param	= rpparam,
+	.tsw_modem	= rpmodem,
+	.tsw_free	= rpfree,
+};
+
+
+static void
+rpfree(void *softc)
+{
+	struct	rp_port *rp = softc;
+	CONTROLLER_t *ctlp = rp->rp_ctlp;
+
+	atomic_subtract_32(&ctlp->free, 1);
+}
+
 int
 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
 {
-	int	oldspl, unit;
+	int	unit;
 	int	num_chan;
 	int	aiop, chan, port;
 	int	ChanStatus, line, count;
@@ -775,7 +758,7 @@ rp_attachcommon(CONTROLLER_T *ctlp, int 
 	callout_handle_init(&rp_callout_handle);
 
 	ctlp->rp = rp = (struct rp_port *)
-		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
+		malloc(sizeof(struct rp_port) * num_ports, M_DEVBUF, M_NOWAIT | M_ZERO);
 	if (rp == NULL) {
 		device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
 		retval = ENOMEM;
@@ -785,26 +768,13 @@ rp_attachcommon(CONTROLLER_T *ctlp, int 
 	count = unit * 32;      /* board times max ports per card SG */
 
 	bzero(rp, sizeof(struct rp_port) * num_ports);
-	oldspl = spltty();
 	rp_addr(unit) = rp;
-	splx(oldspl);
 
 	port = 0;
 	for(aiop=0; aiop < num_aiops; aiop++) {
 		num_chan = sGetAiopNumChan(ctlp, aiop);
 		for(chan=0; chan < num_chan; chan++, port++, rp++) {
-			tp = rp->rp_tty = ttyalloc();
-			tp->t_sc = rp;
-			tp->t_param = rpparam;
-			tp->t_oproc = rpstart;
-			tp->t_stop = rpstop;
-			tp->t_break = rpbreak;
-			tp->t_modem = rpmodem;
-			tp->t_close = rpclose;
-			tp->t_open = rpopen;
-			tp->t_ififosize = 512;
-			tp->t_ispeedwat = (speed_t)-1;
-			tp->t_ospeedwat = (speed_t)-1;
+			rp->rp_tty = tp = tty_alloc(&rp_tty_class, rp, NULL);
 			rp->rp_port = port;
 			rp->rp_ctlp = ctlp;
 			rp->rp_unit = unit;
@@ -826,11 +796,13 @@ rp_attachcommon(CONTROLLER_T *ctlp, int 
 			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
 			line = (unit << 5) | (aiop << 3) | chan;
 			rp_table(line) = rp;
-			ttycreate(tp, TS_CALLOUT, "R%r%r", unit, port);
+			tty_makedev(tp, NULL, "R%r%r", unit, port);
 		}
 	}
 
 	rp_ndevs++;
+	mtx_init(&ctlp->hwmtx, "rp_hwmtx", NULL, MTX_DEF);
+	ctlp->hwmtx_init = 1;
 	return (0);
 
 nogo:
@@ -842,7 +814,7 @@ nogo:
 void
 rp_releaseresource(CONTROLLER_t *ctlp)
 {
-	int i, s, unit;
+	int i, unit;
 	struct	rp_port *rp;
 
 
@@ -850,21 +822,25 @@ rp_releaseresource(CONTROLLER_t *ctlp)
 	if (rp_addr(unit) != NULL) {
 		for (i = 0; i < rp_num_ports[unit]; i++) {
 			rp = rp_addr(unit) + i;
-			ttyfree(rp->rp_tty);
+			atomic_add_32(&ctlp->free, 1);
+			tty_lock(rp->rp_tty);
+			tty_rel_gone(rp->rp_tty);
 		}
 	}
 
+	while (ctlp->free != 0) {
+		pause("rpwt", hz / 10);
+	}
+
 	if (ctlp->rp != NULL) {
-		s = spltty();
 		for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
 			if (p_rp_addr[i] == ctlp->rp)
 				p_rp_addr[i] = NULL;
 		for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
 			if (p_rp_table[i] == ctlp->rp)
 				p_rp_table[i] = NULL;
-		splx(s);
-		free(ctlp->rp, M_DEVBUF);
-		ctlp->rp = NULL;
+                free(ctlp->rp, M_DEVBUF);
+                ctlp->rp = NULL;
 	}
 }
 
@@ -875,15 +851,13 @@ rp_untimeout(void)
 }
 
 static int
-rpopen(struct tty *tp, struct cdev *dev)
+rpopen(struct tty *tp)
 {
 	struct	rp_port *rp;
-	int	oldspl, flags;
+	int	flags;
 	unsigned int	IntMask, ChanStatus;
 
-	rp = dev->si_drv1;
-
-	oldspl = spltty();
+	rp = tty_softc(tp);
 
 	flags = 0;
 	flags |= SET_RTS;
@@ -938,7 +912,7 @@ rpclose(struct tty *tp)
 {
 	struct	rp_port	*rp;
 
-	rp = tp->t_sc;
+	rp = tty_softc(tp);
 	rphardclose(tp);
 	device_unbusy(rp->rp_ctlp->dev);
 }
@@ -949,7 +923,7 @@ rphardclose(struct tty *tp)
 	struct	rp_port	*rp;
 	CHANNEL_t	*cp;
 
-	rp = tp->t_sc;
+	rp = tty_softc(tp);
 	cp = &rp->rp_channel;
 
 	sFlushRxFIFO(cp);
@@ -961,6 +935,7 @@ rphardclose(struct tty *tp)
 	sDisTxSoftFlowCtl(cp);
 	sClrTxXOFF(cp);
 
+#ifdef DJA
 	if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) {
 		sClrDTR(cp);
 	}
@@ -970,18 +945,24 @@ rphardclose(struct tty *tp)
 	tp->t_actout = FALSE;
 	wakeup(&tp->t_actout);
 	wakeup(TSA_CARR_ON(tp));
+#endif /* DJA */
 }
 
-static void
-rpbreak(struct tty *tp, int sig)
+static int
+rpioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
 {
 	struct rp_port	*rp;
 
-	rp = tp->t_sc;
-	if (sig) {
+	rp = tty_softc(tp);
+	switch (cmd) {
+	case TIOCSBRK:
 		sSendBreak(&rp->rp_channel);
-	} else {
+		return (0);
+	case TIOCCBRK:
 		sClrBreak(&rp->rp_channel);
+		return (0);
+	default:
+		return ENOIOCTL;
 	}
 }
 
@@ -991,7 +972,7 @@ rpmodem(struct tty *tp, int sigon, int s
 	struct rp_port	*rp;
 	int i, j, k;
 
-	rp = tp->t_sc;
+	rp = tty_softc(tp);
 	if (sigon != 0 || sigoff != 0) {
 		i = j = 0;
 		if (sigon & SER_DTR)
@@ -1025,7 +1006,11 @@ rpmodem(struct tty *tp, int sigon, int s
 	return (0);
 }
 
-static struct speedtab baud_table[] = {
+static struct
+{
+	int baud;
+	int conversion;
+} baud_table[] = {
 	{B0,	0},		{B50,	BRD50},		{B75,	BRD75},
 	{B110,	BRD110}, 	{B134,	BRD134}, 	{B150,	BRD150},
 	{B200,	BRD200}, 	{B300,	BRD300}, 	{B600,	BRD600},
@@ -1037,6 +1022,17 @@ static struct speedtab baud_table[] = {
 	{-1,	-1}
 };
 
+static int rp_convert_baud(int baud) {
+	int i;
+
+	for (i = 0; baud_table[i].baud >= 0; i++) {
+		if (baud_table[i].baud == baud)
+			break;
+	}
+
+	return baud_table[i].conversion;
+}
+
 static int
 rpparam(tp, t)
 	struct tty *tp;
@@ -1044,16 +1040,14 @@ rpparam(tp, t)
 {
 	struct rp_port	*rp;
 	CHANNEL_t	*cp;
-	int	oldspl, cflag, iflag, oflag, lflag;
+	int	cflag, iflag, oflag, lflag;
 	int	ospeed;
 #ifdef RPCLOCAL
 	int	devshift;
 #endif
 
-
-	rp = tp->t_sc;
+	rp = tty_softc(tp);
 	cp = &rp->rp_channel;
-	oldspl = spltty();
 
 	cflag = t->c_cflag;
 #ifdef RPCLOCAL
@@ -1067,17 +1061,10 @@ rpparam(tp, t)
 	oflag = t->c_oflag;
 	lflag = t->c_lflag;
 
-	ospeed = ttspeedtab(t->c_ispeed, baud_table);
+	ospeed = rp_convert_baud(t->c_ispeed);
 	if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 		return(EINVAL);
 
-	tp->t_ispeed = t->c_ispeed;
-	tp->t_ospeed = t->c_ospeed;
-	tp->t_cflag = cflag;
-	tp->t_iflag = iflag;
-	tp->t_oflag = oflag;
-	tp->t_lflag = lflag;
-
 	if(t->c_ospeed == 0) {
 		sClrDTR(cp);
 		return(0);
@@ -1143,104 +1130,36 @@ rpparam(tp, t)
 	} else {
 		sDisRTSFlowCtl(cp);
 	}
-	ttyldoptim(tp);
-
-	if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
-		tp->t_state |= TS_CARR_ON;
-		wakeup(TSA_CARR_ON(tp));
-	}
-
-/*	tp->t_state |= TS_CAN_BYPASS_L_RINT;
-	flags = rp->rp_channel.TxControl[3];
-	if(flags & SET_DTR)
-	else
-	if(flags & SET_RTS)
-	else
-*/
-	splx(oldspl);
 
 	return(0);
 }
 
 static void
-rpstart(tp)
-	struct tty *tp;
+rpstart(struct tty *tp)
 {
 	struct rp_port	*rp;
 	CHANNEL_t	*cp;
-	struct	clist	*qp;
 	char	flags;
-	int	spl, xmit_fifo_room;
+	int	xmit_fifo_room;
 	int	i, count, wcount;
 
-
-	rp = tp->t_sc;
+	rp = tty_softc(tp);
 	cp = &rp->rp_channel;
 	flags = rp->rp_channel.TxControl[3];
-	spl = spltty();
 
-	if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
-		ttwwakeup(tp);
-		splx(spl);
-		return;
-	}
 	if(rp->rp_xmit_stopped) {
 		sEnTransmit(cp);
 		rp->rp_xmit_stopped = 0;
 	}
-	count = sGetTxCnt(cp);
 
-	if(tp->t_outq.c_cc == 0) {
-		if((tp->t_state & TS_BUSY) && (count == 0)) {
-			tp->t_state &= ~TS_BUSY;
-		}
-		ttwwakeup(tp);
-		splx(spl);
-		return;
-	}
 	xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-	qp = &tp->t_outq;
-	if(xmit_fifo_room > 0 && qp->c_cc > 0) {
-		tp->t_state |= TS_BUSY;
-		count = q_to_b( qp, rp->TxBuf, xmit_fifo_room );
+	count = ttydisc_getc(tp, &rp->TxBuf, xmit_fifo_room);
+	if(xmit_fifo_room > 0) {
 		for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) {
-			rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(rp->TxBuf + i));
+			rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(&rp->TxBuf[i]));
 		}
 		if ( count & 1 ) {
 			rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]);
 		}
 	}
-	rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
-
-	ttwwakeup(tp);
-	splx(spl);
-}
-
-static
-void
-rpstop(tp, flag)
-	register struct tty *tp;
-	int	flag;
-{
-	struct rp_port	*rp;
-	CHANNEL_t	*cp;
-	int	spl;
-
-	rp = tp->t_sc;
-	cp = &rp->rp_channel;
-
-	spl = spltty();
-
-	if(tp->t_state & TS_BUSY) {
-		if((tp->t_state&TS_TTSTOP) == 0) {
-			sFlushTxFIFO(cp);
-		} else {
-			if(rp->rp_xmit_stopped == 0) {
-				sDisTransmit(cp);
-				rp->rp_xmit_stopped = 1;
-			}
-		}
-	}
-	splx(spl);
-	rpstart(tp);
 }

Modified: head/sys/dev/rp/rp_pci.c
==============================================================================
--- head/sys/dev/rp/rp_pci.c	Mon Apr 27 15:45:54 2009	(r191562)
+++ head/sys/dev/rp/rp_pci.c	Mon Apr 27 15:58:38 2009	(r191563)
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
 #define RP_DEVICE_ID_6M		0x000C
 #define RP_DEVICE_ID_4M		0x000D
 #define RP_DEVICE_ID_UPCI_32	0x0801
+#define RP_DEVICE_ID_UPCI_16	0x0803
 #define RP_DEVICE_ID_UPCI_8O	0x0805
 
 /**************************************************************************
@@ -180,6 +181,7 @@ rp_pciattach(device_t dev)
 	ctlp->bus_ctlp = NULL;
 
 	switch (pci_get_device(dev)) {
+	case RP_DEVICE_ID_UPCI_16:
 	case RP_DEVICE_ID_UPCI_32:
 	case RP_DEVICE_ID_UPCI_8O:
 		ctlp->io_rid[0] = PCIR_BAR(2);

Modified: head/sys/dev/rp/rpreg.h
==============================================================================
--- head/sys/dev/rp/rpreg.h	Mon Apr 27 15:45:54 2009	(r191562)
+++ head/sys/dev/rp/rpreg.h	Mon Apr 27 15:58:38 2009	(r191563)
@@ -361,6 +361,10 @@ struct CONTROLLER_str
 	int		AiopID[AIOP_CTL_SIZE];
 	int		AiopNumChan[AIOP_CTL_SIZE];
 
+        struct mtx	hwmtx;     /* Spinlock protecting hardware. */
+	int		hwmtx_init;
+	int		free;
+
 	/* Device and resource management */
 	device_t		dev;		/* device */
 	int			io_num;		/* Number of IO resources */
@@ -1005,6 +1009,18 @@ void sDisInterrupts(CHANNEL_T *ChP,Word_
 int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports);
 void rp_releaseresource(CONTROLLER_t *ctlp);
 void rp_untimeout(void);
+static __inline void
+rp_lock(CONTROLLER_T *CtlP)
+{
+        if (CtlP->hwmtx_init != 0)
+                mtx_lock_spin(&CtlP->hwmtx);
+}
+static __inline void
+rp_unlock(CONTROLLER_T *CtlP)
+{
+        if (CtlP->hwmtx_init != 0)
+                mtx_unlock_spin(&CtlP->hwmtx);
+}
 
 #ifndef ROCKET_C
 extern Byte_t R[RDATASIZE];


More information about the svn-src-head mailing list