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*33408Skarels * @(#)mt.c 7.2 (Berkeley) 01/28/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 15*33408Skarels #include "param.h" 16*33408Skarels #include "inode.h" 17*33408Skarels #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 { 335151Ssam register int skip; 3410776Ssam register struct mtdevice *mtaddr = 3510776Ssam (struct mtdevice *)mbadrv(io->i_unit); 36*33408Skarels register int i; 375151Ssam 38*33408Skarels if (mbainit(UNITTOMBA(io->i_unit)) == 0) 39*33408Skarels return (ENXIO); 405151Ssam for (i = 0; mttypes[i]; i++) 415151Ssam if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) 425151Ssam goto found; 43*33408Skarels printf("not a tape\n"); 44*33408Skarels return (ENXIO); 455151Ssam found: 465151Ssam mtaddr->mtid = MTID_CLR; 475151Ssam DELAY(250); 485151Ssam while ((mtaddr->mtid & MTID_RDY) == 0) 495151Ssam ; 5010776Ssam 5110776Ssam /* clear any attention bits present on open */ 5210776Ssam i = mtaddr->mtner; 5310776Ssam mtaddr->mtas = mtaddr->mtas; 5410776Ssam 555151Ssam mtstrategy(io, MT_REW); 565151Ssam skip = io->i_boff; 575151Ssam while (skip--) { 585151Ssam io->i_cc = -1; 595151Ssam mtstrategy(io, MT_SFORWF); 605151Ssam } 61*33408Skarels return (0); 625151Ssam } 635151Ssam 645151Ssam mtclose(io) 655151Ssam register struct iob *io; 665151Ssam { 675151Ssam 685151Ssam mtstrategy(io, MT_REW); 695151Ssam } 705151Ssam 715151Ssam mtstrategy(io, func) 725151Ssam register struct iob *io; 735151Ssam int func; 745151Ssam { 755151Ssam register int errcnt, s, ic; 765151Ssam register struct mtdevice *mtaddr = 775151Ssam (struct mtdevice *)mbadrv(io->i_unit); 7810776Ssam struct mba_regs *mba = mbamba(io->i_unit); 795151Ssam 805151Ssam errcnt = 0; 815151Ssam retry: 8210776Ssam /* code to trap for attention up prior to start of command */ 8310776Ssam if ((mtaddr->mtas & 0xffff) != 0) { 8410776Ssam printf("mt unexpected attention er=%x - continuing\n", 8510776Ssam MASKREG(mtaddr->mtner)); 8610776Ssam mtaddr->mtas = mtaddr->mtas; 8710776Ssam } 8810776Ssam 895151Ssam if (func == READ || func == WRITE) { 905151Ssam mtaddr->mtca = 1<<2; /* 1 record */ 915151Ssam mtaddr->mtbc = io->i_cc; 925151Ssam mbastart(io, func); 9310776Ssam /* wait for mba to go idle and read result status */ 9410776Ssam while((mba->mba_sr & MBSR_DTBUSY) != 0) 9510776Ssam ; 9610776Ssam ic = mtaddr->mter & MTER_INTCODE; 975151Ssam } else { 985151Ssam mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; 995151Ssam rwait: 1005151Ssam do 1015151Ssam s = mtaddr->mtas&0xffff; 1025151Ssam while (s == 0); 10310776Ssam ic = mtaddr->mtner & MTER_INTCODE; 1045151Ssam mtaddr->mtas = mtaddr->mtas; /* clear attention */ 1055151Ssam } 1065151Ssam switch (ic) { 1075151Ssam case MTER_TM: 1085151Ssam case MTER_EOT: 1095151Ssam case MTER_LEOT: 1105151Ssam return (0); 1115151Ssam 1125151Ssam case MTER_DONE: 11310776Ssam /* make sure a record was read */ 11410776Ssam if ((mtaddr->mtca & (1 << 2)) != 0) { 11510776Ssam printf("mt record count not decremented - retrying\n"); 11610776Ssam goto retry; 11710776Ssam } 1185151Ssam break; 1195151Ssam 1205151Ssam case MTER_RWDING: 1215151Ssam goto rwait; 1225151Ssam default: 12310776Ssam printf("mt hard error: er=%x\n", 1245151Ssam MASKREG(mtaddr->mter)); 1255151Ssam mtaddr->mtid = MTID_CLR; 1265151Ssam DELAY(250); 1275151Ssam while ((mtaddr->mtid & MTID_RDY) == 0) 1285151Ssam ; 1295151Ssam return (-1); 1305151Ssam 1315151Ssam case MTER_RETRY: 13210776Ssam printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); 1335151Ssam if (errcnt == 10) { 1345151Ssam printf("mt: unrecovered error\n"); 1355151Ssam return (-1); 1365151Ssam } 1375151Ssam errcnt++; 1385151Ssam goto retry; 1395151Ssam } 1405151Ssam if (errcnt) 1415151Ssam printf("mt: recovered by retry\n"); 1425151Ssam return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ 1435151Ssam } 144