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