xref: /plan9/sys/src/9/bcm/devarch.c (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
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 enum {
10 	Qdir = 0,
11 	Qbase,
12 
13 	Qmax = 16,
14 };
15 
16 typedef long Rdwrfn(Chan*, void*, long, vlong);
17 
18 static Rdwrfn *readfn[Qmax];
19 static Rdwrfn *writefn[Qmax];
20 
21 static Dirtab archdir[Qmax] = {
22 	".",		{ Qdir, 0, QTDIR },	0,	0555,
23 };
24 
25 Lock archwlock;	/* the lock is only for changing archdir */
26 int narchdir = Qbase;
27 
28 /*
29  * Add a file to the #P listing.  Once added, you can't delete it.
30  * You can't add a file with the same name as one already there,
31  * and you get a pointer to the Dirtab entry so you can do things
32  * like change the Qid version.  Changing the Qid path is disallowed.
33  */
34 Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)35 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
36 {
37 	int i;
38 	Dirtab d;
39 	Dirtab *dp;
40 
41 	memset(&d, 0, sizeof d);
42 	strcpy(d.name, name);
43 	d.perm = perm;
44 
45 	lock(&archwlock);
46 	if(narchdir >= Qmax){
47 		unlock(&archwlock);
48 		return nil;
49 	}
50 
51 	for(i=0; i<narchdir; i++)
52 		if(strcmp(archdir[i].name, name) == 0){
53 			unlock(&archwlock);
54 			return nil;
55 		}
56 
57 	d.qid.path = narchdir;
58 	archdir[narchdir] = d;
59 	readfn[narchdir] = rdfn;
60 	writefn[narchdir] = wrfn;
61 	dp = &archdir[narchdir++];
62 	unlock(&archwlock);
63 
64 	return dp;
65 }
66 
67 static Chan*
archattach(char * spec)68 archattach(char* spec)
69 {
70 	return devattach('P', spec);
71 }
72 
73 Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)74 archwalk(Chan* c, Chan *nc, char** name, int nname)
75 {
76 	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
77 }
78 
79 static int
archstat(Chan * c,uchar * dp,int n)80 archstat(Chan* c, uchar* dp, int n)
81 {
82 	return devstat(c, dp, n, archdir, narchdir, devgen);
83 }
84 
85 static Chan*
archopen(Chan * c,int omode)86 archopen(Chan* c, int omode)
87 {
88 	return devopen(c, omode, archdir, narchdir, devgen);
89 }
90 
91 static void
archclose(Chan *)92 archclose(Chan*)
93 {
94 }
95 
96 static long
archread(Chan * c,void * a,long n,vlong offset)97 archread(Chan *c, void *a, long n, vlong offset)
98 {
99 	Rdwrfn *fn;
100 
101 	switch((ulong)c->qid.path){
102 	case Qdir:
103 		return devdirread(c, a, n, archdir, narchdir, devgen);
104 
105 	default:
106 		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
107 			return fn(c, a, n, offset);
108 		error(Eperm);
109 		break;
110 	}
111 
112 	return 0;
113 }
114 
115 static long
archwrite(Chan * c,void * a,long n,vlong offset)116 archwrite(Chan *c, void *a, long n, vlong offset)
117 {
118 	Rdwrfn *fn;
119 
120 	if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
121 		return fn(c, a, n, offset);
122 	error(Eperm);
123 
124 	return 0;
125 }
126 
127 void archinit(void);
128 
129 Dev archdevtab = {
130 	'P',
131 	"arch",
132 
133 	devreset,
134 	archinit,
135 	devshutdown,
136 	archattach,
137 	archwalk,
138 	archstat,
139 	archopen,
140 	devcreate,
141 	archclose,
142 	archread,
143 	devbread,
144 	archwrite,
145 	devbwrite,
146 	devremove,
147 	devwstat,
148 };
149 
150 static long
cputyperead(Chan *,void * a,long n,vlong offset)151 cputyperead(Chan*, void *a, long n, vlong offset)
152 {
153 	char str[128];
154 
155 	snprint(str, sizeof str, "ARM11 %d\n", m->cpumhz);
156 	return readstr(offset, a, n, str);
157 }
158 
159 void
archinit(void)160 archinit(void)
161 {
162 	addarchfile("cputype", 0444, cputyperead, nil);
163 }
164