|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: init.c
9:
10: Abstract:
11:
12: This section reads the QIC40 Header and initalizes some
13: of the Context for the rest of the system.
14:
15:
16: Revision History:
17:
18:
19:
20:
21: --*/
22:
23: //
24: // Includes
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: q117LoadTape (
36: IN OUT PTAPE_HEADER *HeaderPointer,
37: IN OUT PQ117_CONTEXT Context
38: )
39:
40: /*++
41:
42: Routine Description:
43:
44: Initialize the tape interface for read or write
45: This routine reads the bad sector map into memory.
46:
47: Arguments:
48:
49: HeaderPointer -
50:
51: Context - Context of the driver
52:
53: Return Value:
54:
55: NoErr, BadTape, any
56: Driver error except BadBlk, <EndOfVol>
57:
58: --*/
59:
60: {
61: STATUS ret; // Return value from other routines called or
62: // the status of block 1 of tracks 1-5 when read in.
63: PTAPE_HEADER hdr;
64: unsigned badSize;
65:
66: if (ret = q117InitFiler(Context)) {
67:
68: return(ret);
69:
70: }
71:
72: q117ClearQueue(Context);
73:
74: //
75: // Is defined later at ReadVolumeEntry().
76: //
77:
78: Context->CurrentOperation.EndOfUsedTape=0;
79:
80: if (!ret) {
81:
82: //
83: // this memset allows IssIOReq to find the first two
84: // good segments on the tape
85: //
86:
87: RtlZeroMemory(
88: Context->CurrentTape.BadMapPtr,
89: sizeof(BAD_MAP));
90:
91: if (!(ret = q117ReadHeaderSegment(&hdr, Context))) {
92:
93: if (HeaderPointer) {
94:
95: *HeaderPointer = (PVOID)hdr;
96:
97: }
98:
99: if (Context->CurrentTape.TapeFormatCode == QIC_FORMAT) {
100:
101: badSize = sizeof(LONG) * (hdr->LastSegment+1);
102:
103: if (badSize > Context->CurrentTape.BadSectorMapSize) {
104:
105: ret = BadTape;
106:
107: }
108:
109: }
110:
111: if (ret == NoErr) {
112:
113: //
114: // move the bad sector map into BadSectorMap array
115: //
116:
117: RtlMoveMemory(Context->CurrentTape.BadMapPtr,
118: &(hdr->BadMap), sizeof(BAD_MAP));
119: Context->CurrentTape.CurBadListIndex = 0;
120:
121: //
122: // if any bad sectors in the tape directory then don't
123: // read ahead
124: //
125:
126: if (q117CountBits(Context, Context->CurrentTape.VolumeSegment, 0l)) {
127:
128: Context->tapedir = (PIO_REQUEST)NULL;
129:
130: }
131:
132: //
133: // set global variables
134: //
135:
136: Context->CurrentTape.LastUsedSegment = Context->CurrentTape.VolumeSegment;
137:
138: //
139: // Last data block that can be written to on tape
140: //
141:
142: Context->CurrentTape.LastSegment = hdr->LastSegment;
143: Context->CurrentTape.MaximumVolumes = (USHORT) (
144: q117GoodDataBytes(hdr->FirstSegment,Context) /
145: sizeof(VOLUME_TABLE_ENTRY));
146:
147: //
148: // get number of bad sectors on tape and set CurrentTape.LastSegment to
149: // last good block
150: //
151:
152: q117GetBadSectors(Context);
153: }
154: }
155: }
156: return(ret);
157: }
158:
159:
160: STATUS
161: q117InitFiler (
162: IN OUT PQ117_CONTEXT Context
163: )
164:
165: /*++
166:
167: Routine Description:
168:
169: Initialize filer parameters before reading the tape header.
170:
171: Arguments:
172:
173: Context - Context of the driver
174:
175: Return Value:
176:
177: Driver error except BadBlk, <EndOfVol>
178:
179: --*/
180:
181: {
182: STATUS ret;
183:
184: ret = q117GetTapeCapacity(NULL,Context);
185:
186: return ret;
187: }
188:
189:
190: void
191: q117GetBadSectors (
192: IN OUT PQ117_CONTEXT Context
193: )
194:
195: /*++
196:
197: Routine Description:
198:
199: Gets the number of bad sectors on the whole tape.
200:
201: Arguments:
202:
203: Context - Context of the driver
204:
205: Return Value:
206:
207: Driver error except BadBlk, <EndOfVol>
208:
209: --*/
210:
211: {
212: ULONG badBits;
213: SEGMENT segment,lastGood;
214:
215: Context->CurrentTape.BadSectors = 0;
216:
217: //
218: // count up the bad blocks for status information
219: //
220:
221: for ( segment = 0; segment <= Context->CurrentTape.LastSegment; ++segment ) {
222:
223: badBits = q117CountBits(Context, segment, 0l);
224:
225: if (badBits >= BLOCKS_PER_SEGMENT-ECC_BLOCKS_PER_SEGMENT) {
226:
227: badBits = BLOCKS_PER_SEGMENT;
228:
229: } else {
230:
231: lastGood = segment;
232:
233: }
234:
235: Context->CurrentTape.BadSectors += badBits;
236:
237: }
238:
239:
240: //
241: // set CurrentTape.LastSegment to last good segment
242: //
243:
244: Context->CurrentTape.LastSegment = lastGood;
245: }
246:
247:
248: STATUS
249: q117ReadHeaderSegment (
250: OUT PTAPE_HEADER *HeaderPointer,
251: IN OUT PQ117_CONTEXT Context
252: )
253:
254: /*++
255:
256: Routine Description:
257:
258: Reads a QIC40 tape header. This includes reconstructing the header
259: using 100% redundancy and Reed-Solomon Error correction.
260:
261: Arguments:
262:
263: HeaderPointer -
264:
265: Context - Context of the driver
266:
267: Return Value:
268:
269: Driver error except BadBlk, <EndOfVol>
270:
271: --*/
272:
273: {
274: STATUS ret;
275: int i,j;
276: BLOCK headerBlock[2];
277: LONG headerBlockCount;
278: PVOID data;
279: PIO_REQUEST ioreq;
280: PTAPE_HEADER hdr;
281:
282: //
283: // default volume directory not loaded
284: //
285:
286: Context->tapedir = NULL;
287:
288: //
289: // read first segment from tape
290: //
291:
292: Context->CurrentOperation.CurrentSegment=0;
293:
294: Context->CurrentTape.BadSectors = headerBlockCount = 0;
295:
296: //
297: // Read the first block of the bad sector map into memory to get the
298: // size of the bad sector map.
299: //
300:
301: do {
302:
303: while (Context->CurrentOperation.CurrentSegment <=
304: Context->CurrentTape.LastSegment &&
305: !q117QueueFull(Context)) {
306:
307: if (ret = q117IssIOReq(
308: (PVOID)NULL,
309: DReadBad,
310: SEGMENT_TO_BLOCK(Context->CurrentOperation.CurrentSegment),
311: NULL,
312: Context)) {
313:
314: return(ret);
315:
316: }
317:
318: ++Context->CurrentOperation.CurrentSegment;
319:
320: }
321:
322: ioreq = q117Dequeue(WaitForItem, Context);
323:
324: ret = ioreq->Status;
325:
326: if (ret == BadBlk || ret == NoErr) {
327:
328: headerBlock[headerBlockCount++] = ioreq->Block;
329:
330: if (q117DoCorrect(ioreq->Data,0l,ioreq->BadList)) {
331:
332: ret = BadBlk;
333:
334: } else {
335:
336: ret = NoErr;
337:
338: }
339:
340: }
341:
342: if ((ret != NoErr) && (ret != BadBlk) &&
343: (ret != NoData) && (ret != BadMark)) {
344:
345: //
346: // A Driver error other tan BadBlk has occurred.
347: //
348:
349: return(ret);
350:
351: }
352:
353: } while (ret && headerBlockCount < 2 && (!q117QueueEmpty(Context) ||
354: Context->CurrentOperation.CurrentSegment <=
355: Context->CurrentTape.LastSegment));
356:
357: //
358: // if we did not find both tape header blocks and we got a bad block
359: // (or other driver error) return to caller with BadTape tape
360: //
361:
362: if (headerBlockCount < 2 && ret) {
363:
364: //
365: // All copies of the tape header are bad.
366: //
367: return(BadTape);
368: }
369:
370:
371: //
372: // if we got a bad block then we need to do 100% redundancy
373: // reconstruction
374: //
375:
376: if (ret == BadBlk) {
377:
378: ULONG badBits,curentBit;
379:
380: //
381: // clear out any pending requests
382: //
383:
384: q117ClearQueue(Context);
385:
386: //
387: // re-read the first segment (error correction
388: // routines corrupt data if they fail)
389: //
390:
391: ret = q117IssIOReq((PVOID)NULL, DReadBad, headerBlock[0],NULL,Context);
392: ioreq = q117Dequeue(WaitForItem,Context);
393: badBits = ioreq->BadList;
394: data = ioreq->Data;
395: curentBit = 1;
396:
397: for (i = 0; i < BLOCKS_PER_SEGMENT; ++i) {
398:
399: if (badBits & curentBit) {
400:
401: //
402: // try to read bad sector out of either header segment
403: //
404:
405: for ( j = 0; j < 2; ++j ) {
406:
407: if (ret = q117IssIOReq(
408: (UCHAR *)data+(BYTES_PER_SECTOR * i),
409: DRetry,
410: headerBlock[j]+i,
411: ioreq->BufferInfo,
412: Context)) {
413:
414: return(ret);
415:
416: }
417:
418: if (q117Dequeue(WaitForItem, Context)->Status == NoErr) {
419:
420: //
421: // turn off the bit (we just got a good copy
422: // of this sector)
423: //
424:
425: badBits &= ~curentBit;
426:
427: //
428: // don't try the duplicate header segment
429: //
430:
431: break;
432:
433: }
434:
435: }
436:
437: }
438:
439: //
440: // shift bit left once (optimized)
441: //
442:
443: curentBit += curentBit;
444: }
445:
446: //
447: // re-try the error correction after 100% correction
448: //
449:
450: if (q117DoCorrect(data,0l,badBits)) {
451:
452: return(BadTape);
453:
454: }
455:
456: } else {
457:
458: data = ioreq->Data;
459:
460:
461: //
462: // go on and read the volume directory if we have
463: // already queued it up
464: //
465:
466: Context->CurrentTape.VolumeSegment =
467: ((PTAPE_HEADER)ioreq->Data)->FirstSegment;
468:
469: if (Context->CurrentTape.VolumeSegment <
470: Context->CurrentOperation.CurrentSegment) {
471:
472: do {
473:
474: ioreq = q117Dequeue(WaitForItem, Context);
475:
476: } while (ioreq->Block !=
477: SEGMENT_TO_BLOCK( Context->CurrentTape.VolumeSegment ) );
478:
479: Context->tapedir = ioreq;
480: }
481:
482: q117ClearQueue(Context);
483: }
484:
485: *HeaderPointer = hdr = (PTAPE_HEADER)data;
486:
487: //
488: // make sure this is a valid QIC40 tape
489: //
490:
491: if (hdr->Signature != TapeHeaderSig) {
492:
493: return(Unformat);
494:
495: }
496:
497: if ((hdr->FormatCode != QIC_FORMAT) &&
498: (hdr->FormatCode != QICEST_FORMAT)) {
499:
500: return(UnknownFormat);
501:
502: } else {
503:
504: Context->CurrentTape.TapeFormatCode = hdr->FormatCode;
505:
506: }
507:
508: if (hdr->HeaderSegment != BLOCK_TO_SEGMENT( headerBlock[0] ) ) {
509:
510: //
511: // segment number of header
512: //
513:
514: return(BadTape);
515:
516: }
517:
518: if (headerBlockCount > 1 &&
519: hdr->DupHeaderSegment != BLOCK_TO_SEGMENT( headerBlock[1] ) ) {
520:
521: //
522: // segment number of duplicate header
523: //
524:
525: return(BadTape);
526:
527: }
528:
529:
530: Context->CurrentTape.VolumeSegment = hdr->FirstSegment;
531:
532: return(NoErr);
533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.