Export CONFIG_ options via #version/kconfig
[akaros.git] / kern / drivers / dev / regress.c
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 // regression device.
11 // Currently, has only one file, monitor, which is used to send
12 // commands to the monitor.
13 // TODO: read them back :-)
14
15 #include <vfs.h>
16 #include <kfs.h>
17 #include <slab.h>
18 #include <kmalloc.h>
19 #include <kref.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <assert.h>
23 #include <error.h>
24 #include <cpio.h>
25 #include <pmap.h>
26 #include <smp.h>
27 #include <ip.h>
28 #include <monitor.h>
29 #include <ktest.h>
30
31 struct dev regressdevtab;
32
33 static char *devname(void)
34 {
35         return regressdevtab.name;
36 }
37
38 struct regress
39 {
40         spinlock_t lock;
41         struct queue *monitor;
42 };
43 struct regress regress;
44
45 enum{
46         Monitordirqid = 0,
47         Monitordataqid,
48         Monitorctlqid,
49 };
50
51 struct dirtab regresstab[]={
52         {".",           {Monitordirqid, 0, QTDIR},0,    DMDIR|0550},
53         {"mondata",     {Monitordataqid},               0,      0600},
54         {"monctl",      {Monitorctlqid},                0,      0600},
55 };
56
57 static char *ctlcommands = "ktest";
58
59 static struct chan*
60 regressattach(char *spec)
61 {
62         uint32_t n;
63
64         regress.monitor = qopen(2 << 20, 0, 0, 0);
65         if (! regress.monitor) {
66                 printk("monitor allocate failed. No monitor output\n");
67         }
68         return devattach(devname(), spec);
69 }
70
71 static void
72 regressinit(void)
73 {
74 }
75
76 static struct walkqid*
77 regresswalk(struct chan *c, struct chan *nc, char **name, int nname)
78 {
79         return devwalk(c, nc, name, nname, regresstab, ARRAY_SIZE(regresstab), devgen);
80 }
81
82 static int
83 regressstat(struct chan *c, uint8_t *db, int n)
84 {
85         if (regress.monitor)
86                 regresstab[Monitordataqid].length = qlen(regress.monitor);
87         else
88                 regresstab[Monitordataqid].length = 0;
89
90         return devstat(c, db, n, regresstab, ARRAY_SIZE(regresstab), devgen);
91 }
92
93 static struct chan*
94 regressopen(struct chan *c, int omode)
95 {
96         if(c->qid.type & QTDIR){
97                 if(openmode(omode) != O_READ)
98                         error(EPERM, ERROR_FIXME);
99         }
100         c->mode = openmode(omode);
101         c->flag |= COPEN;
102         c->offset = 0;
103         return c;
104 }
105
106 static void
107 regressclose(struct chan*unused)
108 {
109 }
110
111 static long
112 regressread(struct chan *c, void *va, long n, int64_t off)
113 {
114         uint64_t w, *bp;
115         char *a, *ea;
116         uintptr_t offset = off;
117         uint64_t pc;
118         int snp_ret, ret = 0;
119
120         switch((int)c->qid.path){
121         case Monitordirqid:
122                 n = devdirread(c, va, n, regresstab, ARRAY_SIZE(regresstab), devgen);
123                 break;
124
125         case Monitorctlqid:
126                 n = readstr(off, va, n, ctlcommands);
127                 break;
128
129         case Monitordataqid:
130                 if (regress.monitor) {
131                         printd("monitordataqid: regress.monitor %p len %p\n", regress.monitor, qlen(kprof.monitor));
132                         if (qlen(regress.monitor) > 0)
133                                 n = qread(regress.monitor, va, n);
134                         else
135                                 n = 0;
136                 } else
137                         error(EFAIL, "no monitor queue");
138                 break;
139         default:
140                 n = 0;
141                 break;
142         }
143         return n;
144 }
145
146 static long
147 regresswrite(struct chan *c, void *a, long n, int64_t unused)
148 {
149         ERRSTACK(1);
150         uintptr_t pc;
151         struct cmdbuf *cb;
152         cb = parsecmd(a, n);
153
154         if (waserror()) {
155                 kfree(cb);
156                 nexterror();
157         }
158
159         switch((int)(c->qid.path)){
160         case Monitorctlqid:
161                 if(strncmp(a, "ktest", 5) == 0){
162                         run_registered_ktest_suites();
163                 } else {
164                         error(EFAIL, "regresswrite: only commands are %s", ctlcommands);
165                 }
166                 break;
167
168         case Monitordataqid:
169                 if (onecmd(cb->nf, cb->f, NULL) < 0)
170                         n = -1;
171                 break;
172         default:
173                 error(EBADFD, ERROR_FIXME);
174         }
175         kfree(cb);
176         poperror();
177         return n;
178 }
179
180 struct dev regressdevtab __devtab = {
181         .name = "regress",
182
183         .reset = devreset,
184         .init = regressinit,
185         .shutdown = devshutdown,
186         .attach = regressattach,
187         .walk = regresswalk,
188         .stat = regressstat,
189         .open = regressopen,
190         .create = devcreate,
191         .close = regressclose,
192         .read = regressread,
193         .bread = devbread,
194         .write = regresswrite,
195         .bwrite = devbwrite,
196         .remove = devremove,
197         .wstat = devwstat,
198 };