123244Smckusick /* 235052Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 323244Smckusick * All rights reserved. The Berkeley software License Agreement 423244Smckusick * specifies the terms and conditions for redistribution. 523244Smckusick * 6*45803Sbostic * @(#)tm.c 7.7 (Berkeley) 12/16/90 723244Smckusick */ 83263Swnj 91811Sbill /* 103263Swnj * TM11/TE?? 111811Sbill */ 121811Sbill 13*45803Sbostic #include "sys/param.h" 149186Ssam 15*45803Sbostic #include "../include/pte.h" 1635052Skarels 17*45803Sbostic #include "../uba/ubareg.h" 18*45803Sbostic #include "../uba/tmreg.h" 199186Ssam 20*45803Sbostic #include "stand/saio.h" 213263Swnj #include "savax.h" 221811Sbill 2333531Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 2433531Sbostic u_short tmstd[MAXCTLR] = { 0172520 }; 251811Sbill 261811Sbill tmopen(io) 271924Swnj register struct iob *io; 281811Sbill { 2933531Sbostic register int skip; 301811Sbill 3135052Skarels if ((u_int)io->i_adapt >= nuba) 3235052Skarels return (EADAPT); 3333531Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 3433531Sbostic return (ECTLR); 3533550Sbostic if (badaddr((char *)ubamem(io->i_adapt, tmstd[io->i_ctlr]), sizeof(short))) 3633408Skarels return (ENXIO); 373263Swnj tmstrategy(io, TM_REW); 3833531Sbostic for (skip = io->i_part; skip--;) { 391811Sbill io->i_cc = 0; 403477Sroot tmstrategy(io, TM_SFORW); 411811Sbill } 4233408Skarels return (0); 431811Sbill } 441811Sbill 451811Sbill tmclose(io) 461924Swnj register struct iob *io; 471811Sbill { 483263Swnj tmstrategy(io, TM_REW); 491811Sbill } 501811Sbill 511811Sbill tmstrategy(io, func) 521924Swnj register struct iob *io; 531811Sbill { 5433531Sbostic register int com, errcnt; 5533531Sbostic register struct tmdevice *tmaddr; 563263Swnj int word, info; 571811Sbill 5833531Sbostic tmaddr = (struct tmdevice *)ubamem(io->i_adapt, tmstd[io->i_ctlr]); 591811Sbill errcnt = 0; 601811Sbill retry: 613263Swnj tmquiet(tmaddr); 621811Sbill info = ubasetup(io, 1); 633263Swnj tmaddr->tmbc = -io->i_cc; 643263Swnj tmaddr->tmba = info; 6533531Sbostic com = (io->i_unit<<8) | TM_GO; 661811Sbill if (func == READ) 6733531Sbostic tmaddr->tmcs = com | TM_RCOM; 681811Sbill else if (func == WRITE) 6933531Sbostic tmaddr->tmcs = com | TM_WCOM; 703263Swnj else if (func == TM_SREV) { 713263Swnj tmaddr->tmbc = -1; 7233531Sbostic tmaddr->tmcs = com | TM_SREV; 731924Swnj return (0); 741811Sbill } else 7533531Sbostic tmaddr->tmcs = com | func; 761924Swnj for (;;) { 773263Swnj word = tmaddr->tmcs; 7813568Ssam DELAY(100); 7911383Ssam if (word & TM_CUR) 801924Swnj break; 811924Swnj } 823263Swnj ubafree(io, info); 833263Swnj word = tmaddr->tmer; 8411383Ssam if (word & TMER_EOT) 8511383Ssam return (0); 8611383Ssam if (word & TM_ERR) { 8711383Ssam if (word & TMER_EOF) 8811383Ssam return (0); 8933531Sbostic printf("tm tape error: er=%b\n", word, TMER_BITS); 9033531Sbostic if (errcnt++ == 10) { 9133531Sbostic printf("tm: unrecovered error\n"); 9211383Ssam return (-1); 931811Sbill } 943263Swnj tmstrategy(io, TM_SREV); 951811Sbill goto retry; 961811Sbill } 971811Sbill if (errcnt) 9833531Sbostic printf("tm: recovered by retry\n"); 9911383Ssam if (word & TMER_EOF) 10011383Ssam return (0); 10111383Ssam return (io->i_cc + tmaddr->tmbc); 1021811Sbill } 1031811Sbill 1043263Swnj tmquiet(tmaddr) 1055157Sroot register struct tmdevice *tmaddr; 1061811Sbill { 1071924Swnj register word; 1081924Swnj for (;;) { 1093263Swnj word = tmaddr->tmcs; 11013568Ssam DELAY(100); 1113263Swnj if (word&TM_CUR) 1121924Swnj break; 1131924Swnj } 1141924Swnj for (;;) { 1153263Swnj word = tmaddr->tmer; 11613568Ssam DELAY(100); 1173263Swnj if ((word&TMER_TUR) && (word&TMER_SDWN)==0) 1181924Swnj break; 1191924Swnj } 1201811Sbill } 121