/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles H. Dickman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell and Rick Macklem.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell and Rick Macklem.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
// determine source and loop until all are no longer active
for (;;) {
stat[0] = qvaux_read2(sc, sc->sc_qr.qr_ch_regs[0].qr_sr);
stat[1] = qvaux_read2(sc, sc->sc_qr.qr_ch_regs[1].qr_sr);
if ((stat[0] & SR_RX_RDY) == 0) {
if ((stat[1] & SR_RX_RDY) == 0)
break;
else
line = 1;
}
else
line = 0;
cc = qvaux_read2(sc, sc->sc_qr.qr_ch_regs[line].qr_dat) & 0xFF;
tp = sc->sc_qvaux[line].qvaux_tty;
/* Must be caught early */
if (sc->sc_qvaux[line].qvaux_catch &&
(*sc->sc_qvaux[line].qvaux_catch)(sc->sc_qvaux[line]
.qvaux_private, cc)) {
continue;
}
if (stat[line] & SR_BREAK) // do SR error bits need to be
// cleared by an error reset?
mcc = CNC_BREAK;
else
mcc = cc;
cn_check_magic(tp->t_dev, mcc, qvaux_cnm_state);
if (!(tp->t_state & TS_ISOPEN)) {
cv_broadcast(&tp->t_rawcv);
continue;
}
/* Just send out a char if we have one */
/* As long as we can fill the chip buffer, we just loop here */
// no fifo, just holding register
if (cl->c_cc) {
tp->t_state |= TS_BUSY;
ch = getc(cl);
qvaux_write1(sc, sc->sc_qr.qr_ch_regs[line].qr_dat, ch);
continue;
}
/* Nothing to send, clear the tx flags */
sc->sc_imr &= ~((line) ? (INT_TXB) : (INT_TXA));
qvaux_write2(sc, sc->sc_qr.qr_imr, sc->sc_imr);
int
qvauxopen(dev_t dev, int flag, int mode, struct lwp *l)
{
const int line = QVA_PORT(minor(dev));
struct qvaux_softc *sc = device_lookup_private(&qvaux_cd,
QVA_I2C(minor(dev))); // only one controller
struct tty *tp;
int error = 0;
if (sc == NULL || line >= NQVAUXLINE)
return ENXIO;
/* if some other device is using the line, it's busy */
if (sc->sc_qvaux[line].qvaux_catch)
return EBUSY;
tp = sc->sc_qvaux[line].qvaux_tty;
if (tp == NULL)
return (ENODEV);
/* Use DMBIS and *not* DMSET or else we clobber incoming bits */
if (qvauxmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
tp->t_state |= TS_CARR_ON;
ttylock(tp);
while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
!(tp->t_state & TS_CARR_ON)) {
tp->t_wopen++;
error = ttysleep(tp, &tp->t_rawcv, true, 0);
tp->t_wopen--;
if (error)
break;
}
ttyunlock(tp);
if (error)
return (error);
return ((*tp->t_linesw->l_open)(dev, tp));
}
/*ARGSUSED*/
int
qvauxclose(dev_t dev, int flag, int mode, struct lwp *l)
{
const int line = QVA_PORT(minor(dev));
struct qvaux_softc *sc = device_lookup_private(&qvaux_cd,
QVA_I2C(minor(dev))); // only one controller
struct tty *tp = sc->sc_qvaux[line].qvaux_tty;
(*tp->t_linesw->l_close)(tp, flag);
/* Make sure a BREAK state is not left enabled. */
(void) qvauxmctl(sc, line, DML_BRK, DMBIC);
/* Do a hangup if so required. */
if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN))
(void) qvauxmctl(sc, line, 0, DMSET);
return ttyclose(tp);
}
int
qvauxread(dev_t dev, struct uio *uio, int flag)
{
struct qvaux_softc *sc = device_lookup_private(&qvaux_cd,
QVA_I2C(minor(dev))); // only one controller
struct tty *tp = sc->sc_qvaux[QVA_PORT(minor(dev))].qvaux_tty;
// QVSS has no modem control signals
static unsigned
qvauxmctl(struct qvaux_softc *sc, int line, int bits, int how)
{
/* unsigned status; */
unsigned mbits;
unsigned bit;
int s;
s = spltty();
mbits = 0;
bit = (1 << line);
#if 0
/* external signals as seen from the port */
status = qvaux_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr;
if (status & bit)
mbits |= DML_DCD;
status = qvaux_read1(sc, sc->sc_dr.dr_ring);
if (status & bit)
mbits |= DML_RI;
/* internal signals/state delivered to port */
status = qvaux_read1(sc, sc->sc_dr.dr_dtr);
if (status & bit)
mbits |= DML_DTR;
#endif
if (sc->sc_brk & bit)
mbits |= DML_BRK;
/*
* Called after an ubareset. The QVSS card is reset, but the only thing
* that must be done is to start the receiver and transmitter again.
* No DMA setup to care about.
*/
void
qvauxreset(device_t dev)
{
struct qvaux_softc *sc = device_private(dev);
struct tty *tp;
int i;
for (i = 0; i < NQVAUXLINE; i++) {
tp = sc->sc_qvaux[i].qvaux_tty;
void
qvauxputc(struct qvaux_linestate *ls, int ch)
{
//int line;
int s;
/* if the qvaux has already been attached, the MI
driver will do the transmitting: */
if (ls && ls->qvaux_sc) {
s = spltty();
// line = ls->qvaux_line;
putc(ch, &ls->qvaux_tty->t_outq);
qvauxstart(ls->qvaux_tty);
splx(s);
return;
}
/* use qvauxcnputc to do the transmitting: */
//qvauxcnputc(makedev(cdevsw_lookup_major(&qvaux_cdevsw), 0), ch);
}
#endif /* NQVKBD > 0 || NQVMS > 0 */