Add a #template device
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 24 Feb 2020 21:41:39 +0000 (16:41 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 Mar 2020 20:13:30 +0000 (15:13 -0500)
This is for quickly crafting simple devices that use a devdir table and
devgen().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/template.c [new file with mode: 0644]

diff --git a/kern/drivers/dev/template.c b/kern/drivers/dev/template.c
new file mode 100644 (file)
index 0000000..5d92116
--- /dev/null
@@ -0,0 +1,141 @@
+/* Copyright (c) 2020 Google Inc
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * #template.  Dummy device with a devdir table.
+ */
+
+#include <ns.h>
+#include <kmalloc.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <error.h>
+
+struct dev template_devtab;
+
+static char *devname(void)
+{
+       return template_devtab.name;
+}
+
+enum {
+       Qdir,
+       Qctl,
+};
+
+static struct dirtab XXX_dir[] = {
+       {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0555},
+       {"ctl", {Qctl, 0, QTFILE}, 0, 0666},
+};
+
+static struct chan *XXX_attach(char *spec)
+{
+       return devattach(devname(), spec);
+}
+
+static struct walkqid *XXX_walk(struct chan *c, struct chan *nc, char **name,
+                              unsigned int nname)
+{
+       return devwalk(c, nc, name, nname, XXX_dir, ARRAY_SIZE(XXX_dir),
+                      devgen);
+}
+
+static size_t XXX_stat(struct chan *c, uint8_t *db, size_t n)
+{
+       return devstat(c, db, n, XXX_dir, ARRAY_SIZE(XXX_dir), devgen);
+}
+
+static struct chan *XXX_open(struct chan *c, int omode)
+{
+       return devopen(c, omode, XXX_dir, ARRAY_SIZE(XXX_dir), devgen);
+}
+
+static void XXX_close(struct chan *c)
+{
+       /* If you do anything after open, only undo it for COPEN chans */
+       if (!(c->flag & COPEN))
+               return;
+}
+
+static size_t XXX_read(struct chan *c, void *ubuf, size_t n, off64_t offset)
+{
+       switch (c->qid.path) {
+       case Qdir:
+               return devdirread(c, ubuf, n, XXX_dir, ARRAY_SIZE(XXX_dir),
+                                 devgen);
+       case Qctl:
+               return readstr(offset, ubuf, n, "XXX");
+       default:
+               panic("Bad Qid %p!", c->qid.path);
+       }
+       return -1;
+}
+
+#define XXX_CTL_USAGE "start|stop|print|reset"
+
+static void XXX_ctl_cmd(struct chan *c, struct cmdbuf *cb)
+{
+       ERRSTACK(1);
+
+       if (cb->nf < 1)
+               error(EFAIL, XXX_CTL_USAGE);
+
+       if (waserror()) {
+               nexterror();
+       }
+       if (!strcmp(cb->f[0], "start")) {
+               ;
+       } else if (!strcmp(cb->f[0], "stop")) {
+               ;
+       } else if (!strcmp(cb->f[0], "print")) {
+               ;
+       } else if (!strcmp(cb->f[0], "reset")) {
+               ;
+       } else {
+               error(EFAIL, XXX_CTL_USAGE);
+       }
+       poperror();
+}
+
+static size_t XXX_write(struct chan *c, void *ubuf, size_t n, off64_t unused)
+{
+       ERRSTACK(1);
+       struct cmdbuf *cb = parsecmd(ubuf, n);
+
+       if (waserror()) {
+               kfree(cb);
+               nexterror();
+       }
+       switch (c->qid.path) {
+       case Qctl:
+               XXX_ctl_cmd(c, cb);
+               break;
+       default:
+               error(EFAIL, "Unable to write to %s", devname());
+       }
+       kfree(cb);
+       poperror();
+       return n;
+}
+
+struct dev template_devtab __devtab = {
+       .name = "template",
+       .reset = devreset,
+       .init = devinit,
+       .shutdown = devshutdown,
+       .attach = XXX_attach,
+       .walk = XXX_walk,
+       .stat = XXX_stat,
+       .open = XXX_open,
+       .create = devcreate,
+       .close = XXX_close,
+       .read = XXX_read,
+       .bread = devbread,
+       .write = XXX_write,
+       .bwrite = devbwrite,
+       .remove = devremove,
+       .wstat = devwstat,
+       .power = devpower,
+       .chaninfo = devchaninfo,
+};