1 #include "all.h"
2
3 #define DEBUG 0
4
5 long niob;
6 long nhiob;
7 Hiob *hiob;
8
9 Iobuf*
getbuf(Device dev,long addr,int flag)10 getbuf(Device dev, long addr, int flag)
11 {
12 Iobuf *p, *s;
13 Hiob *hp;
14 long h;
15
16 if(DEBUG)
17 print("getbuf %D(%ld) f=%x\n", dev, addr, flag);
18 h = addr +
19 dev.type*1009L +
20 dev.ctrl*10007L +
21 dev.unit*100003L +
22 dev.part*1000003L;
23 if(h < 0)
24 h = ~h;
25 h %= nhiob;
26 hp = &hiob[h];
27
28 loop:
29 lock(hp);
30
31 /*
32 * look for it in the active list
33 */
34 s = hp->link;
35 for(p=s;;) {
36 if(p->addr == addr && !devcmp(p->dev, dev)) {
37 if(p != s) {
38 p->back->fore = p->fore;
39 p->fore->back = p->back;
40 p->fore = s;
41 p->back = s->back;
42 s->back = p;
43 p->back->fore = p;
44 hp->link = p;
45 }
46 unlock(hp);
47 qlock(p);
48 if(p->addr != addr || devcmp(p->dev, dev)) {
49 qunlock(p);
50 goto loop;
51 }
52 p->flags |= flag;
53 cons.bhit.count++;
54 p->iobuf = p->xiobuf;
55 return p;
56 }
57 p = p->fore;
58 if(p == s)
59 break;
60 }
61 if(flag & Bprobe) {
62 unlock(hp);
63 return 0;
64 }
65
66 /*
67 * not found
68 * take oldest unlocked entry in this queue
69 */
70 xloop:
71 p = s->back;
72 if(!canqlock(p)) {
73 if(p == hp->link) {
74 unlock(hp);
75 print("iobuf all locked\n");
76 goto loop;
77 }
78 s = p;
79 goto xloop;
80 }
81 /*
82 * its dangerous to flush the pseudo
83 * devices since they recursively call
84 * getbuf/putbuf. deadlock!
85 */
86 if(p->flags & Bres) {
87 qunlock(p);
88 if(p == hp->link) {
89 unlock(hp);
90 print("iobuf all resed\n");
91 goto loop;
92 }
93 s = p;
94 goto xloop;
95 }
96 if(p->flags & Bmod) {
97 unlock(hp);
98 if(!devwrite(p->dev, p->addr, p->xiobuf))
99 p->flags &= ~(Bimm|Bmod);
100 qunlock(p);
101 goto loop;
102 }
103 hp->link = p;
104 p->addr = addr;
105 p->dev = dev;
106 p->flags = flag;
107 unlock(hp);
108 p->iobuf = p->xiobuf;
109 if(flag & Bread) {
110 if(devread(p->dev, p->addr, p->iobuf)) {
111 p->flags = 0;
112 p->dev = devnone;
113 p->addr = -1;
114 p->iobuf = (char*)-1;
115 qunlock(p);
116 return 0;
117 }
118 cons.bread.count++;
119 return p;
120 }
121 cons.binit.count++;
122 return p;
123 }
124
125 /*
126 * syncblock tries to put out a block per hashline
127 * returns 0 all done,
128 * returns 1 if it missed something
129 */
130 int
syncblock(void)131 syncblock(void)
132 {
133 Iobuf *p, *s, *q;
134 Hiob *hp;
135 long h;
136 int flag;
137
138 flag = 0;
139 for(h=0; h<nhiob; h++) {
140 q = 0;
141 hp = &hiob[h];
142 lock(hp);
143 s = hp->link;
144 for(p=s;;) {
145 if(p->flags & Bmod) {
146 if(q)
147 flag = 1; /* more than 1 mod/line */
148 q = p;
149 }
150 p = p->fore;
151 if(p == s)
152 break;
153 }
154 unlock(hp);
155 if(q) {
156 if(!canqlock(q)) {
157 flag = 1; /* missed -- was locked */
158 continue;
159 }
160 if(!(q->flags & Bmod)) {
161 qunlock(q);
162 continue;
163 }
164 if(!devwrite(q->dev, q->addr, q->xiobuf))
165 q->flags &= ~(Bmod|Bimm);
166 qunlock(q);
167 }
168 }
169 return flag;
170 }
171
172 void
sync(char * reason)173 sync(char *reason)
174 {
175 long i;
176
177 print("sync: %s\n", reason);
178 for(i=10*nhiob; i>0; i--)
179 if(!syncblock())
180 return;
181 print("sync shorted\n");
182 }
183
184 void
putbuf(Iobuf * p)185 putbuf(Iobuf *p)
186 {
187 if(canqlock(p))
188 print("buffer not locked %D(%ld)\n", p->dev, p->addr);
189 if(p->flags & Bimm) {
190 if(!(p->flags & Bmod))
191 print("imm and no mod %D(%ld)\n", p->dev, p->addr);
192 if(!devwrite(p->dev, p->addr, p->iobuf))
193 p->flags &= ~(Bmod|Bimm);
194 }
195 p->iobuf = (char*)-1;
196 qunlock(p);
197 }
198
199 int
checktag(Iobuf * p,int tag,long qpath)200 checktag(Iobuf *p, int tag, long qpath)
201 {
202 Tag *t;
203
204 t = (Tag*)(p->iobuf+BUFSIZE);
205 if(t->tag != tag) {
206 if(1 || CHAT(0))
207 print(" tag = %G; expected %G; addr = %lud\n",
208 t->tag, tag, p->addr);
209 return 2;
210 }
211 if(qpath != QPNONE) {
212 qpath &= ~QPDIR;
213 if(qpath != t->path) {
214 if(qpath == (t->path&~QPDIR)) /* old bug */
215 return 0;
216 if(1 || CHAT(0))
217 print(" tag/path = %lux; expected %G/%lux\n",
218 t->path, tag, qpath);
219 return 1;
220 }
221 }
222 return 0;
223 }
224
225 void
settag(Iobuf * p,int tag,long qpath)226 settag(Iobuf *p, int tag, long qpath)
227 {
228 Tag *t;
229
230 t = (Tag*)(p->iobuf+BUFSIZE);
231 t->tag = tag;
232 if(qpath != QPNONE)
233 t->path = qpath & ~QPDIR;
234 p->flags |= Bmod;
235 }
236