|
|
1.1 ! root 1: /* D.L.Buck and Associates, Inc. - 9/4/84 ! 2: * ! 3: * COPYRIGHT NOTICE: ! 4: * Copyright c 9/4/84 - An unpublished work by ! 5: * D.L.Buck and Associates, Inc. ! 6: * ! 7: * PROPRIETARY RIGHTS NOTICE: ! 8: * All rights reserved. This document and program contains ! 9: * proprietary information of D.L.Buck and Associates,Inc. ! 10: * of San Jose, California, U.S.A., embodying confidential ! 11: * information, ideas, and expressions, no part of which ! 12: * may be reproduced, or transmitted in any form or by any ! 13: * means, electronic, mechanical, or otherwise, without ! 14: * the written permission of D.L.Buck and Associates, Inc. ! 15: * ! 16: * NAME ! 17: * bsm - multi-station bisync device driver ! 18: * ! 19: * DESCRIPTION ! 20: * This file contains the Unix system interface routines, prepared for ! 21: * UNIX Version 7, System III, System V, or BSD 4.2. ! 22: * The entry points are bsmopen, bsmclose, bsmread, bsmwrite, and ! 23: * bsmioctl. These routines are meant to be hardware-independent. ! 24: */ ! 25: ! 26: #ifndef lint ! 27: static char bsm_c[] = "@(#)bscm.c 1.17 REL"; ! 28: #endif ! 29: ! 30: #include "../bsc/local.h" ! 31: #include "../bsc/bscio.h" ! 32: #include "../bsc/bsc.h" ! 33: ! 34: #if defined v7 || defined BSD42 ! 35: #define delay(x) sleep((caddr_t)&lbolt, BSCPRI) ! 36: extern int lbolt; ! 37: #endif ! 38: ! 39: #if defined BSD42 ! 40: #define ERRRET(x) return x ! 41: #define UCOUNT uio->uio_resid ! 42: #else ! 43: #define ERRRET(x) u.u_error = x; return ! 44: #define UCOUNT u.u_count ! 45: #endif ! 46: ! 47: ! 48: /*** ! 49: #define DEV(dev) (minor(dev) >> 5) & 0x7 ! 50: #define SUBDEV(dev) minor(dev) & 0x1f ! 51: ***/ ! 52: ! 53: #define DEV(dev) (minor(dev) >> 4) & 0xf ! 54: #define SUBDEV(dev) minor(dev) & 0xf ! 55: ! 56: extern struct state states[]; /* state table in bscpsm.c */ ! 57: #ifdef NBSM ! 58: extern struct bsc bsc[]; /* device-specific information */ ! 59: struct bscsub bscsubs[NVBSC*NBSM][NBSSUB]; ! 60: ! 61: /* ! 62: * DEVICE ADDRESSING TABLES ! 63: * For device numbers 0 - 31, the tables hold the corresponding ! 64: * EBCDIC (ebcdev) or ASCII (ascdev) address ! 65: */ ! 66: ! 67: ! 68: char ascdev[] = {0x20,0x41,0x42,0x43,0x44,0x45,0x46,0x47, ! 69: 0x48,0x49,0x5b,0x2e,0x3c,0x28,0x2b,0x21, ! 70: 0x26,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50, ! 71: 0x51,0x52,0x5d,0x24,0x2a,0x29,0x3b,0x5e}; ! 72: ! 73: char ebcdev[] = {0x40,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, ! 74: 0xc8,0xc9,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, ! 75: 0x50,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7, ! 76: 0xd8,0xd9,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f}; ! 77: /* ! 78: * NAME ! 79: * bsmopen -- Prepare for BISYNC communications, multistation mode ! 80: * SYNOPSIS ! 81: * bsmopen (dev, flag) ! 82: * dev_t dev; minor device number: ! 83: * bits 7-5: modem port number ! 84: * bits 4-0: station number, 0-31 ! 85: * int flag; unused ! 86: * ALGORITHM ! 87: * 1. Check and lock device. ! 88: * 2. If first station to open on this line, do line initialization ! 89: * 2.1 Set up defaults for ioctl-provided params ! 90: * 2.2 Set up counters and fields returned via ioctl ! 91: * 2.3 Set up miscellaneous fields for driver ! 92: * 2.4 Initialize I/O port ! 93: * 3. Wait till DSR shows ! 94: * 4. If tracing activated, awaken bstopen ! 95: */ ! 96: ! 97: /* VARARGS1 */ ! 98: bsmopen (dev) /* prepare for BISYNC communication */ ! 99: dev_t dev; ! 100: { ! 101: register dev_t bscdev; /* modem port number */ ! 102: register struct bsc *bp; /* ptr to port's bsc entry */ ! 103: register int subdev; /* station number */ ! 104: register struct bscsub *bpsub; /* ptr to station's bscsubs entry */ ! 105: int errcode; ! 106: ! 107: /* 1. Check and lock device. */ ! 108: bscdev = DEV(dev); ! 109: subdev = SUBDEV(dev); ! 110: ! 111: if (bscdev >= MX_NBSM || subdev >= NBSSUB){ ! 112: ERRRET(ENXIO); /* no such device */ ! 113: } ! 114: bp = &bsc[bscdev]; ! 115: bpsub = &bscsubs[bscdev][subdev]; ! 116: if ((bp->b_lock == SSLOCK) || /* line opened for point to point */ ! 117: (bpsub->bs_mode != BS_FREE)) { /* subdevice busy */ ! 118: ERRRET(EBUSY); ! 119: } ! 120: bpsub->bs_mode = BS_IDLE; ! 121: bpsub->bs_sema = BSC_DDONE | BSC_PDONE; ! 122: ! 123: /* 2. If first station to open on this line, do line initialization */ ! 124: if (++bp->b_lock == 1) { /* First one initializes */ ! 125: ! 126: /* 2.1 Set up defaults for ioctl-provided params */ ! 127: bp->b_iocin.b_blks = BSCMBLK; /* max block size */ ! 128: bp->b_hlflgs = BSCMPT; /* flags: we are multipoint */ ! 129: bp->b_iocin.b_termid[0] = '\0'; /* no terminal id */ ! 130: bp->b_iocin.b_hostid[0] = '\0'; /* no host id */ ! 131: bp->b_iocin.b_nbid = /* max # bids */ ! 132: bp->b_iocin.b_nnak = /* max # naks we will give */ ! 133: bp->b_iocin.b_nretry = 15; /* max # rcv t/o's and naks */ ! 134: /* we will accept */ ! 135: bp->b_iocin.b_nttd = /* max # ttds we will accept */ ! 136: bp->b_iocin.b_nwack = 100; /* max # wacks we will accept */ ! 137: bp->b_iocin.b_nor = 30; /* max time to wait on */ ! 138: /* initial rd */ ! 139: ! 140: /* 2.2 Set up counters and fields returned via ioctl */ ! 141: bp->b_iocout.b_blks = 0; /* # blocks sent/received */ ! 142: bp->b_iocout.b_flags = 0; /* flags: see definition */ ! 143: bp->b_iocout.b_termid[0] = '\0';/* no terminal id */ ! 144: bp->b_iocout.b_hostid[0] = '\0';/* no host id */ ! 145: bp->b_iocout.b_nbid = 0; /* no bids so far */ ! 146: bp->b_iocout.b_nnak = 0; /* no naks so far */ ! 147: bp->b_iocout.b_nretry = 0; /* no retry so far */ ! 148: bp->b_iocout.b_nttd = 0; /* no ttds so far */ ! 149: bp->b_iocout.b_nwack = 0; /* no wacks so far */ ! 150: bp->b_iocout.b_nor = 0; /* no overruns so far */ ! 151: ! 152: /* 2.3 Set up miscellaneous fields for driver */ ! 153: bp->b_state = 0; /* set initial psm state*/ ! 154: bp->b_mode = BSC_INIT; /* initial mode indicates */ ! 155: /* haven't done any i/o yet */ ! 156: bp->b_psmbsy = -1; /* no device selected */ ! 157: bp->b_rxst0 = 0; /* reset l/l driver state */ ! 158: bp->b_tmperr = 0; /* no temp. errors yet */ ! 159: bp->b_sema = BSC_DDONE; /* driver not busy */ ! 160: ! 161: /* 2.4 Initialize I/O port */ ! 162: errcode = bsclopn(bscdev,bp); /* device-specific init. */ ! 163: if (errcode) { ! 164: bp->b_lock = 0; /* Unlock device */ ! 165: ERRRET(errcode); ! 166: } ! 167: } ! 168: ! 169: /* 3. Wait till DSR shows */ ! 170: while (bsckdsr(bscdev,bp), !(bp->b_hlflgs & BSC_DSR) && !u.u_error) ! 171: delay(PSMTICK); ! 172: ! 173: /* 4. If tracing activated, awaken bstopen */ ! 174: if (bp->b_trace) ! 175: wakeup(&bp->b_trace); ! 176: if (u.u_error) ! 177: bsmclose(dev); ! 178: #if defined BSD42 ! 179: return 0; ! 180: #endif ! 181: } ! 182: ! 183: /* ! 184: * NAME ! 185: * bsmclose -- Terminate station processing ! 186: * SYNOPSIS ! 187: * bsmclose(dev) ! 188: * dev_t dev; minor device number: ! 189: * bits 7-5: modem port number ! 190: * bits 4-0: station number, 0-31 ! 191: * ALGORITHM ! 192: * 1. Mark station done, free; decrement multistation lock ! 193: * If not last station using line, return. ! 194: * 2. Terminate PSM processing, kill receive and tracing ! 195: * 3. Turn off DTR ! 196: */ ! 197: bsmclose(dev) ! 198: dev_t dev; ! 199: { ! 200: register dev_t bscdev; /* modem port number */ ! 201: register struct bsc *bp; /* ptr to port's bsc entry */ ! 202: register int subdev; /* station number */ ! 203: register struct bscsub *bpsub; /* ptr to station's bscsubs entry */ ! 204: register long s; ! 205: ! 206: bscdev = DEV(dev); ! 207: subdev = SUBDEV(dev); ! 208: bp = &bsc[bscdev]; ! 209: bpsub = &bscsubs[bscdev][subdev]; ! 210: ! 211: /* 1. Mark station done, free; decrement multistation lock. */ ! 212: /* If not last station using line, return. */ ! 213: bpsub->bs_sema &= ~BSC_DBUSY; ! 214: bpsub->bs_sema |= BSC_DDONE; ! 215: bpsub->bs_mode = BS_FREE; ! 216: bpsub->bs_flags = 0; ! 217: if (--bp->b_lock) return; /* others still using the line */ ! 218: s = spl8(); ! 219: ! 220: /* 2. Terminate PSM processing, kill receive and tracing */ ! 221: bp->b_mode = BSC_CLOSED; /* mode is CLOSED */ ! 222: bp->b_rclptr = (char *)0; /* terminate receive */ ! 223: bstclose(bscdev); /* close trace device, too */ ! 224: ! 225: /* 3. Turn off DTR */ ! 226: bsclcls (bscdev, bp); ! 227: splx(s); ! 228: ! 229: #if defined BSD42 ! 230: return 0; ! 231: #endif ! 232: } ! 233: ! 234: /* ! 235: * NAME ! 236: * bsmread -- read next data block. ! 237: * SYNOPSIS ! 238: * bsmread(dev) ! 239: * dev_t dev; minor device number: ! 240: * bits 7-5: modem port number ! 241: * bits 4-0: station number, 0-31 ! 242: * ALGORITHM ! 243: * 1. Check for error latch or lack of DSR. ! 244: * If either set, return EIO error. ! 245: * 2. If first activity on line, set up psm. ! 246: * 3. Based on present mode: ! 247: * 3.1 Write: error (EINVAL) ! 248: * 3.2 Idle: Synch up with psm, then go to Read mode ! 249: * 3.3 Read: If delay mode in effect, wait for err, eof, or data ! 250: * 3.3.1 Check for NO DELAY mode ! 251: * 3.3.2 Wait for full buffer, eof, or error ! 252: * 3.3.3 If EOF, chg mode to Idle, return 0 bytes read ! 253: * 3.3.4 If ERR, leave mode at Read, return -1(EIO) ! 254: * 3.3.5 Buffer full. Copy data out, set length. ! 255: * 4. Mark buffer empty, awaken psm if its sleeping ! 256: */ ! 257: #if defined BSD42 ! 258: bsmread(dev,uio) ! 259: register dev_t dev; ! 260: struct uio *uio; ! 261: #else ! 262: bsmread(dev) ! 263: register dev_t dev; ! 264: #endif ! 265: { ! 266: register dev_t bscdev; /* modem port number */ ! 267: register struct bsc *bp; /* ptr to port's bsc entry */ ! 268: register int subdev; /* station number */ ! 269: register struct bscsub *bpsub; /* ptr to station's bscsubs entry */ ! 270: register int l; /* length info. */ ! 271: int x; /* prty save area */ ! 272: int errcode = 0; /* Error code upon return */ ! 273: ! 274: bscdev = DEV(dev); ! 275: subdev = SUBDEV(dev); ! 276: bp = &bsc[bscdev]; ! 277: bpsub = &bscsubs[bscdev][subdev]; ! 278: ! 279: /* 1. Check for error latch or lack of DSR. */ ! 280: /* If either set, return EIO error. */ ! 281: if (!(bp->b_hlflgs & BSC_DSR) || (bpsub->bs_flags & BS_ERR)) { ! 282: if (!(bpsub->bs_flags & BS_ERR)) { ! 283: bpsub->bs_flags |= BS_ERR; ! 284: bpsub->bs_err = BSCNDSR; ! 285: } ! 286: bpsub->bs_mode = BS_IDLE; ! 287: ERRRET(EIO); ! 288: } ! 289: ! 290: /* 2. If first activity on line, set up psm */ ! 291: if (bp->b_mode == BSC_INIT) { ! 292: bscsetup(bscdev); ! 293: bp->b_mode = BSC_IDLE; ! 294: } ! 295: ! 296: /* 3. Based on present mode: */ ! 297: switch (bpsub->bs_mode) ! 298: { ! 299: /* 3.1 Write: error (EINVAL) */ ! 300: case BS_WRITE: ! 301: ERRRET(EINVAL); ! 302: ! 303: /* 3.2 Idle: Synch up with psm, then go to Read mode */ ! 304: case BS_IDLE: /* First read call */ ! 305: while (!u.u_error && ! 306: !(bpsub->bs_sema & BSC_PDONE) && ! 307: (bpsub->bs_mode == BS_IDLE) && ! 308: !(bpsub->bs_flags&BS_ERR)) ! 309: delay(PSMTICK); /* Synchronize */ ! 310: /* Set read timeout counter */ ! 311: bpsub->bs_rdflg = bp->b_iocin.b_nor*PSMTPS; ! 312: bpsub->bs_mode = BS_READ; ! 313: bpsub->bs_sema |= BSC_DBUSY; ! 314: bpsub->bs_sema &= ~BSC_DDONE; /* driver now busy */ ! 315: ! 316: /* 3.3 Read: If delay mode in effect, wait for err, eof, or data */ ! 317: case BS_READ: /* not first read */ ! 318: forceread: ! 319: x = spl8(); ! 320: /* 3.3.1 Check for NO DELAY mode */ ! 321: if (bpsub->bs_sema & BSC_SEENBUF) { ! 322: bpsub->bs_flags &= ~BS_FULL; ! 323: bpsub->bs_sema &= ~BSC_SEENBUF; ! 324: if (states[bp->b_state].s_type == 'd' && ! 325: bp->b_alenb) { ! 326: bp->b_alenb = 0; /* disable alarm */ ! 327: splx(x); ! 328: bscpsm(bscdev); /* awaken psm */ ! 329: } ! 330: } ! 331: if ((bpsub->bs_sema & BSC_NDLY) && ! 332: !(bpsub->bs_flags & (BS_FULL|BS_ERR|BS_LAST))) { ! 333: splx(x); ! 334: ERRRET(EAGAIN); /* Call again later */ ! 335: } ! 336: ! 337: /* 3.3.2 Wait for full buffer, eof, or error */ ! 338: while (!(bpsub->bs_flags & (BS_FULL|BS_ERR|BS_LAST))) ! 339: sleep ((caddr_t)&bpsub->bs_flags,BSCPRI); ! 340: splx(x); ! 341: ! 342: bpsub->bs_rdflg = 0; /* cancel read timeout */ ! 343: ! 344: /* 3.3.3 If EOF, chg mode to Idle, return 0 bytes read */ ! 345: if (bpsub->bs_flags & BS_LAST) { ! 346: bpsub->bs_mode = BS_IDLE; ! 347: bp->b_hlflgs &= ~(BSC_XLAST|BSC_XTRN); ! 348: bpsub->bs_flags &= ~(BS_LAST|BSC_XTRN); ! 349: bpsub->bs_sema |= BSC_DDONE; ! 350: bpsub->bs_sema &= ~BSC_DBUSY; ! 351: goto readexit; ! 352: } ! 353: ! 354: /* 3.3.4 If ERR, leave mode at Read, return -1(EIO) */ ! 355: if (bpsub->bs_flags & BS_ERR) { /* error way out */ ! 356: bp->b_hlflgs &= ~(BSC_XLAST|BSC_FULL|BSC_XTRN); ! 357: bpsub->bs_flags &= ~BS_FULL; ! 358: bpsub->bs_sema &= ~BSC_SEENBUF; ! 359: errcode = EIO; ! 360: goto readexit; ! 361: } ! 362: ! 363: /* 3.3.5 Buffer full. Copy data out, set length. */ ! 364: l = bp->b_bsize; /* buffer space occupied */ ! 365: if (l > UCOUNT) ! 366: l = UCOUNT; ! 367: if (l) ! 368: #if defined BSD42 ! 369: errcode = uiomove(bp->b_buffer,l,UIO_READ,uio); ! 370: #else ! 371: if (iomove (bp->b_buffer, l, B_READ)) ! 372: errcode = EFAULT; ! 373: #endif ! 374: ! 375: if (bpsub->bs_sema & BSC_FACK) { ! 376: bpsub->bs_sema |= BSC_SEENBUF; ! 377: goto readret; ! 378: } ! 379: ! 380: /* 4. Mark buffer empty, awaken psm if its sleeping */ ! 381: readexit: ! 382: bpsub->bs_flags &= ~BS_FULL; ! 383: bp->b_hlflgs &= ~BSC_FULL; /* mark buffer empty */ ! 384: x = spl8(); ! 385: if (states[bp->b_state].s_type == 'd' && ! 386: bp->b_alenb) { ! 387: bp->b_alenb = 0; /* disable alarm */ ! 388: splx(x); ! 389: bscpsm(bscdev); /* awaken psm */ ! 390: } else splx(x); ! 391: } ! 392: readret: ! 393: #if defined BSD42 ! 394: return errcode; ! 395: #else ! 396: if (errcode) ! 397: u.u_error = errcode; ! 398: #endif ! 399: } ! 400: ! 401: /* ! 402: * bsmwrite -- 1) if user's length = 0 or > max block, error ! 403: * 2) if mode = read, or if error latch set, error! ! 404: * 3) if mode = init, prime the driver ! 405: * 4) if mode = idle, init, or write, ! 406: * a) set mode to write, ! 407: * b) wait till buffer empty, ! 408: * c) fill the buffer, ! 409: * d) set flag to show buffer full. ! 410: * ** The psm will reset the mode to idle after sending EOT. ! 411: */ ! 412: #if defined BSD42 ! 413: bsmwrite(dev,uio) ! 414: register dev_t dev; ! 415: struct uio *uio; ! 416: #else ! 417: bsmwrite(dev) ! 418: register dev_t dev; ! 419: #endif ! 420: { ! 421: register int l; /* length given us */ ! 422: register struct bsc *bp; /* ptr to bsc dev info */ ! 423: register struct bscsub *bpsub; /* ptr to bsc prot dev */ ! 424: register int subdev; ! 425: register dev_t bscdev; ! 426: int x; /* prty save area */ ! 427: int errcode = 0; /* Error code to be returned */ ! 428: ! 429: subdev = SUBDEV(dev); ! 430: bscdev = DEV(dev); ! 431: bp = &bsc[bscdev]; ! 432: bpsub = &bscsubs[bscdev][subdev]; ! 433: ! 434: /* 0. Check error latch and DSR */ ! 435: if ((bpsub->bs_flags & BS_ERR) || !(bp->b_hlflgs & BSC_DSR)) { ! 436: if (!(bpsub->bs_flags & BS_ERR)) { ! 437: bpsub->bs_flags |= BS_ERR; ! 438: bpsub->bs_err = BSCNDSR; ! 439: } ! 440: ERRRET(EIO); ! 441: } ! 442: ! 443: /* 1. Check length and other errors */ ! 444: if ( (l = UCOUNT) == 0 || l > bp->b_iocin.b_blks) { ! 445: ERRRET(EINVAL); ! 446: } ! 447: ! 448: if (bp->b_mode == BSC_INIT) { ! 449: bscsetup(bscdev); ! 450: bp->b_mode = BSC_IDLE; ! 451: } ! 452: ! 453: /* 2. process according to mode */ ! 454: switch (bpsub->bs_mode) ! 455: { ! 456: case BS_READ: ! 457: if ((bpsub->bs_sema & BSC_FACK) && ! 458: (bpsub->bs_sema & BSC_SEENBUF)) { ! 459: bpsub->bs_flags &= ~BS_FULL; ! 460: bpsub->bs_sema &= ~BSC_SEENBUF; ! 461: bpsub->bs_mode = BS_WRITE; ! 462: goto casewrite; ! 463: } ! 464: if (bpsub->bs_rdflg == 0) { ! 465: ERRRET(EINVAL); /* oops - can't read now! */ ! 466: } else { ! 467: bpsub->bs_sema &= ~BSC_DBUSY; ! 468: bpsub->bs_sema |= BSC_DDONE; ! 469: bpsub->bs_rdflg = 1; ! 470: while (bpsub->bs_mode == BS_READ && ! 471: !(bpsub->bs_flags & BS_ERR)) ! 472: delay(PSMTICK); ! 473: } ! 474: bpsub->bs_mode = BS_IDLE; ! 475: ! 476: case BS_IDLE: ! 477: if (bpsub->bs_flags & BS_FULL) { ! 478: ERRRET(EINVAL); /* Caller needs to read */ ! 479: } ! 480: while (!(bpsub->bs_sema & BSC_PDONE) && ! 481: !(bpsub->bs_flags & BS_ERR)) ! 482: delay(PSMTICK); /* Synchronize */ ! 483: bpsub->bs_mode = BS_WRITE; ! 484: bpsub->bs_flags &= ~BS_ERR; /* reset possible err */ ! 485: bpsub->bs_sema |= BSC_DBUSY; ! 486: bpsub->bs_sema &= ~BSC_DDONE; /* driver now busy */ ! 487: ! 488: casewrite: ! 489: case BS_WRITE: ! 490: x = spl8(); ! 491: while ((bpsub->bs_flags & BS_FULL) && /*wait til empty */ ! 492: (!(bpsub->bs_flags & BS_ERR))) ! 493: sleep ((caddr_t)&bpsub->bs_flags,BSCPRI); ! 494: splx(x); ! 495: ! 496: if (bpsub->bs_flags & BS_ERR){ ! 497: bp->b_hlflgs &= ~(BSC_FULL|BSC_XLAST|BSC_XTRN); ! 498: bpsub->bs_flags &= ~(BS_FULL|BS_LAST|BSC_XTRN); ! 499: bpsub->bs_mode = BS_IDLE; ! 500: ERRRET(EIO); ! 501: } ! 502: ! 503: /* copy data to buffer */ ! 504: #if defined BSD42 ! 505: errcode = uiomove(bpsub->bs_buf,l,UIO_WRITE,uio); ! 506: #else ! 507: if (iomove (bpsub->bs_buf, l, B_WRITE)) ! 508: errcode = EFAULT; ! 509: #endif ! 510: ! 511: bpsub->bs_size = l; /*save size */ ! 512: ! 513: x = spl8(); ! 514: bpsub->bs_flags |= BS_FULL; /* bufr now full */ ! 515: if (states[bp->b_state].s_type == 'd' && ! 516: bp->b_alenb) { /* decision wait? */ ! 517: bp->b_alenb = 0; /* disable pto */ ! 518: splx(x); ! 519: bscpsm(bscdev); /* wake 'em up */ ! 520: } else splx(x); ! 521: ! 522: if (bpsub->bs_flags & BS_LAST) { /* if last block, wait */ ! 523: x = spl8(); ! 524: while ((bpsub->bs_flags & BS_FULL) && /*wait til empty*/ ! 525: (!(bpsub->bs_flags & BS_ERR))) /*no error*/ ! 526: sleep ((caddr_t)&bpsub->bs_flags, BSCPRI); ! 527: splx(x); ! 528: if (bpsub->bs_flags & BS_ERR){ ! 529: errcode = EIO; ! 530: } else { ! 531: bpsub->bs_sema |= BSC_DDONE; ! 532: bpsub->bs_sema &= ~BSC_DBUSY; ! 533: bpsub->bs_mode = BS_IDLE; ! 534: } ! 535: bp->b_hlflgs &= ~(BSC_XLAST|BSC_FULL|BSC_XTRN); ! 536: bpsub->bs_flags &= ~(BS_LAST|BS_FULL|BSC_XTRN); ! 537: } ! 538: } ! 539: #if defined BSD42 ! 540: return errcode; ! 541: #else ! 542: if (errcode) ! 543: u.u_error = errcode; ! 544: #endif ! 545: } ! 546: ! 547: /* bsmioctl -- set options or get counter values ! 548: * Depending on cmd: ! 549: * BSCGET - copy b_iocout to user's area ! 550: * BSCSET - copy user's values to b_iocin (set stuff) ! 551: * BSCTRNSP - set transparent mode flag ! 552: * BSCNTRNS - reset transparent mode flag ! 553: * BSCSOH - set send SOH flag ! 554: * BSCNSOH - turn off SOH flag ! 555: * BSCLAST - set send last flag ! 556: * BSCID - determine port id number ! 557: */ ! 558: ! 559: /*VARARGS3*/ ! 560: bsmioctl(dev, cmd, arg) ! 561: dev_t dev; ! 562: struct bscio *arg; ! 563: { ! 564: register struct bsc *bp; /* ptr to dev info */ ! 565: register struct bscsub *bpsub; /* ptr to port info */ ! 566: struct bscio tmp; /* temp struct for chk'g user params*/ ! 567: register int x; ! 568: register int subdev; ! 569: register dev_t bscdev; ! 570: int y,errcode = 0; ! 571: ! 572: dev = minor(dev); ! 573: subdev = SUBDEV(dev); ! 574: bscdev = DEV(dev); ! 575: bp = &bsc[bscdev]; ! 576: bpsub = &bscsubs[bscdev][subdev]; ! 577: if (cmd != BSCGET && cmd != BSCSET) { /* if write op, wait on buf */ ! 578: x = spl8(); ! 579: while (bpsub->bs_mode == BS_WRITE && bpsub->bs_flags & BS_FULL) ! 580: sleep ((caddr_t)&bpsub->bs_flags, BSCPRI); ! 581: splx(x); ! 582: } ! 583: ! 584: if ((cmd == BSCSET) && (bp->b_lock != 1)) {/* only 1st can set modes */ ! 585: ERRRET(EINVAL); ! 586: } ! 587: switch (cmd) { ! 588: case BSCGET: ! 589: x = spl8(); ! 590: bp->b_iocout.b_flags = bpsub->bs_err; ! 591: #if defined BSD42 ! 592: bcopy((caddr_t)&bp->b_iocout, arg, sizeof bp->b_iocout); ! 593: #else ! 594: if (copyout(&bp->b_iocout, arg, sizeof bp->b_iocout)) ! 595: errcode = EFAULT; ! 596: #endif ! 597: bpsub->bs_err = 0; ! 598: bp->b_iocout.b_flags = 0; ! 599: if (bpsub->bs_flags & BS_ERR) { ! 600: bpsub->bs_flags &= ~(BS_ERR|BS_LAST|BS_FULL|BSC_XTRN); ! 601: bpsub->bs_sema &= ~BSC_DBUSY; ! 602: bpsub->bs_sema |= BSC_DDONE; ! 603: bpsub->bs_mode = BS_IDLE; ! 604: } ! 605: splx(x); ! 606: break; ! 607: ! 608: case BSCSET: ! 609: if (bpsub->bs_mode == BS_READ || bpsub->bs_mode == BS_WRITE) { ! 610: errcode = EINVAL; /* can't set if active */ ! 611: break; ! 612: } ! 613: #if defined BSD42 ! 614: bcopy(arg, (caddr_t)&tmp, sizeof tmp); ! 615: #else ! 616: if (copyin (arg, &tmp, sizeof tmp)) { ! 617: errcode = EFAULT; ! 618: break; ! 619: } ! 620: #endif ! 621: if (tmp.b_blks > BSCMBLK || /* block size too big? */ ! 622: tmp.b_blks > sizeof bpsub->bs_buf) { ! 623: errcode = EINVAL; ! 624: break; ! 625: } ! 626: bcopy (/*from*/&tmp, /*to*/&bp->b_iocin, sizeof tmp); ! 627: x = spl8(); /* *** protect hlflgs */ ! 628: bp->b_hlflgs &= ~BSC_UFLAGS; /* throw out old user flags */ ! 629: bp->b_hlflgs |= (BSCMPT|(tmp.b_flags & BSC_UFLAGS)); ! 630: splx(x); /* *** end protection */ ! 631: bscparam(bscdev); /* redo parameters */ ! 632: break; ! 633: ! 634: case BSCTRNSP: ! 635: x = spl8(); /* *** protect bsflgs */ ! 636: bpsub->bs_flags |= BSC_XTRN; /* set transparent mode */ ! 637: splx(x); /* *** end protection */ ! 638: break; ! 639: ! 640: case BSCNTRNS: ! 641: x = spl8(); /* *** protect bsflgs */ ! 642: bpsub->bs_flags &= ~BSC_XTRN; /* reset transp. mode */ ! 643: splx(x); /* *** end protection */ ! 644: break; ! 645: ! 646: case BSCSOH: ! 647: x = spl8(); /* *** protect bsflags */ ! 648: bpsub->bs_flags |= BSC_XSOH; /* set send SOH flag */ ! 649: splx(x); /* *** end protection */ ! 650: break; ! 651: ! 652: case BSCNSOH: ! 653: x = spl8(); /* *** protect bsflags */ ! 654: bpsub->bs_flags &= ~BSC_XSOH; /* clear send SOH flag*/ ! 655: splx(x); /* end protection */ ! 656: break; ! 657: ! 658: case BSCLAST: ! 659: x = spl8(); /* *** protect bsflags */ ! 660: bpsub->bs_flags |= BS_LAST; /* set send last blk flag */ ! 661: splx(x); /* end protection */ ! 662: break; ! 663: ! 664: case BSCNDLY: ! 665: x = spl8(); /* protect bs flags */ ! 666: bpsub->bs_sema |= BSC_NDLY; ! 667: splx(x); ! 668: break; ! 669: ! 670: case BSCID: ! 671: y = ((bp->b_hlflgs & BSCASCII)?ascdev:ebcdev)[subdev]; ! 672: #if defined BSD42 ! 673: bcopy((caddr_t)&y, (int *)arg, sizeof y); ! 674: #else ! 675: copyout(&y,(int *)arg,sizeof y); ! 676: #endif ! 677: break; ! 678: ! 679: case BSCFACK: ! 680: x = spl8(); ! 681: bpsub->bs_sema |= BSC_FACK; ! 682: splx(x); ! 683: break; ! 684: ! 685: default: ! 686: errcode = EINVAL; ! 687: break; ! 688: } ! 689: #if defined BSD42 ! 690: return errcode; ! 691: #else ! 692: if (errcode) ! 693: u.u_error = errcode; ! 694: #endif ! 695: } ! 696: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.