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.2 (Berkeley) 01/28/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 int skip; 34 register struct mtdevice *mtaddr = 35 (struct mtdevice *)mbadrv(io->i_unit); 36 register int i; 37 38 if (mbainit(UNITTOMBA(io->i_unit)) == 0) 39 return (ENXIO); 40 for (i = 0; mttypes[i]; i++) 41 if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE)) 42 goto found; 43 printf("not a tape\n"); 44 return (ENXIO); 45 found: 46 mtaddr->mtid = MTID_CLR; 47 DELAY(250); 48 while ((mtaddr->mtid & MTID_RDY) == 0) 49 ; 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 skip = io->i_boff; 57 while (skip--) { 58 io->i_cc = -1; 59 mtstrategy(io, MT_SFORWF); 60 } 61 return (0); 62 } 63 64 mtclose(io) 65 register struct iob *io; 66 { 67 68 mtstrategy(io, MT_REW); 69 } 70 71 mtstrategy(io, func) 72 register struct iob *io; 73 int func; 74 { 75 register int errcnt, s, ic; 76 register struct mtdevice *mtaddr = 77 (struct mtdevice *)mbadrv(io->i_unit); 78 struct mba_regs *mba = mbamba(io->i_unit); 79 80 errcnt = 0; 81 retry: 82 /* code to trap for attention up prior to start of command */ 83 if ((mtaddr->mtas & 0xffff) != 0) { 84 printf("mt unexpected attention er=%x - continuing\n", 85 MASKREG(mtaddr->mtner)); 86 mtaddr->mtas = mtaddr->mtas; 87 } 88 89 if (func == READ || func == WRITE) { 90 mtaddr->mtca = 1<<2; /* 1 record */ 91 mtaddr->mtbc = io->i_cc; 92 mbastart(io, func); 93 /* wait for mba to go idle and read result status */ 94 while((mba->mba_sr & MBSR_DTBUSY) != 0) 95 ; 96 ic = mtaddr->mter & MTER_INTCODE; 97 } else { 98 mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO; 99 rwait: 100 do 101 s = mtaddr->mtas&0xffff; 102 while (s == 0); 103 ic = mtaddr->mtner & MTER_INTCODE; 104 mtaddr->mtas = mtaddr->mtas; /* clear attention */ 105 } 106 switch (ic) { 107 case MTER_TM: 108 case MTER_EOT: 109 case MTER_LEOT: 110 return (0); 111 112 case MTER_DONE: 113 /* make sure a record was read */ 114 if ((mtaddr->mtca & (1 << 2)) != 0) { 115 printf("mt record count not decremented - retrying\n"); 116 goto retry; 117 } 118 break; 119 120 case MTER_RWDING: 121 goto rwait; 122 default: 123 printf("mt hard error: er=%x\n", 124 MASKREG(mtaddr->mter)); 125 mtaddr->mtid = MTID_CLR; 126 DELAY(250); 127 while ((mtaddr->mtid & MTID_RDY) == 0) 128 ; 129 return (-1); 130 131 case MTER_RETRY: 132 printf("mt error: er=%x\n", MASKREG(mtaddr->mter)); 133 if (errcnt == 10) { 134 printf("mt: unrecovered error\n"); 135 return (-1); 136 } 137 errcnt++; 138 goto retry; 139 } 140 if (errcnt) 141 printf("mt: recovered by retry\n"); 142 return (io->i_cc); /* NO PARTIAL RECORD READS!!! */ 143 } 144