19a747e4fSDavid du Colombier #include "u.h" 29a747e4fSDavid du Colombier #include "../port/lib.h" 39a747e4fSDavid du Colombier #include "mem.h" 49a747e4fSDavid du Colombier #include "dat.h" 59a747e4fSDavid du Colombier #include "fns.h" 69a747e4fSDavid du Colombier #include "../port/error.h" 79a747e4fSDavid du Colombier 89a747e4fSDavid du Colombier enum 99a747e4fSDavid du Colombier { 109a747e4fSDavid du Colombier Qtopdir, 119a747e4fSDavid du Colombier Qsegdir, 129a747e4fSDavid du Colombier Qctl, 139a747e4fSDavid du Colombier Qdata, 149a747e4fSDavid du Colombier 159a747e4fSDavid du Colombier /* commands to kproc */ 169a747e4fSDavid du Colombier Cnone=0, 179a747e4fSDavid du Colombier Cread, 189a747e4fSDavid du Colombier Cwrite, 199a747e4fSDavid du Colombier Cstart, 209a747e4fSDavid du Colombier Cdie, 219a747e4fSDavid du Colombier }; 229a747e4fSDavid du Colombier 239a747e4fSDavid du Colombier #define TYPE(x) (int)( (c)->qid.path & 0x7 ) 249a747e4fSDavid du Colombier #define SEG(x) ( ((c)->qid.path >> 3) & 0x3f ) 259a747e4fSDavid du Colombier #define PATH(s, t) ( ((s)<<3) | (t) ) 269a747e4fSDavid du Colombier 279a747e4fSDavid du Colombier typedef struct Globalseg Globalseg; 289a747e4fSDavid du Colombier struct Globalseg 299a747e4fSDavid du Colombier { 309a747e4fSDavid du Colombier Ref; 319a747e4fSDavid du Colombier Segment *s; 329a747e4fSDavid du Colombier 339a747e4fSDavid du Colombier char *name; 349a747e4fSDavid du Colombier char *uid; 359a747e4fSDavid du Colombier vlong length; 369a747e4fSDavid du Colombier long perm; 379a747e4fSDavid du Colombier 389a747e4fSDavid du Colombier /* kproc to do reading and writing */ 399a747e4fSDavid du Colombier QLock l; /* sync kproc access */ 409a747e4fSDavid du Colombier Rendez cmdwait; /* where kproc waits */ 419a747e4fSDavid du Colombier Rendez replywait; /* where requestor waits */ 429a747e4fSDavid du Colombier Proc *kproc; 439a747e4fSDavid du Colombier char *data; 449a747e4fSDavid du Colombier long off; 459a747e4fSDavid du Colombier int dlen; 469a747e4fSDavid du Colombier int cmd; 479a747e4fSDavid du Colombier char err[64]; 489a747e4fSDavid du Colombier }; 499a747e4fSDavid du Colombier 509a747e4fSDavid du Colombier static Globalseg *globalseg[100]; 519a747e4fSDavid du Colombier static Lock globalseglock; 529a747e4fSDavid du Colombier 539a747e4fSDavid du Colombier 549a747e4fSDavid du Colombier Segment* (*_globalsegattach)(Proc*, char*); 559a747e4fSDavid du Colombier static Segment* globalsegattach(Proc *p, char *name); 569a747e4fSDavid du Colombier static int cmddone(void*); 579a747e4fSDavid du Colombier static void segmentkproc(void*); 589a747e4fSDavid du Colombier static void docmd(Globalseg *g, int cmd); 599a747e4fSDavid du Colombier 609a747e4fSDavid du Colombier /* 619a747e4fSDavid du Colombier * returns with globalseg incref'd 629a747e4fSDavid du Colombier */ 639a747e4fSDavid du Colombier static Globalseg* 649a747e4fSDavid du Colombier getgseg(Chan *c) 659a747e4fSDavid du Colombier { 669a747e4fSDavid du Colombier int x; 679a747e4fSDavid du Colombier Globalseg *g; 689a747e4fSDavid du Colombier 699a747e4fSDavid du Colombier x = SEG(c); 709a747e4fSDavid du Colombier lock(&globalseglock); 719a747e4fSDavid du Colombier if(x >= nelem(globalseg)) 729a747e4fSDavid du Colombier panic("getgseg"); 739a747e4fSDavid du Colombier g = globalseg[x]; 749a747e4fSDavid du Colombier if(g != nil) 759a747e4fSDavid du Colombier incref(g); 769a747e4fSDavid du Colombier unlock(&globalseglock); 779a747e4fSDavid du Colombier if(g == nil) 789a747e4fSDavid du Colombier error("global segment disappeared"); 799a747e4fSDavid du Colombier return g; 809a747e4fSDavid du Colombier } 819a747e4fSDavid du Colombier 829a747e4fSDavid du Colombier static void 839a747e4fSDavid du Colombier putgseg(Globalseg *g) 849a747e4fSDavid du Colombier { 859a747e4fSDavid du Colombier if(decref(g) > 0) 869a747e4fSDavid du Colombier return; 879a747e4fSDavid du Colombier if(g->s != nil) 889a747e4fSDavid du Colombier putseg(g->s); 899a747e4fSDavid du Colombier if(g->kproc) 909a747e4fSDavid du Colombier docmd(g, Cdie); 919a747e4fSDavid du Colombier free(g->name); 929a747e4fSDavid du Colombier free(g->uid); 939a747e4fSDavid du Colombier free(g); 949a747e4fSDavid du Colombier } 959a747e4fSDavid du Colombier 969a747e4fSDavid du Colombier static int 979a747e4fSDavid du Colombier segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) 989a747e4fSDavid du Colombier { 999a747e4fSDavid du Colombier Qid q; 1009a747e4fSDavid du Colombier Globalseg *g; 1019a747e4fSDavid du Colombier ulong size; 1029a747e4fSDavid du Colombier 1039a747e4fSDavid du Colombier switch(TYPE(c)) { 1049a747e4fSDavid du Colombier case Qtopdir: 1059a747e4fSDavid du Colombier if(s == DEVDOTDOT){ 1069a747e4fSDavid du Colombier q.vers = 0; 1079a747e4fSDavid du Colombier q.path = PATH(0, Qtopdir); 1089a747e4fSDavid du Colombier q.type = QTDIR; 1099a747e4fSDavid du Colombier devdir(c, q, "#g", 0, eve, DMDIR|0777, dp); 1109a747e4fSDavid du Colombier break; 1119a747e4fSDavid du Colombier } 1129a747e4fSDavid du Colombier 1139a747e4fSDavid du Colombier if(s >= nelem(globalseg)) 1149a747e4fSDavid du Colombier return -1; 1159a747e4fSDavid du Colombier 1169a747e4fSDavid du Colombier lock(&globalseglock); 1179a747e4fSDavid du Colombier g = globalseg[s]; 1189a747e4fSDavid du Colombier if(g == nil){ 1199a747e4fSDavid du Colombier unlock(&globalseglock); 1209a747e4fSDavid du Colombier return 0; 1219a747e4fSDavid du Colombier } 1229a747e4fSDavid du Colombier q.vers = 0; 1239a747e4fSDavid du Colombier q.path = PATH(s, Qsegdir); 1249a747e4fSDavid du Colombier q.type = QTDIR; 1259a747e4fSDavid du Colombier devdir(c, q, g->name, 0, g->uid, DMDIR|0777, dp); 1269a747e4fSDavid du Colombier unlock(&globalseglock); 1279a747e4fSDavid du Colombier 1289a747e4fSDavid du Colombier break; 1299a747e4fSDavid du Colombier case Qsegdir: 1309a747e4fSDavid du Colombier if(s == DEVDOTDOT){ 1319a747e4fSDavid du Colombier q.vers = 0; 1329a747e4fSDavid du Colombier q.path = PATH(0, Qtopdir); 1339a747e4fSDavid du Colombier q.type = QTDIR; 1349a747e4fSDavid du Colombier devdir(c, q, "#g", 0, eve, DMDIR|0777, dp); 1359a747e4fSDavid du Colombier break; 1369a747e4fSDavid du Colombier } 1379a747e4fSDavid du Colombier /* fall through */ 1389a747e4fSDavid du Colombier case Qctl: 1399a747e4fSDavid du Colombier case Qdata: 1409a747e4fSDavid du Colombier switch(s){ 1419a747e4fSDavid du Colombier case 0: 1429a747e4fSDavid du Colombier g = getgseg(c); 1439a747e4fSDavid du Colombier q.vers = 0; 1449a747e4fSDavid du Colombier q.path = PATH(SEG(c), Qctl); 1459a747e4fSDavid du Colombier q.type = QTFILE; 1469a747e4fSDavid du Colombier devdir(c, q, "ctl", 0, g->uid, g->perm, dp); 1479a747e4fSDavid du Colombier putgseg(g); 1489a747e4fSDavid du Colombier break; 1499a747e4fSDavid du Colombier case 1: 1509a747e4fSDavid du Colombier g = getgseg(c); 1519a747e4fSDavid du Colombier q.vers = 0; 1529a747e4fSDavid du Colombier q.path = PATH(SEG(c), Qdata); 1539a747e4fSDavid du Colombier q.type = QTFILE; 1549a747e4fSDavid du Colombier if(g->s != nil) 1559a747e4fSDavid du Colombier size = g->s->top - g->s->base; 1569a747e4fSDavid du Colombier else 1579a747e4fSDavid du Colombier size = 0; 1589a747e4fSDavid du Colombier devdir(c, q, "data", size, g->uid, g->perm, dp); 1599a747e4fSDavid du Colombier putgseg(g); 1609a747e4fSDavid du Colombier break; 1619a747e4fSDavid du Colombier default: 1629a747e4fSDavid du Colombier return -1; 1639a747e4fSDavid du Colombier } 1649a747e4fSDavid du Colombier break; 1659a747e4fSDavid du Colombier } 1669a747e4fSDavid du Colombier return 1; 1679a747e4fSDavid du Colombier } 1689a747e4fSDavid du Colombier 1699a747e4fSDavid du Colombier static void 1709a747e4fSDavid du Colombier segmentinit(void) 1719a747e4fSDavid du Colombier { 1729a747e4fSDavid du Colombier _globalsegattach = globalsegattach; 1739a747e4fSDavid du Colombier } 1749a747e4fSDavid du Colombier 1759a747e4fSDavid du Colombier static Chan* 1769a747e4fSDavid du Colombier segmentattach(char *spec) 1779a747e4fSDavid du Colombier { 1789a747e4fSDavid du Colombier return devattach('g', spec); 1799a747e4fSDavid du Colombier } 1809a747e4fSDavid du Colombier 1819a747e4fSDavid du Colombier static Walkqid* 1829a747e4fSDavid du Colombier segmentwalk(Chan *c, Chan *nc, char **name, int nname) 1839a747e4fSDavid du Colombier { 1849a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, segmentgen); 1859a747e4fSDavid du Colombier } 1869a747e4fSDavid du Colombier 1879a747e4fSDavid du Colombier static int 1889a747e4fSDavid du Colombier segmentstat(Chan *c, uchar *db, int n) 1899a747e4fSDavid du Colombier { 1909a747e4fSDavid du Colombier return devstat(c, db, n, 0, 0, segmentgen); 1919a747e4fSDavid du Colombier } 1929a747e4fSDavid du Colombier 1939a747e4fSDavid du Colombier static int 1949a747e4fSDavid du Colombier cmddone(void *arg) 1959a747e4fSDavid du Colombier { 1969a747e4fSDavid du Colombier Globalseg *g = arg; 1979a747e4fSDavid du Colombier 1989a747e4fSDavid du Colombier return g->cmd == Cnone; 1999a747e4fSDavid du Colombier } 2009a747e4fSDavid du Colombier 2019a747e4fSDavid du Colombier static Chan* 2029a747e4fSDavid du Colombier segmentopen(Chan *c, int omode) 2039a747e4fSDavid du Colombier { 2049a747e4fSDavid du Colombier Globalseg *g; 2059a747e4fSDavid du Colombier 2069a747e4fSDavid du Colombier switch(TYPE(c)){ 2079a747e4fSDavid du Colombier case Qtopdir: 2089a747e4fSDavid du Colombier case Qsegdir: 2099a747e4fSDavid du Colombier if(omode != 0) 2109a747e4fSDavid du Colombier error(Eisdir); 2119a747e4fSDavid du Colombier break; 2129a747e4fSDavid du Colombier case Qctl: 2139a747e4fSDavid du Colombier g = getgseg(c); 2149a747e4fSDavid du Colombier if(waserror()){ 2159a747e4fSDavid du Colombier putgseg(g); 2169a747e4fSDavid du Colombier nexterror(); 2179a747e4fSDavid du Colombier } 2189a747e4fSDavid du Colombier devpermcheck(g->uid, g->perm, omode); 2199a747e4fSDavid du Colombier c->aux = g; 2209a747e4fSDavid du Colombier poperror(); 2219a747e4fSDavid du Colombier c->flag |= COPEN; 2229a747e4fSDavid du Colombier break; 2239a747e4fSDavid du Colombier case Qdata: 2249a747e4fSDavid du Colombier g = getgseg(c); 2259a747e4fSDavid du Colombier if(waserror()){ 2269a747e4fSDavid du Colombier putgseg(g); 2279a747e4fSDavid du Colombier nexterror(); 2289a747e4fSDavid du Colombier } 2299a747e4fSDavid du Colombier devpermcheck(g->uid, g->perm, omode); 2309a747e4fSDavid du Colombier if(g->s == nil) 2319a747e4fSDavid du Colombier error("segment not yet allocated"); 2329a747e4fSDavid du Colombier if(g->kproc == nil){ 2339a747e4fSDavid du Colombier qlock(&g->l); 2349a747e4fSDavid du Colombier if(waserror()){ 2359a747e4fSDavid du Colombier qunlock(&g->l); 2369a747e4fSDavid du Colombier nexterror(); 2379a747e4fSDavid du Colombier } 2389a747e4fSDavid du Colombier if(g->kproc == nil){ 2399a747e4fSDavid du Colombier g->cmd = Cnone; 2409a747e4fSDavid du Colombier kproc(g->name, segmentkproc, g); 2419a747e4fSDavid du Colombier docmd(g, Cstart); 2429a747e4fSDavid du Colombier } 2439a747e4fSDavid du Colombier qunlock(&g->l); 2449a747e4fSDavid du Colombier poperror(); 2459a747e4fSDavid du Colombier } 2469a747e4fSDavid du Colombier c->aux = g; 2479a747e4fSDavid du Colombier poperror(); 2489a747e4fSDavid du Colombier c->flag |= COPEN; 2499a747e4fSDavid du Colombier break; 2509a747e4fSDavid du Colombier default: 2519a747e4fSDavid du Colombier panic("segmentopen"); 2529a747e4fSDavid du Colombier } 2539a747e4fSDavid du Colombier c->mode = openmode(omode); 2549a747e4fSDavid du Colombier c->offset = 0; 2559a747e4fSDavid du Colombier return c; 2569a747e4fSDavid du Colombier } 2579a747e4fSDavid du Colombier 2589a747e4fSDavid du Colombier static void 2599a747e4fSDavid du Colombier segmentclose(Chan *c) 2609a747e4fSDavid du Colombier { 2619a747e4fSDavid du Colombier if(TYPE(c) == Qtopdir) 2629a747e4fSDavid du Colombier return; 2639a747e4fSDavid du Colombier if(c->flag & COPEN) 2649a747e4fSDavid du Colombier putgseg(c->aux); 2659a747e4fSDavid du Colombier } 2669a747e4fSDavid du Colombier 2679a747e4fSDavid du Colombier static void 2689a747e4fSDavid du Colombier segmentcreate(Chan *c, char *name, int omode, ulong perm) 2699a747e4fSDavid du Colombier { 2709a747e4fSDavid du Colombier int x, xfree; 2719a747e4fSDavid du Colombier Globalseg *g; 2729a747e4fSDavid du Colombier 2739a747e4fSDavid du Colombier if(TYPE(c) != Qtopdir) 2749a747e4fSDavid du Colombier error(Eperm); 2759a747e4fSDavid du Colombier 2769a747e4fSDavid du Colombier if(isphysseg(name)) 2779a747e4fSDavid du Colombier error(Eexist); 2789a747e4fSDavid du Colombier 2799a747e4fSDavid du Colombier if((perm & DMDIR) == 0) 2809a747e4fSDavid du Colombier error(Ebadarg); 2819a747e4fSDavid du Colombier 2829a747e4fSDavid du Colombier if(waserror()){ 2839a747e4fSDavid du Colombier unlock(&globalseglock); 2849a747e4fSDavid du Colombier nexterror(); 2859a747e4fSDavid du Colombier } 2869a747e4fSDavid du Colombier lock(&globalseglock); 2879a747e4fSDavid du Colombier xfree = -1; 2889a747e4fSDavid du Colombier for(x = 0; x < nelem(globalseg); x++){ 2899a747e4fSDavid du Colombier g = globalseg[x]; 2909a747e4fSDavid du Colombier if(g == nil){ 2919a747e4fSDavid du Colombier if(xfree < 0) 2929a747e4fSDavid du Colombier xfree = x; 2939a747e4fSDavid du Colombier } else { 2949a747e4fSDavid du Colombier if(strcmp(g->name, name) == 0) 2959a747e4fSDavid du Colombier error(Eexist); 2969a747e4fSDavid du Colombier } 2979a747e4fSDavid du Colombier } 2989a747e4fSDavid du Colombier if(xfree < 0) 2999a747e4fSDavid du Colombier error("too many global segments"); 3009a747e4fSDavid du Colombier g = smalloc(sizeof(Globalseg)); 3019a747e4fSDavid du Colombier g->ref = 1; 3029a747e4fSDavid du Colombier kstrdup(&g->name, name); 3039a747e4fSDavid du Colombier kstrdup(&g->uid, up->user); 3049a747e4fSDavid du Colombier g->perm = 0660; 3059a747e4fSDavid du Colombier globalseg[xfree] = g; 3069a747e4fSDavid du Colombier unlock(&globalseglock); 3079a747e4fSDavid du Colombier poperror(); 3089a747e4fSDavid du Colombier 3099a747e4fSDavid du Colombier c->qid.path = PATH(x, Qsegdir); 3109a747e4fSDavid du Colombier c->qid.type = QTDIR; 3119a747e4fSDavid du Colombier c->qid.vers = 0; 3129a747e4fSDavid du Colombier c->mode = openmode(omode); 3139a747e4fSDavid du Colombier c->mode = OWRITE; 3149a747e4fSDavid du Colombier } 3159a747e4fSDavid du Colombier 3169a747e4fSDavid du Colombier static long 3179a747e4fSDavid du Colombier segmentread(Chan *c, void *a, long n, vlong voff) 3189a747e4fSDavid du Colombier { 3199a747e4fSDavid du Colombier Globalseg *g; 3209a747e4fSDavid du Colombier char buf[32]; 3219a747e4fSDavid du Colombier 3229a747e4fSDavid du Colombier if(c->qid.type == QTDIR) 3239a747e4fSDavid du Colombier return devdirread(c, a, n, (Dirtab *)0, 0L, segmentgen); 3249a747e4fSDavid du Colombier 3259a747e4fSDavid du Colombier switch(TYPE(c)){ 3269a747e4fSDavid du Colombier case Qctl: 3279a747e4fSDavid du Colombier g = c->aux; 3289a747e4fSDavid du Colombier if(g->s == nil) 3299a747e4fSDavid du Colombier error("segment not yet allocated"); 3309a747e4fSDavid du Colombier sprint(buf, "va 0x%lux 0x%lux\n", g->s->base, g->s->top-g->s->base); 3319a747e4fSDavid du Colombier return readstr(voff, a, n, buf); 3329a747e4fSDavid du Colombier case Qdata: 3339a747e4fSDavid du Colombier g = c->aux; 3349a747e4fSDavid du Colombier if(voff > g->s->top - g->s->base) 3359a747e4fSDavid du Colombier error(Ebadarg); 3369a747e4fSDavid du Colombier if(voff + n > g->s->top - g->s->base) 3379a747e4fSDavid du Colombier n = g->s->top - g->s->base - voff; 3389a747e4fSDavid du Colombier qlock(&g->l); 3399a747e4fSDavid du Colombier g->off = voff + g->s->base; 3409a747e4fSDavid du Colombier g->data = smalloc(n); 3419a747e4fSDavid du Colombier if(waserror()){ 3429a747e4fSDavid du Colombier free(g->data); 3439a747e4fSDavid du Colombier qunlock(&g->l); 3449a747e4fSDavid du Colombier nexterror(); 3459a747e4fSDavid du Colombier } 3469a747e4fSDavid du Colombier g->dlen = n; 3479a747e4fSDavid du Colombier docmd(g, Cread); 3489a747e4fSDavid du Colombier memmove(a, g->data, g->dlen); 3499a747e4fSDavid du Colombier free(g->data); 3509a747e4fSDavid du Colombier qunlock(&g->l); 3519a747e4fSDavid du Colombier poperror(); 3529a747e4fSDavid du Colombier return g->dlen; 3539a747e4fSDavid du Colombier default: 3549a747e4fSDavid du Colombier panic("segmentread"); 3559a747e4fSDavid du Colombier } 3569a747e4fSDavid du Colombier return 0; /* not reached */ 3579a747e4fSDavid du Colombier } 3589a747e4fSDavid du Colombier 3599a747e4fSDavid du Colombier static long 3609a747e4fSDavid du Colombier segmentwrite(Chan *c, void *a, long n, vlong voff) 3619a747e4fSDavid du Colombier { 3629a747e4fSDavid du Colombier Cmdbuf *cb; 3639a747e4fSDavid du Colombier Globalseg *g; 3649a747e4fSDavid du Colombier ulong va, len, top; 3659a747e4fSDavid du Colombier 3669a747e4fSDavid du Colombier if(c->qid.type == QTDIR) 3679a747e4fSDavid du Colombier error(Eperm); 3689a747e4fSDavid du Colombier 3699a747e4fSDavid du Colombier switch(TYPE(c)){ 3709a747e4fSDavid du Colombier case Qctl: 3719a747e4fSDavid du Colombier g = c->aux; 3729a747e4fSDavid du Colombier cb = parsecmd(a, n); 3739a747e4fSDavid du Colombier if(strcmp(cb->f[0], "va") == 0){ 3749a747e4fSDavid du Colombier if(g->s != nil) 3759a747e4fSDavid du Colombier error("already has a virtual address"); 3769a747e4fSDavid du Colombier if(cb->nf < 3) 3779a747e4fSDavid du Colombier error(Ebadarg); 3789a747e4fSDavid du Colombier va = strtoul(cb->f[1], 0, 0); 3799a747e4fSDavid du Colombier len = strtoul(cb->f[2], 0, 0); 3809a747e4fSDavid du Colombier top = PGROUND(va + len); 3819a747e4fSDavid du Colombier va = va&~(BY2PG-1); 3829a747e4fSDavid du Colombier len = (top - va) / BY2PG; 3839a747e4fSDavid du Colombier if(len == 0) 3849a747e4fSDavid du Colombier error(Ebadarg); 3859a747e4fSDavid du Colombier g->s = newseg(SG_SHARED, va, len); 3869a747e4fSDavid du Colombier } else 3879a747e4fSDavid du Colombier error(Ebadctl); 3889a747e4fSDavid du Colombier break; 3899a747e4fSDavid du Colombier case Qdata: 3909a747e4fSDavid du Colombier g = c->aux; 3919a747e4fSDavid du Colombier if(voff + n > g->s->top - g->s->base) 3929a747e4fSDavid du Colombier error(Ebadarg); 3939a747e4fSDavid du Colombier qlock(&g->l); 3949a747e4fSDavid du Colombier g->off = voff + g->s->base; 3959a747e4fSDavid du Colombier g->data = smalloc(n); 3969a747e4fSDavid du Colombier if(waserror()){ 3979a747e4fSDavid du Colombier free(g->data); 3989a747e4fSDavid du Colombier qunlock(&g->l); 3999a747e4fSDavid du Colombier nexterror(); 4009a747e4fSDavid du Colombier } 4019a747e4fSDavid du Colombier g->dlen = n; 4029a747e4fSDavid du Colombier memmove(g->data, a, g->dlen); 4039a747e4fSDavid du Colombier docmd(g, Cwrite); 4049a747e4fSDavid du Colombier free(g->data); 4059a747e4fSDavid du Colombier qunlock(&g->l); 4069a747e4fSDavid du Colombier poperror(); 4079a747e4fSDavid du Colombier return g->dlen; 4089a747e4fSDavid du Colombier default: 4099a747e4fSDavid du Colombier panic("segmentwrite"); 4109a747e4fSDavid du Colombier } 4119a747e4fSDavid du Colombier return 0; /* not reached */ 4129a747e4fSDavid du Colombier } 4139a747e4fSDavid du Colombier 4149a747e4fSDavid du Colombier static int 4159a747e4fSDavid du Colombier segmentwstat(Chan *c, uchar *dp, int n) 4169a747e4fSDavid du Colombier { 4179a747e4fSDavid du Colombier Globalseg *g; 4189a747e4fSDavid du Colombier Dir *d; 4199a747e4fSDavid du Colombier 4209a747e4fSDavid du Colombier if(c->qid.type == QTDIR) 4219a747e4fSDavid du Colombier error(Eperm); 4229a747e4fSDavid du Colombier 4239a747e4fSDavid du Colombier g = getgseg(c); 4249a747e4fSDavid du Colombier if(waserror()){ 4259a747e4fSDavid du Colombier putgseg(g); 4269a747e4fSDavid du Colombier nexterror(); 4279a747e4fSDavid du Colombier } 4289a747e4fSDavid du Colombier 4299a747e4fSDavid du Colombier if(strcmp(g->uid, up->user) && !iseve()) 4309a747e4fSDavid du Colombier error(Eperm); 4319a747e4fSDavid du Colombier d = smalloc(sizeof(Dir)+n); 4329a747e4fSDavid du Colombier n = convM2D(dp, n, &d[0], (char*)&d[1]); 4339a747e4fSDavid du Colombier g->perm = d->mode & 0777; 4349a747e4fSDavid du Colombier 4359a747e4fSDavid du Colombier putgseg(g); 4369a747e4fSDavid du Colombier poperror(); 4379a747e4fSDavid du Colombier 4389a747e4fSDavid du Colombier free(d); 4399a747e4fSDavid du Colombier return n; 4409a747e4fSDavid du Colombier } 4419a747e4fSDavid du Colombier 4429a747e4fSDavid du Colombier static void 4439a747e4fSDavid du Colombier segmentremove(Chan *c) 4449a747e4fSDavid du Colombier { 4459a747e4fSDavid du Colombier Globalseg *g; 4469a747e4fSDavid du Colombier int x; 4479a747e4fSDavid du Colombier 4489a747e4fSDavid du Colombier if(TYPE(c) != Qsegdir) 4499a747e4fSDavid du Colombier error(Eperm); 4509a747e4fSDavid du Colombier lock(&globalseglock); 4519a747e4fSDavid du Colombier x = SEG(c); 4529a747e4fSDavid du Colombier g = globalseg[x]; 4539a747e4fSDavid du Colombier globalseg[x] = nil; 4549a747e4fSDavid du Colombier unlock(&globalseglock); 4559a747e4fSDavid du Colombier if(g != nil) 4569a747e4fSDavid du Colombier putgseg(g); 4579a747e4fSDavid du Colombier } 4589a747e4fSDavid du Colombier 4599a747e4fSDavid du Colombier /* 4609a747e4fSDavid du Colombier * called by segattach() 4619a747e4fSDavid du Colombier */ 4629a747e4fSDavid du Colombier static Segment* 4639a747e4fSDavid du Colombier globalsegattach(Proc *p, char *name) 4649a747e4fSDavid du Colombier { 4659a747e4fSDavid du Colombier int x; 4669a747e4fSDavid du Colombier Globalseg *g; 4679a747e4fSDavid du Colombier Segment *s; 4689a747e4fSDavid du Colombier 4699a747e4fSDavid du Colombier g = nil; 4709a747e4fSDavid du Colombier if(waserror()){ 4719a747e4fSDavid du Colombier unlock(&globalseglock); 4729a747e4fSDavid du Colombier nexterror(); 4739a747e4fSDavid du Colombier } 4749a747e4fSDavid du Colombier lock(&globalseglock); 4759a747e4fSDavid du Colombier for(x = 0; x < nelem(globalseg); x++){ 4769a747e4fSDavid du Colombier g = globalseg[x]; 4779a747e4fSDavid du Colombier if(g != nil && strcmp(g->name, name) == 0) 4789a747e4fSDavid du Colombier break; 4799a747e4fSDavid du Colombier } 4809a747e4fSDavid du Colombier if(x == nelem(globalseg)){ 4819a747e4fSDavid du Colombier unlock(&globalseglock); 4829a747e4fSDavid du Colombier poperror(); 4839a747e4fSDavid du Colombier return nil; 4849a747e4fSDavid du Colombier } 4859a747e4fSDavid du Colombier devpermcheck(g->uid, g->perm, ORDWR); 4869a747e4fSDavid du Colombier s = g->s; 4879a747e4fSDavid du Colombier if(s == nil) 4889a747e4fSDavid du Colombier error("global segment not assigned a virtual address"); 489*4de34a7eSDavid du Colombier if(isoverlap(p, s->base, s->top - s->base) != nil) 4909a747e4fSDavid du Colombier error("overlaps existing segment"); 4919a747e4fSDavid du Colombier incref(s); 4929a747e4fSDavid du Colombier unlock(&globalseglock); 4939a747e4fSDavid du Colombier poperror(); 4949a747e4fSDavid du Colombier return s; 4959a747e4fSDavid du Colombier } 4969a747e4fSDavid du Colombier 4979a747e4fSDavid du Colombier static void 4989a747e4fSDavid du Colombier docmd(Globalseg *g, int cmd) 4999a747e4fSDavid du Colombier { 5009a747e4fSDavid du Colombier g->err[0] = 0; 5019a747e4fSDavid du Colombier g->cmd = cmd; 5029a747e4fSDavid du Colombier wakeup(&g->cmdwait); 5039a747e4fSDavid du Colombier sleep(&g->replywait, cmddone, g); 5049a747e4fSDavid du Colombier if(g->err[0]) 5059a747e4fSDavid du Colombier error(g->err); 5069a747e4fSDavid du Colombier } 5079a747e4fSDavid du Colombier 5089a747e4fSDavid du Colombier static int 5099a747e4fSDavid du Colombier cmdready(void *arg) 5109a747e4fSDavid du Colombier { 5119a747e4fSDavid du Colombier Globalseg *g = arg; 5129a747e4fSDavid du Colombier 5139a747e4fSDavid du Colombier return g->cmd != Cnone; 5149a747e4fSDavid du Colombier } 5159a747e4fSDavid du Colombier 5169a747e4fSDavid du Colombier static void 5179a747e4fSDavid du Colombier segmentkproc(void *arg) 5189a747e4fSDavid du Colombier { 5199a747e4fSDavid du Colombier Globalseg *g = arg; 5209a747e4fSDavid du Colombier int done; 5219a747e4fSDavid du Colombier int sno; 5229a747e4fSDavid du Colombier 5239a747e4fSDavid du Colombier for(sno = 0; sno < NSEG; sno++) 5249a747e4fSDavid du Colombier if(up->seg[sno] == nil && sno != ESEG) 5259a747e4fSDavid du Colombier break; 5269a747e4fSDavid du Colombier if(sno == NSEG) 5279a747e4fSDavid du Colombier panic("segmentkproc"); 5289a747e4fSDavid du Colombier g->kproc = up; 5299a747e4fSDavid du Colombier 5309a747e4fSDavid du Colombier incref(g->s); 5319a747e4fSDavid du Colombier up->seg[sno] = g->s; 5329a747e4fSDavid du Colombier 5339a747e4fSDavid du Colombier for(done = 0; !done;){ 5349a747e4fSDavid du Colombier sleep(&g->cmdwait, cmdready, g); 5359a747e4fSDavid du Colombier if(waserror()){ 5369a747e4fSDavid du Colombier strncpy(g->err, up->errstr, sizeof(g->err)); 5379a747e4fSDavid du Colombier } else { 5389a747e4fSDavid du Colombier switch(g->cmd){ 5399a747e4fSDavid du Colombier case Cstart: 5409a747e4fSDavid du Colombier break; 5419a747e4fSDavid du Colombier case Cdie: 5429a747e4fSDavid du Colombier done = 1; 5439a747e4fSDavid du Colombier break; 5449a747e4fSDavid du Colombier case Cread: 5459a747e4fSDavid du Colombier memmove(g->data, (char*)g->off, g->dlen); 5469a747e4fSDavid du Colombier break; 5479a747e4fSDavid du Colombier case Cwrite: 5489a747e4fSDavid du Colombier memmove((char*)g->off, g->data, g->dlen); 5499a747e4fSDavid du Colombier break; 5509a747e4fSDavid du Colombier } 5519a747e4fSDavid du Colombier poperror(); 5529a747e4fSDavid du Colombier } 5539a747e4fSDavid du Colombier g->cmd = Cnone; 5549a747e4fSDavid du Colombier wakeup(&g->replywait); 5559a747e4fSDavid du Colombier } 5569a747e4fSDavid du Colombier } 5579a747e4fSDavid du Colombier 5589a747e4fSDavid du Colombier Dev segmentdevtab = { 5599a747e4fSDavid du Colombier 'g', 5609a747e4fSDavid du Colombier "segment", 5619a747e4fSDavid du Colombier 5629a747e4fSDavid du Colombier devreset, 5639a747e4fSDavid du Colombier segmentinit, 5649a747e4fSDavid du Colombier devshutdown, 5659a747e4fSDavid du Colombier segmentattach, 5669a747e4fSDavid du Colombier segmentwalk, 5679a747e4fSDavid du Colombier segmentstat, 5689a747e4fSDavid du Colombier segmentopen, 5699a747e4fSDavid du Colombier segmentcreate, 5709a747e4fSDavid du Colombier segmentclose, 5719a747e4fSDavid du Colombier segmentread, 5729a747e4fSDavid du Colombier devbread, 5739a747e4fSDavid du Colombier segmentwrite, 5749a747e4fSDavid du Colombier devbwrite, 5759a747e4fSDavid du Colombier segmentremove, 5769a747e4fSDavid du Colombier segmentwstat, 5779a747e4fSDavid du Colombier }; 5789a747e4fSDavid du Colombier 579