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