1*9a747e4fSDavid du Colombier #include "u.h" 2*9a747e4fSDavid du Colombier #include "../port/lib.h" 3*9a747e4fSDavid du Colombier #include "mem.h" 4*9a747e4fSDavid du Colombier #include "dat.h" 5*9a747e4fSDavid du Colombier #include "fns.h" 6*9a747e4fSDavid du Colombier #include "../port/error.h" 7*9a747e4fSDavid du Colombier 8*9a747e4fSDavid du Colombier enum 9*9a747e4fSDavid du Colombier { 10*9a747e4fSDavid du Colombier Qtopdir, 11*9a747e4fSDavid du Colombier Qsegdir, 12*9a747e4fSDavid du Colombier Qctl, 13*9a747e4fSDavid du Colombier Qdata, 14*9a747e4fSDavid du Colombier 15*9a747e4fSDavid du Colombier /* commands to kproc */ 16*9a747e4fSDavid du Colombier Cnone=0, 17*9a747e4fSDavid du Colombier Cread, 18*9a747e4fSDavid du Colombier Cwrite, 19*9a747e4fSDavid du Colombier Cstart, 20*9a747e4fSDavid du Colombier Cdie, 21*9a747e4fSDavid du Colombier }; 22*9a747e4fSDavid du Colombier 23*9a747e4fSDavid du Colombier #define TYPE(x) (int)( (c)->qid.path & 0x7 ) 24*9a747e4fSDavid du Colombier #define SEG(x) ( ((c)->qid.path >> 3) & 0x3f ) 25*9a747e4fSDavid du Colombier #define PATH(s, t) ( ((s)<<3) | (t) ) 26*9a747e4fSDavid du Colombier 27*9a747e4fSDavid du Colombier typedef struct Globalseg Globalseg; 28*9a747e4fSDavid du Colombier struct Globalseg 29*9a747e4fSDavid du Colombier { 30*9a747e4fSDavid du Colombier Ref; 31*9a747e4fSDavid du Colombier Segment *s; 32*9a747e4fSDavid du Colombier 33*9a747e4fSDavid du Colombier char *name; 34*9a747e4fSDavid du Colombier char *uid; 35*9a747e4fSDavid du Colombier vlong length; 36*9a747e4fSDavid du Colombier long perm; 37*9a747e4fSDavid du Colombier 38*9a747e4fSDavid du Colombier /* kproc to do reading and writing */ 39*9a747e4fSDavid du Colombier QLock l; /* sync kproc access */ 40*9a747e4fSDavid du Colombier Rendez cmdwait; /* where kproc waits */ 41*9a747e4fSDavid du Colombier Rendez replywait; /* where requestor waits */ 42*9a747e4fSDavid du Colombier Proc *kproc; 43*9a747e4fSDavid du Colombier char *data; 44*9a747e4fSDavid du Colombier long off; 45*9a747e4fSDavid du Colombier int dlen; 46*9a747e4fSDavid du Colombier int cmd; 47*9a747e4fSDavid du Colombier char err[64]; 48*9a747e4fSDavid du Colombier }; 49*9a747e4fSDavid du Colombier 50*9a747e4fSDavid du Colombier static Globalseg *globalseg[100]; 51*9a747e4fSDavid du Colombier static Lock globalseglock; 52*9a747e4fSDavid du Colombier 53*9a747e4fSDavid du Colombier 54*9a747e4fSDavid du Colombier Segment* (*_globalsegattach)(Proc*, char*); 55*9a747e4fSDavid du Colombier static Segment* globalsegattach(Proc *p, char *name); 56*9a747e4fSDavid du Colombier static int cmddone(void*); 57*9a747e4fSDavid du Colombier static void segmentkproc(void*); 58*9a747e4fSDavid du Colombier static void docmd(Globalseg *g, int cmd); 59*9a747e4fSDavid du Colombier 60*9a747e4fSDavid du Colombier /* 61*9a747e4fSDavid du Colombier * returns with globalseg incref'd 62*9a747e4fSDavid du Colombier */ 63*9a747e4fSDavid du Colombier static Globalseg* 64*9a747e4fSDavid du Colombier getgseg(Chan *c) 65*9a747e4fSDavid du Colombier { 66*9a747e4fSDavid du Colombier int x; 67*9a747e4fSDavid du Colombier Globalseg *g; 68*9a747e4fSDavid du Colombier 69*9a747e4fSDavid du Colombier x = SEG(c); 70*9a747e4fSDavid du Colombier lock(&globalseglock); 71*9a747e4fSDavid du Colombier if(x >= nelem(globalseg)) 72*9a747e4fSDavid du Colombier panic("getgseg"); 73*9a747e4fSDavid du Colombier g = globalseg[x]; 74*9a747e4fSDavid du Colombier if(g != nil) 75*9a747e4fSDavid du Colombier incref(g); 76*9a747e4fSDavid du Colombier unlock(&globalseglock); 77*9a747e4fSDavid du Colombier if(g == nil) 78*9a747e4fSDavid du Colombier error("global segment disappeared"); 79*9a747e4fSDavid du Colombier return g; 80*9a747e4fSDavid du Colombier } 81*9a747e4fSDavid du Colombier 82*9a747e4fSDavid du Colombier static void 83*9a747e4fSDavid du Colombier putgseg(Globalseg *g) 84*9a747e4fSDavid du Colombier { 85*9a747e4fSDavid du Colombier if(decref(g) > 0) 86*9a747e4fSDavid du Colombier return; 87*9a747e4fSDavid du Colombier if(g->s != nil) 88*9a747e4fSDavid du Colombier putseg(g->s); 89*9a747e4fSDavid du Colombier if(g->kproc) 90*9a747e4fSDavid du Colombier docmd(g, Cdie); 91*9a747e4fSDavid du Colombier free(g->name); 92*9a747e4fSDavid du Colombier free(g->uid); 93*9a747e4fSDavid du Colombier free(g); 94*9a747e4fSDavid du Colombier } 95*9a747e4fSDavid du Colombier 96*9a747e4fSDavid du Colombier static int 97*9a747e4fSDavid du Colombier segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp) 98*9a747e4fSDavid du Colombier { 99*9a747e4fSDavid du Colombier Qid q; 100*9a747e4fSDavid du Colombier Globalseg *g; 101*9a747e4fSDavid du Colombier ulong size; 102*9a747e4fSDavid du Colombier 103*9a747e4fSDavid du Colombier switch(TYPE(c)) { 104*9a747e4fSDavid du Colombier case Qtopdir: 105*9a747e4fSDavid du Colombier if(s == DEVDOTDOT){ 106*9a747e4fSDavid du Colombier q.vers = 0; 107*9a747e4fSDavid du Colombier q.path = PATH(0, Qtopdir); 108*9a747e4fSDavid du Colombier q.type = QTDIR; 109*9a747e4fSDavid du Colombier devdir(c, q, "#g", 0, eve, DMDIR|0777, dp); 110*9a747e4fSDavid du Colombier break; 111*9a747e4fSDavid du Colombier } 112*9a747e4fSDavid du Colombier 113*9a747e4fSDavid du Colombier if(s >= nelem(globalseg)) 114*9a747e4fSDavid du Colombier return -1; 115*9a747e4fSDavid du Colombier 116*9a747e4fSDavid du Colombier lock(&globalseglock); 117*9a747e4fSDavid du Colombier g = globalseg[s]; 118*9a747e4fSDavid du Colombier if(g == nil){ 119*9a747e4fSDavid du Colombier unlock(&globalseglock); 120*9a747e4fSDavid du Colombier return 0; 121*9a747e4fSDavid du Colombier } 122*9a747e4fSDavid du Colombier q.vers = 0; 123*9a747e4fSDavid du Colombier q.path = PATH(s, Qsegdir); 124*9a747e4fSDavid du Colombier q.type = QTDIR; 125*9a747e4fSDavid du Colombier devdir(c, q, g->name, 0, g->uid, DMDIR|0777, dp); 126*9a747e4fSDavid du Colombier unlock(&globalseglock); 127*9a747e4fSDavid du Colombier 128*9a747e4fSDavid du Colombier break; 129*9a747e4fSDavid du Colombier case Qsegdir: 130*9a747e4fSDavid du Colombier if(s == DEVDOTDOT){ 131*9a747e4fSDavid du Colombier q.vers = 0; 132*9a747e4fSDavid du Colombier q.path = PATH(0, Qtopdir); 133*9a747e4fSDavid du Colombier q.type = QTDIR; 134*9a747e4fSDavid du Colombier devdir(c, q, "#g", 0, eve, DMDIR|0777, dp); 135*9a747e4fSDavid du Colombier break; 136*9a747e4fSDavid du Colombier } 137*9a747e4fSDavid du Colombier /* fall through */ 138*9a747e4fSDavid du Colombier case Qctl: 139*9a747e4fSDavid du Colombier case Qdata: 140*9a747e4fSDavid du Colombier switch(s){ 141*9a747e4fSDavid du Colombier case 0: 142*9a747e4fSDavid du Colombier g = getgseg(c); 143*9a747e4fSDavid du Colombier q.vers = 0; 144*9a747e4fSDavid du Colombier q.path = PATH(SEG(c), Qctl); 145*9a747e4fSDavid du Colombier q.type = QTFILE; 146*9a747e4fSDavid du Colombier devdir(c, q, "ctl", 0, g->uid, g->perm, dp); 147*9a747e4fSDavid du Colombier putgseg(g); 148*9a747e4fSDavid du Colombier break; 149*9a747e4fSDavid du Colombier case 1: 150*9a747e4fSDavid du Colombier g = getgseg(c); 151*9a747e4fSDavid du Colombier q.vers = 0; 152*9a747e4fSDavid du Colombier q.path = PATH(SEG(c), Qdata); 153*9a747e4fSDavid du Colombier q.type = QTFILE; 154*9a747e4fSDavid du Colombier if(g->s != nil) 155*9a747e4fSDavid du Colombier size = g->s->top - g->s->base; 156*9a747e4fSDavid du Colombier else 157*9a747e4fSDavid du Colombier size = 0; 158*9a747e4fSDavid du Colombier devdir(c, q, "data", size, g->uid, g->perm, dp); 159*9a747e4fSDavid du Colombier putgseg(g); 160*9a747e4fSDavid du Colombier break; 161*9a747e4fSDavid du Colombier default: 162*9a747e4fSDavid du Colombier return -1; 163*9a747e4fSDavid du Colombier } 164*9a747e4fSDavid du Colombier break; 165*9a747e4fSDavid du Colombier } 166*9a747e4fSDavid du Colombier return 1; 167*9a747e4fSDavid du Colombier } 168*9a747e4fSDavid du Colombier 169*9a747e4fSDavid du Colombier static void 170*9a747e4fSDavid du Colombier segmentinit(void) 171*9a747e4fSDavid du Colombier { 172*9a747e4fSDavid du Colombier _globalsegattach = globalsegattach; 173*9a747e4fSDavid du Colombier } 174*9a747e4fSDavid du Colombier 175*9a747e4fSDavid du Colombier static Chan* 176*9a747e4fSDavid du Colombier segmentattach(char *spec) 177*9a747e4fSDavid du Colombier { 178*9a747e4fSDavid du Colombier return devattach('g', spec); 179*9a747e4fSDavid du Colombier } 180*9a747e4fSDavid du Colombier 181*9a747e4fSDavid du Colombier static Walkqid* 182*9a747e4fSDavid du Colombier segmentwalk(Chan *c, Chan *nc, char **name, int nname) 183*9a747e4fSDavid du Colombier { 184*9a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, segmentgen); 185*9a747e4fSDavid du Colombier } 186*9a747e4fSDavid du Colombier 187*9a747e4fSDavid du Colombier static int 188*9a747e4fSDavid du Colombier segmentstat(Chan *c, uchar *db, int n) 189*9a747e4fSDavid du Colombier { 190*9a747e4fSDavid du Colombier return devstat(c, db, n, 0, 0, segmentgen); 191*9a747e4fSDavid du Colombier } 192*9a747e4fSDavid du Colombier 193*9a747e4fSDavid du Colombier static int 194*9a747e4fSDavid du Colombier cmddone(void *arg) 195*9a747e4fSDavid du Colombier { 196*9a747e4fSDavid du Colombier Globalseg *g = arg; 197*9a747e4fSDavid du Colombier 198*9a747e4fSDavid du Colombier return g->cmd == Cnone; 199*9a747e4fSDavid du Colombier } 200*9a747e4fSDavid du Colombier 201*9a747e4fSDavid du Colombier static Chan* 202*9a747e4fSDavid du Colombier segmentopen(Chan *c, int omode) 203*9a747e4fSDavid du Colombier { 204*9a747e4fSDavid du Colombier Globalseg *g; 205*9a747e4fSDavid du Colombier 206*9a747e4fSDavid du Colombier switch(TYPE(c)){ 207*9a747e4fSDavid du Colombier case Qtopdir: 208*9a747e4fSDavid du Colombier case Qsegdir: 209*9a747e4fSDavid du Colombier if(omode != 0) 210*9a747e4fSDavid du Colombier error(Eisdir); 211*9a747e4fSDavid du Colombier break; 212*9a747e4fSDavid du Colombier case Qctl: 213*9a747e4fSDavid du Colombier g = getgseg(c); 214*9a747e4fSDavid du Colombier if(waserror()){ 215*9a747e4fSDavid du Colombier putgseg(g); 216*9a747e4fSDavid du Colombier nexterror(); 217*9a747e4fSDavid du Colombier } 218*9a747e4fSDavid du Colombier devpermcheck(g->uid, g->perm, omode); 219*9a747e4fSDavid du Colombier c->aux = g; 220*9a747e4fSDavid du Colombier poperror(); 221*9a747e4fSDavid du Colombier c->flag |= COPEN; 222*9a747e4fSDavid du Colombier break; 223*9a747e4fSDavid du Colombier case Qdata: 224*9a747e4fSDavid du Colombier g = getgseg(c); 225*9a747e4fSDavid du Colombier if(waserror()){ 226*9a747e4fSDavid du Colombier putgseg(g); 227*9a747e4fSDavid du Colombier nexterror(); 228*9a747e4fSDavid du Colombier } 229*9a747e4fSDavid du Colombier devpermcheck(g->uid, g->perm, omode); 230*9a747e4fSDavid du Colombier if(g->s == nil) 231*9a747e4fSDavid du Colombier error("segment not yet allocated"); 232*9a747e4fSDavid du Colombier if(g->kproc == nil){ 233*9a747e4fSDavid du Colombier qlock(&g->l); 234*9a747e4fSDavid du Colombier if(waserror()){ 235*9a747e4fSDavid du Colombier qunlock(&g->l); 236*9a747e4fSDavid du Colombier nexterror(); 237*9a747e4fSDavid du Colombier } 238*9a747e4fSDavid du Colombier if(g->kproc == nil){ 239*9a747e4fSDavid du Colombier g->cmd = Cnone; 240*9a747e4fSDavid du Colombier kproc(g->name, segmentkproc, g); 241*9a747e4fSDavid du Colombier docmd(g, Cstart); 242*9a747e4fSDavid du Colombier } 243*9a747e4fSDavid du Colombier qunlock(&g->l); 244*9a747e4fSDavid du Colombier poperror(); 245*9a747e4fSDavid du Colombier } 246*9a747e4fSDavid du Colombier c->aux = g; 247*9a747e4fSDavid du Colombier poperror(); 248*9a747e4fSDavid du Colombier c->flag |= COPEN; 249*9a747e4fSDavid du Colombier break; 250*9a747e4fSDavid du Colombier default: 251*9a747e4fSDavid du Colombier panic("segmentopen"); 252*9a747e4fSDavid du Colombier } 253*9a747e4fSDavid du Colombier c->mode = openmode(omode); 254*9a747e4fSDavid du Colombier c->offset = 0; 255*9a747e4fSDavid du Colombier return c; 256*9a747e4fSDavid du Colombier } 257*9a747e4fSDavid du Colombier 258*9a747e4fSDavid du Colombier static void 259*9a747e4fSDavid du Colombier segmentclose(Chan *c) 260*9a747e4fSDavid du Colombier { 261*9a747e4fSDavid du Colombier if(TYPE(c) == Qtopdir) 262*9a747e4fSDavid du Colombier return; 263*9a747e4fSDavid du Colombier if(c->flag & COPEN) 264*9a747e4fSDavid du Colombier putgseg(c->aux); 265*9a747e4fSDavid du Colombier } 266*9a747e4fSDavid du Colombier 267*9a747e4fSDavid du Colombier static void 268*9a747e4fSDavid du Colombier segmentcreate(Chan *c, char *name, int omode, ulong perm) 269*9a747e4fSDavid du Colombier { 270*9a747e4fSDavid du Colombier int x, xfree; 271*9a747e4fSDavid du Colombier Globalseg *g; 272*9a747e4fSDavid du Colombier 273*9a747e4fSDavid du Colombier if(TYPE(c) != Qtopdir) 274*9a747e4fSDavid du Colombier error(Eperm); 275*9a747e4fSDavid du Colombier 276*9a747e4fSDavid du Colombier if(isphysseg(name)) 277*9a747e4fSDavid du Colombier error(Eexist); 278*9a747e4fSDavid du Colombier 279*9a747e4fSDavid du Colombier if((perm & DMDIR) == 0) 280*9a747e4fSDavid du Colombier error(Ebadarg); 281*9a747e4fSDavid du Colombier 282*9a747e4fSDavid du Colombier if(waserror()){ 283*9a747e4fSDavid du Colombier unlock(&globalseglock); 284*9a747e4fSDavid du Colombier nexterror(); 285*9a747e4fSDavid du Colombier } 286*9a747e4fSDavid du Colombier lock(&globalseglock); 287*9a747e4fSDavid du Colombier xfree = -1; 288*9a747e4fSDavid du Colombier for(x = 0; x < nelem(globalseg); x++){ 289*9a747e4fSDavid du Colombier g = globalseg[x]; 290*9a747e4fSDavid du Colombier if(g == nil){ 291*9a747e4fSDavid du Colombier if(xfree < 0) 292*9a747e4fSDavid du Colombier xfree = x; 293*9a747e4fSDavid du Colombier } else { 294*9a747e4fSDavid du Colombier if(strcmp(g->name, name) == 0) 295*9a747e4fSDavid du Colombier error(Eexist); 296*9a747e4fSDavid du Colombier } 297*9a747e4fSDavid du Colombier } 298*9a747e4fSDavid du Colombier if(xfree < 0) 299*9a747e4fSDavid du Colombier error("too many global segments"); 300*9a747e4fSDavid du Colombier g = smalloc(sizeof(Globalseg)); 301*9a747e4fSDavid du Colombier g->ref = 1; 302*9a747e4fSDavid du Colombier kstrdup(&g->name, name); 303*9a747e4fSDavid du Colombier kstrdup(&g->uid, up->user); 304*9a747e4fSDavid du Colombier g->perm = 0660; 305*9a747e4fSDavid du Colombier globalseg[xfree] = g; 306*9a747e4fSDavid du Colombier unlock(&globalseglock); 307*9a747e4fSDavid du Colombier poperror(); 308*9a747e4fSDavid du Colombier 309*9a747e4fSDavid du Colombier c->qid.path = PATH(x, Qsegdir); 310*9a747e4fSDavid du Colombier c->qid.type = QTDIR; 311*9a747e4fSDavid du Colombier c->qid.vers = 0; 312*9a747e4fSDavid du Colombier c->mode = openmode(omode); 313*9a747e4fSDavid du Colombier c->mode = OWRITE; 314*9a747e4fSDavid du Colombier } 315*9a747e4fSDavid du Colombier 316*9a747e4fSDavid du Colombier static long 317*9a747e4fSDavid du Colombier segmentread(Chan *c, void *a, long n, vlong voff) 318*9a747e4fSDavid du Colombier { 319*9a747e4fSDavid du Colombier Globalseg *g; 320*9a747e4fSDavid du Colombier char buf[32]; 321*9a747e4fSDavid du Colombier 322*9a747e4fSDavid du Colombier if(c->qid.type == QTDIR) 323*9a747e4fSDavid du Colombier return devdirread(c, a, n, (Dirtab *)0, 0L, segmentgen); 324*9a747e4fSDavid du Colombier 325*9a747e4fSDavid du Colombier switch(TYPE(c)){ 326*9a747e4fSDavid du Colombier case Qctl: 327*9a747e4fSDavid du Colombier g = c->aux; 328*9a747e4fSDavid du Colombier if(g->s == nil) 329*9a747e4fSDavid du Colombier error("segment not yet allocated"); 330*9a747e4fSDavid du Colombier sprint(buf, "va 0x%lux 0x%lux\n", g->s->base, g->s->top-g->s->base); 331*9a747e4fSDavid du Colombier return readstr(voff, a, n, buf); 332*9a747e4fSDavid du Colombier case Qdata: 333*9a747e4fSDavid du Colombier g = c->aux; 334*9a747e4fSDavid du Colombier if(voff > g->s->top - g->s->base) 335*9a747e4fSDavid du Colombier error(Ebadarg); 336*9a747e4fSDavid du Colombier if(voff + n > g->s->top - g->s->base) 337*9a747e4fSDavid du Colombier n = g->s->top - g->s->base - voff; 338*9a747e4fSDavid du Colombier qlock(&g->l); 339*9a747e4fSDavid du Colombier g->off = voff + g->s->base; 340*9a747e4fSDavid du Colombier g->data = smalloc(n); 341*9a747e4fSDavid du Colombier if(waserror()){ 342*9a747e4fSDavid du Colombier free(g->data); 343*9a747e4fSDavid du Colombier qunlock(&g->l); 344*9a747e4fSDavid du Colombier nexterror(); 345*9a747e4fSDavid du Colombier } 346*9a747e4fSDavid du Colombier g->dlen = n; 347*9a747e4fSDavid du Colombier docmd(g, Cread); 348*9a747e4fSDavid du Colombier memmove(a, g->data, g->dlen); 349*9a747e4fSDavid du Colombier free(g->data); 350*9a747e4fSDavid du Colombier qunlock(&g->l); 351*9a747e4fSDavid du Colombier poperror(); 352*9a747e4fSDavid du Colombier return g->dlen; 353*9a747e4fSDavid du Colombier default: 354*9a747e4fSDavid du Colombier panic("segmentread"); 355*9a747e4fSDavid du Colombier } 356*9a747e4fSDavid du Colombier return 0; /* not reached */ 357*9a747e4fSDavid du Colombier } 358*9a747e4fSDavid du Colombier 359*9a747e4fSDavid du Colombier static long 360*9a747e4fSDavid du Colombier segmentwrite(Chan *c, void *a, long n, vlong voff) 361*9a747e4fSDavid du Colombier { 362*9a747e4fSDavid du Colombier Cmdbuf *cb; 363*9a747e4fSDavid du Colombier Globalseg *g; 364*9a747e4fSDavid du Colombier ulong va, len, top; 365*9a747e4fSDavid du Colombier 366*9a747e4fSDavid du Colombier if(c->qid.type == QTDIR) 367*9a747e4fSDavid du Colombier error(Eperm); 368*9a747e4fSDavid du Colombier 369*9a747e4fSDavid du Colombier switch(TYPE(c)){ 370*9a747e4fSDavid du Colombier case Qctl: 371*9a747e4fSDavid du Colombier g = c->aux; 372*9a747e4fSDavid du Colombier cb = parsecmd(a, n); 373*9a747e4fSDavid du Colombier if(strcmp(cb->f[0], "va") == 0){ 374*9a747e4fSDavid du Colombier if(g->s != nil) 375*9a747e4fSDavid du Colombier error("already has a virtual address"); 376*9a747e4fSDavid du Colombier if(cb->nf < 3) 377*9a747e4fSDavid du Colombier error(Ebadarg); 378*9a747e4fSDavid du Colombier va = strtoul(cb->f[1], 0, 0); 379*9a747e4fSDavid du Colombier len = strtoul(cb->f[2], 0, 0); 380*9a747e4fSDavid du Colombier top = PGROUND(va + len); 381*9a747e4fSDavid du Colombier va = va&~(BY2PG-1); 382*9a747e4fSDavid du Colombier len = (top - va) / BY2PG; 383*9a747e4fSDavid du Colombier if(len == 0) 384*9a747e4fSDavid du Colombier error(Ebadarg); 385*9a747e4fSDavid du Colombier g->s = newseg(SG_SHARED, va, len); 386*9a747e4fSDavid du Colombier } else 387*9a747e4fSDavid du Colombier error(Ebadctl); 388*9a747e4fSDavid du Colombier break; 389*9a747e4fSDavid du Colombier case Qdata: 390*9a747e4fSDavid du Colombier g = c->aux; 391*9a747e4fSDavid du Colombier if(voff + n > g->s->top - g->s->base) 392*9a747e4fSDavid du Colombier error(Ebadarg); 393*9a747e4fSDavid du Colombier qlock(&g->l); 394*9a747e4fSDavid du Colombier g->off = voff + g->s->base; 395*9a747e4fSDavid du Colombier g->data = smalloc(n); 396*9a747e4fSDavid du Colombier if(waserror()){ 397*9a747e4fSDavid du Colombier free(g->data); 398*9a747e4fSDavid du Colombier qunlock(&g->l); 399*9a747e4fSDavid du Colombier nexterror(); 400*9a747e4fSDavid du Colombier } 401*9a747e4fSDavid du Colombier g->dlen = n; 402*9a747e4fSDavid du Colombier memmove(g->data, a, g->dlen); 403*9a747e4fSDavid du Colombier docmd(g, Cwrite); 404*9a747e4fSDavid du Colombier free(g->data); 405*9a747e4fSDavid du Colombier qunlock(&g->l); 406*9a747e4fSDavid du Colombier poperror(); 407*9a747e4fSDavid du Colombier return g->dlen; 408*9a747e4fSDavid du Colombier default: 409*9a747e4fSDavid du Colombier panic("segmentwrite"); 410*9a747e4fSDavid du Colombier } 411*9a747e4fSDavid du Colombier return 0; /* not reached */ 412*9a747e4fSDavid du Colombier } 413*9a747e4fSDavid du Colombier 414*9a747e4fSDavid du Colombier static int 415*9a747e4fSDavid du Colombier segmentwstat(Chan *c, uchar *dp, int n) 416*9a747e4fSDavid du Colombier { 417*9a747e4fSDavid du Colombier Globalseg *g; 418*9a747e4fSDavid du Colombier Dir *d; 419*9a747e4fSDavid du Colombier 420*9a747e4fSDavid du Colombier if(c->qid.type == QTDIR) 421*9a747e4fSDavid du Colombier error(Eperm); 422*9a747e4fSDavid du Colombier 423*9a747e4fSDavid du Colombier g = getgseg(c); 424*9a747e4fSDavid du Colombier if(waserror()){ 425*9a747e4fSDavid du Colombier putgseg(g); 426*9a747e4fSDavid du Colombier nexterror(); 427*9a747e4fSDavid du Colombier } 428*9a747e4fSDavid du Colombier 429*9a747e4fSDavid du Colombier if(strcmp(g->uid, up->user) && !iseve()) 430*9a747e4fSDavid du Colombier error(Eperm); 431*9a747e4fSDavid du Colombier d = smalloc(sizeof(Dir)+n); 432*9a747e4fSDavid du Colombier n = convM2D(dp, n, &d[0], (char*)&d[1]); 433*9a747e4fSDavid du Colombier g->perm = d->mode & 0777; 434*9a747e4fSDavid du Colombier 435*9a747e4fSDavid du Colombier putgseg(g); 436*9a747e4fSDavid du Colombier poperror(); 437*9a747e4fSDavid du Colombier 438*9a747e4fSDavid du Colombier free(d); 439*9a747e4fSDavid du Colombier return n; 440*9a747e4fSDavid du Colombier } 441*9a747e4fSDavid du Colombier 442*9a747e4fSDavid du Colombier static void 443*9a747e4fSDavid du Colombier segmentremove(Chan *c) 444*9a747e4fSDavid du Colombier { 445*9a747e4fSDavid du Colombier Globalseg *g; 446*9a747e4fSDavid du Colombier int x; 447*9a747e4fSDavid du Colombier 448*9a747e4fSDavid du Colombier if(TYPE(c) != Qsegdir) 449*9a747e4fSDavid du Colombier error(Eperm); 450*9a747e4fSDavid du Colombier lock(&globalseglock); 451*9a747e4fSDavid du Colombier x = SEG(c); 452*9a747e4fSDavid du Colombier g = globalseg[x]; 453*9a747e4fSDavid du Colombier globalseg[x] = nil; 454*9a747e4fSDavid du Colombier unlock(&globalseglock); 455*9a747e4fSDavid du Colombier if(g != nil) 456*9a747e4fSDavid du Colombier putgseg(g); 457*9a747e4fSDavid du Colombier } 458*9a747e4fSDavid du Colombier 459*9a747e4fSDavid du Colombier /* 460*9a747e4fSDavid du Colombier * called by segattach() 461*9a747e4fSDavid du Colombier */ 462*9a747e4fSDavid du Colombier static Segment* 463*9a747e4fSDavid du Colombier globalsegattach(Proc *p, char *name) 464*9a747e4fSDavid du Colombier { 465*9a747e4fSDavid du Colombier int x; 466*9a747e4fSDavid du Colombier Globalseg *g; 467*9a747e4fSDavid du Colombier Segment *s; 468*9a747e4fSDavid du Colombier 469*9a747e4fSDavid du Colombier g = nil; 470*9a747e4fSDavid du Colombier if(waserror()){ 471*9a747e4fSDavid du Colombier unlock(&globalseglock); 472*9a747e4fSDavid du Colombier nexterror(); 473*9a747e4fSDavid du Colombier } 474*9a747e4fSDavid du Colombier lock(&globalseglock); 475*9a747e4fSDavid du Colombier for(x = 0; x < nelem(globalseg); x++){ 476*9a747e4fSDavid du Colombier g = globalseg[x]; 477*9a747e4fSDavid du Colombier if(g != nil && strcmp(g->name, name) == 0) 478*9a747e4fSDavid du Colombier break; 479*9a747e4fSDavid du Colombier } 480*9a747e4fSDavid du Colombier if(x == nelem(globalseg)){ 481*9a747e4fSDavid du Colombier unlock(&globalseglock); 482*9a747e4fSDavid du Colombier poperror(); 483*9a747e4fSDavid du Colombier return nil; 484*9a747e4fSDavid du Colombier } 485*9a747e4fSDavid du Colombier devpermcheck(g->uid, g->perm, ORDWR); 486*9a747e4fSDavid du Colombier s = g->s; 487*9a747e4fSDavid du Colombier if(s == nil) 488*9a747e4fSDavid du Colombier error("global segment not assigned a virtual address"); 489*9a747e4fSDavid du Colombier if(isoverlap(p, s->base, s->top) != nil) 490*9a747e4fSDavid du Colombier error("overlaps existing segment"); 491*9a747e4fSDavid du Colombier incref(s); 492*9a747e4fSDavid du Colombier unlock(&globalseglock); 493*9a747e4fSDavid du Colombier poperror(); 494*9a747e4fSDavid du Colombier return s; 495*9a747e4fSDavid du Colombier } 496*9a747e4fSDavid du Colombier 497*9a747e4fSDavid du Colombier static void 498*9a747e4fSDavid du Colombier docmd(Globalseg *g, int cmd) 499*9a747e4fSDavid du Colombier { 500*9a747e4fSDavid du Colombier g->err[0] = 0; 501*9a747e4fSDavid du Colombier g->cmd = cmd; 502*9a747e4fSDavid du Colombier wakeup(&g->cmdwait); 503*9a747e4fSDavid du Colombier sleep(&g->replywait, cmddone, g); 504*9a747e4fSDavid du Colombier if(g->err[0]) 505*9a747e4fSDavid du Colombier error(g->err); 506*9a747e4fSDavid du Colombier } 507*9a747e4fSDavid du Colombier 508*9a747e4fSDavid du Colombier static int 509*9a747e4fSDavid du Colombier cmdready(void *arg) 510*9a747e4fSDavid du Colombier { 511*9a747e4fSDavid du Colombier Globalseg *g = arg; 512*9a747e4fSDavid du Colombier 513*9a747e4fSDavid du Colombier return g->cmd != Cnone; 514*9a747e4fSDavid du Colombier } 515*9a747e4fSDavid du Colombier 516*9a747e4fSDavid du Colombier static void 517*9a747e4fSDavid du Colombier segmentkproc(void *arg) 518*9a747e4fSDavid du Colombier { 519*9a747e4fSDavid du Colombier Globalseg *g = arg; 520*9a747e4fSDavid du Colombier int done; 521*9a747e4fSDavid du Colombier int sno; 522*9a747e4fSDavid du Colombier 523*9a747e4fSDavid du Colombier for(sno = 0; sno < NSEG; sno++) 524*9a747e4fSDavid du Colombier if(up->seg[sno] == nil && sno != ESEG) 525*9a747e4fSDavid du Colombier break; 526*9a747e4fSDavid du Colombier if(sno == NSEG) 527*9a747e4fSDavid du Colombier panic("segmentkproc"); 528*9a747e4fSDavid du Colombier g->kproc = up; 529*9a747e4fSDavid du Colombier 530*9a747e4fSDavid du Colombier incref(g->s); 531*9a747e4fSDavid du Colombier up->seg[sno] = g->s; 532*9a747e4fSDavid du Colombier 533*9a747e4fSDavid du Colombier for(done = 0; !done;){ 534*9a747e4fSDavid du Colombier sleep(&g->cmdwait, cmdready, g); 535*9a747e4fSDavid du Colombier if(waserror()){ 536*9a747e4fSDavid du Colombier strncpy(g->err, up->errstr, sizeof(g->err)); 537*9a747e4fSDavid du Colombier } else { 538*9a747e4fSDavid du Colombier switch(g->cmd){ 539*9a747e4fSDavid du Colombier case Cstart: 540*9a747e4fSDavid du Colombier break; 541*9a747e4fSDavid du Colombier case Cdie: 542*9a747e4fSDavid du Colombier done = 1; 543*9a747e4fSDavid du Colombier break; 544*9a747e4fSDavid du Colombier case Cread: 545*9a747e4fSDavid du Colombier memmove(g->data, (char*)g->off, g->dlen); 546*9a747e4fSDavid du Colombier break; 547*9a747e4fSDavid du Colombier case Cwrite: 548*9a747e4fSDavid du Colombier memmove((char*)g->off, g->data, g->dlen); 549*9a747e4fSDavid du Colombier break; 550*9a747e4fSDavid du Colombier } 551*9a747e4fSDavid du Colombier poperror(); 552*9a747e4fSDavid du Colombier } 553*9a747e4fSDavid du Colombier g->cmd = Cnone; 554*9a747e4fSDavid du Colombier wakeup(&g->replywait); 555*9a747e4fSDavid du Colombier } 556*9a747e4fSDavid du Colombier } 557*9a747e4fSDavid du Colombier 558*9a747e4fSDavid du Colombier Dev segmentdevtab = { 559*9a747e4fSDavid du Colombier 'g', 560*9a747e4fSDavid du Colombier "segment", 561*9a747e4fSDavid du Colombier 562*9a747e4fSDavid du Colombier devreset, 563*9a747e4fSDavid du Colombier segmentinit, 564*9a747e4fSDavid du Colombier devshutdown, 565*9a747e4fSDavid du Colombier segmentattach, 566*9a747e4fSDavid du Colombier segmentwalk, 567*9a747e4fSDavid du Colombier segmentstat, 568*9a747e4fSDavid du Colombier segmentopen, 569*9a747e4fSDavid du Colombier segmentcreate, 570*9a747e4fSDavid du Colombier segmentclose, 571*9a747e4fSDavid du Colombier segmentread, 572*9a747e4fSDavid du Colombier devbread, 573*9a747e4fSDavid du Colombier segmentwrite, 574*9a747e4fSDavid du Colombier devbwrite, 575*9a747e4fSDavid du Colombier segmentremove, 576*9a747e4fSDavid du Colombier segmentwstat, 577*9a747e4fSDavid du Colombier }; 578*9a747e4fSDavid du Colombier 579