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*45803Sbostic * @(#)mt.c 7.6 (Berkeley) 12/16/90 723235Smckusick */ 85151Ssam 95151Ssam /* 105151Ssam * TM78/TU78 tape driver 1110776Ssam * Made to work reliably by by Jeffrey R. Schwab (Purdue) 125151Ssam */ 13*45803Sbostic #include "../include/pte.h" 145151Ssam 15*45803Sbostic #include "sys/param.h" 169186Ssam 17*45803Sbostic #include "../mba/mtreg.h" 18*45803Sbostic #include "../mba/mbareg.h" 199186Ssam 20*45803Sbostic #include "stand/saio.h" 215151Ssam #include "savax.h" 225151Ssam 235151Ssam short mttypes[] = 245151Ssam { MBDT_TU78, 0 }; 255151Ssam 265151Ssam #define MASKREG(reg) ((reg)&0xffff) 275151Ssam 285151Ssam mtopen(io) 295151Ssam register struct iob *io; 305151Ssam { 3133529Sbostic register struct mtdevice *mtaddr; 3233529Sbostic register int i, skip; 335151Ssam 3433529Sbostic if (mbainit(io->i_adapt) == 0) 3533529Sbostic return (EADAPT); 3633529Sbostic mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); 3733529Sbostic for (i = 0;; i++) { 3833529Sbostic if (!mttypes[i]) { 3933529Sbostic printf("mt: not a tape\n"); 4033529Sbostic return (ENXIO); 4133529Sbostic } 425151Ssam if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) 4333529Sbostic break; 4433529Sbostic } 455151Ssam mtaddr->mtid = MTID_CLR; 465151Ssam DELAY(250); 4733529Sbostic while ((mtaddr->mtid & MTID_RDY) == 0); 4810776Ssam 4910776Ssam /* clear any attention bits present on open */ 5010776Ssam i = mtaddr->mtner; 5110776Ssam mtaddr->mtas = mtaddr->mtas; 5210776Ssam 535151Ssam mtstrategy(io, MT_REW); 5433529Sbostic for (skip = io->i_part; skip--;) { 555151Ssam io->i_cc = -1; 565151Ssam mtstrategy(io, MT_SFORWF); 575151Ssam } 5833408Skarels return (0); 595151Ssam } 605151Ssam 615151Ssam mtclose(io) 625151Ssam register struct iob *io; 635151Ssam { 645151Ssam mtstrategy(io, MT_REW); 655151Ssam } 665151Ssam 675151Ssam mtstrategy(io, func) 685151Ssam register struct iob *io; 695151Ssam int func; 705151Ssam { 715151Ssam register int errcnt, s, ic; 7233529Sbostic register struct mtdevice *mtaddr; 7333529Sbostic struct mba_regs *mba; 745151Ssam 755151Ssam errcnt = 0; 7633529Sbostic mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); 7733529Sbostic mba = mbamba(io->i_adapt); 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; 8933529Sbostic mbastart(io, io->i_ctlr, 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)); 13033529Sbostic if (errcnt++ == 10) { 1315151Ssam printf("mt: unrecovered error\n"); 1325151Ssam return (-1); 1335151Ssam } 1345151Ssam goto retry; 1355151Ssam } 1365151Ssam if (errcnt) 1375151Ssam printf("mt: recovered by retry\n"); 1385151Ssam return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ 1395151Ssam } 140