SC11 > 0 rather than ifdef SC11
[unix-history] / usr / src / sys / vax / mba / ht.c
CommitLineData
f0a3ddbd 1/* ht.c 4.3 %G% */
786dff00 2
a5cc519e
BJ
3#include "../conf/ht.h"
4#if NHT > 0
786dff00
BJ
5/*
6 * TJU16 tape driver
7 */
8
9#include "../h/param.h"
10#include "../h/systm.h"
11#include "../h/buf.h"
12#include "../h/conf.h"
13#include "../h/dir.h"
14#include "../h/file.h"
15#include "../h/user.h"
16#include "../h/map.h"
80e7c811 17#include "../h/pte.h"
786dff00 18#include "../h/mba.h"
f0a3ddbd
BJ
19#include "../h/vm.h"
20#include "../h/cmap.h"
786dff00
BJ
21
22struct device
23{
24 int htcs1;
25 int htds;
26 int hter;
27 int htmr;
28 int htas;
29 int htfc;
30 int htdt;
31 int htck;
32 int htsn;
33 int httc;
34};
35
36struct buf httab;
37struct buf rhtbuf;
38struct buf chtbuf;
39
786dff00
BJ
40#define INF 1000000
41
a5cc519e
BJ
42char h_openf[NHT];
43daddr_t h_blkno[NHT];
44char h_flags[NHT];
45daddr_t h_nxrec[NHT];
786dff00
BJ
46
47#define GO 01
48#define WCOM 060
49#define RCOM 070
50#define NOP 0
51#define WEOF 026
52#define SFORW 030
53#define SREV 032
54#define ERASE 024
55#define REW 06
56#define DCLR 010
57#define P800 01700 /* 800 + pdp11 mode */
58#define P1600 02300 /* 1600 + pdp11 mode */
59#define IENABLE 0100
60#define RDY 0200
61#define TM 04
62#define DRY 0200
63#define EOT 02000
64#define CS 02000
65#define COR 0100000
66#define PES 040
67#define WRL 04000
68#define MOL 010000
69#define ERR 040000
70#define FCE 01000
71#define TRE 040000
72#define HARD 064023 /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */
73
74#define SIO 1
75#define SSFOR 2
76#define SSREV 3
77#define SRETRY 4
78#define SCOM 5
79#define SOK 6
80
81#define H_WRITTEN 1
82
83htopen(dev, flag)
84{
85 register unit, ds;
86
80e7c811
BJ
87 if ((mbaact&(1<<HTMBANUM)) == 0)
88 mbainit(HTMBANUM);
786dff00
BJ
89 httab.b_flags |= B_TAPE;
90 unit = minor(dev) & 03;
a5cc519e 91 if (unit >= NHT || h_openf[unit]) {
786dff00
BJ
92 u.u_error = ENXIO;
93 return;
94 }
95 h_blkno[unit] = 0;
96 h_nxrec[unit] = INF;
97 h_flags[unit] = 0;
98 ds = hcommand(dev, NOP);
99 if ((ds&MOL)==0 || (flag && (ds&WRL)))
100 u.u_error = ENXIO;
101 if (u.u_error==0)
102 h_openf[unit]++;
103}
104
105htclose(dev, flag)
106{
107 register int unit;
108
109 unit = minor(dev) & 03;
110 if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) {
81263dba
BJ
111 (void) hcommand(dev, WEOF);
112 (void) hcommand(dev, WEOF);
113 (void) hcommand(dev, SREV);
786dff00 114 }
786dff00 115 if((minor(dev)&4) == 0) /* no 4 -> rewind */
81263dba 116 (void) hcommand(dev, REW);
786dff00
BJ
117 h_openf[unit] = 0;
118}
119
120hcommand(dev, com)
121{
122 register struct buf *bp;
123
124 bp = &chtbuf;
81263dba 125 (void) spl5();
786dff00
BJ
126 while(bp->b_flags&B_BUSY) {
127 bp->b_flags |= B_WANTED;
128 sleep((caddr_t)bp, PRIBIO);
129 }
81263dba 130 (void) spl0();
786dff00
BJ
131 bp->b_dev = dev;
132 bp->b_resid = com;
133 bp->b_blkno = 0;
134 bp->b_flags = B_BUSY|B_READ;
135 htstrategy(bp);
136 iowait(bp);
137 if(bp->b_flags&B_WANTED)
138 wakeup((caddr_t)bp);
139 bp->b_flags = 0;
140 return(bp->b_resid);
141}
142
143htstrategy(bp)
144register struct buf *bp;
145{
146 register daddr_t *p;
147
148 if(bp != &chtbuf) {
149 p = &h_nxrec[minor(bp->b_dev)&03];
150 if(dbtofsb(bp->b_blkno) > *p) {
151 bp->b_flags |= B_ERROR;
152 bp->b_error = ENXIO;
153 iodone(bp);
154 return;
155 }
156 if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) {
157 bp->b_resid = bp->b_bcount;
158 clrbuf(bp);
159 iodone(bp);
160 return;
161 }
162 if ((bp->b_flags&B_READ)==0) {
163 *p = dbtofsb(bp->b_blkno) + 1;
164 h_flags[minor(bp->b_dev)&03] |= H_WRITTEN;
165 }
166 }
167 bp->av_forw = NULL;
81263dba 168 (void) spl5();
786dff00
BJ
169 if (httab.b_actf == NULL)
170 httab.b_actf = bp;
171 else
172 httab.b_actl->av_forw = bp;
173 httab.b_actl = bp;
174 if (httab.b_active==0)
175 htstart();
81263dba 176 (void) spl0();
786dff00
BJ
177}
178
179htstart()
180{
181 register struct buf *bp;
182 register unit, den;
183 daddr_t blkno;
80e7c811 184 register struct device *htp = mbadev(HTMBA,0);
786dff00
BJ
185
186 loop:
187 if ((bp = httab.b_actf) == NULL)
188 return;
189 unit = minor(bp->b_dev);
190 den = P800 | (unit&03);
191 if(unit >= 8)
192 den = P1600 | (unit&03);
80e7c811
BJ
193 if((htp->httc&03777) != den)
194 htp->httc = den;
786dff00
BJ
195 unit &= 03;
196 blkno = h_blkno[unit];
197 if (bp == &chtbuf) {
198 if (bp->b_resid==NOP) {
80e7c811 199 bp->b_resid = htp->htds & 0xffff;
786dff00
BJ
200 goto next;
201 }
202 httab.b_active = SCOM;
80e7c811
BJ
203 htp->htfc = 0;
204 htp->htcs1 = bp->b_resid|GO;
786dff00
BJ
205 return;
206 }
207 if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit])
208 goto abort;
209 if (blkno == dbtofsb(bp->b_blkno)) {
210 httab.b_active = SIO;
80e7c811
BJ
211 htp->htfc = -bp->b_bcount;
212 mbastart(bp, (int *)htp);
786dff00
BJ
213 } else {
214 if (blkno < dbtofsb(bp->b_blkno)) {
215 httab.b_active = SSFOR;
80e7c811
BJ
216 htp->htfc = blkno - dbtofsb(bp->b_blkno);
217 htp->htcs1 = SFORW|GO;
786dff00
BJ
218 } else {
219 httab.b_active = SSREV;
80e7c811
BJ
220 htp->htfc = dbtofsb(bp->b_blkno) - blkno;
221 htp->htcs1 = SREV|GO;
786dff00
BJ
222 }
223 }
224 return;
225
226 abort:
227 bp->b_flags |= B_ERROR;
228
229 next:
230 httab.b_actf = bp->av_forw;
231 iodone(bp);
232 goto loop;
233}
234
235/*ARGSUSED*/
236htintr(mbastat, as)
237{
238 register struct buf *bp;
239 register int unit, state;
240 int err;
80e7c811 241 register struct device *htp = mbadev(HTMBA,0);
786dff00
BJ
242
243 if ((bp = httab.b_actf)==NULL)
244 return;
245 unit = minor(bp->b_dev) & 03;
246 state = httab.b_active;
247 httab.b_active = 0;
80e7c811
BJ
248 if (htp->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) {
249 err = htp->hter & 0xffff;
786dff00
BJ
250 if ((mbastat & MBAEBITS) || (err&HARD))
251 state = 0;
252 if (bp == &rhtbuf)
253 err &= ~FCE;
80e7c811 254 if ((bp->b_flags&B_READ) && (htp->htds&PES))
786dff00 255 err &= ~(CS|COR);
80e7c811 256 if(htp->htds&EOT || (htp->htds&MOL)==0) {
786dff00
BJ
257 if(h_openf[unit])
258 h_openf[unit] = -1;
259 }
80e7c811
BJ
260 else if(htp->htds&TM) {
261 htp->htfc = 0;
786dff00
BJ
262 h_nxrec[unit] = dbtofsb(bp->b_blkno);
263 state = SOK;
264 }
265 else if(state && err == 0)
266 state = SOK;
267 if(httab.b_errcnt > 4)
80e7c811
BJ
268 deverror(bp, htp->hter, mbastat);
269 HTMBA->mba_cr &= ~MBAIE;
270 htp->htcs1 = DCLR|GO;
271 HTMBA->mba_cr |= MBAIE;
786dff00
BJ
272 if (state==SIO && ++httab.b_errcnt < 10) {
273 httab.b_active = SRETRY;
274 h_blkno[unit]++;
80e7c811
BJ
275 htp->htfc = -1;
276 htp->htcs1 = SREV|GO;
786dff00
BJ
277 return;
278 }
279 if (state!=SOK) {
280 bp->b_flags |= B_ERROR;
281 state = SIO;
282 }
80e7c811
BJ
283 } else if (htp->htcs1 < 0) { /* SC */
284 if(htp->htds & ERR) {
285 HTMBA->mba_cr &= ~MBAIE;
286 htp->htcs1 = DCLR|GO;
287 HTMBA->mba_cr |= MBAIE;
786dff00
BJ
288 }
289 }
290 switch(state) {
291 case SIO:
292 case SOK:
293 h_blkno[unit]++;
294
295 case SCOM:
296 httab.b_errcnt = 0;
297 httab.b_actf = bp->av_forw;
80e7c811 298 bp->b_resid = - (htp->htfc & 0xffff);
786dff00
BJ
299 if (bp->b_flags & B_READ)
300 bp->b_resid += bp->b_bcount;
301 iodone(bp);
302 break;
303
304 case SRETRY:
305 if((bp->b_flags&B_READ)==0) {
306 httab.b_active = SSFOR;
80e7c811 307 htp->htcs1 = ERASE|GO;
786dff00
BJ
308 return;
309 }
310
311 case SSFOR:
312 case SSREV:
293c7069 313#define blk dbtofsb(bp->b_blkno)
80e7c811 314 if(htp->htds & TM) {
786dff00 315 if(state == SSREV) {
80e7c811 316 h_nxrec[unit] = blk - (htp->htfc&0xffff);
786dff00
BJ
317 h_blkno[unit] = h_nxrec[unit];
318 } else {
80e7c811
BJ
319 h_nxrec[unit] = blk + (htp->htfc&0xffff) - 1;
320 h_blkno[unit] = blk + (htp->htfc & 0xffff);
786dff00
BJ
321 }
322 } else
293c7069 323 h_blkno[unit] = blk;
786dff00 324 break;
f0a3ddbd 325#undef blk
786dff00
BJ
326
327 default:
328 return;
329 }
330 htstart();
331}
332
333htread(dev)
334{
335 htphys(dev);
336 physio(htstrategy, &rhtbuf, dev, B_READ, minphys);
337}
338
339htwrite(dev)
340{
341 htphys(dev);
342 physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys);
343}
344
345htphys(dev)
346{
347 register unit;
348 daddr_t a;
349
350 unit = minor(dev) & 03;
a5cc519e 351 if(unit < NHT) {
786dff00
BJ
352 a = u.u_offset >> 9;
353 h_blkno[unit] = dbtofsb(a);
354 h_nxrec[unit] = dbtofsb(a)+1;
355 }
356}
f0a3ddbd
BJ
357
358#define HTADDR ((struct device *)(HTPHYSMBA + 0x400))
359#define HTMAP ((struct pte *) (HTPHYSMBA + 0x800))
360
361#define DBSIZE 20
362
363twall(start, num)
364 char *start;
365 int num;
366{
367 int blk;
368
369 HTADDR->httc = P800; /* set 800 bpi mode */
370 HTADDR->htcs1 = DCLR | GO;
371 while (num > 0) {
372 blk = num > DBSIZE ? DBSIZE : num;
373 twrite(start, blk);
374 start += blk*NBPG;
375 num -= blk;
376 }
377}
378
379twrite(buf, num)
380char *buf;
381{
382 register struct pte *hpte = HTMAP;
383 register int i;
384
385 twait();
386 HTADDR->htfc = -(num*NBPG);
387 for (i = 0; i < num; i++)
388 *(int *)hpte++ = (btop(buf)+i) | PG_V;
389 ((struct mba_regs *)PHYSMBA1)->mba_sr = -1;
390 ((struct mba_regs *)PHYSMBA1)->mba_bcr = -(num*NBPG);
391 ((struct mba_regs *)PHYSMBA1)->mba_var = 0;
392 HTADDR->htcs1 = WCOM | GO;
393}
394
395twait()
396{
397 register s;
398
399 do
400 s = HTADDR->htds;
401 while ((s & RDY) == 0);
402}
403
404rewind()
405{
406
407 twait();
408 HTADDR->htcs1 = REW | GO;
409}
410
411teof()
412{
413
414 twait();
415 HTADDR->htcs1 = WEOF | GO;
416}
a5cc519e 417#endif