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 * @(#)ut.c 7.4 (Berkeley) 02/24/88 7 */ 8 9 /* 10 * SI Model 9700 -- emulates TU45 on the UNIBUS 11 */ 12 #include "../machine/pte.h" 13 14 #include "param.h" 15 #include "inode.h" 16 #include "fs.h" 17 18 #include "../vaxuba/ubareg.h" 19 #include "../vaxuba/utreg.h" 20 21 #include "saio.h" 22 #include "savax.h" 23 24 #define MASKREG(reg) ((reg)&0xffff) 25 26 #define MAXCTLR 1 /* all addresses must be specified */ 27 u_short utstd[MAXCTLR] = { 0172440 }; /* non-standard */ 28 29 utopen(io) 30 register struct iob *io; 31 { 32 register int skip; 33 34 if ((u_int)io->i_ctlr >= MAXCTLR) 35 return (ECTLR); 36 if (badaddr((char *)ubamem(io->i_unit, utstd[io->i_ctlr]), sizeof(short))) 37 return (ENXIO); 38 utstrategy(io, UT_REW); 39 for (skip = io->i_part; skip--;) 40 utstrategy(io, UT_SFORWF); 41 return (0); 42 } 43 44 utclose(io) 45 register struct iob *io; 46 { 47 utstrategy(io, UT_REW); 48 } 49 50 #define UTWAIT(addr) { \ 51 do \ 52 word = addr->utcs1; \ 53 while((word&UT_RDY) == 0); \ 54 } 55 56 utstrategy(io, func) 57 register struct iob *io; 58 { 59 register struct utdevice *addr; 60 register u_short word; 61 register int errcnt; 62 int info, resid; 63 u_short dens; 64 65 addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]); 66 dens = io->i_unit | PDP11FMT | UT_PE; 67 errcnt = 0; 68 retry: 69 utquiet(addr); 70 addr->uttc = dens; 71 info = ubasetup(io, 1); 72 addr->utwc = -((io->i_cc+1) >> 1); 73 addr->utfc = -io->i_cc; 74 if (func == READ) { 75 addr->utba = info; 76 addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO; 77 } else if (func == WRITE) { 78 addr->utba = info; 79 addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO; 80 } else if (func == UT_SREV) { 81 addr->utcs1 = UT_SREV | UT_GO; 82 return (0); 83 } else 84 addr->utcs1 = func | UT_GO; 85 UTWAIT(addr); 86 ubafree(io, info); 87 word = addr->utds; 88 if (word&(UTDS_EOT|UTDS_TM)) { 89 addr->utcs1 = UT_CLEAR | UT_GO; 90 goto done; 91 } 92 if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) { 93 printf("ut error: cs1=%b er=%b cs2=%b ds=%b", 94 addr->utcs1, UT_BITS, addr->uter, UTER_BITS, 95 addr->utcs2, UTCS2_BITS, word, UTDS_BITS); 96 if (errcnt++ == 10) { 97 printf("ut: unrecovered error\n"); 98 return (-1); 99 } 100 if (addr->utcs1&UT_TRE) 101 addr->utcs2 |= UTCS2_CLR; 102 addr->utcs1 = UT_CLEAR | UT_GO; 103 utstrategy(io, UT_SREV); 104 utquiet(addr); 105 if (func == WRITE) { 106 addr->utcs1 = UT_ERASE | UT_GO; 107 UTWAIT(addr); 108 } 109 goto retry; 110 } 111 if (errcnt) 112 printf("ut: recovered by retry\n"); 113 done: 114 if (func == READ) { 115 resid = 0; 116 if (io->i_cc > MASKREG(addr->utfc)) 117 resid = io->i_cc - MASKREG(addr->utfc); 118 } else 119 resid = MASKREG(-addr->utfc); 120 return (io->i_cc - resid); 121 } 122 123 static 124 utquiet(addr) 125 register struct utdevice *addr; 126 { 127 register u_short word; 128 129 UTWAIT(addr); 130 do 131 word = addr->utds; 132 while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP)); 133 } 134