|
|
Power 6/32 Unix version 1.21
#include "vdfmt.h"
#include "cmd.h"
/*
**
*/
extern int wait_for_char;
static cmd_text_element nul_table[] = {
{ 0, "", "" }
};
char *clean_up = "Cleaning up... Please wait.\n";
/*
**
*/
poll(wait)
int wait;
{
int tokens[10];
wait_for_char = 0;
vdtimeout = wait*1000*1000;
uncache(&(dcb.operrsta));
while (!((dcb.operrsta) & (DCBCMP | DCBABT))) {
if(kill_processes == false) {
get_text_cmd(nul_table, tokens);
if(kill_processes == true) {
indent();
print(clean_up);
exdent(1);
}
}
vdtimeout--;
uncache(&(dcb.operrsta));
if (vdtimeout <= 0) {
if(C_INFO.type == SMDCTLR)
printf("\nVDDC");
else
printf("\nSMD-E");
printf(": Controller timeout");
VDDC_ABORT(C_INFO.addr, C_INFO.type);
DELAY(30000);
break;
}
}
if((vdtimeout > 0)) {
if(C_INFO.type == SMD_ECTLR) {
uncache(&(C_INFO.addr->cdr_csr));
while(C_INFO.addr->cdr_csr & CS_GO) {
DELAY(50);
uncache(&(C_INFO.addr->cdr_csr));
}
}
DELAY(500);
}
if((dcb.opcode == RD) || (dcb.opcode == RD_RAW))
mtpr(0, PADC);
uncache(&(dcb.operrsta));
wait_for_char = 1;
}
/*
** Access_with_no_trailer is used to perform controller functions which
** require no data movement.
*/
access_with_no_trailer(function, wait_time)
int function, wait_time;
{
dcb.opcode = function; /* command */
dcb.intflg = NOINT;
dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */
dcb.operrsta = 0;
dcb.devselect = (function == VDSTART) ? 0 : (char)cur.drive;
dcb.trailcnt = (char)0;
mdcb.firstdcb = &dcb;
mdcb.vddcstat = 0;
VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type);
poll(wait_time);
if(vdtimeout <= 0) {
printf(" during startup operation.\n");
_longjmp(abort_environ, 1);
}
return dcb.operrsta;
}
/*
** access_dsk is used by other routines to do reads and writes to the disk.
** The status of the read / write is returned to the caller for processing.
*/
access_dsk(buf, dskaddr, func, count, wait)
char *buf;
dskadr *dskaddr;
int func, count, wait;
{
cur.daddr.cylinder = dskaddr->cylinder;
cur.daddr.track = dskaddr->track;
wait_for_char = 0;
dcb.opcode = func; /* format sector command */
dcb.intflg = NOINT;
dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */
dcb.operrsta = 0;
dcb.devselect = (char)cur.drive;
if(func == SEEK) {
dcb.trailcnt = (char)(sizeof(trseek) / sizeof(long));
dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder;
dcb.trail.sktrail.skaddr.track = dskaddr->track;
dcb.trail.sktrail.skaddr.sector = dskaddr->sector;
}
else {
dcb.trailcnt = (char)(sizeof(trrw) / sizeof(long));
dcb.trail.rwtrail.memadr = buf;
dcb.trail.rwtrail.wcount=count*(CURRENT->secsize/sizeof(short));
dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder;
dcb.trail.rwtrail.disk.track = dskaddr->track;
dcb.trail.rwtrail.disk.sector = dskaddr->sector;
}
mdcb.firstdcb = &dcb;
mdcb.vddcstat = 0;
VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type);
if(wait) {
poll(2*60);
if(vdtimeout <= 0) {
printf(" in access_dsk.\n");
_longjmp(abort_environ, 1);
}
}
wait_for_char = 1;
return dcb.operrsta;
}
/*
** Spin_up_drive starts the drives on a controller and waits around for
** the drive to spin up if it is not already spinning.
*/
spin_up_drive()
{
VDDC_RESET(C_INFO.addr, C_INFO.type);
if(C_INFO.type == SMD_ECTLR) {
C_INFO.addr->cdr_csr = 0;
C_INFO.addr->mdcb_tcf = AM_ENPDA;
C_INFO.addr->dcb_tcf = AM_ENPDA;
C_INFO.addr->trail_tcf = AM_ENPDA;
C_INFO.addr->data_tcf = AM_ENPDA;
C_INFO.addr->cdr_ccf = CCF_SEN | 0x8 | CCF_STS |
XMD_32BIT | BSZ_16WRD | CCF_ERR |
CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE;
}
access_with_no_trailer(INIT, 10);
access_with_no_trailer(DIAG, 20);
configure_drive(0);
}
/*
** Configure_drive tells the controller what kind of drive is attached
** on a particular line.
*/
configure_drive(pass)
int pass;
{
dcb.opcode = RSTCFG; /* command */
dcb.intflg = NOINT;
dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */
dcb.operrsta = 0;
dcb.devselect = (char)cur.drive;
dcb.trail.rstrail.ncyl = CURRENT->ncyl;
dcb.trail.rstrail.nsurfaces = CURRENT->ntrak;
if(C_INFO.type == SMDCTLR)
dcb.trailcnt = (char)2;
else {
dcb.trailcnt = (char)4;
dcb.trail.rstrail.nsectors = CURRENT->nsec;
dcb.trail.rstrail.slip_sec = CURRENT->nslip;
dcb.trail.rstrail.recovery = 0x00;
C_INFO.addr->cyl_skew = (*C_INFO.cylinder_skew)();
C_INFO.addr->trk_skew = (*C_INFO.track_skew)();
}
mdcb.firstdcb = &dcb;
mdcb.vddcstat = 0;
VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type);
poll(5);
if(vdtimeout <= 0) {
printf(" during drive configuration.\n");
_longjmp(abort_environ, 1);
}
if(dcb.operrsta & (NOTCYLERR | DRVNRDY)) {
if(pass) {
printf("\nDrive failed to start!\n\n");
_longjmp(abort_environ, -1);
}
access_with_no_trailer(VDSTART, (cur.drive * 6) + 62);
DELAY((cur.drive * 5500000) + 62000000);
configure_drive(1);
}
}
/*
** data_ok checks an error status word for bit patterns
** associated with error conditions from the VDDC controller. If a hardware
** error is present then the problem is reported on the console and the program
** is halted. If a data error is present the a zero is returned.
** If everything is OK then a 1 is returned.
*/
data_ok()
{
register int status = dcb.operrsta;
if(status & HARD_ERROR){
if(status & DRVNRDY)
printf("\nDrive is not ready!");
else if(status & INVDADR)
printf("\nInvalid disk address issued!");
else if(status & DNEMEM)
printf("\nNon-existent memory error!");
else if(status & PARERR)
printf("\nMain memory parity error!");
else if(status & OPABRT)
printf("\nCPU aborted operation!");
else if(status & WPTERR)
printf("\nDrive is write protected!");
else if(status & DSEEKERR)
printf("\nDisk seek error!");
else if(status & CTLRERR)
printf("\nController hardware error!");
else
printf("\nNot on cylinder error!");
printf(" Status = 0x%lx", status);
if(C_INFO.type == SMD_ECTLR)
printf(" Error code = 0x%x", dcb.err_code & 0xff);
printf("\n");
printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk);
printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode);
reset_controller();
dcb.operrsta &= HEADER_ERROR;
}
return (int)(!(status & (DATA_ERROR | HEADER_ERROR)));
}
/*
**
*/
reset_controller()
{
printf("Resetting controller. Please wait...\n");
spin_up_drive();
printf("Controller was reset successfully.\n");
}
/*
**
*/
static int indent_count;
/*
**
*/
indent()
{
indent_count += 2;
}
/*
**
*/
exdent(count)
int count;
{
if(count == -1)
indent_count = 0;
else
indent_count -= count * 2;
if(indent_count < 0)
indent_count = 0;
}
/*
**
*/
/*VARARGS1*/
print(par0, par1, par2, par3, par4, par5, par6)
char *par0, *par1, *par2, *par3, *par4, *par5, *par6;
{
register int count = indent_count;
while(count--)
printf(" ");
printf(par0, par1, par2, par3, par4, par5, par6);
DELAY((strlen(par0) + 20) * 9000);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.