1 2 /* @(#)tmscp.c 7.2 (Berkeley) 01/28/88 */ 3 4 /**************************************************************** 5 * * 6 * Licensed from Digital Equipment Corporation * 7 * Copyright (c) * 8 * Digital Equipment Corporation * 9 * Maynard, Massachusetts * 10 * 1985, 1986 * 11 * All rights reserved. * 12 * * 13 * The Information in this software is subject to change * 14 * without notice and should not be construed as a commitment * 15 * by Digital Equipment Corporation. Digital makes no * 16 * representations about the suitability of this software for * 17 * any purpose. It is supplied "As Is" without expressed or * 18 * implied warranty. * 19 * * 20 * If the Regents of the University of California or its * 21 * licensees modify the software in a manner creating * 22 * diriviative copyright rights, appropriate copyright * 23 * legends may be placed on the drivative work in addition * 24 * to that set forth above. * 25 ***************************************************************/ 26 /* 27 * tmscp.c - TMSCP (TK50/TU81) standalone driver 28 */ 29 30 # ifndef lint 31 static char *sccsid = "@(#)tmscp.c 1.5 (ULTRIX) 4/18/86"; 32 # endif not lint 33 34 /* ------------------------------------------------------------------------ 35 * Modification History: /sys/stand/tmscp.c 36 * 37 * 3-15-85 afd 38 * Don't ask for an interrupt when commands are issued and 39 * check ownership bit in the response descriptor to detect when a 40 * command is complete. Necessary due to the TU81's failure to set 41 * the response interrupt field in the communications area. 42 * 43 * ------------------------------------------------------------------------ 44 */ 45 46 47 #include "param.h" 48 #include "inode.h" 49 #include "fs.h" 50 51 #include "../vax/pte.h" 52 53 #include "savax.h" 54 #include "saio.h" 55 56 /* 57 * Parameters for the communications area 58 * (Only 1 cmd & 1 rsp packet) 59 */ 60 #define NRSPL2 0 61 #define NCMDL2 0 62 #define NRSP (1<<NRSPL2) 63 #define NCMD (1<<NCMDL2) 64 65 #include "../vaxuba/tmscpreg.h" 66 #include "../vaxuba/ubareg.h" 67 #include "../vax/tmscp.h" 68 69 u_short tmscpstd[] = { 0174500 }; 70 71 struct iob ctmscpbuf; 72 73 struct tmscpdevice *tmscpaddr = 0; 74 75 struct tmscp { 76 struct tmscpca tmscp_ca; 77 struct mscp tmscp_rsp; 78 struct mscp tmscp_cmd; 79 } tmscp; 80 81 struct tmscp *tmscp_ubaddr; /* Unibus address of tmscp structure */ 82 83 struct mscp *tmscpcmd(); 84 85 int tmscp_offline = 1; /* Flag to prevent multiple STCON */ 86 int tms_offline[4] = {1,1,1,1}; /* Flag to prevent multiple ONLIN */ 87 88 89 /* 90 * Open a tmscp device. Initialize the controller and set the unit online. 91 */ 92 tmscpopen(io) 93 register struct iob *io; 94 { 95 register struct mscp *mp; 96 int i; 97 98 /* 99 * Have the tmscp controller characteristics already been set up 100 * (STCON)? 101 */ 102 if (tmscp_offline) 103 { 104 if (tmscpaddr == 0) 105 tmscpaddr = (struct tmscpdevice *)ubamem(io->i_unit, tmscpstd[0]); 106 if (tmscp_ubaddr == 0) 107 { 108 ctmscpbuf.i_unit = io->i_unit; 109 ctmscpbuf.i_ma = (caddr_t)&tmscp; 110 ctmscpbuf.i_cc = sizeof(tmscp); 111 tmscp_ubaddr = (struct tmscp *)ubasetup(&ctmscpbuf, 2); 112 } 113 /* 114 * Initialize the tmscp device and wait for the 4 steps 115 * to complete. 116 */ 117 tmscpaddr->tmscpip = 0; 118 while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) 119 ; 120 tmscpaddr->tmscpsa =TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8); 121 122 while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) 123 ; 124 # define STEP1MASK 0174377 125 # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) 126 if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) 127 printf("tmscpopen: step 1 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff); 128 tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; 129 130 while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) 131 ; 132 # define STEP2MASK 0174377 133 # define STEP2GOOD (TMSCP_STEP3) 134 if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) 135 printf("tmscpopen: step 2 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff); 136 tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); 137 138 while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) 139 ; 140 # define STEP3MASK 0174000 141 # define STEP3GOOD TMSCP_STEP4 142 if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) 143 printf("tmscpopen: step 3 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff); 144 tmscpaddr->tmscpsa = TMSCP_GO; 145 146 /* 147 * Init cmd & rsp area 148 */ 149 tmscp.tmscp_ca.ca_cmddsc[0] = (long)&tmscp_ubaddr->tmscp_cmd.mscp_cmdref; 150 tmscp.tmscp_cmd.mscp_dscptr = tmscp.tmscp_ca.ca_cmddsc; 151 tmscp.tmscp_cmd.mscp_header.tmscp_vcid = 1; /* for tape */ 152 153 tmscp.tmscp_ca.ca_rspdsc[0] = (long)&tmscp_ubaddr->tmscp_rsp.mscp_cmdref; 154 tmscp.tmscp_rsp.mscp_dscptr = tmscp.tmscp_ca.ca_rspdsc; 155 tmscp.tmscp_cmd.mscp_cntflgs = 0; 156 if (tmscpcmd(M_OP_STCON, 0) == 0) 157 { 158 printf("tms: open error, STCON\n"); 159 return (EIO); 160 } 161 tmscp_offline = 0; 162 } 163 tmscp.tmscp_cmd.mscp_unit = io->i_unit&03; 164 /* 165 * Has this unit been issued an ONLIN? 166 */ 167 if (tms_offline[tmscp.tmscp_cmd.mscp_unit]) 168 { 169 if ((mp = tmscpcmd(M_OP_ONLIN, 0)) == 0) 170 { 171 _stop("tms: open error, ONLIN\n"); 172 return (EIO); 173 } 174 tms_offline[tmscp.tmscp_cmd.mscp_unit] = 0; 175 } 176 if (io->i_boff < 0 || io->i_boff > 3) { 177 printf("tms: bad offset\n"); 178 return (EUNIT); 179 } 180 else if (io->i_boff > 0) 181 /* 182 * Skip forward the appropriate number of files on the tape. 183 */ 184 { 185 tmscp.tmscp_cmd.mscp_tmkcnt = io->i_boff; 186 tmscpcmd(M_OP_REPOS, 0); 187 tmscp.tmscp_cmd.mscp_tmkcnt = 0; 188 } 189 return (0); 190 } 191 192 193 /* 194 * Close the device (rewind it to BOT) 195 */ 196 tmscpclose(io) 197 register struct iob *io; 198 { 199 tmscpcmd(M_OP_REPOS, M_MD_REWND); 200 } 201 202 203 /* 204 * Set up tmscp command packet. Cause the controller to poll to pick up 205 * the command. 206 */ 207 struct mscp * 208 tmscpcmd(op,mod) 209 int op, mod; /* opcode and modifier (usu 0) */ 210 { 211 struct mscp *mp; /* ptr to cmd packet */ 212 int i; /* read into to init polling */ 213 214 tmscp.tmscp_cmd.mscp_opcode = op; 215 tmscp.tmscp_cmd.mscp_modifier = mod; 216 tmscp.tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen; 217 tmscp.tmscp_ca.ca_cmddsc[0] |= TMSCP_OWN; /* | TMSCP_INT */ 218 tmscp.tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen; 219 tmscp.tmscp_ca.ca_rspdsc[0] |= TMSCP_OWN; /* | TMSCP_INT */ 220 221 i = tmscpaddr->tmscpip; 222 for (;;) 223 { 224 if (tmscpaddr->tmscpsa & TMSCP_ERR) 225 { 226 printf("tmscpcmd: Fatal error sa=%o\n", tmscpaddr->tmscpsa & 0xffff); 227 return(0); 228 } 229 230 if (tmscp.tmscp_ca.ca_cmdint) 231 tmscp.tmscp_ca.ca_cmdint = 0; 232 /* 233 * This is to handle the case of devices not setting the 234 * interrupt field in the communications area. Some 235 * devices (early TU81's) only clear the ownership field 236 * in the Response Descriptor. 237 */ 238 /* 239 if (tmscp.tmscp_ca.ca_rspint) 240 break; 241 */ 242 if (!(tmscp.tmscp_ca.ca_rspdsc[0] & (TMSCP_OWN))) 243 break; 244 } 245 tmscp.tmscp_ca.ca_rspint = 0; 246 mp = &tmscp.tmscp_rsp; 247 if (mp->mscp_opcode != (op|M_OP_END) || 248 (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) 249 { 250 /* Detect hitting tape mark. This signifies the end of the 251 * tape mini-root file. We don't want to return an error 252 * condition to the strategy routine. 253 */ 254 if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM) 255 return(mp); 256 return(0); 257 } 258 return(mp); 259 } 260 261 262 /* 263 * Set up to do reads and writes; call tmscpcmd to issue the cmd. 264 */ 265 tmscpstrategy(io, func) 266 register struct iob *io; 267 int func; 268 { 269 register struct mscp *mp; 270 int ubinfo; 271 272 ubinfo = ubasetup(io, 1); 273 mp = &tmscp.tmscp_cmd; 274 mp->mscp_lbn = io->i_bn; 275 mp->mscp_unit = io->i_unit&03; 276 mp->mscp_bytecnt = io->i_cc; 277 mp->mscp_buffer = (ubinfo & 0x3fffff) | (((ubinfo>>28)&0xf)<<24); 278 if ((mp = tmscpcmd(func == READ ? M_OP_READ : M_OP_WRITE, 0)) == 0) 279 { 280 ubafree(io, ubinfo); 281 printf("tms: I/O error\n"); 282 return(-1); 283 } 284 ubafree(io, ubinfo); 285 /* 286 * Detect hitting tape mark so we do it gracefully and return a 287 * character count of 0 to signify end of copy. Rewind the tape 288 * before returning. 289 */ 290 if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM) 291 return(0); 292 return(io->i_cc); 293 } 294 295 /*ARGSUSED*/ 296 tmscpioctl(io, cmd, arg) 297 struct iob *io; 298 int cmd; 299 caddr_t arg; 300 { 301 return (ECMD); 302 } 303