9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Mdrivers/dev.c | 44+++++++++++++++++++++++++++++---------------
Adrivers/dev.h | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdrivers/devroot.c | 20++++++++++++++------
Mdrivers/devuart.c | 324++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Adrivers/mkdev | 14++++++++++++++
Mdrivers/mkdevc | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mdrivers/pl011.c | 251+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Adrivers/qchar.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Adrivers/qchar.h | 18++++++++++++++++++
Adrivers/uart.h | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/bits/amd64/arch/types.h | 2++
Ainclude/bits/arm32/arch/types.h | 2++
Ainclude/bits/arm64/arch/types.h | 2++
Ainclude/bits/i386/arch/types.h | 2++
Ainclude/bits/rmode/arch/types.h | 2++
Minclude/rcode/9p.h | 21++++++++++++++++++---
Dinclude/rcode/dev.h | 61-------------------------------------------------------------
Minclude/rcode/ramfw.h | 3---
Minclude/rcode/rcode.h | 19+++++++++++++++++--
Minclude/rcode/romfw.h | 6+-----
Dinclude/rcode/uart.h | 7-------
Dscripts/mkdev | 12------------
Msrc/lib9p/dirto9p.c | 1-
Dsrc/libc/arch/rmode/rcode/_read.c | 11-----------
Asrc/libc/arch/rmode/rcode/_read.s | 4++++
Dsrc/libc/arch/rmode/rcode/_write.c | 11-----------
Asrc/libc/arch/rmode/rcode/_write.s | 4++++
Msrc/ramfw/fs.c | 2+-
Mtarget/hosted/arch.c | 30++++++++++++++++++++++++++++++
Mtarget/hosted/rcode | 3+++
Mtarget/native/Makefile | 4----
Mtarget/native/rcode | 4+++-
Mtarget/native/rom.c | 18+++++++++++++++---
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); }