commit 9eee7f80329c988bc76beddc9a154b8bb6d79685
parent b737b36c3b858abef17d4380bed9aeacfdb12d60
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Thu, 7 Feb 2019 00:55:26 +0000
[devuart] Add support for file level operations
Change-Id: I640720c613bf8f559c545fec89c0672bfa04e966
Diffstat:
33 files changed, 923 insertions(+), 247 deletions(-)
diff --git a/drivers/dev.c b/drivers/dev.c
@@ -3,14 +3,9 @@
#include <rcode/rcode.h>
#include <rcode/romfw.h>
-#include <rcode/dev.h>
+#include <rcode/9p.h>
-
-struct devdata {
- Chan fds[NR_CHANS];
- Chan slash;
- Chan dot;
-};
+#include "dev.h"
static Chan *
newchan(void)
@@ -70,8 +65,9 @@ next(const char *s, char *elem)
while (*s == '/')
++s;
+
if (*s == '\0')
- return s;
+ return NULL;
n = 0;
for (t = s; *t != '/' && *t != '\0'; t++) {
@@ -122,13 +118,19 @@ chanclose(Chan *c)
c->offset = 0;
}
+struct devdata *
+devdata(void)
+{
+ return bss->devinfo;
+}
+
Chan *
namec(const char *name, int mode)
{
int type;
const char *s;
Chan *c;
- struct devdata *dinfo = bss->devinfo;
+ struct devdata *dinfo = devdata();
char elem[NAMELEN];
switch (name[0]) {
@@ -137,8 +139,10 @@ namec(const char *name, int mode)
s = name;
break;
case '#':
- if ((s = next(name+1, elem)) == NULL)
+ if ((s = next(name+1, elem)) == NULL) {
+ errno = ENOENT;
return NULL;
+ }
if (elem[1] != '\0') {
errno = ENODEV;
return NULL;
@@ -156,12 +160,12 @@ namec(const char *name, int mode)
if (!c)
return NULL;
- for (s = next(s, elem); s && *s; s = next(s, elem)) {
+ for (s = next(s, elem); s; s = next(s, elem)) {
if (walk(c, elem) < 0)
break;
+ if (*s == '\0')
+ return c;
}
- if (*s == '\0')
- return c;
chanclose(c);
errno = ENOENT;
@@ -225,7 +229,10 @@ devwalk(Chan *c, const char *name, const Dirtab *tab, int ntab, Devgen *gen)
}
int
-devdirread(Chan *c, char *buf, int nbytes, const Dirtab *tab, int ntab, Devgen *gen)
+devdirread(Chan *c,
+ unsigned char *buf, int nbytes,
+ const Dirtab *tab, int ntab,
+ Devgen *gen)
{
int cnt, i, n;
Dir dir;
@@ -239,7 +246,7 @@ devdirread(Chan *c, char *buf, int nbytes, const Dirtab *tab, int ntab, Devgen *
c->offset += DIRLEN;
break;
case 1:
- n = dirto9p(dir, buf + cnt);
+ n = dirto9p(&dir, buf + cnt, -1);
nbytes -= n;
cnt += n;
}
@@ -355,6 +362,12 @@ seek(int fd, long long off, int whence)
return 0;
}
+int
+bind(char *new, char *where, int flags)
+{
+ /* TODO */
+}
+
void
idev(void)
{
@@ -375,4 +388,5 @@ idev(void)
panic("idev:clone");
chanclose(c);
+ devlink();
}
diff --git a/drivers/dev.h b/drivers/dev.h
@@ -0,0 +1,71 @@
+#include <stddef.h>
+
+#define NR_CHANS 4
+#define NR_UARTS 2
+#define NODEV 255
+#define CHDIR (1 << 15)
+
+typedef struct dev Dev;
+typedef struct chan Chan;
+typedef struct dirtab Dirtab;
+typedef int Devgen(Chan *, const Dirtab *, int, int, Dir *);
+typedef struct attr Attr;
+typedef struct uart Uart;
+
+struct dirtab {
+ char name[NAMELEN];
+ Qid qid;
+ unsigned long long length;
+ unsigned char perm;
+};
+
+struct dev {
+ char id;
+ char name[NAMELEN];
+ Chan * (*clone)(Chan *c, Chan *nc);
+ int (*walk)(Chan *c, const char *name);
+ Chan * (*attach)(const char *spec);
+ int (*read)(Chan *c, void *buf, int n);
+ int (*write)(Chan *c, void *buf, int n);
+};
+
+struct chan {
+ Qid qid;
+ unsigned char type;
+ unsigned char dev;
+ unsigned char mode;
+
+ unsigned long long offset; /* 3 bytes of padding here */
+};
+
+struct attr {
+ char *key;
+ char *value;
+};
+
+struct devdata {
+ Chan fds[NR_CHANS];
+ Chan slash;
+ Chan dot;
+ Uart *uarts[NR_UARTS];
+};
+
+extern Chan *devclone(Chan *c, Chan *nc);
+extern Chan *devattach(const char *spec, int id);
+extern Chan *devclone(Chan *c, Chan *nc);
+extern void devlink(void);
+extern int devgen(Chan *c,
+ const Dirtab *tab, int ntab,
+ int n,
+ Dir *dir);
+extern int devwalk(Chan *c,
+ const char *name,
+ const Dirtab *tab, int ntab,
+ Devgen *gen);
+extern int devdirread(Chan *c,
+ unsigned char *buf, int nbytes,
+ const Dirtab *tab, int ntab,
+ Devgen *gen);
+extern struct devdata *devdata(void);
+
+extern Dev *const devtab[];
diff --git a/drivers/devroot.c b/drivers/devroot.c
@@ -1,13 +1,14 @@
#include <rcode/rcode.h>
-#include <rcode/dev.h>
+#include <rcode/9p.h>
+
+#include "dev.h"
enum Orootqid {
- Qslash,
Qdev,
Qrealm,
};
-static const Dirtab rootdirtab[] = {
+static const Dirtab dirtab[] = {
{"dev", CHDIR | Qdev, 0, O_READ},
{"realm", CHDIR | Qrealm, 0, O_READ},
};
@@ -15,7 +16,10 @@ static const Dirtab rootdirtab[] = {
static int
rootwalk(Chan *c, const char *name)
{
- return devwalk(c, name, rootdirtab, NELEM(rootdirtab), devgen);
+ return devwalk(c,
+ name,
+ dirtab, NELEM(dirtab),
+ devgen);
}
static Chan *
@@ -27,8 +31,12 @@ rootattach(const char *spec)
static int
rootread(Chan *c, void *buf, int n)
{
- if (c->qid & CHDIR)
- return devdirread(c, buf, n, rootdirtab, NELEM(rootdirtab), devgen);
+ if (c->qid & CHDIR) {
+ return devdirread(c,
+ buf, n,
+ dirtab, NELEM(dirtab),
+ devgen);
+ }
return -1;
}
diff --git a/drivers/devuart.c b/drivers/devuart.c
@@ -1,6 +1,328 @@
-#include <rcode/dev.h>
+#include <rcode/rcode.h>
+#include <rcode/9p.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libk.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dev.h"
+#include "qchar.h"
+#include "uart.h"
+
+#define UARTSTATUS 128
+
+enum Orootqid {
+ Quartfs,
+ Qdevfs,
+ Qraw,
+ Qctl,
+};
+
+static const Dirtab dirtab[] = {
+ {"raw", Qraw, 0, O_READ | O_WRITE},
+ {"ctl", Qctl, 0, O_READ | O_WRITE}
+};
+
+static int
+uartgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
+{
+ if (n >= NR_UARTS)
+ return -1;
+
+ ksnprint(dir->name, NAMELEN, "uart%d", n);
+ dir->length = 0;
+ dir->qid = CHDIR | Qdevfs;
+ dir->mode = O_READ | O_WRITE;
+ dir->type = c->type;
+ dir->dev = n;
+
+ return 1;
+}
+
+static int
+uartwalk(Chan *c, const char *name)
+{
+ Qid qid;
+
+ qid = c->qid & ~CHDIR;
+ switch (qid) {
+ case Quartfs:
+ case Qdevfs:
+ return devwalk(c,
+ name,
+ dirtab, NELEM(dirtab),
+ (qid == Quartfs) ? uartgen : devgen);
+ case Qraw:
+ case Qctl:
+ errno = ENOENT;
+ return 0;
+ default:
+ panic("uartwalk");
+ }
+}
+
+static Chan *
+uartattach(const char *spec)
+{
+ return devattach(spec, 't');
+}
+
+static Uart *
+getuart(Chan *c)
+{
+ if (c->dev >= NR_UARTS)
+ panic("getuart");
+ return devdata()->uarts[c->dev];
+}
+
+static int
+uartstatus(Uart *up, void *buf, long long offset, int n)
+{
+ int len;
+ struct uartstat st;
+ char tmp[UARTSTATUS];
+
+ if (offset >= UARTSTATUS)
+ return 0;
+
+ (*up->phy->status)(up, &st);
+
+ len = ksnprint(tmp, sizeof(tmp),
+ "b%ld c%d d%d e%d l%d m%d p%c r%d s%d i%d\n",
+ st.rate,
+ (st.hang & SIG_DCD) != 0,
+ st.dtr,
+ (st.hang & SIG_DSR) != 0,
+ st.nbits,
+ st.ctsflow,
+ st.parity,
+ st.rts,
+ st.stop,
+ st.fifo);
+
+ if (offset >= len)
+ return 0;
+
+ if (n + offset >= len)
+ n = UARTSTATUS - offset;
+
+ memcpy(buf, tmp + offset, n);
+ return n;
+}
+
+static void
+uartdrain(Uart *up)
+{
+ /* TODO */
+}
+
+/*
+ * bn Set the baud rate to n.
+ * cn Set hangup on DCD if n is non-zero; else clear it.
+ * dn Set DTR if n is non-zero; else clear it.
+ * f Flush output queue.
+ * h Close input and output queues.
+ * in Enable/disable the FIFOs. If n is zero the FIFOs are
+ * disabled; otherwise n is taken as a trigger level for
+ * the FIFOs. The trigger levels supported are device
+ * dependant, but usually include 1, 4 and 8. An unrecog-
+ * nised, but non-zero, value of n causes the maximum-
+ * supported trigger level to be set.
+ * en Set hangup on DSR if n is non-zero; else clear it.
+ * kn Send a break lasting n milliseconds.
+ * ln Set number of bits per byte to n. Legal values are 5,
+ * 6, 7, or 8.
+ * mn Obey modem CTS signal if n is non-zero; else clear it.
+ * n Make writes non-blocking.
+ * pc Set parity to odd if c is o, to even if c is e; else
+ * set no parity.
+ * qn Set input and output queue limits to n.
+ * rn Set RTS if n is non-zero; else clear it.
+ * sn Set number of stop bits to n. Legal values are 1 or 2.
+ * wn Set the uart clock timer to n times 100us.
+*/
+static int
+uartctl(Uart *up, char *cfg, int n)
+{
+ int cnt, r, i;
+ Uartphy *phy = up->phy;
+ unsigned char *s = (unsigned char *) cfg;
+
+ for (cnt = i = 0; i < n; cnt = i++) {
+ int par, c = s[i];
+
+ if (isspace(c))
+ continue;
+
+ par = 0;
+ while (i+1 < n && isdigit(s[i+1]))
+ par = par*10 + s[++i] - '0';
+
+ switch (c) {
+ case 'b':
+ uartdrain(up);
+ r = (*phy->setbauds)(up, par);
+ break;
+ case 'c':
+ r = 0;
+ up->hang = par;
+ break;
+ case 'd':
+ par = (par != 0) << SIG_DTR;
+ r = (*phy->setsignal)(up, SIG_DTR, par);
+ break;
+ case 'f':
+ // r = drv->flush(drv);
+ case 'h':
+ // r = drv->cleanqueues(drv);
+ case 'i':
+ // r = drv->setfifo(drv, par);
+ break;
+ case 'k':
+ // r = drv->break(drv, par);
+ break;
+ case 'l':
+ // r = drv->numbits(drv, par);
+ break;
+ case 'm':
+ // r = drv->obey(drv, CTS, par);
+ break;
+ case 'n':
+ // r = drv->wrmode(drv, par);
+ break;
+ case 'p':
+ if (par != OPARITY && par != EPARITY)
+ par = NPARITY;
+ // r = drv->parity(drv, par);
+ break;
+ case 'q':
+ // r = drv->queuesiz(drv, par);
+ break;
+ case 'r':
+ // r = drv->signal(drv, RTS);
+ break;
+ case 's':
+ if (par != 1 && par != 2)
+ return -1;
+ // r = drv->bitstop(drv, par);
+ break;
+ case 'w':
+ // r = drv->timer(drv, par);
+ break;
+ default:
+ r = -1;
+ }
+
+ if (r < 0)
+ return cnt;
+ }
+
+ return cnt;
+}
+
+static int
+uartread(Chan *c, void *buf, int n)
+{
+ Uart *up;
+ Qid qid;
+
+ qid = c->qid & ~CHDIR;
+ switch (c->qid & ~CHDIR) {
+ case Quartfs:
+ case Qdevfs:
+ return devdirread(c,
+ buf, n,
+ dirtab, NELEM(dirtab),
+ (qid == Quartfs) ? uartgen : devgen);
+ case Qraw:
+ up = getuart(c);
+ return (*up->phy->read)(up, buf, n);
+ case Qctl:
+ up = getuart(c);
+ return uartstatus(up, buf, c->offset, n);
+ default:
+ panic("uartread");
+ }
+}
+
+static int
+uartwrite(Chan *c, void *buf, int n)
+{
+ Uart *up;
+
+ switch (c->qid & ~CHDIR) {
+ case Quartfs:
+ case Qdevfs:
+ return -1;
+ case Qraw:
+ up = getuart(c);
+ return (*up->phy->write)(up, buf, n);
+ case Qctl:
+ up = getuart(c);
+ return uartctl(up, buf, n);
+ default:
+ panic("uartwrite");
+ }
+}
+
+static Uart *
+uartphy(Uartphy *phy)
+{
+ size_t siz;
+ Uart *up;
+ struct devdata *dinfo;
+ int i;
+
+ siz = sizeof(Uart);
+ up = memset(alloc(siz), 0, siz);
+ up->phy = phy;
+
+ dinfo = devdata();
+ for (i = 0; i < NR_UARTS && dinfo->uarts[i] ; i++)
+ ;
+ if (i == NR_UARTS)
+ panic("uartphy");
+
+ return dinfo->uarts[i] = up;
+}
+
+void
+uartlink(Uartphy *phy, Attr *attr)
+{
+ size_t siz;
+ Uart *up;
+ Attr *a;
+ char *cfg = NULL;
+
+ up = uartphy(phy);
+ /* init qc */
+ /* init up->mutex */
+
+ for (a = attr; a->key; a++) {
+ if (!strcmp(a->key, "base"))
+ up->base = (void *) strtoull(a->value, NULL, 0);
+ else if (!strcmp(a->key, "clk"))
+ up->clk = strtoull(a->value, NULL, 0);
+ else if (!strcmp(a->key, "cfg"))
+ cfg = a->value;
+ }
+ (*phy->init)(up, attr);
+
+ if (!cfg)
+ cfg = "b19200 l8";
+ siz = strlen(cfg);
+
+ if (uartctl(up, cfg, siz) != siz)
+ panic("uartlink");
+}
const Dev uartdevtab = {
.id = 't',
.name = "uart",
+ .attach = uartattach,
+ .walk = uartwalk,
+ .clone = devclone,
+ .read = uartread,
+ .write = uartwrite,
};
diff --git a/drivers/mkdev b/drivers/mkdev
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM
+
+sed 's/#.*//' $@ |
+awk '
+BEGIN {print "DEVS = dev.o\\"}
+/^[ \t]*$/ {next}
+/^dev/ {indev = 1; next}
+/^\t\t/ {objs[$1 ".o"] = 1; next}
+indev && /^\t/ {objs["dev" $1 ".o"] = 1; next}
+END {for (i in objs)
+ printf "\t%s\\\n", i}' > $$.tmp &&
+mv $$.tmp devs.mk
diff --git a/drivers/mkdevc b/drivers/mkdevc
@@ -4,14 +4,69 @@ trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM
sed -e 's/^#.*//' -e '/^[ \t]*$/d' $@ |
awk '
-BEGIN {print "#include <rcode/dev.h>\n"}
-/^dev/ {dev = 1; next}
-/^[^ \t]/ {dev = 0; next}
-dev && /^[ \t]/ {devs[$1 "devtab"] = 1}
-END {for (i in devs)
- printf "extern Dev %s;\n", i
- print "\nDev *const devtab[] = {"
- for (i in devs)
- printf "\t&%s,\n", i
- print "};"}' > $$.tmp &&
-mv $$.tmp devc.c
+/^[ \t]*$/ {next}
+/^dev/ {indev = 1; next}
+indev && /^\t\t/ {devs[dev]++
+ phys[$1] = dev
+ drivers[n++] = dev FS $1 FS $2}
+indev && /^\t[^\t]/ {dev = $1
+ devs[dev] = 0}
+END {typedef()
+ extern()
+ devtab()
+ devlink()}
+
+function capital(x)
+{
+ return toupper(substr(x, 1, 1)) substr(x, 2)
+}
+
+function typedef()
+{
+ print "typedef struct dev Dev;"
+ print "typedef struct attr Attr;"
+ for (i in devs)
+ printf "typedef struct %sphy %sphy;\n", i, capital(i)
+ print "\nstruct attr {"
+ print "\tchar *key;"
+ print "\tchar *value;"
+ print "};\n"
+}
+
+function extern()
+{
+ for (i in devs)
+ printf "extern Dev %sdevtab;\n", i
+ for (i in phys)
+ printf "extern %sphy %s;\n", capital(phys[i]), i "phy"
+ for (i in devs) {
+ if (devs[i] > 0) {
+ printf "extern void %slink(%sphy *, Attr *);\n",
+ i, capital(i)
+ }
+ }
+}
+
+function devtab()
+{
+ print "\nDev *const devtab[] = {"
+ for (i in devs)
+ printf "\t&%sdevtab,\n", i
+ print "};\n"
+}
+
+function devlink()
+{
+ printf "void\ndevlink(void)\n{\n"
+ for (i in drivers) {
+ split(drivers[i], links)
+ printf "\t%slink(&%s, (Attr []) {", links[1], links[2] "phy"
+ n = split(links[3], args, / *, */)
+ for (j = 1; j <= n; j++) {
+ split(args[j], keys, / *= */)
+ printf "{\"%s\", \"%s\"},", keys[1], keys[2]
+ }
+ print "{0}});"
+ }
+ print "}"
+}' > $$.tmp && mv $$.tmp devc.c
diff --git a/drivers/pl011.c b/drivers/pl011.c
@@ -1,113 +1,186 @@
-#include <rcode/uart.h>
#include <rcode/rcode.h>
-#include <rcode/romfw.h>
-
-#define CR 0x30
-#define FBRD 0x28
-#define IBRD 0x24
-#define LCRH 0x2c
-#define FR 0x18
-#define RSR_ECR 0x4
-#define DR 0x0
-
-#define CR_RTS (1 << 11)
-#define CR_RXE (1 << 9)
-#define CR_TXE (1 << 8)
-#define CR_EN (1 << 0)
-
-#define LCRH_FEN (1 << 4)
-#define LCRH_WLEN_8 (3 << 5)
-
-#define FR_TXFE (1 << 6)
-#define FR_TXFF (1 << 5)
-#define FR_RXFE (1 << 4)
-
-static void
-setbaudrate(unsigned clk, unsigned baudrate)
+#include <rcode/9p.h>
+
+#include "dev.h"
+#include "qchar.h"
+#include "uart.h"
+
+enum phyregs {
+ UARTDR, /* Data register */
+ UARTRSR, /* Receive status register */
+ RES1, /* Reserved */
+ UARTFR, /* Flag register */
+ RES2, /* Reserved */
+ UARTILPR, /* IrDA low-power count register */
+ UARTIBRD, /* Integer baud rate */
+ UARTFBRD, /* Fractional baud rate register */
+ UARTLCR_H, /* Line control register */
+ UARTCR, /* Control register */
+ UARTIFLS, /* Interrupt FIFO level select register */
+ UARTIMSC, /* Interrupt mask set/clear register */
+ UARTRIS, /* Raw interrupt status register */
+ UARTMIS, /* Masked interrupt register */
+ UARTICR, /* Interrupt clear register */
+ UARTDMACR, /* DMA control register */
+ RES3, /* Reserved */
+ RES4, /* Reserved */
+ RES5, /* Reserved */
+ RES6, /* Reserved */
+ UARTPID0, /* UART Periph ID0 */
+ UARTPID1, /* UART Periph ID1 */
+ UARTPID2, /* UART Periph ID2 */
+ UARTPID3, /* UART Periph ID3 */
+ UARTCID0, /* UART Cell ID0 */
+ UARTCID1, /* UART Cell ID1 */
+ UARTCID2, /* UART Cell ID2 */
+ UARTCID3, /* UART Cell ID3 */
+};
+
+enum eoi {
+ RIMC = 1 << 0, /* clears UARTRIINTR */
+ CTSMIC = 1 << 1, /* clears UARTCTSINTR */
+ DCDMIC = 1 << 2, /* clears UARTDCDINTR */
+ DSRMIC = 1 << 3, /* clears UARTDSRINTR */
+ RXIC = 1 << 4, /* clears UARTRXINTR */
+ TXIC = 1 << 5, /* clears UARTTXINTR */
+ RTIC = 1 << 6, /* clears UARTRTINTR */
+ FEIC = 1 << 7, /* clears UARTFEINTR */
+ PEIC = 1 << 8, /* clears UARTPEINTR */
+ BEIC = 1 << 9, /* clears UARTBEINTR */
+ OEIC = 1 << 10, /* clears UARTOEINTR */
+};
+
+#define ALLIC (RIMC|CTSMIC|DCDMIC|DSRMIC|RXIC|TXIC|\
+ RTIC|FEIC|PEIC|BEIC|OEIC)
+
+enum uartlcr_h {
+ BRK = 1 << 0, /* send break */
+ PEN = 1 << 1, /* Parity enable */
+ EPS = 1 << 2, /* Even parity enable */
+ STP2 = 1 << 3, /* Two stop bits */
+ FEN = 1 << 4, /* Enable FIFOs */
+ WLEN_5 = 0 << 5, /* word lenght (5 bits) */
+ WLEN_6 = 1 << 5, /* word lenght (6 bits) */
+ WLEN_7 = 2 << 5, /* word lenght (7 bits) */
+ WLEN_8 = 3 << 5, /* word lenght (8 bits) */
+ SPS = 1 << 7, /* Stick parity select */
+};
+
+enum uartcr {
+ UARTEN = 1 << 0, /* UART enable */
+ SIREN = 1 << 1, /* SIR enable */
+ SIRLP = 1 << 2, /* SIR low power IrDA mode */
+ LBE = 1 << 7, /* Loopback enable */
+ TXE = 1 << 8, /* TX enable */
+ RXE = 1 << 9, /* RX enable */
+ DTR = 1 << 10, /* Data transmit ready */
+ RTS = 1 << 11, /* Request to send */
+ OUT1 = 1 << 12, /* can be used for DCD */
+ OUT2 = 1 << 13, /* can be used for RI */
+ RSTEN = 1 << 14, /* RTS hardware flow control mode */
+ CTSEN = 1 << 15, /* CTS hardware flow control mode */
+};
+
+#define ALLCR (UARTEN|SIREN|SIRLP|LBE|TXE|RXE|DTR|\
+ RTS|OUT1|OUT2|RSTEN|CTSEN)
+
+enum uartfr {
+ FR_CTS = 1 << 0, /* CTS flag */
+ FR_DSR = 1 << 1, /* DSR flag */
+ FR_DCD = 1 << 2, /* DCD flag */
+ FR_BUSY = 1 << 3, /* UART busy transmiting */
+ FR_RXFE = 1 << 4, /* Receive FIFO empty */
+ FR_TXFF = 1 << 5, /* Transmit FIFO full */
+ FR_RXFF = 1 << 6, /* Receive FIFO full */
+ FR_TXFE = 1 << 7, /* Transmit FIFO empty */
+ FR_RI = 1 << 8, /* Ring indicator */
+};
+
+static unsigned long
+plin(Uart *up, int reg)
{
- char *base = bss->uartbase;
- unsigned int div;
+ char *addr = up->base;
- div = (clk * 4) / baudrate;
- outm32(div >> 6, base + IBRD);
- outm32(div & 0x3f, base + FBRD);
+ addr += reg * 4;
+ return inm32(addr);
}
static void
-flush(void)
+plout(Uart *up, int reg, unsigned long val)
{
- char *base = bss->uartbase;
+ char *addr = up->base;
- while ((inm32(base + CR) & CR_EN) && (inm32(base + FR) & FR_TXFE))
- ;
+ addr += reg * 4;
+ outm32(val, addr);
}
-static void
-ansisetmode(void)
+static int
+setbauds(Uart *up, long rate)
{
- static const char ansism[5] = "\x1b[20h";
- static const char echo[6] = "\x1b[12l";
-
- uartwrite(ansism, sizeof(ansism));
- uartwrite(echo, sizeof(echo));
-}
+ unsigned div;
+ unsigned long cr;
-void
-uartinit(unsigned clk, unsigned baudrate)
-{
- char *base = bss->uartbase;
-
- outm32(0, base + RSR_ECR);
- outm32(0, base + CR);
- setbaudrate(clk, baudrate);
- outm32(LCRH_WLEN_8 | LCRH_FEN, base + LCRH);
- outm32(CR_EN | CR_TXE | CR_RXE, base + CR);
- ansisetmode();
- return;
-}
+ div = (up->clk * 4) / rate;
+ if (div == 0)
+ return -1;
-int
-uartgetc(void)
-{
- char *base = bss->uartbase;
+ cr = plin(up, UARTCR);
+ plout(up, UARTCR, cr & ~UARTEN);
+ plout(up, UARTIBRD, div >> 6);
+ plout(up, UARTFBRD, div & 0x3f);
+ up->rate = rate;
+ plout(up, UARTCR, cr | UARTEN);
- while ((inm32(base + FR) & FR_RXFE))
- ;
- return inm8(base + DR);
+ return 0;
}
-int
-uartputc(int c)
+static void
+pl011init(Uart *up, Attr *attr)
{
- char *base = bss->uartbase;
-
- while ((inm32(base + FR) & FR_TXFF))
- ;
- outm8(c, base + DR);
- return c;
+ unsigned long cr;
+
+ cr = plin(up, UARTCR) & ~ALLCR;
+ plout(up, UARTCR, cr);
+ plout(up, UARTICR, ALLIC);
+ plout(up, UARTRSR, 0);
+ plout(up, UARTLCR_H, WLEN_8);
+ plout(up, UARTIMSC, 0);
+ plout(up, UARTIBRD, 0);
+ plout(up, UARTFBRD, 0);
+ plout(up, UARTCR, cr | UARTEN | TXE | RXE);
}
-int
-uartread(void *buf, size_t siz)
+static int
+pl011read(Uart *up, void *buf, int n)
{
- size_t i;
- char *ptr = buf;
-
- for (i = 0; i < siz; i++)
- if ((ptr[i] = uartgetc()) < 0)
- return i;
- return siz;
+ int i;
+ char *bp = buf;
+
+ for (i = 0; i < n; i++) {
+ while ((plin(up, UARTFR) & FR_RXFE) == 0)
+ ;
+ bp[i] = plin(up, UARTDR);
+ }
+ return n;
}
-int
-uartwrite(const void *buf, size_t siz)
+static int
+pl011write(Uart *up, void *buf, int n)
{
- size_t i;
- const char *ptr = buf;
-
- for (i = 0; i < siz; i++)
- if (uartputc(ptr[i]) < 0)
- return i;
- flush();
- return siz;
+ int i;
+ char *bp = buf;
+
+ for (i = 0; i < n; i++) {
+ while ((plin(up, UARTFR) & FR_TXFF) == 0)
+ ;
+ plout(up, UARTDR, bp[i]);
+ }
+ return n;
}
+
+const Uartphy pl011phy = {
+ .init = pl011init,
+ .setbauds = setbauds,
+ .read = pl011read,
+ .write = pl011write,
+};
diff --git a/drivers/qchar.c b/drivers/qchar.c
@@ -0,0 +1,50 @@
+#include <rcode/arch.h>
+#include "qchar.h"
+
+void
+qin(Qchar *qc, int c)
+{
+ int head;
+
+ head = (qc->head+1) % qc->size;
+
+ while (head == qc->tail)
+ sleep(qc);
+
+ qc->buff[head] = c;
+ qc->head = head;
+
+ return 1;
+}
+
+int
+qout(Qchar *qc)
+{
+ int c;
+
+ while (qc->head == qc->tail)
+ sleep(qc);
+
+ c = qc->tail;
+ qc->tail = (qc->tail+1) % qc->size;
+
+ return c;
+}
+
+Qchar *
+qchar(int siz)
+{
+ Qchar *qc;
+
+ if ((qc = alloc(sizeof(*qc) + siz)) == NULL)
+ panic("newqchar");
+ qc->size = siz;
+ qc->head = qc->tail = 0;
+
+ return qc;
+}
+
+void
+qflush(Qchar *qc)
+{
+}
diff --git a/drivers/qchar.h b/drivers/qchar.h
@@ -0,0 +1,18 @@
+typedef struct queue Qchar;
+
+struct queue {
+ int size;
+ atomic_t head;
+ atomic_t tail;
+
+ void *who;
+ void (*put)(void *who, unsigned char);
+ void (*get)(void *who, unsigned char);
+
+ unsigned char buf[];
+};
+
+extern void qflush(Qchar *qc);
+extern void qin(Qchar *qc, int c);
+extern int qout(Qchar *qc);
+extern Qchar *qchar(int siz);
diff --git a/drivers/uart.h b/drivers/uart.h
@@ -0,0 +1,70 @@
+typedef struct uart Uart;
+typedef struct uartphy Uartphy;
+
+enum rs232sig {
+ SIG_DCD,
+ SIG_RXD,
+ SIG_TXD,
+ SIG_DTR,
+ SIG_DSR,
+ SIG_RTS,
+ SIG_CTS,
+ SIG_RI,
+};
+
+enum parity {
+ OPARITY = 'o',
+ EPARITY = 'e',
+ NPARITY = 'n',
+};
+
+
+struct uartstat {
+ long rate;
+ int nbits;
+ int hang;
+ int ctsflow;
+ int parity;
+ int rts;
+ int dtr;
+ int stop;
+ int fifo;
+};
+
+struct uart {
+ long rate;
+ int nbits;
+ int nstop;
+ int hang;
+ long clk;
+ void *base;
+ void *phydata;
+
+ mutex_t m;
+ Qchar *qc;
+ Uartphy *phy;
+};
+
+struct uartphy {
+ void (*init)(Uart *up, Attr *attr);
+ int (*setbauds)(Uart *up, long rate);
+ int (*setsignal)(Uart *up, int mask, int val);
+ int (*getsignal)(Uart *up, int mask, int *val);
+ int (*read)(Uart *up, void *buf, int n);
+ int (*write)(Uart *up, void *buf, int n);
+ int (*status)(Uart *up, struct uartstat *st);
+
+ int (*flush)(Uart *uart);
+ int (*cleanqueues)(Uart *uart);
+ int (*setfifo)(Uart *uart, int size);
+ int (*dobreak)(Uart *uart, int mils);
+ int (*numbits)(Uart *uart, int nbits);
+ int (*flow)(Uart *uart, int type, int ena);
+ int (*nonblocking)(Uart *uart, int ena);
+ int (*parity)(Uart *uart, int type);
+ int (*queuesize)(Uart *up, int size);
+ int (*bitstop)(Uart *up, int nstops);
+ int (*settimer)(Uart *up, int ntimes);
+};
+
+extern void uartlink(Uartphy *phy, Attr *attr);
diff --git a/include/bits/amd64/arch/types.h b/include/bits/amd64/arch/types.h
@@ -0,0 +1,2 @@
+typedef int atomic_t;
+typedef unsigned char mutex_t;
diff --git a/include/bits/arm32/arch/types.h b/include/bits/arm32/arch/types.h
@@ -0,0 +1,2 @@
+typedef int atomic_t;
+typedef unsigned char mutex_t;
diff --git a/include/bits/arm64/arch/types.h b/include/bits/arm64/arch/types.h
@@ -0,0 +1,2 @@
+typedef int atomic_t;
+typedef unsigned char mutex_t;
diff --git a/include/bits/i386/arch/types.h b/include/bits/i386/arch/types.h
@@ -0,0 +1,2 @@
+typedef int atomic_t;
+typedef unsigned char mutex_t;
diff --git a/include/bits/rmode/arch/types.h b/include/bits/rmode/arch/types.h
@@ -0,0 +1,2 @@
+typedef int atomic_t;
+typedef unsigned char mutex_t;
diff --git a/include/rcode/9p.h b/include/rcode/9p.h
@@ -1,4 +1,19 @@
-/*
- * This file expects rcode/dev.h to be included before
- */
+#define NAMELEN 8
+#define STATLEN 41
+#define ROOTLEN (2 + 4)
+#define FILNAMLEN (2 + NAMELEN)
+#define DIRLEN (STATLEN + FILNAMLEN + 3*ROOTLEN)
+
+typedef struct dir Dir;
+typedef unsigned short Qid;
+
+struct dir {
+ char name[NAMELEN];
+ unsigned long long length;
+ unsigned char mode;
+ unsigned char type;
+ unsigned char dev;
+ Qid qid;
+};
+
extern int dirto9p(Dir *dp, unsigned char *buf, int n);
diff --git a/include/rcode/dev.h b/include/rcode/dev.h
@@ -1,61 +0,0 @@
-#include <stddef.h>
-
-#define NR_CHANS 4
-#define NODEV 255
-#define NAMELEN 8
-#define STATLEN 41
-#define ROOTLEN (2 + 4)
-#define FILNAMLEN (2 + NAMELEN)
-#define DIRLEN (STATLEN + FILNAMLEN + 3*ROOTLEN)
-#define CHDIR (1 << 15)
-
-typedef struct dev Dev;
-typedef struct chan Chan;
-typedef struct dirtab Dirtab;
-typedef struct dir Dir;
-typedef int Devgen(Chan *, const Dirtab *, int, int, Dir *);
-typedef unsigned short Qid;
-
-struct dir {
- char name[NAMELEN];
- unsigned long long length;
- unsigned char mode;
- unsigned char type;
- unsigned char dev;
- Qid qid;
-};
-
-struct dirtab {
- char name[NAMELEN];
- Qid qid;
- unsigned long long length;
- unsigned char perm;
-};
-
-struct dev {
- char id;
- char name[NAMELEN];
- Chan * (*clone)(Chan *c, Chan *nc);
- int (*walk)(Chan *c, const char *name);
- Chan * (*attach)(const char *spec);
- int (*read)(Chan *c, void *buf, int n);
- int (*write)(Chan *c, void *buf, int n);
-};
-
-struct chan {
- Qid qid;
- unsigned char type;
- unsigned char dev;
- unsigned char mode;
-
- unsigned long long offset; /* 3 bytes of padding here */
-};
-
-extern Dev *const devtab[];
-
-extern Chan *devclone(Chan *c, Chan *nc);
-extern Chan *devattach(const char *spec, int id);
-extern Chan *devclone(Chan *c, Chan *nc);
-extern int devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir);
-extern int devwalk(Chan *c, const char *name, const Dirtab *tab, int ntab, Devgen *gen);
-extern int devdirread(Chan *c, char *buf, int nbytes, const Dirtab *tab, int ntab, Devgen *gen);
diff --git a/include/rcode/ramfw.h b/include/rcode/ramfw.h
@@ -1,6 +1,3 @@
struct bssmap {
void *text;
};
-
-extern struct bssmap *bss(void);
-#define bss bss()
diff --git a/include/rcode/rcode.h b/include/rcode/rcode.h
@@ -1,7 +1,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <arch/types.h>
-#include "features.h"
+#include "../features.h"
#ifndef NDEBUG
#define dbg kprint
@@ -24,6 +25,13 @@ enum devflags {
O_TRUNC = 1 << 5,
};
+enum bindflags {
+ MREPL = 1 << 0,
+ MBEFORE = 1 << 1,
+ MAFTER = 1 << 2,
+ MCREATE = 1 << 3,
+};
+
enum regidx {
X0,
X1,
@@ -83,6 +91,8 @@ struct rmucmd {
struct trapframe *fp;
};
+struct bssmap;
+
extern noreturn void halt(void);
extern noreturn void panic(const char *msg);
extern noreturn void swtch(struct trapframe *fp);
@@ -101,7 +111,7 @@ extern int close(int fd);
extern int read(int fd, void *buf, int n);
extern int write(int fd, void *buf, int n);
extern int seek(int fd, long long off, int whence);
-extern int bind(const char *path, char *where);
+extern int bind(char *path, char *where, int flags);
/* architectural functions */
extern void *alloc(size_t size);
@@ -115,3 +125,8 @@ extern uint32_t inm32(void *addr);
extern uint8_t outm8(uint8_t, void *addr);
extern uint16_t outm16(uint16_t, void *addr);
extern uint32_t outm32(uint32_t, void *addr);
+extern void lock(mutex_t *m);
+extern void unlock(mutex_t *m);
+
+extern struct bssmap *bss(void);
+#define bss bss()
diff --git a/include/rcode/romfw.h b/include/rcode/romfw.h
@@ -4,7 +4,7 @@
struct rmctab;
struct trapframe;
struct rmucmd;
-struct Fgrp;
+struct devdata;
struct bssmap {
unsigned char in_panic;
@@ -15,7 +15,6 @@ struct bssmap {
void *environ;
size_t bsssize;
- void *uartbase;
const char *errstr;
jmp_buf dbgrecover;
struct rmctab *rmctab;
@@ -30,7 +29,4 @@ struct bssmap {
struct devdata *devinfo;
};
-extern struct bssmap *bss(void);
-#define bss bss()
-
extern struct rmctab romtab;
diff --git a/include/rcode/uart.h b/include/rcode/uart.h
@@ -1,7 +0,0 @@
-#include <stddef.h>
-
-extern void uartinit(unsigned clkrate, unsigned baudrate);
-extern int uartgetc(void);
-extern int uartputc(int c);
-extern int uartread(void *buf, size_t siz);
-extern int uartwrite(const void *buf, size_t siz);
diff --git a/scripts/mkdev b/scripts/mkdev
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-sed 's/#.*//' $@ |
-awk '
-BEGIN {print "DEVS = dev.o\\"}
-/^[ \t]*$/ {next}
-/^dev/ {dev = 1; home = 1; next}
-/^misc/ {dev = 0; home = 1; next}
-/^[^ \t]/ {print "error: " $0; exit -1}
-/^[ \t]/ {printf "\t%s\\\n", (dev) ? "dev" $1 ".o" : $1 ".o"
- for (i = 2; i <= NF; i++)
- printf "\t%s.o\\\n", $i}' > devs.mk
diff --git a/src/lib9p/dirto9p.c b/src/lib9p/dirto9p.c
@@ -1,6 +1,5 @@
#include <assert.h>
-#include <rcode/dev.h>
#include <rcode/9p.h>
#include "conv.h"
diff --git a/src/libc/arch/rmode/rcode/_read.c b/src/libc/arch/rmode/rcode/_read.c
@@ -1,11 +0,0 @@
-#include <stddef.h>
-
-#include "../../../syscall.h"
-
-extern int uartread(void *buf, size_t siz);
-
-int
-_read(int fd, void *buf, size_t n)
-{
- return uartread(buf, n);
-}
diff --git a/src/libc/arch/rmode/rcode/_read.s b/src/libc/arch/rmode/rcode/_read.s
@@ -0,0 +1,4 @@
+ .globl _read
+
+_read:
+ b read
diff --git a/src/libc/arch/rmode/rcode/_write.c b/src/libc/arch/rmode/rcode/_write.c
@@ -1,11 +0,0 @@
-#include <stddef.h>
-
-#include "../../../syscall.h"
-
-extern int uartwrite(const void *buf, size_t siz);
-
-int
-_write(int fd, void *buf, size_t len)
-{
- return uartwrite(buf, len);
-}
diff --git a/src/libc/arch/rmode/rcode/_write.s b/src/libc/arch/rmode/rcode/_write.s
@@ -0,0 +1,4 @@
+ .globl _write
+
+_write:
+ b write
diff --git a/src/ramfw/fs.c b/src/ramfw/fs.c
@@ -7,4 +7,4 @@ int read(int fd, void *buf, int n){return 0;}
int write(int fd, void *buf, int n){return 0;}
int seek(int fd, long long off, int whence){return 0;}
int chdir(const char *path){return 0;}
-int bind(const char *path, char *where){return 0;}
+int bind(char *path, char *where, int flags){return 0;}
diff --git a/target/hosted/arch.c b/target/hosted/arch.c
@@ -43,3 +43,33 @@ dopanic(void)
trap(fp);
abort();
}
+
+uint8_t
+inm8(void *addr)
+{
+}
+
+uint16_t
+inm16(void *addr)
+{
+}
+
+uint32_t
+inm32(void *addr)
+{
+}
+
+uint8_t
+outm8(uint8_t val, void *addr)
+{
+}
+
+uint16_t
+outm16(uint16_t val, void *addr)
+{
+}
+
+uint32_t
+outm32(uint32_t val, void *addr)
+{
+}
diff --git a/target/hosted/rcode b/target/hosted/rcode
@@ -1,2 +1,5 @@
dev
root
+ uart
+ pl011 base=0x1c0c0000,clk=24000000,cfg=b115200 l8
+ pl011 base=0x1c0c0100,clk=24000000
diff --git a/target/native/Makefile b/target/native/Makefile
@@ -2,10 +2,6 @@
PROJECTDIR = ../..
include $(PROJECTDIR)/scripts/rules.mk
-MORECFLAGS = -DUARTBASE=0x1c0c0000 \
- -DUARTCLK=24000000 \
- -DUARTBAUDRATE=115200 \
-
ROMOBJS = rom-crt.o \
rom.o \
arch.o \
diff --git a/target/native/rcode b/target/native/rcode
@@ -1,3 +1,5 @@
dev
root
- uart pl011
+ uart
+ pl011 base=0x1c0c0000,clk=24000000,rate=115200
+ pl011 base=0x1c0c0100,clk=24000000,rate=115200
diff --git a/target/native/rom.c b/target/native/rom.c
@@ -5,7 +5,6 @@
#include <libk.h>
#include <rcode/rcode.h>
#include <rcode/romfw.h>
-#include <rcode/uart.h>
#include "version.h"
#include "sysreg.h"
@@ -103,7 +102,6 @@ ibss(Mach *mp)
bss->text = mp->txt;
bss->backtrace = 1;
bss->dumpstack = 1;
- bss->uartbase = (void *)UARTBASE;
bss->bsssize = sizeof(struct bssmap);
bss->rmctab = &romtab;
envp = bss->environ = mp->env;
@@ -127,6 +125,20 @@ info(Mach *mp)
mp->sp, mp->stacksiz);
}
+static void
+namespace(void)
+{
+ int fd;
+
+ if (bind("#t/", "/dev/", MREPL) < 0)
+ panic("openfds1");
+
+ fd = open("/dev/uart0/raw", O_READ | O_WRITE); */
+
+ if (fd != 0)
+ panic("openfds2");
+}
+
void
main(void *txt, size_t txtsiz, void *ram, size_t ramsiz)
{
@@ -135,9 +147,9 @@ main(void *txt, size_t txtsiz, void *ram, size_t ramsiz)
imach(&mach, txt, txtsiz, ram, ramsiz);
ibss(&mach);
idev();
- uartinit(UARTCLK, UARTBAUDRATE);
intr(IENABLE);
barrier(ISB);
+ namespace();
info(&mach);
swtch(&mach.frame);
}