|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: rcnsttrk.c
9:
10: Abstract:
11:
12: This is the tape class driver.
13:
14: Revision History:
15:
16:
17:
18:
19: --*/
20:
21: //
22: // Includes
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: q117ReconstructSegment(
34: IN PIO_REQUEST IoReq,
35: IN PQ117_CONTEXT Context
36: )
37:
38: /*++
39:
40: Routine Description:
41:
42: Reconstructs a segment of data by performing error correction
43: and heroic retries.
44:
45: Arguments:
46:
47: Return Value:
48:
49: Any driver error
50: RdncUnsc - If error correction failed
51: NoErr - If correction complete
52:
53: --*/
54:
55: {
56: IO_REQUEST req;
57: ULONG badbits,mapbits;
58: STATUS ret;
59:
60: mapbits = q117ReadBadSectorList(Context, (SEGMENT)(IoReq->Block/BLOCKS_PER_SEGMENT));
61: badbits = IoReq->BadList;
62:
63: if ( ret = q117DoCorrect(IoReq->Data,mapbits,badbits) ) {
64:
65: CheckedDump(QIC117DBGP,("Track Reconstruction required\n"));
66: CheckedDump(QIC117DBGP,("map: %08x bad:%08x\n",mapbits,badbits));
67:
68: //
69: // if error correction failed then we must re-read the data
70: // because it has been corrupted by the Reed-Solomon routines
71: //
72:
73: req.Data = IoReq->Data;
74: req.Block = IoReq->Block;
75: req.BadList = mapbits;
76: req.Command = DRetry;
77: req.Number = BLOCKS_PER_SEGMENT;
78:
79: ret = q117DoIO((PIO_REQUEST)&req, IoReq->BufferInfo,Context);
80:
81: if (ret) {
82:
83: return (ret);
84:
85: }
86:
87: if (req.Status != BadBlk && req.Status) {
88:
89: return(req.Status);
90:
91: }
92:
93: badbits = req.BadList;
94:
95: ret = q117DoCorrect(IoReq->Data, mapbits, badbits);
96: }
97: return(ret);
98: }
99:
100: STATUS
101: q117DoCorrect(
102: IN PVOID DataBuffer,
103: IN ULONG BadSectorMap,
104: IN ULONG SectorsInError
105: )
106:
107: /*++
108:
109: Routine Description:
110:
111: does the error correction for a segment (using Reed-Solomon
112: module)
113:
114: Arguments:
115:
116: Return Value:
117:
118: RdncUnsc - If error correction failed
119: NoErr - If correction complete
120:
121: --*/
122:
123: {
124: LONG i,j;
125: UCHAR offset,num_map,num_bad;
126: UCHAR s[ECC_BLOCKS_PER_SEGMENT];
127: ULONG bit_i;
128:
129: //
130: // Turn off bits for any correspondingly mapped out sectors.
131: //
132: SectorsInError &= ~BadSectorMap;
133:
134: num_map = q117CountBits(NULL, 0, BadSectorMap);
135: num_bad = q117CountBits(NULL, 0, SectorsInError);
136:
137: if (num_bad > ECC_BLOCKS_PER_SEGMENT) {
138:
139: CheckedDump(QIC117DBGP,("DoCorrect: Too many bad sectors\n"));
140:
141: return(RdncUnsc);
142:
143: }
144:
145: if (num_bad == 0) {
146:
147: if (q117RdsReadCheck(DataBuffer,(UCHAR)(BLOCKS_PER_SEGMENT-num_map)) == NoErr) {
148:
149: return(NoErr);
150:
151: }
152:
153: CheckedDump(QIC117DBGP,("CRC failure detected\n"));
154:
155:
156: }
157:
158: j = offset = 0;
159: bit_i = 1;
160:
161: //
162: // get offset into buffer (note: offset excludes bad sectors)
163: //
164: for (i = 0; i < BLOCKS_PER_SEGMENT; ++i) {
165:
166: if (!(BadSectorMap & bit_i)) {
167:
168: if (SectorsInError & bit_i) {
169:
170: s[j++] = offset;
171:
172: }
173:
174: ++offset;
175:
176: }
177:
178: //
179: // shift bit left one (same as mult by two or add to self)
180: //
181: bit_i += bit_i;
182: }
183:
184: CheckedDump(QIC117INFO,("Correct( s0: %x s1: %x s2: %x) ... ",s[0],s[1],s[2]));
185:
186: if ( q117RdsCorrect(DataBuffer,(UCHAR)(BLOCKS_PER_SEGMENT-num_map),
187: num_bad,s[0],s[1],s[2]) == NoErr ) {
188:
189: CheckedDump(QIC117INFO,("OK"));
190:
191: return(NoErr);
192:
193: } else {
194:
195: CheckedDump(QIC117INFO,("failed"));
196:
197: return(RdncUnsc);
198:
199: }
200: }
201:
202: UCHAR
203: q117CountBits(
204: IN PQ117_CONTEXT Context,
205: IN SEGMENT Segment,
206: ULONG Map
207: )
208:
209: /*++
210:
211: Routine Description:
212:
213: Counts the number of bad sectors for the segment set in "Segment" argument
214:
215: Arguments:
216:
217:
218: Return Value:
219:
220: Number of bits set
221:
222: --*/
223:
224: {
225: USHORT i;
226: UCHAR numBits;
227: ULONG tmp;
228: ULONG allBits;
229:
230:
231: numBits = 0;
232:
233: if (Context == NULL) {
234:
235: allBits = Map;
236:
237: } else {
238:
239: allBits = q117ReadBadSectorList(Context, Segment);
240:
241: }
242:
243: //
244: // Optimization (no bits set)
245: //
246:
247: if (allBits != 0) {
248:
249: tmp = 1;
250:
251: //
252: // Loop through checking all the bits
253: //
254: for (i = 0; i < BLOCKS_PER_SEGMENT; ++i) {
255:
256: if ( allBits & tmp ) {
257: ++numBits;
258: }
259:
260:
261: //
262: // shift left one (tmp *= 2 optimized)
263: //
264: tmp += tmp;
265:
266: }
267:
268: }
269:
270: return numBits;
271: }
272:
273: ULONG q117ReadBadSectorList (
274: IN PQ117_CONTEXT Context,
275: IN SEGMENT Segment
276: )
277:
278: /*++
279:
280: Routine Description:
281:
282:
283: Arguments:
284:
285: Context - Context of the driver
286:
287: Segment -
288:
289:
290: Return Value:
291:
292:
293:
294: --*/
295:
296: {
297: ULONG listEntry=0l;
298: USHORT listIndex = 0;
299: ULONG startSector;
300: ULONG endSector;
301: ULONG badSectorMap = 0l;
302: ULONG mapFlag;
303:
304: if (Context->CurrentTape.TapeFormatCode == QIC_FORMAT) {
305:
306: badSectorMap = Context->CurrentTape.BadMapPtr->BadSectors[Segment];
307:
308: } else {
309:
310: listIndex = Context->CurrentTape.CurBadListIndex;
311:
312: listEntry =
313: q117BadListEntryToSector(
314: Context->CurrentTape.BadMapPtr->BadList[listIndex].ListEntry
315: );
316:
317: //
318: // if there is no bad sector list.
319: //
320: if ((listIndex == 0) && (listEntry == 0l)) {
321:
322: badSectorMap = 0l;
323:
324: } else {
325:
326: //
327: // get the start and end sectors for the segment we are looking
328: // for.
329: //
330: startSector = (Segment * BLOCKS_PER_SEGMENT) + 1;
331: endSector = (startSector + BLOCKS_PER_SEGMENT) - 1;
332:
333:
334: //
335: // position to the start of this list
336: //
337:
338: //
339: // if we are ahead of the entry we are looking for
340: // scoot back.
341: //
342: while (listEntry > startSector && listIndex > 0) {
343:
344: --listIndex;
345:
346: listEntry =
347: q117BadListEntryToSector(
348: Context->CurrentTape.BadMapPtr->BadList[listIndex].ListEntry
349: );
350:
351: }
352:
353: //
354: // Now look forward for sectors within the range.
355: //
356: while (listEntry &&
357: (listEntry <= endSector) &&
358: (listIndex < MAX_BAD_LIST)) {
359:
360: if (listEntry >= startSector && listEntry <= endSector) {
361:
362: mapFlag = 1l << (listEntry - startSector);
363: badSectorMap |= mapFlag;
364:
365: }
366:
367: listEntry = q117BadListEntryToSector(Context->CurrentTape.BadMapPtr->BadList[listIndex++].ListEntry);
368:
369: }
370:
371: //
372: // If we walked off the end of the list (listEntry = 0),
373: // put us back on.
374: //
375: if (listEntry == 0) {
376: listIndex--;
377: }
378:
379: Context->CurrentTape.CurBadListIndex = listIndex;
380: }
381: }
382:
383: return (badSectorMap);
384: }
385:
386: USHORT
387: q117GoodDataBytes(
388: IN SEGMENT Segment,
389: IN PQ117_CONTEXT Context
390: )
391:
392: /*++
393:
394: Routine Description:
395:
396: Calculates the number of bytes (excluding bad sectors and
397: error correction sectors) within a givin segment.
398:
399: Arguments:
400:
401: Segment - segment to look up in Context->CurrentTape.BadSectorMap
402:
403: Return Value:
404:
405: Number of bytes.
406:
407: --*/
408:
409: {
410: int val;
411:
412: val = BLOCKS_PER_SEGMENT - ECC_BLOCKS_PER_SEGMENT -
413: q117CountBits(Context, Segment, 0l);
414:
415: //
416: // Value could be negitave
417: //
418: if ( val <= 0 ) {
419:
420: return(0);
421:
422: }
423:
424: return val * BYTES_PER_SECTOR;
425: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.