summaryrefslogtreecommitdiff
path: root/os/ks32/devuart.c
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
commit78ee7d5717807e6ac779293d0d3c78341de6130a (patch)
treea43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/ks32/devuart.c
parentbdaf46cf45bbb59261da245d548a179d95a42768 (diff)
Move existing boards into subdits split per arch
Diffstat (limited to 'os/ks32/devuart.c')
-rw-r--r--os/ks32/devuart.c719
1 files changed, 0 insertions, 719 deletions
diff --git a/os/ks32/devuart.c b/os/ks32/devuart.c
deleted file mode 100644
index 2251dd59..00000000
--- a/os/ks32/devuart.c
+++ /dev/null
@@ -1,719 +0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-#include "../port/netif.h"
-
-/*
- * currently no DMA or flow control (hardware or software)
- */
-
-/*
- * problems fixed from previous vsn:
- *
- * - no kick on queue's, so redirections weren't getting
- * started until the clock tick
- *
- * - lots of unnecessary overhead
- *
- * - initialization sequencing
- *
- * - uart[n] no longer indexed before calling uartinstall()
- */
-#define DEBUG if(0)iprint
-
-static void uartintr(Ureg*, void*);
-
-enum
-{
- Stagesize= 1024,
- Dmabufsize=Stagesize/2,
- Nuart=7, /* max per machine */
-};
-
-typedef struct Uart Uart;
-struct Uart
-{
- QLock;
-
- int opens;
-
- int enabled;
-
- int port; /* 0 or 1 */
- int kickme; /* for kick */
- int frame; /* framing errors */
- int overrun; /* rcvr overruns */
- int perror; /* parity error */
- int bps; /* baud rate */
- uchar bits;
- char parity;
- uchar stop;
-
- int inters; /* total interrupt count */
- int rinters; /* interrupts due to read */
- int winters; /* interrupts due to write */
-
- int rcount; /* total read count */
- int wcount; /* total output count */
-
- /* buffers */
- int (*putc)(Queue*, int);
- Queue *iq;
- Queue *oq;
-
- UartReg *reg;
-
- /* staging areas to avoid some of the per character costs */
- uchar *ip;
- uchar *ie;
- uchar *op;
- uchar *oe;
-
- /* put large buffers last to aid register-offset optimizations: */
- char name[KNAMELEN];
- uchar istage[Stagesize];
- uchar ostage[Stagesize];
-};
-
-#define UCON_ENABLEMASK (UCON_RXMDMASK | UCON_TXMDMASK | UCON_SINTMASK)
-#define UCON_ENABLESET (UCON_RXMDINT | UCON_TXMDINT | UCON_SINTON)
-#define UCON_DISABLESET (UCON_RXMDOFF | UCON_TXMDOFF | UCON_SINTOFF)
-
-static Uart *uart[Nuart];
-static int nuart;
-
-static uchar
-readstatus(Uart *p)
-{
- UartReg *reg = p->reg;
- uchar stat = reg->stat;
- if (stat & USTAT_OV)
- p->overrun++;
- if (stat & USTAT_PE)
- p->perror++;
- if (stat & USTAT_FE)
- p->frame++;
- return stat;
-}
-
-static void
-uartset(Uart *p)
-{
- UartReg *reg = p->reg;
- ulong denom;
- ulong brdiv;
- int n;
- uchar lcon;
-
- lcon= ULCON_CLOCKMCLK | ULCON_IROFF;
- lcon |= ULCON_WL5 + (p->bits - 5);
- lcon |= p->stop == 1 ? ULCON_STOP1 : ULCON_STOP2;
- switch (p->parity) {
- default:
- case 'n':
- lcon |= ULCON_PMDNONE;
- break;
- case 'o':
- lcon |= ULCON_PMDODD;
- break;
- case 'e':
- lcon |= ULCON_PMDEVEN;
- break;
- }
- reg->lcon = lcon;
-
- /* clear the break and loopback bits; leave everything else alone */
- reg->con = (reg->con & ~(UCON_BRKMASK | UCON_LOOPMASK)) | UCON_BRKOFF | UCON_LOOPOFF;
-
- denom = 2 * 16 * p->bps;
- brdiv = (TIMER_HZ + denom / 2) / denom - 1;
- reg->brdiv = brdiv << 4;
-
- /* set buffer length according to speed, to allow
- * at most a 200ms delay before dumping the staging buffer
- * into the input queue
- */
- n = p->bps/(10*1000/200);
- p->ie = &p->istage[n < Stagesize ? n : Stagesize];
-}
-
-/*
- * send break
- */
-static void
-uartbreak(Uart *p, int ms)
-{
- UartReg *reg = p->reg;
- if(ms == 0)
- ms = 200;
- reg->con |= UCON_BRKON;
- tsleep(&up->sleep, return0, 0, ms);
- reg->con &= ~UCON_BRKON;
-}
-
-/*
- * turn on a port
- */
-static void
-uartenable(Uart *p)
-{
- UartReg *reg = p->reg;
-
- if(p->enabled)
- return;
-
- uartset(p);
- // enable receive, transmit, and receive interrupt:
- reg->con = (reg->con & UCON_ENABLEMASK) | UCON_ENABLESET;
- p->enabled = 1;
-}
-
-/*
- * turn off a port
- */
-static void
-uartdisable(Uart *p)
-{
- p->reg->con = (p->reg->con & UCON_ENABLEMASK) | UCON_DISABLESET;
- p->enabled = 0;
-}
-
-/*
- * put some bytes into the local queue to avoid calling
- * qconsume for every character
- */
-static int
-stageoutput(Uart *p)
-{
- int n;
- Queue *q = p->oq;
-
- if(!q)
- return 0;
- n = qconsume(q, p->ostage, Stagesize);
- if(n <= 0)
- return 0;
- p->op = p->ostage;
- p->oe = p->ostage + n;
- return n;
-}
-
-static void
-uartxmit(Uart *p)
-{
- UartReg *reg = p->reg;
- ulong gag = 1;
- while(p->op < p->oe || stageoutput(p)) {
- if(readstatus(p) & USTAT_TBE) {
- DEBUG("T");
- reg->txbuf = *(p->op++);
- p->wcount++;
- } else {
- DEBUG("F");
- gag = 0;
- break;
- }
- }
- if (gag) {
- DEBUG("G");
- p->kickme = 1;
- intrmask(UARTTXbit(p->port), 0);
- }
-}
-
-static void
-uartrecvq(Uart *p)
-{
- uchar *cp = p->istage;
- int n = p->ip - cp;
-
- if(n == 0)
- return;
- if(p->putc)
- while(n-- > 0)
- p->putc(p->iq, *cp++);
- else if(p->iq)
- if(qproduce(p->iq, p->istage, n) < n)
- print("qproduce flow control");
- p->ip = p->istage;
-}
-
-static void
-uartrecv(Uart *p)
-{
- UartReg *reg = p->reg;
- uchar stat = readstatus(p);
-
-DEBUG("R");
- if (stat & USTAT_RDR) {
- int c;
- c = reg->rxbuf;
- if (c == '?') {
- DEBUG("mod 0x%.8lx\n", INTREG->mod);
- DEBUG("msk 0x%.8lx\n", INTREG->msk);
- DEBUG("pnd 0x%.8lx\n", INTREG->pnd);
- }
- *p->ip++ = c;
-/* if(p->ip >= p->ie) */
- uartrecvq(p);
- p->rcount++;
- }
-}
-
-static void
-uartkick(void *a)
-{
- Uart *p = a;
- int x = splhi();
- DEBUG("k");
- if (p->kickme) {
- p->kickme = 0;
- DEBUG("K");
- intrunmask(UARTTXbit(p->port), 0);
- }
- splx(x);
-}
-
-/*
- * UART Interrupt Handler
- */
-static void
-uarttxintr(Ureg*, void* arg)
-{
- Uart *p = arg;
- intrclear(UARTTXbit(p->port), 0);
- p->inters++;
- p->winters++;
- uartxmit(p);
-}
-
-static void
-uartrxintr(Ureg*, void* arg)
-{
- Uart *p = arg;
- intrclear(UARTRXbit(p->port), 0);
- p->inters++;
- p->rinters++;
- uartrecv(p);
-}
-
-
-static void
-uartsetup(ulong port, char *name)
-{
- Uart *p;
-
- if(nuart >= Nuart)
- return;
-
- p = xalloc(sizeof(Uart));
- uart[nuart++] = p;
- strcpy(p->name, name);
-
- p->reg = &UARTREG[port];
- p->bps = 9600;
- p->bits = 8;
- p->parity = 'n';
- p->stop = 1;
- p->kickme = 0;
- p->port = port;
-
- p->iq = qopen(4*1024, 0, 0 , p);
- p->oq = qopen(4*1024, 0, uartkick, p);
-
- p->ip = p->istage;
- p->ie = &p->istage[Stagesize];
- p->op = p->ostage;
- p->oe = p->ostage;
-
- intrenable(UARTTXbit(port), uarttxintr, p, 0);
- intrenable(UARTRXbit(port), uartrxintr, p, 0);
-}
-
-static void
-uartinstall(void)
-{
- static int already;
-
- if(already)
- return;
- already = 1;
-
- uartsetup(0, "eia0");
-// uartsetup(1, "eia1");
-}
-
-/*
- * called by main() to configure a duart port as a console or a mouse
- */
-void
-uartspecial(int port, int bps, char parity, Queue **in, Queue **out, int (*putc)(Queue*, int))
-{
- Uart *p;
-
- uartinstall();
- if(port >= nuart)
- return;
- p = uart[port];
- if(bps)
- p->bps = bps;
- if(parity)
- p->parity = parity;
- uartenable(p);
- p->putc = putc;
- if(in)
- *in = p->iq;
- if(out)
- *out = p->oq;
- p->opens++;
-}
-
-Dirtab *uartdir;
-int ndir;
-
-static void
-setlength(int i)
-{
- Uart *p;
-
- if(i > 0){
- p = uart[i];
- if(p && p->opens && p->iq)
- uartdir[1+3*i].length = qlen(p->iq);
- } else for(i = 0; i < nuart; i++){
- p = uart[i];
- if(p && p->opens && p->iq)
- uartdir[1+3*i].length = qlen(p->iq);
- }
-}
-
-/*
- * all uarts must be uartsetup() by this point or inside of uartinstall()
- */
-static void
-uartreset(void)
-{
- int i;
- Dirtab *dp;
-
- uartinstall();
-
- ndir = 1+3*nuart;
- uartdir = xalloc(ndir * sizeof(Dirtab));
- dp = uartdir;
- strcpy(dp->name, ".");
- mkqid(&dp->qid, 0, 0, QTDIR);
- dp->length = 0;
- dp->perm = DMDIR|0555;
- dp++;
- for(i = 0; i < nuart; i++){
- /* 3 directory entries per port */
- strcpy(dp->name, uart[i]->name);
- dp->qid.path = NETQID(i, Ndataqid);
- dp->perm = 0660;
- dp++;
- sprint(dp->name, "%sctl", uart[i]->name);
- dp->qid.path = NETQID(i, Nctlqid);
- dp->perm = 0660;
- dp++;
- sprint(dp->name, "%sstatus", uart[i]->name);
- dp->qid.path = NETQID(i, Nstatqid);
- dp->perm = 0444;
- dp++;
- }
-}
-
-static Chan*
-uartattach(char *spec)
-{
- return devattach('t', spec);
-}
-
-static Walkqid*
-uartwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, uartdir, ndir, devgen);
-}
-
-static int
-uartstat(Chan *c, uchar *dp, int n)
-{
- if(NETTYPE(c->qid.path) == Ndataqid)
- setlength(NETID(c->qid.path));
- return devstat(c, dp, n, uartdir, ndir, devgen);
-}
-
-static Chan*
-uartopen(Chan *c, int omode)
-{
- Uart *p;
-
- c = devopen(c, omode, uartdir, ndir, devgen);
-
- switch(NETTYPE(c->qid.path)){
- case Nctlqid:
- case Ndataqid:
- p = uart[NETID(c->qid.path)];
- qlock(p);
- if(p->opens++ == 0){
- uartenable(p);
- qreopen(p->iq);
- qreopen(p->oq);
- }
- qunlock(p);
- break;
- }
-
- return c;
-}
-
-static void
-uartclose(Chan *c)
-{
- Uart *p;
-
- if(c->qid.type & QTDIR)
- return;
- if((c->flag & COPEN) == 0)
- return;
- switch(NETTYPE(c->qid.path)){
- case Ndataqid:
- case Nctlqid:
- p = uart[NETID(c->qid.path)];
- qlock(p);
- if(--(p->opens) == 0){
- uartdisable(p);
- qclose(p->iq);
- qclose(p->oq);
- p->ip = p->istage;
- }
- qunlock(p);
- break;
- }
-}
-
-static long
-uartstatus(Chan *c, Uart *p, void *buf, long n, long offset)
-{
- char str[256];
- USED(c);
-
- str[0] = 0;
- sprint(str, "opens %d ferr %d oerr %d perr %d baud %d parity %c"
- " intr %d rintr %d wintr %d"
- " rcount %d wcount %d",
- p->opens, p->frame, p->overrun, p->perror, p->bps, p->parity,
- p->inters, p->rinters, p->winters,
- p->rcount, p->wcount);
-
- strcat(str, "\n");
- return readstr(offset, buf, n, str);
-}
-
-static long
-uartread(Chan *c, void *buf, long n, vlong offset)
-{
- Uart *p;
-
- if(c->qid.type & QTDIR){
- setlength(-1);
- return devdirread(c, buf, n, uartdir, ndir, devgen);
- }
-
- p = uart[NETID(c->qid.path)];
- switch(NETTYPE(c->qid.path)){
- case Ndataqid:
- return qread(p->iq, buf, n);
- case Nctlqid:
- return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
- case Nstatqid:
- return uartstatus(c, p, buf, n, offset);
- }
-
- return 0;
-}
-
-static void
-uartctl(Uart *p, char *cmd)
-{
- int i, n;
-
- /* let output drain for a while (up to 4 secs) */
- for(i = 0; i < 200 && (qlen(p->oq) || (readstatus(p) & USTAT_TC) == 0); i++)
- tsleep(&up->sleep, return0, 0, 20);
-
- if(strncmp(cmd, "break", 5) == 0){
- uartbreak(p, 0);
- return;
- }
-
- n = atoi(cmd+1);
- switch(*cmd){
- case 'B':
- case 'b':
- if(n <= 0)
- error(Ebadarg);
- p->bps = n;
- uartset(p);
- break;
- case 'f':
- case 'F':
- qflush(p->oq);
- break;
- case 'H':
- case 'h':
- qhangup(p->iq, 0);
- qhangup(p->oq, 0);
- break;
- case 'L':
- case 'l':
- if(n < 7 || n > 8)
- error(Ebadarg);
- p->bits = n;
- uartset(p);
- break;
- case 'n':
- case 'N':
- qnoblock(p->oq, n);
- break;
- case 'P':
- case 'p':
- p->parity = *(cmd+1);
- uartset(p);
- break;
- case 'K':
- case 'k':
- uartbreak(p, n);
- break;
- case 'Q':
- case 'q':
- qsetlimit(p->iq, n);
- qsetlimit(p->oq, n);
- break;
- case 's':
- case 'S':
- if(n < 1 || n > 2)
- error(Ebadarg);
- p->stop = n;
- uartset(p);
- break;
- }
-}
-
-static long
-uartwrite(Chan *c, void *buf, long n, vlong offset)
-{
- Uart *p;
- char cmd[32];
-
- USED(offset);
-
- if(c->qid.type & QTDIR)
- error(Eperm);
-
- p = uart[NETID(c->qid.path)];
-
- switch(NETTYPE(c->qid.path)){
- case Ndataqid:
- return qwrite(p->oq, buf, n);
- case Nctlqid:
-
- if(n >= sizeof(cmd))
- n = sizeof(cmd)-1;
- memmove(cmd, buf, n);
- cmd[n] = 0;
- uartctl(p, cmd);
- return n;
- }
-}
-
-static int
-uartwstat(Chan *c, uchar *dp, int n)
-{
- error(Eperm);
- return 0;
-#ifdef xxx
- Dir d;
- Dirtab *dt;
-
- if(!iseve())
- error(Eperm);
- if(c->qid.type & QTDIR)
- error(Eperm);
- if(NETTYPE(c->qid.path) == Nstatqid)
- error(Eperm);
-
- dt = &uartdir[3 * NETID(c->qid.path)];
- convM2D(dp, &d);
- d.mode &= 0666;
- dt[0].perm = dt[1].perm = d.mode;
-#endif
-}
-
-Dev uartdevtab = {
- 't',
- "uart",
-
- uartreset,
- devinit,
- devshutdown,
- uartattach,
- uartwalk,
- uartstat,
- uartopen,
- devcreate,
- uartclose,
- uartread,
- devbread,
- uartwrite,
- devbwrite,
- devremove,
- uartwstat,
-};
-
-void
-uartputc(int c)
-{
- UartReg *u;
-
- if (!c)
- return;
- u = &UARTREG[1];
- while ((u->stat & USTAT_TBE) == 0)
- ;
- u->txbuf = c;
- if (c == '\n')
- while((u->stat & USTAT_TC) == 0) /* flush xmit fifo */
- ;
-}
-
-void
-uartputs(char *data, int len)
-{
- int x;
-
- clockpoll();
- x = splfhi();
- while (len--){
- if(*data == '\n')
- uartputc('\r');
- uartputc(*data++);
- }
- splx(x);
-}
-
-int
-uartgetc(void)
-{
- UartReg *u;
-
- clockcheck();
- u = &UARTREG[1];
- while((u->stat & USTAT_RDR) == 0)
- clockcheck();
- return u->rxbuf;
-}