9os

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

commit 71c38bc3d65907d2997c23b62fdd13f193b62cee
parent 4eafb8af2fd2454170d0ee08467a2a37090943e8
Author: Ambroise Vincent <ambroise.vincent@arm.com>
Date:   Wed,  3 Apr 2019 10:32:15 +0100

[dev] Add console driver

Allow to add and remove outputs from the file system.

Change-Id: Ifbde6cfe6c02c1ffad0cab5b47946b1343feb2bc
Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com>

Diffstat:
Mdrivers/dev.h | 3++-
Adrivers/devcons.c | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdrivers/devroot.c | 10++++++++--
Mtarget/native/rcode | 3++-
Mtarget/native/rom.c | 34+++++++++++++++++++++++++++++-----
5 files changed, 254 insertions(+), 9 deletions(-)

diff --git a/drivers/dev.h b/drivers/dev.h @@ -1,7 +1,8 @@ #include <stddef.h> -#define NR_CHANS 20 +#define NR_CHANS 15 #define NR_UARTS 2 +#define NR_CONSS 1 #define NR_BINDS 4 #define NODEV 255 #define CHDIR (1 << 15) diff --git a/drivers/devcons.c b/drivers/devcons.c @@ -0,0 +1,213 @@ +#include <assert.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 <rcode/dev.h> + +#define CONSOUT 2 +#define NAMESIZE 15 +#define CONSSTATUS 128 + +enum Orootqid { + Qconsfs, + Qraw, + Qctl +}; + +static const Dirtab dirtab[] = { + {"raw", Qraw, 0, O_READ | O_WRITE}, + {"ctl", Qctl, 0, O_READ | O_WRITE} +}; + +struct cons { + Chan *in; + char inname[NAMESIZE]; + Chan *out[CONSOUT]; + char outname[CONSOUT][NAMESIZE]; +}; + +static struct cons *cons; + +static int +conswalk(Chan *c, const char *name) +{ + return devwalk(c, name, dirtab, NELEM(dirtab), devgen); +} + +static int +consstatus(void *buf, Chan *c, int n) +{ + int i; + int len = 0; + char tmp[CONSSTATUS]; + + if (cons->in) + len += ksnprint(tmp, sizeof(tmp), + "addin %s\n", + cons->inname); + + for (i = 0; i < CONSOUT; i++) { + if (cons->out[i]) + len += ksnprint(tmp + len, sizeof(tmp) - len, + "addout %s\n", + cons->outname[i]); + } + + if (len == sizeof(tmp)) + panic("consstatus"); + + return buf2chan(c, buf, tmp, n, len); +} + +static int +consaddin(void *buf, int n) +{ + if (cons->in || n >= NAMESIZE) + return -1; + + cons->in = namec(buf, O_READ); + memcpy(cons->inname, buf, n); + return 0; +} + +static int +consaddout(void *buf, int n) +{ + int i; + + if (n >= NAMESIZE) + return -1; + + for (i = 0; i < CONSOUT; i++) { + if (!cons->out[i]) { + cons->out[i] = namec(buf, O_WRITE); + memcpy(cons->outname[i], buf, n); + return 0; + } + } + return -1; +} + +static int +consdelin(void *buf, int n) +{ + if (!cons->in || memcmp(buf, cons->inname, n)) + return -1; + + chanclose(cons->in); + cons->in = NULL; + cons->inname[0] = '\0'; + return 0; +} + +static int +consdelout(void *buf, int n) +{ + int i; + + for (i = 0; i < CONSOUT; i++) { + if (cons->out[i] && !memcmp(buf, cons->outname[i], n)) { + chanclose(cons->out[i]); + cons->out[i] = NULL; + cons->outname[i][0] = '\0'; + return 0; + } + } + return -1; +} + +static int +conswrite(Chan *c, void *buf, int n) +{ + char *tokens[2]; + int written, i; + Chan *p; + Chan **pp; + int (*func)(void *, int); + + struct conscmds { + const char name[7]; + int (*func)(void *, int); + }; + + const struct conscmds conscmds[] = { + {"addin", consaddin}, + {"addout", consaddout}, + {"delin", consdelin}, + {"delout", consdelout} + }; + + switch (c->qid & ~CHDIR) { + case Qconsfs: + return -1; + case Qraw: + written = -1; + for (pp = cons->out; pp < &cons->out[CONSOUT]; pp++) { + if ((p = *pp) == NULL) + continue; + written = devtab[p->type]->write(p, buf, n); + } + return written; + case Qctl: + if (tokenize(buf, n, tokens, 2) != 2) + return -1; + for (i = 0; i < NELEM(conscmds); i++) { + if (!strcmp(tokens[0], conscmds[i].name)) { + func = conscmds[i].func; + return (*func)(tokens[1], strlen(tokens[1])); + } + } + return -1; + default: + panic("conswrite"); + } +} + +static int +consread(Chan *c, void *buf, int n) +{ + switch (c->qid & ~CHDIR) { + case Qconsfs: + return dirread(c, buf, n, dirtab, NELEM(dirtab), devgen); + case Qraw: { + Chan *in = cons->in; + if (cons->in) + return devtab[in->type]->read(in, buf, n); + return -1; + } + case Qctl: + return consstatus(buf, c, n); + default: + panic("consread"); + } +} + +void +conslink(Attr *attr) +{ + size_t siz; + Attr *a; + int index = 0; + + siz = sizeof(struct cons); + cons = memset(alloc(siz), 0, siz); + + for (a = attr; a->key; a++) { + if (!strcmp(a->key, "in")) + consaddin(a->value, strlen(a->value)); + else if (!strcmp(a->key, "out") && index < CONSOUT) + consaddout(a->value, strlen(a->value)); + } +} + +const Dev consdevtab = { + .id = 's', + .walk = conswalk, + .read = consread, + .write = conswrite, +}; diff --git a/drivers/devroot.c b/drivers/devroot.c @@ -7,7 +7,10 @@ enum Orootqid { Qroot, Qdev, - Qdevuart, + Qdevuart0, + Qdevuart1, + Qdevuart2, + Qdevuart3, Qdevcons, Qrealm, Qarfs, @@ -27,7 +30,10 @@ static const Dirtab dirtab[] = { }; static const Dirtab devfstab[] = { - {"uart", CHDIR | Qdevuart, 0, O_READ}, + {"uart0", CHDIR | Qdevuart0, 0, O_READ}, + {"uart1", CHDIR | Qdevuart1, 0, O_READ}, + {"uart2", CHDIR | Qdevuart2, 0, O_READ}, + {"uart3", CHDIR | Qdevuart3, 0, O_READ}, {"cons", CHDIR | Qdevcons, 0, O_READ}, }; diff --git a/target/native/rcode b/target/native/rcode @@ -1,6 +1,7 @@ dev root uart + pl011 base=0x1C090000,clk=24000000,rate=115200 pl011 base=0x1c0c0000,clk=24000000,rate=115200 - pl011 base=0x1c0c0100,clk=24000000,rate=115200 + cons end diff --git a/target/native/rom.c b/target/native/rom.c @@ -93,20 +93,44 @@ info(Mach *mp) mp->sp, mp->stacksiz); } +/* + * TODO: This should be in devc.c. The way the rcode file is parsed should be + * modified to allow that. + */ +typedef struct attr Attr; + +struct attr { + char *key; + char *value; +}; + +extern void conslink(Attr *attr); + static void namespace(void) { - if (open("#t0/raw", O_READ) != 0) + if (open("#s0/raw", O_READ) != 0) goto error; - if (open("#t0/raw", O_WRITE) != 1) + if (open("#s0/raw", O_WRITE) != 1) goto error; - if (open("#t0/raw", O_WRITE) != 2) + if (open("#s0/raw", O_WRITE) != 2) goto error; - if (bind("#t0", "/dev/uart") < 0) + if (bind("#s0", "/dev/cons") < 0) goto error; - if (bind("#t0", "/dev/cons") < 0) + + if (bind("#t0", "/dev/uart0") < 0) goto error; + if (bind("#t1", "/dev/uart3") < 0) + goto error; + + /* + * TODO: This should be in devc.c. The way the rcode file is parsed should be + * modified to allow that. + */ + // Link required after bind + conslink((Attr []) {{"in", "/dev/uart0/raw"},{"out", "/dev/uart0/raw"},{0}}); + return; error: