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.3 (Berkeley) 02/22/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 printf("ut: nonexistent device\n"); 38 return (ENXIO); 39 } 40 utstrategy(io, UT_REW); 41 for (skip = io->i_part; skip--;) 42 utstrategy(io, UT_SFORWF); 43 return (0); 44 } 45 46 utclose(io) 47 register struct iob *io; 48 { 49 utstrategy(io, UT_REW); 50 } 51 52 #define UTWAIT(addr) { \ 53 do \ 54 word = addr->utcs1; \ 55 while((word&UT_RDY) == 0); \ 56 } 57 58 utstrategy(io, func) 59 register struct iob *io; 60 { 61 register struct utdevice *addr; 62 register u_short word; 63 register int errcnt; 64 int info, resid; 65 u_short dens; 66 67 addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]); 68 dens = io->i_unit | PDP11FMT | UT_PE; 69 errcnt = 0; 70 retry: 71 utquiet(addr); 72 addr->uttc = dens; 73 info = ubasetup(io, 1); 74 addr->utwc = -((io->i_cc+1) >> 1); 75 addr->utfc = -io->i_cc; 76 if (func == READ) { 77 addr->utba = info; 78 addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO; 79 } else if (func == WRITE) { 80 addr->utba = info; 81 addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO; 82 } else if (func == UT_SREV) { 83 addr->utcs1 = UT_SREV | UT_GO; 84 return (0); 85 } else 86 addr->utcs1 = func | UT_GO; 87 UTWAIT(addr); 88 ubafree(io, info); 89 word = addr->utds; 90 if (word&(UTDS_EOT|UTDS_TM)) { 91 addr->utcs1 = UT_CLEAR | UT_GO; 92 goto done; 93 } 94 if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) { 95 printf("ut error: cs1=%b er=%b cs2=%b ds=%b", 96 addr->utcs1, UT_BITS, addr->uter, UTER_BITS, 97 addr->utcs2, UTCS2_BITS, word, UTDS_BITS); 98 if (errcnt++ == 10) { 99 printf("ut: unrecovered error\n"); 100 return (-1); 101 } 102 if (addr->utcs1&UT_TRE) 103 addr->utcs2 |= UTCS2_CLR; 104 addr->utcs1 = UT_CLEAR | UT_GO; 105 utstrategy(io, UT_SREV); 106 utquiet(addr); 107 if (func == WRITE) { 108 addr->utcs1 = UT_ERASE | UT_GO; 109 UTWAIT(addr); 110 } 111 goto retry; 112 } 113 if (errcnt) 114 printf("ut: recovered by retry\n"); 115 done: 116 if (func == READ) { 117 resid = 0; 118 if (io->i_cc > MASKREG(addr->utfc)) 119 resid = io->i_cc - MASKREG(addr->utfc); 120 } else 121 resid = MASKREG(-addr->utfc); 122 return (io->i_cc - resid); 123 } 124 125 static 126 utquiet(addr) 127 register struct utdevice *addr; 128 { 129 register u_short word; 130 131 UTWAIT(addr); 132 do 133 word = addr->utds; 134 while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP)); 135 } 136