129532Ssam #ifndef lint 2*31318Ssam static char sccsid[] = "@(#)io.c 1.4 (Berkeley/CCI) 06/01/87"; 329532Ssam #endif 429532Ssam 529532Ssam #include "vdfmt.h" 629532Ssam #include "cmd.h" 729532Ssam 829532Ssam 929532Ssam /* 1029532Ssam ** 1129532Ssam */ 1229532Ssam 1329532Ssam static cmd_text_element nul_table[] = { 1429532Ssam { 0, "", "" } 1529532Ssam }; 1629532Ssam 1729981Skarels int wait_for_char; 1830324Skarels int vdtimeout; 1929532Ssam char *clean_up = "Cleaning up... Please wait.\n"; 2029532Ssam 2129532Ssam 2229532Ssam /* 2329532Ssam ** 2429532Ssam */ 2529532Ssam 2629532Ssam poll(wait) 2729532Ssam int wait; 2829532Ssam { 2929532Ssam int tokens[10]; 3029981Skarels int didmsg = 0; 3129532Ssam 3229981Skarels wait_for_char = 0; 3329532Ssam vdtimeout = wait*1000*1000; 3429532Ssam uncache(&(dcb.operrsta)); 35*31318Ssam while (!((dcb.operrsta) & (DCBS_DONE | DCBS_ABORT))) { 3629981Skarels if (input()) { 3729532Ssam get_text_cmd(nul_table, tokens); 3829981Skarels if (didmsg == 0 && kill_processes == true) { 3929981Skarels didmsg = 1; 4029532Ssam indent(); 4129532Ssam print(clean_up); 4229532Ssam exdent(1); 4329532Ssam } 4429532Ssam } 4529532Ssam vdtimeout--; 4629532Ssam uncache(&(dcb.operrsta)); 4729532Ssam if (vdtimeout <= 0) { 48*31318Ssam if(C_INFO.type == VDTYPE_VDDC) 4929532Ssam printf("\nVDDC"); 5029532Ssam else 5129532Ssam printf("\nSMD-E"); 5229532Ssam printf(": Controller timeout"); 53*31318Ssam VDABORT(C_INFO.addr, C_INFO.type); 5429532Ssam DELAY(30000); 5529532Ssam break; 5629532Ssam } 5729532Ssam } 5829532Ssam if((vdtimeout > 0)) { 59*31318Ssam if(C_INFO.type == VDTYPE_SMDE) { 60*31318Ssam uncache(&(C_INFO.addr->vdcsr)); 61*31318Ssam while(C_INFO.addr->vdcsr & CS_GO) { 6229532Ssam DELAY(50); 63*31318Ssam uncache(&(C_INFO.addr->vdcsr)); 6429532Ssam } 6529532Ssam } 6629532Ssam DELAY(500); 6729532Ssam } 68*31318Ssam if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW)) 6929981Skarels mtpr(PADC, 0); 7029532Ssam uncache(&(dcb.operrsta)); 7129981Skarels uncache(&(dcb.err_code)); 7229981Skarels wait_for_char = 1; 7329532Ssam } 7429532Ssam 7529532Ssam 7629532Ssam /* 7729532Ssam ** Access_with_no_trailer is used to perform controller functions which 7829532Ssam ** require no data movement. 7929532Ssam */ 8029532Ssam 8129532Ssam access_with_no_trailer(function, wait_time) 8229532Ssam int function, wait_time; 8329532Ssam { 8429532Ssam dcb.opcode = function; /* command */ 85*31318Ssam dcb.intflg = DCBINT_NONE; 86*31318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */ 8729532Ssam dcb.operrsta = 0; 88*31318Ssam dcb.devselect = (function == VDOP_START) ? 0 : (char)cur.drive; 8929532Ssam dcb.trailcnt = (char)0; 90*31318Ssam mdcb.mdcb_head = &dcb; 91*31318Ssam mdcb.mdcb_status = 0; 92*31318Ssam VDGO(C_INFO.addr, (u_long)&mdcb, C_INFO.type); 9329532Ssam poll(wait_time); 9429532Ssam if(vdtimeout <= 0) { 9529532Ssam printf(" during startup operation.\n"); 9629532Ssam _longjmp(abort_environ, 1); 9729532Ssam } 9829532Ssam return dcb.operrsta; 9929532Ssam } 10029532Ssam 10129532Ssam 10229532Ssam /* 10329532Ssam ** access_dsk is used by other routines to do reads and writes to the disk. 10429532Ssam ** The status of the read / write is returned to the caller for processing. 10529532Ssam */ 10629532Ssam 10729532Ssam access_dsk(buf, dskaddr, func, count, wait) 10829532Ssam char *buf; 10929532Ssam dskadr *dskaddr; 11029532Ssam int func, count, wait; 11129532Ssam { 11229532Ssam cur.daddr.cylinder = dskaddr->cylinder; 11329532Ssam cur.daddr.track = dskaddr->track; 11429981Skarels wait_for_char = 0; 11529532Ssam dcb.opcode = func; /* format sector command */ 116*31318Ssam dcb.intflg = DCBINT_NONE; 117*31318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */ 11829532Ssam dcb.operrsta = 0; 11929532Ssam dcb.devselect = (char)cur.drive; 120*31318Ssam if(func == VDOP_SEEK) { 121*31318Ssam dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long)); 12229532Ssam dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder; 12329532Ssam dcb.trail.sktrail.skaddr.track = dskaddr->track; 12429532Ssam dcb.trail.sktrail.skaddr.sector = dskaddr->sector; 12529532Ssam } 12629532Ssam else { 127*31318Ssam dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long)); 128*31318Ssam dcb.trail.rwtrail.memadr = (u_long)buf; 12929532Ssam dcb.trail.rwtrail.wcount=count*(SECSIZ/sizeof(short)); 13029532Ssam dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder; 13129532Ssam dcb.trail.rwtrail.disk.track = dskaddr->track; 13229532Ssam dcb.trail.rwtrail.disk.sector = dskaddr->sector; 13329532Ssam } 134*31318Ssam mdcb.mdcb_head = &dcb; 135*31318Ssam mdcb.mdcb_status = 0; 136*31318Ssam VDGO(C_INFO.addr, (u_long)&mdcb, C_INFO.type); 13729532Ssam if(wait) { 13829532Ssam poll(2*60); 13929532Ssam if(vdtimeout <= 0) { 14029532Ssam printf(" in access_dsk.\n"); 14129532Ssam _longjmp(abort_environ, 1); 14229532Ssam } 14329532Ssam } 14429981Skarels wait_for_char = 1; 14529532Ssam return dcb.operrsta; 14629532Ssam } 14729532Ssam 14829532Ssam 14929532Ssam /* 15029532Ssam ** Spin_up_drive starts the drives on a controller and waits around for 15129532Ssam ** the drive to spin up if it is not already spinning. 15229532Ssam */ 15329532Ssam 15429532Ssam spin_up_drive() 15529532Ssam { 156*31318Ssam VDRESET(C_INFO.addr, C_INFO.type); 157*31318Ssam if(C_INFO.type == VDTYPE_SMDE) { 158*31318Ssam C_INFO.addr->vdcsr = 0; 159*31318Ssam C_INFO.addr->vdtcf_mdcb = AM_ENPDA; 160*31318Ssam C_INFO.addr->vdtcf_dcb = AM_ENPDA; 161*31318Ssam C_INFO.addr->vdtcf_trail = AM_ENPDA; 162*31318Ssam C_INFO.addr->vdtcf_data = AM_ENPDA; 163*31318Ssam C_INFO.addr->vdccf = CCF_SEN | 0x8 | CCF_STS | 16429532Ssam XMD_32BIT | BSZ_16WRD | CCF_ERR | 16529532Ssam CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE; 16629532Ssam } 167*31318Ssam access_with_no_trailer(VDOP_INIT, 10); 168*31318Ssam access_with_no_trailer(VDOP_DIAG, 20); 16929532Ssam configure_drive(0); 17029532Ssam } 17129532Ssam 17229532Ssam /* 17329532Ssam ** Configure_drive tells the controller what kind of drive is attached 17429532Ssam ** on a particular line. 17529532Ssam */ 17629532Ssam 17729532Ssam configure_drive(pass) 17829532Ssam int pass; 17929532Ssam { 180*31318Ssam dcb.opcode = VDOP_CONFIG; /* command */ 181*31318Ssam dcb.intflg = DCBINT_NONE; 182*31318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */ 18329532Ssam dcb.operrsta = 0; 18429532Ssam dcb.devselect = (char)cur.drive; 18529532Ssam dcb.trail.rstrail.ncyl = CURRENT->vc_ncyl; 18629532Ssam dcb.trail.rstrail.nsurfaces = CURRENT->vc_ntrak; 187*31318Ssam if(C_INFO.type == VDTYPE_VDDC) 18829532Ssam dcb.trailcnt = (char)2; 18929532Ssam else { 19029532Ssam dcb.trailcnt = (char)4; 19129532Ssam dcb.trail.rstrail.nsectors = CURRENT->vc_nsec; 19229532Ssam dcb.trail.rstrail.slip_sec = CURRENT->vc_nslip; 19329532Ssam dcb.trail.rstrail.recovery = 0x00; 194*31318Ssam C_INFO.addr->vdcylskew = (*C_INFO.cylinder_skew)(); 195*31318Ssam C_INFO.addr->vdtrackskew = (*C_INFO.track_skew)(); 19629532Ssam } 197*31318Ssam mdcb.mdcb_head = &dcb; 198*31318Ssam mdcb.mdcb_status = 0; 199*31318Ssam VDGO(C_INFO.addr, (u_long)&mdcb, C_INFO.type); 20029532Ssam poll(5); 20129532Ssam if(vdtimeout <= 0) { 20229532Ssam printf(" during drive configuration.\n"); 20329532Ssam _longjmp(abort_environ, 1); 20429532Ssam } 205*31318Ssam if(dcb.operrsta & (DCBS_OCYL | DCBS_NRDY)) { 20629532Ssam if(pass) { 20729532Ssam printf("\nDrive failed to start!\n\n"); 20829532Ssam _longjmp(abort_environ, -1); 20929532Ssam } 21029981Skarels printf("\ndrive not ready, attempting to spin up..."); 211*31318Ssam access_with_no_trailer(VDOP_START, (cur.drive * 6) + 62); 21229532Ssam DELAY((cur.drive * 5500000) + 62000000); 21329981Skarels printf(" retrying drive configuration\n"); 21429532Ssam configure_drive(1); 21529532Ssam } 21629532Ssam } 21729532Ssam 21829532Ssam 21929532Ssam /* 22029532Ssam ** data_ok checks an error status word for bit patterns 22129532Ssam ** associated with error conditions from the VDDC controller. If a hardware 22229532Ssam ** error is present then the problem is reported on the console and the program 22329532Ssam ** is halted. If a data error is present the a zero is returned. 22429532Ssam ** If everything is OK then a 1 is returned. 22529532Ssam */ 22629532Ssam 22729532Ssam data_ok() 22829532Ssam { 22929532Ssam register int status = dcb.operrsta; 23029532Ssam 23129532Ssam if(status & HARD_ERROR){ 232*31318Ssam if(status & DCBS_NRDY) 23329532Ssam printf("\nDrive is not ready!"); 234*31318Ssam else if(status & DCBS_IVA) 23529532Ssam printf("\nInvalid disk address issued!"); 236*31318Ssam else if(status & DCBS_NEM) 23729532Ssam printf("\nNon-existent memory error!"); 238*31318Ssam else if(status & DCBS_DPE) 23929532Ssam printf("\nMain memory parity error!"); 240*31318Ssam else if(status & DCBS_OAB) 24129532Ssam printf("\nCPU aborted operation!"); 242*31318Ssam else if(status & DCBS_WPT) 24329532Ssam printf("\nDrive is write protected!"); 244*31318Ssam else if(status & DCBS_SKI) 24529532Ssam printf("\nDisk seek error!"); 246*31318Ssam else if(status & DCBS_CHE) 24729532Ssam printf("\nController hardware error!"); 24829532Ssam else 24929532Ssam printf("\nNot on cylinder error!"); 25029532Ssam printf(" Status = 0x%lx", status); 251*31318Ssam if(C_INFO.type == VDTYPE_SMDE) 25229532Ssam printf(" Error code = 0x%x", dcb.err_code & 0xff); 25329532Ssam printf("\n"); 25429532Ssam printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk); 25529532Ssam printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode); 25629532Ssam reset_controller(); 25729532Ssam dcb.operrsta &= HEADER_ERROR; 25829532Ssam } 25929532Ssam return (int)(!(status & (DATA_ERROR | HEADER_ERROR))); 26029532Ssam } 26129532Ssam 26229532Ssam 26329532Ssam /* 26429532Ssam ** 26529532Ssam */ 26629532Ssam 26729532Ssam reset_controller() 26829532Ssam { 26929532Ssam printf("Resetting controller. Please wait...\n"); 27029532Ssam spin_up_drive(); 27129532Ssam printf("Controller was reset successfully.\n"); 27229532Ssam } 27329532Ssam 27429532Ssam /* 27529532Ssam ** 27629532Ssam */ 27729532Ssam 27829532Ssam static int indent_count; 27929532Ssam 28029532Ssam 28129532Ssam /* 28229532Ssam ** 28329532Ssam */ 28429532Ssam 28529532Ssam indent() 28629532Ssam { 28729532Ssam indent_count += 2; 28829532Ssam } 28929532Ssam 29029532Ssam 29129532Ssam /* 29229532Ssam ** 29329532Ssam */ 29429532Ssam 29529532Ssam exdent(count) 29629532Ssam int count; 29729532Ssam { 29829532Ssam if(count == -1) 29929532Ssam indent_count = 0; 30029532Ssam else 30129532Ssam indent_count -= count * 2; 30229532Ssam if(indent_count < 0) 30329532Ssam indent_count = 0; 30429532Ssam } 30529532Ssam 30629532Ssam 30729532Ssam /* 30829532Ssam ** 30929532Ssam */ 31029532Ssam /*VARARGS1*/ 31129532Ssam print(par0, par1, par2, par3, par4, par5, par6) 31229532Ssam char *par0, *par1, *par2, *par3, *par4, *par5, *par6; 31329532Ssam { 31429532Ssam register int count = indent_count; 31529532Ssam 31629532Ssam while(count--) 31729532Ssam printf(" "); 31829532Ssam printf(par0, par1, par2, par3, par4, par5, par6); 31929532Ssam DELAY((strlen(par0) + 20) * 9000); 32029532Ssam } 321