1 /* tty_subr.c 6.3 84/08/29 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "conf.h" 6 #include "buf.h" 7 #include "tty.h" 8 #include "clist.h" 9 10 char cwaiting; 11 12 /* 13 * Character list get/put 14 */ 15 getc(p) 16 register struct clist *p; 17 { 18 register struct cblock *bp; 19 register int c, s; 20 21 s = spl5(); 22 if (p->c_cc <= 0) { 23 c = -1; 24 p->c_cc = 0; 25 p->c_cf = p->c_cl = NULL; 26 } else { 27 c = *p->c_cf++ & 0377; 28 if (--p->c_cc<=0) { 29 bp = (struct cblock *)(p->c_cf-1); 30 bp = (struct cblock *) ((int)bp & ~CROUND); 31 p->c_cf = NULL; 32 p->c_cl = NULL; 33 bp->c_next = cfreelist; 34 cfreelist = bp; 35 cfreecount += CBSIZE; 36 if (cwaiting) { 37 wakeup(&cwaiting); 38 cwaiting = 0; 39 } 40 } else if (((int)p->c_cf & CROUND) == 0){ 41 bp = (struct cblock *)(p->c_cf); 42 bp--; 43 p->c_cf = bp->c_next->c_info; 44 bp->c_next = cfreelist; 45 cfreelist = bp; 46 cfreecount += CBSIZE; 47 if (cwaiting) { 48 wakeup(&cwaiting); 49 cwaiting = 0; 50 } 51 } 52 } 53 splx(s); 54 return(c); 55 } 56 57 /* 58 * copy clist to buffer. 59 * return number of bytes moved. 60 */ 61 q_to_b(q, cp, cc) 62 register struct clist *q; 63 register char *cp; 64 { 65 register struct cblock *bp; 66 register int s; 67 char *acp; 68 69 if (cc <= 0) 70 return(0); 71 s = spl5(); 72 if (q->c_cc <= 0) { 73 q->c_cc = 0; 74 q->c_cf = q->c_cl = NULL; 75 splx(s); 76 return(0); 77 } 78 acp = cp; 79 cc++; 80 81 while (--cc) { 82 *cp++ = *q->c_cf++; 83 if (--q->c_cc <= 0) { 84 bp = (struct cblock *)(q->c_cf-1); 85 bp = (struct cblock *)((int)bp & ~CROUND); 86 q->c_cf = q->c_cl = NULL; 87 bp->c_next = cfreelist; 88 cfreelist = bp; 89 cfreecount += CBSIZE; 90 if (cwaiting) { 91 wakeup(&cwaiting); 92 cwaiting = 0; 93 } 94 break; 95 } 96 if (((int)q->c_cf & CROUND) == 0) { 97 bp = (struct cblock *)(q->c_cf); 98 bp--; 99 q->c_cf = bp->c_next->c_info; 100 bp->c_next = cfreelist; 101 cfreelist = bp; 102 cfreecount += CBSIZE; 103 if (cwaiting) { 104 wakeup(&cwaiting); 105 cwaiting = 0; 106 } 107 } 108 } 109 splx(s); 110 return(cp-acp); 111 } 112 113 /* 114 * Return count of contiguous characters 115 * in clist starting at q->c_cf. 116 * Stop counting if flag&character is non-null. 117 */ 118 ndqb(q, flag) 119 register struct clist *q; 120 { 121 register cc; 122 int s; 123 124 s = spl5(); 125 if (q->c_cc <= 0) { 126 cc = -q->c_cc; 127 goto out; 128 } 129 cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 130 cc -= (int)q->c_cf; 131 if (q->c_cc < cc) 132 cc = q->c_cc; 133 if (flag) { 134 register char *p, *end; 135 136 p = q->c_cf; 137 end = p; 138 end += cc; 139 while (p < end) { 140 if (*p & flag) { 141 cc = (int)p; 142 cc -= (int)q->c_cf; 143 break; 144 } 145 p++; 146 } 147 } 148 out: 149 splx(s); 150 return(cc); 151 } 152 153 154 155 /* 156 * Flush cc bytes from q. 157 */ 158 ndflush(q, cc) 159 register struct clist *q; 160 register cc; 161 { 162 register struct cblock *bp; 163 char *end; 164 int rem, s; 165 166 s = spl5(); 167 if (q->c_cc <= 0) { 168 goto out; 169 } 170 while (cc>0 && q->c_cc) { 171 bp = (struct cblock *)((int)q->c_cf & ~CROUND); 172 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 173 end = q->c_cl; 174 } else { 175 end = (char *)((int)bp + sizeof (struct cblock)); 176 } 177 rem = end - q->c_cf; 178 if (cc >= rem) { 179 cc -= rem; 180 q->c_cc -= rem; 181 q->c_cf = bp->c_next->c_info; 182 bp->c_next = cfreelist; 183 cfreelist = bp; 184 cfreecount += CBSIZE; 185 if (cwaiting) { 186 wakeup(&cwaiting); 187 cwaiting = 0; 188 } 189 } else { 190 q->c_cc -= cc; 191 q->c_cf += cc; 192 if (q->c_cc <= 0) { 193 bp->c_next = cfreelist; 194 cfreelist = bp; 195 cfreecount += CBSIZE; 196 if (cwaiting) { 197 wakeup(&cwaiting); 198 cwaiting = 0; 199 } 200 } 201 break; 202 } 203 } 204 if (q->c_cc <= 0) { 205 q->c_cf = q->c_cl = NULL; 206 q->c_cc = 0; 207 } 208 out: 209 splx(s); 210 } 211 212 213 putc(c, p) 214 register struct clist *p; 215 { 216 register struct cblock *bp; 217 register char *cp; 218 register s; 219 220 s = spl5(); 221 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 222 if ((bp = cfreelist) == NULL) { 223 splx(s); 224 return(-1); 225 } 226 cfreelist = bp->c_next; 227 cfreecount -= CBSIZE; 228 bp->c_next = NULL; 229 p->c_cf = cp = bp->c_info; 230 } else if (((int)cp & CROUND) == 0) { 231 bp = (struct cblock *)cp - 1; 232 if ((bp->c_next = cfreelist) == NULL) { 233 splx(s); 234 return(-1); 235 } 236 bp = bp->c_next; 237 cfreelist = bp->c_next; 238 cfreecount -= CBSIZE; 239 bp->c_next = NULL; 240 cp = bp->c_info; 241 } 242 *cp++ = c; 243 p->c_cc++; 244 p->c_cl = cp; 245 splx(s); 246 return(0); 247 } 248 249 250 251 /* 252 * copy buffer to clist. 253 * return number of bytes not transfered. 254 */ 255 b_to_q(cp, cc, q) 256 register char *cp; 257 struct clist *q; 258 register int cc; 259 { 260 register char *cq; 261 register struct cblock *bp; 262 register s, acc; 263 264 if (cc <= 0) 265 return(0); 266 acc = cc; 267 268 269 s = spl5(); 270 if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 271 if ((bp = cfreelist) == NULL) 272 goto out; 273 cfreelist = bp->c_next; 274 cfreecount -= CBSIZE; 275 bp->c_next = NULL; 276 q->c_cf = cq = bp->c_info; 277 } 278 279 while (cc) { 280 if (((int)cq & CROUND) == 0) { 281 bp = (struct cblock *) cq - 1; 282 if ((bp->c_next = cfreelist) == NULL) 283 goto out; 284 bp = bp->c_next; 285 cfreelist = bp->c_next; 286 cfreecount -= CBSIZE; 287 bp->c_next = NULL; 288 cq = bp->c_info; 289 } 290 *cq++ = *cp++; 291 cc--; 292 } 293 out: 294 q->c_cl = cq; 295 q->c_cc += acc-cc; 296 splx(s); 297 return(cc); 298 } 299 300 /* 301 * Given a non-NULL pointter into the list (like c_cf which 302 * always points to a real character if non-NULL) return the pointer 303 * to the next character in the list or return NULL if no more chars. 304 * 305 * Callers must not allow getc's to happen between nextc's so that the 306 * pointer becomes invalid. Note that interrupts are NOT masked. 307 */ 308 char * 309 nextc(p, cp) 310 register struct clist *p; 311 register char *cp; 312 { 313 314 if (p->c_cc && ++cp != p->c_cl) { 315 if (((int)cp & CROUND) == 0) 316 return (((struct cblock *)cp)[-1].c_next->c_info); 317 return (cp); 318 } 319 return (0); 320 } 321 322 /* 323 * Remove the last character in the list and return it. 324 */ 325 unputc(p) 326 register struct clist *p; 327 { 328 register struct cblock *bp; 329 register int c, s; 330 struct cblock *obp; 331 332 s = spl5(); 333 if (p->c_cc <= 0) 334 c = -1; 335 else { 336 c = *--p->c_cl; 337 if (--p->c_cc <= 0) { 338 bp = (struct cblock *)p->c_cl; 339 bp = (struct cblock *)((int)bp & ~CROUND); 340 p->c_cl = p->c_cf = NULL; 341 bp->c_next = cfreelist; 342 cfreelist = bp; 343 cfreecount += CBSIZE; 344 } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 345 p->c_cl = (char *)((int)p->c_cl & ~CROUND); 346 bp = (struct cblock *)p->c_cf; 347 bp = (struct cblock *)((int)bp & ~CROUND); 348 while (bp->c_next != (struct cblock *)p->c_cl) 349 bp = bp->c_next; 350 obp = bp; 351 p->c_cl = (char *)(bp + 1); 352 bp = bp->c_next; 353 bp->c_next = cfreelist; 354 cfreelist = bp; 355 cfreecount += CBSIZE; 356 obp->c_next = NULL; 357 } 358 } 359 splx(s); 360 return (c); 361 } 362 363 /* 364 * Put the chars in the from que 365 * on the end of the to que. 366 * 367 * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 368 */ 369 catq(from, to) 370 struct clist *from, *to; 371 { 372 register c; 373 374 while ((c = getc(from)) >= 0) 375 (void) putc(c, to); 376 } 377 378 /* 379 * Integer (short) get/put 380 * using clists 381 */ 382 typedef short word_t; 383 union chword { 384 word_t word; 385 struct { 386 char Ch[sizeof (word_t)]; 387 } Cha; 388 #define ch Cha.Ch 389 }; 390 391 getw(p) 392 register struct clist *p; 393 { 394 register int i; 395 union chword x; 396 397 if (p->c_cc < sizeof (word_t)) 398 return (-1); 399 for (i = 0; i < sizeof (word_t); i++) 400 x.ch[i] = getc(p); 401 return (x.word); 402 } 403 404 putw(c, p) 405 register struct clist *p; 406 { 407 register s; 408 register int i; 409 union chword x; 410 411 s = spl5(); 412 if (cfreelist==NULL) { 413 splx(s); 414 return(-1); 415 } 416 x.word = c; 417 for (i = 0; i < sizeof (word_t); i++) 418 (void) putc(x.ch[i], p); 419 splx(s); 420 return (0); 421 } 422