123235Smckusick /* 2*29304Smckusick * 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*29304Smckusick * @(#)mt.c 7.1 (Berkeley) 06/05/86 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 155151Ssam #include "../h/param.h" 165151Ssam #include "../h/inode.h" 177446Sroot #include "../h/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 { 335151Ssam register int skip; 3410776Ssam register struct mtdevice *mtaddr = 3510776Ssam (struct mtdevice *)mbadrv(io->i_unit); 365151Ssam int i; 375151Ssam 385151Ssam for (i = 0; mttypes[i]; i++) 395151Ssam if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) 405151Ssam goto found; 415151Ssam _stop("not a tape\n"); 425151Ssam found: 435151Ssam mbainit(UNITTOMBA(io->i_unit)); 445151Ssam mtaddr->mtid = MTID_CLR; 455151Ssam DELAY(250); 465151Ssam while ((mtaddr->mtid & MTID_RDY) == 0) 475151Ssam ; 4810776Ssam 4910776Ssam /* clear any attention bits present on open */ 5010776Ssam i = mtaddr->mtner; 5110776Ssam mtaddr->mtas = mtaddr->mtas; 5210776Ssam 535151Ssam mtstrategy(io, MT_REW); 545151Ssam skip = io->i_boff; 555151Ssam while (skip--) { 565151Ssam io->i_cc = -1; 575151Ssam mtstrategy(io, MT_SFORWF); 585151Ssam } 595151Ssam } 605151Ssam 615151Ssam mtclose(io) 625151Ssam register struct iob *io; 635151Ssam { 645151Ssam 655151Ssam mtstrategy(io, MT_REW); 665151Ssam } 675151Ssam 685151Ssam mtstrategy(io, func) 695151Ssam register struct iob *io; 705151Ssam int func; 715151Ssam { 725151Ssam register int errcnt, s, ic; 735151Ssam register struct mtdevice *mtaddr = 745151Ssam (struct mtdevice *)mbadrv(io->i_unit); 7510776Ssam struct mba_regs *mba = mbamba(io->i_unit); 765151Ssam 775151Ssam errcnt = 0; 785151Ssam retry: 7910776Ssam /* code to trap for attention up prior to start of command */ 8010776Ssam if ((mtaddr->mtas & 0xffff) != 0) { 8110776Ssam printf("mt unexpected attention er=%x - continuing\n", 8210776Ssam MASKREG(mtaddr->mtner)); 8310776Ssam mtaddr->mtas = mtaddr->mtas; 8410776Ssam } 8510776Ssam 865151Ssam if (func == READ || func == WRITE) { 875151Ssam mtaddr->mtca = 1<<2; /* 1 record */ 885151Ssam mtaddr->mtbc = io->i_cc; 895151Ssam mbastart(io, func); 9010776Ssam /* wait for mba to go idle and read result status */ 9110776Ssam while((mba->mba_sr & MBSR_DTBUSY) != 0) 9210776Ssam ; 9310776Ssam ic = mtaddr->mter & MTER_INTCODE; 945151Ssam } else { 955151Ssam mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; 965151Ssam rwait: 975151Ssam do 985151Ssam s = mtaddr->mtas&0xffff; 995151Ssam while (s == 0); 10010776Ssam ic = mtaddr->mtner & MTER_INTCODE; 1015151Ssam mtaddr->mtas = mtaddr->mtas; /* clear attention */ 1025151Ssam } 1035151Ssam switch (ic) { 1045151Ssam case MTER_TM: 1055151Ssam case MTER_EOT: 1065151Ssam case MTER_LEOT: 1075151Ssam return (0); 1085151Ssam 1095151Ssam case MTER_DONE: 11010776Ssam /* make sure a record was read */ 11110776Ssam if ((mtaddr->mtca & (1 << 2)) != 0) { 11210776Ssam printf("mt record count not decremented - retrying\n"); 11310776Ssam goto retry; 11410776Ssam } 1155151Ssam break; 1165151Ssam 1175151Ssam case MTER_RWDING: 1185151Ssam goto rwait; 1195151Ssam default: 12010776Ssam printf("mt hard error: er=%x\n", 1215151Ssam MASKREG(mtaddr->mter)); 1225151Ssam mtaddr->mtid = MTID_CLR; 1235151Ssam DELAY(250); 1245151Ssam while ((mtaddr->mtid & MTID_RDY) == 0) 1255151Ssam ; 1265151Ssam return (-1); 1275151Ssam 1285151Ssam case MTER_RETRY: 12910776Ssam printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); 1305151Ssam if (errcnt == 10) { 1315151Ssam printf("mt: unrecovered error\n"); 1325151Ssam return (-1); 1335151Ssam } 1345151Ssam errcnt++; 1355151Ssam goto retry; 1365151Ssam } 1375151Ssam if (errcnt) 1385151Ssam printf("mt: recovered by retry\n"); 1395151Ssam return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ 1405151Ssam } 141