|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: stbk.c ! 9: ! 10: Abstract: ! 11: ! 12: These routines setup all of the global variables for appending ! 13: to current tape. ! 14: ! 15: ! 16: Revision History: ! 17: ! 18: ! 19: ! 20: ! 21: --*/ ! 22: ! 23: // ! 24: // include files ! 25: // ! 26: ! 27: #include <ntddk.h> ! 28: #include <ntddtape.h> ! 29: #include "common.h" ! 30: #include "q117.h" ! 31: #include "protos.h" ! 32: ! 33: ! 34: STATUS ! 35: q117StartBack( ! 36: IN OUT PVOLUME_TABLE_ENTRY TheVolumeTable, ! 37: IN PQ117_CONTEXT Context ! 38: ) ! 39: ! 40: /*++ ! 41: ! 42: Routine Description: ! 43: ! 44: This routine gets the necessry information for backing up to the ! 45: end of the current tape. ! 46: ! 47: Arguments: ! 48: ! 49: TheVolumeTable - volume table entry to be used for updating the tape ! 50: directory and for tape linking. ! 51: ! 52: Return value: ! 53: ! 54: Error in return value. ! 55: ! 56: --*/ ! 57: ! 58: { ! 59: STATUS ret = NoErr; // Return value from other routines called ! 60: LONG i; // Loop variable. ! 61: VOLUME_TABLE_ENTRY temp; ! 62: ! 63: // ! 64: // Check to see if anyone has read the last ! 65: // volume entry since Init was called ! 66: // ! 67: ! 68: if (Context->CurrentOperation.EndOfUsedTape==0) { ! 69: ! 70: // ! 71: // read tape directory (this sets CurrentOperation.EndOfUsedTape) ! 72: // ! 73: if (ret=q117GetEndBlock(&temp,&i,Context)) ! 74: ! 75: // ! 76: // RdncUnsc (had to skip over the bad sector map), any ! 77: // Driver error except BadBlk, <EndOfVol>, <LinkRC>. ! 78: // ! 79: return(ret); ! 80: } ! 81: ! 82: if (Context->ActiveVolumeNumber == Context->CurrentTape.MaximumVolumes) { ! 83: return(VolFull); ! 84: } ! 85: ! 86: if (Context->CurrentOperation.EndOfUsedTape == ! 87: Context->CurrentTape.LastSegment) { ! 88: ! 89: return(TapeFull); ! 90: ! 91: } ! 92: ! 93: // ! 94: // fill in the appropriate information in ! 95: // the volume entry ! 96: // ! 97: TheVolumeTable->Signature=VolumeTableSig; ! 98: TheVolumeTable->CreationTime = 0; // lbt_qictime() ! 99: TheVolumeTable->NotVerified = TRUE; // set if volume not verified yet ! 100: TheVolumeTable->NoNewName = FALSE; // set if new file names (redirection) disallowed ! 101: TheVolumeTable->SequenceNumber = 1; // multi-cartridge sequence number ! 102: ! 103: ret = q117StartComm(TheVolumeTable,Context); ! 104: ! 105: // ! 106: // do common initialization (start or link) ! 107: // ! 108: ! 109: return(ret); ! 110: } ! 111: ! 112: ! 113: STATUS ! 114: q117StartAppend( ! 115: IN OUT ULONG BytesAlreadyThere, ! 116: IN PVOLUME_TABLE_ENTRY TheVolumeTable, ! 117: IN OUT PQ117_CONTEXT Context ! 118: ) ! 119: ! 120: /*++ ! 121: ! 122: Routine Description: ! 123: ! 124: ! 125: ! 126: ! 127: Arguments: ! 128: ! 129: BytesAlreadyThere - ! 130: ! 131: TheVolumeTable - ! 132: ! 133: Context - ! 134: ! 135: Return Value: ! 136: ! 137: ! 138: --*/ ! 139: ! 140: { ! 141: STATUS ret = NoErr; // Return value from other routines called. ! 142: PSEGMENT_BUFFER bufferInfo; ! 143: PIO_REQUEST ioreq; ! 144: int queuePointer; ! 145: ! 146: ! 147: // ! 148: // Set up as if we were starting a backup from scratch ! 149: // ! 150: ! 151: ret = q117StartBack(TheVolumeTable,Context); ! 152: ! 153: if (!ret) { ! 154: ! 155: // ! 156: // Now advance past the existing data ! 157: // ! 158: ! 159: // ! 160: // Walk through the previous backup ! 161: // to find the ending data and segment ! 162: // ! 163: ! 164: while (BytesAlreadyThere >= ! 165: (ULONG)Context->CurrentOperation.SegmentBytesRemaining) { ! 166: ! 167: // ! 168: // Adjust counters as if we had backed up the data ! 169: // ! 170: BytesAlreadyThere -= ! 171: Context->CurrentOperation.SegmentBytesRemaining; ! 172: ! 173: Context->CurrentOperation.BytesOnTape += ! 174: Context->CurrentOperation.SegmentBytesRemaining; ! 175: ! 176: ++Context->CurrentOperation.CurrentSegment; ! 177: ! 178: Context->CurrentOperation.SegmentBytesRemaining = ! 179: q117GoodDataBytes( ! 180: Context->CurrentOperation.CurrentSegment, ! 181: Context); ! 182: } ! 183: ! 184: // ! 185: // If there is data in the segment we are going to append to ! 186: // ! 187: if (BytesAlreadyThere) { ! 188: Context->CurrentOperation.BytesOnTape += BytesAlreadyThere; ! 189: ! 190: // ! 191: // Get pointer to current buffer and buffer info ! 192: // ! 193: Context->CurrentOperation.SegmentPointer = ! 194: q117GetFreeBuffer(&bufferInfo,Context); ! 195: ! 196: queuePointer = q117GetQueueIndex(Context); ! 197: ! 198: // ! 199: // Read this data block into memory ! 200: // ! 201: ret=q117IssIOReq( ! 202: Context->CurrentOperation.SegmentPointer, ! 203: DRead, ! 204: SEGMENT_TO_BLOCK( Context->CurrentOperation.CurrentSegment), ! 205: bufferInfo, ! 206: Context); ! 207: ! 208: if (!ret) { ! 209: ! 210: // ! 211: // Wait for data to be read ! 212: // ! 213: ioreq=q117Dequeue(WaitForItem,Context); ! 214: ! 215: if (ioreq->Status != BadBlk && ioreq->Status) { ! 216: ret = ioreq->Status; ! 217: } else { ! 218: ! 219: // ! 220: // correct data segment with Reed-Solomon and ! 221: // Heroic retries ! 222: // ! 223: ret = q117ReconstructSegment(ioreq,Context); ! 224: } ! 225: } ! 226: ! 227: // ! 228: // Setup queue to write this buffer back out ! 229: // ! 230: q117SetQueueIndex(queuePointer,Context); ! 231: ! 232: // ! 233: // Now adjust pointer into buffer to point pass data ! 234: // that is already there. ! 235: // ! 236: (UCHAR *)Context->CurrentOperation.SegmentPointer += ! 237: BytesAlreadyThere; ! 238: ! 239: Context->CurrentOperation.SegmentBytesRemaining -= ! 240: (USHORT)BytesAlreadyThere; ! 241: ! 242: } ! 243: } ! 244: ! 245: return(ret); ! 246: ! 247: } ! 248: ! 249: ! 250: STATUS ! 251: q117StartComm( ! 252: OUT PVOLUME_TABLE_ENTRY TheVolumeTable, ! 253: IN OUT PQ117_CONTEXT Context ! 254: ) ! 255: ! 256: /*++ ! 257: ! 258: Routine Description: ! 259: ! 260: This routine gets the necessary information for backing up to the end ! 261: of the current tape. ! 262: ! 263: Arguments: ! 264: ! 265: TheVolumeTable - volume table entry to be used for updating the tape ! 266: directory and for tape linking. ! 267: ! 268: Return Value: ! 269: ! 270: Error in return value. ! 271: ! 272: --*/ ! 273: ! 274: { ! 275: LONG ret = NoErr; ! 276: ! 277: // ! 278: // zero out appropriate information ! 279: // ! 280: TheVolumeTable->MultiCartridge = FALSE; // set if volume spans another tape ! 281: TheVolumeTable->DirectorySize = 0; // number of bytes reserved for directory ! 282: TheVolumeTable->DataSize = 0; // size of data area (includes other cartridges) ! 283: TheVolumeTable->EndingSegment = 0; ! 284: TheVolumeTable->NoNewName = FALSE; // allow restoring to new name (re-direction) ! 285: TheVolumeTable->reserved = 0; // QIC-40 spec. says to zero this out ! 286: ! 287: // ! 288: // set global variables ! 289: // ! 290: Context->CurrentOperation.CurrentSegment = ! 291: Context->CurrentOperation.EndOfUsedTape+1; ! 292: ! 293: Context->CurrentOperation.LastSegment = Context->CurrentTape.LastSegment; ! 294: ! 295: // clear out the flag for update of bad map ! 296: Context->CurrentOperation.UpdateBadMap = FALSE; ! 297: ! 298: Context->CurrentOperation.BytesZeroFilled = 0; ! 299: Context->CurrentOperation.BytesOnTape = 0; ! 300: Context->CurrentOperation.SegmentPointer = q117GetFreeBuffer(NULL, Context); ! 301: ! 302: #ifndef NO_MARKS ! 303: ! 304: // ! 305: // We need to skip segments with no data area (too many bad sectors) ! 306: // ! 307: while ((Context->CurrentOperation.SegmentBytesRemaining = ! 308: q117GoodDataBytes( ! 309: Context->CurrentOperation.CurrentSegment, ! 310: Context) ! 311: ) <= 0) { ! 312: ! 313: ++Context->CurrentOperation.CurrentSegment; ! 314: } ! 315: ! 316: ! 317: // ! 318: // Use the directorySize field to store the segment that has marks ! 319: // ! 320: TheVolumeTable->DirectorySize = ! 321: (ULONG)Context->CurrentOperation.CurrentSegment++; ! 322: ! 323: #endif ! 324: ! 325: // ! 326: // We need to skip segments with no data area (too many bad sectors) ! 327: // ! 328: while ((Context->CurrentOperation.SegmentBytesRemaining = q117GoodDataBytes( ! 329: Context->CurrentOperation.CurrentSegment, ! 330: Context)) <= 0) { ! 331: ++Context->CurrentOperation.CurrentSegment; ! 332: } ! 333: ! 334: TheVolumeTable->StartSegment = Context->CurrentOperation.CurrentSegment; ! 335: return(ret); ! 336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.