File: [local] / sys / arch / mvmeppc / dev / bugtty.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:07:44 2008 UTC (16 years, 6 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: bugtty.c,v 1.10 2004/05/14 20:38:32 miod Exp $ */
/* Copyright (c) 1998 Steve Murphree, Jr.
* Copyright (c) 1995 Dale Rahn.
* All rights reserved.
*
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/device.h>
#include <sys/tty.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/queue.h>
#include <machine/autoconf.h>
#include <machine/bugio.h>
#include <machine/conf.h>
#include <machine/cpu.h>
#include <dev/cons.h>
#include "bugtty.h"
int bugttymatch(struct device *parent, void *self, void *aux);
void bugttyattach(struct device *parent, struct device *self, void *aux);
struct cfattach bugtty_ca = {
sizeof(struct device), bugttymatch, bugttyattach
};
struct cfdriver bugtty_cd = {
NULL, "bugtty", DV_TTY
};
/* prototypes */
cons_decl(bugtty);
cdev_decl(bugtty);
int bugttymctl(dev_t dev, int bits, int how);
int bugttyparam(struct tty *tp, struct termios *tm);
void bugtty_chkinput(void);
#define DIALOUT(x) ((x) & 0x80)
#define SWFLAGS(dev) (bugttyswflags | (DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0))
#define BUGBUF 80
char bugtty_ibuffer[BUGBUF+1];
volatile char *pinchar = bugtty_ibuffer;
char bug_obuffer[BUGBUF+1];
#define BUGTTYS 4
struct tty *bugtty_tty[BUGTTYS];
int
bugttymatch(parent, self, aux)
struct device *parent;
void *self;
void *aux;
{
struct confargs *ca = aux;
if (strcmp(ca->ca_name, bugtty_cd.cd_name) != 0)
return (0);
return (1);
}
void
bugttyattach(parent, self, aux)
struct device *parent;
struct device *self;
void *aux;
{
printf(": fallback console\n");
}
#define BUGTTYUNIT(x) ((x) & (0x7f))
void bugttyoutput(struct tty *tp);
int bugttydefaultrate = TTYDEF_SPEED;
int bugttyswflags;
struct tty *
bugttytty(dev)
dev_t dev;
{
int unit;
unit = BUGTTYUNIT(dev);
if (unit >= BUGTTYS) {
return (NULL);
}
return bugtty_tty[unit];
}
int
bugttymctl(dev, bits, how)
dev_t dev;
int bits, how;
{
int s;
/*printf("mctl: dev %x, bits %x, how %x,",dev, bits, how);*/
/* settings are currently ignored */
s = spltty();
switch (how) {
case DMSET:
break;
case DMBIC:
break;
case DMBIS:
break;
case DMGET:
break;
}
splx(s);
bits = 0;
/* proper defaults? */
bits |= TIOCM_DTR;
bits |= TIOCM_RTS;
bits |= TIOCM_CTS;
bits |= TIOCM_CD;
/* bits |= TIOCM_RI; */
bits |= TIOCM_DSR;
/* printf("retbits %x\n", bits); */
return (bits);
}
int
bugttyopen(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
int s, unit = BUGTTYUNIT(dev);
struct tty *tp;
s = spltty();
if (bugtty_tty[unit]) {
tp = bugtty_tty[unit];
} else {
tp = bugtty_tty[unit] = ttymalloc();
}
tp->t_oproc = bugttyoutput;
tp->t_param = NULL;
tp->t_dev = dev;
if ((tp->t_state & TS_ISOPEN) == 0) {
tp->t_state |= TS_WOPEN;
ttychars(tp);
if (tp->t_ispeed == 0) {
/*
* only when cleared do we reset to defaults.
*/
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_cflag = TTYDEF_CFLAG;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_ispeed = tp->t_ospeed = bugttydefaultrate;
}
/* bugtty does not have carrier */
tp->t_cflag |= CLOCAL;
/*
* do these all the time
*/
if (bugttyswflags & TIOCFLAG_CLOCAL)
tp->t_cflag |= CLOCAL;
if (bugttyswflags & TIOCFLAG_CRTSCTS)
tp->t_cflag |= CRTSCTS;
if (bugttyswflags & TIOCFLAG_MDMBUF)
tp->t_cflag |= MDMBUF;
bugttyparam(tp, &tp->t_termios);
ttsetwater(tp);
(void)bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
/*
if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) ||
(bugttymctl(dev, 0, DMGET) & TIOCM_CD))
tp->t_state |= TS_CARR_ON;
else
tp->t_state &= ~TS_CARR_ON;
*/
tp->t_state |= TS_CARR_ON;
} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
splx(s);
return (EBUSY);
}
/*
* if NONBLOCK requested, ignore carrier
*/
/*
if (flag & O_NONBLOCK)
goto done;
*/
splx(s);
/*
* Reset the tty pointer, as there could have been a dialout
* use of the tty with a dialin open waiting.
*/
tp->t_dev = dev;
return ((*linesw[tp->t_line].l_open)(dev, tp));
}
int
bugttyparam(tp, tm)
struct tty *tp;
struct termios *tm;
{
return (0);
}
void
bugttyoutput(tp)
struct tty *tp;
{
int cc, s, cnt;
/* only supports one unit */
if ((tp->t_state & TS_ISOPEN) == 0)
return;
s = spltty();
cc = tp->t_outq.c_cc;
while (cc > 0) {
cnt = min(BUGBUF, cc);
cnt = q_to_b(&tp->t_outq, bug_obuffer, cnt);
mvmeprom_outstr(bug_obuffer, &bug_obuffer[cnt]);
cc -= cnt;
}
splx(s);
}
int
bugttyclose(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
int unit = BUGTTYUNIT(dev);
struct tty *tp = bugtty_tty[unit];
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
#if 0
bugtty_tty[unit] = NULL;
#endif
return (0);
}
int
bugttyread(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
struct tty *tp;
if ((tp = bugtty_tty[BUGTTYUNIT(dev)]) == NULL)
return (ENXIO);
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
/* only to be called at splclk() */
void
bugtty_chkinput()
{
struct tty *tp;
tp = bugtty_tty[0]; /* assumes console on the first port... */
if (tp == NULL)
return;
while (mvmeprom_instat() != 0) {
u_char c = mvmeprom_getchar() & 0xff;
(*linesw[tp->t_line].l_rint)(c, tp);
}
}
int
bugttywrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
#if 0
/* bypass tty output routines. */
int i, cnt, s;
int oldoff;
s = spltty();
oldoff = uio->uio_offset;
do {
uiomove(bug_obuffer, BUGBUF, uio);
bugoutstr(bug_obuffer, &bug_obuffer[uio->uio_offset - oldoff]);
oldoff = uio->uio_offset;
} while (uio->uio_resid != 0);
splx(s);
return (0);
#else
struct tty *tp;
if((tp = bugtty_tty[BUGTTYUNIT(dev)]) == NULL)
return (ENXIO);
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
#endif
}
int
bugttyioctl(dev, cmd, data, flag, p)
dev_t dev;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
int unit = BUGTTYUNIT(dev);
struct tty *tp = bugtty_tty[unit];
int error;
if (!tp)
return (ENXIO);
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return (error);
error = ttioctl(tp, cmd, data, flag, p);
if (error >= 0)
return (error);
switch (cmd) {
case TIOCSBRK:
/* */
break;
case TIOCCBRK:
/* */
break;
case TIOCSDTR:
(void) bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
break;
case TIOCCDTR:
(void) bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
break;
case TIOCMSET:
(void) bugttymctl(dev, *(int *) data, DMSET);
break;
case TIOCMBIS:
(void) bugttymctl(dev, *(int *) data, DMBIS);
break;
case TIOCMBIC:
(void) bugttymctl(dev, *(int *) data, DMBIC);
break;
case TIOCMGET:
*(int *)data = bugttymctl(dev, 0, DMGET);
break;
case TIOCGFLAGS:
*(int *)data = SWFLAGS(dev);
break;
case TIOCSFLAGS:
error = suser(p, 0);
if (error != 0)
return (EPERM);
bugttyswflags = *(int *)data;
bugttyswflags &= /* only allow valid flags */
(TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
break;
default:
return (ENOTTY);
}
return (0);
}
int
bugttystop(tp, flag)
struct tty *tp;
int flag;
{
int s;
s = spltty();
if (tp->t_state & TS_BUSY) {
if ((tp->t_state & TS_TTSTOP) == 0)
tp->t_state |= TS_FLUSH;
}
splx(s);
return (0);
}
/*
* bugtty is the last possible choice for a console device.
*/
void
bugttycnprobe(cp)
struct consdev *cp;
{
int maj;
/* locate the major number */
for (maj = 0; maj < nchrdev; maj++)
if (cdevsw[maj].d_open == bugttyopen)
break;
cp->cn_dev = makedev(maj, 0);
cp->cn_pri = CN_NORMAL;
}
void
bugttycninit(cp)
struct consdev *cp;
{
/* Nothing to do */
}
int
bugttycngetc(dev)
dev_t dev;
{
return (mvmeprom_getchar());
}
void
bugttycnputc(dev, c)
dev_t dev;
char c;
{
mvmeprom_outchar(c);
}