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