|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1992 Microsoft Corporation
4:
5: Module Name:
6:
7: tandqic.c
8:
9: Abstract:
10:
11: This module contains device specific routines for Tandberg QIC
12: drives with SCSI-2 interfaces -- TDC 4220, TDC 4120, TDC 3820,
13: and TDC 3660.
14:
15: Author:
16:
17: Mike Colandreo (Maynard)
18:
19: Environment:
20:
21: kernel mode only
22:
23: Revision History:
24:
25: --*/
26:
27: #include "ntddk.h"
28: #include "tape.h"
29: #include "physlogi.h"
30:
31: //
32: // Internal (module wide) defines that symbolize
33: // non-QFA mode and the two QFA mode partitions.
34: //
35: #define NO_PARTITIONS 0 // non-QFA mode
36: #define DIRECTORY_PARTITION 1 // QFA mode, directory partition #
37: #define DATA_PARTITION 2 // QFA mode, data partition #
38:
39: //
40: // Internal (module wide) defines that symbolize
41: // the Tandberg QIC drives supported by this module.
42: //
43: #define TDC_3600 (ULONG)1 // aka the TDC 3660
44: #define TDC_3800 (ULONG)2 // aka the TDC 3820
45: #define TDC_4100 (ULONG)3 // aka the TDC 4120
46: #define TDC_4200 (ULONG)4 // aka the TDC 4220
47:
48: //
49: // Function Prototype(s) for internal function(s)
50: //
51: static
52: NTSTATUS
53: GetInquiryInformationData (
54: IN PDEVICE_OBJECT DeviceObject,
55: IN PIRP Irp,
56: OUT PINQUIRYDATA InquiryBuffer
57: );
58:
59: static
60: NTSTATUS
61: RewindToBOT(
62: IN PDEVICE_OBJECT DeviceObject,
63: IN PIRP Irp
64: );
65:
66: static
67: ULONG
68: WhichIsIt(
69: IN PINQUIRYDATA InquiryData
70: );
71:
72:
73: NTSTATUS
74: TapeCreatePartition(
75: IN PDEVICE_OBJECT DeviceObject,
76: IN PIRP Irp
77: )
78:
79: /*++
80: Routine Description:
81:
82: This routine can either "create" two, fixed, QFA partitions on a QIC
83: tape by selecting/enabling the drive's dual-partition, QFA mode or
84: return the drive to the not partitioned mode (i.e., disable QFA mode).
85: Note that this function "creates" two partitions only in a conceptual
86: sense -- it does not physically affect tape.
87:
88: Arguments:
89:
90: DeviceObject
91: Irp
92:
93: Return Value:
94:
95: NTSTATUS
96:
97: --*/
98:
99: {
100: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
101: PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer;
102: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
103: PMODE_MEDIUM_PART_PAGE buffer;
104: SCSI_REQUEST_BLOCK srb;
105: PCDB cdb = (PCDB)srb.Cdb;
106: NTSTATUS status;
107:
108: //
109: // Only support 2 partitions, QFA mode
110: // Partition 1 = Used as directory
111: // Partition 0 = used as data
112: //
113: // Note that 0 & 1 are partition numbers used
114: // by the drive -- they are not tape API partition
115: // numbers.
116: //
117:
118: DebugPrint((3,"TapeCreatePartition: Enter routine\n"));
119:
120: switch (tapePartition->Method) {
121: case TAPE_FIXED_PARTITIONS:
122: DebugPrint((3,"TapeCreatePartition: fixed partitions\n"));
123: break;
124:
125: case TAPE_SELECT_PARTITIONS:
126: case TAPE_INITIATOR_PARTITIONS:
127: default:
128: DebugPrint((1,"TapeCreatePartition: "));
129: DebugPrint((1,"PartitionMethod -- operation not supported\n"));
130: return STATUS_NOT_IMPLEMENTED;
131: }
132:
133: //
134: // Must rewind to BOT before one can enable/disable QFA mode.
135: // Changing the value of the FDP bit is only valid at BOT.
136: // FDP bit is used to enable/disable "additional partitions"
137: // (mode sense command).
138: //
139:
140: DebugPrint((3,"TapeCreatePartition: SendSrb (rewind)\n"));
141:
142: status = RewindToBOT(DeviceObject, Irp);
143:
144: if (!NT_SUCCESS(status)) {
145: DebugPrint((1,"TapeCreatePartition: rewind, SendSrb unsuccessful\n"));
146: return status;
147: }
148:
149: //
150: // Performing mode select command, medium partition parameters page,
151: // to enable/disable QFA mode: set the FDP bit accordingly.
152: //
153:
154: buffer = ExAllocatePool(NonPagedPoolCacheAligned,
155: sizeof(MODE_MEDIUM_PART_PAGE));
156:
157: if (!buffer) {
158: DebugPrint((1,"TapeCreatePartition: insufficient resources (buffer)\n"));
159: return STATUS_INSUFFICIENT_RESOURCES;
160: }
161:
162: RtlZeroMemory(buffer, sizeof(MODE_MEDIUM_PART_PAGE));
163:
164: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
165:
166: buffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION;
167: buffer->MediumPartPage.PageLength = 0x06;
168: buffer->MediumPartPage.MaximumAdditionalPartitions = 1;
169:
170: //
171: // Setup FDP bit to enable/disable "additional partition".
172: //
173:
174: if (tapePartition->Count == 0) {
175: buffer->MediumPartPage.FDPBit = SETBITOFF;
176: } else {
177: buffer->MediumPartPage.FDPBit = SETBITON;
178: }
179:
180: //
181: // Zero CDB in SRB on stack.
182: //
183:
184: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
185:
186: //
187: // Prepare SCSI command (CDB)
188: //
189:
190: srb.CdbLength = CDB6GENERIC_LENGTH;
191:
192: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
193: cdb->MODE_SELECT.PFBit = SETBITON;
194: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE) - 4;
195:
196: //
197: // Set timeout value.
198: //
199:
200: srb.TimeOutValue = deviceExtension->TimeOutValue;
201:
202: //
203: // Send SCSI command (CDB) to device
204: //
205:
206: DebugPrint((3,"TapeCreatePartition: SendSrb (mode select)\n"));
207:
208: status = ScsiClassSendSrbSynchronous(DeviceObject,
209: &srb,
210: buffer,
211: sizeof(MODE_MEDIUM_PART_PAGE) - 4,
212: TRUE);
213:
214: ExFreePool(buffer);
215:
216: if (NT_SUCCESS(status)) {
217:
218: if (tapePartition->Count == 0) {
219: tapeData->CurrentPartition = NO_PARTITIONS;
220: DebugPrint((3,"TapeCreatePartition: QFA disabled\n"));
221: } else {
222: tapeData->CurrentPartition = DATA_PARTITION;
223: DebugPrint((3,"TapeCreatePartition: QFA enabled\n"));
224: }
225:
226: } else {
227:
228: DebugPrint((1,"TapeCreatePartition: mode select, SendSrb unsuccessful\n"));
229:
230: }
231:
232: return status;
233:
234: } // end TapeCreatePartition()
235:
236:
237: NTSTATUS
238: TapeErase(
239: IN PDEVICE_OBJECT DeviceObject,
240: IN PIRP Irp
241: )
242:
243: /*++
244: Routine Description:
245:
246: This routine erases the entire tape. The Tandberg QIC drives cannot
247: partially erase tape. Positioning the tape at BOT is a prerequisite:
248: the drive rejects the command if the tape is not at BOT.
249:
250: Arguments:
251:
252: DeviceObject
253: Irp
254:
255: Return Value:
256:
257: NTSTATUS
258:
259: --*/
260:
261: {
262: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
263: PTAPE_ERASE tapeErase = Irp->AssociatedIrp.SystemBuffer;
264: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
265: SCSI_REQUEST_BLOCK srb;
266: PCDB cdb = (PCDB)srb.Cdb;
267: NTSTATUS status;
268:
269: DebugPrint((3,"TapeErase: Enter routine\n"));
270:
271: if (tapeErase->Immediate) {
272: switch (tapeErase->Type) {
273: case TAPE_ERASE_LONG:
274: DebugPrint((3,"TapeErase: immediate\n"));
275: break;
276:
277: case TAPE_ERASE_SHORT:
278: default:
279: DebugPrint((1,"TapeErase: EraseType, immediate -- operation not supported\n"));
280: return STATUS_NOT_IMPLEMENTED;
281: }
282: }
283:
284: switch (tapeErase->Type) {
285: case TAPE_ERASE_LONG:
286: DebugPrint((3,"TapeErase: long\n"));
287: break;
288:
289: case TAPE_ERASE_SHORT:
290: default:
291: DebugPrint((1,"TapeErase: EraseType -- operation not supported\n"));
292: return STATUS_NOT_IMPLEMENTED;
293: }
294:
295: //
296: // Zero CDB in SRB on stack.
297: //
298:
299: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
300:
301: //
302: // Prepare SCSI command (CDB)
303: //
304:
305: srb.CdbLength = CDB6GENERIC_LENGTH;
306:
307: cdb->ERASE.OperationCode = SCSIOP_ERASE;
308: cdb->ERASE.Immediate = tapeErase->Immediate;
309: cdb->ERASE.Long = SETBITON;
310:
311: //
312: // Set timeout value.
313: //
314:
315: srb.TimeOutValue = 360;
316:
317: //
318: // Send SCSI command (CDB) to device
319: //
320:
321: DebugPrint((3,"TapeErase: SendSrb (erase)\n"));
322:
323: status = ScsiClassSendSrbSynchronous(DeviceObject,
324: &srb,
325: NULL,
326: 0,
327: FALSE);
328:
329: if (!NT_SUCCESS(status)) {
330: DebugPrint((1,"TapeErase: erase, SendSrb unsuccessful\n"));
331: return status;
332: }
333:
334: if (tapeData->CurrentPartition) {
335: tapeData->CurrentPartition = DATA_PARTITION;
336: }
337:
338: return status;
339:
340: } // end TapeErase()
341:
342:
343: VOID
344: TapeError(
345: PDEVICE_OBJECT DeviceObject,
346: PSCSI_REQUEST_BLOCK Srb,
347: NTSTATUS *Status,
348: BOOLEAN *Retry
349: )
350:
351: /*++
352:
353: Routine Description:
354:
355: When a request completes with error, the routine InterpretSenseInfo is
356: called to determine from the sense data whether the request should be
357: retried and what NT status to set in the IRP. Then this routine is called
358: for tape requests to handle tape-specific errors and update the nt status
359: and retry boolean.
360:
361: Arguments:
362:
363: DeviceObject - Supplies a pointer to the device object.
364:
365: Srb - Supplies a pointer to the failing Srb.
366:
367: Status - NT Status used to set the IRP's completion status.
368:
369: Retry - Indicates that this request should be retried.
370:
371: Return Value:
372:
373: None.
374:
375: --*/
376:
377: {
378: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
379: PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
380: NTSTATUS status = *Status;
381: BOOLEAN retry = *Retry;
382:
383: DebugPrint((3,"TapeError: Enter routine\n"));
384: DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", status, retry));
385: return;
386:
387: } // end TapeError()
388:
389:
390: NTSTATUS
391: TapeGetDriveParameters(
392: IN PDEVICE_OBJECT DeviceObject,
393: IN PIRP Irp
394: )
395:
396: /*++
397: Routine Description:
398:
399: This routine determines and returns the "drive parameters" of the
400: Tandberg QIC tape drive associated with "DeviceObject". From time
401: to time, the drive paramater set of a given drive will vary. It will
402: change as drive operating characteristics change: e.g., tape media
403: type loaded, recording density of the media type loaded, etc.
404:
405: Arguments:
406:
407: DeviceObject
408: Irp
409:
410: Return Value:
411:
412: NTSTATUS
413:
414: --*/
415:
416: {
417: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
418: PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
419: PMODE_PARM_READ_WRITE_DATA modeParmBuffer;
420: PREAD_BLOCK_LIMITS_DATA blockLimits;
421: PINQUIRYDATA inquiryBuffer;
422: UCHAR densityCode;
423: UCHAR mediumType;
424: ULONG tapeBlockLength;
425: ULONG whichdrive;
426: SCSI_REQUEST_BLOCK srb;
427: PCDB cdb = (PCDB)srb.Cdb;
428: NTSTATUS status;
429:
430: DebugPrint((3,"TapeGetDriveParameters: Enter routine\n"));
431:
432: RtlZeroMemory(tapeGetDriveParams, sizeof(TAPE_GET_DRIVE_PARAMETERS));
433: Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
434:
435: modeParmBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
436: sizeof(MODE_PARM_READ_WRITE_DATA));
437:
438: if (!modeParmBuffer) {
439: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (modeParmBuffer)\n"));
440: return STATUS_INSUFFICIENT_RESOURCES;
441: }
442:
443: RtlZeroMemory(modeParmBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
444:
445: //
446: // Zero CDB in SRB on stack.
447: //
448:
449: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
450:
451: //
452: // Prepare SCSI command (CDB)
453: //
454:
455: srb.CdbLength = CDB6GENERIC_LENGTH;
456:
457: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
458: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_PARM_READ_WRITE_DATA);
459:
460: //
461: // Set timeout value.
462: //
463:
464: srb.TimeOutValue = deviceExtension->TimeOutValue;
465:
466: //
467: // Send SCSI command (CDB) to device
468: //
469:
470: DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode sense)\n"));
471:
472: status = ScsiClassSendSrbSynchronous(DeviceObject,
473: &srb,
474: modeParmBuffer,
475: sizeof(MODE_PARM_READ_WRITE_DATA),
476: FALSE);
477:
478: if (NT_SUCCESS(status)) {
479:
480: mediumType = modeParmBuffer->ParameterListHeader.MediumType;
481: densityCode = modeParmBuffer->ParameterListBlock.DensityCode;
482: tapeBlockLength = modeParmBuffer->ParameterListBlock.BlockLength[2];
483: tapeBlockLength += (modeParmBuffer->ParameterListBlock.BlockLength[1] << 8);
484: tapeBlockLength += (modeParmBuffer->ParameterListBlock.BlockLength[0] << 16);
485:
486: switch (mediumType) {
487: case 1:
488: mediumType = DC600;
489: break;
490:
491: case 2:
492: mediumType = DC6150;
493: break;
494:
495: case 3:
496: mediumType = DC6320;
497: break;
498:
499: }
500:
501: }
502:
503: ExFreePool(modeParmBuffer);
504:
505: if (!NT_SUCCESS(status)) {
506: DebugPrint((1,"TapeGetDriveParameters: mode sense, SendSrb unsuccessful\n"));
507: return status;
508: }
509:
510: blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
511: sizeof(READ_BLOCK_LIMITS_DATA));
512:
513: if (!blockLimits) {
514: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (blockLimits)\n"));
515: return STATUS_INSUFFICIENT_RESOURCES;
516: }
517:
518: RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));
519:
520: //
521: // Zero CDB in SRB on stack.
522: //
523:
524: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
525:
526: //
527: // Prepare SCSI command (CDB)
528: //
529:
530: srb.CdbLength = CDB6GENERIC_LENGTH;
531:
532: cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
533:
534: //
535: // Set timeout value.
536: //
537:
538: srb.TimeOutValue = deviceExtension->TimeOutValue;
539:
540: //
541: // Send SCSI command (CDB) to device
542: //
543:
544: DebugPrint((3,"TapeGetDriveParameters: SendSrb (read block limits)\n"));
545:
546: status = ScsiClassSendSrbSynchronous(DeviceObject,
547: &srb,
548: blockLimits,
549: sizeof(READ_BLOCK_LIMITS_DATA),
550: FALSE);
551:
552: if (NT_SUCCESS(status)) {
553: tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
554: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
555: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);
556:
557: tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
558: tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
559: }
560:
561: ExFreePool(blockLimits);
562:
563: if (!NT_SUCCESS(status)) {
564: DebugPrint((1,"TapeGetDriveParameters: read block limits, SendSrb unsuccessful\n"));
565: return status;
566: }
567:
568: inquiryBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
569: sizeof(INQUIRYDATA));
570:
571: if (!inquiryBuffer) {
572: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (inquiryBuffer)\n"));
573: return STATUS_INSUFFICIENT_RESOURCES;
574: }
575:
576: RtlZeroMemory(inquiryBuffer, sizeof(INQUIRYDATA));
577:
578: //
579: // Send SCSI command (CDB) to device
580: //
581:
582: DebugPrint((3,"TapeGetDriveParameters: SendSrb (inquiry)\n"));
583:
584: status = GetInquiryInformationData(DeviceObject, Irp, inquiryBuffer);
585:
586: if (NT_SUCCESS(status)) {
587:
588: //
589: // Which drive do we have, TDC 3660, 3820, 4120 or 4220?
590: //
591:
592: whichdrive = WhichIsIt(inquiryBuffer);
593: }
594:
595: ExFreePool(inquiryBuffer);
596:
597: if (!NT_SUCCESS(status)) {
598: DebugPrint((1,"TapeGetDriveParameters: inquiry, SendSrb unsuccessful\n"));
599: return status;
600: }
601:
602: tapeGetDriveParams->ECC = 0;
603: tapeGetDriveParams->Compression = 0;
604: tapeGetDriveParams->DataPadding = 0;
605: tapeGetDriveParams->MaximumPartitionCount = 2;
606:
607: if ((whichdrive == TDC_4100) || (whichdrive == TDC_4200)) {
608:
609: tapeGetDriveParams->ReportSetmarks = TRUE;
610:
611: tapeGetDriveParams->FeaturesLow |=
612: TAPE_DRIVE_REPORT_SMKS;
613:
614: tapeGetDriveParams->FeaturesHigh |=
615: TAPE_DRIVE_SETMARKS |
616: TAPE_DRIVE_WRITE_SETMARKS;
617:
618: }
619:
620: if (whichdrive != TDC_3600) {
621:
622: tapeGetDriveParams->FeaturesLow |=
623: TAPE_DRIVE_VARIABLE_BLOCK;
624:
625: tapeGetDriveParams->FeaturesHigh |=
626: TAPE_DRIVE_SET_BLOCK_SIZE;
627:
628: }
629:
630: switch (densityCode) {
631: case QIC_XX:
632: switch (mediumType) {
633: case DC6320:
634: case DC6525:
635: case DC9100:
636: case DC9100XL:
637: tapeGetDriveParams->DefaultBlockSize = 1024;
638: break;
639:
640: default:
641: tapeGetDriveParams->DefaultBlockSize = 512;
642: break;
643: }
644: break;
645:
646: case QIC_525:
647: case QIC_1000:
648: case QIC_2GB:
649: tapeGetDriveParams->DefaultBlockSize = 1024;
650: break;
651:
652: default:
653: tapeGetDriveParams->DefaultBlockSize = 512;
654: break;
655: }
656:
657: tapeGetDriveParams->FeaturesLow |=
658: TAPE_DRIVE_FIXED |
659: TAPE_DRIVE_ERASE_LONG |
660: TAPE_DRIVE_ERASE_BOP_ONLY |
661: TAPE_DRIVE_ERASE_IMMEDIATE |
662: TAPE_DRIVE_FIXED_BLOCK |
663: TAPE_DRIVE_WRITE_PROTECT |
664: TAPE_DRIVE_GET_ABSOLUTE_BLK |
665: TAPE_DRIVE_GET_LOGICAL_BLK;
666:
667: tapeGetDriveParams->FeaturesHigh |=
668: TAPE_DRIVE_LOAD_UNLOAD |
669: TAPE_DRIVE_TENSION |
670: TAPE_DRIVE_LOCK_UNLOCK |
671: TAPE_DRIVE_REWIND_IMMEDIATE |
672: TAPE_DRIVE_LOAD_UNLD_IMMED |
673: TAPE_DRIVE_TENSION_IMMED |
674: TAPE_DRIVE_ABSOLUTE_BLK |
675: TAPE_DRIVE_LOGICAL_BLK |
676: TAPE_DRIVE_END_OF_DATA |
677: TAPE_DRIVE_RELATIVE_BLKS |
678: TAPE_DRIVE_FILEMARKS |
679: TAPE_DRIVE_SEQUENTIAL_FMKS |
680: TAPE_DRIVE_REVERSE_POSITION |
681: TAPE_DRIVE_WRITE_FILEMARKS |
682: TAPE_DRIVE_WRITE_MARK_IMMED;
683:
684: tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
685:
686: DebugPrint((3,"TapeGetDriveParameters: FeaturesLow == 0x%.8X\n",
687: tapeGetDriveParams->FeaturesLow));
688: DebugPrint((3,"TapeGetDriveParameters: FeaturesHigh == 0x%.8X\n",
689: tapeGetDriveParams->FeaturesHigh));
690:
691: return status;
692:
693: } // end TapeGetDriveParameters()
694:
695:
696: NTSTATUS
697: TapeGetMediaParameters(
698: IN PDEVICE_OBJECT DeviceObject,
699: IN PIRP Irp
700: )
701:
702: /*++
703: Routine Description:
704:
705: This routine determines and returns the "media parameters" of the
706: Tandberg QIC tape drive associated with "DeviceObject". Tape media
707: must be present (loaded) in the drive for this function to return
708: "no error".
709:
710: Arguments:
711:
712: DeviceObject
713: Irp
714:
715: Return Value:
716:
717: NTSTATUS
718:
719: --*/
720:
721: {
722: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
723: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
724: PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
725: PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer;
726: PMODE_DEVICE_CONFIG_PAGE deviceConfigBuffer;
727: ULONG sectorShift;
728: SCSI_REQUEST_BLOCK srb;
729: PCDB cdb = (PCDB)srb.Cdb;
730: NTSTATUS status;
731:
732: DebugPrint((3,"TapeGetMediaParameters: Enter routine\n"));
733:
734: RtlZeroMemory(tapeGetMediaParams, sizeof(TAPE_GET_MEDIA_PARAMETERS));
735: Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
736:
737: //
738: // Zero CDB in SRB on stack.
739: //
740:
741: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
742:
743: //
744: // Prepare SCSI command (CDB)
745: //
746:
747: srb.CdbLength = CDB6GENERIC_LENGTH;
748:
749: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
750:
751: //
752: // Set timeout value.
753: //
754:
755: srb.TimeOutValue = deviceExtension->TimeOutValue;
756:
757: //
758: // Send SCSI command (CDB) to device
759: //
760:
761: DebugPrint((3,"TapeGetMediaParameters: SendSrb (test unit ready)\n"));
762:
763: status = ScsiClassSendSrbSynchronous(DeviceObject,
764: &srb,
765: NULL,
766: 0,
767: FALSE);
768:
769: if (!NT_SUCCESS(status)) {
770: DebugPrint((1,"TapeGetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
771: return status;
772: }
773:
774: mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
775: sizeof(MODE_TAPE_MEDIA_INFORMATION));
776:
777: if (!mediaInfoBuffer) {
778: DebugPrint((1,"TapeGetMediaParameters: insufficient resources (mediaInfoBuffer)\n"));
779: return STATUS_INSUFFICIENT_RESOURCES;
780: }
781:
782: RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
783:
784: //
785: // Zero CDB in SRB on stack.
786: //
787:
788: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
789:
790: //
791: // Prepare SCSI command (CDB)
792: //
793:
794: srb.CdbLength = CDB6GENERIC_LENGTH;
795:
796: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
797: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
798: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4;
799:
800: //
801: // Set timeout value.
802: //
803:
804: srb.TimeOutValue = deviceExtension->TimeOutValue;
805:
806: //
807: // Send SCSI command (CDB) to device
808: //
809:
810: DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense #1)\n"));
811:
812: status = ScsiClassSendSrbSynchronous(DeviceObject,
813: &srb,
814: mediaInfoBuffer,
815: sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4,
816: FALSE);
817:
818: if (!NT_SUCCESS(status)) {
819: DebugPrint((1,"TapeGetMediaParameters: mode sense #1, SendSrb unsuccessful\n"));
820: ExFreePool(mediaInfoBuffer);
821: return status;
822: }
823:
824: if (mediaInfoBuffer->MediumPartPage.FDPBit) {
825:
826: deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
827: sizeof(MODE_DEVICE_CONFIG_PAGE));
828:
829: if (!deviceConfigBuffer) {
830: DebugPrint((1,"TapeGetMediaParameters: insufficient resources (deviceConfigBuffer)\n"));
831: ExFreePool(mediaInfoBuffer);
832: return STATUS_INSUFFICIENT_RESOURCES;
833: }
834:
835: RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
836:
837: //
838: // Zero CDB in SRB on stack.
839: //
840:
841: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
842:
843: //
844: // Prepare SCSI command (CDB)
845: //
846:
847: srb.CdbLength = CDB6GENERIC_LENGTH;
848:
849: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
850: cdb->MODE_SENSE.Dbd = SETBITON;
851: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
852: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
853:
854: //
855: // Set timeout value.
856: //
857:
858: srb.TimeOutValue = deviceExtension->TimeOutValue;
859:
860: //
861: // Send SCSI command (CDB) to device
862: //
863:
864: DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense #2)\n"));
865:
866: status = ScsiClassSendSrbSynchronous(DeviceObject,
867: &srb,
868: deviceConfigBuffer,
869: sizeof(MODE_DEVICE_CONFIG_PAGE),
870: FALSE);
871:
872: if (!NT_SUCCESS(status)) {
873: DebugPrint((1,"TapeGetMediaParameters: mode sense #2, SendSrb unsuccessful\n"));
874: ExFreePool(deviceConfigBuffer);
875: ExFreePool(mediaInfoBuffer);
876: return status;
877: }
878:
879: tapeData->CurrentPartition =
880: deviceConfigBuffer->DeviceConfigPage.ActivePartition?
881: DIRECTORY_PARTITION : DATA_PARTITION;
882:
883: tapeGetMediaParams->PartitionCount = 2;
884:
885: ExFreePool(deviceConfigBuffer);
886:
887: } else {
888:
889: tapeGetMediaParams->PartitionCount = 1 ;
890:
891: tapeData->CurrentPartition = NO_PARTITIONS;
892:
893: }
894:
895: tapeGetMediaParams->BlockSize = mediaInfoBuffer->ParameterListBlock.BlockLength[2];
896: tapeGetMediaParams->BlockSize += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8);
897: tapeGetMediaParams->BlockSize += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16);
898:
899: WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift);
900: deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize;
901: deviceExtension->SectorShift = sectorShift;
902:
903: tapeGetMediaParams->WriteProtected =
904: ((mediaInfoBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & 0x01);
905:
906: ExFreePool(mediaInfoBuffer);
907:
908: return status;
909:
910: } // end TapeGetMediaParameters()
911:
912:
913: NTSTATUS
914: TapeGetPosition(
915: IN PDEVICE_OBJECT DeviceObject,
916: IN PIRP Irp
917: )
918:
919: /*++
920: Routine Description:
921:
922: This routine returns the current position of the tape.
923:
924: Arguments:
925:
926: DeviceObject
927: Irp
928:
929: Return Value:
930:
931: NTSTATUS
932:
933: --*/
934:
935: {
936: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
937: PTAPE_GET_POSITION tapeGetPosition = Irp->AssociatedIrp.SystemBuffer;
938: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
939: PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer;
940: PMODE_DEVICE_CONFIG_PAGE deviceConfigBuffer;
941: PTAPE_POSITION_DATA absoluteBuffer;
942: UCHAR densityCode;
943: ULONG tapeBlockLength;
944: ULONG tapeBlockAddress;
945: ULONG type;
946: SCSI_REQUEST_BLOCK srb;
947: PCDB cdb = (PCDB)srb.Cdb;
948: NTSTATUS status;
949:
950: DebugPrint((3,"TapeGetPosition: Enter routine\n"));
951:
952: type = tapeGetPosition->Type;
953: RtlZeroMemory(tapeGetPosition, sizeof(TAPE_GET_POSITION));
954: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
955: tapeGetPosition->Type = type;
956:
957: //
958: // Zero CDB in SRB on stack.
959: //
960:
961: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
962:
963: //
964: // Prepare SCSI command (CDB)
965: //
966:
967: srb.CdbLength = CDB6GENERIC_LENGTH;
968:
969: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
970:
971: //
972: // Set timeout value.
973: //
974:
975: srb.TimeOutValue = deviceExtension->TimeOutValue;
976:
977: //
978: // Send SCSI command (CDB) to device
979: //
980:
981: DebugPrint((3,"TapeGetPosition: SendSrb (test unit ready)\n"));
982:
983: status = ScsiClassSendSrbSynchronous(DeviceObject,
984: &srb,
985: NULL,
986: 0,
987: FALSE);
988:
989: if (!NT_SUCCESS(status)) {
990: DebugPrint((1,"TapeGetPosition: test unit ready, SendSrb unsuccessful\n"));
991: return status;
992: }
993:
994: if (type == TAPE_LOGICAL_POSITION) {
995:
996: DebugPrint((3,"TapeGetPosition: pseudo logical\n"));
997:
998: type = TAPE_PSEUDO_LOGICAL_POSITION;
999:
1000: mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1001: sizeof(MODE_TAPE_MEDIA_INFORMATION));
1002:
1003: if (!mediaInfoBuffer) {
1004: DebugPrint((1,"TapeGetPosition: insufficient resources (mediaInfoBuffer)\n"));
1005: return STATUS_INSUFFICIENT_RESOURCES;
1006: }
1007:
1008: RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
1009:
1010: //
1011: // Zero CDB in SRB on stack.
1012: //
1013:
1014: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1015:
1016: //
1017: // Prepare SCSI command (CDB)
1018: //
1019:
1020: srb.CdbLength = CDB6GENERIC_LENGTH;
1021:
1022: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1023: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
1024: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4;
1025:
1026: //
1027: // Set timeout value.
1028: //
1029:
1030: srb.TimeOutValue = deviceExtension->TimeOutValue;
1031:
1032: //
1033: // Send SCSI command (CDB) to device
1034: //
1035:
1036: DebugPrint((3,"TapeGetPosition: SendSrb (mode sense #1)\n"));
1037:
1038: status = ScsiClassSendSrbSynchronous(DeviceObject,
1039: &srb,
1040: mediaInfoBuffer,
1041: sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4,
1042: FALSE);
1043:
1044: if (!NT_SUCCESS(status)) {
1045: DebugPrint((1,"TapeGetPosition: mode sense #1, SendSrb unsuccessful\n"));
1046: ExFreePool(mediaInfoBuffer);
1047: return status;
1048: }
1049:
1050: if (mediaInfoBuffer->MediumPartPage.FDPBit) {
1051:
1052: deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1053: sizeof(MODE_DEVICE_CONFIG_PAGE));
1054:
1055: if (!deviceConfigBuffer) {
1056: DebugPrint((1,"TapeGetPosition: insufficient resources (deviceConfigBuffer)\n"));
1057: ExFreePool(mediaInfoBuffer);
1058: return STATUS_INSUFFICIENT_RESOURCES;
1059: }
1060:
1061: RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
1062:
1063: //
1064: // Zero CDB in SRB on stack.
1065: //
1066:
1067: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1068:
1069: //
1070: // Prepare SCSI command (CDB)
1071: //
1072:
1073: srb.CdbLength = CDB6GENERIC_LENGTH;
1074:
1075: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1076: cdb->MODE_SENSE.Dbd = SETBITON;
1077: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
1078: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
1079:
1080: //
1081: // Set timeout value.
1082: //
1083:
1084: srb.TimeOutValue = deviceExtension->TimeOutValue;
1085:
1086: //
1087: // Send SCSI command (CDB) to device
1088: //
1089:
1090: DebugPrint((3,"TapeGetPosition: SendSrb (mode sense #2)\n"));
1091:
1092: status = ScsiClassSendSrbSynchronous(DeviceObject,
1093: &srb,
1094: deviceConfigBuffer,
1095: sizeof(MODE_DEVICE_CONFIG_PAGE),
1096: FALSE);
1097:
1098: if (!NT_SUCCESS(status)) {
1099: DebugPrint((1,"TapeGetPosition: mode sense #2, SendSrb unsuccessful\n"));
1100: ExFreePool(deviceConfigBuffer);
1101: ExFreePool(mediaInfoBuffer);
1102: return status;
1103: }
1104:
1105: tapeData->CurrentPartition =
1106: deviceConfigBuffer->DeviceConfigPage.ActivePartition?
1107: DIRECTORY_PARTITION : DATA_PARTITION;
1108:
1109: ExFreePool(deviceConfigBuffer);
1110:
1111: } else {
1112:
1113: tapeData->CurrentPartition = NO_PARTITIONS;
1114:
1115: }
1116:
1117: densityCode = mediaInfoBuffer->ParameterListBlock.DensityCode;
1118: tapeBlockLength = mediaInfoBuffer->ParameterListBlock.BlockLength[2];
1119: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8);
1120: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16);
1121:
1122: ExFreePool(mediaInfoBuffer);
1123:
1124: }
1125:
1126: switch (type) {
1127: case TAPE_PSEUDO_LOGICAL_POSITION:
1128: case TAPE_ABSOLUTE_POSITION:
1129: absoluteBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1130: sizeof(TAPE_POSITION_DATA));
1131:
1132: if (!absoluteBuffer) {
1133: DebugPrint((1,"TapeGetPosition: insufficient resources (absoluteBuffer)\n"));
1134: return STATUS_INSUFFICIENT_RESOURCES;
1135: }
1136:
1137: RtlZeroMemory(absoluteBuffer, sizeof(TAPE_POSITION_DATA));
1138:
1139: //
1140: // Zero CDB in SRB on stack.
1141: //
1142:
1143: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1144:
1145: //
1146: // Prepare SCSI command (CDB)
1147: //
1148:
1149: srb.CdbLength = CDB10GENERIC_LENGTH;
1150:
1151: cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION;
1152: cdb->READ_POSITION.BlockType = SETBITON;
1153:
1154: //
1155: // Set timeout value.
1156: //
1157:
1158: srb.TimeOutValue = deviceExtension->TimeOutValue;
1159:
1160: //
1161: // Send SCSI command (CDB) to device
1162: //
1163:
1164: DebugPrint((3,"TapeGetPosition: SendSrb (read position)\n"));
1165:
1166: status = ScsiClassSendSrbSynchronous(DeviceObject,
1167: &srb,
1168: absoluteBuffer,
1169: sizeof(TAPE_POSITION_DATA),
1170: FALSE);
1171:
1172: if (NT_SUCCESS(status)) {
1173:
1174: REVERSE_BYTES((PFOUR_BYTE)&tapeBlockAddress,
1175: (PFOUR_BYTE)absoluteBuffer->FirstBlock);
1176: }
1177:
1178: ExFreePool(absoluteBuffer);
1179:
1180: if (!NT_SUCCESS(status)) {
1181: DebugPrint((1,"TapeGetPosition: read position, SendSrb unsuccessful\n"));
1182: return status;
1183: }
1184:
1185: if (type == TAPE_ABSOLUTE_POSITION) {
1186: tapeGetPosition->Partition = 0;
1187: tapeGetPosition->Offset.HighPart = 0;
1188: tapeGetPosition->Offset.LowPart = tapeBlockAddress;
1189: break;
1190: }
1191:
1192: tapeBlockAddress =
1193: TapePhysicalBlockToLogicalBlock(
1194: densityCode,
1195: tapeBlockAddress,
1196: tapeBlockLength,
1197: (BOOLEAN)(
1198: (tapeData->CurrentPartition
1199: == DIRECTORY_PARTITION)?
1200: NOT_FROM_BOT : FROM_BOT
1201: )
1202: );
1203:
1204: tapeGetPosition->Offset.HighPart = 0;
1205: tapeGetPosition->Offset.LowPart = tapeBlockAddress;
1206: tapeGetPosition->Partition = tapeData->CurrentPartition;
1207: break;
1208:
1209: default:
1210: DebugPrint((1,"TapeGetPosition: PositionType -- operation not supported\n"));
1211: return STATUS_NOT_IMPLEMENTED;
1212: }
1213:
1214: return status;
1215:
1216: } // end TapeGetPosition()
1217:
1218:
1219: NTSTATUS
1220: TapeGetStatus(
1221: IN PDEVICE_OBJECT DeviceObject,
1222: IN PIRP Irp
1223: )
1224:
1225: /*++
1226: Routine Description:
1227:
1228: This routine returns the status of the device.
1229:
1230: Arguments:
1231:
1232: DeviceObject
1233: Irp
1234:
1235: Return Value:
1236:
1237: NTSTATUS
1238:
1239: --*/
1240:
1241: {
1242: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1243: SCSI_REQUEST_BLOCK srb;
1244: PCDB cdb = (PCDB)srb.Cdb;
1245: NTSTATUS status;
1246:
1247: DebugPrint((3,"TapeGetStatus: Enter routine\n"));
1248:
1249: //
1250: // Zero CDB in SRB on stack.
1251: //
1252:
1253: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1254:
1255: //
1256: // Prepare SCSI command (CDB)
1257: //
1258:
1259: srb.CdbLength = CDB6GENERIC_LENGTH;
1260:
1261: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
1262:
1263: //
1264: // Set timeout value.
1265: //
1266:
1267: srb.TimeOutValue = deviceExtension->TimeOutValue;
1268:
1269: //
1270: // Send SCSI command (CDB) to device
1271: //
1272:
1273: DebugPrint((3,"TapeGetStatus: SendSrb (test unit ready)\n"));
1274:
1275: status = ScsiClassSendSrbSynchronous(DeviceObject,
1276: &srb,
1277: NULL,
1278: 0,
1279: FALSE);
1280:
1281: if (!NT_SUCCESS(status)) {
1282: DebugPrint((1,"TapeGetStatus: test unit ready, SendSrb unsuccessful\n"));
1283: }
1284:
1285: return status;
1286:
1287: } // end TapeGetStatus()
1288:
1289:
1290: NTSTATUS
1291: TapePrepare(
1292: IN PDEVICE_OBJECT DeviceObject,
1293: IN PIRP Irp
1294: )
1295:
1296: /*++
1297: Routine Description:
1298:
1299: This routine loads, unloads, tensions, locks, or unlocks the tape.
1300:
1301: Arguments:
1302:
1303: DeviceObject
1304: Irp
1305:
1306: Return Value:
1307:
1308: NTSTATUS
1309:
1310: --*/
1311:
1312: {
1313: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1314: PTAPE_PREPARE tapePrepare = Irp->AssociatedIrp.SystemBuffer;
1315: SCSI_REQUEST_BLOCK srb;
1316: PCDB cdb = (PCDB)srb.Cdb;
1317: NTSTATUS status;
1318:
1319: DebugPrint((3,"TapePrepare: Enter routine\n"));
1320:
1321: if (tapePrepare->Immediate) {
1322: switch (tapePrepare->Operation) {
1323: case TAPE_LOAD:
1324: case TAPE_UNLOAD:
1325: case TAPE_TENSION:
1326: DebugPrint((3,"TapePrepare: immediate\n"));
1327: break;
1328:
1329: case TAPE_LOCK:
1330: case TAPE_UNLOCK:
1331: default:
1332: DebugPrint((1,"TapePrepare: Operation, immediate -- operation not supported\n"));
1333: return STATUS_NOT_IMPLEMENTED;
1334: }
1335: }
1336:
1337: //
1338: // Zero CDB in SRB on stack.
1339: //
1340:
1341: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1342:
1343: //
1344: // Prepare SCSI command (CDB)
1345: //
1346:
1347: srb.CdbLength = CDB6GENERIC_LENGTH;
1348:
1349: cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
1350:
1351: switch (tapePrepare->Operation) {
1352: case TAPE_LOAD:
1353: DebugPrint((3,"TapePrepare: Operation == load\n"));
1354: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
1355: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
1356: srb.TimeOutValue = 180;
1357: break;
1358:
1359: case TAPE_UNLOAD:
1360: DebugPrint((3,"TapePrepare: Operation == unload\n"));
1361: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
1362: srb.TimeOutValue = 180;
1363: break;
1364:
1365: case TAPE_TENSION:
1366: DebugPrint((3,"TapePrepare: Operation == tension\n"));
1367: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
1368: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x03;
1369: srb.TimeOutValue = 360;
1370: break;
1371:
1372: case TAPE_LOCK:
1373: DebugPrint((3,"TapePrepare: Operation == lock\n"));
1374: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1375: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
1376: srb.TimeOutValue = 180;
1377: break;
1378:
1379: case TAPE_UNLOCK:
1380: DebugPrint((3,"TapePrepare: Operation == unlock\n"));
1381: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1382: srb.TimeOutValue = 180;
1383: break;
1384:
1385: default:
1386: DebugPrint((1,"TapePrepare: Operation -- operation not supported\n"));
1387: return STATUS_NOT_IMPLEMENTED;
1388: }
1389:
1390: //
1391: // Send SCSI command (CDB) to device
1392: //
1393:
1394: DebugPrint((3,"TapePrepare: SendSrb (Operation)\n"));
1395:
1396: status = ScsiClassSendSrbSynchronous(DeviceObject,
1397: &srb,
1398: NULL,
1399: 0,
1400: FALSE);
1401:
1402: if (!NT_SUCCESS(status)) {
1403: DebugPrint((1,"TapePrepare: Operation, SendSrb unsuccessful\n"));
1404: }
1405:
1406: return status;
1407:
1408: } // end TapePrepare()
1409:
1410:
1411: NTSTATUS
1412: TapeReadWrite(
1413: IN PDEVICE_OBJECT DeviceObject,
1414: IN PIRP Irp
1415: )
1416:
1417: /*++
1418:
1419: Routine Description:
1420:
1421: This routine builds SRBs and CDBs for read and write requests to
1422: Tandberg QIC drives.
1423:
1424: Arguments:
1425:
1426: DeviceObject
1427: Irp
1428:
1429: Return Value:
1430:
1431: Returns STATUS_PENDING.
1432:
1433: --*/
1434:
1435: {
1436: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1437: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
1438: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
1439: PSCSI_REQUEST_BLOCK srb;
1440: PCDB cdb;
1441: KIRQL currentIrql;
1442: ULONG transferBlocks;
1443: LARGE_INTEGER startingOffset =
1444: currentIrpStack->Parameters.Read.ByteOffset;
1445:
1446: DebugPrint((3,"TapeReadWrite: Enter routine\n"));
1447:
1448: //
1449: // Allocate an Srb.
1450: //
1451:
1452: if (deviceExtension->SrbZone != NULL &&
1453: (srb = ExInterlockedAllocateFromZone(
1454: deviceExtension->SrbZone,
1455: deviceExtension->SrbZoneSpinLock)) != NULL) {
1456:
1457: srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
1458:
1459: } else {
1460:
1461: //
1462: // Allocate Srb from non-paged pool.
1463: // This call must succeed.
1464: //
1465:
1466: srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
1467:
1468: srb->SrbFlags = 0;
1469:
1470: }
1471:
1472: //
1473: // Write length to SRB.
1474: //
1475:
1476: srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1477:
1478: //
1479: // Set up IRP Address.
1480: //
1481:
1482: srb->OriginalRequest = Irp;
1483:
1484: //
1485: // Set up target id and logical unit number.
1486: //
1487:
1488: srb->PathId = deviceExtension->PathId;
1489: srb->TargetId = deviceExtension->TargetId;
1490: srb->Lun = deviceExtension->Lun;
1491:
1492:
1493: srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1494:
1495: srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1496:
1497: //
1498: // Save byte count of transfer in SRB Extension.
1499: //
1500:
1501: srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
1502:
1503: //
1504: // Indicate auto request sense by specifying buffer and size.
1505: //
1506:
1507: srb->SenseInfoBuffer = deviceExtension->SenseData;
1508:
1509: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1510:
1511: //
1512: // Initialize the queue actions field.
1513: //
1514:
1515: srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
1516:
1517: //
1518: // Indicate auto request sense by specifying buffer and size.
1519: //
1520:
1521: srb->SenseInfoBuffer = deviceExtension->SenseData;
1522:
1523: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1524:
1525: //
1526: // Set timeout value in seconds.
1527: //
1528:
1529: srb->TimeOutValue = deviceExtension->TimeOutValue;
1530:
1531: //
1532: // Zero statuses.
1533: //
1534:
1535: srb->SrbStatus = srb->ScsiStatus = 0;
1536:
1537: srb->NextSrb = 0;
1538:
1539: //
1540: // Indicate that 6-byte CDB's will be used.
1541: //
1542:
1543: srb->CdbLength = CDB6GENERIC_LENGTH;
1544:
1545: //
1546: // Fill in CDB fields.
1547: //
1548:
1549: cdb = (PCDB)srb->Cdb;
1550:
1551: //
1552: // Zero CDB in SRB.
1553: //
1554:
1555: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1556:
1557: //
1558: // Since we are writing fixed block mode, normalize transfer count
1559: // to number of blocks.
1560: //
1561:
1562: transferBlocks =
1563: currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift;
1564:
1565: //
1566: // Set up transfer length
1567: //
1568:
1569: cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
1570: cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff);
1571: cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
1572:
1573: //
1574: // Tell the python we are in fixed block mode
1575: //
1576:
1577: cdb->CDB6READWRITETAPE.VendorSpecific = 1;
1578:
1579: //
1580: // Set transfer direction flag and Cdb command.
1581: //
1582:
1583: if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
1584:
1585: DebugPrint((3, "TapeRequest: Read Command\n"));
1586:
1587: srb->SrbFlags = SRB_FLAGS_DATA_IN;
1588: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
1589:
1590: } else {
1591:
1592: DebugPrint((3, "TapeRequest: Write Command\n"));
1593:
1594: srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1595: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
1596: }
1597:
1598: //
1599: // Or in the default flags from the device object.
1600: //
1601:
1602: srb->SrbFlags |= deviceExtension->SrbFlags;
1603:
1604: //
1605: // Set up major SCSI function.
1606: //
1607:
1608: nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1609:
1610: //
1611: // Save SRB address in next stack for port driver.
1612: //
1613:
1614: nextIrpStack->Parameters.Scsi.Srb = srb;
1615:
1616: //
1617: // Save retry count in current IRP stack.
1618: //
1619:
1620: currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
1621:
1622: //
1623: // Set up IoCompletion routine address.
1624: //
1625:
1626: IoSetCompletionRoutine(Irp,
1627: ScsiClassIoComplete,
1628: srb,
1629: TRUE,
1630: TRUE,
1631: FALSE);
1632:
1633: return STATUS_PENDING;
1634:
1635: } // end TapeReadWrite()
1636:
1637:
1638: NTSTATUS
1639: TapeSetDriveParameters(
1640: IN PDEVICE_OBJECT DeviceObject,
1641: IN PIRP Irp
1642: )
1643:
1644: /*++
1645: Routine Description:
1646:
1647: This routine would "set" the "drive parameters" of the Tandberg QIC
1648: tape drive associated with "DeviceObject" if any could be set, but
1649: none can! Hence, this routine always returns a STATUS_NOT_IMPLEMENTED
1650: status.
1651:
1652: Arguments:
1653:
1654: DeviceObject
1655: Irp
1656:
1657: Return Value:
1658:
1659: NTSTATUS
1660:
1661: --*/
1662:
1663: {
1664: DebugPrint((3,"TapeSetDriveParameters: Enter routine\n"));
1665:
1666: DebugPrint((1,"TapeSetDriveParameters: Operation -- operation not supported\n"));
1667:
1668: return STATUS_NOT_IMPLEMENTED;
1669:
1670: } // end TapeSetDriveParameters()
1671:
1672:
1673:
1674: NTSTATUS
1675: TapeSetMediaParameters(
1676: IN PDEVICE_OBJECT DeviceObject,
1677: IN PIRP Irp
1678: )
1679:
1680: /*++
1681: Routine Description:
1682:
1683: This routine "sets" the "media parameters" of the Tandberg QIC tape
1684: drive associated with "DeviceObject". Tape media must be present
1685: (loaded) in the drive for this function to return "no error".
1686:
1687: Arguments:
1688:
1689: DeviceObject
1690: Irp
1691:
1692: Return Value:
1693:
1694: NTSTATUS
1695:
1696: --*/
1697:
1698: {
1699: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1700: PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
1701: PMODE_PARM_READ_WRITE_DATA modeBuffer;
1702: PINQUIRYDATA inquiryBuffer;
1703: ULONG whichdrive;
1704: SCSI_REQUEST_BLOCK srb;
1705: PCDB cdb = (PCDB)srb.Cdb;
1706: NTSTATUS status;
1707:
1708: DebugPrint((3,"TapeSetMediaParameters: Enter routine\n"));
1709:
1710: inquiryBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1711: sizeof(INQUIRYDATA));
1712:
1713: if (!inquiryBuffer) {
1714: DebugPrint((1,"TapeSetMediaParameters: insufficient resources (inquiryBuffer)\n"));
1715: return STATUS_INSUFFICIENT_RESOURCES;
1716: }
1717:
1718: RtlZeroMemory(inquiryBuffer, sizeof(INQUIRYDATA));
1719:
1720: //
1721: // Send SCSI command (CDB) to device
1722: //
1723:
1724: DebugPrint((3,"TapeSetMediaParameters: SendSrb (inquiry)\n"));
1725:
1726: status = GetInquiryInformationData(DeviceObject, Irp, inquiryBuffer);
1727:
1728: if (NT_SUCCESS(status)) {
1729:
1730: //
1731: // Which drive do we have, TDC 3660, 3820, 4120 or 4220?
1732: //
1733:
1734: whichdrive = WhichIsIt(inquiryBuffer);
1735: }
1736:
1737: ExFreePool(inquiryBuffer);
1738:
1739: if (!NT_SUCCESS(status)) {
1740: DebugPrint((1,"TapeSetMediaParameters: inquiry, SendSrb unsuccessful\n"));
1741: return status;
1742: }
1743:
1744: if (whichdrive == TDC_3600) {
1745: DebugPrint((1,"TapeSetMediaParameters: whichdrive -- operation not supported\n"));
1746: return STATUS_NOT_IMPLEMENTED;
1747: }
1748:
1749: //
1750: // Zero CDB in SRB on stack.
1751: //
1752:
1753: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1754:
1755: //
1756: // Prepare SCSI command (CDB)
1757: //
1758:
1759: srb.CdbLength = CDB6GENERIC_LENGTH;
1760:
1761: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
1762:
1763: //
1764: // Set timeout value.
1765: //
1766:
1767: srb.TimeOutValue = deviceExtension->TimeOutValue;
1768:
1769: //
1770: // Send SCSI command (CDB) to device
1771: //
1772:
1773: DebugPrint((3,"TapeSetMediaParameters: SendSrb (test unit ready)\n"));
1774:
1775: status = ScsiClassSendSrbSynchronous(DeviceObject,
1776: &srb,
1777: NULL,
1778: 0,
1779: FALSE);
1780:
1781: if (!NT_SUCCESS(status)) {
1782: DebugPrint((1,"TapeSetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
1783: return status;
1784: }
1785:
1786: modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1787: sizeof(MODE_PARM_READ_WRITE_DATA));
1788:
1789: if (!modeBuffer) {
1790: DebugPrint((1,"TapeSetMediaParameters: insufficient resources (modeBuffer)\n"));
1791: return STATUS_INSUFFICIENT_RESOURCES;
1792: }
1793:
1794: RtlZeroMemory(modeBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
1795:
1796: modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
1797: modeBuffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH;
1798:
1799: modeBuffer->ParameterListBlock.DensityCode = 0x7F;
1800: modeBuffer->ParameterListBlock.BlockLength[0] =
1801: ((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
1802: modeBuffer->ParameterListBlock.BlockLength[1] =
1803: ((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
1804: modeBuffer->ParameterListBlock.BlockLength[2] =
1805: (tapeSetMediaParams->BlockSize & 0xFF);
1806:
1807: //
1808: // Zero CDB in SRB on stack.
1809: //
1810:
1811: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1812:
1813: //
1814: // Prepare SCSI command (CDB)
1815: //
1816:
1817: srb.CdbLength = CDB6GENERIC_LENGTH;
1818:
1819: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1820: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
1821:
1822: //
1823: // Set timeout value.
1824: //
1825:
1826: srb.TimeOutValue = deviceExtension->TimeOutValue;
1827:
1828: //
1829: // Send SCSI command (CDB) to device
1830: //
1831:
1832: DebugPrint((3,"TapeSetMediaParameters: SendSrb (mode select)\n"));
1833:
1834: status = ScsiClassSendSrbSynchronous(DeviceObject,
1835: &srb,
1836: modeBuffer,
1837: sizeof(MODE_PARM_READ_WRITE_DATA),
1838: TRUE);
1839:
1840: ExFreePool(modeBuffer);
1841:
1842: if (!NT_SUCCESS(status)) {
1843: DebugPrint((1,"TapeSetMediaParameters: mode select, SendSrb unsuccessful\n"));
1844: }
1845:
1846: return status;
1847:
1848: } // end TapeSetMediaParameters()
1849:
1850:
1851: NTSTATUS
1852: TapeSetPosition(
1853: IN PDEVICE_OBJECT DeviceObject,
1854: IN PIRP Irp
1855: )
1856:
1857: /*++
1858: Routine Description:
1859:
1860: This routine sets the position of the tape.
1861:
1862: Arguments:
1863:
1864: DeviceObject
1865: Irp
1866:
1867: Return Value:
1868:
1869: NTSTATUS
1870:
1871: --*/
1872:
1873: {
1874: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1875: PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
1876: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
1877: BOOLEAN changePartition = FALSE;
1878: PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer;
1879: PMODE_DEVICE_CONFIG_PAGE deviceConfigBuffer;
1880: TAPE_PHYS_POSITION physPosition;
1881: UCHAR densityCode;
1882: ULONG tapePositionVector;
1883: ULONG tapeBlockLength;
1884: ULONG method;
1885: SCSI_REQUEST_BLOCK srb;
1886: PCDB cdb = (PCDB)srb.Cdb;
1887: NTSTATUS status;
1888:
1889: DebugPrint((3,"TapeSetPosition: Enter routine\n"));
1890:
1891: if (tapeSetPosition->Immediate) {
1892: switch (tapeSetPosition->Method) {
1893: case TAPE_REWIND:
1894: DebugPrint((3,"TapeSetPosition: immediate\n"));
1895: break;
1896:
1897: case TAPE_LOGICAL_BLOCK:
1898: case TAPE_ABSOLUTE_BLOCK:
1899: case TAPE_SPACE_END_OF_DATA:
1900: case TAPE_SPACE_RELATIVE_BLOCKS:
1901: case TAPE_SPACE_FILEMARKS:
1902: case TAPE_SPACE_SEQUENTIAL_FMKS:
1903: case TAPE_SPACE_SETMARKS:
1904: case TAPE_SPACE_SEQUENTIAL_SMKS:
1905: default:
1906: DebugPrint((1,"TapeSetPosition: PositionMethod, immediate -- operation not supported\n"));
1907: return STATUS_NOT_IMPLEMENTED;
1908: }
1909: }
1910:
1911: method = tapeSetPosition->Method;
1912: tapePositionVector = tapeSetPosition->Offset.LowPart;
1913:
1914: if (method == TAPE_LOGICAL_BLOCK) {
1915:
1916: DebugPrint((3,"TapeSetPosition: pseudo logical\n"));
1917:
1918: method = TAPE_PSEUDO_LOGICAL_BLOCK;
1919:
1920: mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1921: sizeof(MODE_TAPE_MEDIA_INFORMATION));
1922:
1923: if (!mediaInfoBuffer) {
1924: DebugPrint((1,"TapeSetPosition: insufficient resources (mediaInfoBuffer)\n"));
1925: return STATUS_INSUFFICIENT_RESOURCES;
1926: }
1927:
1928: RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
1929:
1930: //
1931: // Zero CDB in SRB on stack.
1932: //
1933:
1934: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1935:
1936: //
1937: // Prepare SCSI command (CDB)
1938: //
1939:
1940: srb.CdbLength = CDB6GENERIC_LENGTH;
1941:
1942: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1943: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
1944: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4;
1945:
1946: //
1947: // Set timeout value.
1948: //
1949:
1950: srb.TimeOutValue = deviceExtension->TimeOutValue;
1951:
1952: //
1953: // Send SCSI command (CDB) to device
1954: //
1955:
1956: DebugPrint((3,"TapeSetPosition: SendSrb (mode sense #1)\n"));
1957:
1958: status = ScsiClassSendSrbSynchronous(DeviceObject,
1959: &srb,
1960: mediaInfoBuffer,
1961: sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4,
1962: FALSE);
1963:
1964: if (!NT_SUCCESS(status)) {
1965: DebugPrint((1,"TapeSetPosition: mode sense #1, SendSrb unsuccessful\n"));
1966: ExFreePool(mediaInfoBuffer);
1967: return status;
1968: }
1969:
1970: if (mediaInfoBuffer->MediumPartPage.FDPBit) {
1971:
1972: deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1973: sizeof(MODE_DEVICE_CONFIG_PAGE));
1974:
1975: if (!deviceConfigBuffer) {
1976: DebugPrint((1,"TapeSetPosition: insufficient resources (deviceConfigBuffer)\n"));
1977: ExFreePool(mediaInfoBuffer);
1978: return STATUS_INSUFFICIENT_RESOURCES;
1979: }
1980:
1981: RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
1982:
1983: //
1984: // Zero CDB in SRB on stack.
1985: //
1986:
1987: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1988:
1989: //
1990: // Prepare SCSI command (CDB)
1991: //
1992:
1993: srb.CdbLength = CDB6GENERIC_LENGTH;
1994:
1995: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1996: cdb->MODE_SENSE.Dbd = SETBITON;
1997: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
1998: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
1999:
2000: //
2001: // Set timeout value.
2002: //
2003:
2004: srb.TimeOutValue = deviceExtension->TimeOutValue;
2005:
2006: //
2007: // Send SCSI command (CDB) to device
2008: //
2009:
2010: DebugPrint((3,"TapeSetPosition: SendSrb (mode sense #2)\n"));
2011:
2012: status = ScsiClassSendSrbSynchronous(DeviceObject,
2013: &srb,
2014: deviceConfigBuffer,
2015: sizeof(MODE_DEVICE_CONFIG_PAGE),
2016: FALSE);
2017:
2018: if (!NT_SUCCESS(status)) {
2019: DebugPrint((1,"TapeSetPosition: mode sense #2, SendSrb unsuccessful\n"));
2020: ExFreePool(deviceConfigBuffer);
2021: ExFreePool(mediaInfoBuffer);
2022: return status;
2023: }
2024:
2025: tapeData->CurrentPartition =
2026: deviceConfigBuffer->DeviceConfigPage.ActivePartition?
2027: DIRECTORY_PARTITION : DATA_PARTITION;
2028:
2029: ExFreePool(deviceConfigBuffer);
2030:
2031: } else {
2032:
2033: tapeData->CurrentPartition = NO_PARTITIONS;
2034:
2035: }
2036:
2037: densityCode = mediaInfoBuffer->ParameterListBlock.DensityCode;
2038: tapeBlockLength = mediaInfoBuffer->ParameterListBlock.BlockLength[2];
2039: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8);
2040: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16);
2041:
2042: ExFreePool(mediaInfoBuffer);
2043:
2044: switch (tapeSetPosition->Partition) {
2045: case 0:
2046: break;
2047:
2048: case DIRECTORY_PARTITION:
2049: case DATA_PARTITION:
2050: if (tapeData->CurrentPartition != NO_PARTITIONS) {
2051: if (tapeSetPosition->Partition
2052: != tapeData->CurrentPartition) {
2053: changePartition = TRUE;
2054: }
2055: break;
2056: }
2057: // else: fall through to next case
2058:
2059: default:
2060: DebugPrint((1,"TapeSetPosition: Partition -- invalid parameter\n"));
2061: return STATUS_INVALID_PARAMETER;
2062: }
2063:
2064: physPosition =
2065: TapeLogicalBlockToPhysicalBlock(
2066: densityCode,
2067: tapePositionVector,
2068: tapeBlockLength,
2069: (BOOLEAN)(
2070: (tapeData->CurrentPartition
2071: == DIRECTORY_PARTITION)?
2072: NOT_FROM_BOT : FROM_BOT
2073: )
2074: );
2075:
2076: tapePositionVector = physPosition.SeekBlockAddress;
2077:
2078: }
2079:
2080: //
2081: // Zero CDB in SRB on stack.
2082: //
2083:
2084: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
2085:
2086: //
2087: // Prepare SCSI command (CDB)
2088: //
2089:
2090: srb.CdbLength = CDB6GENERIC_LENGTH;
2091:
2092: cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
2093:
2094: switch (method) {
2095: case TAPE_REWIND:
2096: DebugPrint((3,"TapeSetPosition: method == rewind\n"));
2097: cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
2098: srb.TimeOutValue = 180;
2099: break;
2100:
2101: case TAPE_PSEUDO_LOGICAL_BLOCK:
2102: case TAPE_ABSOLUTE_BLOCK:
2103: DebugPrint((3,"TapeSetPosition: method == locate (absolute)\n"));
2104: srb.CdbLength = CDB10GENERIC_LENGTH;
2105: cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
2106: cdb->LOCATE.CPBit = changePartition? SETBITON : SETBITOFF;
2107: cdb->LOCATE.BTBit = SETBITON;
2108: cdb->LOCATE.LogicalBlockAddress[1] =
2109: ((tapePositionVector >> 16) & 0xFF);
2110: cdb->LOCATE.LogicalBlockAddress[2] =
2111: ((tapePositionVector >> 8) & 0xFF);
2112: cdb->LOCATE.LogicalBlockAddress[3] =
2113: (tapePositionVector & 0xFF);
2114: if (changePartition &&
2115: (tapeSetPosition->Partition == DIRECTORY_PARTITION)) {
2116: cdb->LOCATE.Partition = 1;
2117: }
2118: srb.TimeOutValue = 480;
2119: if ((physPosition.SpaceBlockCount != 0) &&
2120: (method == TAPE_PSEUDO_LOGICAL_BLOCK)) {
2121:
2122: //
2123: // Send SCSI command (CDB) to device
2124: //
2125:
2126: DebugPrint((3,"TapeSetPosition: SendSrb (locate)\n"));
2127:
2128: status = ScsiClassSendSrbSynchronous(DeviceObject,
2129: &srb,
2130: NULL,
2131: 0,
2132: FALSE);
2133:
2134: if (!NT_SUCCESS(status)) {
2135: DebugPrint((1,"TapeSetPosition: locate, SendSrb unsuccessful\n"));
2136: return status;
2137: }
2138:
2139: //
2140: // Zero CDB in SRB on stack.
2141: //
2142:
2143: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
2144:
2145: //
2146: // Prepare SCSI command (CDB)
2147: //
2148:
2149: srb.CdbLength = CDB6GENERIC_LENGTH;
2150:
2151: DebugPrint((3,"TapeSetPosition: method == space block(s)\n"));
2152: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
2153: cdb->SPACE_TAPE_MARKS.Code = 0;
2154: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
2155: ((physPosition.SpaceBlockCount >> 16) & 0xFF);
2156: cdb->SPACE_TAPE_MARKS.NumMarks =
2157: ((physPosition.SpaceBlockCount >> 8) & 0xFF);
2158: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
2159: (physPosition.SpaceBlockCount & 0xFF);
2160: srb.TimeOutValue = deviceExtension->TimeOutValue;
2161:
2162: }
2163: break;
2164:
2165: case TAPE_SPACE_END_OF_DATA:
2166: DebugPrint((3,"TapeSetPosition: method == space to end-of-data\n"));
2167: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
2168: cdb->SPACE_TAPE_MARKS.Code = 3;
2169: srb.TimeOutValue = 480;
2170: break;
2171:
2172: case TAPE_SPACE_RELATIVE_BLOCKS:
2173: DebugPrint((3,"TapeSetPosition: method == space blocks\n"));
2174: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
2175: cdb->SPACE_TAPE_MARKS.Code = 0;
2176: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
2177: ((tapePositionVector >> 16) & 0xFF);
2178: cdb->SPACE_TAPE_MARKS.NumMarks =
2179: ((tapePositionVector >> 8) & 0xFF);
2180: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
2181: (tapePositionVector & 0xFF);
2182: srb.TimeOutValue = 4100;
2183: break;
2184:
2185: case TAPE_SPACE_FILEMARKS:
2186: DebugPrint((3,"TapeSetPosition: method == space filemarks\n"));
2187: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
2188: cdb->SPACE_TAPE_MARKS.Code = 1;
2189: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
2190: ((tapePositionVector >> 16) & 0xFF);
2191: cdb->SPACE_TAPE_MARKS.NumMarks =
2192: ((tapePositionVector >> 8) & 0xFF);
2193: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
2194: (tapePositionVector & 0xFF);
2195: srb.TimeOutValue = 4100;
2196: break;
2197:
2198: case TAPE_SPACE_SEQUENTIAL_FMKS:
2199: DebugPrint((3,"TapeSetPosition: method == space sequential filemarks\n"));
2200: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
2201: cdb->SPACE_TAPE_MARKS.Code = 2;
2202: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
2203: ((tapePositionVector >> 16) & 0xFF);
2204: cdb->SPACE_TAPE_MARKS.NumMarks =
2205: ((tapePositionVector >> 8) & 0xFF);
2206: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
2207: (tapePositionVector & 0xFF);
2208: srb.TimeOutValue = 4100;
2209: break;
2210:
2211: case TAPE_SPACE_SETMARKS:
2212: DebugPrint((3,"TapeSetPosition: method == space setmarks\n"));
2213: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
2214: cdb->SPACE_TAPE_MARKS.Code = 4;
2215: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
2216: ((tapePositionVector >> 16) & 0xFF);
2217: cdb->SPACE_TAPE_MARKS.NumMarks =
2218: ((tapePositionVector >> 8) & 0xFF);
2219: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
2220: (tapePositionVector & 0xFF);
2221: srb.TimeOutValue = 4100;
2222: break;
2223:
2224: default:
2225: DebugPrint((1,"TapeSetPosition: PositionMethod -- operation not supported\n"));
2226: return STATUS_NOT_IMPLEMENTED;
2227: }
2228:
2229: //
2230: // Send SCSI command (CDB) to device
2231: //
2232:
2233: DebugPrint((3,"TapeSetPosition: SendSrb (method)\n"));
2234:
2235: status = ScsiClassSendSrbSynchronous(DeviceObject,
2236: &srb,
2237: NULL,
2238: 0,
2239: FALSE);
2240:
2241: if (NT_SUCCESS(status)) {
2242: if (changePartition) {
2243: tapeData->CurrentPartition = tapeSetPosition->Partition;
2244: }
2245: } else {
2246: DebugPrint((1,"TapeSetPosition: method, SendSrb unsuccessful\n"));
2247: }
2248:
2249: return status;
2250:
2251: } // end TapeSetPosition()
2252:
2253:
2254: BOOLEAN
2255: TapeVerifyInquiry(
2256: IN PSCSI_INQUIRY_DATA LunInfo
2257: )
2258:
2259: /*++
2260: Routine Description:
2261:
2262: This routine determines if this driver should claim this device.
2263:
2264: Arguments:
2265:
2266: LunInfo
2267:
2268: Return Value:
2269:
2270: TRUE - driver should claim this device.
2271: FALSE - driver should not claim this device.
2272:
2273: --*/
2274:
2275: {
2276: PINQUIRYDATA inquiryData;
2277:
2278: DebugPrint((3,"TapeVerifyInquiry: Enter routine\n"));
2279:
2280: inquiryData = (PVOID)LunInfo->InquiryData;
2281:
2282: //
2283: // Determine, from the Product ID field in the
2284: // inquiry data, whether or not to "claim" this drive.
2285: //
2286:
2287: return WhichIsIt(inquiryData)? TRUE : FALSE;
2288:
2289: } // end TapeVerifyInquiry()
2290:
2291:
2292: NTSTATUS
2293: TapeWriteMarks(
2294: IN PDEVICE_OBJECT DeviceObject,
2295: IN PIRP Irp
2296: )
2297:
2298: /*++
2299: Routine Description:
2300:
2301: This routine writes tapemarks on the tape.
2302:
2303: Arguments:
2304:
2305: DeviceObject
2306: Irp
2307:
2308: Return Value:
2309:
2310: NTSTATUS
2311:
2312: --*/
2313:
2314: {
2315: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2316: PTAPE_WRITE_MARKS tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
2317: SCSI_REQUEST_BLOCK srb;
2318: PCDB cdb = (PCDB)srb.Cdb;
2319: NTSTATUS status;
2320:
2321: DebugPrint((3,"TapeWriteMarks: Enter routine\n"));
2322:
2323: if (tapeWriteMarks->Immediate) {
2324: switch (tapeWriteMarks->Type) {
2325: case TAPE_SETMARKS:
2326: case TAPE_FILEMARKS:
2327: DebugPrint((3,"TapeWriteMarks: immediate\n"));
2328: break;
2329:
2330: case TAPE_SHORT_FILEMARKS:
2331: case TAPE_LONG_FILEMARKS:
2332: default:
2333: DebugPrint((1,"TapeWriteMarks: TapemarkType, immediate -- operation not supported\n"));
2334: return STATUS_NOT_IMPLEMENTED;
2335: }
2336: }
2337:
2338: //
2339: // Zero CDB in SRB on stack.
2340: //
2341:
2342: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
2343:
2344: //
2345: // Prepare SCSI command (CDB)
2346: //
2347:
2348: srb.CdbLength = CDB6GENERIC_LENGTH;
2349:
2350: cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
2351: cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate;
2352:
2353: switch (tapeWriteMarks->Type) {
2354: case TAPE_SETMARKS:
2355: DebugPrint((3,"TapeWriteMarks: TapemarkType == setmarks\n"));
2356: cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON;
2357: break;
2358:
2359: case TAPE_FILEMARKS:
2360: DebugPrint((3,"TapeWriteMarks: TapemarkType == filemarks\n"));
2361: break;
2362:
2363: case TAPE_SHORT_FILEMARKS:
2364: case TAPE_LONG_FILEMARKS:
2365: default:
2366: DebugPrint((1,"TapeWriteMarks: TapemarkType -- operation not supported\n"));
2367: return STATUS_NOT_IMPLEMENTED;
2368: }
2369:
2370: cdb->WRITE_TAPE_MARKS.TransferLength[0] =
2371: ((tapeWriteMarks->Count >> 16) & 0xFF);
2372: cdb->WRITE_TAPE_MARKS.TransferLength[1] =
2373: ((tapeWriteMarks->Count >> 8) & 0xFF);
2374: cdb->WRITE_TAPE_MARKS.TransferLength[2] =
2375: (tapeWriteMarks->Count & 0xFF);
2376:
2377: //
2378: // Set timeout value.
2379: //
2380:
2381: srb.TimeOutValue = deviceExtension->TimeOutValue;
2382:
2383: //
2384: // Send SCSI command (CDB) to device
2385: //
2386:
2387: DebugPrint((3,"TapeWriteMarks: SendSrb (TapemarkType)\n"));
2388:
2389: status = ScsiClassSendSrbSynchronous(DeviceObject,
2390: &srb,
2391: NULL,
2392: 0,
2393: FALSE);
2394:
2395: if (!NT_SUCCESS(status)) {
2396: DebugPrint((1,"TapeWriteMarks: TapemarkType, SendSrb unsuccessful\n"));
2397: }
2398:
2399: return status;
2400:
2401: } // end TapeWriteMarks()
2402:
2403:
2404: static
2405: NTSTATUS
2406: GetInquiryInformationData (
2407: IN PDEVICE_OBJECT DeviceObject,
2408: IN PIRP Irp,
2409: OUT PINQUIRYDATA InquiryBuffer
2410: )
2411:
2412: /*++
2413: Routine Description:
2414:
2415: Get the inquiry parameter list buffer
2416:
2417: Arguments:
2418:
2419: DeviceObject
2420: Irp
2421: InquiryBuffer
2422:
2423: Return Value:
2424:
2425: NTSTATUS
2426:
2427: --*/
2428:
2429: {
2430: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2431: SCSI_REQUEST_BLOCK srb;
2432: PCDB cdb = (PCDB)srb.Cdb;
2433: NTSTATUS status;
2434:
2435: RtlZeroMemory(InquiryBuffer, sizeof(INQUIRYDATA));
2436:
2437: //
2438: // Zero CDB in SRB on stack.
2439: //
2440:
2441: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
2442:
2443: //
2444: // Prepare SCSI command (CDB)
2445: //
2446:
2447: srb.CdbLength = CDB6GENERIC_LENGTH;
2448:
2449: cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
2450: cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
2451:
2452: //
2453: // Set timeout value.
2454: //
2455:
2456: srb.TimeOutValue = deviceExtension->TimeOutValue;
2457:
2458: //
2459: // Send SCSI command (CDB) to device
2460: //
2461:
2462: status = ScsiClassSendSrbSynchronous(DeviceObject,
2463: &srb,
2464: InquiryBuffer,
2465: INQUIRYDATABUFFERSIZE,
2466: FALSE);
2467:
2468: return status;
2469: }
2470:
2471:
2472: static
2473: NTSTATUS
2474: RewindToBOT(
2475: IN PDEVICE_OBJECT DeviceObject,
2476: IN PIRP Irp
2477: )
2478:
2479: /*++
2480: Routine Description:
2481:
2482: This routine will rewind to BOT. Note: BOP is BOT for both the
2483: data partition and the directory partition; thus, if QFA is enabled,
2484: a rewind to BOT is a rewind to BOP of the active partition.
2485:
2486: Arguments:
2487:
2488: DeviceObject
2489: Irp
2490:
2491: Return Value:
2492:
2493: NTSTATUS
2494:
2495: --*/
2496:
2497: {
2498: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2499: SCSI_REQUEST_BLOCK srb;
2500: PCDB cdb = (PCDB)srb.Cdb;
2501: NTSTATUS status;
2502:
2503: //
2504: // Zero CDB in SRB on stack.
2505: //
2506:
2507: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
2508:
2509: //
2510: // Prepare SCSI command (CDB)
2511: //
2512:
2513: srb.CdbLength = CDB6GENERIC_LENGTH;
2514:
2515: cdb->CDB6INQUIRY.OperationCode = SCSIOP_REWIND;
2516:
2517: //
2518: // Set timeout value.
2519: //
2520:
2521: srb.TimeOutValue = 180;
2522:
2523: //
2524: // Send SCSI command (CDB) to device
2525: //
2526:
2527: status = ScsiClassSendSrbSynchronous(DeviceObject,
2528: &srb,
2529: NULL,
2530: 0,
2531: FALSE);
2532: return status;
2533: }
2534:
2535:
2536: static
2537: ULONG
2538: WhichIsIt(
2539: IN PINQUIRYDATA InquiryData
2540: )
2541:
2542: /*++
2543: Routine Description:
2544:
2545: This routine determines a drive's identity from the Product ID field
2546: in its inquiry data.
2547:
2548: Arguments:
2549:
2550: InquiryData (from an Inquiry command)
2551:
2552: Return Value:
2553:
2554: driveID
2555:
2556: --*/
2557:
2558: {
2559: if (RtlCompareMemory(InquiryData->VendorId,"TANDBERG",8) == 8) {
2560:
2561: if (RtlCompareMemory(InquiryData->ProductId," TDC 3600",9) == 9) {
2562: return TDC_3600;
2563: }
2564:
2565: if (RtlCompareMemory(InquiryData->ProductId," TDC 3800",9) == 9) {
2566: return TDC_3800;
2567: }
2568:
2569: if (RtlCompareMemory(InquiryData->ProductId," TDC 4100",9) == 9) {
2570: return TDC_4100;
2571: }
2572:
2573: if (RtlCompareMemory(InquiryData->ProductId," IBM 4100",9) == 9) {
2574: return TDC_4100;
2575: }
2576:
2577: if (RtlCompareMemory(InquiryData->ProductId," TDC 4200",9) == 9) {
2578: return TDC_4200;
2579: }
2580:
2581: }
2582:
2583: if (RtlCompareMemory(InquiryData->VendorId,"DEC ",8) == 8) {
2584:
2585: if (RtlCompareMemory(InquiryData->ProductId,"TZK10",5) == 5) {
2586: return TDC_3800;
2587: }
2588:
2589: }
2590:
2591: return (ULONG)0;
2592: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.