|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1992 Microsoft Corporation
4:
5: Module Name:
6:
7: 4mmdat.c
8:
9: Abstract:
10:
11: This module contains the device-specific routines for the Archive
12: Python DDS, DDS-DC, and Turbo-Speed DDS-DC DAT tape drives, the
13: HP 35470A DDS and 35480A DDS-DC DAT tape drives, the WangDAT
14: Model 3200 DDS-DC DAT tape drive, and the Compaq DDS-DC DAT tape
15: drive.
16:
17: Author:
18:
19: Mike Glass
20: Hunter Small (Maynard)
21: Lori Brown (Maynard)
22: Chris Hugh Sam (Maynard)
23:
24: Environment:
25:
26: kernel mode only
27:
28: Revision History:
29:
30: --*/
31:
32: #include "ntddk.h"
33: #include "tape.h"
34: #include "4mmdat.h"
35:
36: static ULONG gb_PartitionCount;
37: static UCHAR gb_VendorId[8];
38: static UCHAR gb_ProductId[16];
39:
40: //
41: // Internal (module wide) defines that symbolize
42: // the 4mm DAT drives supported by this module.
43: //
44: #define ARCHIVE_PYTHON 1 ;
45: #define DEC_TLZ06 2 ;
46: #define EXABYTE_4200 3 ;
47: #define EXABYTE_4200C 4 ;
48: #define HP_35470A 5 ;
49: #define HP_35480A 6 ;
50: #define HP_IBM35480A 7 ;
51: #define WANGDAT_1300 8 ;
52: #define WANGDAT_3100 9 ;
53: #define WANGDAT_3200 10 ;
54:
55: //
56: // Function prototype(s) for internal function(s)
57: //
58: static ULONG WhichIsIt(IN PINQUIRYDATA InquiryData);
59:
60:
61: NTSTATUS
62: TapeCreatePartition(
63: IN PDEVICE_OBJECT DeviceObject,
64: IN PIRP Irp
65: )
66:
67: /*++
68: Routine Description:
69:
70: This routine creates initiator-defined partitions on the tape.
71:
72: Arguments:
73:
74: DeviceObject
75: Irp
76:
77: Return Value:
78:
79: NTSTATUS
80:
81: --*/
82:
83: {
84: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
85: PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer;
86: PMODE_MEDIUM_PART_PAGE buffer;
87: SCSI_REQUEST_BLOCK srb;
88: PCDB cdb = (PCDB)srb.Cdb;
89: NTSTATUS status;
90:
91: //
92: // Zero CDB in SRB on stack.
93: //
94:
95: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
96:
97: srb.CdbLength = CDB6GENERIC_LENGTH;
98:
99: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
100:
101: //
102: // Set timeout value.
103: //
104:
105: srb.TimeOutValue = 8000;
106:
107: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE);
108: cdb->MODE_SELECT.PFBit = 1;
109:
110: buffer = ExAllocatePool(NonPagedPoolCacheAligned,
111: sizeof(MODE_MEDIUM_PART_PAGE));
112:
113: if (!buffer) {
114: return STATUS_INSUFFICIENT_RESOURCES;
115: }
116:
117: RtlZeroMemory(buffer, sizeof(MODE_MEDIUM_PART_PAGE));
118:
119: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
120:
121: buffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION;
122:
123: if (tapePartition->Count != 1 && tapePartition->Count != 2) {
124: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
125: ExFreePool(buffer);
126: return STATUS_INVALID_DEVICE_REQUEST;
127: }
128:
129: buffer->MediumPartPage.AdditionalPartitionDefined = tapePartition->Count - 1;
130:
131: switch (tapePartition->Method) {
132: case TAPE_FIXED_PARTITIONS:
133: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
134: DebugPrint((3,"TapeIoControl: Create Fixed Tape Partitions\n"));
135: buffer->MediumPartPage.FDPBit = SETBITON;
136: buffer->MediumPartPage.PageLength = 0x0A;
137: } else {
138: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
139: ExFreePool(buffer);
140: return STATUS_INVALID_DEVICE_REQUEST;
141: }
142: break;
143:
144: case TAPE_SELECT_PARTITIONS:
145: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
146: DebugPrint((3,"TapeIoControl: Create Select Tape Partitions\n"));
147: buffer->MediumPartPage.SDPBit = SETBITON;
148: buffer->MediumPartPage.PageLength = 0x0A;
149: } else {
150: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
151: ExFreePool(buffer);
152: return STATUS_INVALID_DEVICE_REQUEST;
153: }
154: break;
155:
156: case TAPE_INITIATOR_PARTITIONS:
157: DebugPrint((3,"TapeIoControl: Create Initiator Defined Tape Partitions\n"));
158: buffer->MediumPartPage.IDPBit = SETBITON;
159:
160: if (buffer->MediumPartPage.AdditionalPartitionDefined) {
161: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
162: buffer->MediumPartPage.PageLength = 0x0A;
163:
164: buffer->MediumPartPage.Partition1Size[0] =
165: ((tapePartition->Size >> 8) & 0xFF);
166: buffer->MediumPartPage.Partition1Size[1] =
167: (tapePartition->Size & 0xFF);
168:
169: buffer->MediumPartPage.PSUMBit = 2;
170: } else {
171: buffer->MediumPartPage.PageLength = 0x08;
172: cdb->MODE_SELECT.ParameterListLength -= 2;
173:
174: buffer->MediumPartPage.Partition0Size[0] =
175: ((tapePartition->Size >> 8) & 0xFF);
176: buffer->MediumPartPage.Partition0Size[1] =
177: (tapePartition->Size & 0xFF);
178:
179: buffer->MediumPartPage.PSUMBit = 2;
180: }
181: } else {
182: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
183: buffer->MediumPartPage.PageLength = 0x0A;
184: } else {
185: buffer->MediumPartPage.PageLength = 0x06;
186: cdb->MODE_SELECT.ParameterListLength -= 4;
187: }
188: }
189:
190: break;
191:
192: default:
193: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
194: ExFreePool(buffer);
195: return STATUS_INVALID_DEVICE_REQUEST;
196: }
197:
198: status = ScsiClassSendSrbSynchronous(DeviceObject,
199: &srb,
200: buffer,
201: cdb->MODE_SELECT.ParameterListLength,
202: TRUE);
203:
204: ExFreePool(buffer);
205:
206: return status;
207:
208: } // end TapeCreatePartition()
209:
210:
211: NTSTATUS
212: TapeErase(
213: IN PDEVICE_OBJECT DeviceObject,
214: IN PIRP Irp
215: )
216:
217: /*++
218: Routine Description:
219:
220: This routine erases the current partition of the device by writing an
221: end-of-recorded data marker beginning at the current position.
222:
223: Arguments:
224:
225: DeviceObject
226: Irp
227:
228: Return Value:
229:
230: NTSTATUS
231:
232: --*/
233:
234: {
235: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
236: PTAPE_ERASE tapeErase = Irp->AssociatedIrp.SystemBuffer;
237: SCSI_REQUEST_BLOCK srb;
238: PCDB cdb = (PCDB)srb.Cdb;
239: NTSTATUS status;
240:
241: //
242: // Zero CDB in SRB on stack.
243: //
244:
245: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
246:
247: srb.CdbLength = CDB6GENERIC_LENGTH;
248:
249: cdb->ERASE.OperationCode = SCSIOP_ERASE;
250:
251: //
252: // Set timeout value.
253: //
254:
255: srb.TimeOutValue = deviceExtension->TimeOutValue;
256:
257: if (tapeErase->Type != TAPE_ERASE_SHORT) {
258: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
259: return STATUS_INVALID_DEVICE_REQUEST;
260: }
261:
262: DebugPrint((3,"TapeIoControl: Short Erase Tape\n"));
263:
264: //
265: // Set immediate bit if indicated.
266: //
267:
268: cdb->ERASE.Immediate = tapeErase->Immediate;
269:
270: status = ScsiClassSendSrbSynchronous(DeviceObject,
271: &srb,
272: NULL,
273: 0,
274: FALSE);
275:
276: return status;
277:
278: } // end TapeErase()
279:
280:
281:
282: VOID
283: TapeError(
284: PDEVICE_OBJECT DeviceObject,
285: PSCSI_REQUEST_BLOCK Srb,
286: NTSTATUS *Status,
287: BOOLEAN *Retry
288: )
289:
290: /*++
291:
292: Routine Description:
293:
294: When a request completes with error, the routine InterpretSenseInfo is
295: called to determine from the sense data whether the request should be
296: retried and what NT status to set in the IRP. Then this routine is called
297: for tape requests to handle tape-specific errors and update the nt status
298: and retry boolean.
299:
300: Arguments:
301:
302: DeviceObject - Supplies a pointer to the device object.
303:
304: Srb - Supplies a pointer to the failing Srb.
305:
306: Status - NT Status used to set the IRP's completion status.
307:
308: Retry - Indicates that this request should be retried.
309:
310: Return Value:
311:
312: None.
313:
314: --*/
315:
316: {
317: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
318: PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
319: NTSTATUS status = *Status;
320: BOOLEAN retry = *Retry;
321: UCHAR adsenseq = senseBuffer->AdditionalSenseCodeQualifier;
322: UCHAR adsense = senseBuffer->AdditionalSenseCode;
323:
324: if (status == STATUS_DEVICE_NOT_READY) {
325: if ((adsense == SCSI_ADSENSE_LUN_NOT_READY) &&
326: (adsenseq == SCSI_SENSEQ_BECOMING_READY) ) {
327:
328: *Status = STATUS_NO_MEDIA;
329: *Retry = FALSE;
330:
331: }
332: }
333: return;
334:
335: } // end TapeError()
336:
337:
338: NTSTATUS
339: TapeGetDriveParameters(
340: IN PDEVICE_OBJECT DeviceObject,
341: IN PIRP Irp
342: )
343:
344: /*++
345: Routine Description:
346:
347: This routine returns an indication if reporting setmarks is disabled or
348: enabled, the default fixed-block size, the maximum block size, the
349: minimum block size, the maximum number of partitions, and the device
350: features flag.
351:
352: Arguments:
353:
354: DeviceObject
355: Irp
356:
357: Return Value:
358:
359: NTSTATUS
360:
361: --*/
362:
363: {
364: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
365: PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
366: PMODE_DEVICE_CONFIG_PAGE buffer;
367: PREAD_BLOCK_LIMITS_DATA blockLimits;
368: SCSI_REQUEST_BLOCK srb;
369: PCDB cdb = (PCDB)srb.Cdb;
370: NTSTATUS status;
371: PMODE_DATA_COMPRESS_PAGE dcbuff;
372:
373: DebugPrint((3,"TapeIoControl: Get Tape Drive Parameters\n"));
374:
375: //
376: // Zero CDB in SRB on stack.
377: //
378:
379: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
380:
381: srb.CdbLength = CDB6GENERIC_LENGTH;
382:
383: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
384:
385: //
386: // Set timeout value.
387: //
388:
389: srb.TimeOutValue = deviceExtension->TimeOutValue;
390:
391: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
392: cdb->MODE_SENSE.Dbd = SETBITON;
393: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
394:
395: buffer = ExAllocatePool(NonPagedPoolCacheAligned,
396: sizeof(MODE_DEVICE_CONFIG_PAGE));
397:
398: if (!buffer) {
399: return STATUS_INSUFFICIENT_RESOURCES;
400: }
401:
402: RtlZeroMemory(buffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
403:
404: status = ScsiClassSendSrbSynchronous(DeviceObject,
405: &srb,
406: buffer,
407: sizeof( MODE_DEVICE_CONFIG_PAGE ),
408: FALSE);
409:
410: if (NT_SUCCESS(status)) {
411: Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
412:
413: tapeGetDriveParams->ECC = 0;
414: tapeGetDriveParams->DataPadding = 0;
415: tapeGetDriveParams->Compression = 0;
416: tapeGetDriveParams->ReportSetmarks = (buffer->DeviceConfigPage.RSmk ? 1 : 0 );
417: tapeGetDriveParams->DefaultBlockSize = 0x200;
418: tapeGetDriveParams->MaximumPartitionCount = 2;
419:
420: tapeGetDriveParams->FeaturesLow =
421: TAPE_DRIVE_INITIATOR |
422: TAPE_DRIVE_ERASE_SHORT |
423: TAPE_DRIVE_ERASE_BOP_ONLY |
424: TAPE_DRIVE_ERASE_IMMEDIATE |
425: TAPE_DRIVE_TAPE_CAPACITY |
426: TAPE_DRIVE_FIXED_BLOCK |
427: TAPE_DRIVE_VARIABLE_BLOCK |
428: TAPE_DRIVE_WRITE_PROTECT |
429: TAPE_DRIVE_REPORT_SMKS |
430: TAPE_DRIVE_GET_ABSOLUTE_BLK |
431: TAPE_DRIVE_GET_LOGICAL_BLK;
432:
433: tapeGetDriveParams->FeaturesHigh =
434: TAPE_DRIVE_LOAD_UNLOAD |
435: TAPE_DRIVE_LOCK_UNLOCK |
436: TAPE_DRIVE_REWIND_IMMEDIATE |
437: TAPE_DRIVE_SET_BLOCK_SIZE |
438: TAPE_DRIVE_LOAD_UNLD_IMMED |
439: TAPE_DRIVE_SET_REPORT_SMKS |
440: TAPE_DRIVE_ABSOLUTE_BLK |
441: TAPE_DRIVE_ABS_BLK_IMMED |
442: TAPE_DRIVE_LOGICAL_BLK |
443: TAPE_DRIVE_END_OF_DATA |
444: TAPE_DRIVE_RELATIVE_BLKS |
445: TAPE_DRIVE_FILEMARKS |
446: TAPE_DRIVE_SEQUENTIAL_FMKS |
447: TAPE_DRIVE_SETMARKS |
448: TAPE_DRIVE_REVERSE_POSITION |
449: TAPE_DRIVE_WRITE_SETMARKS |
450: TAPE_DRIVE_WRITE_FILEMARKS |
451: TAPE_DRIVE_WRITE_MARK_IMMED;
452:
453: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
454: tapeGetDriveParams->FeaturesLow |=
455: TAPE_DRIVE_FIXED |
456: TAPE_DRIVE_SELECT;
457: tapeGetDriveParams->FeaturesHigh |=
458: TAPE_DRIVE_LOG_BLK_IMMED |
459: TAPE_DRIVE_SEQUENTIAL_SMKS;
460: } else if (RtlCompareMemory(gb_VendorId,"HP ",8) == 8) {
461: tapeGetDriveParams->FeaturesHigh |=
462: TAPE_DRIVE_LOG_BLK_IMMED |
463: TAPE_DRIVE_SEQUENTIAL_SMKS;
464: } else {
465: tapeGetDriveParams->FeaturesLow |=
466: TAPE_DRIVE_TAPE_REMAINING;
467: }
468:
469: }
470:
471: ExFreePool(buffer);
472:
473: if (!NT_SUCCESS(status)) {
474: return status;
475: }
476:
477: //
478: // Zero CDB in SRB on stack.
479: //
480:
481: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
482:
483: srb.CdbLength = CDB6GENERIC_LENGTH;
484:
485: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
486:
487: //
488: // Set timeout value.
489: //
490:
491: srb.TimeOutValue = deviceExtension->TimeOutValue;
492:
493: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE);
494: cdb->MODE_SENSE.Dbd = SETBITON;
495: cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS;
496:
497: dcbuff = ExAllocatePool(NonPagedPoolCacheAligned,
498: sizeof(MODE_DATA_COMPRESS_PAGE));
499:
500: if (!dcbuff) {
501: return STATUS_INSUFFICIENT_RESOURCES;
502: }
503:
504: RtlZeroMemory(dcbuff, sizeof(MODE_DATA_COMPRESS_PAGE));
505:
506: status = ScsiClassSendSrbSynchronous(DeviceObject,
507: &srb,
508: dcbuff,
509: sizeof( MODE_DATA_COMPRESS_PAGE ),
510: FALSE);
511:
512: if (NT_SUCCESS(status)) {
513: if (dcbuff->DataCompressPage.DCC == 1) {
514: tapeGetDriveParams->FeaturesLow |= TAPE_DRIVE_COMPRESSION;
515: tapeGetDriveParams->FeaturesHigh |= TAPE_DRIVE_SET_COMPRESSION;
516: tapeGetDriveParams->Compression = (dcbuff->DataCompressPage.DCE == 1 ? TRUE : FALSE);
517: }
518: }
519:
520: ExFreePool(dcbuff);
521:
522: if (!NT_SUCCESS(status) && (status != STATUS_INVALID_DEVICE_REQUEST)) {
523: return status;
524: }
525:
526: //
527: // Zero CDB in SRB on stack.
528: //
529:
530: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
531:
532: srb.CdbLength = CDB6GENERIC_LENGTH;
533:
534: cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
535:
536: //
537: // Set timeout value.
538: //
539:
540: srb.TimeOutValue = deviceExtension->TimeOutValue;
541:
542: blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
543: sizeof(READ_BLOCK_LIMITS_DATA));
544:
545: if (!blockLimits) {
546: return STATUS_INSUFFICIENT_RESOURCES;
547: }
548:
549: RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));
550:
551: status = ScsiClassSendSrbSynchronous(DeviceObject,
552: &srb,
553: blockLimits,
554: sizeof(READ_BLOCK_LIMITS_DATA),
555: FALSE);
556:
557: if (NT_SUCCESS(status)) {
558: tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
559: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
560: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);
561:
562: tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
563: tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
564: }
565:
566: ExFreePool(blockLimits);
567:
568: tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
569:
570: return status;
571:
572: } // end TapeGetDriveParameters()
573:
574:
575: NTSTATUS
576: TapeGetMediaParameters(
577: IN PDEVICE_OBJECT DeviceObject,
578: IN PIRP Irp
579: )
580:
581: /*++
582: Routine Description:
583:
584: This routine returns the maximum tape capacity, the remaining tape
585: capacity, the fixed-length logical block size, the number of partitions
586: on the tape, and an indication if the tape is write protected. A block
587: size of 0 indicates variable-length block mode.
588:
589: Arguments:
590:
591: DeviceObject
592: Irp
593:
594: Return Value:
595:
596: NTSTATUS
597:
598: --*/
599:
600: {
601: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
602: PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
603: PMODE_TAPE_MEDIA_INFORMATION modeBuffer;
604: PLOG_SENSE_PARAMETER_FORMAT logBuffer;
605: SCSI_REQUEST_BLOCK srb;
606: PCDB cdb = (PCDB)srb.Cdb;
607: NTSTATUS status;
608: LARGE_INTEGER capacityBuffer[2];
609: LARGE_INTEGER remainingBuffer[2];
610: ULONG sectorShift;
611:
612: DebugPrint((3,"TapeIoControl: Get Tape Media Parameters\n"));
613:
614: //
615: // Zero CDB in SRB on stack.
616: //
617:
618: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
619:
620: srb.CdbLength = CDB6GENERIC_LENGTH;
621:
622: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
623:
624: //
625: // Set timeout value.
626: //
627:
628: srb.TimeOutValue = deviceExtension->TimeOutValue;
629:
630: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION);
631: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
632:
633: modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
634: sizeof(MODE_TAPE_MEDIA_INFORMATION));
635:
636: if (!modeBuffer) {
637: return STATUS_INSUFFICIENT_RESOURCES;
638: }
639:
640: RtlZeroMemory(modeBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
641:
642: status = ScsiClassSendSrbSynchronous(DeviceObject,
643: &srb,
644: modeBuffer,
645: sizeof( MODE_TAPE_MEDIA_INFORMATION ),
646: FALSE);
647:
648: if (status == STATUS_DATA_OVERRUN) {
649: status = STATUS_SUCCESS;
650: }
651:
652: if (NT_SUCCESS(status)) {
653: Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
654:
655: tapeGetMediaParams->BlockSize = modeBuffer->ParameterListBlock.BlockLength[2];
656: tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[1] << 8);
657: tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[0] << 16);
658:
659: tapeGetMediaParams->PartitionCount =
660: modeBuffer->MediumPartPage.AdditionalPartitionDefined + 1;
661:
662: tapeGetMediaParams->WriteProtected =
663: ((modeBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) &
664: 0x01);
665:
666: gb_PartitionCount =
667: modeBuffer->MediumPartPage.AdditionalPartitionDefined + 1;
668:
669: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
670: capacityBuffer[0].LowPart = modeBuffer->MediumPartPage.Partition0Size[1];
671: capacityBuffer[0].LowPart += (modeBuffer->MediumPartPage.Partition0Size[0] << 8);
672:
673: capacityBuffer[0].HighPart = 0;
674:
675: if (tapeGetMediaParams->PartitionCount == 2) {
676: capacityBuffer[1].LowPart = modeBuffer->MediumPartPage.Partition1Size[1];
677: capacityBuffer[1].LowPart += (modeBuffer->MediumPartPage.Partition1Size[0] << 8);
678:
679: capacityBuffer[1].HighPart = 0;
680: } else {
681: capacityBuffer[1].LowPart = 0;
682: capacityBuffer[1].HighPart = 0;
683: }
684:
685: capacityBuffer[0] =
686: RtlLargeIntegerAdd( capacityBuffer[0], capacityBuffer[1]);
687: capacityBuffer[0] =
688: RtlExtendedIntegerMultiply(capacityBuffer[0], 1024000);
689:
690: tapeGetMediaParams->Capacity = capacityBuffer[0];
691:
692: tapeGetMediaParams->Remaining.LowPart = 0;
693: tapeGetMediaParams->Remaining.HighPart = 0;
694:
695: WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift);
696: deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize;
697: deviceExtension->SectorShift = sectorShift;
698:
699:
700: }
701: }
702:
703: ExFreePool(modeBuffer);
704:
705: if (!NT_SUCCESS(status)) {
706:
707: return status;
708: }
709:
710: if (!(RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8)) {
711: //
712: // Zero CDB in SRB on stack.
713: //
714:
715: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
716:
717: srb.CdbLength = CDB10GENERIC_LENGTH;
718:
719: cdb->LOGSENSE.OperationCode = SCSIOP_LOG_SENSE;
720:
721: //
722: // Set timeout value.
723: //
724:
725: srb.TimeOutValue = deviceExtension->TimeOutValue;
726:
727: cdb->LOGSENSE.AllocationLength[0] = 0;
728: cdb->LOGSENSE.AllocationLength[1] = 0x24;
729:
730: cdb->LOGSENSE.PageCode = LOGSENSEPAGE31;
731: cdb->LOGSENSE.PCBit = 0x01;
732:
733: logBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
734: sizeof(LOG_SENSE_PARAMETER_FORMAT));
735:
736: if (!logBuffer) {
737: return STATUS_INSUFFICIENT_RESOURCES;
738: }
739:
740: RtlZeroMemory(logBuffer, sizeof(LOG_SENSE_PARAMETER_FORMAT));
741:
742: status = ScsiClassSendSrbSynchronous(DeviceObject,
743: &srb,
744: logBuffer,
745: 0x24,
746: FALSE);
747:
748: if (status == STATUS_DATA_OVERRUN) {
749: status = STATUS_SUCCESS;
750: }
751:
752: if (NT_SUCCESS(status)) {
753: capacityBuffer[0].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[3];
754: capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[2] << 8);
755: capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[1] << 16);
756: capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[0] << 24);
757:
758: capacityBuffer[0].HighPart = 0;
759:
760: remainingBuffer[0].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[3];
761: remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[2] << 8);
762: remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[1] << 16);
763: remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[0] << 24);
764:
765: remainingBuffer[0].HighPart = 0;
766:
767: if (tapeGetMediaParams->PartitionCount == 2) {
768: capacityBuffer[1].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[3];
769: capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[2] << 8);
770: capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[1] << 16);
771: capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[0] << 24);
772:
773: capacityBuffer[1].HighPart = 0;
774:
775: remainingBuffer[1].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[3];
776: remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[2] << 8);
777: remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[1] << 16);
778: remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[0] << 24);
779:
780: remainingBuffer[1].HighPart = 0;
781:
782: } else {
783: capacityBuffer[1].LowPart = 0;
784: capacityBuffer[1].HighPart = 0;
785: remainingBuffer[1].LowPart = 0;
786: remainingBuffer[1].HighPart = 0;
787: }
788:
789: capacityBuffer[0] =
790: RtlLargeIntegerAdd( capacityBuffer[0], capacityBuffer[1]);
791: capacityBuffer[0] =
792: RtlExtendedIntegerMultiply(capacityBuffer[0], 1024);
793:
794: tapeGetMediaParams->Capacity = capacityBuffer[0];
795:
796: remainingBuffer[0] =
797: RtlLargeIntegerAdd( remainingBuffer[0], remainingBuffer[1]);
798: remainingBuffer[0] =
799: RtlExtendedIntegerMultiply(remainingBuffer[0], 1024);
800:
801: tapeGetMediaParams->Remaining = remainingBuffer[0];
802: }
803:
804: ExFreePool(logBuffer);
805: }
806:
807: return status;
808:
809: } // end TapeGetMediaParameters()
810:
811:
812: NTSTATUS
813: TapeGetPosition(
814: IN PDEVICE_OBJECT DeviceObject,
815: IN PIRP Irp
816: )
817:
818: /*++
819: Routine Description:
820:
821: This routine returns the current position of the tape.
822:
823: Arguments:
824:
825: DeviceObject
826: Irp
827:
828: Return Value:
829:
830: NTSTATUS
831:
832: --*/
833:
834: {
835: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
836: PTAPE_GET_POSITION tapeGetPosition = Irp->AssociatedIrp.SystemBuffer;
837: PTAPE_POSITION_DATA logicalBuffer;
838: PUCHAR absoluteBuffer;
839: SCSI_REQUEST_BLOCK srb;
840: PCDB cdb = (PCDB)srb.Cdb;
841: NTSTATUS status;
842:
843: //
844: // Zero CDB in SRB on stack.
845: //
846:
847: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
848:
849: //
850: // Set timeout value.
851: //
852:
853: srb.TimeOutValue = deviceExtension->TimeOutValue;
854:
855: switch (tapeGetPosition->Type) {
856: case TAPE_ABSOLUTE_POSITION:
857: DebugPrint((3,"TapeIoControl: Get Absolute Position\n"));
858: srb.CdbLength = CDB6GENERIC_LENGTH;
859: cdb->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_BLOCK_ADDR;
860: absoluteBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 3);
861:
862: if (!absoluteBuffer) {
863: return STATUS_INSUFFICIENT_RESOURCES;
864: }
865:
866: status = ScsiClassSendSrbSynchronous(DeviceObject,
867: &srb,
868: absoluteBuffer,
869: 3,
870: FALSE);
871:
872: if (NT_SUCCESS(status)) {
873: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
874:
875: tapeGetPosition->Partition = 0;
876: tapeGetPosition->Offset.HighPart = 0;
877: tapeGetPosition->Offset.LowPart = absoluteBuffer[2];
878: tapeGetPosition->Offset.LowPart += (absoluteBuffer[1] << 8);
879: tapeGetPosition->Offset.LowPart += (absoluteBuffer[0] << 16);
880: }
881:
882: ExFreePool(absoluteBuffer);
883: break;
884:
885: case TAPE_LOGICAL_POSITION:
886: DebugPrint((3,"TapeIoControl: Get Logical Position\n"));
887: srb.CdbLength = CDB10GENERIC_LENGTH;
888: cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION;
889: logicalBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
890: sizeof(TAPE_POSITION_DATA));
891:
892: if (!logicalBuffer) {
893: return STATUS_INSUFFICIENT_RESOURCES;
894: }
895:
896: status = ScsiClassSendSrbSynchronous(DeviceObject,
897: &srb,
898: logicalBuffer,
899: sizeof( TAPE_POSITION_DATA ),
900: FALSE);
901:
902: if (NT_SUCCESS(status)) {
903: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
904:
905: if (logicalBuffer->BlockPositionUnsupported) {
906: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
907: return STATUS_INVALID_DEVICE_REQUEST;
908: }
909:
910: tapeGetPosition->Partition = logicalBuffer->PartitionNumber + 1;
911: tapeGetPosition->Offset.HighPart = 0;
912: REVERSE_BYTES((PFOUR_BYTE)&tapeGetPosition->Offset.LowPart,
913: (PFOUR_BYTE)logicalBuffer->FirstBlock);
914: }
915:
916: ExFreePool(logicalBuffer);
917: break;
918:
919: default:
920: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
921: return STATUS_INVALID_DEVICE_REQUEST;
922: }
923:
924: return status;
925:
926: } // end TapeGetPosition()
927:
928:
929: NTSTATUS
930: TapeGetStatus(
931: IN PDEVICE_OBJECT DeviceObject,
932: IN PIRP Irp
933: )
934:
935: /*++
936: Routine Description:
937:
938: This routine returns the status of the device.
939:
940: Arguments:
941:
942: DeviceObject
943: Irp
944:
945: Return Value:
946:
947: NTSTATUS
948:
949: --*/
950:
951: {
952: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
953: SCSI_REQUEST_BLOCK srb;
954: PCDB cdb = (PCDB)srb.Cdb;
955: NTSTATUS status;
956:
957: DebugPrint((3,"TapeIoControl: Get Tape Status\n"));
958:
959: //
960: // Zero CDB in SRB on stack.
961: //
962:
963: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
964:
965: srb.CdbLength = CDB6GENERIC_LENGTH;
966:
967: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
968:
969: //
970: // Set timeout value.
971: //
972:
973: srb.TimeOutValue = deviceExtension->TimeOutValue;
974:
975: status = ScsiClassSendSrbSynchronous(DeviceObject,
976: &srb,
977: NULL,
978: 0,
979: FALSE);
980:
981: return status;
982:
983: } // end TapeGetStatus()
984:
985:
986: NTSTATUS
987: TapePrepare(
988: IN PDEVICE_OBJECT DeviceObject,
989: IN PIRP Irp
990: )
991:
992: /*++
993: Routine Description:
994:
995: This routine loads, unloads, locks, or unlocks the tape.
996:
997: Arguments:
998:
999: DeviceObject
1000: Irp
1001:
1002: Return Value:
1003:
1004: NTSTATUS
1005:
1006: --*/
1007:
1008: {
1009: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1010: PTAPE_PREPARE tapePrepare = Irp->AssociatedIrp.SystemBuffer;
1011: SCSI_REQUEST_BLOCK srb;
1012: PCDB cdb = (PCDB)srb.Cdb;
1013: NTSTATUS status;
1014:
1015: //
1016: // Zero CDB in SRB on stack.
1017: //
1018:
1019: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1020:
1021: //
1022: // Set timeout value.
1023: //
1024:
1025: srb.TimeOutValue = deviceExtension->TimeOutValue;
1026:
1027: switch (tapePrepare->Operation) {
1028: case TAPE_LOAD:
1029: DebugPrint((3,"TapeIoControl: Load Tape\n"));
1030: srb.CdbLength = CDB6GENERIC_LENGTH;
1031: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
1032: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
1033: break;
1034:
1035: case TAPE_UNLOAD:
1036: DebugPrint((3,"TapeIoControl: Unload Tape\n"));
1037: srb.CdbLength = CDB6GENERIC_LENGTH;
1038: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
1039: break;
1040:
1041: case TAPE_LOCK:
1042: DebugPrint((3,"TapeIoControl: Prevent Tape Removal\n"));
1043: srb.CdbLength = CDB6GENERIC_LENGTH;
1044: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1045: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
1046: break;
1047:
1048: case TAPE_UNLOCK:
1049: DebugPrint((3,"TapeIoControl: Allow Tape Removal\n"));
1050: srb.CdbLength = CDB6GENERIC_LENGTH;
1051: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1052: break;
1053:
1054: default:
1055: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
1056: return STATUS_INVALID_DEVICE_REQUEST;
1057: }
1058:
1059: //
1060: // Set immediate bit if indicated.
1061: //
1062:
1063: cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
1064:
1065: status = ScsiClassSendSrbSynchronous(DeviceObject,
1066: &srb,
1067: NULL,
1068: 0,
1069: FALSE);
1070:
1071: return status;
1072:
1073: } // end TapePrepare()
1074:
1075: NTSTATUS
1076: TapeReadWrite(
1077: IN PDEVICE_OBJECT DeviceObject,
1078: IN PIRP Irp
1079: )
1080:
1081: /*++
1082:
1083: Routine Description:
1084:
1085: This routine builds SRBs and CDBs for read and write requests to 4MM DAT
1086: devices.
1087:
1088: Arguments:
1089:
1090: DeviceObject
1091: Irp
1092:
1093: Return Value:
1094:
1095: Returns STATUS_PENDING.
1096:
1097: --*/
1098:
1099: {
1100: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1101: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
1102: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
1103: PSCSI_REQUEST_BLOCK srb;
1104: PCDB cdb;
1105: KIRQL currentIrql;
1106: ULONG transferBlocks;
1107: LARGE_INTEGER startingOffset =
1108: currentIrpStack->Parameters.Read.ByteOffset;
1109:
1110: //
1111: // Allocate an Srb.
1112: //
1113:
1114: if (deviceExtension->SrbZone != NULL &&
1115: (srb = ExInterlockedAllocateFromZone(
1116: deviceExtension->SrbZone,
1117: deviceExtension->SrbZoneSpinLock)) != NULL) {
1118:
1119: srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
1120:
1121: } else {
1122:
1123: //
1124: // Allocate Srb from non-paged pool.
1125: // This call must succeed.
1126: //
1127:
1128: srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
1129:
1130: srb->SrbFlags = 0;
1131:
1132: }
1133:
1134: //
1135: // Write length to SRB.
1136: //
1137:
1138: srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1139:
1140: //
1141: // Set up IRP Address.
1142: //
1143:
1144: srb->OriginalRequest = Irp;
1145:
1146: //
1147: // Set up target id and logical unit number.
1148: //
1149:
1150: srb->PathId = deviceExtension->PathId;
1151: srb->TargetId = deviceExtension->TargetId;
1152: srb->Lun = deviceExtension->Lun;
1153:
1154:
1155: srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1156:
1157: srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1158:
1159: //
1160: // Save byte count of transfer in SRB Extension.
1161: //
1162:
1163: srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
1164:
1165: //
1166: // Indicate auto request sense by specifying buffer and size.
1167: //
1168:
1169: srb->SenseInfoBuffer = deviceExtension->SenseData;
1170:
1171: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1172:
1173: //
1174: // Initialize the queue actions field.
1175: //
1176:
1177: srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
1178:
1179: //
1180: // Indicate auto request sense by specifying buffer and size.
1181: //
1182:
1183: srb->SenseInfoBuffer = deviceExtension->SenseData;
1184:
1185: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1186:
1187: //
1188: // Set timeout value in seconds.
1189: //
1190:
1191: srb->TimeOutValue = deviceExtension->TimeOutValue;
1192:
1193: //
1194: // Zero statuses.
1195: //
1196:
1197: srb->SrbStatus = srb->ScsiStatus = 0;
1198:
1199: srb->NextSrb = 0;
1200:
1201: //
1202: // Indicate that 6-byte CDB's will be used.
1203: //
1204:
1205: srb->CdbLength = CDB6GENERIC_LENGTH;
1206:
1207: //
1208: // Fill in CDB fields.
1209: //
1210:
1211: cdb = (PCDB)srb->Cdb;
1212:
1213: //
1214: // Zero CDB in SRB.
1215: //
1216:
1217: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1218:
1219: //
1220: // Since we are writing fixed block mode, normalize transfer count
1221: // to number of blocks.
1222: //
1223:
1224: transferBlocks =
1225: currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift;
1226:
1227: //
1228: // Set up transfer length
1229: //
1230:
1231: cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
1232: cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff);
1233: cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
1234:
1235: //
1236: // Tell the python we are in fixed block mode
1237: //
1238:
1239: cdb->CDB6READWRITETAPE.VendorSpecific = 1;
1240:
1241: //
1242: // Set transfer direction flag and Cdb command.
1243: //
1244:
1245: if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
1246:
1247: DebugPrint((3, "TapeRequest: Read Command\n"));
1248:
1249: srb->SrbFlags = SRB_FLAGS_DATA_IN;
1250: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
1251:
1252: } else {
1253:
1254: DebugPrint((3, "TapeRequest: Write Command\n"));
1255:
1256: srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1257: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
1258: }
1259:
1260: //
1261: // Or in the default flags from the device object.
1262: //
1263:
1264: srb->SrbFlags |= deviceExtension->SrbFlags;
1265:
1266: //
1267: // Set up major SCSI function.
1268: //
1269:
1270: nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1271:
1272: //
1273: // Save SRB address in next stack for port driver.
1274: //
1275:
1276: nextIrpStack->Parameters.Scsi.Srb = srb;
1277:
1278: //
1279: // Save retry count in current IRP stack.
1280: //
1281:
1282: currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
1283:
1284: //
1285: // Set up IoCompletion routine address.
1286: //
1287:
1288: IoSetCompletionRoutine(Irp,
1289: ScsiClassIoComplete,
1290: srb,
1291: TRUE,
1292: TRUE,
1293: FALSE);
1294:
1295: return STATUS_PENDING;
1296:
1297: } // end TapeReadWrite()
1298:
1299: NTSTATUS
1300: TapeSetDriveParameters(
1301: IN PDEVICE_OBJECT DeviceObject,
1302: IN PIRP Irp
1303: )
1304:
1305: /*++
1306: Routine Description:
1307:
1308: This routine enables/disables reporting of setmarks.
1309:
1310: Arguments:
1311:
1312: DeviceObject
1313: Irp
1314:
1315: Return Value:
1316:
1317: NTSTATUS
1318:
1319: --*/
1320:
1321: {
1322: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1323: PTAPE_SET_DRIVE_PARAMETERS tapeSetDriveParams = Irp->AssociatedIrp.SystemBuffer;
1324: PMODE_DEVICE_CONFIG_PAGE buffer;
1325: SCSI_REQUEST_BLOCK srb;
1326: PCDB cdb = (PCDB)srb.Cdb;
1327: NTSTATUS status;
1328: PMODE_DATA_COMPRESS_PAGE dcbuff;
1329:
1330: DebugPrint((3,"TapeIoControl: Set Tape Drive Parameters\n"));
1331:
1332: //
1333: // Zero CDB in SRB on stack.
1334: //
1335:
1336: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1337:
1338: srb.CdbLength = CDB6GENERIC_LENGTH;
1339:
1340: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1341:
1342: //
1343: // Set timeout value.
1344: //
1345:
1346: srb.TimeOutValue = deviceExtension->TimeOutValue;
1347:
1348: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
1349: cdb->MODE_SENSE.Dbd = SETBITON;
1350: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
1351:
1352: buffer = ExAllocatePool(NonPagedPoolCacheAligned,
1353: sizeof(MODE_DEVICE_CONFIG_PAGE));
1354:
1355: if (!buffer) {
1356: return STATUS_INSUFFICIENT_RESOURCES;
1357: }
1358:
1359: RtlZeroMemory(buffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
1360:
1361: status = ScsiClassSendSrbSynchronous(DeviceObject,
1362: &srb,
1363: buffer,
1364: sizeof( MODE_DEVICE_CONFIG_PAGE ),
1365: FALSE);
1366:
1367: if (!NT_SUCCESS(status)) {
1368: ExFreePool(buffer);
1369: return status;
1370: }
1371:
1372: //
1373: // Zero CDB in SRB on stack.
1374: //
1375:
1376: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1377:
1378: srb.CdbLength = CDB6GENERIC_LENGTH;
1379:
1380: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1381:
1382: //
1383: // Set timeout value.
1384: //
1385:
1386: srb.TimeOutValue = deviceExtension->TimeOutValue;
1387:
1388: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
1389: cdb->MODE_SELECT.PFBit = 1;
1390:
1391: buffer->ParameterListHeader.ModeDataLength = 0;
1392: buffer->ParameterListHeader.MediumType = 0;
1393: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
1394: buffer->ParameterListHeader.BlockDescriptorLength = 0;
1395:
1396: buffer->DeviceConfigPage.PageCode = MODE_PAGE_DEVICE_CONFIG;
1397: buffer->DeviceConfigPage.PageLength = 0x0E;
1398:
1399: if (tapeSetDriveParams->ReportSetmarks) {
1400: buffer->DeviceConfigPage.RSmk = SETBITON;
1401: } else {
1402: buffer->DeviceConfigPage.RSmk = SETBITOFF;
1403: }
1404:
1405: status = ScsiClassSendSrbSynchronous(DeviceObject,
1406: &srb,
1407: buffer,
1408: sizeof( MODE_DEVICE_CONFIG_PAGE ),
1409: TRUE);
1410:
1411: ExFreePool(buffer);
1412:
1413: if (!NT_SUCCESS(status)) {
1414: return status;
1415: }
1416:
1417: //
1418: // Zero CDB in SRB on stack.
1419: //
1420:
1421: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1422:
1423: srb.CdbLength = CDB6GENERIC_LENGTH;
1424:
1425: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1426:
1427: //
1428: // Set timeout value.
1429: //
1430:
1431: srb.TimeOutValue = deviceExtension->TimeOutValue;
1432:
1433: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE);
1434: cdb->MODE_SENSE.Dbd = SETBITON;
1435: cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS;
1436:
1437: dcbuff = ExAllocatePool(NonPagedPoolCacheAligned,
1438: sizeof(MODE_DATA_COMPRESS_PAGE));
1439:
1440: if (!dcbuff) {
1441: return STATUS_INSUFFICIENT_RESOURCES;
1442: }
1443:
1444: RtlZeroMemory(dcbuff, sizeof(MODE_DATA_COMPRESS_PAGE));
1445:
1446: status = ScsiClassSendSrbSynchronous(DeviceObject,
1447: &srb,
1448: dcbuff,
1449: sizeof( MODE_DATA_COMPRESS_PAGE ),
1450: FALSE);
1451:
1452: if (!NT_SUCCESS(status) && (status != STATUS_INVALID_DEVICE_REQUEST)) {
1453: ExFreePool(dcbuff);
1454: return status;
1455: }
1456:
1457: if (NT_SUCCESS(status) && dcbuff->DataCompressPage.DCC == 1) {
1458: //
1459: // Zero CDB in SRB on stack.
1460: //
1461:
1462: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1463:
1464: srb.CdbLength = CDB6GENERIC_LENGTH;
1465:
1466: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1467:
1468: //
1469: // Set timeout value.
1470: //
1471:
1472: srb.TimeOutValue = deviceExtension->TimeOutValue;
1473:
1474: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DATA_COMPRESS_PAGE);
1475: cdb->MODE_SELECT.PFBit = 1;
1476:
1477: dcbuff->ParameterListHeader.ModeDataLength = 0;
1478: dcbuff->ParameterListHeader.MediumType = 0;
1479: dcbuff->ParameterListHeader.DeviceSpecificParameter = 0x10;
1480: dcbuff->ParameterListHeader.BlockDescriptorLength = 0;
1481:
1482: dcbuff->DataCompressPage.PageCode = MODE_PAGE_DATA_COMPRESS;
1483: dcbuff->DataCompressPage.PageLength = 0x0E;
1484:
1485: if (tapeSetDriveParams->Compression) {
1486: dcbuff->DataCompressPage.DCE = SETBITON;
1487: } else {
1488: dcbuff->DataCompressPage.DCE = SETBITOFF;
1489: }
1490:
1491: status = ScsiClassSendSrbSynchronous(DeviceObject,
1492: &srb,
1493: dcbuff,
1494: sizeof( MODE_DATA_COMPRESS_PAGE ),
1495: TRUE);
1496: } else if (status == STATUS_INVALID_DEVICE_REQUEST) {
1497: status = STATUS_SUCCESS;
1498: }
1499:
1500: ExFreePool(dcbuff);
1501:
1502: return status;
1503:
1504: } // end TapeSetDriveParameters()
1505:
1506:
1507: NTSTATUS
1508: TapeSetMediaParameters(
1509: IN PDEVICE_OBJECT DeviceObject,
1510: IN PIRP Irp
1511: )
1512:
1513: /*++
1514: Routine Description:
1515:
1516: This routine sets the fixed-length logical block size or variable-length
1517: block mode (if the block size is 0).
1518:
1519: Arguments:
1520:
1521: DeviceObject
1522: Irp
1523:
1524: Return Value:
1525:
1526: NTSTATUS
1527:
1528: --*/
1529:
1530: {
1531: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1532: PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
1533: PMODE_PARM_READ_WRITE_DATA buffer;
1534: SCSI_REQUEST_BLOCK srb;
1535: PCDB cdb = (PCDB)srb.Cdb;
1536: NTSTATUS status;
1537:
1538: DebugPrint((3,"TapeIoControl: Set Tape Media Parameters \n"));
1539:
1540: //
1541: // Zero CDB in SRB on stack.
1542: //
1543:
1544: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1545:
1546: srb.CdbLength = CDB6GENERIC_LENGTH;
1547:
1548: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1549:
1550: //
1551: // Set timeout value.
1552: //
1553:
1554: srb.TimeOutValue = deviceExtension->TimeOutValue;
1555:
1556: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
1557: cdb->MODE_SELECT.PFBit = 1;
1558:
1559: buffer = ExAllocatePool(NonPagedPoolCacheAligned,
1560: sizeof(MODE_PARM_READ_WRITE_DATA));
1561:
1562: if (!buffer) {
1563: return STATUS_INSUFFICIENT_RESOURCES;
1564: }
1565:
1566: RtlZeroMemory(buffer, sizeof(MODE_PARM_READ_WRITE_DATA));
1567:
1568: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
1569: buffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH;
1570:
1571: buffer->ParameterListBlock.BlockLength[0] =
1572: ((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
1573: buffer->ParameterListBlock.BlockLength[1] =
1574: ((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
1575: buffer->ParameterListBlock.BlockLength[2] =
1576: (tapeSetMediaParams->BlockSize & 0xFF);
1577:
1578: status = ScsiClassSendSrbSynchronous(DeviceObject,
1579: &srb,
1580: buffer,
1581: sizeof( MODE_PARM_READ_WRITE_DATA ),
1582: TRUE);
1583:
1584: ExFreePool(buffer);
1585:
1586: return status;
1587:
1588: } // end TapeSetMediaParameters()
1589:
1590:
1591: NTSTATUS
1592: TapeSetPosition(
1593: IN PDEVICE_OBJECT DeviceObject,
1594: IN PIRP Irp
1595: )
1596:
1597: /*++
1598: Routine Description:
1599:
1600: This routine sets the position of the tape.
1601:
1602: Arguments:
1603:
1604: DeviceObject
1605: Irp
1606:
1607: Return Value:
1608:
1609: NTSTATUS
1610:
1611: --*/
1612:
1613: {
1614: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1615: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
1616: PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
1617: SCSI_REQUEST_BLOCK srb;
1618: PCDB cdb = (PCDB)srb.Cdb;
1619: NTSTATUS status;
1620:
1621: if (tapeSetPosition->Immediate) {
1622: switch (tapeSetPosition->Method) {
1623: case TAPE_REWIND:
1624: case TAPE_ABSOLUTE_BLOCK:
1625: case TAPE_LOGICAL_BLOCK:
1626: break;
1627:
1628: case TAPE_SPACE_END_OF_DATA:
1629: case TAPE_SPACE_RELATIVE_BLOCKS:
1630: case TAPE_SPACE_FILEMARKS:
1631: case TAPE_SPACE_SEQUENTIAL_FMKS:
1632: case TAPE_SPACE_SETMARKS:
1633: case TAPE_SPACE_SEQUENTIAL_SMKS:
1634: default:
1635: return STATUS_NOT_IMPLEMENTED;
1636: }
1637: }
1638:
1639: //
1640: // Zero CDB in SRB on stack.
1641: //
1642:
1643: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1644:
1645: //
1646: // Set timeout value.
1647: //
1648:
1649: srb.TimeOutValue = deviceExtension->TimeOutValue;
1650:
1651: srb.CdbLength = CDB6GENERIC_LENGTH;
1652:
1653: //
1654: // Set immediate bit if indicated.
1655: //
1656:
1657: cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
1658:
1659: switch (tapeSetPosition->Method) {
1660: case TAPE_REWIND:
1661: DebugPrint((3,"TapeIoControl: Rewind Tape\n"));
1662: cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
1663:
1664: break;
1665:
1666: case TAPE_ABSOLUTE_BLOCK:
1667: DebugPrint((3,"TapeIoControl: Position Tape to an Absolute Block\n"));
1668:
1669: srb.TimeOutValue = 360;
1670:
1671: cdb->CDB6GENERIC.OperationCode = SCSIOP_SEEK_BLOCK;
1672:
1673: cdb->CDB6GENERIC.CommandUniqueBytes[0] =
1674: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
1675: cdb->CDB6GENERIC.CommandUniqueBytes[1] =
1676: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
1677: cdb->CDB6GENERIC.CommandUniqueBytes[2] =
1678: (tapeSetPosition->Offset.LowPart & 0xFF);
1679: break;
1680:
1681: case TAPE_LOGICAL_BLOCK:
1682: DebugPrint((3,"TapeIoControl: Position Tape to a Logical Block\n"));
1683:
1684: srb.TimeOutValue = 360;
1685:
1686: cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
1687:
1688: srb.CdbLength = CDB10GENERIC_LENGTH;
1689:
1690: if ((tapeSetPosition->Partition != (ULONG)0) &&
1691: (tapeSetPosition->Partition != (ULONG)tapeData->CurrentPartition) &&
1692: gb_PartitionCount > 1) {
1693: cdb->LOCATE.CPBit = SETBITON;
1694: cdb->LOCATE.Partition =
1695: tapeSetPosition->Partition - 1;
1696: }
1697: cdb->LOCATE.LogicalBlockAddress[0] =
1698: ((tapeSetPosition->Offset.LowPart >> 24) & 0xFF);
1699: cdb->LOCATE.LogicalBlockAddress[1] =
1700: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
1701: cdb->LOCATE.LogicalBlockAddress[2] =
1702: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
1703: cdb->LOCATE.LogicalBlockAddress[3] =
1704: (tapeSetPosition->Offset.LowPart & 0xFF);
1705:
1706: break;
1707:
1708: case TAPE_SPACE_END_OF_DATA:
1709: DebugPrint((3,"TapeIoControl: Position Tape to End-of-Data\n"));
1710: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1711: cdb->SPACE_TAPE_MARKS.Code = 3;
1712: break;
1713:
1714: case TAPE_SPACE_RELATIVE_BLOCKS:
1715: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Blocks\n"));
1716: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1717: cdb->SPACE_TAPE_MARKS.Code = 0;
1718: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
1719: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
1720: cdb->SPACE_TAPE_MARKS.NumMarks =
1721: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
1722: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
1723: (tapeSetPosition->Offset.LowPart & 0xFF);
1724: break;
1725:
1726: case TAPE_SPACE_FILEMARKS:
1727: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Filemarks\n"));
1728: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1729: cdb->SPACE_TAPE_MARKS.Code = 1;
1730: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
1731: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
1732: cdb->SPACE_TAPE_MARKS.NumMarks =
1733: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
1734: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
1735: (tapeSetPosition->Offset.LowPart & 0xFF);
1736: break;
1737:
1738: case TAPE_SPACE_SEQUENTIAL_FMKS:
1739: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Sequential Filemarks\n"));
1740: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1741: cdb->SPACE_TAPE_MARKS.Code = 2;
1742: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
1743: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
1744: cdb->SPACE_TAPE_MARKS.NumMarks =
1745: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
1746: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
1747: (tapeSetPosition->Offset.LowPart & 0xFF);
1748: break;
1749:
1750: case TAPE_SPACE_SETMARKS:
1751: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Setmarks\n"));
1752: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
1753: cdb->SPACE_TAPE_MARKS.Code = 4;
1754: cdb->SPACE_TAPE_MARKS.NumMarksMSB =
1755: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
1756: cdb->SPACE_TAPE_MARKS.NumMarks =
1757: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
1758: cdb->SPACE_TAPE_MARKS.NumMarksLSB =
1759: (tapeSetPosition->Offset.LowPart & 0xFF);
1760: break;
1761:
1762: case TAPE_SPACE_SEQUENTIAL_SMKS:
1763: default:
1764: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
1765: return STATUS_INVALID_DEVICE_REQUEST;
1766: }
1767:
1768: status = ScsiClassSendSrbSynchronous(DeviceObject,
1769: &srb,
1770: NULL,
1771: 0,
1772: FALSE);
1773:
1774: if (NT_SUCCESS(status)) {
1775: switch (tapeSetPosition->Method) {
1776: case TAPE_LOGICAL_BLOCK:
1777: tapeData->CurrentPartition = tapeSetPosition->Partition;
1778: break;
1779: }
1780: }
1781:
1782: return status;
1783:
1784: } // end TapeSetPosition()
1785:
1786:
1787: BOOLEAN
1788: TapeVerifyInquiry(
1789: IN PSCSI_INQUIRY_DATA LunInfo
1790: )
1791:
1792: /*++
1793: Routine Description:
1794:
1795: This routine determines if the driver should claim this device.
1796:
1797: Arguments:
1798:
1799: LunInfo
1800:
1801: Return Value:
1802:
1803: TRUE - driver should claim this device.
1804: FALSE - driver should not claim this device.
1805:
1806: --*/
1807:
1808: {
1809: PINQUIRYDATA inquiryData;
1810:
1811: DebugPrint((3,"TapeIoControl: Verify Tape Inquiry Data\n"));
1812:
1813: inquiryData = (PVOID)LunInfo->InquiryData;
1814:
1815: //
1816: // Determine, from the Product ID field in the
1817: // inquiry data, whether or not to "claim" this drive.
1818: //
1819:
1820: if (WhichIsIt(inquiryData)) {
1821:
1822: RtlMoveMemory(gb_VendorId,inquiryData->VendorId,8);
1823: RtlMoveMemory(gb_ProductId,inquiryData->ProductId,16);
1824: return TRUE;
1825:
1826: }
1827: return FALSE;
1828:
1829: } // end TapeVerifyInquiry()
1830:
1831:
1832: NTSTATUS
1833: TapeWriteMarks(
1834: IN PDEVICE_OBJECT DeviceObject,
1835: IN PIRP Irp
1836: )
1837:
1838: /*++
1839: Routine Description:
1840:
1841: This routine writes tapemarks on the tape.
1842:
1843: Arguments:
1844:
1845: DeviceObject
1846: Irp
1847:
1848: Return Value:
1849:
1850: NTSTATUS
1851:
1852: --*/
1853:
1854: {
1855: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1856: PTAPE_WRITE_MARKS tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
1857: SCSI_REQUEST_BLOCK srb;
1858: PCDB cdb = (PCDB)srb.Cdb;
1859: NTSTATUS status;
1860:
1861: //
1862: // Zero CDB in SRB on stack.
1863: //
1864:
1865: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
1866:
1867: srb.CdbLength = CDB6GENERIC_LENGTH;
1868:
1869: cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
1870:
1871: cdb->WRITE_TAPE_MARKS.TransferLength[0] =
1872: ((tapeWriteMarks->Count >> 16) & 0xFF);
1873:
1874: cdb->WRITE_TAPE_MARKS.TransferLength[1] =
1875: ((tapeWriteMarks->Count >> 8) & 0xFF);
1876:
1877: cdb->WRITE_TAPE_MARKS.TransferLength[2] =
1878: (tapeWriteMarks->Count & 0xFF);
1879:
1880: //
1881: // Set timeout value.
1882: //
1883:
1884: srb.TimeOutValue = deviceExtension->TimeOutValue;
1885:
1886: switch (tapeWriteMarks->Type) {
1887: case TAPE_SETMARKS:
1888: DebugPrint((3,"TapeIoControl: Write Setmarks to Tape\n"));
1889: cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON;
1890: break;
1891:
1892: case TAPE_FILEMARKS:
1893: DebugPrint((3,"TapeIoControl: Write Filemarks to Tape\n"));
1894: break;
1895:
1896: case TAPE_SHORT_FILEMARKS:
1897: case TAPE_LONG_FILEMARKS:
1898: default:
1899: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
1900: return STATUS_INVALID_DEVICE_REQUEST;
1901: }
1902:
1903: //
1904: // Set immediate bit if indicated.
1905: //
1906:
1907: cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate;
1908:
1909:
1910: srb.CdbLength = CDB6GENERIC_LENGTH;
1911:
1912: status = ScsiClassSendSrbSynchronous(DeviceObject,
1913: &srb,
1914: NULL,
1915: 0,
1916: FALSE);
1917:
1918: return status;
1919:
1920: } // end TapeWriteMarks()
1921:
1922:
1923: static
1924: ULONG
1925: WhichIsIt(
1926: IN PINQUIRYDATA InquiryData
1927: )
1928:
1929: /*++
1930: Routine Description:
1931:
1932: This routine determines a drive's identity from the Product ID field
1933: in its inquiry data.
1934:
1935: Arguments:
1936:
1937: InquiryData (from an Inquiry command)
1938:
1939: Return Value:
1940:
1941: driveID
1942:
1943: --*/
1944:
1945: {
1946: if (RtlCompareMemory(InquiryData->VendorId,"ARCHIVE ",8) == 8) {
1947:
1948: if (RtlCompareMemory(InquiryData->ProductId,"Python",6) == 6) {
1949: return ARCHIVE_PYTHON;
1950: }
1951:
1952: }
1953:
1954: if (RtlCompareMemory(InquiryData->VendorId,"DEC ",8) == 8) {
1955:
1956: if (RtlCompareMemory(InquiryData->ProductId,"TLZ06",5) == 5) {
1957: return DEC_TLZ06;
1958: }
1959:
1960: }
1961:
1962: if (RtlCompareMemory(InquiryData->VendorId,"EXABYTE ",8) == 8) {
1963:
1964: if (RtlCompareMemory(InquiryData->ProductId,"EXB-4200 ",9) == 9) {
1965: return EXABYTE_4200;
1966: }
1967:
1968: if (RtlCompareMemory(InquiryData->ProductId,"EXB-4200c",9) == 9) {
1969: return EXABYTE_4200C;
1970: }
1971:
1972: }
1973:
1974: if (RtlCompareMemory(InquiryData->VendorId,"HP ",8) == 8) {
1975:
1976: if (RtlCompareMemory(InquiryData->ProductId,"HP35470A",8) == 8) {
1977: return HP_35470A;
1978: }
1979:
1980: if (RtlCompareMemory(InquiryData->ProductId,"HP35480A",8) == 8) {
1981: return HP_35480A;
1982: }
1983:
1984: if (RtlCompareMemory(InquiryData->ProductId,"IBM35480A",9) == 9) {
1985: return HP_IBM35480A;
1986: }
1987:
1988: }
1989:
1990: if (RtlCompareMemory(InquiryData->VendorId,"WangDAT ",8) == 8) {
1991:
1992: if (RtlCompareMemory(InquiryData->ProductId,"Model 1300",10) == 10) {
1993: return WANGDAT_1300;
1994: }
1995:
1996: if (RtlCompareMemory(InquiryData->ProductId,"Model 3100",10) == 10) {
1997: return WANGDAT_3100;
1998: }
1999:
2000: if (RtlCompareMemory(InquiryData->ProductId,"Model 3200",10) == 10) {
2001: return WANGDAT_3200;
2002: }
2003:
2004: }
2005:
2006: return 0;
2007: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.