1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)mt.c 7.7 (Berkeley) 05/04/91 7 */ 8 9 /* 10 * TM78/TU78 tape driver 11 * Made to work reliably by by Jeffrey R. Schwab (Purdue) 12 */ 13 #include "../include/pte.h" 14 15 #include "sys/param.h" 16 17 #include "../mba/mtreg.h" 18 #include "../mba/mbareg.h" 19 20 #include "stand/saio.h" 21 #include "savax.h" 22 23 short mttypes[] = 24 { MBDT_TU78, 0 }; 25 26 #define MASKREG(reg) ((reg)&0xffff) 27 28 mtopen(io) 29 register struct iob *io; 30 { 31 register struct mtdevice *mtaddr; 32 register int i, skip; 33 34 if (mbainit(io->i_adapt) == 0) 35 return (EADAPT); 36 mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); 37 for (i = 0;; i++) { 38 if (!mttypes[i]) { 39 printf("mt: not a tape\n"); 40 return (ENXIO); 41 } 42 if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) 43 break; 44 } 45 mtaddr->mtid = MTID_CLR; 46 DELAY(250); 47 while ((mtaddr->mtid & MTID_RDY) == 0); 48 49 /* clear any attention bits present on open */ 50 i = mtaddr->mtner; 51 mtaddr->mtas = mtaddr->mtas; 52 53 mtstrategy(io, MT_REW); 54 for (skip = io->i_part; skip--;) { 55 io->i_cc = -1; 56 mtstrategy(io, MT_SFORWF); 57 } 58 return (0); 59 } 60 61 mtclose(io) 62 register struct iob *io; 63 { 64 mtstrategy(io, MT_REW); 65 } 66 67 mtstrategy(io, func) 68 register struct iob *io; 69 int func; 70 { 71 register int errcnt, s, ic; 72 register struct mtdevice *mtaddr; 73 struct mba_regs *mba; 74 75 errcnt = 0; 76 mtaddr = (struct mtdevice *)mbadrv(io->i_adapt, io->i_ctlr); 77 mba = mbamba(io->i_adapt); 78 retry: 79 /* code to trap for attention up prior to start of command */ 80 if ((mtaddr->mtas & 0xffff) != 0) { 81 printf("mt unexpected attention er=%x - continuing\n", 82 MASKREG(mtaddr->mtner)); 83 mtaddr->mtas = mtaddr->mtas; 84 } 85 86 if (func == F_READ || func == F_WRITE) { 87 mtaddr->mtca = 1<<2; /* 1 record */ 88 mtaddr->mtbc = io->i_cc; 89 mbastart(io, io->i_ctlr, func); 90 /* wait for mba to go idle and read result status */ 91 while((mba->mba_sr & MBSR_DTBUSY) != 0) 92 ; 93 ic = mtaddr->mter & MTER_INTCODE; 94 } else { 95 mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; 96 rwait: 97 do 98 s = mtaddr->mtas&0xffff; 99 while (s == 0); 100 ic = mtaddr->mtner & MTER_INTCODE; 101 mtaddr->mtas = mtaddr->mtas; /* clear attention */ 102 } 103 switch (ic) { 104 case MTER_TM: 105 case MTER_EOT: 106 case MTER_LEOT: 107 return (0); 108 109 case MTER_DONE: 110 /* make sure a record was read */ 111 if ((mtaddr->mtca & (1 << 2)) != 0) { 112 printf("mt record count not decremented - retrying\n"); 113 goto retry; 114 } 115 break; 116 117 case MTER_RWDING: 118 goto rwait; 119 default: 120 printf("mt hard error: er=%x\n", 121 MASKREG(mtaddr->mter)); 122 mtaddr->mtid = MTID_CLR; 123 DELAY(250); 124 while ((mtaddr->mtid & MTID_RDY) == 0) 125 ; 126 return (-1); 127 128 case MTER_RETRY: 129 printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); 130 if (errcnt++ == 10) { 131 printf("mt: unrecovered error\n"); 132 return (-1); 133 } 134 goto retry; 135 } 136 if (errcnt) 137 printf("mt: recovered by retry\n"); 138 return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ 139 } 140