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