|
|
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.