|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1992 Microsoft Corporation
4:
5: Module Name:
6:
7: exabyte2.c
8:
9: Abstract:
10:
11: This module contains the device-specific routines for the Exabyte
12: EXB-8500 tape drive.
13:
14: Author:
15:
16: Mike Glass
17: Hunter Small (Maynard)
18: Lori Brown (Maynard)
19: Chris Hugh Sam (Maynard)
20:
21: Environment:
22:
23: kernel mode only
24:
25: Revision History:
26:
27: --*/
28:
29: #include "ntddk.h"
30: #include "tape.h"
31:
32: //
33: // Internal (module wide) defines that symbolize
34: // density codes returned by/from EXB-8500 drives
35: //
36: #define EXB_XX00 0 // undetermined tape recording density
37: #define EXB_8200 20 // 0x14 // EXB-8200 tape recording density
38: #define EXB_8500 133 // 0x85 // EXB-8500 tape recording density
39:
40: //
41: // Internal (module wide) defines that symbolize
42: // the 8mm drives supported by this module.
43: //
44: #define EXABYTE_8500 1 // aka the Maynard 5000
45: #define EXABYTE_8505 2 // An Exabyte 8500 with data compresion
46: #define IBM_8505 3 // OEM Exabyte 8500 with data compresion
47:
48: //
49: // Define EXABYTE vendor unique mode select/sense information.
50: //
51:
52: #define EXABYTE_MODE_LENGTH 0x11
53: #define EXABYTE_CARTRIDGE 0x80
54: #define EXABYTE_NO_DATA_DISCONNECT 0x20
55: #define EXABYTE_NO_BUSY_ENABLE 0x08
56: #define EXABYTE_EVEN_BYTE_DISCONNECT 0x04
57: #define EXABYTE_PARITY_ENABLE 0x02
58: #define EXABYTE_NO_AUTO_LOAD 0X01
59:
60: //
61: // Function prototype(s) for internal function(s)
62: //
63: static ULONG WhichIsIt(IN PINQUIRYDATA InquiryData);
64:
65:
66: NTSTATUS
67: TapeCreatePartition(
68: IN PDEVICE_OBJECT DeviceObject,
69: IN PIRP Irp
70: )
71:
72: /*++
73: Routine Description:
74:
75: This routine would partition the tape if the drive was able to do
76: so: because the drive cannot do so, this routine always returns a
77: STATUS_NOT_IMPLEMENTED status.
78:
79: Arguments:
80:
81: DeviceObject
82: Irp
83:
84: Return Value:
85:
86: NTSTATUS
87:
88: --*/
89:
90: {
91: DebugPrint((3,"TapeCreatePartition: Enter routine\n"));
92: DebugPrint((1,"TapeCreatePartition: operation not supported\n"));
93: return STATUS_NOT_IMPLEMENTED;
94:
95: } // end TapeCreatePartition()
96:
97:
98: NTSTATUS
99: TapeErase(
100: IN PDEVICE_OBJECT DeviceObject,
101: IN PIRP Irp
102: )
103:
104: /*++
105: Routine Description:
106:
107: This routine will erase to EOT from the "current position" on tape;
108: i.e., tape will be erased to EOT from the point on tape at which the
109: tape is positioned at the time of entry herein.
110:
111: Arguments:
112:
113: DeviceObject
114: Irp
115:
116: Return Value:
117:
118: NTSTATUS
119:
120: --*/
121:
122: {
123: PTAPE_ERASE tapeErase = Irp->AssociatedIrp.SystemBuffer;
124: SCSI_REQUEST_BLOCK srb;
125: PCDB cdb = (PCDB)srb.Cdb;
126: NTSTATUS status;
127:
128: DebugPrint((3,"TapeErase: Enter routine\n"));
129:
130: if (tapeErase->Immediate) {
131: switch (tapeErase->Type) {
132: case TAPE_ERASE_LONG:
133: DebugPrint((3,"TapeErase: immediate\n"));
134: break;
135:
136: case TAPE_ERASE_SHORT:
137: default:
138: DebugPrint((1,"TapeErase: EraseType, immediate -- operation not supported\n"));
139: return STATUS_NOT_IMPLEMENTED;
140: }
141: }
142:
143: switch (tapeErase->Type) {
144: case TAPE_ERASE_LONG:
145: DebugPrint((3,"TapeErase: long\n"));
146: break;
147:
148: case TAPE_ERASE_SHORT:
149: default:
150: DebugPrint((1,"TapeErase: EraseType -- operation not supported\n"));
151: return STATUS_NOT_IMPLEMENTED;
152: }
153:
154: //
155: // Zero CDB in SRB on stack.
156: //
157:
158: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
159:
160: //
161: // Prepare SCSI command (CDB)
162: //
163:
164: srb.CdbLength = CDB6GENERIC_LENGTH;
165:
166: cdb->ERASE.OperationCode = SCSIOP_ERASE;
167: cdb->ERASE.Immediate = tapeErase->Immediate;
168: cdb->ERASE.Long = SETBITON;
169:
170: //
171: // Set timeout value.
172: //
173:
174: srb.TimeOutValue = 18000;
175:
176: //
177: // Send SCSI command (CDB) to device
178: //
179:
180: DebugPrint((3,"TapeErase: SendSrb (erase)\n"));
181:
182: status = ScsiClassSendSrbSynchronous(DeviceObject,
183: &srb,
184: NULL,
185: 0,
186: FALSE);
187:
188: if (!NT_SUCCESS(status)) {
189: DebugPrint((1,"TapeErase: erase, SendSrb unsuccessful\n"));
190: }
191:
192: return status;
193:
194: } // end TapeErase()
195:
196:
197: VOID
198: TapeError(
199: PDEVICE_OBJECT DeviceObject,
200: PSCSI_REQUEST_BLOCK Srb,
201: NTSTATUS *Status,
202: BOOLEAN *Retry
203: )
204:
205: /*++
206:
207: Routine Description:
208:
209: When a request completes with error, the routine InterpretSenseInfo is
210: called to determine from the sense data whether the request should be
211: retried and what NT status to set in the IRP. Then this routine is called
212: for tape requests to handle tape-specific errors and update the nt status
213: and retry boolean.
214:
215: Arguments:
216:
217: DeviceObject - Supplies a pointer to the device object.
218:
219: Srb - Supplies a pointer to the failing Srb.
220:
221: Status - NT Status used to set the IRP's completion status.
222:
223: Retry - Indicates that this request should be retried.
224:
225: Return Value:
226:
227: None.
228:
229: --*/
230:
231: {
232: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
233: PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
234: NTSTATUS status = *Status;
235: BOOLEAN retry = *Retry;
236:
237: DebugPrint((3,"TapeError: Enter routine\n"));
238: DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", status, retry));
239: return;
240:
241: } // end TapeError()
242:
243:
244: NTSTATUS
245: TapeGetDriveParameters(
246: IN PDEVICE_OBJECT DeviceObject,
247: IN PIRP Irp
248: )
249:
250: /*++
251: Routine Description:
252:
253: This routine determines and returns the "drive parameters" of the
254: Exabyte 8500 tape drive associated with "DeviceObject". From time to
255: time, the drive paramater set of a given drive is variable. It will
256: change as drive operating characteristics change: e.g., tape media
257: type loaded, recording density of the media type loaded, etc.
258:
259: Arguments:
260:
261: DeviceObject
262: Irp
263:
264: Return Value:
265:
266: NTSTATUS
267:
268: --*/
269:
270: {
271: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
272: PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
273: PMODE_PARM_READ_WRITE_DATA modeParmBuffer;
274: PREAD_BLOCK_LIMITS_DATA blockLimits;
275: UCHAR densityCode;
276: SCSI_REQUEST_BLOCK srb;
277: PCDB cdb = (PCDB)srb.Cdb;
278: NTSTATUS status;
279:
280: DebugPrint((3,"TapeGetDriveParameters: Enter routine\n"));
281:
282: RtlZeroMemory(tapeGetDriveParams, sizeof(TAPE_GET_DRIVE_PARAMETERS));
283: Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
284:
285: modeParmBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
286: sizeof(MODE_PARM_READ_WRITE_DATA));
287:
288: if (!modeParmBuffer) {
289: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (modeParmBuffer)\n"));
290: return STATUS_INSUFFICIENT_RESOURCES;
291: }
292:
293: RtlZeroMemory(modeParmBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
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->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
308: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_PARM_READ_WRITE_DATA);
309:
310: //
311: // Set timeout value.
312: //
313:
314: srb.TimeOutValue = deviceExtension->TimeOutValue;
315:
316: //
317: // Send SCSI command (CDB) to device
318: //
319:
320: DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode sense)\n"));
321:
322: status = ScsiClassSendSrbSynchronous(DeviceObject,
323: &srb,
324: modeParmBuffer,
325: sizeof(MODE_PARM_READ_WRITE_DATA),
326: FALSE);
327:
328: if (NT_SUCCESS(status)) {
329: densityCode = modeParmBuffer->ParameterListBlock.DensityCode;
330: }
331:
332: ExFreePool(modeParmBuffer);
333:
334: if (!NT_SUCCESS(status)) {
335: DebugPrint((1,"TapeGetDriveParameters: mode sense, SendSrb unsuccessful\n"));
336: return status;
337: }
338:
339: blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
340: sizeof(READ_BLOCK_LIMITS_DATA));
341:
342: if (!blockLimits) {
343: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (blockLimits)\n"));
344: return STATUS_INSUFFICIENT_RESOURCES;
345: }
346:
347: RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));
348:
349: //
350: // Zero CDB in SRB on stack.
351: //
352:
353: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
354:
355: //
356: // Prepare SCSI command (CDB)
357: //
358:
359: srb.CdbLength = CDB6GENERIC_LENGTH;
360:
361: cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
362:
363: //
364: // Set timeout value.
365: //
366:
367: srb.TimeOutValue = deviceExtension->TimeOutValue;
368:
369: //
370: // Send SCSI command (CDB) to device
371: //
372:
373: DebugPrint((3,"TapeGetDriveParameters: SendSrb (read block limits)\n"));
374:
375: status = ScsiClassSendSrbSynchronous(DeviceObject,
376: &srb,
377: blockLimits,
378: sizeof(READ_BLOCK_LIMITS_DATA),
379: FALSE);
380:
381: if (NT_SUCCESS(status)) {
382: tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
383: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
384: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);
385:
386: tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
387: tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
388: }
389:
390: ExFreePool(blockLimits);
391:
392: if (!NT_SUCCESS(status)) {
393: return status;
394: }
395:
396: tapeGetDriveParams->ECC = 0;
397: tapeGetDriveParams->Compression = 0;
398: tapeGetDriveParams->DataPadding = 0;
399: tapeGetDriveParams->ReportSetmarks = 0;
400: tapeGetDriveParams->MaximumPartitionCount = 0;
401: tapeGetDriveParams->DefaultBlockSize = 1024;
402:
403: tapeGetDriveParams->FeaturesLow |=
404: TAPE_DRIVE_ERASE_LONG |
405: TAPE_DRIVE_ERASE_IMMEDIATE |
406: TAPE_DRIVE_FIXED_BLOCK |
407: TAPE_DRIVE_VARIABLE_BLOCK |
408: TAPE_DRIVE_WRITE_PROTECT |
409: TAPE_DRIVE_GET_ABSOLUTE_BLK |
410: TAPE_DRIVE_GET_LOGICAL_BLK;
411:
412: tapeGetDriveParams->FeaturesHigh |=
413: TAPE_DRIVE_LOAD_UNLOAD |
414: TAPE_DRIVE_LOCK_UNLOCK |
415: TAPE_DRIVE_REWIND_IMMEDIATE |
416: TAPE_DRIVE_SET_BLOCK_SIZE |
417: TAPE_DRIVE_LOAD_UNLD_IMMED |
418: TAPE_DRIVE_RELATIVE_BLKS |
419: TAPE_DRIVE_FILEMARKS |
420: TAPE_DRIVE_REVERSE_POSITION |
421: TAPE_DRIVE_WRITE_SHORT_FMKS |
422: TAPE_DRIVE_WRITE_LONG_FMKS |
423: TAPE_DRIVE_WRITE_MARK_IMMED |
424: TAPE_DRIVE_ABSOLUTE_BLK |
425: TAPE_DRIVE_ABS_BLK_IMMED |
426: TAPE_DRIVE_LOGICAL_BLK |
427: TAPE_DRIVE_LOG_BLK_IMMED |
428: TAPE_DRIVE_END_OF_DATA;
429:
430: tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
431:
432: DebugPrint((3,"TapeGetDriveParameters: FeaturesLow == 0x%.8X\n",
433: tapeGetDriveParams->FeaturesLow));
434: DebugPrint((3,"TapeGetDriveParameters: FeaturesHigh == 0x%.8X\n",
435: tapeGetDriveParams->FeaturesHigh));
436:
437: return status;
438:
439: } // end TapeGetDriveParameters()
440:
441:
442: NTSTATUS
443: TapeGetMediaParameters(
444: IN PDEVICE_OBJECT DeviceObject,
445: IN PIRP Irp
446: )
447:
448: /*++
449: Routine Description:
450:
451: This routine determines and returns the "media parameters" of the
452: Exabyte 8500 tape drive associated with "DeviceObject". Tape media
453: must be present (loaded) in the drive for this function to return
454: "no error".
455:
456: Arguments:
457:
458: DeviceObject
459: Irp
460:
461: Return Value:
462:
463: NTSTATUS
464:
465: --*/
466:
467: {
468: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
469: PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
470: PMODE_PARM_READ_WRITE_DATA modeBuffer;
471: ULONG sectorShift;
472: SCSI_REQUEST_BLOCK srb;
473: PCDB cdb = (PCDB)srb.Cdb;
474: NTSTATUS status;
475:
476: DebugPrint((3,"TapeGetMediaParameters: Enter routine\n"));
477:
478: RtlZeroMemory(tapeGetMediaParams, sizeof(TAPE_GET_MEDIA_PARAMETERS));
479: Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
480:
481: //
482: // Zero CDB in SRB on stack.
483: //
484:
485: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
486:
487: //
488: // Prepare SCSI command (CDB)
489: //
490:
491: srb.CdbLength = CDB6GENERIC_LENGTH;
492:
493: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
494:
495: //
496: // Set timeout value.
497: //
498:
499: srb.TimeOutValue = deviceExtension->TimeOutValue;
500:
501: //
502: // Send SCSI command (CDB) to device
503: //
504:
505: DebugPrint((3,"TapeGetMediaParameters: SendSrb (test unit ready)\n"));
506:
507: status = ScsiClassSendSrbSynchronous(DeviceObject,
508: &srb,
509: NULL,
510: 0,
511: FALSE);
512:
513: if (!NT_SUCCESS(status)) {
514: DebugPrint((1,"TapeGetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
515: return status;
516: }
517:
518: modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
519: EXABYTE_MODE_LENGTH);
520:
521: if (!modeBuffer) {
522: DebugPrint((1,"TapeGetMediaParameters: insufficient resources (modeBuffer)\n"));
523: return STATUS_INSUFFICIENT_RESOURCES;
524: }
525:
526: RtlZeroMemory(modeBuffer, EXABYTE_MODE_LENGTH);
527:
528: //
529: // Zero CDB in SRB on stack.
530: //
531:
532: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
533:
534: //
535: // Prepare SCSI command (CDB)
536: //
537:
538: srb.CdbLength = CDB6GENERIC_LENGTH;
539:
540: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
541: cdb->MODE_SENSE.AllocationLength = EXABYTE_MODE_LENGTH;
542:
543: //
544: // Set timeout value.
545: //
546:
547: srb.TimeOutValue = deviceExtension->TimeOutValue;
548:
549: //
550: // Send SCSI command (CDB) to device
551: //
552:
553: DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense)\n"));
554:
555: status = ScsiClassSendSrbSynchronous(DeviceObject,
556: &srb,
557: modeBuffer,
558: EXABYTE_MODE_LENGTH,
559: FALSE);
560:
561: if (NT_SUCCESS(status)) {
562:
563: tapeGetMediaParams->BlockSize = modeBuffer->ParameterListBlock.BlockLength[2];
564: tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[1] << 8);
565: tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[0] << 16);
566:
567: WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift);
568: deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize;
569: deviceExtension->SectorShift = sectorShift;
570:
571: tapeGetMediaParams->WriteProtected =
572: ((modeBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & 0x01);
573:
574: //
575: // Set the even byte disconnect flag in the mode data. This is the
576: // first byte of the vendor unique data.
577: //
578:
579: *((PUCHAR)(modeBuffer+1)) |= EXABYTE_EVEN_BYTE_DISCONNECT;
580:
581: modeBuffer->ParameterListHeader.ModeDataLength = 0;
582: modeBuffer->ParameterListHeader.MediumType = 0;
583: modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
584: modeBuffer->ParameterListBlock.DensityCode = 0;
585: modeBuffer->ParameterListBlock.NumberOfBlocks[0] = 0;
586: modeBuffer->ParameterListBlock.NumberOfBlocks[1] = 0;
587: modeBuffer->ParameterListBlock.NumberOfBlocks[2] = 0;
588: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
589:
590: ScsiClassSendSrbSynchronous(DeviceObject,
591: &srb,
592: modeBuffer,
593: EXABYTE_MODE_LENGTH,
594: TRUE);
595:
596:
597: } else {
598:
599: DebugPrint((1,"TapeGetMediaParameters: mode sense, SendSrb unsuccessful\n"));
600:
601: }
602:
603: ExFreePool(modeBuffer);
604:
605: return status;
606:
607: } // end TapeGetMediaParameters()
608:
609:
610: NTSTATUS
611: TapeGetPosition(
612: IN PDEVICE_OBJECT DeviceObject,
613: IN PIRP Irp
614: )
615:
616: /*++
617: Routine Description:
618:
619: This routine returns the current position of the tape.
620:
621: Arguments:
622:
623: DeviceObject
624: Irp
625:
626: Return Value:
627:
628: NTSTATUS
629:
630: --*/
631:
632: {
633: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
634: PTAPE_GET_POSITION tapeGetPosition = Irp->AssociatedIrp.SystemBuffer;
635: PTAPE_POSITION_DATA logicalBuffer;
636: ULONG type;
637: SCSI_REQUEST_BLOCK srb;
638: PCDB cdb = (PCDB)srb.Cdb;
639: NTSTATUS status;
640:
641: DebugPrint((3,"TapeGetPosition: Enter routine\n"));
642:
643: type = tapeGetPosition->Type;
644: RtlZeroMemory(tapeGetPosition, sizeof(TAPE_GET_POSITION));
645: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
646: tapeGetPosition->Type = type;
647:
648: switch (type) {
649: case TAPE_ABSOLUTE_POSITION:
650: case TAPE_LOGICAL_POSITION:
651: logicalBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
652: sizeof(TAPE_POSITION_DATA));
653:
654: if (!logicalBuffer) {
655: DebugPrint((1,"TapeGetPosition: insufficient resources (logicalBuffer)\n"));
656: return STATUS_INSUFFICIENT_RESOURCES;
657: }
658:
659: RtlZeroMemory(logicalBuffer, sizeof(TAPE_POSITION_DATA));
660:
661: //
662: // Zero CDB in SRB on stack.
663: //
664:
665: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
666:
667: //
668: // Prepare SCSI command (CDB)
669: //
670:
671: srb.CdbLength = CDB10GENERIC_LENGTH;
672:
673: cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION;
674:
675: //
676: // Set timeout value.
677: //
678:
679: srb.TimeOutValue = deviceExtension->TimeOutValue;
680:
681: //
682: // Send SCSI command (CDB) to device
683: //
684:
685: DebugPrint((3,"TapeGetPosition: SendSrb (read position)\n"));
686:
687: status = ScsiClassSendSrbSynchronous(DeviceObject,
688: &srb,
689: logicalBuffer,
690: sizeof(TAPE_POSITION_DATA),
691: FALSE);
692:
693: if (NT_SUCCESS(status)) {
694:
695: if (logicalBuffer->BlockPositionUnsupported) {
696: DebugPrint((1,"TapeGetPosition: read position -- logical block position unsupported\n"));
697: ExFreePool(logicalBuffer);
698: return STATUS_INVALID_DEVICE_REQUEST;
699: }
700:
701: tapeGetPosition->Partition = 0;
702: tapeGetPosition->Offset.HighPart = 0;
703: REVERSE_BYTES((PFOUR_BYTE)&tapeGetPosition->Offset.LowPart,
704: (PFOUR_BYTE)logicalBuffer->FirstBlock);
705:
706: }
707:
708: ExFreePool(logicalBuffer);
709:
710: if (!NT_SUCCESS(status)) {
711: DebugPrint((1,"TapeGetPosition: read position, SendSrb unsuccessful\n"));
712: return status;
713: }
714:
715: break;
716:
717: default:
718: DebugPrint((1,"TapeGetPosition: PositionType -- operation not supported\n"));
719: return STATUS_NOT_IMPLEMENTED;
720: }
721:
722: return status;
723:
724: } // end TapeGetPosition()
725:
726:
727: NTSTATUS
728: TapeGetStatus(
729: IN PDEVICE_OBJECT DeviceObject,
730: IN PIRP Irp
731: )
732:
733: /*++
734: Routine Description:
735:
736: This routine returns the status of the device.
737:
738: Arguments:
739:
740: DeviceObject
741: Irp
742:
743: Return Value:
744:
745: NTSTATUS
746:
747: --*/
748:
749: {
750: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
751: SCSI_REQUEST_BLOCK srb;
752: PCDB cdb = (PCDB)srb.Cdb;
753: NTSTATUS status;
754:
755: DebugPrint((3,"TapeGetStatus: Enter routine\n"));
756:
757: //
758: // Zero CDB in SRB on stack.
759: //
760:
761: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
762:
763: //
764: // Prepare SCSI command (CDB)
765: //
766:
767: srb.CdbLength = CDB6GENERIC_LENGTH;
768:
769: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
770:
771: //
772: // Set timeout value.
773: //
774:
775: srb.TimeOutValue = deviceExtension->TimeOutValue;
776:
777: //
778: // Send SCSI command (CDB) to device
779: //
780:
781: DebugPrint((3,"TapeGetStatus: SendSrb (test unit ready)\n"));
782:
783: status = ScsiClassSendSrbSynchronous(DeviceObject,
784: &srb,
785: NULL,
786: 0,
787: FALSE);
788:
789: if (!NT_SUCCESS(status)) {
790: DebugPrint((1,"TapeGetStatus: test unit ready, SendSrb unsuccessful\n"));
791: }
792:
793: return status;
794:
795: } // end TapeGetStatus()
796:
797:
798: NTSTATUS
799: TapePrepare(
800: IN PDEVICE_OBJECT DeviceObject,
801: IN PIRP Irp
802: )
803:
804: /*++
805: Routine Description:
806:
807: This routine loads, unloads, locks, or unlocks the tape.
808:
809: Arguments:
810:
811: DeviceObject
812: Irp
813:
814: Return Value:
815:
816: NTSTATUS
817:
818: --*/
819:
820: {
821: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
822: PTAPE_PREPARE tapePrepare = Irp->AssociatedIrp.SystemBuffer;
823: SCSI_REQUEST_BLOCK srb;
824: PCDB cdb = (PCDB)srb.Cdb;
825: NTSTATUS status;
826:
827: DebugPrint((3,"TapePrepare: Enter routine\n"));
828:
829: if (tapePrepare->Immediate) {
830: switch (tapePrepare->Operation) {
831: case TAPE_LOAD:
832: case TAPE_UNLOAD:
833: DebugPrint((3,"TapePrepare: immediate\n"));
834: break;
835:
836: case TAPE_TENSION:
837: case TAPE_LOCK:
838: case TAPE_UNLOCK:
839: default:
840: DebugPrint((1,"TapePrepare: Operation, immediate -- operation not supported\n"));
841: return STATUS_NOT_IMPLEMENTED;
842: }
843: }
844:
845: //
846: // Zero CDB in SRB on stack.
847: //
848:
849: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
850:
851: //
852: // Prepare SCSI command (CDB)
853: //
854:
855: srb.CdbLength = CDB6GENERIC_LENGTH;
856:
857: cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
858:
859: switch (tapePrepare->Operation) {
860: case TAPE_LOAD:
861: DebugPrint((3,"TapePrepare: Operation == load\n"));
862: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
863: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
864: srb.TimeOutValue = 150;
865: break;
866:
867: case TAPE_UNLOAD:
868: DebugPrint((3,"TapePrepare: Operation == unload\n"));
869: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
870: srb.TimeOutValue = 150;
871: break;
872:
873: case TAPE_LOCK:
874: DebugPrint((3,"TapePrepare: Operation == lock\n"));
875: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
876: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
877: srb.TimeOutValue = 150;
878: break;
879:
880: case TAPE_UNLOCK:
881: DebugPrint((3,"TapePrepare: Operation == unlock\n"));
882: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
883: srb.TimeOutValue = 150;
884: break;
885:
886: case TAPE_TENSION:
887: default:
888: DebugPrint((1,"TapePrepare: Operation -- operation not supported\n"));
889: return STATUS_NOT_IMPLEMENTED;
890: }
891:
892: //
893: // Send SCSI command (CDB) to device
894: //
895:
896: DebugPrint((3,"TapePrepare: SendSrb (Operation)\n"));
897:
898: status = ScsiClassSendSrbSynchronous(DeviceObject,
899: &srb,
900: NULL,
901: 0,
902: FALSE);
903:
904: if (!NT_SUCCESS(status)) {
905: DebugPrint((1,"TapePrepare: Operation, SendSrb unsuccessful\n"));
906: }
907:
908: return status;
909:
910: } // end TapePrepare()
911:
912:
913: NTSTATUS
914: TapeReadWrite(
915: IN PDEVICE_OBJECT DeviceObject,
916: IN PIRP Irp
917: )
918:
919: /*++
920:
921: Routine Description:
922:
923: This routine builds SRBs and CDBs for read and write requests to
924: Exabyte 8500 drives.
925:
926: Arguments:
927:
928: DeviceObject
929: Irp
930:
931: Return Value:
932:
933: Returns STATUS_PENDING.
934:
935: --*/
936:
937: {
938: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
939: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
940: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
941: PSCSI_REQUEST_BLOCK srb;
942: PCDB cdb;
943: KIRQL currentIrql;
944: ULONG transferBlocks;
945: LARGE_INTEGER startingOffset =
946: currentIrpStack->Parameters.Read.ByteOffset;
947:
948: DebugPrint((3,"TapeReadWrite: Enter routine\n"));
949:
950: //
951: // Allocate an Srb.
952: //
953:
954: if (deviceExtension->SrbZone != NULL &&
955: (srb = ExInterlockedAllocateFromZone(
956: deviceExtension->SrbZone,
957: deviceExtension->SrbZoneSpinLock)) != NULL) {
958:
959: srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
960:
961: } else {
962:
963: //
964: // Allocate Srb from non-paged pool.
965: // This call must succeed.
966: //
967:
968: srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
969:
970: srb->SrbFlags = 0;
971:
972: }
973:
974: //
975: // Write length to SRB.
976: //
977:
978: srb->Length = SCSI_REQUEST_BLOCK_SIZE;
979:
980: //
981: // Set up IRP Address.
982: //
983:
984: srb->OriginalRequest = Irp;
985:
986: //
987: // Set up target id and logical unit number.
988: //
989:
990: srb->PathId = deviceExtension->PathId;
991: srb->TargetId = deviceExtension->TargetId;
992: srb->Lun = deviceExtension->Lun;
993:
994:
995: srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
996:
997: srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
998:
999: //
1000: // Save byte count of transfer in SRB Extension.
1001: //
1002:
1003: srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
1004:
1005: //
1006: // Indicate auto request sense by specifying buffer and size.
1007: //
1008:
1009: srb->SenseInfoBuffer = deviceExtension->SenseData;
1010:
1011: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1012:
1013: //
1014: // Initialize the queue actions field.
1015: //
1016:
1017: srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
1018:
1019: //
1020: // Set timeout value in seconds.
1021: //
1022:
1023: srb->TimeOutValue = deviceExtension->TimeOutValue;
1024:
1025: //
1026: // Zero statuses.
1027: //
1028:
1029: srb->SrbStatus = srb->ScsiStatus = 0;
1030:
1031: srb->NextSrb = 0;
1032:
1033: //
1034: // Indicate that 6-byte CDB's will be used.
1035: //
1036:
1037: srb->CdbLength = CDB6GENERIC_LENGTH;
1038:
1039: //
1040: // Fill in CDB fields.
1041: //
1042:
1043: cdb = (PCDB)srb->Cdb;
1044:
1045: //
1046: // Zero CDB in SRB.
1047: //
1048:
1049: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1050:
1051: //
1052: // Since we are writing fixed block mode, normalize transfer count
1053: // to number of blocks.
1054: //
1055:
1056: transferBlocks =
1057: currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift;
1058:
1059: //
1060: // Set up transfer length
1061: //
1062:
1063: cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
1064: cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff);
1065: cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
1066:
1067: //
1068: // Tell the drive we are in fixed block mode
1069: //
1070:
1071: cdb->CDB6READWRITETAPE.VendorSpecific = 1;
1072:
1073: //
1074: // Set transfer direction flag and Cdb command.
1075: //
1076:
1077: if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
1078:
1079: DebugPrint((3, "TapeRequest: Read Command\n"));
1080:
1081: srb->SrbFlags = SRB_FLAGS_DATA_IN;
1082: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
1083:
1084: } else {
1085:
1086: DebugPrint((3, "TapeRequest: Write Command\n"));
1087:
1088: srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1089: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
1090: }
1091:
1092: //
1093: // Or in the default flags from the device object.
1094: //
1095:
1096: srb->SrbFlags |= deviceExtension->SrbFlags;
1097:
1098: //
1099: // Set up major SCSI function.
1100: //
1101:
1102: nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1103:
1104: //
1105: // Save SRB address in next stack for port driver.
1106: //
1107:
1108: nextIrpStack->Parameters.Scsi.Srb = srb;
1109:
1110: //
1111: // Save retry count in current IRP stack.
1112: //
1113:
1114: currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
1115:
1116: //
1117: // Set up IoCompletion routine address.
1118: //
1119:
1120: IoSetCompletionRoutine(Irp,
1121: ScsiClassIoComplete,
1122: srb,
1123: TRUE,
1124: TRUE,
1125: FALSE);
1126:
1127: return STATUS_PENDING;
1128:
1129: } // end TapeReadWrite()
1130:
1131:
1132: NTSTATUS
1133: TapeSetDriveParameters(
1134: IN PDEVICE_OBJECT DeviceObject,
1135: IN PIRP Irp
1136: )
1137:
1138: /*++
1139: Routine Description:
1140:
1141: This routine would "set" the "drive parameters", but this drive does not
1142: support doing so: this routine always returns a STATUS_NOT_IMPLEMENTED
1143: status
1144:
1145: Arguments:
1146:
1147: DeviceObject
1148: Irp
1149:
1150: Return Value:
1151:
1152: NTSTATUS
1153:
1154: --*/
1155:
1156: {
1157: DebugPrint((3,"TapeSetDriveParameters: Enter routine\n"));
1158: DebugPrint((1,"TapeSetDriveParameters: operation not supported\n"));
1159: return STATUS_NOT_IMPLEMENTED;
1160:
1161: } // end TapeSetDriveParameters()
1162:
1163:
1164: NTSTATUS
1165: TapeSetMediaParameters(
1166: IN PDEVICE_OBJECT DeviceObject,
1167: IN PIRP Irp
1168: )
1169:
1170: /*++
1171: Routine Description:
1172:
1173: This routine "sets" the "media parameters" of the Exabyte 8500 tape
1174: drive associated with "DeviceObject". Tape media must be present
1175: (loaded) in the drive for this function to return "no error".
1176:
1177: Arguments:
1178:
1179: DeviceObject
1180: Irp
1181:
1182: Return Value:
1183:
1184: NTSTATUS
1185:
1186: --*/
1187:
1188: {
1189: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1190: PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
1191: PMODE_PARM_READ_WRITE_DATA modeBuffer;
1192: SCSI_REQUEST_BLOCK srb;
1193: PCDB cdb = (PCDB)srb.Cdb;
1194: NTSTATUS status;
1195:
1196: DebugPrint((3,"TapeSetMediaParameters: Enter routine\n"));
1197:
1198: //
1199: // Zero CDB in SRB on stack.
1200: //
1201:
1202: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1203:
1204: //
1205: // Prepare SCSI command (CDB)
1206: //
1207:
1208: srb.CdbLength = CDB6GENERIC_LENGTH;
1209:
1210: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
1211:
1212: //
1213: // Set timeout value.
1214: //
1215:
1216: srb.TimeOutValue = deviceExtension->TimeOutValue;
1217:
1218: //
1219: // Send SCSI command (CDB) to device
1220: //
1221:
1222: DebugPrint((3,"TapeSetMediaParameters: SendSrb (test unit ready)\n"));
1223:
1224: status = ScsiClassSendSrbSynchronous(DeviceObject,
1225: &srb,
1226: NULL,
1227: 0,
1228: FALSE);
1229:
1230: if (!NT_SUCCESS(status)) {
1231: DebugPrint((1,"TapeSetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
1232: return status;
1233: }
1234:
1235: modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
1236: sizeof(MODE_PARM_READ_WRITE_DATA));
1237:
1238: if (!modeBuffer) {
1239: DebugPrint((1,"TapeSetMediaParameters: insufficient resources (modeBuffer)\n"));
1240: return STATUS_INSUFFICIENT_RESOURCES;
1241: }
1242:
1243: RtlZeroMemory(modeBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
1244:
1245: modeBuffer->ParameterListHeader.ModeDataLength = 0;
1246: modeBuffer->ParameterListHeader.MediumType = 0;
1247: modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
1248: modeBuffer->ParameterListHeader.BlockDescriptorLength =
1249: MODE_BLOCK_DESC_LENGTH;
1250:
1251: modeBuffer->ParameterListBlock.DensityCode = 0x7F;
1252: modeBuffer->ParameterListBlock.BlockLength[0] =
1253: ((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
1254: modeBuffer->ParameterListBlock.BlockLength[1] =
1255: ((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
1256: modeBuffer->ParameterListBlock.BlockLength[2] =
1257: (tapeSetMediaParams->BlockSize & 0xFF);
1258:
1259: //
1260: // Zero CDB in SRB on stack.
1261: //
1262:
1263: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1264:
1265: //
1266: // Prepare SCSI command (CDB)
1267: //
1268:
1269: srb.CdbLength = CDB6GENERIC_LENGTH;
1270:
1271: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1272: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
1273:
1274: //
1275: // Set timeout value.
1276: //
1277:
1278: srb.TimeOutValue = deviceExtension->TimeOutValue;
1279:
1280: //
1281: // Send SCSI command (CDB) to device
1282: //
1283:
1284: DebugPrint((3,"TapeSetMediaParameters: SendSrb (mode select)\n"));
1285:
1286: status = ScsiClassSendSrbSynchronous(DeviceObject,
1287: &srb,
1288: modeBuffer,
1289: sizeof(MODE_PARM_READ_WRITE_DATA),
1290: TRUE);
1291:
1292: ExFreePool(modeBuffer);
1293:
1294: if (!NT_SUCCESS(status)) {
1295: DebugPrint((1,"TapeSetMediaParameters: mode select, SendSrb unsuccessful\n"));
1296: }
1297:
1298: return status;
1299:
1300: } // end TapeSetMediaParameters()
1301:
1302:
1303: NTSTATUS
1304: TapeSetPosition(
1305: IN PDEVICE_OBJECT DeviceObject,
1306: IN PIRP Irp
1307: )
1308:
1309: /*++
1310: Routine Description:
1311:
1312: This routine sets the position of the tape.
1313:
1314: Arguments:
1315:
1316: DeviceObject
1317: Irp
1318:
1319: Return Value:
1320:
1321: NTSTATUS
1322:
1323: --*/
1324:
1325: {
1326: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1327: PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
1328: ULONG tapePositionVector;
1329: ULONG method;
1330: SCSI_REQUEST_BLOCK srb;
1331: PCDB cdb = (PCDB)srb.Cdb;
1332: NTSTATUS status;
1333:
1334:
1335: DebugPrint((3,"TapeSetPosition: Enter routine\n"));
1336:
1337: if (tapeSetPosition->Immediate) {
1338: switch (tapeSetPosition->Method) {
1339: case TAPE_REWIND:
1340: case TAPE_ABSOLUTE_BLOCK:
1341: case TAPE_LOGICAL_BLOCK:
1342: DebugPrint((3,"TapeSetPosition: immediate\n"));
1343: break;
1344:
1345: case TAPE_SPACE_END_OF_DATA:
1346: case TAPE_SPACE_RELATIVE_BLOCKS:
1347: case TAPE_SPACE_FILEMARKS:
1348: case TAPE_SPACE_SEQUENTIAL_FMKS:
1349: case TAPE_SPACE_SETMARKS:
1350: case TAPE_SPACE_SEQUENTIAL_SMKS:
1351: default:
1352: DebugPrint((1,"TapeSetPosition: PositionMethod, immediate -- operation not supported\n"));
1353: return STATUS_NOT_IMPLEMENTED;
1354: }
1355: }
1356:
1357: method = tapeSetPosition->Method;
1358: tapePositionVector = tapeSetPosition->Offset.LowPart;
1359:
1360: //
1361: // Zero CDB in SRB on stack.
1362: //
1363:
1364: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1365:
1366: //
1367: // Prepare SCSI command (CDB)
1368: //
1369:
1370: srb.CdbLength = CDB6GENERIC_LENGTH;
1371:
1372: cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
1373:
1374: switch (method) {
1375: case TAPE_REWIND:
1376: DebugPrint((3,"TapeSetPosition: method == rewind\n"));
1377: cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
1378: srb.TimeOutValue = 250;
1379: break;
1380:
1381: case TAPE_ABSOLUTE_BLOCK:
1382: case TAPE_LOGICAL_BLOCK:
1383: DebugPrint((3,"TapeSetPosition: method == locate (absolute/logical)\n"));
1384: srb.CdbLength = CDB10GENERIC_LENGTH;
1385: cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
1386: cdb->LOCATE.LogicalBlockAddress[0] =
1387: ((tapePositionVector >> 24) & 0xFF);
1388: cdb->LOCATE.LogicalBlockAddress[1] =
1389: ((tapePositionVector >> 16) & 0xFF);
1390: cdb->LOCATE.LogicalBlockAddress[2] =
1391: ((tapePositionVector >> 8) & 0xFF);
1392: cdb->LOCATE.LogicalBlockAddress[3] =
1393: (tapePositionVector & 0xFF);
1394: srb.TimeOutValue = 300;
1395: break;
1396:
1397: case TAPE_SPACE_END_OF_DATA:
1398: DebugPrint((3,"TapeSetPosition: method == space to end-of-data\n"));
1399: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1400: cdb->SPACE_TAPE_MARKS.Code = 3;
1401: srb.TimeOutValue = 150;
1402: break;
1403:
1404: case TAPE_SPACE_RELATIVE_BLOCKS:
1405: DebugPrint((3,"TapeSetPosition: method == space blocks\n"));
1406: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1407: cdb->SPACE_TAPE_MARKS.Code = 0;
1408: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
1409: ((tapePositionVector >> 16) & 0xFF);
1410: cdb->SPACE_TAPE_MARKS.NumMarks =
1411: ((tapePositionVector >> 8) & 0xFF);
1412: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
1413: (tapePositionVector & 0xFF);
1414: srb.TimeOutValue = 4100;
1415: break;
1416:
1417: case TAPE_SPACE_FILEMARKS:
1418: DebugPrint((3,"TapeSetPosition: method == space filemarks\n"));
1419: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1420: cdb->SPACE_TAPE_MARKS.Code = 1;
1421: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
1422: ((tapePositionVector >> 16) & 0xFF);
1423: cdb->SPACE_TAPE_MARKS.NumMarks =
1424: ((tapePositionVector >> 8) & 0xFF);
1425: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
1426: (tapePositionVector & 0xFF);
1427: srb.TimeOutValue = 4100;
1428: break;
1429:
1430: case TAPE_SPACE_SEQUENTIAL_FMKS:
1431: case TAPE_SPACE_SETMARKS:
1432: case TAPE_SPACE_SEQUENTIAL_SMKS:
1433: default:
1434: DebugPrint((1,"TapeSetPosition: PositionMethod -- operation not supported\n"));
1435: return STATUS_NOT_IMPLEMENTED;
1436: }
1437:
1438: //
1439: // Send SCSI command (CDB) to device
1440: //
1441:
1442: DebugPrint((3,"TapeSetPosition: SendSrb (method)\n"));
1443:
1444: status = ScsiClassSendSrbSynchronous(DeviceObject,
1445: &srb,
1446: NULL,
1447: 0,
1448: FALSE);
1449:
1450: if (!NT_SUCCESS(status)) {
1451: DebugPrint((1,"TapeSetPosition: method, SendSrb unsuccessful\n"));
1452: }
1453:
1454: return status;
1455:
1456: } // end TapeSetPosition()
1457:
1458:
1459: BOOLEAN
1460: TapeVerifyInquiry(
1461: IN PSCSI_INQUIRY_DATA LunInfo
1462: )
1463:
1464: /*++
1465: Routine Description:
1466:
1467: This routine determines if this driver should claim this drive.
1468:
1469: Arguments:
1470:
1471: LunInfo
1472:
1473: Return Value:
1474:
1475: TRUE - driver should claim this drive.
1476: FALSE - driver should not claim this drive.
1477:
1478: --*/
1479:
1480: {
1481: PINQUIRYDATA inquiryData;
1482:
1483: DebugPrint((3,"TapeVerifyInquiry: Enter routine\n"));
1484:
1485: inquiryData = (PVOID)LunInfo->InquiryData;
1486:
1487: //
1488: // Determine, from the Product ID field in the
1489: // inquiry data, whether or not to "claim" this drive.
1490: //
1491:
1492: return WhichIsIt(inquiryData)? TRUE : FALSE;
1493:
1494: } // end TapeVerifyInquiry()
1495:
1496:
1497: NTSTATUS
1498: TapeWriteMarks(
1499: IN PDEVICE_OBJECT DeviceObject,
1500: IN PIRP Irp
1501: )
1502:
1503: /*++
1504: Routine Description:
1505:
1506: This routine writes tapemarks on the tape.
1507:
1508: Arguments:
1509:
1510: DeviceObject
1511: Irp
1512:
1513: Return Value:
1514:
1515: NTSTATUS
1516:
1517: --*/
1518:
1519: {
1520: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1521: PTAPE_WRITE_MARKS tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
1522: SCSI_REQUEST_BLOCK srb;
1523: PCDB cdb = (PCDB)srb.Cdb;
1524: NTSTATUS status;
1525:
1526: DebugPrint((3,"TapeWriteMarks: Enter routine\n"));
1527:
1528: if (tapeWriteMarks->Immediate) {
1529: switch (tapeWriteMarks->Type) {
1530: case TAPE_SHORT_FILEMARKS:
1531: case TAPE_LONG_FILEMARKS:
1532: DebugPrint((3,"TapeWriteMarks: immediate\n"));
1533: break;
1534:
1535: case TAPE_SETMARKS:
1536: case TAPE_FILEMARKS:
1537: default:
1538: DebugPrint((1,"TapeWriteMarks: TapemarkType, immediate -- operation not supported\n"));
1539: return STATUS_NOT_IMPLEMENTED;
1540: }
1541: }
1542:
1543: //
1544: // Zero CDB in SRB on stack.
1545: //
1546:
1547: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1548:
1549: //
1550: // Prepare SCSI command (CDB)
1551: //
1552:
1553: srb.CdbLength = CDB6GENERIC_LENGTH;
1554:
1555: cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
1556: cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate;
1557:
1558: switch (tapeWriteMarks->Type) {
1559: case TAPE_SHORT_FILEMARKS:
1560: DebugPrint((3,"TapeWriteMarks: TapemarkType == short filemarks\n"));
1561: cdb->WRITE_TAPE_MARKS.Control = 0x80;
1562: break;
1563:
1564: case TAPE_LONG_FILEMARKS:
1565: DebugPrint((3,"TapeWriteMarks: TapemarkType == long filemarks\n"));
1566: break;
1567:
1568: case TAPE_SETMARKS:
1569: case TAPE_FILEMARKS:
1570: default:
1571: DebugPrint((1,"TapeWriteMarks: TapemarkType -- operation not supported\n"));
1572: return STATUS_NOT_IMPLEMENTED;
1573: }
1574:
1575: cdb->WRITE_TAPE_MARKS.TransferLength[0] =
1576: ((tapeWriteMarks->Count >> 16) & 0xFF);
1577: cdb->WRITE_TAPE_MARKS.TransferLength[1] =
1578: ((tapeWriteMarks->Count >> 8) & 0xFF);
1579: cdb->WRITE_TAPE_MARKS.TransferLength[2] =
1580: (tapeWriteMarks->Count & 0xFF);
1581:
1582: //
1583: // Set timeout value.
1584: //
1585:
1586: srb.TimeOutValue = deviceExtension->TimeOutValue;
1587:
1588: //
1589: // Send SCSI command (CDB) to device
1590: //
1591:
1592: DebugPrint((3,"TapeWriteMarks: SendSrb (TapemarkType)\n"));
1593:
1594: status = ScsiClassSendSrbSynchronous(DeviceObject,
1595: &srb,
1596: NULL,
1597: 0,
1598: FALSE);
1599:
1600: if (!NT_SUCCESS(status)) {
1601: DebugPrint((1,"TapeWriteMarks: TapemarkType, SendSrb unsuccessful\n"));
1602: }
1603:
1604: return status;
1605:
1606: } // end TapeWriteMarks()
1607:
1608:
1609: static
1610: ULONG
1611: WhichIsIt(
1612: IN PINQUIRYDATA InquiryData
1613: )
1614:
1615: /*++
1616: Routine Description:
1617:
1618: This routine determines a drive's identity from the Product ID field
1619: in its inquiry data.
1620:
1621: Arguments:
1622:
1623: InquiryData (from an Inquiry command)
1624:
1625: Return Value:
1626:
1627: driveID
1628:
1629: --*/
1630:
1631: {
1632: if (RtlCompareMemory(InquiryData->VendorId,"EXABYTE ",8) == 8) {
1633:
1634: if (RtlCompareMemory(InquiryData->ProductId,"EXB-8500",8) == 8) {
1635: return EXABYTE_8500;
1636: }
1637:
1638: if (RtlCompareMemory(InquiryData->ProductId,"EXB8500C",8) == 8) {
1639: return EXABYTE_8500;
1640: }
1641:
1642: if (RtlCompareMemory(InquiryData->ProductId,"EXB-8505",8) == 8) {
1643: return EXABYTE_8505;
1644: }
1645:
1646: if (RtlCompareMemory(InquiryData->ProductId,"IBM-8505",8) == 8) {
1647: return IBM_8505;
1648: }
1649:
1650: }
1651: return 0;
1652: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.