Home | History | Annotate | Line # | Download | only in ir
irframe_tty.c revision 1.1
      1  1.1  augustss /*	$NetBSD: irframe_tty.c,v 1.1 2001/12/03 23:32:32 augustss Exp $	*/
      2  1.1  augustss 
      3  1.1  augustss /*
      4  1.1  augustss  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  1.1  augustss  * All rights reserved.
      6  1.1  augustss  *
      7  1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  augustss  * by Lennart Augustsson (lennart (at) augustsson.net).
      9  1.1  augustss  *
     10  1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11  1.1  augustss  * modification, are permitted provided that the following conditions
     12  1.1  augustss  * are met:
     13  1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14  1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15  1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18  1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     19  1.1  augustss  *    must display the following acknowledgement:
     20  1.1  augustss  *        This product includes software developed by the NetBSD
     21  1.1  augustss  *        Foundation, Inc. and its contributors.
     22  1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  augustss  *    contributors may be used to endorse or promote products derived
     24  1.1  augustss  *    from this software without specific prior written permission.
     25  1.1  augustss  *
     26  1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  augustss  */
     38  1.1  augustss 
     39  1.1  augustss /*
     40  1.1  augustss  * Loosely based on ppp_tty.c.
     41  1.1  augustss  */
     42  1.1  augustss 
     43  1.1  augustss #include <sys/param.h>
     44  1.1  augustss #include <sys/proc.h>
     45  1.1  augustss #include <sys/ioctl.h>
     46  1.1  augustss #include <sys/tty.h>
     47  1.1  augustss #include <sys/kernel.h>
     48  1.1  augustss #include <sys/conf.h>
     49  1.1  augustss #include <sys/systm.h>
     50  1.1  augustss #include <sys/device.h>
     51  1.1  augustss #include <sys/file.h>
     52  1.1  augustss #include <sys/poll.h>
     53  1.1  augustss 
     54  1.1  augustss #include <dev/ir/ir.h>
     55  1.1  augustss #include <dev/ir/irdaio.h>
     56  1.1  augustss #include <dev/ir/irframevar.h>
     57  1.1  augustss 
     58  1.1  augustss /* Macros to clear/set/test flags. */
     59  1.1  augustss #define	SET(t, f)	(t) |= (f)
     60  1.1  augustss #define	CLR(t, f)	(t) &= ~((unsigned)(f))
     61  1.1  augustss #define	ISSET(t, f)	((t) & (f))
     62  1.1  augustss 
     63  1.1  augustss #ifdef IRFRAMET_DEBUG
     64  1.1  augustss #define DPRINTF(x)	if (irframetdebug) printf x
     65  1.1  augustss int irframetdebug = 1;
     66  1.1  augustss #else
     67  1.1  augustss #define DPRINTF(x)
     68  1.1  augustss #endif
     69  1.1  augustss 
     70  1.1  augustss /* Protocol constants */
     71  1.1  augustss #define SIR_EXTRA_BOF            0xff
     72  1.1  augustss #define SIR_BOF                  0xc0
     73  1.1  augustss #define SIR_CE                   0x7d
     74  1.1  augustss #define SIR_EOF                  0xc1
     75  1.1  augustss 
     76  1.1  augustss #define SIR_ESC_BIT              0x20
     77  1.1  augustss /*****/
     78  1.1  augustss 
     79  1.1  augustss #define MAX_IRDA_FRAME 5000	/* XXX what is it? */
     80  1.1  augustss 
     81  1.1  augustss struct irframet_softc {
     82  1.1  augustss 	struct irframe_softc sc_irp;
     83  1.1  augustss 	struct tty *sc_tp;
     84  1.1  augustss 	int sc_ebofs;
     85  1.1  augustss };
     86  1.1  augustss 
     87  1.1  augustss /* line discipline methods */
     88  1.1  augustss int	irframetopen(dev_t dev, struct tty *tp);
     89  1.1  augustss int	irframetclose(struct tty *tp, int flag);
     90  1.1  augustss int	irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
     91  1.1  augustss 		     struct proc *);
     92  1.1  augustss int	irframetinput(int c, struct tty *tp);
     93  1.1  augustss int	irframetstart(struct tty *tp);
     94  1.1  augustss 
     95  1.1  augustss /* irframe methods */
     96  1.1  augustss int	irframet_open(void *h, int flag, int mode, struct proc *p);
     97  1.1  augustss int	irframet_close(void *h, int flag, int mode, struct proc *p);
     98  1.1  augustss int	irframet_read(void *h, struct uio *uio, int flag);
     99  1.1  augustss int	irframet_write(void *h, struct uio *uio, int flag);
    100  1.1  augustss int	irframet_poll(void *h, int events, struct proc *p);
    101  1.1  augustss int	irframet_set_params(void *h, struct irda_params *params);
    102  1.1  augustss int	irframet_reset_params(void *h);
    103  1.1  augustss int	irframet_get_speeds(void *h, int *speeds);
    104  1.1  augustss int	irframet_get_turnarounds(void *h, int *times);
    105  1.1  augustss 
    106  1.1  augustss int	irframet_write_buf(void *h, void *buf, size_t len);
    107  1.1  augustss 
    108  1.1  augustss void	irframettyattach(int);
    109  1.1  augustss 
    110  1.1  augustss struct irframe_methods irframet_methods = {
    111  1.1  augustss 	irframet_open, irframet_close, irframet_read, irframet_write,
    112  1.1  augustss 	irframet_poll, irframet_set_params, irframet_reset_params,
    113  1.1  augustss 	irframet_get_speeds, irframet_get_speeds
    114  1.1  augustss };
    115  1.1  augustss 
    116  1.1  augustss void
    117  1.1  augustss irframettyattach(int n)
    118  1.1  augustss {
    119  1.1  augustss }
    120  1.1  augustss 
    121  1.1  augustss /*
    122  1.1  augustss  * Line specific open routine for async tty devices.
    123  1.1  augustss  * Attach the given tty to the first available irframe unit.
    124  1.1  augustss  * Called from device open routine or ttioctl.
    125  1.1  augustss  */
    126  1.1  augustss /* ARGSUSED */
    127  1.1  augustss int
    128  1.1  augustss irframetopen(dev_t dev, struct tty *tp)
    129  1.1  augustss {
    130  1.1  augustss 	struct proc *p = curproc;		/* XXX */
    131  1.1  augustss 	struct irframet_softc *sc;
    132  1.1  augustss 	int error, s;
    133  1.1  augustss 
    134  1.1  augustss 	DPRINTF(("%s\n", __FUNCTION__));
    135  1.1  augustss 
    136  1.1  augustss 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    137  1.1  augustss 		return (error);
    138  1.1  augustss 
    139  1.1  augustss 	s = spltty();
    140  1.1  augustss 
    141  1.1  augustss 	DPRINTF(("%s: linesw=%p disc=%d\n", __FUNCTION__, tp->t_linesw,
    142  1.1  augustss 		 tp->t_linesw->l_no));
    143  1.1  augustss 	if (tp->t_linesw->l_no == IRFRAMEDISC) {
    144  1.1  augustss 		sc = (struct irframet_softc *)tp->t_sc;
    145  1.1  augustss 		DPRINTF(("%s: sc=%p sc_tp=%p\n", __FUNCTION__, sc, sc->sc_tp));
    146  1.1  augustss 		if (sc != NULL) {
    147  1.1  augustss 			splx(s);
    148  1.1  augustss 			return (EBUSY);
    149  1.1  augustss 		}
    150  1.1  augustss 	}
    151  1.1  augustss 
    152  1.1  augustss 	printf("%s attached at tty%d:", sc->sc_irp.sc_dev.dv_xname,
    153  1.1  augustss 	    minor(tp->t_dev));
    154  1.1  augustss 	tp->t_sc = irframe_alloc(sizeof (struct irframet_softc),
    155  1.1  augustss 			&irframet_methods, tp);
    156  1.1  augustss 	sc = (struct irframet_softc *)tp->t_sc;
    157  1.1  augustss 	sc->sc_tp = tp;
    158  1.1  augustss 
    159  1.1  augustss 	DPRINTF(("%s: set sc=%p\n", __FUNCTION__, sc));
    160  1.1  augustss 
    161  1.1  augustss 	ttyflush(tp, FREAD | FWRITE);
    162  1.1  augustss 
    163  1.1  augustss 	splx(s);
    164  1.1  augustss 	return (0);
    165  1.1  augustss }
    166  1.1  augustss 
    167  1.1  augustss /*
    168  1.1  augustss  * Line specific close routine, called from device close routine
    169  1.1  augustss  * and from ttioctl.
    170  1.1  augustss  * Detach the tty from the irframe unit.
    171  1.1  augustss  * Mimics part of ttyclose().
    172  1.1  augustss  */
    173  1.1  augustss int
    174  1.1  augustss irframetclose(struct tty *tp, int flag)
    175  1.1  augustss {
    176  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    177  1.1  augustss 	int s;
    178  1.1  augustss 
    179  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    180  1.1  augustss 
    181  1.1  augustss 	s = spltty();
    182  1.1  augustss 	ttyflush(tp, FREAD | FWRITE);
    183  1.1  augustss 	tp->t_linesw = linesw[0]; /* default line discipline */
    184  1.1  augustss 	if (sc != NULL) {
    185  1.1  augustss 		tp->t_sc = NULL;
    186  1.1  augustss 		printf("%s detached from tty%d\n", sc->sc_irp.sc_dev.dv_xname,
    187  1.1  augustss 		    minor(tp->t_dev));
    188  1.1  augustss 
    189  1.1  augustss 		if (sc->sc_tp == tp)
    190  1.1  augustss 			irframe_dealloc(&sc->sc_irp.sc_dev);
    191  1.1  augustss 	}
    192  1.1  augustss 	splx(s);
    193  1.1  augustss 	return (0);
    194  1.1  augustss }
    195  1.1  augustss 
    196  1.1  augustss /*
    197  1.1  augustss  * Line specific (tty) ioctl routine.
    198  1.1  augustss  * This discipline requires that tty device drivers call
    199  1.1  augustss  * the line specific l_ioctl routine from their ioctl routines.
    200  1.1  augustss  */
    201  1.1  augustss /* ARGSUSED */
    202  1.1  augustss int
    203  1.1  augustss irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
    204  1.1  augustss 	     struct proc *p)
    205  1.1  augustss {
    206  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    207  1.1  augustss 	int error;
    208  1.1  augustss 
    209  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    210  1.1  augustss 
    211  1.1  augustss 	if (sc == NULL || tp != sc->sc_tp)
    212  1.1  augustss 		return (-1);
    213  1.1  augustss 
    214  1.1  augustss 	error = 0;
    215  1.1  augustss 	switch (cmd) {
    216  1.1  augustss 	default:
    217  1.1  augustss #if 0
    218  1.1  augustss 		error = irframeioctl(sc, cmd, data, flag, p);
    219  1.1  augustss #else
    220  1.1  augustss 		error = EINVAL;
    221  1.1  augustss #endif
    222  1.1  augustss 		break;
    223  1.1  augustss 	}
    224  1.1  augustss 
    225  1.1  augustss 	return (error);
    226  1.1  augustss }
    227  1.1  augustss 
    228  1.1  augustss /*
    229  1.1  augustss  * Start output on async tty interface.  If the transmit queue
    230  1.1  augustss  * has drained sufficiently, arrange for irframeasyncstart to be
    231  1.1  augustss  * called later at splsoftnet.
    232  1.1  augustss  * Called at spltty or higher.
    233  1.1  augustss  */
    234  1.1  augustss int
    235  1.1  augustss irframetstart(struct tty *tp)
    236  1.1  augustss {
    237  1.1  augustss 	/*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/
    238  1.1  augustss 
    239  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    240  1.1  augustss 
    241  1.1  augustss 	/*
    242  1.1  augustss 	 * If there is stuff in the output queue, send it now.
    243  1.1  augustss 	 * We are being called in lieu of ttstart and must do what it would.
    244  1.1  augustss 	 */
    245  1.1  augustss 	if (tp->t_oproc != NULL)
    246  1.1  augustss 		(*tp->t_oproc)(tp);
    247  1.1  augustss 
    248  1.1  augustss 	return (0);
    249  1.1  augustss }
    250  1.1  augustss 
    251  1.1  augustss int
    252  1.1  augustss irframetinput(int c, struct tty *tp)
    253  1.1  augustss {
    254  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    255  1.1  augustss 
    256  1.1  augustss 	DPRINTF(("%s: tp=%p c=0x%0x\n", __FUNCTION__, tp, c));
    257  1.1  augustss 
    258  1.1  augustss 	if (sc == NULL || tp != (struct tty *)sc->sc_tp)
    259  1.1  augustss 		return (0);
    260  1.1  augustss #if 0
    261  1.1  augustss 
    262  1.1  augustss 
    263  1.1  augustss     ++tk_nin;
    264  1.1  augustss     ++sc->sc_stats.irframe_ibytes;
    265  1.1  augustss 
    266  1.1  augustss     if (c & TTY_FE) {
    267  1.1  augustss 	/* framing error or overrun on this char - abort packet */
    268  1.1  augustss 	if (sc->sc_flags & SC_DEBUG)
    269  1.1  augustss 	    printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
    270  1.1  augustss 	goto flush;
    271  1.1  augustss     }
    272  1.1  augustss 
    273  1.1  augustss     c &= 0xff;
    274  1.1  augustss 
    275  1.1  augustss     /*
    276  1.1  augustss      * Handle software flow control of output.
    277  1.1  augustss      */
    278  1.1  augustss     if (tp->t_iflag & IXON) {
    279  1.1  augustss 	if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
    280  1.1  augustss 	    if ((tp->t_state & TS_TTSTOP) == 0) {
    281  1.1  augustss 		tp->t_state |= TS_TTSTOP;
    282  1.1  augustss 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
    283  1.1  augustss 	    }
    284  1.1  augustss 	    return 0;
    285  1.1  augustss 	}
    286  1.1  augustss 	if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
    287  1.1  augustss 	    tp->t_state &= ~TS_TTSTOP;
    288  1.1  augustss 	    if (tp->t_oproc != NULL)
    289  1.1  augustss 		(*tp->t_oproc)(tp);
    290  1.1  augustss 	    return 0;
    291  1.1  augustss 	}
    292  1.1  augustss     }
    293  1.1  augustss 
    294  1.1  augustss     s = spltty();
    295  1.1  augustss     if (c & 0x80)
    296  1.1  augustss 	sc->sc_flags |= SC_RCV_B7_1;
    297  1.1  augustss     else
    298  1.1  augustss 	sc->sc_flags |= SC_RCV_B7_0;
    299  1.1  augustss     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
    300  1.1  augustss 	sc->sc_flags |= SC_RCV_ODDP;
    301  1.1  augustss     else
    302  1.1  augustss 	sc->sc_flags |= SC_RCV_EVNP;
    303  1.1  augustss     splx(s);
    304  1.1  augustss 
    305  1.1  augustss     if (sc->sc_flags & SC_LOG_RAWIN)
    306  1.1  augustss 	irframelogchar(sc, c);
    307  1.1  augustss 
    308  1.1  augustss     if (c == IRFRAME_FLAG) {
    309  1.1  augustss 	ilen = sc->sc_ilen;
    310  1.1  augustss 	sc->sc_ilen = 0;
    311  1.1  augustss 
    312  1.1  augustss 	if (sc->sc_rawin_count > 0)
    313  1.1  augustss 	    irframelogchar(sc, -1);
    314  1.1  augustss 
    315  1.1  augustss 	/*
    316  1.1  augustss 	 * If SC_ESCAPED is set, then we've seen the packet
    317  1.1  augustss 	 * abort sequence "}~".
    318  1.1  augustss 	 */
    319  1.1  augustss 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
    320  1.1  augustss 	    || (ilen > 0 && sc->sc_fcs != IRFRAME_GOODFCS)) {
    321  1.1  augustss 	    s = spltty();
    322  1.1  augustss 	    sc->sc_flags |= SC_PKTLOST;	/* note the dropped packet */
    323  1.1  augustss 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
    324  1.1  augustss 		if (sc->sc_flags & SC_DEBUG)
    325  1.1  augustss 		    printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
    326  1.1  augustss 			sc->sc_fcs);
    327  1.1  augustss 		sc->sc_if.if_ierrors++;
    328  1.1  augustss 		sc->sc_stats.irframe_ierrors++;
    329  1.1  augustss 	    } else
    330  1.1  augustss 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
    331  1.1  augustss 	    splx(s);
    332  1.1  augustss 	    return 0;
    333  1.1  augustss 	}
    334  1.1  augustss 
    335  1.1  augustss 	if (ilen < IRFRAME_HDRLEN + IRFRAME_FCSLEN) {
    336  1.1  augustss 	    if (ilen) {
    337  1.1  augustss 		if (sc->sc_flags & SC_DEBUG)
    338  1.1  augustss 		    printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
    339  1.1  augustss 		s = spltty();
    340  1.1  augustss 		sc->sc_if.if_ierrors++;
    341  1.1  augustss 		sc->sc_stats.irframe_ierrors++;
    342  1.1  augustss 		sc->sc_flags |= SC_PKTLOST;
    343  1.1  augustss 		splx(s);
    344  1.1  augustss 	    }
    345  1.1  augustss 	    return 0;
    346  1.1  augustss 	}
    347  1.1  augustss 
    348  1.1  augustss 	/*
    349  1.1  augustss 	 * Remove FCS trailer.  Somewhat painful...
    350  1.1  augustss 	 */
    351  1.1  augustss 	ilen -= 2;
    352  1.1  augustss 	if (--sc->sc_mc->m_len == 0) {
    353  1.1  augustss 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
    354  1.1  augustss 		;
    355  1.1  augustss 	    sc->sc_mc = m;
    356  1.1  augustss 	}
    357  1.1  augustss 	sc->sc_mc->m_len--;
    358  1.1  augustss 
    359  1.1  augustss 	/* excise this mbuf chain */
    360  1.1  augustss 	m = sc->sc_m;
    361  1.1  augustss 	sc->sc_m = sc->sc_mc->m_next;
    362  1.1  augustss 	sc->sc_mc->m_next = NULL;
    363  1.1  augustss 
    364  1.1  augustss 	irframepktin(sc, m, sc->sc_flags & SC_PKTLOST);
    365  1.1  augustss 	if (sc->sc_flags & SC_PKTLOST) {
    366  1.1  augustss 	    s = spltty();
    367  1.1  augustss 	    sc->sc_flags &= ~SC_PKTLOST;
    368  1.1  augustss 	    splx(s);
    369  1.1  augustss 	}
    370  1.1  augustss 
    371  1.1  augustss 	irframegetm(sc);
    372  1.1  augustss 	return 0;
    373  1.1  augustss     }
    374  1.1  augustss 
    375  1.1  augustss     if (sc->sc_flags & SC_FLUSH) {
    376  1.1  augustss 	if (sc->sc_flags & SC_LOG_FLUSH)
    377  1.1  augustss 	    irframelogchar(sc, c);
    378  1.1  augustss 	return 0;
    379  1.1  augustss     }
    380  1.1  augustss 
    381  1.1  augustss     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
    382  1.1  augustss 	return 0;
    383  1.1  augustss 
    384  1.1  augustss     s = spltty();
    385  1.1  augustss     if (sc->sc_flags & SC_ESCAPED) {
    386  1.1  augustss 	sc->sc_flags &= ~SC_ESCAPED;
    387  1.1  augustss 	c ^= IRFRAME_TRANS;
    388  1.1  augustss     } else if (c == IRFRAME_ESCAPE) {
    389  1.1  augustss 	sc->sc_flags |= SC_ESCAPED;
    390  1.1  augustss 	splx(s);
    391  1.1  augustss 	return 0;
    392  1.1  augustss     }
    393  1.1  augustss     splx(s);
    394  1.1  augustss 
    395  1.1  augustss     /*
    396  1.1  augustss      * Initialize buffer on first octet received.
    397  1.1  augustss      * First octet could be address or protocol (when compressing
    398  1.1  augustss      * address/control).
    399  1.1  augustss      * Second octet is control.
    400  1.1  augustss      * Third octet is first or second (when compressing protocol)
    401  1.1  augustss      * octet of protocol.
    402  1.1  augustss      * Fourth octet is second octet of protocol.
    403  1.1  augustss      */
    404  1.1  augustss     if (sc->sc_ilen == 0) {
    405  1.1  augustss 	/* reset the first input mbuf */
    406  1.1  augustss 	if (sc->sc_m == NULL) {
    407  1.1  augustss 	    irframegetm(sc);
    408  1.1  augustss 	    if (sc->sc_m == NULL) {
    409  1.1  augustss 		if (sc->sc_flags & SC_DEBUG)
    410  1.1  augustss 		    printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
    411  1.1  augustss 		goto flush;
    412  1.1  augustss 	    }
    413  1.1  augustss 	}
    414  1.1  augustss 	m = sc->sc_m;
    415  1.1  augustss 	m->m_len = 0;
    416  1.1  augustss 	m->m_data = M_DATASTART(sc->sc_m);
    417  1.1  augustss 	sc->sc_mc = m;
    418  1.1  augustss 	sc->sc_mp = mtod(m, char *);
    419  1.1  augustss 	sc->sc_fcs = IRFRAME_INITFCS;
    420  1.1  augustss 	if (c != IRFRAME_ALLSTATIONS) {
    421  1.1  augustss 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
    422  1.1  augustss 		if (sc->sc_flags & SC_DEBUG)
    423  1.1  augustss 		    printf("%s: garbage received: 0x%x (need 0xFF)\n",
    424  1.1  augustss 		    sc->sc_if.if_xname, c);
    425  1.1  augustss 		goto flush;
    426  1.1  augustss 	    }
    427  1.1  augustss 	    *sc->sc_mp++ = IRFRAME_ALLSTATIONS;
    428  1.1  augustss 	    *sc->sc_mp++ = IRFRAME_UI;
    429  1.1  augustss 	    sc->sc_ilen += 2;
    430  1.1  augustss 	    m->m_len += 2;
    431  1.1  augustss 	}
    432  1.1  augustss     }
    433  1.1  augustss     if (sc->sc_ilen == 1 && c != IRFRAME_UI) {
    434  1.1  augustss 	if (sc->sc_flags & SC_DEBUG)
    435  1.1  augustss 	    printf("%s: missing UI (0x3), got 0x%x\n",
    436  1.1  augustss 		sc->sc_if.if_xname, c);
    437  1.1  augustss 	goto flush;
    438  1.1  augustss     }
    439  1.1  augustss     if (sc->sc_ilen == 2 && (c & 1) == 1) {
    440  1.1  augustss 	/* a compressed protocol */
    441  1.1  augustss 	*sc->sc_mp++ = 0;
    442  1.1  augustss 	sc->sc_ilen++;
    443  1.1  augustss 	sc->sc_mc->m_len++;
    444  1.1  augustss     }
    445  1.1  augustss     if (sc->sc_ilen == 3 && (c & 1) == 0) {
    446  1.1  augustss 	if (sc->sc_flags & SC_DEBUG)
    447  1.1  augustss 	    printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
    448  1.1  augustss 		(sc->sc_mp[-1] << 8) + c);
    449  1.1  augustss 	goto flush;
    450  1.1  augustss     }
    451  1.1  augustss 
    452  1.1  augustss     /* packet beyond configured mru? */
    453  1.1  augustss     if (++sc->sc_ilen > sc->sc_mru + IRFRAME_HDRLEN + IRFRAME_FCSLEN) {
    454  1.1  augustss 	if (sc->sc_flags & SC_DEBUG)
    455  1.1  augustss 	    printf("%s: packet too big\n", sc->sc_if.if_xname);
    456  1.1  augustss 	goto flush;
    457  1.1  augustss     }
    458  1.1  augustss 
    459  1.1  augustss     /* is this mbuf full? */
    460  1.1  augustss     m = sc->sc_mc;
    461  1.1  augustss     if (M_TRAILINGSPACE(m) <= 0) {
    462  1.1  augustss 	if (m->m_next == NULL) {
    463  1.1  augustss 	    irframegetm(sc);
    464  1.1  augustss 	    if (m->m_next == NULL) {
    465  1.1  augustss 		if (sc->sc_flags & SC_DEBUG)
    466  1.1  augustss 		    printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
    467  1.1  augustss 		goto flush;
    468  1.1  augustss 	    }
    469  1.1  augustss 	}
    470  1.1  augustss 	sc->sc_mc = m = m->m_next;
    471  1.1  augustss 	m->m_len = 0;
    472  1.1  augustss 	m->m_data = M_DATASTART(m);
    473  1.1  augustss 	sc->sc_mp = mtod(m, char *);
    474  1.1  augustss     }
    475  1.1  augustss 
    476  1.1  augustss     ++m->m_len;
    477  1.1  augustss     *sc->sc_mp++ = c;
    478  1.1  augustss     sc->sc_fcs = IRFRAME_FCS(sc->sc_fcs, c);
    479  1.1  augustss     return 0;
    480  1.1  augustss 
    481  1.1  augustss  flush:
    482  1.1  augustss     if (!(sc->sc_flags & SC_FLUSH)) {
    483  1.1  augustss 	s = spltty();
    484  1.1  augustss 	sc->sc_if.if_ierrors++;
    485  1.1  augustss 	sc->sc_stats.irframe_ierrors++;
    486  1.1  augustss 	sc->sc_flags |= SC_FLUSH;
    487  1.1  augustss 	splx(s);
    488  1.1  augustss 	if (sc->sc_flags & SC_LOG_FLUSH)
    489  1.1  augustss 	    irframelogchar(sc, c);
    490  1.1  augustss     }
    491  1.1  augustss #endif
    492  1.1  augustss     return 0;
    493  1.1  augustss }
    494  1.1  augustss 
    495  1.1  augustss 
    496  1.1  augustss /**********************************************************************
    497  1.1  augustss  * CRC
    498  1.1  augustss  **********************************************************************/
    499  1.1  augustss 
    500  1.1  augustss static const int fcstab[] = {
    501  1.1  augustss   0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    502  1.1  augustss   0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    503  1.1  augustss   0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    504  1.1  augustss   0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    505  1.1  augustss   0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    506  1.1  augustss   0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    507  1.1  augustss   0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    508  1.1  augustss   0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    509  1.1  augustss   0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    510  1.1  augustss   0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    511  1.1  augustss   0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    512  1.1  augustss   0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    513  1.1  augustss   0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    514  1.1  augustss   0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    515  1.1  augustss   0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    516  1.1  augustss   0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    517  1.1  augustss   0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    518  1.1  augustss   0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    519  1.1  augustss   0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    520  1.1  augustss   0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    521  1.1  augustss   0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    522  1.1  augustss   0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    523  1.1  augustss   0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    524  1.1  augustss   0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    525  1.1  augustss   0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    526  1.1  augustss   0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    527  1.1  augustss   0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    528  1.1  augustss   0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    529  1.1  augustss   0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    530  1.1  augustss   0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    531  1.1  augustss   0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    532  1.1  augustss   0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
    533  1.1  augustss };
    534  1.1  augustss 
    535  1.1  augustss static const int INITFCS = 0xffff;
    536  1.1  augustss static const int GOODFCS = 0xf0b8;
    537  1.1  augustss 
    538  1.1  augustss static __inline int updateFCS(int fcs, int c) {
    539  1.1  augustss 	return (fcs >> 8) ^ fcstab[(fcs^c) & 0xff];
    540  1.1  augustss }
    541  1.1  augustss 
    542  1.1  augustss /*** irframe methods ***/
    543  1.1  augustss 
    544  1.1  augustss int
    545  1.1  augustss irframet_open(void *h, int flag, int mode, struct proc *p)
    546  1.1  augustss {
    547  1.1  augustss 	struct tty *tp = h;
    548  1.1  augustss 
    549  1.1  augustss 	tp = tp;
    550  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    551  1.1  augustss 	return (0);
    552  1.1  augustss }
    553  1.1  augustss 
    554  1.1  augustss int
    555  1.1  augustss irframet_close(void *h, int flag, int mode, struct proc *p)
    556  1.1  augustss {
    557  1.1  augustss 	struct tty *tp = h;
    558  1.1  augustss 
    559  1.1  augustss 	tp = tp;
    560  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    561  1.1  augustss 	return (0);
    562  1.1  augustss }
    563  1.1  augustss 
    564  1.1  augustss int
    565  1.1  augustss irframet_read(void *h, struct uio *uio, int flag)
    566  1.1  augustss {
    567  1.1  augustss 	struct tty *tp = h;
    568  1.1  augustss 
    569  1.1  augustss 	tp = tp;
    570  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    571  1.1  augustss 	return (0);
    572  1.1  augustss }
    573  1.1  augustss 
    574  1.1  augustss static int
    575  1.1  augustss putch(int c, struct tty *tp)
    576  1.1  augustss {
    577  1.1  augustss 	int s;
    578  1.1  augustss 	int error;
    579  1.1  augustss 
    580  1.1  augustss 	if (tp->t_outq.c_cc > tp->t_hiwat) {
    581  1.1  augustss 		irframetstart(tp);
    582  1.1  augustss 		s = spltty();
    583  1.1  augustss 		/*
    584  1.1  augustss 		 * This can only occur if FLUSHO is set in t_lflag,
    585  1.1  augustss 		 * or if ttstart/oproc is synchronous (or very fast).
    586  1.1  augustss 		 */
    587  1.1  augustss 		if (tp->t_outq.c_cc <= tp->t_hiwat) {
    588  1.1  augustss 			splx(s);
    589  1.1  augustss 			goto go;
    590  1.1  augustss 		}
    591  1.1  augustss 		SET(tp->t_state, TS_ASLEEP);
    592  1.1  augustss 		error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
    593  1.1  augustss 		splx(s);
    594  1.1  augustss 		if (error)
    595  1.1  augustss 			return (error);
    596  1.1  augustss 	}
    597  1.1  augustss  go:
    598  1.1  augustss 	if (putc(c, &tp->t_rawq) < 0) {
    599  1.1  augustss 		printf("irframe: putc failed\n");
    600  1.1  augustss 		return (EIO);
    601  1.1  augustss 	}
    602  1.1  augustss 	return (0);
    603  1.1  augustss }
    604  1.1  augustss 
    605  1.1  augustss static int
    606  1.1  augustss put_esc(int c, struct tty *tp)
    607  1.1  augustss {
    608  1.1  augustss 	int error;
    609  1.1  augustss 
    610  1.1  augustss 	if (c == SIR_BOF || c == SIR_EOF || c == SIR_CE) {
    611  1.1  augustss 		error = putch(SIR_CE, tp);
    612  1.1  augustss 		if (!error)
    613  1.1  augustss 			error = putch(SIR_ESC_BIT^c, tp);
    614  1.1  augustss 	} else {
    615  1.1  augustss 		error = putch(c, tp);
    616  1.1  augustss 	}
    617  1.1  augustss 	return (error);
    618  1.1  augustss }
    619  1.1  augustss 
    620  1.1  augustss int
    621  1.1  augustss irframet_write(void *h, struct uio *uio, int flag)
    622  1.1  augustss {
    623  1.1  augustss 	u_int8_t buf[MAX_IRDA_FRAME];
    624  1.1  augustss 	size_t n;
    625  1.1  augustss 	int error;
    626  1.1  augustss 
    627  1.1  augustss 	DPRINTF(("%s\n", __FUNCTION__));
    628  1.1  augustss 
    629  1.1  augustss 	n = uio->uio_resid;
    630  1.1  augustss 	if (n > MAX_IRDA_FRAME)
    631  1.1  augustss 		return (EINVAL);
    632  1.1  augustss 	error = uiomove(buf, n, uio);
    633  1.1  augustss 	if (error)
    634  1.1  augustss 		return (error);
    635  1.1  augustss 	return (irframet_write_buf(h, buf, n));
    636  1.1  augustss }
    637  1.1  augustss 
    638  1.1  augustss int
    639  1.1  augustss irframet_write_buf(void *h, void *buf, size_t len)
    640  1.1  augustss {
    641  1.1  augustss 	struct tty *tp = h;
    642  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    643  1.1  augustss 	u_int8_t *cp = buf;
    644  1.1  augustss 	int c, error, ofcs, i;
    645  1.1  augustss 
    646  1.1  augustss 	DPRINTF(("%s: tp=%p len=%d\n", __FUNCTION__, tp, len));
    647  1.1  augustss 
    648  1.1  augustss 	ofcs = INITFCS;
    649  1.1  augustss 	error = 0;
    650  1.1  augustss 
    651  1.1  augustss 	for (i = 0; i < sc->sc_ebofs; i++)
    652  1.1  augustss 		putch(SIR_EXTRA_BOF, tp);
    653  1.1  augustss 	putch(SIR_BOF, tp);
    654  1.1  augustss 
    655  1.1  augustss 	while (len-- > 0) {
    656  1.1  augustss 		c = *cp++;
    657  1.1  augustss 		ofcs = updateFCS(ofcs, c);
    658  1.1  augustss 		error = put_esc(c, tp);
    659  1.1  augustss 		if (error)
    660  1.1  augustss 			return (error);
    661  1.1  augustss 	}
    662  1.1  augustss 
    663  1.1  augustss 	ofcs = ~ofcs;
    664  1.1  augustss 	error = put_esc(ofcs & 0xff, tp);
    665  1.1  augustss 	if (!error)
    666  1.1  augustss 		error = put_esc((ofcs >> 8) & 0xff, tp);
    667  1.1  augustss 	if (!error)
    668  1.1  augustss 		error = putch(SIR_EOF, tp);
    669  1.1  augustss 
    670  1.1  augustss 	irframetstart(tp);
    671  1.1  augustss 
    672  1.1  augustss 	return (error);
    673  1.1  augustss }
    674  1.1  augustss 
    675  1.1  augustss int
    676  1.1  augustss irframet_poll(void *h, int events, struct proc *p)
    677  1.1  augustss {
    678  1.1  augustss 	struct oboe_softc *sc = h;
    679  1.1  augustss 	int revents = 0;
    680  1.1  augustss 	int s;
    681  1.1  augustss 
    682  1.1  augustss 	DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
    683  1.1  augustss 
    684  1.1  augustss 	s = splir();
    685  1.1  augustss 	if (events & (POLLOUT | POLLWRNORM))
    686  1.1  augustss 		revents |= events & (POLLOUT | POLLWRNORM);
    687  1.1  augustss #if 0
    688  1.1  augustss 	if (events & (POLLIN | POLLRDNORM)) {
    689  1.1  augustss 		if (sc->sc_saved > 0) {
    690  1.1  augustss 			DPRINTF(("%s: have data\n", __FUNCTION__));
    691  1.1  augustss 			revents |= events & (POLLIN | POLLRDNORM);
    692  1.1  augustss 		} else {
    693  1.1  augustss 			DPRINTF(("%s: recording select", __FUNCTION__));
    694  1.1  augustss 			selrecord(p, &sc->sc_rsel);
    695  1.1  augustss 		}
    696  1.1  augustss 	}
    697  1.1  augustss #endif
    698  1.1  augustss 	splx(s);
    699  1.1  augustss 
    700  1.1  augustss 	return (revents);
    701  1.1  augustss }
    702  1.1  augustss 
    703  1.1  augustss int
    704  1.1  augustss irframet_set_params(void *h, struct irda_params *p)
    705  1.1  augustss {
    706  1.1  augustss 	struct tty *tp = h;
    707  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    708  1.1  augustss 
    709  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    710  1.1  augustss 
    711  1.1  augustss 	/* XXX speed */
    712  1.1  augustss 	sc->sc_ebofs = p->ebofs;
    713  1.1  augustss 	/* XXX maxsize */
    714  1.1  augustss 
    715  1.1  augustss 	return (0);
    716  1.1  augustss }
    717  1.1  augustss 
    718  1.1  augustss int
    719  1.1  augustss irframet_reset_params(void *h)
    720  1.1  augustss {
    721  1.1  augustss 	struct tty *tp = h;
    722  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    723  1.1  augustss 
    724  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    725  1.1  augustss 
    726  1.1  augustss 	sc->sc_ebofs = IRDA_DEFAULT_EBOFS;
    727  1.1  augustss 
    728  1.1  augustss 	return (0);
    729  1.1  augustss }
    730  1.1  augustss 
    731  1.1  augustss int
    732  1.1  augustss irframet_get_speeds(void *h, int *speeds)
    733  1.1  augustss {
    734  1.1  augustss 	struct tty *tp = h;
    735  1.1  augustss 
    736  1.1  augustss 	tp = tp;
    737  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    738  1.1  augustss 	*speeds = IRDA_SPEEDS_SIR;
    739  1.1  augustss 	return (0);
    740  1.1  augustss }
    741  1.1  augustss 
    742  1.1  augustss int
    743  1.1  augustss irframet_get_turnarounds(void *h, int *turnarounds)
    744  1.1  augustss {
    745  1.1  augustss 	struct tty *tp = h;
    746  1.1  augustss 
    747  1.1  augustss 	tp = tp;
    748  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    749  1.1  augustss 	*turnarounds = IRDA_TURNT_10000;
    750  1.1  augustss 	return (0);
    751  1.1  augustss }
    752