/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code was written by Alessandro Forin and Neil Pittman
* at Microsoft Research and contributed to The NetBSD Foundation
* by Microsoft Corporation.
*
* 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.
*/
#ifndef TIOCM_BRK
#define TIOCM_BRK 0100000 /* no equivalent */
static void dzstart(struct tty *);
static int dzparam(struct tty *, struct termios *);
static unsigned dzmctl(struct dz_softc *sc, int line,
int bits, /* one of the TIOCM_xx */
int how); /* one of the DMSET/BIS.. */
/* 10 times error in percent: */
error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
/* 3.0% maximum error tolerance: */
if (error < -30 || error > 30)
return -1;
return divisor;
}
static int
dzparam(struct tty *tp, struct termios *t)
{
struct dz_softc *sc;
int cflag = t->c_cflag;
int unit, line;
int speed;
unsigned lpr;
int s;
struct _Usart *dzr;
unit = DZ_I2C(minor(tp->t_dev));
line = DZ_PORT(minor(tp->t_dev));
sc = device_lookup_private(&dz_cd, unit);
/* check requested parameters */
if (t->c_ispeed != t->c_ospeed)
return EINVAL;
speed = dzdivisor(t->c_ispeed);
if (speed < 0)
return EINVAL;
/* Just send out a char if we have one */
if (cl->c_cc) {
tp->t_state |= TS_BUSY;
ch = getc(cl);
dzr->TxData = ch;
dzr->IntrEnable = USI_TXRDY;
return;
}
/* Nothing to send; turn off intr */
dzr->IntrDisable = USI_TXRDY;
if (tp->t_state & TS_FLUSH)
tp->t_state &= ~TS_FLUSH;
else
ndflush(&tp->t_outq, cl->c_cc);
(*tp->t_linesw->l_start)(tp);
}
/*
* Machdep part of the driver
*/
int dz_ebus_match(device_t, cfdata_t, void *);
void dz_ebus_attach(device_t, device_t, void *);
int dz_ebus_intr(void *, void *);
for (; ((csr = (dzr->ChannelStatus & dzr->IntrMask)) &
USI_INTERRUPTS) != 0;) {
if ((csr & USI_INTRS) != 0)
dzrint(sc, csr);
if ((csr & USI_TXRDY) != 0)
dzxint(sc, csr);
}
return 0;
}
void
dz_ebus_cnsetup(paddr_t addr)
{
dzcn = (struct _Usart *)addr;
#if 0
/*
* Initialize enough to xmit/recv via polling.
* Bootloader might or might not have done it.
*/
dzcn->Control =
USC_RXEN |
USC_TXEN |
USC_BPC_8 |
USC_NONE |
USC_1STOP |
USC_CLKDIV_4;
dzcn->Baud = 0x29; /* 38400 */
#endif
/*
* Point the console at us
*/
cn_tab = &dz_ebus_consdev;
cn_tab->cn_pri = CN_NORMAL;/*CN_REMOTE?*/
cn_tab->cn_dev = makedev(dz_ebus_getmajor(), 0);
}
void
dz_ebus_cninit(struct consdev *cn)
{
}
int
dz_ebus_cngetc(dev_t dev)
{
int c, s;
c = 0;
s = spltty();
while ((dzcn->ChannelStatus & USI_RXRDY) == 0)
DELAY(10);
c = dzcn->RxData;
splx(s);
if (c == 13) /* map cr->ln */
c = 10;
return c;
}
int dzflipped = 0;
void
dz_ebus_cnputc(dev_t dev, int ch)
{
int timeout, s;
/* Don't hang the machine! */
timeout = 1 << 15;
s = spltty();
#if 1
/* Keep wired to hunt for a bug */
if (dzcn && (dzcn != (struct _Usart *)0xfff90000)) {
dzcn = (struct _Usart *)0xfff90000;
dzflipped++;
}
#endif
/* Wait until ready */
while ((dzcn->ChannelStatus & USI_TXRDY) == 0)
if (--timeout < 0)
break;
/* Put the character */
dzcn->TxData = ch;
splx(s);
}
/*
* Called before/after going into poll mode
*/
void
dz_ebus_cnpollc(dev_t dev, int on)
{
}