1 #include "all.h" 2 3 #define DEBUG 0 4 5 long niob; 6 long nhiob; 7 Hiob *hiob; 8 9 Iobuf* 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 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 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 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 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\n", 208 t->tag, tag); 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 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