1: /*
2: * Copyright (c) 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)ht.c 2.2 (2.11BSD GTE) 1/2/93
7: */
8:
9: /*
10: * TJU77/TWU77/TJE16/TWE16 tape driver
11: */
12: #include "ht.h"
13: #if NHT > 0
14: #include "param.h"
15: #include "buf.h"
16: #include "ioctl.h"
17: #include "conf.h"
18: #include "file.h"
19: #include "user.h"
20: #include "mtio.h"
21: #include "fs.h"
22: #include "htreg.h"
23: #include "systm.h"
24:
25: struct buf httab, chtbuf;
26: static short rh70; /* ht.c was ONLY user of B_RH70 and that bit
27: * was wanted for something else (B_LOCKED)
28: */
29: struct htdevice *HTADDR;
30:
31: #define INF 32760
32:
33: struct softc {
34: char sc_openf;
35: char sc_lastiow;
36: daddr_t sc_blkno;
37: daddr_t sc_nxrec;
38: u_short sc_erreg;
39: u_short sc_fsreg;
40: short sc_resid;
41: short sc_dens;
42: } tu_softc[NHT];
43:
44:
45: #define SIO 1
46: #define SSFOR 2
47: #define SSREV 3
48: #define SRETRY 4
49: #define SCOM 5
50: #define SOK 6
51:
52:
53: /* bits in minor device */
54: #define TUUNIT(dev) (minor(dev) & 03)
55: #define H_NOREWIND 004
56: #define H_1600BPI 010
57:
58: htattach(addr, unit)
59: register struct htdevice *addr;
60: {
61: /*
62: * This driver supports only one controller.
63: */
64: if (unit == 0) {
65: HTADDR = addr;
66: if (fioword(&(addr->htbae)) != -1)
67: rh70 = 1;
68: return(1);
69: }
70: return(0);
71: }
72:
73: htopen(dev, flag)
74: dev_t dev;
75: {
76: register ds;
77: register htunit = TUUNIT(dev);
78: register struct softc *sc = &tu_softc[htunit];
79: int olddens, dens;
80:
81: httab.b_flags |= B_TAPE;
82: if (!HTADDR || htunit >= NHT)
83: return(ENXIO);
84: if (sc->sc_openf)
85: return(EBUSY);
86: sc->sc_blkno = (daddr_t) 0;
87: sc->sc_nxrec = (daddr_t) INF;
88: sc->sc_lastiow = 0;
89: olddens = sc->sc_dens;
90: dens = sc->sc_dens =
91: ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|
92: HTTC_PDP11|htunit;
93: ds = htcommand(dev, HT_SENSE, 1);
94: sc->sc_dens = olddens;
95: if ((ds & HTFS_MOL) == 0) {
96: uprintf("tu%d: not online\n", htunit);
97: return(EIO);
98: }
99: if ((flag & FWRITE) && (ds & HTFS_WRL)) {
100: uprintf("tu%d: no write ring\n", htunit);
101: return(EIO);
102: }
103: if ((flag & FWRITE) && (ds & HTFS_BOT) == 0 &&
104: dens != sc->sc_dens) {
105: uprintf("tu%d: can't change density in mid-tape\n", htunit);
106: return (EIO);
107: }
108: sc->sc_openf = 1;
109: sc->sc_dens = dens;
110: return(0);
111: }
112:
113: htclose(dev, flag)
114: dev_t dev;
115: {
116: register struct softc *sc = &tu_softc[TUUNIT(dev)];
117:
118: if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) {
119: htcommand(dev, HT_WEOF, 1);
120: htcommand(dev, HT_WEOF, 1);
121: htcommand(dev, HT_SREV, 1);
122: }
123: if ((minor(dev) & H_NOREWIND) == 0)
124: htcommand(dev, HT_REW, 1);
125: sc->sc_openf = 0;
126: }
127:
128: /*ARGSUSED*/
129: htcommand(dev, com, count)
130: u_short count;
131: dev_t dev;
132: {
133: register s;
134: register struct buf *bp;
135:
136: bp = &chtbuf;
137: s = splbio();
138: while(bp->b_flags & B_BUSY) {
139: /*
140: * This special check is because B_BUSY never
141: * gets cleared in the non-waiting rewind case.
142: */
143: if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE))
144: break;
145: bp->b_flags |= B_WANTED;
146: sleep((caddr_t) bp, PRIBIO);
147: }
148: bp->b_flags = B_BUSY | B_READ;
149: splx(s);
150: bp->b_dev = dev;
151: if (com == HT_SFORW || com == HT_SREV)
152: bp->b_repcnt = count;
153: bp->b_command = com;
154: bp->b_blkno = (daddr_t) 0;
155: htstrategy(bp);
156: /*
157: * In case of rewind from close, don't wait.
158: * This is the only case where count can be 0.
159: */
160: if (count == 0)
161: return(0);
162: iowait(bp);
163: if(bp->b_flags & B_WANTED)
164: wakeup((caddr_t)bp);
165: bp->b_flags &= B_ERROR;
166: return (bp->b_resid);
167: }
168:
169: htstrategy(bp)
170: register struct buf *bp;
171: {
172: register int s;
173: register struct softc *sc = &tu_softc[TUUNIT(bp->b_dev)];
174:
175: if (rh70 == 0)
176: mapalloc(bp);
177: if (bp->b_flags & B_PHYS) {
178: sc->sc_blkno = sc->sc_nxrec = dbtofsb(bp->b_blkno);
179: sc->sc_nxrec++;
180: }
181: bp->av_forw = NULL;
182: s = splbio();
183: if (httab.b_actf == NULL)
184: httab.b_actf = bp;
185: else
186: httab.b_actl->av_forw = bp;
187: httab.b_actl = bp;
188: if (httab.b_active == 0)
189: htstart();
190: splx(s);
191: }
192:
193: htstart()
194: {
195: register struct buf *bp;
196: register den;
197: daddr_t blkno;
198: register struct softc *sc;
199:
200: loop:
201: if ((bp = httab.b_actf) == NULL)
202: return;
203: sc = &tu_softc[TUUNIT(bp->b_dev)];
204: sc->sc_erreg = HTADDR->hter;
205: sc->sc_fsreg = HTADDR->htfs;
206: sc->sc_resid = HTADDR->htfc;
207: HTADDR->htcs2 = 0; /* controller 0 - do we need this? */
208: if ((HTADDR->httc & 03777) != sc->sc_dens)
209: HTADDR->httc = sc->sc_dens;
210: sc->sc_lastiow = 0;
211: if (sc->sc_openf < 0 || HTADDR->htcs2 & HTCS2_NEF || !(HTADDR->htfs & HTFS_MOL))
212: goto abort;
213: if (bp == &chtbuf) {
214: if (bp->b_command == HT_SENSE) {
215: bp->b_resid = HTADDR->htfs;
216: goto next;
217: }
218: httab.b_active = SCOM;
219: HTADDR->htfc = 0;
220: HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO;
221: return;
222: }
223: if (dbtofsb(bp->b_blkno) > sc->sc_nxrec)
224: goto abort;
225: if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) {
226: /*
227: * Reading at end of file returns 0 bytes.
228: * Buffer will be cleared (if written) in rwip.
229: */
230: bp->b_resid = bp->b_bcount;
231: goto next;
232: }
233: if ((bp->b_flags & B_READ) == 0)
234: /*
235: * Writing sets EOF
236: */
237: sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
238: if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
239: httab.b_active = SIO;
240: HTADDR->htba = bp->b_un.b_addr;
241: if (rh70)
242: HTADDR->htbae = bp->b_xmem;
243: HTADDR->htfc = -bp->b_bcount;
244: HTADDR->htwc = -(bp->b_bcount >> 1);
245: den = ((bp->b_xmem & 3) << 8) | HT_IE | HT_GO;
246: if(bp->b_flags & B_READ)
247: den |= HT_RCOM;
248: else {
249: if(HTADDR->htfs & HTFS_EOT) {
250: bp->b_resid = bp->b_bcount;
251: bp->b_error = ENXIO;
252: httab.b_active = 0;
253: goto next;
254: }
255: den |= HT_WCOM;
256: }
257: HTADDR->htcs1 = den;
258: } else {
259: if (blkno < dbtofsb(bp->b_blkno)) {
260: httab.b_active = SSFOR;
261: HTADDR->htfc = blkno - dbtofsb(bp->b_blkno);
262: HTADDR->htcs1 = HT_SFORW | HT_IE | HT_GO;
263: } else {
264: httab.b_active = SSREV;
265: HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno;
266: HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO;
267: }
268: }
269: return;
270:
271: abort:
272: bp->b_flags |= B_ERROR;
273:
274: next:
275: httab.b_actf = bp->av_forw;
276: iodone(bp);
277: goto loop;
278: }
279:
280: htintr()
281: {
282: register struct buf *bp;
283: register state;
284: int err, htunit;
285: register struct softc *sc;
286:
287: if ((bp = httab.b_actf) == NULL)
288: return;
289: htunit = TUUNIT(bp->b_dev);
290: sc = &tu_softc[htunit];
291: sc->sc_erreg = HTADDR->hter;
292: sc->sc_fsreg = HTADDR->htfs;
293: sc->sc_resid = HTADDR->htfc;
294: if ((bp->b_flags & B_READ) == 0)
295: sc->sc_lastiow = 1;
296: state = httab.b_active;
297: httab.b_active = 0;
298: if (HTADDR->htcs1 & HT_TRE) {
299: err = HTADDR->hter;
300: if (HTADDR->htcs2 & HTCS2_ERR || (err & HTER_HARD))
301: state = 0;
302: if (bp->b_flags & B_PHYS)
303: err &= ~HTER_FCE;
304: if ((bp->b_flags & B_READ) && (HTADDR->htfs & HTFS_PES))
305: err &= ~(HTER_CSITM | HTER_CORCRC);
306: if ((HTADDR->htfs & HTFS_MOL) == 0) {
307: if(sc->sc_openf)
308: sc->sc_openf = -1;
309: }
310: else
311: if (HTADDR->htfs & HTFS_TM) {
312: HTADDR->htwc = -(bp->b_bcount >> 1);
313: sc->sc_nxrec = dbtofsb(bp->b_blkno);
314: state = SOK;
315: }
316: else
317: if (state && err == 0)
318: state = SOK;
319: if (httab.b_errcnt > 4)
320: printf("tu%d: hard error bn %D er=%b ds=%b\n",
321: htunit, bp->b_blkno,
322: sc->sc_erreg, HTER_BITS,
323: sc->sc_fsreg, HTFS_BITS);
324: htinit();
325: if (state == SIO && ++httab.b_errcnt < 10) {
326: httab.b_active = SRETRY;
327: sc->sc_blkno++;
328: HTADDR->htfc = -1;
329: HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO;
330: return;
331: }
332: if (state != SOK) {
333: bp->b_flags |= B_ERROR;
334: state = SIO;
335: }
336: } else
337: if (HTADDR->htcs1 & HT_SC)
338: if(HTADDR->htfs & HTFS_ERR)
339: htinit();
340:
341: switch (state) {
342: case SIO:
343: case SOK:
344: sc->sc_blkno++;
345:
346: case SCOM:
347: httab.b_errcnt = 0;
348: httab.b_actf = bp->av_forw;
349: iodone(bp);
350: bp->b_resid = -(HTADDR->htwc << 1);
351: break;
352:
353: case SRETRY:
354: if((bp->b_flags & B_READ) == 0) {
355: httab.b_active = SSFOR;
356: HTADDR->htcs1 = HT_ERASE | HT_IE | HT_GO;
357: return;
358: }
359:
360: case SSFOR:
361: case SSREV:
362: if(HTADDR->htfs & HTFS_TM) {
363: if(state == SSREV) {
364: sc->sc_nxrec = dbtofsb(bp->b_blkno) - HTADDR->htfc;
365: sc->sc_blkno = sc->sc_nxrec;
366: } else
367: {
368: sc->sc_nxrec = dbtofsb(bp->b_blkno) + HTADDR->htfc - 1;
369: sc->sc_blkno = sc->sc_nxrec + 1;
370: }
371: } else
372: sc->sc_blkno = dbtofsb(bp->b_blkno);
373: break;
374:
375: default:
376: return;
377: }
378: htstart();
379: }
380:
381: htinit()
382: {
383: register ocs2;
384: register omttc;
385:
386: omttc = HTADDR->httc & 03777; /* preserve old slave select, dens, format */
387: ocs2 = HTADDR->htcs2 & 07; /* preserve old unit */
388:
389: HTADDR->htcs2 = HTCS2_CLR;
390: HTADDR->htcs2 = ocs2;
391: HTADDR->httc = omttc;
392: HTADDR->htcs1 = HT_DCLR | HT_GO;
393: }
394:
395: /*ARGSUSED*/
396: htioctl(dev, cmd, data, flag)
397: dev_t dev;
398: u_int cmd;
399: caddr_t data;
400: int flag;
401: {
402: register struct buf *bp = &chtbuf;
403: register struct softc *sc = &tu_softc[minor(dev)&07];
404: register callcount;
405: int fcount;
406: struct mtop *mtop;
407: struct mtget *mtget;
408: /* we depend on the values and order of the MT codes here */
409: static htops[] = {HT_WEOF, HT_SFORW, HT_SREV, HT_SFORW,
410: HT_SREV, HT_REW, HT_REWOFFL, HT_SENSE};
411:
412: switch (cmd) {
413: case MTIOCTOP:
414: mtop = (struct mtop *)data;
415: switch (mtop->mt_op) {
416: case MTWEOF:
417: callcount = mtop->mt_count;
418: fcount = 1;
419: break;
420: case MTFSF: case MTBSF:
421: callcount = mtop->mt_count;
422: fcount = INF;
423: break;
424: case MTFSR: case MTBSR:
425: callcount = 1;
426: fcount = mtop->mt_count;
427: break;
428: case MTREW: case MTOFFL: case MTNOP:
429: callcount = 1;
430: fcount = 1;
431: break;
432: default:
433: return (ENXIO);
434: }
435: if (callcount <= 0 || fcount <= 0)
436: return (EINVAL);
437: while (--callcount >= 0) {
438: htcommand(dev, htops[mtop->mt_op], fcount);
439: if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) &&
440: bp->b_resid)
441: return (EIO);
442: if ((bp->b_flags&B_ERROR) || sc->sc_fsreg&HTFS_BOT)
443: break;
444: }
445: return (geterror(bp));
446: case MTIOCGET:
447: mtget = (struct mtget *)data;
448: mtget->mt_dsreg = sc->sc_fsreg;
449: mtget->mt_erreg = sc->sc_erreg;
450: mtget->mt_resid = sc->sc_resid;
451: mtget->mt_type = MT_ISHT;
452: break;
453: default:
454: return (ENXIO);
455: }
456: return (0);
457: }
458: #endif NHT
Defined functions
Defined variables
HTADDR
defined in line
29; used 48 times
- in line 65,
82,
204-220(11),
240-249(5),
257-266(5),
291-312(10),
328-329(2),
337-338(2),
350,
356,
362-368(3),
386-392(6)
httab
defined in line
25; used 22 times
- in line 81,
183-188(5),
201,
218,
239,
252,
260-264(2),
275,
287,
296-297(2),
319,
325-326(2),
347-348(2),
355
rh70
defined in line
26; used 3 times
Defined struct's
softc
defined in line
33; used 12 times
Defined macros
INF
defined in line
31; used 2 times
SCOM
defined in line
49; used 1 times
SIO
defined in line
45; used 3 times
SOK
defined in line
50; used 3 times
SSFOR
defined in line
46; used 2 times
SSREV
defined in line
47; used 2 times