154008Sfujita /*
254008Sfujita * Copyright (c) 1992 OMRON Corporation.
3*63192Sbostic * Copyright (c) 1992, 1993
4*63192Sbostic * The Regents of the University of California. All rights reserved.
554008Sfujita *
654008Sfujita * This code is derived from software contributed to Berkeley by
754008Sfujita * OMRON Corporation.
854008Sfujita *
954008Sfujita * %sccs.include.redist.c%
1054008Sfujita *
11*63192Sbostic * @(#)sio.c 8.1 (Berkeley) 06/10/93
1254008Sfujita */
1354008Sfujita
1454008Sfujita /*
1554008Sfujita * sio.c -- NEC uPD7201A UART Device Driver
1656873Sakito * remaked by A.Fujita, NOV-5-1992
1754008Sfujita */
1854008Sfujita
1954008Sfujita #include "sio.h"
2054008Sfujita #if NSIO > 0
2154008Sfujita
2256873Sakito #include "bmc.h"
2354008Sfujita
2457058Sakito #include <sys/param.h>
2557058Sakito #include <sys/systm.h>
2657058Sakito #include <sys/ioctl.h>
2757058Sakito #include <sys/proc.h>
2857058Sakito #include <sys/tty.h>
2957058Sakito #include <sys/conf.h>
3057058Sakito #include <sys/file.h>
3157058Sakito #include <sys/uio.h>
3257058Sakito #include <sys/kernel.h>
3357058Sakito #include <sys/syslog.h>
3454008Sfujita
3557058Sakito #include <luna68k/dev/device.h>
3657058Sakito #include <luna68k/dev/sioreg.h>
3757058Sakito #include <luna68k/dev/siovar.h>
3854008Sfujita
3956873Sakito struct sio_portc *sio_port_assign();
4057291Sakito struct sio_portc *sio_port_get();
4154008Sfujita
4256873Sakito int sioprobe();
4356873Sakito int sioopen();
4456873Sakito void siostart();
4556873Sakito int sioparam();
4656873Sakito int siointr();
4754008Sfujita
4854008Sfujita struct driver siodriver = {
4954008Sfujita sioprobe, "sio",
5054008Sfujita };
5154008Sfujita
5256873Sakito struct sio_portc sio_portc[NPORT] = {
5359648Sakito { -1, -1, 0, (struct siodevice *) 0x51000000, (int (*)()) 0 },
5459648Sakito { -1, -1, 1, (struct siodevice *) 0x51000004, (int (*)()) 0 }
5556873Sakito };
5654008Sfujita
5759648Sakito struct sio_softc sio_softc[NSIO];
5854008Sfujita
5956873Sakito int sio_init_done = 0;
6054008Sfujita
6156873Sakito int siosoftCAR;
6256873Sakito int sio_active;
6357126Sakito int sioconsole = -1;
6456873Sakito int siodefaultrate = TTYDEF_SPEED;
6557291Sakito int siomajor = 12;
6654008Sfujita
6759648Sakito struct tty sio_tty[NSIO];
6854008Sfujita
6956873Sakito struct speedtab siospeedtab[] = {
7056873Sakito 2400, WR4_BAUD24,
7156873Sakito 4800, WR4_BAUD48,
7256873Sakito 9600, WR4_BAUD96,
7354008Sfujita };
7454008Sfujita
7556873Sakito #define siounit(x) minor(x)
7654008Sfujita
7757126Sakito extern struct tty *constty;
7854008Sfujita
7962579Sakito #ifdef KGDB
8054008Sfujita /*
8162579Sakito * Kernel GDB support
8262579Sakito */
8362579Sakito #include <machine/remote-sl.h>
8462579Sakito
8562579Sakito extern dev_t kgdb_dev;
8662579Sakito extern int kgdb_rate;
8762579Sakito extern int kgdb_debug_init;
8862579Sakito #endif
8962579Sakito
9062579Sakito /*
9156873Sakito * probe routines
9254008Sfujita */
9354008Sfujita
sioprobe(hd)9454008Sfujita sioprobe(hd)
9554008Sfujita register struct hp_device *hd;
9654008Sfujita {
9759648Sakito int unit = hd->hp_unit;
9859648Sakito register struct sio_softc *sc = &sio_softc[unit];
9956873Sakito register struct sio_portc *pc;
10054008Sfujita
10159648Sakito if (sc->sc_pc != 0) {
10259648Sakito pc = sc->sc_pc;
10359648Sakito printf("sio%d: port %d, address 0x%x, intr 0x%x (console)\n",
10459648Sakito pc->pc_unit, pc->pc_port, pc->pc_addr, pc->pc_intr);
10562579Sakito return(1);
10659648Sakito }
10754008Sfujita
10862579Sakito sc->sc_pc = pc = sio_port_assign(unit, siomajor, unit, siointr);
10954008Sfujita
11059648Sakito printf("sio%d: port %d, address 0x%x, intr 0x%x\n",
11159648Sakito pc->pc_unit, pc->pc_port, pc->pc_addr, pc->pc_intr);
11254008Sfujita
11359648Sakito sio_active |= 1 << unit;
11462579Sakito
11562579Sakito #ifdef KGDB
11662579Sakito if (major(kgdb_dev) == siomajor) {
11762579Sakito #ifdef notdef
11862579Sakito if (sioconsole == siounit(kgdb_dev)) {
11962579Sakito kgdb_dev = NODEV; /* can't debug over console port */
12062579Sakito } else {
12162579Sakito #endif
12262579Sakito /*
12362579Sakito * The following could potentially be replaced
12462579Sakito * by the corresponding code in dcmcnprobe.
12562579Sakito */
12662579Sakito if (kgdb_debug_init) {
12762579Sakito printf("sio%d: ", siounit(kgdb_dev));
12862579Sakito kgdb_connect(1);
12962579Sakito } else
13062579Sakito printf("sio%d: kgdb enabled\n", siounit(kgdb_dev));
13162579Sakito #ifdef notdef
13262579Sakito }
13362579Sakito #endif
13462579Sakito /* end could be replaced */
13562579Sakito }
13662579Sakito #endif
13762579Sakito
13859648Sakito siosoftCAR |= 1 << unit;
13959648Sakito return(1);
14056873Sakito }
14154008Sfujita
14256873Sakito struct sio_portc *
sio_port_assign(port,major,unit,intr)14356873Sakito sio_port_assign(port, major, unit, intr)
14456873Sakito int port, major, unit;
14556873Sakito int (*intr)();
14656873Sakito {
14757291Sakito register struct sio_portc *pc;
14854008Sfujita
14957291Sakito pc = &sio_portc[port];
15057291Sakito
15156873Sakito pc->pc_major = major;
15256873Sakito pc->pc_intr = intr;
15356873Sakito pc->pc_unit = unit;
15454008Sfujita
15556873Sakito return(pc);
15654008Sfujita }
15754008Sfujita
15857291Sakito struct sio_portc *
sio_port_get(port)15957291Sakito sio_port_get(port)
16057291Sakito int port;
16157291Sakito {
16257291Sakito register struct sio_portc *pc;
16356873Sakito
16457291Sakito pc = &sio_portc[port];
16557291Sakito
16657291Sakito return(pc);
16757291Sakito }
16857291Sakito
16957291Sakito int
sio_port_info()17057291Sakito sio_port_info()
17157291Sakito {
17257291Sakito printf("sio_port_info[sio.c]:\t{%d} major = %d, unit = %d, intr = 0x%x\n",
17357291Sakito 0, sio_portc[0].pc_major, sio_portc[0].pc_unit, sio_portc[0].pc_intr);
17457291Sakito printf("sio_port_info[sio.c]:\t{%d} major = %d, unit = %d, intr = 0x%x\n",
17557291Sakito 1, sio_portc[1].pc_major, sio_portc[1].pc_unit, sio_portc[1].pc_intr);
17657291Sakito }
17757291Sakito
17857291Sakito
17956873Sakito /*
18056873Sakito * entry routines
18156873Sakito */
18256873Sakito
18354008Sfujita /* ARGSUSED */
18454008Sfujita #ifdef __STDC__
sioopen(dev_t dev,int flag,int mode,struct proc * p)18554008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
18654008Sfujita #else
18754008Sfujita sioopen(dev, flag, mode, p)
18854008Sfujita dev_t dev;
18954008Sfujita int flag, mode;
19054008Sfujita struct proc *p;
19154008Sfujita #endif
19254008Sfujita {
19354008Sfujita register struct tty *tp;
19454008Sfujita register int unit;
19554008Sfujita int error = 0;
19654008Sfujita
19754008Sfujita unit = siounit(dev);
19859648Sakito if (unit >= NSIO || (sio_active & (1 << unit)) == 0)
19954008Sfujita return (ENXIO);
20054008Sfujita tp = &sio_tty[unit];
20154008Sfujita tp->t_oproc = siostart;
20254008Sfujita tp->t_param = sioparam;
20354008Sfujita tp->t_dev = dev;
20454008Sfujita if ((tp->t_state & TS_ISOPEN) == 0) {
20554008Sfujita tp->t_state |= TS_WOPEN;
20654008Sfujita ttychars(tp);
20754008Sfujita if (tp->t_ispeed == 0) {
20854008Sfujita tp->t_iflag = TTYDEF_IFLAG;
20954008Sfujita tp->t_oflag = TTYDEF_OFLAG;
21056873Sakito /* tp->t_cflag = TTYDEF_CFLAG; */
21154008Sfujita tp->t_cflag = (CREAD | CS8 | HUPCL);
21254008Sfujita tp->t_lflag = TTYDEF_LFLAG;
21354008Sfujita tp->t_ispeed = tp->t_ospeed = siodefaultrate;
21454008Sfujita }
21554008Sfujita sioparam(tp, &tp->t_termios);
21654008Sfujita ttsetwater(tp);
21754008Sfujita } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
21854008Sfujita return (EBUSY);
21956873Sakito (void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET);
22056873Sakito if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD))
22156873Sakito tp->t_state |= TS_CARR_ON;
22254008Sfujita (void) spltty();
22354008Sfujita while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
22454008Sfujita (tp->t_state & TS_CARR_ON) == 0) {
22554008Sfujita tp->t_state |= TS_WOPEN;
22654008Sfujita if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
22754008Sfujita ttopen, 0))
22854008Sfujita break;
22954008Sfujita }
23054008Sfujita (void) spl0();
23154008Sfujita if (error == 0)
23254008Sfujita error = (*linesw[tp->t_line].l_open)(dev, tp);
23354008Sfujita return (error);
23454008Sfujita }
23556873Sakito
23654008Sfujita /*ARGSUSED*/
sioclose(dev,flag,mode,p)23754008Sfujita sioclose(dev, flag, mode, p)
23854008Sfujita dev_t dev;
23954008Sfujita int flag, mode;
24054008Sfujita struct proc *p;
24154008Sfujita {
24254008Sfujita register struct tty *tp;
24354008Sfujita register int unit;
24454008Sfujita
24554008Sfujita unit = siounit(dev);
24654008Sfujita tp = &sio_tty[unit];
24754008Sfujita (*linesw[tp->t_line].l_close)(tp, flag);
24856873Sakito (void) siomctl(dev, WR5_BREAK, DMBIS);
24956873Sakito if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
25056873Sakito (tp->t_state&TS_ISOPEN) == 0)
25156873Sakito (void) siomctl(dev, 0, DMSET);
25254008Sfujita ttyclose(tp);
25354008Sfujita return (0);
25454008Sfujita }
25554008Sfujita
sioread(dev,uio,flag)25654008Sfujita sioread(dev, uio, flag)
25754008Sfujita dev_t dev;
25854008Sfujita struct uio *uio;
25954008Sfujita {
26054008Sfujita register struct tty *tp = &sio_tty[siounit(dev)];
26154008Sfujita
26254008Sfujita return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
26354008Sfujita }
26454008Sfujita
siowrite(dev,uio,flag)26554008Sfujita siowrite(dev, uio, flag)
26654008Sfujita dev_t dev;
26754008Sfujita struct uio *uio;
26854008Sfujita {
26957126Sakito register int unit = siounit(dev);
27057126Sakito register struct tty *tp = &sio_tty[unit];
27154008Sfujita
27257126Sakito if ((unit == sioconsole) && constty &&
27357126Sakito (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
27457126Sakito tp = constty;
27557126Sakito
27654008Sfujita return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
27754008Sfujita }
27854008Sfujita
27956873Sakito /*
28056873Sakito * Stop output on a line.
28156873Sakito */
28256873Sakito /*ARGSUSED*/
siostop(tp,flag)28356873Sakito siostop(tp, flag)
28456873Sakito register struct tty *tp;
28554008Sfujita {
28656873Sakito register int s;
28754008Sfujita
28856873Sakito s = spltty();
28956873Sakito if (tp->t_state & TS_BUSY) {
29056873Sakito if ((tp->t_state&TS_TTSTOP)==0)
29156873Sakito tp->t_state |= TS_FLUSH;
29254008Sfujita }
29356873Sakito splx(s);
29454008Sfujita }
29554008Sfujita
sioioctl(dev,cmd,data,flag,p)29654008Sfujita sioioctl(dev, cmd, data, flag, p)
29754008Sfujita dev_t dev;
29854008Sfujita int cmd;
29954008Sfujita caddr_t data;
30054008Sfujita int flag;
30154008Sfujita struct proc *p;
30254008Sfujita {
30354008Sfujita register struct tty *tp;
30454008Sfujita register int unit = siounit(dev);
30554008Sfujita register int error;
30656873Sakito
30754008Sfujita tp = &sio_tty[unit];
30854008Sfujita error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
30954008Sfujita if (error >= 0)
31054008Sfujita return (error);
31154008Sfujita error = ttioctl(tp, cmd, data, flag);
31254008Sfujita if (error >= 0)
31354008Sfujita return (error);
31454008Sfujita
31554008Sfujita switch (cmd) {
31654008Sfujita
31754008Sfujita case TIOCSBRK:
31856873Sakito (void) siomctl(dev, WR5_BREAK, DMBIS);
31956873Sakito break;
32056873Sakito
32154008Sfujita case TIOCCBRK:
32256873Sakito (void) siomctl(dev, WR5_BREAK, DMBIC);
32356873Sakito break;
32456873Sakito
32554008Sfujita case TIOCSDTR:
32656873Sakito (void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS);
32756873Sakito break;
32856873Sakito
32954008Sfujita case TIOCCDTR:
33056873Sakito (void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC);
33156873Sakito break;
33256873Sakito
33354008Sfujita case TIOCMSET:
33456873Sakito (void) siomctl(dev, *(int *)data, DMSET);
33556873Sakito break;
33656873Sakito
33754008Sfujita case TIOCMBIS:
33856873Sakito (void) siomctl(dev, *(int *)data, DMBIS);
33956873Sakito break;
34056873Sakito
34154008Sfujita case TIOCMBIC:
34256873Sakito (void) siomctl(dev, *(int *)data, DMBIC);
34356873Sakito break;
34456873Sakito
34554008Sfujita case TIOCMGET:
34656873Sakito *(int *)data = siomctl(dev, 0, DMGET);
34756873Sakito break;
34856873Sakito
34954008Sfujita default:
35054008Sfujita return (ENOTTY);
35154008Sfujita }
35254008Sfujita return (0);
35354008Sfujita }
35454008Sfujita
35554008Sfujita
35656873Sakito /*
35756873Sakito *
35856873Sakito */
35956873Sakito
36054008Sfujita void
siostart(tp)36154008Sfujita siostart(tp)
36254008Sfujita register struct tty *tp;
36354008Sfujita {
36454008Sfujita register struct siodevice *sio;
36556873Sakito register int rr;
36656873Sakito int s, unit, c;
36754008Sfujita
36854008Sfujita unit = siounit(tp->t_dev);
36956873Sakito sio = sio_softc[unit].sc_pc->pc_addr;
37054008Sfujita s = spltty();
37154008Sfujita if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
37254008Sfujita goto out;
37354008Sfujita if (tp->t_outq.c_cc <= tp->t_lowat) {
37454008Sfujita if (tp->t_state&TS_ASLEEP) {
37554008Sfujita tp->t_state &= ~TS_ASLEEP;
37654008Sfujita wakeup((caddr_t)&tp->t_outq);
37754008Sfujita }
37854008Sfujita selwakeup(&tp->t_wsel);
37954008Sfujita }
38054008Sfujita if (tp->t_outq.c_cc == 0)
38154008Sfujita goto out;
38256873Sakito rr = siogetreg(sio);
38354008Sfujita if (rr & RR_TXRDY) {
38454008Sfujita c = getc(&tp->t_outq);
38554008Sfujita tp->t_state |= TS_BUSY;
38654008Sfujita sio->sio_data = c;
38754008Sfujita }
38854008Sfujita out:
38954008Sfujita splx(s);
39054008Sfujita }
39156873Sakito
sioparam(tp,t)39256873Sakito sioparam(tp, t)
39356873Sakito register struct tty *tp;
39456873Sakito register struct termios *t;
39556873Sakito {
39656873Sakito int unit = siounit(tp->t_dev);
39756873Sakito register struct siodevice *sio;
39856873Sakito register cflag = t->c_cflag;
39956873Sakito register u_char wr;
40056873Sakito int ospeed = ttspeedtab(t->c_ospeed, siospeedtab);
40156873Sakito
40256873Sakito sio = sio_softc[unit].sc_pc->pc_addr;
40356873Sakito
40456873Sakito switch (cflag & CSIZE) {
40556873Sakito case CS5:
40656873Sakito case CS6:
40756873Sakito case CS7:
40856873Sakito case CS8:
40956873Sakito break;
41056873Sakito }
41156873Sakito
41256873Sakito wr = ospeed;
41356873Sakito
41456873Sakito if (cflag & PARENB) {
41556873Sakito wr |= WR4_PARENAB;
41656873Sakito if ((cflag&PARODD) == 0)
41756873Sakito wr |= WR4_EPARITY;
41856873Sakito }
41956873Sakito
42056873Sakito if (cflag & CSTOPB)
42156873Sakito wr |= WR4_STOP2; /* 2 stop bit */
42256873Sakito else
42356873Sakito wr |= WR4_STOP1; /* 1 stop bit */
42456873Sakito
42556873Sakito (void) sioreg(sio, WR4, wr);
42656873Sakito
42756873Sakito return (0);
42856873Sakito }
42956873Sakito
siomctl()43056873Sakito siomctl()
43156873Sakito {
43256873Sakito return (0);
43356873Sakito }
43456873Sakito
43556873Sakito
43654008Sfujita /*
43756873Sakito * Interrupt handling
43854008Sfujita */
43956873Sakito
44056873Sakito void
_siointr()44156873Sakito _siointr()
44254008Sfujita {
44356873Sakito register int port;
44456873Sakito register struct sio_portc *pc;
44554008Sfujita
44656873Sakito for (port = 0; port < NPORT; port++) {
44756873Sakito pc = &sio_portc[port];
44856873Sakito
44956873Sakito if (pc->pc_major != -1)
45056873Sakito (pc->pc_intr)(pc->pc_unit);
45154008Sfujita }
45254008Sfujita }
45354008Sfujita
siointr(unit)45456873Sakito siointr(unit)
45556873Sakito register int unit;
45656873Sakito {
45756873Sakito register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr;
45856873Sakito register u_char code;
45956873Sakito register struct tty *tp;
46056873Sakito int s, rr;
46156873Sakito
46256873Sakito tp = &sio_tty[unit];
46357850Sakito
46457850Sakito start:
46556873Sakito rr = siogetreg(sio);
46657850Sakito if (rr & RR_RXRDY) {
46757850Sakito if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
46857850Sakito sioeint(unit, rr, sio);
46957850Sakito goto start;
47057850Sakito }
47156873Sakito
47256873Sakito code = sio->sio_data;
47356873Sakito if ((tp->t_state & TS_ISOPEN) != 0)
47456873Sakito (*linesw[tp->t_line].l_rint)(code, tp);
47562579Sakito #ifdef KGDB
47662579Sakito else {
47762579Sakito if (code == FRAME_END &&
47862579Sakito kgdb_dev == makedev(siomajor, unit))
47962579Sakito kgdb_connect(0); /* trap into kgdb */
48062579Sakito }
48162579Sakito #endif
48257850Sakito while ((rr = siogetreg(sio)) & RR_RXRDY) {
48357850Sakito code = sio->sio_data;
48457850Sakito if ((tp->t_state & TS_ISOPEN) != 0)
48557850Sakito (*linesw[tp->t_line].l_rint)(code, tp);
48662579Sakito #ifdef KGDB
48762579Sakito else {
48862579Sakito if (code == FRAME_END &&
48962579Sakito kgdb_dev == makedev(siomajor, unit))
49062579Sakito kgdb_connect(0); /* trap into kgdb */
49162579Sakito }
49262579Sakito #endif
49357850Sakito }
49456873Sakito }
49556873Sakito
49656873Sakito if (rr & RR_TXRDY) {
49756873Sakito sio->sio_cmd = WR0_RSTPEND;
49856873Sakito tp->t_state &= ~(TS_BUSY|TS_FLUSH);
49956873Sakito if (tp->t_line)
50056873Sakito (*linesw[tp->t_line].l_start)(tp);
50156873Sakito else
50256873Sakito siostart(tp);
50356873Sakito }
50456873Sakito }
50556873Sakito
sioeint(unit,stat,sio)50657850Sakito sioeint(unit, stat, sio)
50757850Sakito register int unit, stat;
50857850Sakito register struct siodevice *sio;
50957850Sakito {
51057850Sakito register struct tty *tp;
51157850Sakito register int code;
51257850Sakito
51357850Sakito tp = &sio_tty[unit];
51457850Sakito
51557850Sakito code = sio->sio_data;
51657850Sakito
51757850Sakito sio->sio_cmd = WR0_ERRRST;
51857850Sakito
51962579Sakito if ((tp->t_state & TS_ISOPEN) == 0) {
52062579Sakito #ifdef KGDB
52162579Sakito /* we don't care about parity errors */
52262579Sakito if (((stat & (RR_FRAMING|RR_PARITY)) == RR_PARITY) &&
52362579Sakito kgdb_dev == makedev(siomajor, unit) && code == FRAME_END)
52462579Sakito kgdb_connect(0); /* trap into kgdb */
52562579Sakito #endif
52657850Sakito return;
52762579Sakito }
52857850Sakito
52957850Sakito if (stat & RR_FRAMING)
53057850Sakito code |= TTY_FE;
53157850Sakito else if (stat & RR_PARITY)
53257850Sakito code |= TTY_PE;
53357850Sakito
53457850Sakito (*linesw[tp->t_line].l_rint)(code, tp);
53557850Sakito }
53657850Sakito
53754008Sfujita /*
53854008Sfujita * Following are all routines needed for SIO to act as console
53954008Sfujita */
54057058Sakito #include <luna68k/luna68k/cons.h>
54154008Sfujita
siocnprobe(cp)54254008Sfujita siocnprobe(cp)
54356873Sakito register struct consdev *cp;
54454008Sfujita {
54556873Sakito register int unit = 0;
54654008Sfujita
54754008Sfujita /* locate the major number */
54854008Sfujita for (siomajor = 0; siomajor < nchrdev; siomajor++)
54954008Sfujita if (cdevsw[siomajor].d_open == sioopen)
55054008Sfujita break;
55154008Sfujita
55254008Sfujita /* initialize required fields */
55354008Sfujita cp->cn_dev = makedev(siomajor, unit);
55456873Sakito cp->cn_tp = &sio_tty[unit];
55554008Sfujita cp->cn_pri = CN_NORMAL;
55654008Sfujita }
55754008Sfujita
55854008Sfujita siocninit(cp)
55954008Sfujita struct consdev *cp;
56054008Sfujita {
56154008Sfujita int unit = siounit(cp->cn_dev);
56256873Sakito register struct sio_softc *sc = &sio_softc[unit];
56354008Sfujita
56456873Sakito sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate);
56556873Sakito
56656873Sakito /* port assign */
56759648Sakito sc->sc_pc = sio_port_assign(SIO_PORT, siomajor, unit, siointr);
56856873Sakito
56954008Sfujita sioconsole = unit;
57056873Sakito sio_active |= 1 << unit;
57156873Sakito siosoftCAR |= 1 << unit;
57254008Sfujita }
57354008Sfujita
siocngetc(dev)57454008Sfujita siocngetc(dev)
57554008Sfujita dev_t dev;
57654008Sfujita {
57756873Sakito struct sio_softc *sc = &sio_softc[siounit(dev)];
57856873Sakito struct sio_portc *pc = sc->sc_pc;
57954008Sfujita
58056873Sakito return(sio_imgetc(pc->pc_addr));
58154008Sfujita }
58254008Sfujita
siocnputc(dev,c)58354008Sfujita siocnputc(dev, c)
58454008Sfujita dev_t dev;
58554008Sfujita int c;
58654008Sfujita {
58756873Sakito struct sio_softc *sc = &sio_softc[siounit(dev)];
58856873Sakito struct sio_portc *pc = sc->sc_pc;
58954008Sfujita
59056873Sakito sio_imputc(pc->pc_addr, c);
59156873Sakito }
59254008Sfujita
59354008Sfujita
59456873Sakito /*
59556873Sakito * sio raw-level routines
59656873Sakito */
59754008Sfujita
sioinit(sio0,rate)59856873Sakito sioinit(sio0, rate)
59956873Sakito register struct siodevice *sio0;
60056873Sakito register int rate;
60156873Sakito {
60256873Sakito register struct siodevice *sio1;
60356873Sakito int s;
60454008Sfujita
60556873Sakito rate = ttspeedtab(rate, siospeedtab);
60654008Sfujita
60756873Sakito if (sio_init_done)
60856873Sakito return;
60954008Sfujita
61056873Sakito sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice));
61154008Sfujita
61254008Sfujita s = splhigh();
61354008Sfujita
61456873Sakito sioreg(sio0, WR0, WR0_CHANRST); /* Channel-A Reset */
61554008Sfujita
61656873Sakito sioreg(sio0, WR2, (WR2_VEC86 | WR2_INTR_1)); /* Set CPU BUS Interface Mode */
61756873Sakito sioreg(sio1, WR2, 0); /* Set Interrupt Vector */
61854008Sfujita
61956873Sakito sioreg(sio0, WR0, WR0_RSTINT); /* Reset E/S Interrupt */
62056873Sakito sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY)); /* Tx/Rx */
62156873Sakito sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL)); /* Rx */
62256873Sakito sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL)); /* Tx */
62356873Sakito sioreg(sio0, WR0, WR0_RSTINT); /* Reset E/S Interrupt */
62456873Sakito sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL));
62554008Sfujita
62656873Sakito sioreg(sio1, WR0, WR0_CHANRST); /* Channel-B Reset */
62754008Sfujita
62856873Sakito sioreg(sio1, WR0, WR0_RSTINT); /* Reset E/S Interrupt */
62956873Sakito sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY)); /* Tx/Rx */
63056873Sakito sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL)); /* Rx */
63156873Sakito sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL)); /* Tx */
63256873Sakito sioreg(sio1, WR0, WR0_RSTINT); /* Reset E/S Interrupt */
63356873Sakito sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL));
63456873Sakito
63554008Sfujita splx(s);
63656873Sakito
63756873Sakito sio_init_done = 1;
63854008Sfujita }
63954008Sfujita
sio_imgetc(sio)64056873Sakito sio_imgetc(sio)
64156873Sakito register struct siodevice *sio;
64254008Sfujita {
64356873Sakito register int rr0, rr1;
64456873Sakito int c, s;
64554008Sfujita
64656873Sakito s = splhigh();
64756873Sakito while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0)
64856873Sakito ;
64956873Sakito c = sio->sio_data;
65056873Sakito sioreg(sio, WR0, WR0_RSTPEND);
65156873Sakito splx(s);
65256873Sakito return (c);
65354008Sfujita }
65454008Sfujita
sio_imputc(sio,c)65556873Sakito sio_imputc(sio, c)
65656873Sakito register struct siodevice *sio;
65754008Sfujita int c;
65854008Sfujita {
65954008Sfujita register u_char code;
66056873Sakito register int rr;
66156873Sakito int s;
66254008Sfujita
66354008Sfujita s = splhigh();
66454008Sfujita
66556873Sakito sioreg(sio, WR1, WR1_RXALLS);
66656873Sakito
66754008Sfujita do {
66854008Sfujita DELAY(1);
66956873Sakito rr = siogetreg(sio);
67054008Sfujita } while (!(rr & RR_TXRDY));
67156873Sakito
67256873Sakito code = (c & 0xFF);
67354008Sfujita sio->sio_data = code;
67454008Sfujita
67554008Sfujita do {
67654008Sfujita DELAY(1);
67756873Sakito rr = siogetreg(sio);
67854008Sfujita } while (!(rr & RR_TXRDY));
67954008Sfujita
68056873Sakito sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL));
68156873Sakito
68254008Sfujita splx(s);
68354008Sfujita }
68454008Sfujita
68556873Sakito /*
68656873Sakito * uPD7201A register operation
68756873Sakito */
68854008Sfujita
68954008Sfujita int
siogetreg(sio)69056873Sakito siogetreg(sio)
69156873Sakito register struct siodevice *sio;
69254008Sfujita {
69354008Sfujita register int rr = 0;
69454008Sfujita
69554008Sfujita rr = sio->sio_stat;
69654008Sfujita rr <<= 8;
69754008Sfujita sio->sio_cmd = 1; /* Select RR1 */
69854008Sfujita rr |= sio->sio_stat;
69954008Sfujita
70054008Sfujita return(rr);
70154008Sfujita }
70254008Sfujita
70354008Sfujita int
sioreg(sio,reg,val)70456873Sakito sioreg(sio, reg, val)
70556873Sakito register struct siodevice *sio;
70654008Sfujita register int reg, val;
70754008Sfujita {
70854008Sfujita if (isStatusReg(reg)) {
70956873Sakito if (reg != 0)
71056873Sakito sio->sio_cmd = reg;
71156873Sakito val = sio->sio_stat;
71254008Sfujita } else {
71356873Sakito if (reg != 0)
71456873Sakito sio->sio_cmd = reg;
71556873Sakito sio->sio_cmd = val;
71654008Sfujita }
71756873Sakito
71856873Sakito return(val);
71954008Sfujita }
72054008Sfujita #endif
721