merge in onyx changes
[unix-history] / usr / src / sys / vax / uba / tm.c
CommitLineData
89bd2f01 1/* tm.c 4.23 %G% */
d75e5c3e 2
443c8066 3#include "te.h"
afb907f2 4#if NTM > 0
d1330646 5int tmgapsdcnt; /* DEBUG */
d75e5c3e 6/*
afb907f2 7 * TM11/TE10 tape driver
7e00c42b 8 *
80905075
BJ
9 * Todo:
10 * Test driver with more than one slave
11 * Test reset code
12 * Do rewinds without hanging in driver
d75e5c3e 13 */
7e00c42b 14#define DELAY(N) { register int d = N; while (--d > 0); }
d75e5c3e
BJ
15#include "../h/param.h"
16#include "../h/buf.h"
17#include "../h/dir.h"
18#include "../h/conf.h"
19#include "../h/user.h"
20#include "../h/file.h"
21#include "../h/map.h"
22#include "../h/pte.h"
e4271c68 23#include "../h/vm.h"
89bd2f01
BJ
24#include "../h/ubareg.h"
25#include "../h/ubavar.h"
d75e5c3e
BJ
26#include "../h/mtio.h"
27#include "../h/ioctl.h"
7455bf3e 28#include "../h/cmap.h"
3f3a34c3 29#include "../h/cpu.h"
d75e5c3e 30
3f3a34c3 31#include "../h/tmreg.h"
d75e5c3e 32
afb907f2
BJ
33struct buf ctmbuf[NTE];
34struct buf rtmbuf[NTE];
d75e5c3e 35
71236e46 36int tmprobe(), tmslave(), tmattach(), tmdgo(), tmintr();
89bd2f01
BJ
37struct uba_ctlr *tmminfo[NTM];
38struct uba_device *tmdinfo[NTE];
afb907f2 39struct buf tmutab[NTE];
71236e46 40#ifdef notyet
89bd2f01 41struct uba_device *tmip[NTM][4];
71236e46 42#endif
d763a2b7 43u_short tmstd[] = { 0772520, 0 };
3f3a34c3 44struct uba_driver tmdriver =
afb907f2 45 { tmprobe, tmslave, tmattach, tmdgo, tmstd, "te", tmdinfo, "tm", tmminfo, 0 };
d75e5c3e
BJ
46
47/* bits in minor device */
71236e46 48#define TMUNIT(dev) (minor(dev)&03)
d75e5c3e
BJ
49#define T_NOREWIND 04
50#define T_1600BPI 08
51
52#define INF (daddr_t)1000000L
53
71236e46
BJ
54/*
55 * Software state per tape transport.
56 */
7e00c42b 57struct tm_softc {
71236e46
BJ
58 char sc_openf; /* lock against multiple opens */
59 char sc_lastiow; /* last op was a write */
60 daddr_t sc_blkno; /* block number, for block device tape */
61 daddr_t sc_nxrec; /* desired block position */
62 u_short sc_erreg; /* copy of last erreg */
63 u_short sc_dsreg; /* copy of last dsreg */
64 short sc_resid; /* copy of last bc */
80905075 65#ifdef notdef
d1330646 66 short sc_lastcmd; /* last command to handle direction changes */
80905075 67#endif
afb907f2 68} tm_softc[NTM];
d75e5c3e 69
71236e46
BJ
70/*
71 * States for um->um_tab.b_active, the
72 * per controller state flag.
73 */
d75e5c3e
BJ
74#define SSEEK 1 /* seeking */
75#define SIO 2 /* doing seq i/o */
76#define SCOM 3 /* sending control command */
71236e46 77#define SREW 4 /* sending a drive rewind */
d75e5c3e 78
71236e46
BJ
79/* WE CURRENTLY HANDLE REWINDS PRIMITIVELY, BUSYING OUT THE CONTROLLER */
80/* DURING THE REWIND... IF WE EVER GET TWO TRANSPORTS, WE CAN DEBUG MORE */
81/* SOPHISTICATED LOGIC... THIS SIMPLE CODE AT LEAST MAY WORK. */
d75e5c3e 82
5aa9d5ea
RE
83/*
84 * Determine if there is a controller for
85 * a tm at address reg. Our goal is to make the
86 * device interrupt.
5aa9d5ea 87 */
71236e46 88tmprobe(reg)
3f3a34c3
BJ
89 caddr_t reg;
90{
d763a2b7 91 register int br, cvec;
5aa9d5ea 92
71236e46
BJ
93#ifdef lint
94 br = 0; br = cvec; cvec = br;
95#endif
96 ((struct device *)reg)->tmcs = TM_IE;
3f3a34c3 97 /*
afb907f2 98 * If this is a tm11, it ought to have interrupted
3f3a34c3 99 * by now, if it isn't (ie: it is a ts04) then we just
d763a2b7
BJ
100 * hope that it didn't interrupt, so autoconf will ignore it.
101 * Just in case, we will reference one
3f3a34c3 102 * of the more distant registers, and hope for a machine
d763a2b7 103 * check, or similar disaster if this is a ts.
7e00c42b
BJ
104 *
105 * Note: on an 11/780, badaddr will just generate
106 * a uba error for a ts; but our caller will notice that
107 * so we won't check for it.
3f3a34c3
BJ
108 */
109 if (badaddr(&((struct device *)reg)->tmrd, 2))
d763a2b7
BJ
110 return (0);
111 return (1);
3f3a34c3
BJ
112}
113
71236e46
BJ
114/*
115 * Due to a design flaw, we cannot ascertain if the tape
116 * exists or not unless it is on line - ie: unless a tape is
117 * mounted. This is too servere a restriction to bear,
118 * so all units are assumed to exist.
119 */
120/*ARGSUSED*/
e4271c68 121tmslave(ui, reg)
89bd2f01 122 struct uba_device *ui;
3f3a34c3
BJ
123 caddr_t reg;
124{
d763a2b7 125
d763a2b7 126 return (1);
3f3a34c3
BJ
127}
128
71236e46
BJ
129/*
130 * Record attachment of the unit to the controller port.
131 */
132/*ARGSUSED*/
133tmattach(ui)
89bd2f01 134 struct uba_device *ui;
71236e46
BJ
135{
136
137#ifdef notyet
138 tmip[ui->ui_ctlr][ui->ui_slave] = ui;
139#endif
140}
141
142/*
143 * Open the device. Tapes are unique open
144 * devices, so we refuse if it is already open.
145 * We also check that a tape is available, and
146 * don't block waiting here.
147 */
d75e5c3e
BJ
148tmopen(dev, flag)
149 dev_t dev;
150 int flag;
151{
71236e46 152 register int unit;
89bd2f01 153 register struct uba_device *ui;
71236e46 154 register struct tm_softc *sc;
d75e5c3e 155
71236e46 156 unit = TMUNIT(dev);
afb907f2 157 if (unit>=NTE || (sc = &tm_softc[unit])->sc_openf ||
71236e46
BJ
158 (ui = tmdinfo[unit]) == 0 || ui->ui_alive == 0) {
159 u.u_error = ENXIO;
d75e5c3e
BJ
160 return;
161 }
71236e46 162 tmcommand(dev, TM_SENSE, 1);
80905075
BJ
163 if ((sc->sc_erreg&(TM_SELR|TM_TUR)) != (TM_SELR|TM_TUR) ||
164 (flag&(FREAD|FWRITE)) == FWRITE && sc->sc_erreg&TM_WRL) {
71236e46 165 u.u_error = EIO;
d75e5c3e
BJ
166 return;
167 }
71236e46 168 sc->sc_openf = 1;
7e00c42b
BJ
169 sc->sc_blkno = (daddr_t)0;
170 sc->sc_nxrec = INF;
71236e46 171 sc->sc_lastiow = 0;
d75e5c3e
BJ
172}
173
71236e46
BJ
174/*
175 * Close tape device.
176 *
177 * If tape was open for writing or last operation was
178 * a write, then write two EOF's and backspace over the last one.
179 * Unless this is a non-rewinding special file, rewind the tape.
180 * Make the tape available to others.
181 */
d75e5c3e
BJ
182tmclose(dev, flag)
183 register dev_t dev;
184 register flag;
185{
71236e46 186 register struct tm_softc *sc = &tm_softc[TMUNIT(dev)];
d75e5c3e 187
71236e46
BJ
188 if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) {
189 tmcommand(dev, TM_WEOF, 1);
190 tmcommand(dev, TM_WEOF, 1);
191 tmcommand(dev, TM_SREV, 1);
d75e5c3e
BJ
192 }
193 if ((minor(dev)&T_NOREWIND) == 0)
71236e46 194 tmcommand(dev, TM_REW, 1);
7e00c42b 195 sc->sc_openf = 0;
d75e5c3e
BJ
196}
197
71236e46
BJ
198/*
199 * Execute a command on the tape drive
200 * a specified number of times.
201 */
e4271c68 202tmcommand(dev, com, count)
d75e5c3e
BJ
203 dev_t dev;
204 int com, count;
205{
206 register struct buf *bp;
207
71236e46 208 bp = &ctmbuf[TMUNIT(dev)];
d75e5c3e
BJ
209 (void) spl5();
210 while (bp->b_flags&B_BUSY) {
211 bp->b_flags |= B_WANTED;
212 sleep((caddr_t)bp, PRIBIO);
213 }
214 bp->b_flags = B_BUSY|B_READ;
215 (void) spl0();
216 bp->b_dev = dev;
217 bp->b_repcnt = -count;
218 bp->b_command = com;
219 bp->b_blkno = 0;
220 tmstrategy(bp);
221 iowait(bp);
222 if (bp->b_flags&B_WANTED)
223 wakeup((caddr_t)bp);
224 bp->b_flags &= B_ERROR;
225}
226
71236e46
BJ
227/*
228 * Decipher a tape operation and do what is needed
229 * to see that it happens.
230 */
d75e5c3e
BJ
231tmstrategy(bp)
232 register struct buf *bp;
233{
71236e46 234 int unit = TMUNIT(bp->b_dev);
89bd2f01 235 register struct uba_ctlr *um;
71236e46
BJ
236 register struct buf *dp;
237 register struct tm_softc *sc = &tm_softc[unit];
d75e5c3e 238
71236e46
BJ
239 /*
240 * Put transfer at end of unit queue
241 */
242 dp = &tmutab[unit];
d75e5c3e
BJ
243 bp->av_forw = NULL;
244 (void) spl5();
71236e46
BJ
245 if (dp->b_actf == NULL) {
246 dp->b_actf = bp;
247 /*
248 * Transport not already active...
249 * put at end of controller queue.
250 */
251 dp->b_forw = NULL;
252 um = tmdinfo[unit]->ui_mi;
253 if (um->um_tab.b_actf == NULL)
254 um->um_tab.b_actf = dp;
255 else
256 um->um_tab.b_actl->b_forw = dp;
257 um->um_tab.b_actl = dp;
258 } else
259 dp->b_actl->av_forw = bp;
260 dp->b_actl = bp;
261 /*
262 * If the controller is not busy, get
263 * it going.
264 */
265 if (um->um_tab.b_active == 0)
266 tmstart(um);
d75e5c3e
BJ
267 (void) spl0();
268}
269
71236e46
BJ
270/*
271 * Start activity on a tm controller.
272 */
273tmstart(um)
89bd2f01 274 register struct uba_ctlr *um;
d75e5c3e 275{
71236e46
BJ
276 register struct buf *bp, *dp;
277 register struct device *addr = (struct device *)um->um_addr;
278 register struct tm_softc *sc;
89bd2f01 279 register struct uba_device *ui;
71236e46 280 int unit, cmd;
7e00c42b 281 daddr_t blkno;
d75e5c3e 282
71236e46
BJ
283 /*
284 * Look for an idle transport on the controller.
285 */
d75e5c3e 286loop:
71236e46 287 if ((dp = um->um_tab.b_actf) == NULL)
d75e5c3e 288 return;
71236e46
BJ
289 if ((bp = dp->b_actf) == NULL) {
290 um->um_tab.b_actf = dp->b_forw;
291 goto loop;
292 }
293 unit = TMUNIT(bp->b_dev);
294 ui = tmdinfo[unit];
295 /*
296 * Record pre-transfer status (e.g. for TM_SENSE)
297 */
298 sc = &tm_softc[unit];
299 addr = (struct device *)um->um_addr;
300 addr->tmcs = (ui->ui_slave << 8);
7e00c42b
BJ
301 sc->sc_dsreg = addr->tmcs;
302 sc->sc_erreg = addr->tmer;
303 sc->sc_resid = addr->tmbc;
71236e46
BJ
304 /*
305 * Default is that last command was NOT a write command;
306 * if we do a write command we will notice this in tmintr().
307 */
308 sc->sc_lastiow = 1;
309 if (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) {
310 /*
311 * Have had a hard error on this (non-raw) tape,
312 * or the tape unit is now unavailable (e.g. taken off
313 * line).
314 */
315 bp->b_flags |= B_ERROR;
d75e5c3e
BJ
316 goto next;
317 }
71236e46
BJ
318 /*
319 * If operation is not a control operation,
320 * check for boundary conditions.
321 */
322 if (bp != &ctmbuf[unit]) {
323 if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
324 bp->b_flags |= B_ERROR;
325 bp->b_error = ENXIO; /* past EOF */
326 goto next;
d75e5c3e 327 }
71236e46
BJ
328 if (dbtofsb(bp->b_blkno) == sc->sc_nxrec &&
329 bp->b_flags&B_READ) {
330 bp->b_resid = bp->b_bcount;
331 clrbuf(bp); /* at EOF */
332 goto next;
333 }
334 if ((bp->b_flags&B_READ) == 0)
335 /* write sets EOF */
336 sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
d75e5c3e 337 }
71236e46
BJ
338 /*
339 * Set up the command, and then if this is a mt ioctl,
340 * do the operation using, for TM_SFORW and TM_SREV, the specified
341 * operation count.
342 */
343 cmd = TM_IE | TM_GO | (ui->ui_slave << 8);
344 if ((minor(bp->b_dev) & T_1600BPI) == 0)
345 cmd |= TM_D800;
346 if (bp == &ctmbuf[unit]) {
347 if (bp->b_command == TM_SENSE)
348 goto next;
71236e46
BJ
349 um->um_tab.b_active =
350 bp->b_command == TM_REW ? SREW : SCOM;
351 if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
352 addr->tmbc = bp->b_repcnt;
d1330646 353 goto dobpcmd;
71236e46
BJ
354 }
355 /*
356 * If the data transfer command is in the correct place,
357 * set up all the registers except the csr, and give
358 * control over to the UNIBUS adapter routines, to
359 * wait for resources to start the i/o.
360 */
7e00c42b 361 if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
3f3a34c3 362 addr->tmbc = -bp->b_bcount;
d75e5c3e 363 if ((bp->b_flags&B_READ) == 0) {
7e00c42b 364 if (um->um_tab.b_errcnt)
71236e46 365 cmd |= TM_WIRG;
d75e5c3e 366 else
71236e46 367 cmd |= TM_WCOM;
d75e5c3e 368 } else
71236e46 369 cmd |= TM_RCOM;
7e00c42b 370 um->um_tab.b_active = SIO;
e4271c68 371 um->um_cmd = cmd;
80905075 372#ifdef notdef
d1330646
BJ
373 if (tmreverseop(sc->sc_lastcmd))
374 while (addr->tmer & TM_SDWN)
375 tmgapsdcnt++;
d1330646 376 sc->sc_lastcmd = TM_RCOM; /* will serve */
80905075 377#endif
e4271c68 378 ubago(ui);
d75e5c3e
BJ
379 return;
380 }
71236e46
BJ
381 /*
382 * Block tape positioned incorrectly;
383 * seek forwards or backwards to the correct spot.
384 */
7e00c42b 385 um->um_tab.b_active = SSEEK;
d75e5c3e 386 if (blkno < dbtofsb(bp->b_blkno)) {
d1330646 387 bp->b_command = TM_SFORW;
3f3a34c3 388 addr->tmbc = blkno - dbtofsb(bp->b_blkno);
d75e5c3e 389 } else {
d1330646 390 bp->b_command = TM_SREV;
3f3a34c3 391 addr->tmbc = dbtofsb(bp->b_blkno) - blkno;
d75e5c3e 392 }
d1330646 393dobpcmd:
80905075 394#ifdef notdef
d1330646
BJ
395 if (tmreverseop(sc->sc_lastcmd) != tmreverseop(bp->b_command))
396 while (addr->tmer & TM_SDWN)
397 tmgapsdcnt++;
d1330646 398 sc->sc_lastcmd = bp->b_command;
80905075 399#endif
d1330646 400 addr->tmcs = (cmd | bp->b_command);
d75e5c3e
BJ
401 return;
402
403next:
71236e46
BJ
404 /*
405 * Done with this operation due to error or
406 * the fact that it doesn't do anything.
407 * Release UBA resources (if any), dequeue
408 * the transfer and continue processing this slave.
409 */
410 if (um->um_ubinfo)
0801d37f 411 ubadone(um);
71236e46
BJ
412 um->um_tab.b_errcnt = 0;
413 dp->b_actf = bp->av_forw;
d75e5c3e
BJ
414 iodone(bp);
415 goto loop;
416}
417
71236e46
BJ
418/*
419 * The UNIBUS resources we needed have been
420 * allocated to us; start the device.
421 */
e4271c68 422tmdgo(um)
89bd2f01 423 register struct uba_ctlr *um;
3f3a34c3 424{
e4271c68 425 register struct device *addr = (struct device *)um->um_addr;
7e00c42b 426
e4271c68
BJ
427 addr->tmba = um->um_ubinfo;
428 addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30);
3f3a34c3
BJ
429}
430
71236e46
BJ
431/*
432 * Tm interrupt routine.
433 */
7e00c42b 434/*ARGSUSED*/
afb907f2
BJ
435tmintr(tm11)
436 int tm11;
d75e5c3e 437{
71236e46 438 struct buf *dp;
d75e5c3e 439 register struct buf *bp;
89bd2f01 440 register struct uba_ctlr *um = tmminfo[tm11];
afb907f2 441 register struct device *addr = (struct device *)tmdinfo[tm11]->ui_addr;
71236e46
BJ
442 register struct tm_softc *sc;
443 int unit;
d75e5c3e
BJ
444 register state;
445
71236e46
BJ
446 /*
447 * If last command was a rewind, and tape is still
448 * rewinding, wait for the rewind complete interrupt.
449 */
450 if (um->um_tab.b_active == SREW) {
451 um->um_tab.b_active = SCOM;
452 if (addr->tmer&TM_RWS)
453 return;
d75e5c3e 454 }
71236e46
BJ
455 /*
456 * An operation completed... record status
457 */
458 if ((dp = um->um_tab.b_actf) == NULL)
d75e5c3e 459 return;
71236e46
BJ
460 bp = dp->b_actf;
461 unit = TMUNIT(bp->b_dev);
462 sc = &tm_softc[unit];
7e00c42b
BJ
463 sc->sc_dsreg = addr->tmcs;
464 sc->sc_erreg = addr->tmer;
465 sc->sc_resid = addr->tmbc;
d75e5c3e 466 if ((bp->b_flags & B_READ) == 0)
71236e46 467 sc->sc_lastiow = 1;
7e00c42b
BJ
468 state = um->um_tab.b_active;
469 um->um_tab.b_active = 0;
71236e46
BJ
470 /*
471 * Check for errors.
472 */
473 if (addr->tmcs&TM_ERR) {
474 while (addr->tmer & TM_SDWN)
d75e5c3e 475 ; /* await settle down */
71236e46
BJ
476 /*
477 * If we hit the end of the tape update our position.
478 */
479 if (addr->tmer&TM_EOF) {
480 tmseteof(bp); /* set blkno and nxrec */
481 state = SCOM; /* force completion */
482 /*
483 * Stuff bc so it will be unstuffed correctly
484 * later to get resid.
485 */
3f3a34c3 486 addr->tmbc = -bp->b_bcount;
71236e46 487 goto opdone;
d75e5c3e 488 }
71236e46
BJ
489 /*
490 * If we were reading and the only error was that the
491 * record was to long, then we don't consider this an error.
492 */
493 if ((bp->b_flags&B_READ) &&
494 (addr->tmer&(TM_HARD|TM_SOFT)) == TM_RLE)
495 goto ignoreerr;
496 /*
497 * If error is not hard, and this was an i/o operation
498 * retry up to 8 times.
499 */
500 if ((addr->tmer&TM_HARD)==0 && state==SIO) {
7e00c42b 501 if (++um->um_tab.b_errcnt < 7) {
7e00c42b 502 sc->sc_blkno++;
0801d37f 503 ubadone(um);
71236e46 504 goto opcont;
d75e5c3e 505 }
71236e46
BJ
506 } else
507 /*
508 * Hard or non-i/o errors on non-raw tape
509 * cause it to close.
510 */
511 if (sc->sc_openf>0 && bp != &rtmbuf[unit])
512 sc->sc_openf = -1;
513 /*
514 * Couldn't recover error
515 */
80905075
BJ
516 printf("te%d: hard error bn%d er=%b\n", minor(bp->b_dev)&03,
517 bp->b_blkno, sc->sc_erreg, TMEREG_BITS);
d75e5c3e 518 bp->b_flags |= B_ERROR;
71236e46 519 goto opdone;
d75e5c3e 520 }
71236e46
BJ
521 /*
522 * Advance tape control FSM.
523 */
524ignoreerr:
d75e5c3e
BJ
525 switch (state) {
526
527 case SIO:
71236e46
BJ
528 /*
529 * Read/write increments tape block number
530 */
7e00c42b 531 sc->sc_blkno++;
71236e46 532 goto opdone;
d75e5c3e
BJ
533
534 case SCOM:
71236e46
BJ
535 /*
536 * Unless special operation, op completed.
537 */
538 if (bp != &ctmbuf[unit])
539 goto opdone;
540 /*
541 * Operation on block device...
542 * iterate operations which don't repeat
543 * for themselves in the hardware; for forward/
544 * backward space record update the current position.
545 */
546 switch (bp->b_command) {
547
548 case TM_SFORW:
549 sc->sc_blkno -= bp->b_repcnt;
550 goto opdone;
551
552 case TM_SREV:
553 sc->sc_blkno += bp->b_repcnt;
554 goto opdone;
d75e5c3e 555
71236e46
BJ
556 default:
557 if (++bp->b_repcnt < 0)
558 goto opcont;
559 goto opdone;
d75e5c3e 560 }
d75e5c3e
BJ
561
562 case SSEEK:
7e00c42b 563 sc->sc_blkno = dbtofsb(bp->b_blkno);
71236e46 564 goto opcont;
d75e5c3e
BJ
565
566 default:
71236e46 567 panic("tmintr");
d75e5c3e 568 }
71236e46
BJ
569opdone:
570 /*
571 * Reset error count and remove
572 * from device queue.
573 */
574 um->um_tab.b_errcnt = 0;
575 dp->b_actf = bp->av_forw;
576 bp->b_resid = -addr->tmbc;
0801d37f 577 ubadone(um);
71236e46
BJ
578 iodone(bp);
579 /*
580 * Circulate slave to end of controller
581 * queue to give other slaves a chance.
582 */
583 um->um_tab.b_actf = dp->b_forw;
584 if (dp->b_actf) {
585 dp->b_forw = NULL;
586 if (um->um_tab.b_actf == NULL)
587 um->um_tab.b_actf = dp;
588 else
589 um->um_tab.b_actl->b_forw = dp;
590 um->um_tab.b_actl = dp;
591 }
592 if (um->um_tab.b_actf == 0)
593 return;
594opcont:
595 tmstart(um);
d75e5c3e
BJ
596}
597
598tmseteof(bp)
599 register struct buf *bp;
600{
71236e46 601 register int unit = TMUNIT(bp->b_dev);
3f3a34c3 602 register struct device *addr =
71236e46
BJ
603 (struct device *)tmdinfo[unit]->ui_addr;
604 register struct tm_softc *sc = &tm_softc[unit];
d75e5c3e 605
71236e46 606 if (bp == &ctmbuf[unit]) {
7e00c42b 607 if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
d75e5c3e 608 /* reversing */
7e00c42b
BJ
609 sc->sc_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc;
610 sc->sc_blkno = sc->sc_nxrec;
d75e5c3e
BJ
611 } else {
612 /* spacing forward */
7e00c42b
BJ
613 sc->sc_blkno = dbtofsb(bp->b_blkno) + addr->tmbc;
614 sc->sc_nxrec = sc->sc_blkno - 1;
d75e5c3e
BJ
615 }
616 return;
617 }
618 /* eof on read */
7e00c42b 619 sc->sc_nxrec = dbtofsb(bp->b_blkno);
d75e5c3e
BJ
620}
621
622tmread(dev)
71236e46 623 dev_t dev;
d75e5c3e
BJ
624{
625
626 tmphys(dev);
89bd2f01
BJ
627 if (u.u_error)
628 return;
71236e46 629 physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_READ, minphys);
d75e5c3e
BJ
630}
631
632tmwrite(dev)
71236e46 633 dev_t dev;
d75e5c3e
BJ
634{
635
636 tmphys(dev);
89bd2f01
BJ
637 if (u.u_error)
638 return;
71236e46 639 physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_WRITE, minphys);
d75e5c3e
BJ
640}
641
642tmphys(dev)
71236e46 643 dev_t dev;
d75e5c3e 644{
89bd2f01 645 register int unit = TMUNIT(dev);
d75e5c3e 646 register daddr_t a;
89bd2f01 647 register struct tm_softc *sc;
d75e5c3e 648
89bd2f01
BJ
649 if (unit >= NTM) {
650 u.u_error = ENXIO;
651 return;
652 }
653 sc = &tm_softc[TMUNIT(dev)];
d75e5c3e 654 a = dbtofsb(u.u_offset >> 9);
7e00c42b
BJ
655 sc->sc_blkno = a;
656 sc->sc_nxrec = a + 1;
d75e5c3e
BJ
657}
658
71236e46
BJ
659tmreset(uban)
660 int uban;
661{
89bd2f01 662 register struct uba_ctlr *um;
afb907f2 663 register tm11, unit;
89bd2f01 664 register struct uba_device *ui;
71236e46
BJ
665 register struct buf *dp;
666
afb907f2
BJ
667 for (tm11 = 0; tm11 < NTM; tm11++) {
668 if ((um = tmminfo[tm11]) == 0 || um->um_alive == 0 ||
71236e46
BJ
669 um->um_ubanum != uban)
670 continue;
80905075 671 printf(" tm%d", tm11);
71236e46
BJ
672 um->um_tab.b_active = 0;
673 um->um_tab.b_actf = um->um_tab.b_actl = 0;
674 if (um->um_ubinfo) {
675 printf("<%d>", (um->um_ubinfo>>28)&0xf);
0801d37f 676 ubadone(um);
71236e46
BJ
677 }
678 ((struct device *)(um->um_addr))->tmcs = TM_DCLR;
afb907f2 679 for (unit = 0; unit < NTE; unit++) {
71236e46
BJ
680 if ((ui = tmdinfo[unit]) == 0)
681 continue;
682 if (ui->ui_alive == 0)
683 continue;
684 dp = &tmutab[unit];
685 dp->b_active = 0;
686 dp->b_forw = 0;
687 if (um->um_tab.b_actf == NULL)
688 um->um_tab.b_actf = dp;
689 else
690 um->um_tab.b_actl->b_forw = dp;
691 um->um_tab.b_actl = dp;
692 tm_softc[unit].sc_openf = -1;
693 }
694 tmstart(um);
695 }
696}
697
d75e5c3e
BJ
698/*ARGSUSED*/
699tmioctl(dev, cmd, addr, flag)
700 caddr_t addr;
701 dev_t dev;
702{
71236e46
BJ
703 int unit = TMUNIT(dev);
704 register struct tm_softc *sc = &tm_softc[unit];
705 register struct buf *bp = &ctmbuf[unit];
d75e5c3e
BJ
706 register callcount;
707 int fcount;
708 struct mtop mtop;
709 struct mtget mtget;
710 /* we depend of the values and order of the MT codes here */
71236e46
BJ
711 static tmops[] =
712 {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE};
d75e5c3e 713
71236e46 714 switch (cmd) {
d75e5c3e
BJ
715 case MTIOCTOP: /* tape operation */
716 if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
717 u.u_error = EFAULT;
718 return;
719 }
720 switch(mtop.mt_op) {
71236e46
BJ
721 case MTWEOF:
722 callcount = mtop.mt_count;
723 fcount = 1;
724 break;
725 case MTFSF: case MTBSF:
d75e5c3e
BJ
726 callcount = mtop.mt_count;
727 fcount = INF;
728 break;
729 case MTFSR: case MTBSR:
730 callcount = 1;
731 fcount = mtop.mt_count;
732 break;
77115c00 733 case MTREW: case MTOFFL: case MTNOP:
d75e5c3e
BJ
734 callcount = 1;
735 fcount = 1;
736 break;
737 default:
738 u.u_error = ENXIO;
739 return;
740 }
71236e46 741 if (callcount <= 0 || fcount <= 0) {
d75e5c3e 742 u.u_error = ENXIO;
71236e46
BJ
743 return;
744 }
745 while (--callcount >= 0) {
e4271c68 746 tmcommand(dev, tmops[mtop.mt_op], fcount);
d75e5c3e 747 if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
71236e46 748 bp->b_resid) {
d75e5c3e
BJ
749 u.u_error = EIO;
750 break;
751 }
71236e46 752 if ((bp->b_flags&B_ERROR) || sc->sc_erreg&TM_BOT)
d75e5c3e
BJ
753 break;
754 }
71236e46 755 geterror(bp);
d75e5c3e
BJ
756 return;
757 case MTIOCGET:
7e00c42b
BJ
758 mtget.mt_dsreg = sc->sc_dsreg;
759 mtget.mt_erreg = sc->sc_erreg;
760 mtget.mt_resid = sc->sc_resid;
d75e5c3e
BJ
761 if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
762 u.u_error = EFAULT;
763 return;
764 default:
765 u.u_error = ENXIO;
766 }
767}
768
769#define DBSIZE 20
770
7455bf3e 771tmdump()
d75e5c3e 772{
89bd2f01 773 register struct uba_device *ui;
3f3a34c3
BJ
774 register struct uba_regs *up;
775 register struct device *addr;
5aa9d5ea
RE
776 int blk, num;
777 int start;
d75e5c3e 778
5aa9d5ea
RE
779 start = 0;
780 num = maxfree;
781#define phys(a,b) ((b)((int)(a)&0x7fffffff))
2536c16c
BJ
782 if (tmdinfo[0] == 0)
783 return (ENXIO);
89bd2f01 784 ui = phys(tmdinfo[0], struct uba_device *);
3f3a34c3
BJ
785 up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
786#if VAX780
787 if (cpu == VAX_780)
788 ubainit(up);
d75e5c3e 789#endif
77115c00 790 DELAY(1000000);
3f3a34c3
BJ
791 addr = (struct device *)ui->ui_physaddr;
792 tmwait(addr);
71236e46 793 addr->tmcs = TM_DCLR | TM_GO;
d75e5c3e
BJ
794 while (num > 0) {
795 blk = num > DBSIZE ? DBSIZE : num;
3f3a34c3 796 tmdwrite(start, blk, addr, up);
d75e5c3e
BJ
797 start += blk;
798 num -= blk;
799 }
5aa9d5ea
RE
800 tmeof(addr);
801 tmeof(addr);
7e00c42b 802 tmwait(addr);
2536c16c
BJ
803 if (addr->tmcs&TM_ERR)
804 return (EIO);
71236e46 805 addr->tmcs = TM_REW | TM_GO;
5aa9d5ea 806 tmwait(addr);
7455bf3e 807 return (0);
d75e5c3e
BJ
808}
809
71236e46
BJ
810tmdwrite(dbuf, num, addr, up)
811 register dbuf, num;
3f3a34c3
BJ
812 register struct device *addr;
813 struct uba_regs *up;
d75e5c3e 814{
3f3a34c3
BJ
815 register struct pte *io;
816 register int npf;
0a51498e 817
3f3a34c3 818 tmwait(addr);
3f3a34c3 819 io = up->uba_map;
d75e5c3e 820 npf = num+1;
0a51498e 821 while (--npf != 0)
89bd2f01 822 *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV);
3f3a34c3
BJ
823 *(int *)io = 0;
824 addr->tmbc = -(num*NBPG);
825 addr->tmba = 0;
71236e46 826 addr->tmcs = TM_WCOM | TM_GO;
d75e5c3e
BJ
827}
828
3f3a34c3
BJ
829tmwait(addr)
830 register struct device *addr;
d75e5c3e 831{
0a51498e 832 register s;
d75e5c3e
BJ
833
834 do
3f3a34c3 835 s = addr->tmcs;
71236e46 836 while ((s & TM_CUR) == 0);
d75e5c3e
BJ
837}
838
3f3a34c3
BJ
839tmeof(addr)
840 struct device *addr;
d75e5c3e
BJ
841{
842
3f3a34c3 843 tmwait(addr);
71236e46 844 addr->tmcs = TM_WEOF | TM_GO;
d75e5c3e
BJ
845}
846#endif