/* Call me SSErase. I use XLR functions to erase the SS disks. * This version accepts cond (for condition) on the command line. * If cond is 0 (FALSE), then do not condition (this is the default), * or if cond is 1, then do conditioning. This takes a LONG time, * and debuggery tells how it's going. * Usage: SSErase -m -c * Revised: 2005 May 08, JAB */ #include #include /* For atoi() */ #include #include /* For getopt(), sleep() */ #include /* For ftime() */ #include /* For TRUE, etc. */ #include "xlrapi.h" #include "Parse5A.h" #define FILL_PATTERN 0x11223344 int errors(); /* Below */ int checkDisks(); /* Below */ int getLabel(int tbank); /* Below */ int setLabel(int tbank); /* Below */ UINT indx = 1; /* Index */ SSHANDLE dev; /* xlrDevice */ S_DIR dir; /* Directory */ S_XLRSWREV swrev; /* Software and firmware versions, etc. */ S_DEVINFO devinfo; /* Device information */ S_BANKSTATUS bkstat; /* Bank status */ S_DEVSTATUS devstatus; /* Device status, devStatus */ S_DRIVESTATS dstats[XLR_MAXBINS]; /* Drive stats */ S_DRIVEINFO dinfo[16]; /* Drive information */ int range[] = { 75000, 150000, 300000, 600000, 1200000, 2400000, 4800000, -1 }; /* Defaults for dstats[].range */ char * me; /* My name */ int msglev = 1; /* Default debug message level */ int cond = FALSE; /* Default also do conditioning? */ int debg = FALSE; /* Default debug only? */ int bmode; /* Bank mode? */ char vsn[2][XLR_LABEL_LENGTH] = { "", "" }; /* Copy of VSNs */ char dms[32] = "Unknown"; /* Disk-module status */ /* (We use the same dms[] for both modules) */ char udir[sizeof(struct SDir) + sizeof(struct Vsn)]; int main(int argc, char * argv[]) { /* SSErase */ int k = 0, count = 0; long long len = 0, leno = 0; struct timeb time1, time2; /* From ftime() */ double dt; /* Time difference */ int i, j, m; unsigned int bus, obus, kbus, ms; char inLine[80]; /* ** Initialize ** */ me = (me = strrchr(argv[0], '/')) == NULL ? argv[0] : me+1; /* My name */ /* * Parse command-line options, if any * */ while (k >= 0) { switch (k = getopt(argc, argv, "hm:c:d:")) { /* That's help, msglev, cond, and debg */ case 'h' : /* Help */ (void) fprintf(stderr, "%s USAGE: \n %s -m -c \n" " where is the debug msglev (range -1 to 3, default 1), \n" " sets conditioning (0 for FALSE, 1 TRUE, default FALSE), \n", me, me); return(0); /* End here (not an error) */ break; /* (Not used) */ case 'm' : /* msglev */ /* msglev = -1 Vast quantities of debuggery prints * msglev = 0 Some debuggery prints * msglev = 1 Default and normal operation; warnings and errors print * msglev = 2 Only errors and operational messages print * msglev = 3 Nothing prints except fatal errors when program dies * (default above) */ msglev = atoi(optarg); /* (No check) */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: msglev set to %d \n", me, msglev); break; case 'c' : /* cond */ /* Conditioning, TRUE or FALSE (default above) */ cond = atoi(optarg); /* (No check) */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: cond set to %d \n", me, cond); break; case 'd' : /* debg */ /* Debuggery (only), TRUE or FALSE (default above) */ debg = atoi(optarg); /* (No check) */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: debg set to %d \n", me, debg); break; case '?' : /* Error: character not in list */ if (msglev < 2) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: Unknown option on command line \n", me); break; case ':' : /* Error: missing numerical parameter */ if (msglev < 2) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: Missing number on command line \n", me); break; default : /* Probably -1, end of parameters */ break; } /* End of switch on k */ } /* End of while k */ /* * Initialize and check XLR * */ if (XLRDeviceFind() <= 0) { /* StreamStor card? */ (void) fprintf(stderr, "%s ERROR: \007 XLRDeviceFind() returned none \n", me); /* Error */ (void) errors(); return(-1); /* XLR error */ } if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRDeviceFind() OK \n", me); (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Trying to XLROpen() ... \n", me); if (XLROpen(indx, &dev) != XLR_SUCCESS) { /* Open, OK? */ (void) fprintf(stderr, "%s ERROR: XLROpen() returned error \n", me); /* Nope */ (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-2); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLROpen() OK \n", me); /* * Get SS software and firmware versions * */ if (XLRGetVersion(dev, &swrev) != XLR_SUCCESS) { /* Version, OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRGetVersion() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-3); /* XLR error */ } if (msglev < 0) /* OK, debuggery? */ (void) fprintf(stderr, "%s DEBUG: " /* Yes */ " ApiVersion %s, ApiDateCode %s, FirmwareVersion %s, \n " " FirmDateCode %s, MonitorVersion %s, XbarVersion %s, \n " " AtaVersion %s, UAtaVersion %s, DriverVersion %s \n", me, swrev.ApiVersion, swrev.ApiDateCode, swrev.FirmwareVersion, swrev.FirmDateCode, swrev.MonitorVersion, swrev.XbarVersion, swrev.AtaVersion, swrev.UAtaVersion, swrev.DriverVersion); (void) errors(); /* * Set mode to PCI * */ /* (This should not be necessary because this should be the default) */ if (XLRSetMode(dev, SS_MODE_PCI) != XLR_SUCCESS) { /* Default mode, OK? */ (void) fprintf(stderr, "%s ERROR: \007 XLRSetMode() returned error \n", me); /* Nope */ (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-4); /* XLR error */ } (void) errors(); if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetMode() to PCI OK \n", me); /* * Device information * */ if (XLRGetDeviceInfo(dev, &devinfo) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRGetDeviceInfo() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-5); /* XLR error */ } (void) errors(); if (msglev < 0) { /* OK, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: GetDeviceInfo() OK \n", me); (void) fprintf(stderr, "%s DEBUG: BoardType %s, SerialNum %d, NumDrives %d, \n " " NumBuses %d, TotalCapacity %d * 4096 bytes \n " " MaxBandwidth %d PciBus %#x PciSlot %#x \n", me, devinfo.BoardType, devinfo.SerialNum, devinfo.NumDrives, devinfo.NumBuses, devinfo.TotalCapacity, devinfo.MaxBandwidth, devinfo.PciBus, devinfo.PciSlot); } /* * Device status * */ if (XLRGetDeviceStatus(dev, &devstatus) != XLR_SUCCESS) { /* Device Stats, OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRGetDeviceStatus() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-6); /* XLR error */ } (void) errors(); if (msglev < 0) { /* OK, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: GetDeviceStatus() OK \n", me); (void) fprintf(stderr, "%s DEBUG: ", me); if (! devstatus.SystemReady) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " SystemReady,"); if (! devstatus.BootmonReady) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " BootmonReady,"); if (! devstatus.Recording) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " Recording \n "); if (! devstatus.Playing) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " Playing,"); // if (! devstatus.VRActive[0]) // (void) fprintf(stderr, " NOT"); // (void) fprintf(stderr, " VRActive[0],"); // if (! devstatus.VRActive[1]) // (void) fprintf(stderr, " NOT"); // (void) fprintf(stderr, " VRActive[1],"); if (! devstatus.FifoActive) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " FifoActive,"); if (! devstatus.DriveFail) (void) fprintf(stderr, " NOT DriveFail \n "); else /* DriveFail--presumably an error */ (void) fprintf(stderr, " DriveFailNumber %d \n ", devstatus.DriveFailNumber); if (! devstatus.SysError) (void) fprintf(stderr, " NOT SysError,"); else /* SysError--presumably an error */ (void) fprintf(stderr, " SysErrorCode %d", devstatus.SysErrorCode); if (! devstatus.CtlrError) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " CtlrError,"); if (! devstatus.FifoFull) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " FifoFull,"); if (! devstatus.Overflow[0]) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " Overflow[0],"); if (! devstatus.Overflow[1]) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " Overflow[1] \n"); } /* End of if debuggery */ /* * To bank mode * */ /* (This should not be necessary because this should be the default) */ if (XLRSetBankMode(dev, SS_BANKMODE_NORMAL) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, "%s ERROR: XLRSetBankMode() returned error \n", me); /* Nope */ (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-7); /* XLR error */ } (void) errors(); bmode = TRUE; /* In bank mode */ if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetBankMode() to normal OK \n", me); /* * Do not skip checking directory * */ /* (This should not be necessary because this should be the default) */ if (XLRClearOption(dev, SS_OPT_SKIPCHECKDIR) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: XLRClearOption() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-8); /* XLR error */ } (void) errors(); if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRClearOption() to not skip check directory OK \n", me); /* * Make sure we're at bank A * */ if (XLRSelectBank(dev, BANK_A) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSelectBank() to A returned error \n", me); (void) errors(); return(-9); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSelectBank() to A OK \n", me); /* * Get SS directory at bank A * */ if (XLRGetDirectory(dev, &dir) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: XLRGetDirectory() returned error \n", me); (void) errors(); // XLRClose(dev); /* See manual notes on XLROpen() */ // return(-10); /* XLR error */ ? } (void) errors(); if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: SS directory Length %Ld, \n" " AppendLength %Ld, Full %d \n", me, dir.Length, dir.AppendLength, dir.Full); /* * Get status of bank A * */ if (XLRGetBankStatus(dev, BANK_A, &bkstat) != XLR_SUCCESS) { /* Status OK? */ (void) fprintf(stderr, "%s ERROR: " /* Nope */ " XLRGetBankStatus() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-11); /* XLR error */ } (void) errors(); if (msglev < 1) { /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Bank A, Label %s, \n", me, bkstat.Label); (void) fprintf(stderr, " Length %Ld,", bkstat.Length); if (bkstat.State == STATE_NOT_READY) /* State? */ (void) fprintf(stderr, " STATE_NOT_READY,"); else if (bkstat.State == STATE_TRANSITION) (void) fprintf(stderr, " STATE_TRANSITION,"); else if (bkstat.State == STATE_READY) (void) fprintf(stderr, " STATE_READY,"); if (! bkstat.Selected) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " Selected, \n "); if (! bkstat.PowerRequested) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " PowerRequested,"); if (! bkstat.PowerEnabled) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " PowerEnabled, \n "); if (bkstat.MediaStatus == MEDIASTATUS_EMPTY) /* MediaStatus */ (void) fprintf(stderr, " MEDIASTATUS_EMPTY,"); else if (bkstat.MediaStatus == MEDIASTATUS_NOT_EMPTY) (void) fprintf(stderr, " MEDIASTATUS_NOT_EMPTY,"); else if (bkstat.MediaStatus == MEDIASTATUS_FAULTED) (void) fprintf(stderr, " MEDIASTATUS_FAULTED,"); if (! bkstat.WriteProtected) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " WriteProtected,"); if (! bkstat.ErrorCode) /* Error? */ (void) fprintf(stderr, " NO error \n"); else /* Bank error */ (void) fprintf(stderr, " Error %d %d \n", bkstat.ErrorCode, bkstat.ErrorData); } /* End of if debuggery */ if (bkstat.State != STATE_READY) { /* Bank A ready? */ (void) fprintf(stderr, "%s ERROR: " /* Nope */ " Bank A must have disks ready \n", me); XLRClose(dev); /* See manual notes on XLROpen() */ return(-12); /* Setup error */ } /* * Check disks in bank A * */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Calling checkDisks() for bank A \n", me); if (checkDisks() < 0) { /* OK? */ (void) fprintf(stderr, "%s ERROR: " /* Nope */ " checkDisks() returned error \n", me); (void) errors(); XLRClose(dev); return(-13); /* Error from checkDisks() */ } /* (The following VSN business is unnecessary because the VSN is * already in bkstat.Label above) */ if (XLRGetLabel(dev, vsn[BANK_A]) != XLR_SUCCESS) { /* Get A VSN, OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRGetLabel() returned error \n", me); (void) errors(); XLRClose(dev); return(-14); /* Error */ } if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Bank A VSN %s \n", me, vsn[BANK_A]); /* * Check: Bank-A disks write protected? * */ if (bkstat.WriteProtected) { /* Protected? */ (void) fprintf(stderr, /* Yes */ "%s: Bank A is write protected. Remove this? (Y or N) ", me); (void) fgets(inLine, sizeof(inLine), stdin); /* Read from stdin */ if (strncasecmp(inLine, "Yes", 1) != 0) { /* Yes? */ (void) fprintf(stderr, "%s WARNING: NOT erased \n", me); /* Nope */ XLRClose(dev); /* See manual notes on XLROpen() */ return(1); /* Not done */ } /* Else remove protection */ if (XLRClearWriteProtect(dev) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: XLRClearWriteProtect() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-15); /* XLR error */ } /* Else write protection removed OK */ } if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Bank A is not write protected \n", me); /* * If not debug mode, then set DMS to "Error" * * (If this all works, then we reset DMS to "Erased" at the end */ if (! debg) { /* Not debug only? */ if ((k = getLabel(BANK_A)) < 0) { /* Yes, get VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: getLabel() returned error %d \n", me, k); /* (We try to go on */ } (void) strcpy(dms, "Error"); /* Set DMS to Error */ if ((k = setLabel(BANK_A)) < 0) { /* Write VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: setLabel() returned error %d \n", me, k); /* (We try to go on */ } } /* * Check: Bank B ready? * */ if (XLRGetBankStatus(dev, BANK_B, &bkstat) != XLR_SUCCESS) { /* Status OK? */ (void) fprintf(stderr, "%s ERROR: " /* Nope */ " XLRGetBankStatus() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-16); /* XLR error */ } (void) errors(); if (msglev < 1) { /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Bank B, Label %s, \n", me, bkstat.Label); (void) fprintf(stderr, " Length %Ld,", bkstat.Length); if (bkstat.State == STATE_NOT_READY) /* State? */ (void) fprintf(stderr, " STATE_NOT_READY,"); else if (bkstat.State == STATE_TRANSITION) (void) fprintf(stderr, " STATE_TRANSITION,"); else if (bkstat.State == STATE_READY) (void) fprintf(stderr, " STATE_READY,"); if (! bkstat.Selected) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " Selected, \n "); if (! bkstat.PowerRequested) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " PowerRequested,"); if (! bkstat.PowerEnabled) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " PowerEnabled, \n "); if (bkstat.MediaStatus == MEDIASTATUS_EMPTY) /* MediaStatus */ (void) fprintf(stderr, " MEDIASTATUS_EMPTY,"); else if (bkstat.MediaStatus == MEDIASTATUS_NOT_EMPTY) (void) fprintf(stderr, " MEDIASTATUS_NOT_EMPTY,"); else if (bkstat.MediaStatus == MEDIASTATUS_FAULTED) (void) fprintf(stderr, " MEDIASTATUS_FAULTED,"); if (! bkstat.WriteProtected) (void) fprintf(stderr, " NOT"); (void) fprintf(stderr, " WriteProtected,"); if (! bkstat.ErrorCode) /* Error? */ (void) fprintf(stderr, " NO error \n"); else /* Bank error */ (void) fprintf(stderr, " Error %d %d \n", bkstat.ErrorCode, bkstat.ErrorData); } /* End of if debuggery */ if (bkstat.State == STATE_READY) { /* Bank B ready? */ /* Yes, change to bank B */ if (XLRSelectBank(dev, BANK_B) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRSelectBank() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-17); /* XLR error */ } (void) errors(); /* * Check disks in bank B * */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Calling checkDisks() for bank B \n", me); if (checkDisks() < 0) { /* OK? */ (void) fprintf(stderr, "%s ERROR: " /* Nope */ " checkDisks() returned error \n", me); (void) errors(); XLRClose(dev); return(-18); /* Error */ } /* (The following VSN business is unnecessary because the VSN is * already in bkstat.Label above) */ if (XLRGetLabel(dev, vsn[BANK_B]) != XLR_SUCCESS) { /* Get B VSN, OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRGetLabel() returned error \n", me); (void) errors(); XLRClose(dev); return(-19); /* Error */ } if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Bank B VSN %s \n", me, vsn[BANK_B]); /* (We'll need these vsn[] later) */ if (bkstat.WriteProtected) { /* Bank B protected? */ (void) fprintf(stderr, /* Yes */ "%s: Bank B is write protected. Remove this? (Y or N) ", me); (void) fgets(inLine, sizeof(inLine), stdin); /* Read from stdin */ if (strncasecmp(inLine, "Yes", 1) != 0) { /* Yes? */ (void) fprintf(stderr, "%s WARNING: NOT erased \n", me); /* Nope */ XLRClose(dev); /* See manual notes on XLROpen() */ return(1); /* Not done */ } /* Else remove protection */ if (XLRClearWriteProtect(dev) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: XLRClearWriteProtect() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-20); /* XLR error */ } (void) errors(); /* Else write protection removed OK */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Bank B is not write protected \n", me); } /* End of if bank-B write protected */ /* * If not debug mode, then set DMS to "Error" * * (If this all works, then we reset DMS to "Erased" at the end */ if (! debg) { /* Not debug only? */ /* * Set DMS to "Error" * */ if ((k = getLabel(BANK_B)) < 0) { /* Get VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: getLabel() returned error %d \n", me, k); /* (We try to go on */ } (void) strcpy(dms, "Error"); /* Set DMS to Error */ if ((k = setLabel(BANK_B)) < 0) { /* Write VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: setLabel() returned error %d \n", me, k); /* (We try to go on */ } } /* Since there are also disks in bank B, we need to turn off bank mode * (to see up to 16 disks) */ if (XLRSetBankMode(dev, SS_BANKMODE_DISABLED) != XLR_SUCCESS) { /* Set to non-bank mode, OK? */ (void) fprintf(stderr, "%s ERROR: XLRSetBankMode() returned error \n", me); /* Nope */ (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-21); /* XLR error */ } (void) errors(); bmode = FALSE; /* Out of bank mode */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Bank mode disabled OK \n", /* Yes */ me); /* (Do we need devinfo again to show changes to out-of-bank mode?) */ /* * Device information * */ if (XLRGetDeviceInfo(dev, &devinfo) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: \007 XLRGetDeviceInfo() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-23); /* XLR error */ } if (msglev < 0) { /* Else OK, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Revised GetDeviceInfo() OK \n", me); (void) fprintf(stderr, "%s DEBUG: BoardType %s, SerialNum %d, NumDrives %d, \n " " NumBuses %d, TotalCapacity %d * 4096 bytes \n " " MaxBandwidth %d PciBus %#x PciSlot %#x \n", me, devinfo.BoardType, devinfo.SerialNum, devinfo.NumDrives, devinfo.NumBuses, devinfo.TotalCapacity, devinfo.MaxBandwidth, devinfo.PciBus, devinfo.PciSlot); } } /* End of if bank B (was) ready */ /* * Drive statistics * */ if (XLRSetOption(dev, SS_OPT_DRVSTATS) != XLR_SUCCESS) { /* Start collecting drive statistics, OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSetOption() drive stats returned error \n", me); /* We try to go on */ (void) errors(); } else if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetOption() drive stats OK \n", me); (void) errors(); for (i = 0; i < XLR_MAXBINS; i++) { /* Each dstats[] */ dstats[i].range = range[i]; /* Set range defaults */ dstats[i].count = 0; /* Clear counts */ } if (XLRSetDriveStats(dev, dstats) != XLR_SUCCESS) { /* Set these, OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSetDriveStats() returned error \n", me); /* We try to go on */ (void) errors(); } else if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetDriveStats() OK \n", me); (void) errors(); /* * Exit here if debuggery only * */ if (debg) { /* Debug only? */ XLRClose(dev); /* Yes */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: XLRClose() OK \n", me); /* Yes */ (void) errors(); /* (We don't reset SS, should we?) */ return(1); /* The end for this case */ } /* * Verify that the user really wants to erase or condition * */ (void) fprintf(stderr, "%s: Are you sure that you want to erase %s" "the disks in bank A%s? (Y or N) ", me, cond ? "and condition " : "", bmode ? "" : " and bank B"); (void) fgets(inLine, sizeof(inLine), stdin); /* Read from stdin */ if (strncasecmp(inLine, "Yes", 1) != 0) { /* Yes? */ (void) fprintf(stderr, "%s WARNING: NOT erased \n", me); /* Nope */ XLRClose(dev); /* See manual notes on XLROpen() */ return(1); /* Not done; the end for this case */ } /* * Instead of XLRRecord() and XLRStop(), we now do a real XLRErase(). * * And if cond, then we condition instead of just erase. */ if (XLRErase(dev, cond ? SS_OVERWRITE_RW_PATTERN : SS_OVERWRITE_NONE) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRErase() returned error \n", me); (void) errors(); /* We try to go on */ } else if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Erase start OK \n", me); /* Yes */ if (cond && msglev < 2) /* Conditioning and debuggery? */ (void) fprintf(stderr, "%s NOTE: This will run a long time \n", /* Yes */ me); if (cond && msglev < 2) /* Conditioning and debug timing? */ (void) ftime(&time1); /* Yes, what time is it? */ /* * Loop and wait for erase to finish * */ while (TRUE) { /* Loop until break */ if (XLRGetDeviceStatus(dev, &devstatus) != XLR_SUCCESS) { /* Status, OK? */ (void) fprintf(stderr, /* Nope */ "%s ERROR: XLRGetDeviceStatus() returned error \n", me); (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-24); /* XLR error */ } if (! devstatus.Recording) /* Still erasing? */ /* No, presume erase done */ break; /* Out of while loop */ if (msglev < 1) { /* Yes. Debuggery? */ if (count < 19) /* This cycle? */ count++; /* Nope, just count */ else { /* Yes, print this cycle */ /* Debug print about once a minute */ len = XLRGetLength(dev); /* To check for progress */ (void) errors(); if (len != leno) /* Progress? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: In progress, %Ld \n", me, len); else /* No progress */ (void) fprintf(stderr, /* Yes */ "%s WARNING: Erase stalled, %Ld \n", me, len); count = 0; /* Restart */ } leno = len; /* For next time */ } (void) sleep(3); /* Sleep a few seconds */ } /* End of while loop until break */ /* * Erase done * */ (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Erase ending \n", me); /* Yes */ if (cond && msglev < 2) { /* Conditioning and debug timing? */ (void) ftime(&time2); /* Yes, now what time is it? */ dt = time2.time + time2.millitm/1000.0 - time1.time - time1.millitm/1000.0; (void) fprintf(stderr, "%s DEBUG: That took %.1f seconds \n", me, dt); } /* * Now also clear the user directory * */ if (XLRSetUserDir(dev, (void *) udir, sizeof(udir)) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSetUserDir() returned error \n", me); (void) errors(); /* Error, but we try to go on */ } else /* OK */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: XLRSetUserDir() OK \n", me); /* Yes */ (void) errors(); /* * Debug print disk statistics? * */ if (msglev < 2) { /* Debuggery? */ for (j = 0; j < 16; j++) /* Yes. Each disk */ dinfo[j].Serial[0] = '\0'; /* Default: No such disk */ kbus = 0; /* Initialize count occupied buses */ obus = (unsigned int) -1; /* Initialize previously counted bus number */ for (j = 0; j < 16; j++) { /* Each disk again */ if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Start disk %d \n", me, j); /* Yes */ bus = j / 2; ms = j % 2; /* One master and one slave per bus */ /* (XLR_MASTER_DRIVE = 0, XLR_SLAVE_DRIVE = 1) */ if (XLRGetDriveInfo(dev, bus, ms, dinfo+j) != XLR_SUCCESS) { /* OK? */ if (msglev < 0) { /* Nope, debuggery? */ (void) errors(); /* Yes */ (void) fprintf(stderr, "%s WARNING: XLRGetDriveInfo() disk %d returned error \n", me, j); } (void) XLRGetLastError(); /* No, clear error */ dinfo[j].Serial[0] = '\0'; /* Assume no such disk (for later check) */ } /* End of if drive info not OK */ if (dinfo[j].Serial[0] == '\0') { /* OK? */ if (j == 8) /* Not OK. Second bank? */ break; /* Yes, out of for j; assume no more disks */ /* (Else still in first bank) */ (void) fprintf(stderr, /* No */ "%s STATS: %d : - ;\n", me, j); /* Assume no such disk */ continue; /* To next j */ } m = strspn(dinfo[j].Serial, " "); /* Starts with lots of spaces */ (void) fprintf(stderr, "%s DISK: %d, %s \n", me, j, m + dinfo[j].Serial); if (XLRGetDriveStats(dev, bus, ms, dstats) != XLR_SUCCESS) { /* OK? */ (void) errors(); /* Nope */ (void) fprintf(stderr, "%s WARNING: XLRGetDriveStats() disk %d returned error \n", me, j); } else { /* Stats OK */ (void) fprintf(stderr, "%s STATS: %d ", me, j); /* Start line */ for (i = 0; i < XLR_MAXBINS; i++) /* Each argument */ (void) fprintf(stderr, ": %ld ", dstats[i].count); (void) fprintf(stderr, ";\n"); /* After last argument */ } /* We assume that this disk is OK even if stats are not */ if (bus != obus) { /* Already counted this bus as occupied? */ kbus++; /* Nope, count it */ obus = bus; /* This bus now counted */ } /* More buses to check? */ if (kbus >= devinfo.NumBuses && ms == XLR_SLAVE_DRIVE) /* More? */ break; /* No, presumably done, out of for j */ } /* End of for j each disk */ } /* End of if debuggery to print disk statistics */ /* * If we were out of bank mode (to erase both disk packs), then * * we now go back into bank mode and erase each pack separately * * so that they can (and must) be used as separate packs without * * additional erasure. */ if (! bmode) { /* Bank mode? */ /* No, so go into bank mode */ if (XLRSetBankMode(dev, SS_BANKMODE_NORMAL) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, "%s ERROR: XLRSetBankMode() returned error \n", me); /* Nope */ (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-25); /* XLR error */ } (void) errors(); bmode = TRUE; /* Now in bank mode (not used) */ if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetBankMode() back to normal OK \n", me); /* We already know that both banks have disks ready. * Change to bank B */ if (XLRSelectBank(dev, BANK_B) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSelectBank() to B returned error \n", me); (void) errors(); return(-26); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSelectBank() to B OK \n", me); /* And erase bank B */ if (XLRErase(dev, SS_OVERWRITE_NONE) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRErase() bank B returned error \n", me); (void) errors(); return(-27); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Erased bank B OK \n", me); /* Yes */ /* Also clear the B user directory */ if (XLRSetUserDir(dev, (void *) udir, sizeof(udir)) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSetUserDir() bank B returned error \n", me); (void) errors(); return(-28); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetUserDir() bank B OK \n", me); /* We'll need to restore the B VSN (but vsn[BANK_B] is already OK) * and set DMS to "Erased" */ (void) strcpy(dms, "Erased"); if ((k = setLabel(BANK_B)) < 0) { /* Write VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: setLabel() returned error %d \n", me, k); /* (We try to go on */ } else if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Bank-B DMS set to Erased \n", me); } /* End of if (formerly) not in bank mode */ /* (Now in bank mode, regardless) */ /* * To bank A * */ if (XLRSelectBank(dev, BANK_A) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSelectBank() to A returned error \n", me); (void) errors(); return(-29); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSelectBank() to A OK \n", me); /* And erase bank A */ if (XLRErase(dev, SS_OVERWRITE_NONE) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRErase() bank A returned error \n", me); (void) errors(); return(-30); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: Erased bank A OK \n", me); /* Yes */ /* Also clear the A user directory */ if (XLRSetUserDir(dev, (void *) udir, sizeof(udir)) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLRSetUserDir() bank A returned error \n", me); (void) errors(); return(-31); /* XLR error */ } (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLRSetUserDir() bank A OK \n", me); /* * Set DMS to "Erased" * */ if ((k = getLabel(BANK_A)) < 0) { /* Get VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: getLabel() returned error %d \n", me, k); /* (We try to go on */ } (void) strcpy(dms, "Erased"); /* Set DMS to Erased */ if ((k = setLabel(BANK_A)) < 0) { /* Write VSN and DMS, OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: setLabel() returned error %d \n", me, k); /* (We try to go on */ } else if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: Bank-A DMS set to Erased \n", me); /* * Done, close * */ XLRClose(dev); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: XLRClose() OK \n", me); /* Yes */ (void) errors(); /* (We don't reset SS, should we?) */ return(0); /* The end */ } /* End of main = SSErase */ int errors() { /* XLR errors? Print XLR error code if so */ extern char * me; /* My name */ extern int msglev; /* Debug print? */ char messg[XLR_ERROR_LENGTH]; /* Error message as a string */ XLR_ERROR_CODE error; /* Return from error request */ if ((error = XLRGetLastError()) != 3) { /* Errors? */ /* Yes, get error message */ if (XLRGetErrorMessage(messg, error) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, "%s errors() ERROR: XLR error %ld, " "but XLRGetErrorMessage() failed \n", me, error); } else /* Error message, messg[], OK */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s ERROR: XLR error %ld %s \n", me, error, messg); return(TRUE); /* Yes, XLR error */ } return(FALSE); /* Else no error */ } /* End of errors() */ int checkDisks() { /* Check disks and get disk info */ static char * masl[] = { "Master", "Slave" }; static char * nok[] = { "Faulty", "OK" }; static int range[] = { 75000, 150000, 300000, 600000, 1200000, 2400000, 4800000, -1 }; /* Defaults for dstats[].range */ /* The SS card has a 15-ns-period clock, so the end of the * first bin (75000) corresponds to 0.001125 second, and each * subsequent bin to twice the one before. Since this is the * time to transfer 65528 (2^16 - 8) bytes, the minimum speed * in the first bin is about 58.25e6 bytes/sec or about * 466e6 baud. Each subsequent bin corresponds to half the * speed of the one before. */ unsigned int kount = 0; /* Initialize count disks */ int slave = FALSE; /* Any slaves? */ int npair = FALSE; /* Any master without a slave? */ int gap = FALSE; /* Gaps in bus sequence? */ int last = -1; /* Last disk found */ unsigned int bus, obus, kbus, ms; int i, j; /* * We need device info first * */ if (XLRGetDeviceInfo(dev, &devinfo) != XLR_SUCCESS) { /* OK? */ (void) fprintf(stderr, /* Nope */ "%s checkDisks() ERROR: \007 XLRGetDeviceInfo() returned error \n", me); (void) errors(); return(-6); /* Error */ } /* * Assume all disks OK until proven otherwise * */ if (XLRClearOption(dev, SS_OPT_SKIPCHECKDIR) != XLR_SUCCESS && /* OK? */ msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() ERROR: XLRClearOption() returned error \n", me); /* We try to go on */ (void) errors(); /* * Verify disk mounting * */ /* Rule: "If any drive cable has a slave drive, then all [in-use] cables * must have a slave drive. Connectors on the controller board should be * used in order without gaps starting from connector zero (0)." * (From the SS manual. "Drive cable," and "connector" mean bus.) * Here I'll try to check for this. */ for (j = 0; j < 16; j++) /* Each potential disk */ dinfo[j].Serial[0] = '\0'; /* Default: No sucn disk */ kbus = 0; /* Initialize count occupied buses */ obus = (unsigned int) -1; /* Initialize previously counted bus number */ for (j = 0; j < 16; j++) { /* Each potential disk again */ bus = j / 2; /* 0 to 7 */ ms = j % 2; /* Assume one master and one slave per bus */ /* (XLR_MASTER_DRIVE = 0, XLR_SLAVE_DRIVE = 1) */ if (XLRGetDriveInfo(dev, bus, ms, dinfo+j) != XLR_SUCCESS) { /* OK? */ (void) XLRGetLastError(); /* No, clear error */ dinfo[j].Serial[0] = '\0'; /* (For later check) */ continue; /* Assume no such disk, to next j */ } if (dinfo[j].Serial[0] == '\0') /* OK? */ continue; /* No, assume no such disk, to next j */ /* OK, here we have a disk */ kount++; /* Kount this disk */ if (bus != obus) { /* Already counted this bus as occupied? */ kbus++; /* Nope, count it */ obus = bus; /* This bus now counted */ } if (msglev < 0) { /* Debuggery? */ (void) fprintf(stderr, "%s checkDisks() DEBUG: Found disk in Bus %d %s, \n" /* Yes */ " Model %s, \n Serial %s, \n Revision %s, \n" " Capacity %d * 512 bytes \n", me, bus, masl[ms], dinfo[j].Model, dinfo[j].Serial, dinfo[j].Revision, dinfo[j].Capacity); if (dinfo[j].SMARTCapable) /* SMART? */ (void) fprintf(stderr, " SMARTState %s \n", nok[dinfo[j].SMARTState]); else /* Not SMART */ (void) fprintf(stderr, " NOT SMARTCapable \n"); } if (ms == XLR_SLAVE_DRIVE) { /* Slave? */ slave = TRUE; /* Yes, at least one slave disk */ if (last != j-1) { /* Master to match? */ (void) fprintf(stderr, /* Nope, error */ "%s checkDisks() ERROR: \007 Disks are incorrectly mounted; " "see instructions \n", me); /* Each slave must have a master */ return(-9); /* Error */ } } else /* Master */ if (last != j-1) /* Previous pair? */ npair = TRUE; /* Nope, previous master had no slave or skipped pair */ if (last != j-1 && last != j-2) /* Gap? */ gap = TRUE; /* Yes, error */ last = j; /* Last disk found and checked (for next time) */ /* More buses to check? */ if (kbus >= devinfo.NumBuses && ms == XLR_SLAVE_DRIVE) /* More? */ break; /* No, presumably done, out of for j */ } /* End of for j each potential disk */ /* XLR errors? */ (void) errors(); /* We try to go on */ /* Now kount is the number of disks counted and last is last disc */ if (kount != devinfo.NumDrives) /* OK? */ (void) fprintf(stderr, "%s checkDisks() WARNING: NumDrives %d; counted %d disks \n", me, devinfo.NumDrives, kount); /* Nope, warning */ if (gap || slave && (npair || last % 2 == 0)) { /* Disk mounting OK? */ if (msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() ERROR: \007 Disks are incorrectly mounted \n" " or faulty; trying SKIPCHECKDIR \n", me); (void) errors(); /* Assume a faulty disk, try SKIPCHECKDIR */ if (XLRSetOption(dev, SS_OPT_SKIPCHECKDIR) != XLR_SUCCESS && /* OK? */ msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() ERROR: XLRSetOption() returned error \n", me); /* We try to go on */ (void) errors(); } /* End of if disk mounting not OK */ else if (msglev < 1) /* OK, debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() DEBUG: Found %d SS disk(s); OK \n", me, kount); (void) errors(); if (XLRGetDirectory(dev, &dir) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() WARNING: XLRGetDirectory() returned error \n", me); } else /* Directory OK */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() DEBUG: SS directory Length %Ld, \n" " AppendLength %Ld, Full %d \n", me, dir.Length, dir.AppendLength, dir.Full); /* XLR errors? */ (void) errors(); /* We try to go on */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() DEBUG: Setting fill pattern \n", me); if (XLRSetFillData(dev, FILL_PATTERN) != XLR_SUCCESS) /* Set fill, OK? */ if (msglev < 2) /* Nope, debuggery? */ (void) fprintf(stderr, /* Nope */ "%s checkDisks() ERROR: \007 XLRSetFillData() returned error \n", me); /* We try to go on */ (void) errors(); /* End of initialize and check XLR */ /* ** Start collecting drive statistics and set default values ** */ if (XLRSetOption(dev, SS_OPT_DRVSTATS) != XLR_SUCCESS) /* Start collecting drive statistics, OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() ERROR: \007 XLRSetOption() returned error \n", me); /* We try to go on */ (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() DEBUG: XLRSetOption() drive statistics \n", me); for (i = 0; i < XLR_MAXBINS; i++) { /* Each dstats[] */ dstats[i].range = range[i]; /* Set range defaults */ dstats[i].count = 0; /* Clear counts */ } if (XLRSetDriveStats(dev, dstats) != XLR_SUCCESS) /* Set these, OK? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() ERROR: \007 XLRSetDriveStats() returned error \n", me); /* We try to go on */ (void) errors(); /* End of drive statistics */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s checkDisks() DEBUG: OK \n", me); return(0); /* Normal end */ } /* End of checkDisks() */ int getLabel(int tbank) { /* Read Label for bank tbank, parse into VSN and DMS */ static char bnk[] = { 'A', 'B' }; char * pchar; /* In order to cover both cases, bank==tbank or not, we use * XLRGetBankStatus() instead of XLRGetLabel() */ if (XLRGetBankStatus(dev, tbank, &bkstat) != XLR_SUCCESS) { /* OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s getLabel() ERROR: XLRGetBankStatus() returned error \n", me); return(-1); /* Error */ } (void) errors(); /* But bkstat.Label is OK only if bkstat.State is STATE_READY */ if (bkstat.State != STATE_READY) { /* OK? */ if (msglev < 1) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s getLabel() ERROR: Bank %c is not ready \n", me, bnk[tbank]); (void) errors(); return(-2); /* Error */ } /* Else OK. Separate Label into its parts: VSN preceding and DMS * following the record separator, RS = \036, if any */ if ((pchar = strchr(bkstat.Label, '\036')) == NULL) { /* Got RS? */ (void) strncpy(vsn[tbank], bkstat.Label, sizeof(vsn)/2); /* Nope */ (void) strcpy(dms, "Unknown"); } else { /* Found RS */ *pchar = '\0'; /* Terminate VSN string in bkstat.Label */ (void) strncpy(vsn[tbank], bkstat.Label, sizeof(vsn)/2); /* Copy VSN */ (void) strncpy(dms, pchar+1, sizeof(dms)); /* Copy DMS */ } if (msglev < 0) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s getLabel() DEBUG: VSN %s \n" "%s getLabel() DEBUG: DMS %s \n", me, vsn[tbank], me, dms); return(0); /* Normal end */ } /* End of getLabel() */ int setLabel(int tbank) { /* Set Label of tbank from VSN and DMS */ char label[XLR_LABEL_LENGTH]; /* Temporary copy */ (void) strncpy(label, vsn[tbank], sizeof(label)); /* Copy VSN */ (void) strncat(label, "\036", sizeof(label) - strlen(label)); /* Add RS */ (void) strncat(label, dms, sizeof(label) - strlen(label)); /* Copy DMS */ if (XLRSetLabel(dev, label, strlen(label)) != XLR_SUCCESS) { /* Write OK? */ (void) errors(); /* Nope */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s setLabel() ERROR: XLRSetLabel() returned error \n", me); return(-1); /* Error */ } return(0); /* Else normal end */ } /* End of setLabel() */