|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: update.c
9:
10: Abstract:
11:
12: Performs the various tape updating functions.
13:
14: Revision History:
15:
16:
17:
18:
19: --*/
20:
21: //
22: // include files
23: //
24:
25: #include <ntddk.h>
26: #include <ntddtape.h>
27: #include "common.h"
28: #include "q117.h"
29: #include "protos.h"
30:
31:
32: STATUS
33: q117UpdateHeader(
34: IN PTAPE_HEADER Header,
35: IN PQ117_CONTEXT Context
36: )
37:
38: /*++
39:
40: Routine Description:
41:
42: This routine updates the tape header.
43:
44: Arguments:
45:
46: Header -
47:
48: Context -
49:
50: Return Value:
51:
52:
53:
54: --*/
55:
56: {
57: STATUS ret;
58: PVOID scrbuf;
59: PSEGMENT_BUFFER bufferInfo;
60:
61: //
62: // put saved logical part of header into transfer buffer
63: //
64: scrbuf = q117GetFreeBuffer(&bufferInfo,Context);
65: RtlMoveMemory(scrbuf, Header, sizeof(TAPE_HEADER));
66:
67: //
68: // write out the TapeHeader structure
69: //
70: ret = q117FillTapeBlocks(
71: DWriteBad,
72: (SEGMENT)0,
73: Header->DupHeaderSegment,
74: scrbuf,
75: Header->HeaderSegment,
76: Header->DupHeaderSegment,
77: bufferInfo,
78: Context);
79: return(ret);
80: }
81:
82: STATUS
83: q117Update(
84: IN OUT PQ117_CONTEXT Context
85: )
86:
87: /*++
88:
89: Routine Description:
90:
91: This routine updates tape directory with cur_vol.
92:
93: Arguments:
94:
95: Link -
96:
97: Context -
98:
99: Return Value:
100:
101:
102:
103: --*/
104: {
105: STATUS ret; // Return value from other routines called.
106:
107: Context->ActiveVolume.DataSize = Context->CurrentOperation.BytesOnTape;
108:
109: //
110: // update volume table entry (to be written to tape directory)
111: //
112: Context->ActiveVolume.EndingSegment = (USHORT)Context->CurrentOperation.CurrentSegment-1;
113:
114:
115: if (Context->CurrentOperation.UpdateBadMap) {
116: if (ret = q117DoUpdateBad(Context))
117: return(ret);
118: }
119:
120: //
121: // update volume directory
122: //
123: // thevoldir->endblock was set to 0 at StartBack().
124: //
125: ret=q117AppVolTD(&Context->ActiveVolume,Context);
126: if (ret==NoErr) {
127: Context->CurrentOperation.EndOfUsedTape = Context->ActiveVolume.EndingSegment;
128: #ifndef NO_MARKS
129: ret = q117DoUpdateMarks(Context);
130: #endif
131: } else {
132: Context->CurrentOperation.EndOfUsedTape=0;
133: }
134:
135: //
136: // Set the tape status.
137: //
138: q117SetTpSt(Context);
139: return(ret);
140: }
141:
142:
143: STATUS
144: q117DoUpdateBad(
145: IN OUT PQ117_CONTEXT Context
146: )
147:
148: /*++
149:
150: Routine Description:
151:
152:
153:
154: Arguments:
155:
156: Context -
157:
158: Return Value:
159:
160:
161:
162: --*/
163: {
164: STATUS ret;
165: PVOID scrbuf;
166: PSEGMENT_BUFFER bufferInfo;
167: PTAPE_HEADER hdr;
168:
169: //
170: //rdr - Beta fix
171: //
172:
173: // return(BadTape);
174:
175: CheckedDump(QIC117INFO,( "Q117i: Starting DoUpdateBad\n"));
176:
177:
178: //
179: // read the header segment in
180: //
181: //if (ret = q117ReadHeaderSegment(&hdr,Context)) {
182: //
183: // return(ret);
184: //
185: //}
186: hdr = Context->CurrentTape.TapeHeader;
187:
188: //
189: // put in the new bad sector map
190: //
191:
192: //RtlMoveMemory(&(hdr->BadMap),
193: // Context->CurrentTape.BadMapPtr,
194: // sizeof(BAD_MAP));
195:
196: scrbuf = q117GetFreeBuffer(&bufferInfo,Context);
197:
198: //
199: // put saved logical part of header into transfer buffer
200: //
201:
202: RtlMoveMemory(scrbuf, hdr, sizeof(TAPE_HEADER));
203:
204: //
205: // write out the TapeHeader structure
206: //
207:
208: if ( ret = q117FillTapeBlocks(
209: DWriteBad,
210: (SEGMENT)0,
211: hdr->DupHeaderSegment,
212: scrbuf,
213: hdr->HeaderSegment,
214: hdr->DupHeaderSegment,
215: bufferInfo,
216: Context) ) {
217:
218: return(UpdErr);
219:
220: }
221:
222: //
223: // tape directory potentialy corrupted by FillTapeBlocks(), so just
224: // re-read it
225: //
226: Context->tapedir = (PIO_REQUEST)NULL;
227:
228: CheckedDump(QIC117INFO,( "Q117i: Ending DoUpdateBad (Success)\n"));
229: return(NoErr);
230: }
231:
232: #ifndef NO_MARKS
233:
234: STATUS
235: q117DoUpdateMarks(
236: IN OUT PQ117_CONTEXT Context
237: )
238:
239: /*++
240:
241: Routine Description:
242:
243:
244:
245: Arguments:
246:
247: Context -
248:
249: Return Value:
250:
251:
252:
253: --*/
254: {
255: STATUS ret;
256: PSEGMENT_BUFFER bufferInfo;
257: PVOID scrbuf;
258: PIO_REQUEST ioreq;
259:
260:
261: scrbuf = q117GetFreeBuffer(&bufferInfo,Context);
262:
263: //
264: // Fill in the mark list
265: //
266: RtlZeroMemory(scrbuf,
267: q117GoodDataBytes(
268: (SEGMENT)Context->ActiveVolume.DirectorySize, Context )
269: );
270:
271: RtlMoveMemory(scrbuf, &Context->MarkArray, sizeof(Context->MarkArray));
272:
273: ret=q117IssIOReq(scrbuf,DWrite,
274: Context->ActiveVolume.DirectorySize * BLOCKS_PER_SEGMENT,bufferInfo,Context);
275:
276: if (!ret) {
277: //
278: // Wait for data to be written
279: //
280: ioreq=q117Dequeue(WaitForItem,Context);
281:
282: ret = ioreq->Status;
283:
284: }
285:
286: return(ret);
287: }
288:
289: STATUS
290: q117GetMarks(
291: IN OUT PQ117_CONTEXT Context
292: )
293:
294: /*++
295:
296: Routine Description:
297:
298:
299:
300: Arguments:
301:
302: Context -
303:
304: Return Value:
305:
306:
307:
308: --*/
309: {
310: STATUS ret;
311: PSEGMENT_BUFFER bufferInfo;
312: PVOID scrbuf;
313: PIO_REQUEST ioreq;
314:
315:
316: scrbuf = q117GetFreeBuffer(&bufferInfo,Context);
317:
318: //
319: // Read this data block into memory
320: //
321: ret=q117IssIOReq(scrbuf,DRead,
322: Context->ActiveVolume.DirectorySize * BLOCKS_PER_SEGMENT,bufferInfo,Context);
323:
324: if (!ret) {
325: // Wait for data to be read
326: ioreq=q117Dequeue(WaitForItem,Context);
327:
328: if (ioreq->Status != BadBlk && ioreq->Status) {
329:
330: ret = ioreq->Status;
331:
332: } else {
333:
334: /* correct data segment with Reed-Solomon and Heroic retries */
335: ret = q117ReconstructSegment(ioreq,Context);
336: }
337:
338: if (!ret) {
339: RtlMoveMemory(&Context->MarkArray, scrbuf, sizeof(Context->MarkArray));
340: }
341:
342: }
343:
344: return(ret);
345: }
346: #endif
347:
348: STATUS
349: q117FillTapeBlocks(
350: IN OUT DRIVER_COMMAND Command,
351: IN SEGMENT CurrentSegment,
352: IN SEGMENT EndSegment,
353: IN OUT PVOID Buffer,
354: IN SEGMENT FirstGood,
355: IN SEGMENT SecondGood,
356: IN PSEGMENT_BUFFER BufferInfo,
357: IN PQ117_CONTEXT Context
358: )
359:
360: /*++
361:
362: Routine Description:
363:
364:
365:
366: Arguments:
367:
368: Command -
369:
370: CurrentSegment -
371:
372: EndSegment -
373:
374: Buffer -
375:
376: FirstGood -
377:
378: SecondGood -
379:
380: BufferInfo -
381:
382: Context -
383:
384: Return Value:
385:
386:
387:
388: --*/
389: {
390: STATUS ret;
391: CHAR iocmd;
392: PIO_REQUEST ioreq;
393: ULONG cur_seg = 0; // The current segment being processed
394: BAD_LIST badList[BLOCKS_PER_SEGMENT];
395: ULONG listEntry;
396: USHORT listIndex;
397:
398: //
399: // set queue into single buffer mode
400: //
401: q117QueueSingle(Context);
402:
403: //
404: // get pointer to free buffer
405: //
406: if (Buffer == NULL) {
407: Buffer = q117GetFreeBuffer(&BufferInfo,Context);
408: }
409:
410: do {
411: while(!q117QueueFull(Context) && CurrentSegment <= EndSegment) {
412: if (Command == DWriteBad && (CurrentSegment == FirstGood || CurrentSegment == SecondGood)) {
413: iocmd = DWrite;
414: } else {
415: iocmd = Command;
416: }
417:
418: //
419: // We need to skip segments with no data area (less than 4
420: // good segments)
421: //
422: while (q117GoodDataBytes(CurrentSegment,Context) <= 0) {
423: ++CurrentSegment;
424: }
425: if (ret=q117IssIOReq(Buffer,iocmd,(LONG)CurrentSegment * BLOCKS_PER_SEGMENT,BufferInfo,Context)) {
426:
427: return(ret);
428: }
429: ++CurrentSegment;
430: }
431:
432: ioreq = q117Dequeue(WaitForItem,Context);
433:
434: if ((ioreq->Status!=NoErr) &&
435: (ioreq->Status!=BadBlk) &&
436: (ioreq->Status!=BadMark)) {
437:
438: //
439: // Any Driver error except BadBlk.
440: //
441: return(ioreq->Status);
442: }
443: if (Command == DVerify) {
444:
445: if (Context->CurrentTape.TapeFormatCode == QIC_FORMAT) {
446:
447: Context->CurrentTape.BadMapPtr->BadSectors[(ioreq->Block)/BLOCKS_PER_SEGMENT] =
448: ioreq->BadList|ioreq->RetryList;
449:
450: } else {
451:
452: if ((ioreq->BadList|ioreq->RetryList) != 0l) {
453:
454: q117BadMapToBadList(
455: (SEGMENT)((ioreq->Block)/BLOCKS_PER_SEGMENT),
456: (ioreq->BadList | ioreq->RetryList),
457: badList);
458:
459: listIndex = 0;
460:
461: do {
462:
463: RtlMoveMemory(
464: Context->CurrentTape.BadMapPtr->BadList[Context->CurrentTape.CurBadListIndex++].ListEntry,
465: badList[listIndex++].ListEntry,
466: (ULONG)LIST_ENTRY_SIZE);
467:
468: listEntry = q117BadListEntryToSector(badList[listIndex].ListEntry);
469:
470: } while (listEntry &&
471: (listIndex < BLOCKS_PER_SEGMENT));
472:
473: }
474:
475: }
476:
477: }
478:
479: //
480: // Till nothing left in the queue.
481: //
482: } while (!q117QueueEmpty(Context) || CurrentSegment <= EndSegment);
483:
484: q117QueueNormal(Context);
485: return(NoErr);
486: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.