1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "io.h"
8
9 #include "../ip/ip.h"
10
11 enum {
12 Qdir = 0,
13 Qbase,
14
15 Qmax = 16,
16 };
17
18 typedef long Rdwrfn(Chan*, void*, long, vlong);
19
20 static Rdwrfn *readfn[Qmax];
21 static Rdwrfn *writefn[Qmax];
22
23 static Dirtab archdir[Qmax] = {
24 ".", { Qdir, 0, QTDIR }, 0, 0555,
25 };
26
27 Lock archwlock; /* the lock is only for changing archdir */
28 int narchdir = Qbase;
29
30 /*
31 * Add a file to the #P listing. Once added, you can't delete it.
32 * You can't add a file with the same name as one already there,
33 * and you get a pointer to the Dirtab entry so you can do things
34 * like change the Qid version. Changing the Qid path is disallowed.
35 */
36 Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)37 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
38 {
39 int i;
40 Dirtab d;
41 Dirtab *dp;
42
43 memset(&d, 0, sizeof d);
44 strcpy(d.name, name);
45 d.perm = perm;
46
47 lock(&archwlock);
48 if(narchdir >= Qmax){
49 unlock(&archwlock);
50 return nil;
51 }
52
53 for(i=0; i<narchdir; i++)
54 if(strcmp(archdir[i].name, name) == 0){
55 unlock(&archwlock);
56 return nil;
57 }
58
59 d.qid.path = narchdir;
60 archdir[narchdir] = d;
61 readfn[narchdir] = rdfn;
62 writefn[narchdir] = wrfn;
63 dp = &archdir[narchdir++];
64 unlock(&archwlock);
65
66 return dp;
67 }
68
69 static Chan*
archattach(char * spec)70 archattach(char* spec)
71 {
72 return devattach('P', spec);
73 }
74
75 Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)76 archwalk(Chan* c, Chan *nc, char** name, int nname)
77 {
78 return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
79 }
80
81 static int
archstat(Chan * c,uchar * dp,int n)82 archstat(Chan* c, uchar* dp, int n)
83 {
84 return devstat(c, dp, n, archdir, narchdir, devgen);
85 }
86
87 static Chan*
archopen(Chan * c,int omode)88 archopen(Chan* c, int omode)
89 {
90 return devopen(c, omode, archdir, narchdir, devgen);
91 }
92
93 static void
archclose(Chan *)94 archclose(Chan*)
95 {
96 }
97
98 static long
archread(Chan * c,void * a,long n,vlong offset)99 archread(Chan *c, void *a, long n, vlong offset)
100 {
101 Rdwrfn *fn;
102
103 switch((ulong)c->qid.path){
104 case Qdir:
105 return devdirread(c, a, n, archdir, narchdir, devgen);
106
107 default:
108 if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
109 return fn(c, a, n, offset);
110 error(Eperm);
111 break;
112 }
113
114 return 0;
115 }
116
117 static long
archwrite(Chan * c,void * a,long n,vlong offset)118 archwrite(Chan *c, void *a, long n, vlong offset)
119 {
120 Rdwrfn *fn;
121
122 if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
123 return fn(c, a, n, offset);
124 error(Eperm);
125
126 return 0;
127 }
128
129 void archinit(void);
130
131 Dev archdevtab = {
132 'P',
133 "arch",
134
135 devreset,
136 archinit,
137 devshutdown,
138 archattach,
139 archwalk,
140 archstat,
141 archopen,
142 devcreate,
143 archclose,
144 archread,
145 devbread,
146 archwrite,
147 devbwrite,
148 devremove,
149 devwstat,
150 };
151
152 /* convert AddrDevid register to a string in buf and return buf */
153 char *
cputype2name(char * buf,int size)154 cputype2name(char *buf, int size)
155 {
156 seprint(buf, buf + size, "Cortex-A8");
157 return buf;
158 }
159
160 static long
cputyperead(Chan *,void * a,long n,vlong offset)161 cputyperead(Chan*, void *a, long n, vlong offset)
162 {
163 char name[64], str[128];
164
165 cputype2name(name, sizeof name);
166 snprint(str, sizeof str, "ARM %s %llud\n", name, m->cpuhz / Mhz);
167 return readstr(offset, a, n, str);
168 }
169
170 static long
tbread(Chan *,void * a,long n,vlong offset)171 tbread(Chan*, void *a, long n, vlong offset)
172 {
173 char str[16];
174 uvlong tb;
175
176 cycles(&tb);
177
178 snprint(str, sizeof(str), "%16.16llux", tb);
179 return readstr(offset, a, n, str);
180 }
181
182 static long
nsread(Chan *,void * a,long n,vlong offset)183 nsread(Chan*, void *a, long n, vlong offset)
184 {
185 char str[16];
186 uvlong tb;
187
188 cycles(&tb);
189
190 snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
191 return readstr(offset, a, n, str);
192 }
193
194 void
archinit(void)195 archinit(void)
196 {
197 addarchfile("cputype", 0444, cputyperead, nil);
198 addarchfile("timebase",0444, tbread, nil);
199 // addarchfile("nsec", 0444, nsread, nil);
200 }
201