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