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