xref: /plan9/sys/src/cmd/cwfs/iobuf.c (revision 223a035810d484657ee1a815f68faa8211009d6d)
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