123244Smckusick /* 2*35052Skarels * 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*35052Skarels * @(#)tm.c 7.5 (Berkeley) 07/09/88 723244Smckusick */ 83263Swnj 91811Sbill /* 103263Swnj * TM11/TE?? 111811Sbill */ 121811Sbill 1333408Skarels #include "param.h" 1433408Skarels #include "inode.h" 1533408Skarels #include "fs.h" 169186Ssam 17*35052Skarels #include "../vax/pte.h" 18*35052Skarels 199186Ssam #include "../vaxuba/ubareg.h" 209186Ssam #include "../vaxuba/tmreg.h" 219186Ssam 221811Sbill #include "saio.h" 233263Swnj #include "savax.h" 241811Sbill 2533531Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 2633531Sbostic u_short tmstd[MAXCTLR] = { 0172520 }; 271811Sbill 281811Sbill tmopen(io) 291924Swnj register struct iob *io; 301811Sbill { 3133531Sbostic register int skip; 321811Sbill 33*35052Skarels if ((u_int)io->i_adapt >= nuba) 34*35052Skarels return (EADAPT); 3533531Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 3633531Sbostic return (ECTLR); 3733550Sbostic if (badaddr((char *)ubamem(io->i_adapt, tmstd[io->i_ctlr]), sizeof(short))) 3833408Skarels return (ENXIO); 393263Swnj tmstrategy(io, TM_REW); 4033531Sbostic for (skip = io->i_part; skip--;) { 411811Sbill io->i_cc = 0; 423477Sroot tmstrategy(io, TM_SFORW); 431811Sbill } 4433408Skarels return (0); 451811Sbill } 461811Sbill 471811Sbill tmclose(io) 481924Swnj register struct iob *io; 491811Sbill { 503263Swnj tmstrategy(io, TM_REW); 511811Sbill } 521811Sbill 531811Sbill tmstrategy(io, func) 541924Swnj register struct iob *io; 551811Sbill { 5633531Sbostic register int com, errcnt; 5733531Sbostic register struct tmdevice *tmaddr; 583263Swnj int word, info; 591811Sbill 6033531Sbostic tmaddr = (struct tmdevice *)ubamem(io->i_adapt, tmstd[io->i_ctlr]); 611811Sbill errcnt = 0; 621811Sbill retry: 633263Swnj tmquiet(tmaddr); 641811Sbill info = ubasetup(io, 1); 653263Swnj tmaddr->tmbc = -io->i_cc; 663263Swnj tmaddr->tmba = info; 6733531Sbostic com = (io->i_unit<<8) | TM_GO; 681811Sbill if (func == READ) 6933531Sbostic tmaddr->tmcs = com | TM_RCOM; 701811Sbill else if (func == WRITE) 7133531Sbostic tmaddr->tmcs = com | TM_WCOM; 723263Swnj else if (func == TM_SREV) { 733263Swnj tmaddr->tmbc = -1; 7433531Sbostic tmaddr->tmcs = com | TM_SREV; 751924Swnj return (0); 761811Sbill } else 7733531Sbostic tmaddr->tmcs = com | func; 781924Swnj for (;;) { 793263Swnj word = tmaddr->tmcs; 8013568Ssam DELAY(100); 8111383Ssam if (word & TM_CUR) 821924Swnj break; 831924Swnj } 843263Swnj ubafree(io, info); 853263Swnj word = tmaddr->tmer; 8611383Ssam if (word & TMER_EOT) 8711383Ssam return (0); 8811383Ssam if (word & TM_ERR) { 8911383Ssam if (word & TMER_EOF) 9011383Ssam return (0); 9133531Sbostic printf("tm tape error: er=%b\n", word, TMER_BITS); 9233531Sbostic if (errcnt++ == 10) { 9333531Sbostic printf("tm: unrecovered error\n"); 9411383Ssam return (-1); 951811Sbill } 963263Swnj tmstrategy(io, TM_SREV); 971811Sbill goto retry; 981811Sbill } 991811Sbill if (errcnt) 10033531Sbostic printf("tm: recovered by retry\n"); 10111383Ssam if (word & TMER_EOF) 10211383Ssam return (0); 10311383Ssam return (io->i_cc + tmaddr->tmbc); 1041811Sbill } 1051811Sbill 1063263Swnj tmquiet(tmaddr) 1075157Sroot register struct tmdevice *tmaddr; 1081811Sbill { 1091924Swnj register word; 1101924Swnj for (;;) { 1113263Swnj word = tmaddr->tmcs; 11213568Ssam DELAY(100); 1133263Swnj if (word&TM_CUR) 1141924Swnj break; 1151924Swnj } 1161924Swnj for (;;) { 1173263Swnj word = tmaddr->tmer; 11813568Ssam DELAY(100); 1193263Swnj if ((word&TMER_TUR) && (word&TMER_SDWN)==0) 1201924Swnj break; 1211924Swnj } 1221811Sbill } 123