Commit | Line | Data |
---|---|---|
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 | ||
15 | struct { | |
16 | int tmer; | |
17 | int tmcs; | |
18 | int tmbc; | |
19 | int tmba; | |
20 | int tmdb; | |
21 | int tmrd; | |
22 | }; | |
23 | ||
24 | struct devtab tmtab; | |
25 | struct buf rtmbuf; | |
26 | ||
27 | char t_openf[8]; | |
28 | char *t_blkno[8]; | |
29 | char *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 | ||
52 | tmopen(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 | ||
66 | tmclose(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 | ||
77 | tcommand(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 | ||
86 | tmstrategy(abp) | |
87 | struct 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 | ||
120 | tmstart() | |
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 | ||
162 | tmintr() | |
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 | ||
200 | tmread(dev) | |
201 | { | |
202 | tmphys(dev); | |
203 | physio(tmstrategy, &rtmbuf, dev, B_READ); | |
204 | u.u_count = -rtmbuf.b_resid; | |
205 | } | |
206 | ||
207 | tmwrite(dev) | |
208 | { | |
209 | tmphys(dev); | |
210 | physio(tmstrategy, &rtmbuf, dev, B_WRITE); | |
211 | u.u_count = 0; | |
212 | } | |
213 | ||
214 | tmphys(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 | } |