|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: format.c
9:
10: Abstract:
11:
12: Tells the driver to format the tape and calls Erase().
13:
14: If DoFormat is TRUE, does format pass and then bad sector mapping; else
15: does only the bad sector mapping.
16:
17:
18: Revision History:
19:
20:
21:
22:
23: --*/
24:
25: //
26: // include files
27: //
28:
29: #include <ntddk.h>
30: #include <ntddtape.h>
31: #include "common.h"
32: #include "q117.h"
33: #include "protos.h"
34:
35: #define QIC80_TRACKS_NUM (VU_80TRACKS_PER_CART * 10)
36: #define TOTAL_GAS_BLOCKS 20
37: #define QIC80_TRACKS_DENOM_FACTOR 10
38:
39: STATUS
40: q117Format(
41: OUT LONG *NumberBad,
42: IN UCHAR DoFormat,
43: IN PQIC40_VENDOR_UNIQUE VendorUnique,
44: IN OUT PQ117_CONTEXT Context
45: )
46:
47: /*++
48:
49: Routine Description:
50:
51: Formats the tape.
52:
53: Arguments:
54:
55: NumberBad - number of bad sectors
56:
57: DoFormat - flag of actually do a QIC40 format
58:
59: VendorUnique -
60:
61: Context -
62:
63: Return Value:
64:
65: NT Status
66:
67: NoErr, any Driver error, UnusTape, RdncUnsc, <LinkBack>
68:
69:
70: --*/
71:
72: {
73: STATUS ret; // Return value from other routines called.
74: PIO_REQUEST ioreq;
75: IO_REQUEST wproIoreq;
76: SEGMENT headerSegment[2];
77: SEGMENT segment;
78: ULONG numberFound;
79: PTAPE_HEADER hdr;
80: PVOID scrbuf;
81: struct S_O_DGetCap tparms; // tape parameters from the driver
82: PSEGMENT_BUFFER bufferInfo;
83:
84: //
85: // Check for write protected cart, DSndWPro will
86: // return stat = WProt in this case.
87: //
88: if (ret = q117DoCmd(&wproIoreq, DSndWPro, NULL, Context)) {
89:
90: return ret;
91:
92: }
93:
94: if (ret = q117InitFiler(Context)) {
95:
96: return(ret);
97:
98: }
99:
100: scrbuf = q117GetFreeBuffer(&bufferInfo,Context);
101:
102: if (DoFormat) {
103:
104: //
105: // Force the tape header, volume list etc, to be re-loaded
106: //
107: Context->CurrentTape.State = NeedInfoLoaded;
108:
109: *(UCHAR *)scrbuf=FORMAT_BYTE;
110:
111: q117GetTapeCapacity(&tparms,Context);
112:
113: if (ret=q117IssIOReq(scrbuf,DFmt,1l,bufferInfo,Context)) {
114:
115: //
116: // <FMemErr>
117: //
118:
119: return(ret);
120:
121: }
122:
123: ioreq = q117Dequeue(WaitForItem,Context);
124:
125: if (ioreq->Status) {
126:
127: return(ioreq->Status);
128:
129: }
130:
131: if (ret = q117GetTapeCapacity(NULL,Context)) {
132:
133: return(ret);
134:
135: }
136:
137: //
138: // clear the bad block map (erase or's in new bad sectors)
139: //
140:
141: RtlZeroMemory(
142: Context->CurrentTape.BadMapPtr,
143: sizeof(BAD_MAP));
144:
145: //
146: // verify the tape (this will set up the bad sector map)
147: //
148:
149: if (ret=q117VerifyFormat(Context)) {
150:
151: //
152: // FMemErr, UnusTape, any Driver error, <LinkBack>, RdncUnsc.
153: //
154:
155: return(ret);
156:
157: }
158:
159: //
160: // find the first two error free segments for the tape headers
161: //
162:
163: numberFound = segment = 0;
164: while (segment <= Context->CurrentTape.LastSegment && numberFound < 2) {
165:
166: if (q117CountBits(Context, segment, 0l) == 0) {
167:
168: headerSegment[numberFound++] = segment;
169:
170: }
171: ++segment;
172: }
173:
174: if (segment > Context->CurrentTape.LastSegment) {
175:
176: return(UnusTape);
177:
178: }
179:
180: //
181: // find the first segment that data can be stored in (more than
182: // 3 good sectors).
183: //
184:
185: while (q117CountBits(Context, segment, 0l) >=
186: (BLOCKS_PER_SEGMENT-ECC_BLOCKS_PER_SEGMENT) && segment <= Context->CurrentTape.LastSegment) {
187:
188: ++segment;
189:
190: }
191:
192: Context->CurrentTape.VolumeSegment = segment;
193:
194: //
195: // count up all bad sectors and find the last segment that data
196: // can be stored in.
197: //
198:
199: q117GetBadSectors(Context);
200:
201: *NumberBad = Context->CurrentTape.BadSectors;
202:
203: if (Context->CurrentTape.VolumeSegment >= Context->CurrentTape.LastSegment) {
204:
205: return(UnusTape);
206:
207: }
208:
209: //
210: // create the tape header
211: //
212:
213: hdr = (PTAPE_HEADER)scrbuf;
214:
215: if (ret = q117BuildHeader(VendorUnique,headerSegment,hdr,Context)) {
216:
217: return(ret);
218:
219: }
220:
221: q117UpdateHeader(hdr,Context);
222:
223: //
224: // Make memory image of header up to date after format.
225: //
226: RtlMoveMemory(
227: Context->CurrentTape.TapeHeader,
228: hdr,
229: sizeof(*Context->CurrentTape.TapeHeader) );
230:
231: if (!ret) {
232:
233: //
234: // erase the tape directory
235: //
236:
237: ret=q117EraseQ(Context);
238:
239: }
240: }
241: return(ret);
242: }
243:
244:
245: STATUS
246: q117BuildHeader(
247: OUT PQIC40_VENDOR_UNIQUE VendorUnique,
248: IN SEGMENT *HeaderSect,
249: IN OUT PTAPE_HEADER Header,
250: IN PQ117_CONTEXT Context
251: )
252:
253: /*++
254:
255: Routine Description:
256:
257: Builds the tape header for a format.
258:
259: Arguments:
260:
261: VendorUnique - vendor unique section
262:
263: HeaderSect - header segment array
264:
265: Header - JUMBO header
266:
267: Return Value:
268:
269:
270:
271: --*/
272:
273: {
274: STATUS ret = NoErr; // Return value from other routines called.
275: LONG divisor, dividend;
276: struct S_O_DGetCap capacity;
277:
278: //
279: // In two of the following calculations, we are changing from the number
280: // of items to the highest possible value for that item. Floppy sectors are
281: // numbered from 1 count, so the count is also the highest possible number.
282: // The rest are numbered 0 through count-1, so the highest possible number
283: // is count-1.
284: // The only fancy calculation is the number of floppy sides. This is
285: // obtained by obtaining the number of logical tape segments (SEG in the
286: // QIC-80 spec), and dividing by the number of segments per track. In addition,
287: // it may be necessary to round up in case of a remainder. To handle the
288: // remainder and the decrement simultaneuously, we decrement only if there
289: // is no remainder.
290: // See the QIC-80 spec, sec 5.3.1 on the identification of sectors, and
291: // 7.1, bytes 24 through 29, for the defined values. Wouldn't it be nice
292: // if this stuff were better documented? -- crc.
293: //
294:
295: if (!(ret = q117GetTapeCapacity(&capacity,Context))) {
296:
297: RtlZeroMemory(
298: VendorUnique,
299: sizeof(*VendorUnique));
300:
301: //
302: // Maximum floppy sectors. Warning: #define!
303: //
304:
305: VendorUnique->correct_name.MaxFlopSect =
306: capacity.MaxFSector;
307:
308: //
309: // Tape segments per tape track
310: //
311:
312: VendorUnique->correct_name.TrackSeg =
313: (USHORT)capacity.SegmentsPerTrack;
314:
315: //
316: // Tape tracks per cartridge
317: //
318:
319: VendorUnique->correct_name.CartTracks =
320: (UCHAR)capacity.TracksPerTape;
321:
322: //
323: // Maximum floppy tracks
324: //
325:
326: VendorUnique->correct_name.MaxFlopTrack =
327: capacity.FTrackPerFSide-1;
328:
329: //
330: // Maximum floppy sides
331: //
332:
333: dividend = capacity.TracksPerTape * capacity.SegmentsPerTrack;
334: divisor = capacity.SegmentsPerFTrack * capacity.FTrackPerFSide;
335: VendorUnique->correct_name.MaxFlopSide =
336: (UCHAR)(dividend / divisor);
337:
338: if( !(dividend % divisor) ) {
339:
340: VendorUnique->correct_name.MaxFlopSide--;
341:
342: }
343:
344: } else {
345:
346: return(ret);
347:
348: }
349:
350: //
351: // zero the tape header structure to start with
352: //
353:
354: RtlZeroMemory(Header,sizeof(TAPE_HEADER));
355:
356: //
357: // fill in the valid info
358: //
359:
360: Header->Signature = TapeHeaderSig; // set to 0xaa55aa55l
361: Header->FormatCode = capacity.TapeFormatCode; // set to 0x02
362: Header->HeaderSegment = (USHORT)HeaderSect[0]; // segment number of header
363: Header->DupHeaderSegment = (USHORT)HeaderSect[1]; // segment number of duplicate header
364: Header->FirstSegment = (USHORT)Context->CurrentTape.VolumeSegment; // segment number of Data area
365: Header->LastSegment = (USHORT)Context->CurrentTape.LastSegment; // segment number of End of Data area
366:
367: //
368: // time of most recent format
369: //
370: Header->CurrentFormat = 0l; // lbt_qictime()
371:
372: //
373: // time of most recent write to cartridge
374: //
375: Header->CurrentUpdate = 0l; // lbt_qictime()
376:
377: //
378: // tape name and name change date
379: //
380: Header->VendorUnique = *VendorUnique;
381:
382: Header->ReformatError = 0; // 0xff if any of remaining data is lost
383: Header->SegmentsUsed = 0; // incremented every time a segment is used
384: Header->InitialFormat = 0l; //lbt_qictime() time of initial format
385: Header->FormatCount = 1; // number of times tape has been formatted
386: Header->FailedSectors = 0; // the number entries in failed sector log
387:
388: //
389: // Set the name of manufacturer that formatted
390: //
391:
392: strcpy(Header->ManufacturerName,"Microsoft Windows NT (CMS Driver)");
393: q117SpacePadString(
394: Header->ManufacturerName,
395: sizeof(Header->ManufacturerName));
396:
397: //
398: // set format lot code
399: //
400:
401: if (Context->drive_type == QIC40_DRIVE) {
402:
403: strcpy(Header->LotCode,"User Formatted, QIC 40 rev G.");
404:
405: } else {
406:
407: strcpy(Header->LotCode,"User Formatted, QIC 80 rev D.");
408:
409: }
410:
411: q117SpacePadString(Header->LotCode,sizeof(Header->LotCode));
412:
413: //
414: // fill in bad sector map just generated
415: //
416:
417: RtlMoveMemory(
418: &(Header->BadMap),
419: Context->CurrentTape.BadMapPtr,
420: sizeof(BAD_MAP));
421:
422: return(ret);
423: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.