Research V5 development
[unix-history] / usr / sys / dmr / tm.c
CommitLineData
b49e078f
DR
1#
2/*
3 * Copyright 1973 Bell Telephone Laboratories Inc
4 */
5
6/*
7 * TM tape driver
8 */
9
10#include "../param.h"
11#include "../buf.h"
12#include "../conf.h"
13#include "../user.h"
14
15struct {
16 int tmer;
17 int tmcs;
18 int tmbc;
19 int tmba;
20 int tmdb;
21 int tmrd;
22};
23
24struct devtab tmtab;
25struct buf rtmbuf;
26
27char t_openf[8];
28char *t_blkno[8];
29char *t_nxrec[8];
30
31#define TMADDR 0172520
32
33#define GO 01
34#define RCOM 02
35#define WCOM 04
36#define WEOF 06
37#define SFORW 010
38#define SREV 012
39#define WIRG 014
40#define REW 016
41#define DENS 060000 /* 9-channel */
42#define IENABLE 0100
43#define CRDY 0200
44#define GAPSD 010000
45#define TUR 1
46#define HARD 0102200 /* ILC, EOT, NXM */
47#define EOF 0040000
48
49#define SSEEK 1
50#define SIO 2
51
52tmopen(dev, flag)
53{
54 register dminor;
55
56 dminor = dev.d_minor;
57 if (t_openf[dminor])
58 u.u_error = ENXIO;
59 else {
60 t_openf[dminor]++;
61 t_blkno[dminor] = 0;
62 t_nxrec[dminor] = 65535;
63 }
64}
65
66tmclose(dev, flag)
67{
68 register int dminor;
69
70 dminor = dev.d_minor;
71 t_openf[dminor] = 0;
72 if (flag)
73 tcommand(dminor, WEOF);
74 tcommand(dminor, REW);
75}
76
77tcommand(unit, com)
78{
79 extern lbolt;
80
81 while (tmtab.d_active || (TMADDR->tmcs & CRDY)==0)
82 sleep(&lbolt, 1);
83 TMADDR->tmcs = DENS|com|GO | (unit<<8);
84}
85
86tmstrategy(abp)
87struct buf *abp;
88{
89 register struct buf *bp;
90 register char **p;
91
92 bp = abp;
93 p = &t_nxrec[bp->b_dev.d_minor];
94 if (*p <= bp->b_blkno) {
95 if (*p < bp->b_blkno) {
96 bp->b_flags =| B_ERROR;
97 iodone(bp);
98 return;
99 }
100 if (bp->b_flags&B_READ) {
101 clrbuf(bp);
102 iodone(bp);
103 return;
104 }
105 }
106 if ((bp->b_flags&B_READ)==0)
107 *p = bp->b_blkno + 1;
108 bp->av_forw = 0;
109 spl5();
110 if (tmtab.d_actf==0)
111 tmtab.d_actf = bp;
112 else
113 tmtab.d_actl->av_forw = bp;
114 tmtab.d_actl = bp;
115 if (tmtab.d_active==0)
116 tmstart();
117 spl0();
118}
119
120tmstart()
121{
122 register struct buf *bp;
123 register int com;
124 int unit;
125 register char *blkno;
126
127 loop:
128 if ((bp = tmtab.d_actf) == 0)
129 return;
130 unit = bp->b_dev.d_minor;
131 blkno = t_blkno[unit];
132 if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY)==0) {
133 bp->b_flags =| B_ERROR;
134 tmtab.d_actf = bp->av_forw;
135 iodone(bp);
136 goto loop;
137 }
138 com = (unit<<8) | (bp->b_flags&B_XMEM) | IENABLE|DENS;
139 if (blkno != bp->b_blkno) {
140 tmtab.d_active = SSEEK;
141 if (blkno < bp->b_blkno) {
142 com =| SFORW|GO;
143 TMADDR->tmbc = blkno - bp->b_blkno;
144 } else {
145 if (bp->b_blkno == 0)
146 com =| REW|GO;
147 else {
148 com =| SREV|GO;
149 TMADDR->tmbc = bp->b_blkno - blkno;
150 }
151 }
152 TMADDR->tmcs = com;
153 return;
154 }
155 tmtab.d_active = SIO;
156 TMADDR->tmbc = bp->b_wcount << 1;
157 TMADDR->tmba = bp->b_addr; /* core address */
158 TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO:
159 ((tmtab.d_errcnt)? WIRG|GO: WCOM|GO));
160}
161
162tmintr()
163{
164 register struct buf *bp;
165 register int unit;
166
167 if ((bp = tmtab.d_actf)==0)
168 return;
169 unit = bp->b_dev.d_minor;
170 if (TMADDR->tmcs < 0) { /* error bit */
171/*
172 deverror(bp, TMADDR->tmer);
173 */
174 while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */
175 if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) {
176 if (++tmtab.d_errcnt < 10) {
177 t_blkno[unit]++;
178 tmtab.d_active = 0;
179 tmstart();
180 return;
181 }
182 } else
183 if(bp != &rtmbuf && (TMADDR->tmer&EOF)==0)
184 t_openf[unit] = -1;
185 bp->b_flags =| B_ERROR;
186 tmtab.d_active = SIO;
187 }
188 if (tmtab.d_active == SIO) {
189 tmtab.d_errcnt = 0;
190 t_blkno[unit]++;
191 tmtab.d_actf = bp->av_forw;
192 tmtab.d_active = 0;
193 iodone(bp);
194 bp->b_resid = TMADDR->tmbc;
195 } else
196 t_blkno[unit] = bp->b_blkno;
197 tmstart();
198}
199
200tmread(dev)
201{
202 tmphys(dev);
203 physio(tmstrategy, &rtmbuf, dev, B_READ);
204 u.u_count = -rtmbuf.b_resid;
205}
206
207tmwrite(dev)
208{
209 tmphys(dev);
210 physio(tmstrategy, &rtmbuf, dev, B_WRITE);
211 u.u_count = 0;
212}
213
214tmphys(dev)
215{
216 register unit, a;
217
218 unit = dev.d_minor;
219 a = lshift(u.u_offset, -9);
220 t_blkno[unit] = a;
221 t_nxrec[unit] = ++a;
222}