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