1 #ifndef lint 2 static char sccsid[] = "@(#)io.c 1.3 (Berkeley/CCI) 12/19/86"; 3 #endif 4 5 #include "vdfmt.h" 6 #include "cmd.h" 7 8 9 /* 10 ** 11 */ 12 13 static cmd_text_element nul_table[] = { 14 { 0, "", "" } 15 }; 16 17 int wait_for_char; 18 int vdtimeout; 19 char *clean_up = "Cleaning up... Please wait.\n"; 20 21 22 /* 23 ** 24 */ 25 26 poll(wait) 27 int wait; 28 { 29 int tokens[10]; 30 int didmsg = 0; 31 32 wait_for_char = 0; 33 vdtimeout = wait*1000*1000; 34 uncache(&(dcb.operrsta)); 35 while (!((dcb.operrsta) & (DCBCMP | DCBABT))) { 36 if (input()) { 37 get_text_cmd(nul_table, tokens); 38 if (didmsg == 0 && kill_processes == true) { 39 didmsg = 1; 40 indent(); 41 print(clean_up); 42 exdent(1); 43 } 44 } 45 vdtimeout--; 46 uncache(&(dcb.operrsta)); 47 if (vdtimeout <= 0) { 48 if(C_INFO.type == SMDCTLR) 49 printf("\nVDDC"); 50 else 51 printf("\nSMD-E"); 52 printf(": Controller timeout"); 53 VDDC_ABORT(C_INFO.addr, C_INFO.type); 54 DELAY(30000); 55 break; 56 } 57 } 58 if((vdtimeout > 0)) { 59 if(C_INFO.type == SMD_ECTLR) { 60 uncache(&(C_INFO.addr->cdr_csr)); 61 while(C_INFO.addr->cdr_csr & CS_GO) { 62 DELAY(50); 63 uncache(&(C_INFO.addr->cdr_csr)); 64 } 65 } 66 DELAY(500); 67 } 68 if((dcb.opcode == RD) || (dcb.opcode == RD_RAW)) 69 mtpr(PADC, 0); 70 uncache(&(dcb.operrsta)); 71 uncache(&(dcb.err_code)); 72 wait_for_char = 1; 73 } 74 75 76 /* 77 ** Access_with_no_trailer is used to perform controller functions which 78 ** require no data movement. 79 */ 80 81 access_with_no_trailer(function, wait_time) 82 int function, wait_time; 83 { 84 dcb.opcode = function; /* command */ 85 dcb.intflg = NOINT; 86 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 87 dcb.operrsta = 0; 88 dcb.devselect = (function == VDSTART) ? 0 : (char)cur.drive; 89 dcb.trailcnt = (char)0; 90 mdcb.firstdcb = &dcb; 91 mdcb.vddcstat = 0; 92 VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type); 93 poll(wait_time); 94 if(vdtimeout <= 0) { 95 printf(" during startup operation.\n"); 96 _longjmp(abort_environ, 1); 97 } 98 return dcb.operrsta; 99 } 100 101 102 /* 103 ** access_dsk is used by other routines to do reads and writes to the disk. 104 ** The status of the read / write is returned to the caller for processing. 105 */ 106 107 access_dsk(buf, dskaddr, func, count, wait) 108 char *buf; 109 dskadr *dskaddr; 110 int func, count, wait; 111 { 112 cur.daddr.cylinder = dskaddr->cylinder; 113 cur.daddr.track = dskaddr->track; 114 wait_for_char = 0; 115 dcb.opcode = func; /* format sector command */ 116 dcb.intflg = NOINT; 117 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 118 dcb.operrsta = 0; 119 dcb.devselect = (char)cur.drive; 120 if(func == SEEK) { 121 dcb.trailcnt = (char)(sizeof(trseek) / sizeof(long)); 122 dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder; 123 dcb.trail.sktrail.skaddr.track = dskaddr->track; 124 dcb.trail.sktrail.skaddr.sector = dskaddr->sector; 125 } 126 else { 127 dcb.trailcnt = (char)(sizeof(trrw) / sizeof(long)); 128 dcb.trail.rwtrail.memadr = buf; 129 dcb.trail.rwtrail.wcount=count*(SECSIZ/sizeof(short)); 130 dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder; 131 dcb.trail.rwtrail.disk.track = dskaddr->track; 132 dcb.trail.rwtrail.disk.sector = dskaddr->sector; 133 } 134 mdcb.firstdcb = &dcb; 135 mdcb.vddcstat = 0; 136 VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type); 137 if(wait) { 138 poll(2*60); 139 if(vdtimeout <= 0) { 140 printf(" in access_dsk.\n"); 141 _longjmp(abort_environ, 1); 142 } 143 } 144 wait_for_char = 1; 145 return dcb.operrsta; 146 } 147 148 149 /* 150 ** Spin_up_drive starts the drives on a controller and waits around for 151 ** the drive to spin up if it is not already spinning. 152 */ 153 154 spin_up_drive() 155 { 156 VDDC_RESET(C_INFO.addr, C_INFO.type); 157 if(C_INFO.type == SMD_ECTLR) { 158 C_INFO.addr->cdr_csr = 0; 159 C_INFO.addr->mdcb_tcf = AM_ENPDA; 160 C_INFO.addr->dcb_tcf = AM_ENPDA; 161 C_INFO.addr->trail_tcf = AM_ENPDA; 162 C_INFO.addr->data_tcf = AM_ENPDA; 163 C_INFO.addr->cdr_ccf = CCF_SEN | 0x8 | CCF_STS | 164 XMD_32BIT | BSZ_16WRD | CCF_ERR | 165 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE; 166 } 167 access_with_no_trailer(INIT, 10); 168 access_with_no_trailer(DIAG, 20); 169 configure_drive(0); 170 } 171 172 /* 173 ** Configure_drive tells the controller what kind of drive is attached 174 ** on a particular line. 175 */ 176 177 configure_drive(pass) 178 int pass; 179 { 180 dcb.opcode = RSTCFG; /* command */ 181 dcb.intflg = NOINT; 182 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 183 dcb.operrsta = 0; 184 dcb.devselect = (char)cur.drive; 185 dcb.trail.rstrail.ncyl = CURRENT->vc_ncyl; 186 dcb.trail.rstrail.nsurfaces = CURRENT->vc_ntrak; 187 if(C_INFO.type == SMDCTLR) 188 dcb.trailcnt = (char)2; 189 else { 190 dcb.trailcnt = (char)4; 191 dcb.trail.rstrail.nsectors = CURRENT->vc_nsec; 192 dcb.trail.rstrail.slip_sec = CURRENT->vc_nslip; 193 dcb.trail.rstrail.recovery = 0x00; 194 C_INFO.addr->cyl_skew = (*C_INFO.cylinder_skew)(); 195 C_INFO.addr->trk_skew = (*C_INFO.track_skew)(); 196 } 197 mdcb.firstdcb = &dcb; 198 mdcb.vddcstat = 0; 199 VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type); 200 poll(5); 201 if(vdtimeout <= 0) { 202 printf(" during drive configuration.\n"); 203 _longjmp(abort_environ, 1); 204 } 205 if(dcb.operrsta & (NOTCYLERR | DRVNRDY)) { 206 if(pass) { 207 printf("\nDrive failed to start!\n\n"); 208 _longjmp(abort_environ, -1); 209 } 210 printf("\ndrive not ready, attempting to spin up..."); 211 access_with_no_trailer(VDSTART, (cur.drive * 6) + 62); 212 DELAY((cur.drive * 5500000) + 62000000); 213 printf(" retrying drive configuration\n"); 214 configure_drive(1); 215 } 216 } 217 218 219 /* 220 ** data_ok checks an error status word for bit patterns 221 ** associated with error conditions from the VDDC controller. If a hardware 222 ** error is present then the problem is reported on the console and the program 223 ** is halted. If a data error is present the a zero is returned. 224 ** If everything is OK then a 1 is returned. 225 */ 226 227 data_ok() 228 { 229 register int status = dcb.operrsta; 230 231 if(status & HARD_ERROR){ 232 if(status & DRVNRDY) 233 printf("\nDrive is not ready!"); 234 else if(status & INVDADR) 235 printf("\nInvalid disk address issued!"); 236 else if(status & DNEMEM) 237 printf("\nNon-existent memory error!"); 238 else if(status & PARERR) 239 printf("\nMain memory parity error!"); 240 else if(status & OPABRT) 241 printf("\nCPU aborted operation!"); 242 else if(status & WPTERR) 243 printf("\nDrive is write protected!"); 244 else if(status & DSEEKERR) 245 printf("\nDisk seek error!"); 246 else if(status & CTLRERR) 247 printf("\nController hardware error!"); 248 else 249 printf("\nNot on cylinder error!"); 250 printf(" Status = 0x%lx", status); 251 if(C_INFO.type == SMD_ECTLR) 252 printf(" Error code = 0x%x", dcb.err_code & 0xff); 253 printf("\n"); 254 printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk); 255 printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode); 256 reset_controller(); 257 dcb.operrsta &= HEADER_ERROR; 258 } 259 return (int)(!(status & (DATA_ERROR | HEADER_ERROR))); 260 } 261 262 263 /* 264 ** 265 */ 266 267 reset_controller() 268 { 269 printf("Resetting controller. Please wait...\n"); 270 spin_up_drive(); 271 printf("Controller was reset successfully.\n"); 272 } 273 274 /* 275 ** 276 */ 277 278 static int indent_count; 279 280 281 /* 282 ** 283 */ 284 285 indent() 286 { 287 indent_count += 2; 288 } 289 290 291 /* 292 ** 293 */ 294 295 exdent(count) 296 int count; 297 { 298 if(count == -1) 299 indent_count = 0; 300 else 301 indent_count -= count * 2; 302 if(indent_count < 0) 303 indent_count = 0; 304 } 305 306 307 /* 308 ** 309 */ 310 /*VARARGS1*/ 311 print(par0, par1, par2, par3, par4, par5, par6) 312 char *par0, *par1, *par2, *par3, *par4, *par5, *par6; 313 { 314 register int count = indent_count; 315 316 while(count--) 317 printf(" "); 318 printf(par0, par1, par2, par3, par4, par5, par6); 319 DELAY((strlen(par0) + 20) * 9000); 320 } 321