|
|
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.