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* 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* 68 archattach(char* spec) 69 { 70 return devattach('P', spec); 71 } 72 73 Walkqid* 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 80 archstat(Chan* c, uchar* dp, int n) 81 { 82 return devstat(c, dp, n, archdir, narchdir, devgen); 83 } 84 85 static Chan* 86 archopen(Chan* c, int omode) 87 { 88 return devopen(c, omode, archdir, narchdir, devgen); 89 } 90 91 static void 92 archclose(Chan*) 93 { 94 } 95 96 static long 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 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 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 160 archinit(void) 161 { 162 addarchfile("cputype", 0444, cputyperead, nil); 163 } 164