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