/* Call me TVGmTest. I use Conduant's XLR functions to read StreamStor data * from SS disks, search for TVG pattern therein, with a mask generated from * the command-line argument, if any, and verify the thus-modified TVG * pattern until either I use up all the recorded data or recieve an * interrupt. Use EndM5 for the interrupt, please. * The mask contains just one bit made from a bit number, 0 to 31, on the * command line. * Revised: 2002 March 29, JAB */ #include "Parse5A.h" #include /* For signal() to catch ^C */ void signalint(int k); /* To catch signal SIGINT (below) */ SSHANDLE dev; /* xlrDevice */ UINT indx = 1; /* Index */ S_READDESC readdesc; /* readDesc */ PS_READDESC prdesc = &readdesc; char * me; /* My name */ int msglev = 0; /* Debug message level */ int main(int argc, char * argv[]) { /* TVGmTest */ unsigned long mask = 0; int length = 32767; /* Words, length of a TVG cycle (for mask = 0) */ unsigned long long lengthb = 131068; /* Length in bytes */ unsigned long rbuff[BUFFL]; /* Read buffer */ unsigned long plapnt[2]; /* Convert to/from long long */ unsigned long long * pplapnt = (unsigned long long *) plapnt; unsigned long patsv, patrv; /* Samples of TVG pattern */ unsigned long long buffl; /* Length of recorded data, bytes */ int first, i, ii, j, k, b; /* *** Initialize *** */ me = (me = strrchr(argv[0], '/')) == NULL ? argv[0] : me+1; /* My name */ if (argc > 1) { /* Bit to mask on the command line? */ mask = 1l << atoi(argv[1]); /* Yes */ /* Calculate the length of a mask-modified cycle */ for (k = 0; k < 32768; k++) { /* Search a full cycle of TVG pattern */ if ((patrv = tvg(k == 0)) & mask) /* Skip this one? */ continue; /* Yes, to next k */ else /* First match */ break; } /* End of for k */ /* Now k is the start of a mask-modified cycle; * search for the end of this cycle */ for (i = k+1; i < k+32768; ) { /* Through a cycle */ if ((patsv = tvg(FALSE)) & mask) /* Skip this one? */ continue; /* Yes, to next i */ if (patsv == patrv) /* End? */ break; /* Yes */ i++; } /* End of for i through a cycle */ /* Now i is the end of a mask-modified cycle, so ... */ length = i-k; /* is the length of a mask-modified cycle, words */ lengthb = 4*length; /* Length in SS bytes */ } /* End of if bit to mask on the command line */ /* (Else mask stays 0, length stays 32767) */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: mask %#8.8lx, length %d \n", /* Yes */ me, mask, length); /* ** Initialize and check XLR ** */ if (XLRDeviceFind() <= 0) { /* StreamStor cards? */ (void) fprintf(stderr, "%s ERROR: \007 XLRDeviceFind() returned none \n", me); /* Error */ (void) errors(); return(-1); /* 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: \007 XLROpen() returned error \n", me); /* Nope */ (void) errors(); XLRClose(dev); /* See manual notes on XLROpen() */ return(-3); /* Error */ } if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s DEBUG: XLROpen() OK \n", me); (void) errors(); /* Check for XLR errors, but we try to go on */ signal(SIGINT, signalint); /* Catch interrupt signal */ /* SS mode to PCI for reading */ if (XLRSetMode(dev, SS_MODE_PCI) != XLR_SUCCESS) { /* Set 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); /* Error */ } (void) errors(); /* Start reading at the start of buffer */ readdesc.BufferAddr = rbuff; /* Read buffer */ readdesc.AddrHi = 0; readdesc.AddrLo = 0; readdesc.XferLength = sizeof(rbuff); /* Bytes */ *pplapnt = 0; b = 0; first = TRUE; /* ** End of initialization; start of main working loop ** */ while (TRUE) { /* Loop until break */ if (XLRRead(dev, prdesc) != XLR_SUCCESS) { /* Read into rbuff, OK? */ if (msglev < 1) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: XLRRead() returned error \n", me); (void) errors(); break; /* Out of while loop forever */ } /* End of if XLRRead() */ (void) errors(); if (first) { /* Find start of pattern? */ for (i = 7; i < 9; i++) { /* Check the first few words of the buffer */ for (k = 0; k < 32768; k++) { /* Search a full cycle of TVG pattern */ if ((patsv = tvg(k == 0)) & mask) /* Skip this one? */ continue; /* Yes, to next k */ if (prdesc->BufferAddr[i] == patsv) { /* Found? */ patrv = patsv; /* Yes, save pattern */ ii = i; /* And index for future use */ break; /* Out of for k */ } } if (k < 32768) /* Found? */ break; /* Yes, out of for i */ } if (i >= 9) { /* Found start of TVG pattern? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: Modified TVG pattern not found \n", me); break; /* Out of while loop until break */ } if (msglev < 1) { /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: k %d, i %d, patsv %#8.8lx \n", me, k, i, patsv); for (j = 0; j < 32; j++) /* Sample print */ (void) fprintf(stderr, " %4d %#8.8lx \n", j, prdesc->BufferAddr[j]); } first = FALSE; /* Never again */ } else /* Not first */ i = -1; /* Start j at start of buffer */ /* Follow TVG pattern through the buffer if possible */ for (j = i+1; j < BUFFL; ) { /* Scan (rest of) buffer */ if ((patsv = tvg(FALSE)) & mask) /* Skip this one? */ continue; /* Yes, to next tvg() */ if (prdesc->BufferAddr[j] != patsv) /* In pattern? */ break; /* No, out of for j */ j++; /* OK, still in pattern */ } /* End of for j scan buffer */ if (j < BUFFL) { /* All pattern? */ if (msglev < 2) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "\n%s WARNING: TVG pattern end, j %d b %d \n " " patsv %#8.8lx, buf %#8.8lx \n", me, j, b, patsv, prdesc->BufferAddr[j]); break; /* Out of while loop forever */ } *pplapnt += readdesc.XferLength; plapnt[0] &= 0xfffffff8; /* Now 8-byte aligned */ readdesc.AddrHi = plapnt[1]; readdesc.AddrLo = plapnt[0]; b++; if (msglev < 1) { /* Debuggery? */ if (b % 1000 == 0) /* Yes */ (void) fprintf(stderr, "#"); if (b % 70000 == 0) /* (70 per line) */ (void) fprintf(stderr, "\n"); } // if (b >= 9) /* End here? */ // break; /* Yes, out of while loop until break */ } /* End of while loop until break */ (void) fprintf(stderr, "\n%s ending after %d blocks each %d 32-bit words \n", me, b, BUFFL); (void) fprintf(stderr, "%s patsv %#8.8lx, %#8.8lx %#8.8lx %#8.8lx \n", me, patsv, prdesc->BufferAddr[j-1], prdesc->BufferAddr[j], prdesc->BufferAddr[j+1]); /* Now check the word count through the buffer */ if (b >= 9) { /* Length OK? */ buffl = XLRGetLength(dev); /* Yes, get data length, bytes */ (void) errors(); if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: buffl %Ld \n", me, buffl); /* Set up to read the last rbuff[] of data */ /* SS mode to PCI for reading */ if (XLRSetMode(dev, SS_MODE_PCI) != XLR_SUCCESS) { /* Set 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); /* Error */ } (void) errors(); readdesc.BufferAddr = rbuff; /* Read buffer */ *pplapnt = buffl - 2 * readdesc.XferLength; /* Bytes */ /* (That 2* backs it up a two full buffers from the end, * then we read one) */ // *pplapnt -= readdesc.XferLength; /* Back to previous buffer */ plapnt[0] &= 0xfffffff8; /* Now 8-byte aligned */ readdesc.AddrHi = plapnt[1]; readdesc.AddrLo = plapnt[0]; readdesc.XferLength = sizeof(rbuff); /* Bytes */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: plapnt %Ld \n", me, *pplapnt); if (XLRRead(dev, prdesc) != XLR_SUCCESS) { /* Read into rbuff, OK? */ if (msglev < 1) /* Nope. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: XLRRead() returned error \n", me); (void) errors(); } /* End of if XLRRead() not OK */ j = (lengthb - *pplapnt % lengthb) / 4 + ii; /* Index into buffer, words */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: j %d \n", me, j); (void) fprintf(stderr, "%s patsv %#8.8lx, %#8.8lx %#8.8lx %#8.8lx ", me, patrv, prdesc->BufferAddr[j-1], prdesc->BufferAddr[j], prdesc->BufferAddr[j+1]); if (patrv == prdesc->BufferAddr[j]) /* OK? */ (void) fprintf(stderr, " OK \n"); /* Yes */ else /* Not OK */ (void) fprintf(stderr, " \n"); } /* End of if b length OK */ else /* Buffer too short */ (void) fprintf(stderr, "%s WARNING: Buffer too short for skip test \n", me); XLRClose(dev); /* See manual notes on XLROpen() */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: XLRClose() done \n", me); /* Yes */ (void) errors(); return(0); /* The end */ } /* End of main = TVGmTest */ 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() */ unsigned long tvg(int init) { /* Calculate the test-vector-generator (TVG) pattern. * Reference: VSI-H Specification, Rev 1.0, 7 August 2000, available * at http://web.haystack.mit.edu/vsi/. See especially Figure 6, * page 29 and Table 13, page 20. Referring to Figure 6, q (below) * represents the Q outputs of the flip-flops, r the upper inputs of * the exors, and u the lower 16 bits of the answer (output). * Revised: 2001 December 18, JAB */ static unsigned short q; unsigned short r, u; if (init) /* Initialize? */ q = 0xffff; /* Yes */ /* Set r to a copy of q right shifted by 1 bit */ r = q >> 1; /* And set r bit 15 to a copy of q bit 2 */ if (q & 4) /* Bit 2 set? */ r |= 0x8000; /* Yes */ /* We need to overwrite r bit 14 with a copy of u bit 0, * so we need to do q exor r temporarily to get this bit */ if ((q ^ r) & 1) /* Bit 0 set? */ r |= 0x4000; /* Yes */ else /* Not set */ r &= 0xbfff; /* Now set u to q exor r */ u = q ^ r; /* Lower 16 bits of the answer */ /* For next time, set q to a copy of u right shifted by 1 bit */ q = u >> 1; /* And set q bit 15 (invisible) to a copy of q bit 0 */ if (q & 1) /* Bit 0 set? */ q |= 0x8000; /* Yes */ /* u has the lower 16 bits of the answer; the upper 16 bits * are the lower 16 bits inverted and shifted up there */ return(((unsigned long) ~u << 16) + u); } /* End of tvg() */ void signalint(int k) { /* To catch interrupt signal SIGINT */ /* (k is not used) */ extern SSHANDLE dev; /* xlrDevice */ extern char * me; /* My name */ extern int msglev; /* Debug message level */ if (msglev < 2) /* Debuggery? */ (void) fprintf(stderr, "%s INTERRUPT \n", me); /* Yes */ /* An XLRReset() here allows swapping disks after XLRClose() below */ if (XLRReset(dev) != XLR_SUCCESS) { /* OK? */ if (msglev < 2) /* No. Debuggery? */ (void) fprintf(stderr, /* Yes */ "%s WARNING: XLRReset() returned error \n", me); (void) errors(); } else if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: XLRReset() OK \n", me); XLRClose(dev); /* See manual notes on XLROpen() */ if (msglev < 1) /* Debuggery? */ (void) fprintf(stderr, "%s DEBUG: XLRClose() done \n", me); /* Yes */ if (msglev < 2) /* Debuggery? */ (void) printf("%s: The End \n", me); exit(0); /* Bye */ } /* End of signalint() */