1 /* tty_subr.c 4.18 82/12/17 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/conf.h" 6 #include "../h/buf.h" 7 #include "../h/tty.h" 8 #include "../h/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; 165 register s; 166 167 s = spl5(); 168 if (q->c_cc < 0) { 169 printf("neg q flush\n"); 170 goto out; 171 } 172 if (q->c_cc == 0) { 173 goto out; 174 } 175 while (cc>0 && q->c_cc) { 176 bp = (struct cblock *)((int)q->c_cf & ~CROUND); 177 if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 178 end = q->c_cl; 179 } else { 180 end = (char *)((int)bp + sizeof (struct cblock)); 181 } 182 rem = end - q->c_cf; 183 if (cc >= rem) { 184 cc -= rem; 185 q->c_cc -= rem; 186 q->c_cf = bp->c_next->c_info; 187 bp->c_next = cfreelist; 188 cfreelist = bp; 189 cfreecount += CBSIZE; 190 if (cwaiting) { 191 wakeup(&cwaiting); 192 cwaiting = 0; 193 } 194 } else { 195 q->c_cc -= cc; 196 q->c_cf += cc; 197 if (q->c_cc <= 0) { 198 bp->c_next = cfreelist; 199 cfreelist = bp; 200 cfreecount += CBSIZE; 201 if (cwaiting) { 202 wakeup(&cwaiting); 203 cwaiting = 0; 204 } 205 } 206 break; 207 } 208 } 209 if (q->c_cc <= 0) { 210 q->c_cf = q->c_cl = NULL; 211 q->c_cc = 0; 212 } 213 out: 214 splx(s); 215 } 216 217 218 putc(c, p) 219 register struct clist *p; 220 { 221 register struct cblock *bp; 222 register char *cp; 223 register s; 224 225 s = spl5(); 226 if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 227 if ((bp = cfreelist) == NULL) { 228 splx(s); 229 return(-1); 230 } 231 cfreelist = bp->c_next; 232 cfreecount -= CBSIZE; 233 bp->c_next = NULL; 234 p->c_cf = cp = bp->c_info; 235 } else if (((int)cp & CROUND) == 0) { 236 bp = (struct cblock *)cp - 1; 237 if ((bp->c_next = cfreelist) == NULL) { 238 splx(s); 239 return(-1); 240 } 241 bp = bp->c_next; 242 cfreelist = bp->c_next; 243 cfreecount -= CBSIZE; 244 bp->c_next = NULL; 245 cp = bp->c_info; 246 } 247 *cp++ = c; 248 p->c_cc++; 249 p->c_cl = cp; 250 splx(s); 251 return(0); 252 } 253 254 255 256 /* 257 * copy buffer to clist. 258 * return number of bytes not transfered. 259 */ 260 b_to_q(cp, cc, q) 261 register char *cp; 262 struct clist *q; 263 register int cc; 264 { 265 register char *cq; 266 register struct cblock *bp; 267 register s, acc; 268 269 if (cc <= 0) 270 return(0); 271 acc = cc; 272 273 274 s = spl5(); 275 if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 276 if ((bp = cfreelist) == NULL) 277 goto out; 278 cfreelist = bp->c_next; 279 cfreecount -= CBSIZE; 280 bp->c_next = NULL; 281 q->c_cf = cq = bp->c_info; 282 } 283 284 while (cc) { 285 if (((int)cq & CROUND) == 0) { 286 bp = (struct cblock *) cq - 1; 287 if ((bp->c_next = cfreelist) == NULL) 288 goto out; 289 bp = bp->c_next; 290 cfreelist = bp->c_next; 291 cfreecount -= CBSIZE; 292 bp->c_next = NULL; 293 cq = bp->c_info; 294 } 295 *cq++ = *cp++; 296 cc--; 297 } 298 out: 299 q->c_cl = cq; 300 q->c_cc += acc-cc; 301 splx(s); 302 return(cc); 303 } 304 305 /* 306 * Given a non-NULL pointter into the list (like c_cf which 307 * always points to a real character if non-NULL) return the pointer 308 * to the next character in the list or return NULL if no more chars. 309 * 310 * Callers must not allow getc's to happen between nextc's so that the 311 * pointer becomes invalid. Note that interrupts are NOT masked. 312 */ 313 char * 314 nextc(p, cp) 315 register struct clist *p; 316 register char *cp; 317 { 318 319 if (p->c_cc && ++cp != p->c_cl) { 320 if (((int)cp & CROUND) == 0) 321 return (((struct cblock *)cp)[-1].c_next->c_info); 322 return (cp); 323 } 324 return (0); 325 } 326 327 /* 328 * Remove the last character in the list and return it. 329 */ 330 unputc(p) 331 register struct clist *p; 332 { 333 register struct cblock *bp; 334 register int c, s; 335 struct cblock *obp; 336 337 s = spl5(); 338 if (p->c_cc <= 0) 339 c = -1; 340 else { 341 c = *--p->c_cl; 342 if (--p->c_cc <= 0) { 343 bp = (struct cblock *)p->c_cl; 344 bp = (struct cblock *)((int)bp & ~CROUND); 345 p->c_cl = p->c_cf = NULL; 346 bp->c_next = cfreelist; 347 cfreelist = bp; 348 cfreecount += CBSIZE; 349 } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 350 p->c_cl = (char *)((int)p->c_cl & ~CROUND); 351 bp = (struct cblock *)p->c_cf; 352 bp = (struct cblock *)((int)bp & ~CROUND); 353 while (bp->c_next != (struct cblock *)p->c_cl) 354 bp = bp->c_next; 355 obp = bp; 356 p->c_cl = (char *)(bp + 1); 357 bp = bp->c_next; 358 bp->c_next = cfreelist; 359 cfreelist = bp; 360 cfreecount += CBSIZE; 361 obp->c_next = NULL; 362 } 363 } 364 splx(s); 365 return (c); 366 } 367 368 /* 369 * Put the chars in the from que 370 * on the end of the to que. 371 * 372 * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 373 */ 374 catq(from, to) 375 struct clist *from, *to; 376 { 377 register c; 378 379 while ((c = getc(from)) >= 0) 380 (void) putc(c, to); 381 } 382 383 /* 384 * Integer (short) get/put 385 * using clists 386 */ 387 typedef short word_t; 388 union chword { 389 word_t word; 390 struct { 391 char Ch[sizeof (word_t)]; 392 } Cha; 393 #define ch Cha.Ch 394 }; 395 396 getw(p) 397 register struct clist *p; 398 { 399 register int i; 400 union chword x; 401 402 if (p->c_cc < sizeof (word_t)) 403 return (-1); 404 for (i = 0; i < sizeof (word_t); i++) 405 x.ch[i] = getc(p); 406 return (x.word); 407 } 408 409 putw(c, p) 410 register struct clist *p; 411 { 412 register s; 413 register int i; 414 union chword x; 415 416 s = spl5(); 417 if (cfreelist==NULL) { 418 splx(s); 419 return(-1); 420 } 421 x.word = c; 422 for (i = 0; i < sizeof (word_t); i++) 423 (void) putc(x.ch[i], p); 424 splx(s); 425 return (0); 426 } 427