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 ulong id, archid, rev;
157 char *manu, *arch, *socrev;
158 char unk[32], socnm[32], revname[32];
159 Pciex *pci;
160
161 m->cputype = *(ulong *)soc.devid;
162 #ifdef OLD
163 switch(m->cputype & 3) {
164 case 0:
165 socnm = "88F6[12]80";
166 break;
167 case 1:
168 socnm = "88F619[02]";
169 break;
170 case 2:
171 socnm = "88F6281";
172 break;
173 default:
174 socnm = "unknown";
175 break;
176 }
177 #endif
178 /* strange way to get this information, but it's what u-boot does */
179 pci = (Pciex *)soc.pci;
180 snprint(socnm, sizeof socnm, "88F%ux", pci->devid);
181 /* stash rev for benefit of later usb initialisation */
182 m->socrev = rev = pci->revid & MASK(4);
183
184 id = cpidget();
185 if ((id >> 24) == 0x56 && pci->venid == 0x11ab)
186 manu = "Marvell";
187 else
188 manu = "unknown";
189 archid = (id >> 16) & MASK(4);
190 switch (archid) {
191 case 5:
192 arch = "v5te";
193 break;
194 default:
195 snprint(unk, sizeof unk, "unknown (%ld)", archid);
196 arch = unk;
197 break;
198 }
199 if (pci->devid != 0x6281)
200 socrev = "unknown";
201 else
202 switch (rev) {
203 case Socrevz0:
204 socrev = "Z0";
205 break;
206 case Socreva0:
207 socrev = "A0";
208 break;
209 case Socreva1:
210 socrev = "A1";
211 break;
212 default:
213 snprint(revname, sizeof revname, "unknown rev (%ld)",
214 rev);
215 socrev = revname;
216 break;
217 }
218 seprint(buf, buf + size,
219 "%s %s %s; arm926ej-s arch %s rev %ld.%ld part %lux",
220 manu, socnm, socrev, arch, (id >> 20) & MASK(4),
221 id & MASK(4), (id >> 4) & MASK(12));
222 return buf;
223 }
224
225 static long
cputyperead(Chan *,void * a,long n,vlong offset)226 cputyperead(Chan*, void *a, long n, vlong offset)
227 {
228 char name[64], str[128];
229
230 cputype2name(name, sizeof name);
231 snprint(str, sizeof str, "ARM %s %llud\n", name, m->cpuhz / 1000000);
232 return readstr(offset, a, n, str);
233 }
234
235 static long
tbread(Chan *,void * a,long n,vlong offset)236 tbread(Chan*, void *a, long n, vlong offset)
237 {
238 char str[16];
239 uvlong tb;
240
241 cycles(&tb);
242
243 snprint(str, sizeof(str), "%16.16llux", tb);
244 return readstr(offset, a, n, str);
245 }
246
247 static long
nsread(Chan *,void * a,long n,vlong offset)248 nsread(Chan*, void *a, long n, vlong offset)
249 {
250 char str[16];
251 uvlong tb;
252
253 cycles(&tb);
254
255 snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
256 return readstr(offset, a, n, str);
257 }
258
259 void
archinit(void)260 archinit(void)
261 {
262 addarchfile("cputype", 0444, cputyperead, nil);
263 addarchfile("timebase",0444, tbread, nil);
264 // addarchfile("nsec", 0444, nsread, nil);
265 }
266