123235Smckusick /* 229304Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323235Smckusick * All rights reserved. The Berkeley software License Agreement 423235Smckusick * specifies the terms and conditions for redistribution. 523235Smckusick * 6*33529Sbostic * @(#)mt.c 7.3 (Berkeley) 02/22/88 723235Smckusick */ 85151Ssam 95151Ssam /* 105151Ssam * TM78/TU78 tape driver 1110776Ssam * Made to work reliably by by Jeffrey R. Schwab (Purdue) 125151Ssam */ 139806Ssam #include "../machine/pte.h" 145151Ssam 1533408Skarels #include "param.h" 1633408Skarels #include "inode.h" 1733408Skarels #include "fs.h" 189186Ssam 199186Ssam #include "../vaxmba/mtreg.h" 209186Ssam #include "../vaxmba/mbareg.h" 219186Ssam 225151Ssam #include "saio.h" 235151Ssam #include "savax.h" 245151Ssam 255151Ssam short mttypes[] = 265151Ssam { MBDT_TU78, 0 }; 275151Ssam 285151Ssam #define MASKREG(reg) ((reg)&0xffff) 295151Ssam 305151Ssam mtopen(io) 315151Ssam register struct iob *io; 325151Ssam { 33*33529Sbostic register struct mtdevice *mtaddr; 34*33529Sbostic register int i, skip; 355151Ssam 36*33529Sbostic if (mbainit(io->i_adapt) == 0) 37*33529Sbostic return (EADAPT); 38*33529Sbostic mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); 39*33529Sbostic for (i = 0;; i++) { 40*33529Sbostic if (!mttypes[i]) { 41*33529Sbostic printf("mt: not a tape\n"); 42*33529Sbostic return (ENXIO); 43*33529Sbostic } 445151Ssam if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) 45*33529Sbostic break; 46*33529Sbostic } 475151Ssam mtaddr->mtid = MTID_CLR; 485151Ssam DELAY(250); 49*33529Sbostic while ((mtaddr->mtid & MTID_RDY) == 0); 5010776Ssam 5110776Ssam /* clear any attention bits present on open */ 5210776Ssam i = mtaddr->mtner; 5310776Ssam mtaddr->mtas = mtaddr->mtas; 5410776Ssam 555151Ssam mtstrategy(io, MT_REW); 56*33529Sbostic for (skip = io->i_part; skip--;) { 575151Ssam io->i_cc = -1; 585151Ssam mtstrategy(io, MT_SFORWF); 595151Ssam } 6033408Skarels return (0); 615151Ssam } 625151Ssam 635151Ssam mtclose(io) 645151Ssam register struct iob *io; 655151Ssam { 665151Ssam mtstrategy(io, MT_REW); 675151Ssam } 685151Ssam 695151Ssam mtstrategy(io, func) 705151Ssam register struct iob *io; 715151Ssam int func; 725151Ssam { 735151Ssam register int errcnt, s, ic; 74*33529Sbostic register struct mtdevice *mtaddr; 75*33529Sbostic struct mba_regs *mba; 765151Ssam 775151Ssam errcnt = 0; 78*33529Sbostic mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); 79*33529Sbostic mba = mbamba(io->i_adapt); 805151Ssam retry: 8110776Ssam /* code to trap for attention up prior to start of command */ 8210776Ssam if ((mtaddr->mtas & 0xffff) != 0) { 8310776Ssam printf("mt unexpected attention er=%x - continuing\n", 8410776Ssam MASKREG(mtaddr->mtner)); 8510776Ssam mtaddr->mtas = mtaddr->mtas; 8610776Ssam } 8710776Ssam 885151Ssam if (func == READ || func == WRITE) { 895151Ssam mtaddr->mtca = 1<<2; /* 1 record */ 905151Ssam mtaddr->mtbc = io->i_cc; 91*33529Sbostic mbastart(io, io->i_ctlr, func); 9210776Ssam /* wait for mba to go idle and read result status */ 9310776Ssam while((mba->mba_sr & MBSR_DTBUSY) != 0) 9410776Ssam ; 9510776Ssam ic = mtaddr->mter & MTER_INTCODE; 965151Ssam } else { 975151Ssam mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; 985151Ssam rwait: 995151Ssam do 1005151Ssam s = mtaddr->mtas&0xffff; 1015151Ssam while (s == 0); 10210776Ssam ic = mtaddr->mtner & MTER_INTCODE; 1035151Ssam mtaddr->mtas = mtaddr->mtas; /* clear attention */ 1045151Ssam } 1055151Ssam switch (ic) { 1065151Ssam case MTER_TM: 1075151Ssam case MTER_EOT: 1085151Ssam case MTER_LEOT: 1095151Ssam return (0); 1105151Ssam 1115151Ssam case MTER_DONE: 11210776Ssam /* make sure a record was read */ 11310776Ssam if ((mtaddr->mtca & (1 << 2)) != 0) { 11410776Ssam printf("mt record count not decremented - retrying\n"); 11510776Ssam goto retry; 11610776Ssam } 1175151Ssam break; 1185151Ssam 1195151Ssam case MTER_RWDING: 1205151Ssam goto rwait; 1215151Ssam default: 12210776Ssam printf("mt hard error: er=%x\n", 1235151Ssam MASKREG(mtaddr->mter)); 1245151Ssam mtaddr->mtid = MTID_CLR; 1255151Ssam DELAY(250); 1265151Ssam while ((mtaddr->mtid & MTID_RDY) == 0) 1275151Ssam ; 1285151Ssam return (-1); 1295151Ssam 1305151Ssam case MTER_RETRY: 13110776Ssam printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); 132*33529Sbostic if (errcnt++ == 10) { 1335151Ssam printf("mt: unrecovered error\n"); 1345151Ssam return (-1); 1355151Ssam } 1365151Ssam goto retry; 1375151Ssam } 1385151Ssam if (errcnt) 1395151Ssam printf("mt: recovered by retry\n"); 1405151Ssam return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ 1415151Ssam } 142