Idenfity devices by name, not by char [1/3]
[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 <console.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);
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("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("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(Ebadusefd);
174         }
175         kfree(cb);
176         poperror();
177         return n;
178 }
179
180 struct dev regressdevtab __devtab = {
181         'Z',
182         "regress",
183
184         devreset,
185         regressinit,
186         devshutdown,
187         regressattach,
188         regresswalk,
189         regressstat,
190         regressopen,
191         devcreate,
192         regressclose,
193         regressread,
194         devbread,
195         regresswrite,
196         devbwrite,
197         devremove,
198         devwstat,
199 };