101a344a2SDavid du Colombier #include "all.h"
201a344a2SDavid du Colombier #include "io.h"
301a344a2SDavid du Colombier
401a344a2SDavid du Colombier enum { DEBUG = 0 };
501a344a2SDavid du Colombier
601a344a2SDavid du Colombier extern long nhiob;
701a344a2SDavid du Colombier extern Hiob *hiob;
801a344a2SDavid du Colombier
901a344a2SDavid du Colombier Iobuf*
getbuf(Device * d,Off addr,int flag)1001a344a2SDavid du Colombier getbuf(Device *d, Off addr, int flag)
1101a344a2SDavid du Colombier {
1201a344a2SDavid du Colombier Iobuf *p, *s;
1301a344a2SDavid du Colombier Hiob *hp;
1401a344a2SDavid du Colombier Off h;
1501a344a2SDavid du Colombier
1601a344a2SDavid du Colombier if(DEBUG)
1701a344a2SDavid du Colombier print("getbuf %Z(%lld) f=%x\n", d, (Wideoff)addr, flag);
18*223a0358SDavid du Colombier h = addr + (Off)(uintptr)d*1009;
1901a344a2SDavid du Colombier if(h < 0)
2001a344a2SDavid du Colombier h = ~h;
2101a344a2SDavid du Colombier h %= nhiob;
2201a344a2SDavid du Colombier hp = &hiob[h];
2301a344a2SDavid du Colombier
2401a344a2SDavid du Colombier loop:
2501a344a2SDavid du Colombier lock(hp);
2601a344a2SDavid du Colombier
2701a344a2SDavid du Colombier /*
2801a344a2SDavid du Colombier * look for it in the active list
2901a344a2SDavid du Colombier */
3001a344a2SDavid du Colombier s = hp->link;
3101a344a2SDavid du Colombier for(p=s;;) {
3201a344a2SDavid du Colombier if(p->addr == addr && p->dev == d) {
3301a344a2SDavid du Colombier if(p != s) {
3401a344a2SDavid du Colombier p->back->fore = p->fore;
3501a344a2SDavid du Colombier p->fore->back = p->back;
3601a344a2SDavid du Colombier p->fore = s;
3701a344a2SDavid du Colombier p->back = s->back;
3801a344a2SDavid du Colombier s->back = p;
3901a344a2SDavid du Colombier p->back->fore = p;
4001a344a2SDavid du Colombier hp->link = p;
4101a344a2SDavid du Colombier }
4201a344a2SDavid du Colombier unlock(hp);
4301a344a2SDavid du Colombier qlock(p);
4401a344a2SDavid du Colombier if(p->addr != addr || p->dev != d || iobufmap(p) == 0) {
4501a344a2SDavid du Colombier qunlock(p);
4601a344a2SDavid du Colombier goto loop;
4701a344a2SDavid du Colombier }
4801a344a2SDavid du Colombier p->flags |= flag;
4901a344a2SDavid du Colombier return p;
5001a344a2SDavid du Colombier }
5101a344a2SDavid du Colombier p = p->fore;
5201a344a2SDavid du Colombier if(p == s)
5301a344a2SDavid du Colombier break;
5401a344a2SDavid du Colombier }
5501a344a2SDavid du Colombier if(flag & Bprobe) {
5601a344a2SDavid du Colombier unlock(hp);
5701a344a2SDavid du Colombier return 0;
5801a344a2SDavid du Colombier }
5901a344a2SDavid du Colombier
6001a344a2SDavid du Colombier /*
6101a344a2SDavid du Colombier * not found
6201a344a2SDavid du Colombier * take oldest unlocked entry in this queue
6301a344a2SDavid du Colombier */
6401a344a2SDavid du Colombier xloop:
6501a344a2SDavid du Colombier p = s->back;
6601a344a2SDavid du Colombier if(!canqlock(p)) {
6701a344a2SDavid du Colombier if(p == hp->link) {
6801a344a2SDavid du Colombier unlock(hp);
6901a344a2SDavid du Colombier print("iobuf all locked\n");
7001a344a2SDavid du Colombier goto loop;
7101a344a2SDavid du Colombier }
7201a344a2SDavid du Colombier s = p;
7301a344a2SDavid du Colombier goto xloop;
7401a344a2SDavid du Colombier }
7501a344a2SDavid du Colombier
7601a344a2SDavid du Colombier /*
7701a344a2SDavid du Colombier * its dangerous to flush the pseudo
7801a344a2SDavid du Colombier * devices since they recursively call
7901a344a2SDavid du Colombier * getbuf/putbuf. deadlock!
8001a344a2SDavid du Colombier */
8101a344a2SDavid du Colombier if(p->flags & Bres) {
8201a344a2SDavid du Colombier qunlock(p);
8301a344a2SDavid du Colombier if(p == hp->link) {
8401a344a2SDavid du Colombier unlock(hp);
8501a344a2SDavid du Colombier print("iobuf all reserved\n");
8601a344a2SDavid du Colombier goto loop;
8701a344a2SDavid du Colombier }
8801a344a2SDavid du Colombier s = p;
8901a344a2SDavid du Colombier goto xloop;
9001a344a2SDavid du Colombier }
9101a344a2SDavid du Colombier if(p->flags & Bmod) {
9201a344a2SDavid du Colombier unlock(hp);
9301a344a2SDavid du Colombier if(iobufmap(p)) {
9401a344a2SDavid du Colombier if(!devwrite(p->dev, p->addr, p->iobuf))
9501a344a2SDavid du Colombier p->flags &= ~(Bimm|Bmod);
9601a344a2SDavid du Colombier iobufunmap(p);
9701a344a2SDavid du Colombier }
9801a344a2SDavid du Colombier qunlock(p);
9901a344a2SDavid du Colombier goto loop;
10001a344a2SDavid du Colombier }
10101a344a2SDavid du Colombier hp->link = p;
10201a344a2SDavid du Colombier p->addr = addr;
10301a344a2SDavid du Colombier p->dev = d;
10401a344a2SDavid du Colombier p->flags = flag;
10501a344a2SDavid du Colombier // p->pc = getcallerpc(&d);
10601a344a2SDavid du Colombier unlock(hp);
10701a344a2SDavid du Colombier if(iobufmap(p))
10801a344a2SDavid du Colombier if(flag & Brd) {
10901a344a2SDavid du Colombier if(!devread(p->dev, p->addr, p->iobuf))
11001a344a2SDavid du Colombier return p;
11101a344a2SDavid du Colombier iobufunmap(p);
11201a344a2SDavid du Colombier } else
11301a344a2SDavid du Colombier return p;
11401a344a2SDavid du Colombier else
11501a344a2SDavid du Colombier print("iobuf cant map buffer\n");
11601a344a2SDavid du Colombier p->flags = 0;
11701a344a2SDavid du Colombier p->dev = devnone;
11801a344a2SDavid du Colombier p->addr = -1;
11901a344a2SDavid du Colombier qunlock(p);
12001a344a2SDavid du Colombier return 0;
12101a344a2SDavid du Colombier }
12201a344a2SDavid du Colombier
12301a344a2SDavid du Colombier /*
12401a344a2SDavid du Colombier * syncblock tries to put out a block per hashline
12501a344a2SDavid du Colombier * returns 0 all done,
12601a344a2SDavid du Colombier * returns 1 if it missed something
12701a344a2SDavid du Colombier */
12801a344a2SDavid du Colombier int
syncblock(void)12901a344a2SDavid du Colombier syncblock(void)
13001a344a2SDavid du Colombier {
13101a344a2SDavid du Colombier Iobuf *p, *s, *q;
13201a344a2SDavid du Colombier Hiob *hp;
13301a344a2SDavid du Colombier long h;
13401a344a2SDavid du Colombier int flag;
13501a344a2SDavid du Colombier
13601a344a2SDavid du Colombier flag = 0;
13701a344a2SDavid du Colombier for(h=0; h<nhiob; h++) {
13801a344a2SDavid du Colombier q = 0;
13901a344a2SDavid du Colombier hp = &hiob[h];
14001a344a2SDavid du Colombier lock(hp);
14101a344a2SDavid du Colombier s = hp->link;
14201a344a2SDavid du Colombier for(p=s;;) {
14301a344a2SDavid du Colombier if(p->flags & Bmod) {
14401a344a2SDavid du Colombier if(q)
14501a344a2SDavid du Colombier flag = 1; /* more than 1 mod/line */
14601a344a2SDavid du Colombier q = p;
14701a344a2SDavid du Colombier }
14801a344a2SDavid du Colombier p = p->fore;
14901a344a2SDavid du Colombier if(p == s)
15001a344a2SDavid du Colombier break;
15101a344a2SDavid du Colombier }
15201a344a2SDavid du Colombier unlock(hp);
15301a344a2SDavid du Colombier if(q) {
15401a344a2SDavid du Colombier if(!canqlock(q)) {
15501a344a2SDavid du Colombier flag = 1; /* missed -- was locked */
15601a344a2SDavid du Colombier continue;
15701a344a2SDavid du Colombier }
15801a344a2SDavid du Colombier if(!(q->flags & Bmod)) {
15901a344a2SDavid du Colombier qunlock(q);
16001a344a2SDavid du Colombier continue;
16101a344a2SDavid du Colombier }
16201a344a2SDavid du Colombier if(iobufmap(q)) {
16301a344a2SDavid du Colombier if(!devwrite(q->dev, q->addr, q->iobuf))
16401a344a2SDavid du Colombier q->flags &= ~(Bmod|Bimm);
16501a344a2SDavid du Colombier iobufunmap(q);
16601a344a2SDavid du Colombier } else
16701a344a2SDavid du Colombier flag = 1;
16801a344a2SDavid du Colombier qunlock(q);
16901a344a2SDavid du Colombier }
17001a344a2SDavid du Colombier }
17101a344a2SDavid du Colombier return flag;
17201a344a2SDavid du Colombier }
17301a344a2SDavid du Colombier
17401a344a2SDavid du Colombier void
sync(char * reason)17501a344a2SDavid du Colombier sync(char *reason)
17601a344a2SDavid du Colombier {
17701a344a2SDavid du Colombier long i;
17801a344a2SDavid du Colombier
17901a344a2SDavid du Colombier print("sync: %s\n", reason);
18001a344a2SDavid du Colombier for(i=10*nhiob; i>0; i--)
18101a344a2SDavid du Colombier if(!syncblock())
18201a344a2SDavid du Colombier return;
18301a344a2SDavid du Colombier print("sync shorted\n");
18401a344a2SDavid du Colombier }
18501a344a2SDavid du Colombier
18601a344a2SDavid du Colombier void
putbuf(Iobuf * p)18701a344a2SDavid du Colombier putbuf(Iobuf *p)
18801a344a2SDavid du Colombier {
18901a344a2SDavid du Colombier
19001a344a2SDavid du Colombier if(canqlock(p))
19101a344a2SDavid du Colombier print("buffer not locked %Z(%lld)\n", p->dev, (Wideoff)p->addr);
19201a344a2SDavid du Colombier if(p->flags & Bimm) {
19301a344a2SDavid du Colombier if(!(p->flags & Bmod))
19401a344a2SDavid du Colombier print("imm and no mod %Z(%lld)\n",
19501a344a2SDavid du Colombier p->dev, (Wideoff)p->addr);
19601a344a2SDavid du Colombier if(!devwrite(p->dev, p->addr, p->iobuf))
19701a344a2SDavid du Colombier p->flags &= ~(Bmod|Bimm);
19801a344a2SDavid du Colombier }
19901a344a2SDavid du Colombier iobufunmap(p);
20001a344a2SDavid du Colombier qunlock(p);
20101a344a2SDavid du Colombier }
20201a344a2SDavid du Colombier
20301a344a2SDavid du Colombier int
checktag(Iobuf * p,int tag,Off qpath)20401a344a2SDavid du Colombier checktag(Iobuf *p, int tag, Off qpath)
20501a344a2SDavid du Colombier {
20601a344a2SDavid du Colombier Tag *t;
20701a344a2SDavid du Colombier static Off lastaddr;
20801a344a2SDavid du Colombier
20901a344a2SDavid du Colombier t = (Tag*)(p->iobuf+BUFSIZE);
21001a344a2SDavid du Colombier if(t->tag != tag) {
21101a344a2SDavid du Colombier if(p->flags & Bmod) {
21201a344a2SDavid du Colombier print("\ttag = %d/%llud; expected %lld/%d -- not flushed\n",
21301a344a2SDavid du Colombier t->tag, (Wideoff)t->path, (Wideoff)qpath, tag);
21401a344a2SDavid du Colombier return 2;
21501a344a2SDavid du Colombier }
21601a344a2SDavid du Colombier if(p->dev != nil && p->dev->type == Devcw)
21701a344a2SDavid du Colombier cwfree(p->dev, p->addr);
21801a344a2SDavid du Colombier if(p->addr != lastaddr)
21901a344a2SDavid du Colombier print("\ttag = %G/%llud; expected %G/%lld -- flushed (%lld)\n",
22001a344a2SDavid du Colombier t->tag, (Wideoff)t->path, tag, (Wideoff)qpath,
22101a344a2SDavid du Colombier (Wideoff)p->addr);
22201a344a2SDavid du Colombier lastaddr = p->addr;
22301a344a2SDavid du Colombier p->dev = devnone;
22401a344a2SDavid du Colombier p->addr = -1;
22501a344a2SDavid du Colombier p->flags = 0;
22601a344a2SDavid du Colombier return 2;
22701a344a2SDavid du Colombier }
22801a344a2SDavid du Colombier if(qpath != QPNONE) {
22901a344a2SDavid du Colombier if((qpath ^ t->path) & ~QPDIR) {
23001a344a2SDavid du Colombier if(1 || CHAT(0))
23101a344a2SDavid du Colombier print("\ttag/path = %llud; expected %d/%llux\n",
23201a344a2SDavid du Colombier (Wideoff)t->path, tag, (Wideoff)qpath);
23301a344a2SDavid du Colombier return 0;
23401a344a2SDavid du Colombier }
23501a344a2SDavid du Colombier }
23601a344a2SDavid du Colombier return 0;
23701a344a2SDavid du Colombier }
23801a344a2SDavid du Colombier
23901a344a2SDavid du Colombier void
settag(Iobuf * p,int tag,long qpath)24001a344a2SDavid du Colombier settag(Iobuf *p, int tag, long qpath)
24101a344a2SDavid du Colombier {
24201a344a2SDavid du Colombier Tag *t;
24301a344a2SDavid du Colombier
24401a344a2SDavid du Colombier t = (Tag*)(p->iobuf+BUFSIZE);
24501a344a2SDavid du Colombier t->tag = tag;
24601a344a2SDavid du Colombier if(qpath != QPNONE)
24701a344a2SDavid du Colombier t->path = qpath & ~QPDIR;
24801a344a2SDavid du Colombier p->flags |= Bmod;
24901a344a2SDavid du Colombier }
25001a344a2SDavid du Colombier
25101a344a2SDavid du Colombier int
qlmatch(QLock * q1,QLock * q2)25201a344a2SDavid du Colombier qlmatch(QLock *q1, QLock *q2)
25301a344a2SDavid du Colombier {
25401a344a2SDavid du Colombier
25501a344a2SDavid du Colombier return q1 == q2;
25601a344a2SDavid du Colombier }
25701a344a2SDavid du Colombier
25801a344a2SDavid du Colombier int
iobufql(QLock * q)25901a344a2SDavid du Colombier iobufql(QLock *q)
26001a344a2SDavid du Colombier {
26101a344a2SDavid du Colombier Iobuf *p, *s;
26201a344a2SDavid du Colombier Hiob *hp;
26301a344a2SDavid du Colombier Tag *t;
26401a344a2SDavid du Colombier long h;
26501a344a2SDavid du Colombier int tag;
26601a344a2SDavid du Colombier
26701a344a2SDavid du Colombier for(h=0; h<nhiob; h++) {
26801a344a2SDavid du Colombier hp = &hiob[h];
26901a344a2SDavid du Colombier lock(hp);
27001a344a2SDavid du Colombier s = hp->link;
27101a344a2SDavid du Colombier for(p=s;;) {
27201a344a2SDavid du Colombier if(qlmatch(q, p)) {
27301a344a2SDavid du Colombier t = (Tag*)(p->iobuf+BUFSIZE);
27401a344a2SDavid du Colombier tag = t->tag;
27501a344a2SDavid du Colombier if(tag < 0 || tag >= MAXTAG)
27601a344a2SDavid du Colombier tag = Tnone;
27701a344a2SDavid du Colombier print("\tIobuf %Z(%lld) t=%s\n",
27801a344a2SDavid du Colombier p->dev, (Wideoff)p->addr, tagnames[tag]);
27901a344a2SDavid du Colombier unlock(hp);
28001a344a2SDavid du Colombier return 1;
28101a344a2SDavid du Colombier }
28201a344a2SDavid du Colombier p = p->fore;
28301a344a2SDavid du Colombier if(p == s)
28401a344a2SDavid du Colombier break;
28501a344a2SDavid du Colombier }
28601a344a2SDavid du Colombier unlock(hp);
28701a344a2SDavid du Colombier }
28801a344a2SDavid du Colombier return 0;
28901a344a2SDavid du Colombier }
290