9ns: Fix devtab function pointer signatures
[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 <net/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 *regresswalk(struct chan *c, struct chan *nc, char **name,
77                                    unsigned int nname)
78 {
79         return devwalk(c, nc, name, nname, regresstab, ARRAY_SIZE(regresstab),
80                        devgen);
81 }
82
83 static size_t regressstat(struct chan *c, uint8_t *db, size_t 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 size_t regressread(struct chan *c, void *va, size_t n, off64_t off)
112 {
113         uint64_t w, *bp;
114         char *a, *ea;
115         uintptr_t offset = off;
116         uint64_t pc;
117         int snp_ret, ret = 0;
118
119         switch((int)c->qid.path){
120         case Monitordirqid:
121                 n = devdirread(c, va, n, regresstab, ARRAY_SIZE(regresstab), devgen);
122                 break;
123
124         case Monitorctlqid:
125                 n = readstr(off, va, n, ctlcommands);
126                 break;
127
128         case Monitordataqid:
129                 if (regress.monitor) {
130                         printd("monitordataqid: regress.monitor %p len %p\n", regress.monitor, qlen(kprof.monitor));
131                         if (qlen(regress.monitor) > 0)
132                                 n = qread(regress.monitor, va, n);
133                         else
134                                 n = 0;
135                 } else
136                         error(EFAIL, "no monitor queue");
137                 break;
138         default:
139                 n = 0;
140                 break;
141         }
142         return n;
143 }
144
145 static size_t regresswrite(struct chan *c, void *a, size_t n, off64_t unused)
146 {
147         ERRSTACK(1);
148         uintptr_t pc;
149         struct cmdbuf *cb;
150         cb = parsecmd(a, n);
151
152         if (waserror()) {
153                 kfree(cb);
154                 nexterror();
155         }
156
157         switch((int)(c->qid.path)){
158         case Monitorctlqid:
159                 if(strncmp(a, "ktest", 5) == 0){
160                         run_registered_ktest_suites();
161                 } else {
162                         error(EFAIL, "regresswrite: only commands are %s", ctlcommands);
163                 }
164                 break;
165
166         case Monitordataqid:
167                 if (onecmd(cb->nf, cb->f, NULL) < 0)
168                         n = -1;
169                 break;
170         default:
171                 error(EBADFD, ERROR_FIXME);
172         }
173         kfree(cb);
174         poperror();
175         return n;
176 }
177
178 struct dev regressdevtab __devtab = {
179         .name = "regress",
180
181         .reset = devreset,
182         .init = regressinit,
183         .shutdown = devshutdown,
184         .attach = regressattach,
185         .walk = regresswalk,
186         .stat = regressstat,
187         .open = regressopen,
188         .create = devcreate,
189         .close = regressclose,
190         .read = regressread,
191         .bread = devbread,
192         .write = regresswrite,
193         .bwrite = devbwrite,
194         .remove = devremove,
195         .wstat = devwstat,
196 };