|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: main.c
9:
10: Abstract:
11:
12: This is the tape class driver.
13:
14: Revision History:
15:
16:
17:
18:
19: --*/
20:
21: //
22: // Includes
23: //
24:
25: #include <ntddk.h>
26: #include <ntddtape.h> // tape device driver I/O control codes
27: #include <ntiologc.h>
28: #include "common.h"
29: #include "q117.h"
30: #include "cms.h"
31: #include "protos.h"
32: #include "hilevel.h"
33: #include "q117log.h"
34:
35: //
36: // Protos for entry points
37: //
38:
39: NTSTATUS
40: q117CreateNumericKey(
41: IN HANDLE Root,
42: IN ULONG Name,
43: IN PWSTR Prefix,
44: OUT PHANDLE NewKey
45: );
46:
47: NTSTATUS
48: q117CreateRegistryInfo(
49: IN ULONG TapeNumber,
50: IN PUNICODE_STRING RegistryPath,
51: IN PQ117_CONTEXT Context
52: );
53:
54: #ifdef ALLOC_PRAGMA
55: #pragma alloc_text(init,q117Initialize)
56: #endif
57:
58:
59: //
60: // Start of code
61: //
62:
63:
64: NTSTATUS
65: q117Initialize(
66: IN PDRIVER_OBJECT DriverObject,
67: IN PDEVICE_OBJECT q117iDeviceObject,
68: IN PUNICODE_STRING RegistryPath,
69: PADAPTER_OBJECT AdapterObject,
70: ULONG NumberOfMapRegisters
71: )
72:
73: /*++
74:
75: Routine Description:
76:
77: This routine initializes the SCSI Tape class driver.
78:
79: Arguments:
80:
81: DriverObject
82:
83: Return Value:
84:
85: NT Status
86:
87: --*/
88:
89: {
90: PDEVICE_OBJECT q117DeviceObject;
91: NTSTATUS status;
92: UNICODE_STRING ntUnicodeString;
93: UCHAR ntNameBuffer[256];
94: STRING ntNameString;
95: BOOLEAN tapeDeviceFound = FALSE;
96: PQ117_CONTEXT context;
97: ULONG tapeNumber;
98: STRING dosString;
99: UNICODE_STRING dosUnicodeString;
100: CCHAR dosNameBuffer[64];
101:
102: //
103: // Build the unicode name for the floppy tape.
104: //
105: tapeNumber = IoGetConfigurationInformation()->TapeCount;
106:
107: sprintf(ntNameBuffer,
108: "\\Device\\Tape%d",
109: tapeNumber);
110:
111: RtlInitString(&ntNameString, ntNameBuffer);
112:
113: status = RtlAnsiStringToUnicodeString(
114: &ntUnicodeString,
115: &ntNameString,
116: TRUE );
117:
118: if (!NT_SUCCESS(status)) {
119: return(status);
120: }
121:
122: //
123: // Create a device object for this floppy drive.
124: //
125:
126: status = IoCreateDevice(
127: DriverObject,
128: sizeof( struct _Q117_CONTEXT ),
129: &ntUnicodeString,
130: FILE_DEVICE_UNKNOWN,
131: FILE_REMOVABLE_MEDIA,
132: FALSE,
133: &q117DeviceObject );
134:
135:
136: if (!NT_SUCCESS(status)) {
137: return(status);
138: }
139:
140: //
141: // Create the DOS port driver name.
142: //
143:
144: sprintf(dosNameBuffer,
145: "\\DosDevices\\TAPE%d",
146: tapeNumber);
147:
148: RtlInitString(&dosString, dosNameBuffer);
149:
150: status = RtlAnsiStringToUnicodeString(&dosUnicodeString,
151: &dosString,
152: TRUE);
153:
154: if (!NT_SUCCESS(status)) {
155:
156: dosUnicodeString.Buffer = NULL;
157:
158: } else {
159:
160: IoAssignArcName(&dosUnicodeString, &ntUnicodeString);
161:
162: }
163:
164: RtlFreeUnicodeString(&ntUnicodeString);
165:
166: if (dosUnicodeString.Buffer != NULL) {
167:
168: RtlFreeUnicodeString(&dosUnicodeString);
169:
170: }
171:
172:
173: //
174: // Increment system tape count.
175: //
176: ++IoGetConfigurationInformation()->TapeCount;
177:
178: //
179: // Get device extension address.
180: //
181:
182: context = q117DeviceObject->DeviceExtension;
183: context->q117iDeviceObject = q117iDeviceObject;
184:
185: //
186: // Allocate memory for the filer
187: //
188:
189: status = q117AllocatePermanentMemory(
190: context,
191: AdapterObject,
192: NumberOfMapRegisters
193: );
194:
195: if (status) {
196: IoDeleteDevice(q117DeviceObject);
197: return status;
198: }
199:
200: //
201: // Indicate MDLs required.
202: //
203:
204: q117DeviceObject->Flags = DO_DIRECT_IO;
205:
206: status = q117CreateRegistryInfo(tapeNumber, RegistryPath, context);
207:
208: q117RdsInitReed();
209:
210: return status;
211:
212: } // end Q117Initialize()
213:
214: NTSTATUS
215: q117CreateRegistryInfo(
216: IN ULONG TapeNumber,
217: IN PUNICODE_STRING RegistryPath,
218: IN PQ117_CONTEXT Context
219: )
220:
221: /*++
222:
223: Routine Description:
224:
225: This function adds Tape\Unit x to the devicemap and puts the Id info
226: and type info values in it.
227:
228: Arguments:
229:
230: tapeNumber - unit number of the tape (current tape count)
231:
232: Context - current context of the driver (this is used to
233: identify the device).
234:
235:
236: Return Value:
237:
238: Returns the status of the operation.
239:
240: --*/
241:
242: {
243: HANDLE lunKey;
244: HANDLE unitKey;
245: UNICODE_STRING ntUnicodeString;
246: UCHAR ntNameBuffer[80];
247: STRING ntNameString;
248: UNICODE_STRING name;
249: OBJECT_ATTRIBUTES objectAttributes;
250: ULONG disposition;
251: NTSTATUS status;
252:
253: //
254: // Create the Tape key in the device map.
255: //
256:
257: RtlInitUnicodeString(
258: &name,
259: L"\\Registry\\Machine\\Hardware\\DeviceMap\\Tape"
260: );
261:
262: //
263: // Initialize the object for the key.
264: //
265:
266: InitializeObjectAttributes( &objectAttributes,
267: &name,
268: OBJ_CASE_INSENSITIVE,
269: NULL,
270: (PSECURITY_DESCRIPTOR) NULL );
271:
272: //
273: // Create the key or open it.
274: //
275:
276: status = ZwCreateKey(&lunKey,
277: KEY_READ | KEY_WRITE,
278: &objectAttributes,
279: 0,
280: (PUNICODE_STRING) NULL,
281: REG_OPTION_VOLATILE,
282: &disposition );
283:
284: if (!NT_SUCCESS(status)) {
285: return status;
286: }
287:
288: status = q117CreateNumericKey(lunKey, TapeNumber, L"Unit ", &unitKey);
289:
290: ZwClose(lunKey);
291:
292: if (!NT_SUCCESS(status)) {
293: return status;
294: }
295:
296:
297: //
298: // Add Identifier value.
299: //
300:
301: RtlInitUnicodeString(&name, L"Identifier");
302:
303: status = ZwSetValueKey(
304: unitKey,
305: &name,
306: 0,
307: REG_SZ,
308: L"QIC-40/QIC-80 floppy tape drive",
309: sizeof(L"QIC-40/QIC-80 floppy tape drive")
310: );
311:
312: if ( NT_SUCCESS(status) ) {
313: //
314: // Add driver value.
315: //
316:
317: RtlInitUnicodeString(&name, L"Driver");
318:
319: status = ZwSetValueKey(
320: unitKey,
321: &name,
322: 0,
323: REG_SZ,
324: RegistryPath->Buffer,
325: RegistryPath->Length
326: );
327: }
328:
329: if ( NT_SUCCESS(status) ) {
330: //
331: // Add DeviceName value.
332: //
333:
334: RtlInitUnicodeString(&name, L"DeviceName");
335:
336: sprintf(ntNameBuffer,
337: "Tape%d",
338: TapeNumber);
339:
340: RtlInitString(&ntNameString, ntNameBuffer);
341:
342: status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
343: &ntNameString,
344: TRUE);
345:
346: status = ZwSetValueKey(
347: unitKey,
348: &name,
349: 0,
350: REG_SZ,
351: ntUnicodeString.Buffer,
352: ntUnicodeString.Length
353: );
354:
355: RtlFreeUnicodeString(&ntUnicodeString);
356: }
357:
358: if ( NT_SUCCESS(status) ) {
359: //
360: // Add UniqueID
361: //
362:
363: RtlInitUnicodeString(&name, L"UniqueId");
364:
365: status = ZwSetValueKey(
366: unitKey,
367: &name,
368: 0,
369: REG_SZ,
370: L"",
371: 0
372: );
373: }
374:
375:
376: ZwClose(unitKey);
377:
378: return status;
379:
380: } // end q117CreateRegistryInfo
381:
382: NTSTATUS
383: q117CreateNumericKey(
384: IN HANDLE Root,
385: IN ULONG Name,
386: IN PWSTR Prefix,
387: OUT PHANDLE NewKey
388: )
389:
390: /*++
391:
392: Routine Description:
393:
394: This function creates a registry key. The name of the key is a string
395: version of numeric value passed in.
396:
397: Arguments:
398:
399: RootKey - Supplies a handle to the key where the new key should be inserted.
400:
401: Name - Supplies the numeric value to name the key.
402:
403: Prefix - Supplies a prefix name to add to name.
404:
405: NewKey - Returns the handle for the new key.
406:
407: Return Value:
408:
409: Returns the status of the operation.
410:
411: --*/
412:
413: {
414:
415: UNICODE_STRING string;
416: UNICODE_STRING stringNum;
417: OBJECT_ATTRIBUTES objectAttributes;
418: WCHAR bufferNum[16];
419: WCHAR buffer[64];
420: ULONG disposition;
421: NTSTATUS status;
422:
423: //
424: // Copy the Prefix into a string.
425: //
426:
427: string.Length = 0;
428: string.MaximumLength=64;
429: string.Buffer = buffer;
430:
431: RtlInitUnicodeString(&stringNum, Prefix);
432:
433: RtlCopyUnicodeString(&string, &stringNum);
434:
435: //
436: // Create a port number key entry.
437: //
438:
439: stringNum.Length = 0;
440: stringNum.MaximumLength = 16;
441: stringNum.Buffer = bufferNum;
442:
443: status = RtlIntegerToUnicodeString(Name, 10, &stringNum);
444:
445: if (!NT_SUCCESS(status)) {
446: return status;
447: }
448:
449: //
450: // Append the prefix and the numeric name.
451: //
452:
453: RtlAppendUnicodeStringToString(&string, &stringNum);
454:
455: InitializeObjectAttributes( &objectAttributes,
456: &string,
457: OBJ_CASE_INSENSITIVE,
458: Root,
459: (PSECURITY_DESCRIPTOR) NULL );
460:
461: status = ZwCreateKey(NewKey,
462: KEY_READ | KEY_WRITE,
463: &objectAttributes,
464: 0,
465: (PUNICODE_STRING) NULL,
466: REG_OPTION_VOLATILE,
467: &disposition );
468:
469: return(status);
470:
471: } // end q117CreateNumericKey
472:
473: NTSTATUS
474: q117Read(
475: IN PDEVICE_OBJECT DeviceObject,
476: IN PIRP Irp
477: )
478:
479: /*++
480:
481: Routine Description:
482:
483: This is the tape class driver IO handler routine.
484:
485: Arguments:
486:
487: DeviceObject
488: Irp - IO request
489:
490: Return Value:
491:
492: NT Status
493:
494: --*/
495:
496: {
497:
498: PIO_STACK_LOCATION currentIrpStack;
499: KIRQL currentIrql;
500: STATUS status;
501: NTSTATUS ntStatus;
502: PVOID usrBuf;
503: PQ117_CONTEXT context;
504: ULONG amount;
505: BOOLEAN endOfVolume = FALSE;
506:
507:
508: context = DeviceObject->DeviceExtension;
509: currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
510:
511: status = NoErr;
512: ntStatus = STATUS_SUCCESS;
513:
514: //
515: // If this is the first read, find the NT volume and read
516: if (context->CurrentOperation.Type == NoOperation) {
517:
518: ntStatus = q117OpenForRead(
519: context->CurrentOperation.BytesRead,
520: context,
521: DeviceObject);
522:
523: if (ntStatus == STATUS_NO_DATA_DETECTED) {
524:
525: //
526: // Flag no bytes read (end of media, end of data, etc.)
527: //
528:
529: ntStatus = STATUS_SUCCESS;
530: Irp->IoStatus.Information = 0;
531: endOfVolume = TRUE;
532:
533: }
534:
535: }
536:
537:
538: if (NT_SUCCESS(ntStatus)) {
539:
540: //
541: // Return the results of the call to the port driver.
542: //
543: usrBuf = MmGetSystemAddressForMdl(Irp->MdlAddress);
544:
545: //
546: // Check to see if user is asking for more data than is there
547: // (bytes on tape - current offset)
548: //
549:
550: amount = currentIrpStack->Parameters.Read.Length;
551:
552: ntStatus = q117ConvertStatus(
553: DeviceObject,
554: q117ReadTape(usrBuf,&amount,context)
555: );
556:
557: //
558: // Set the amount read to the amount we copied out of the buffer
559: //
560: Irp->IoStatus.Information = amount;
561:
562: CheckedDump(QIC117SHOWTD,("%x=Read(%x) - Status: %x\n",amount,currentIrpStack->Parameters.Read.Length, status));
563:
564: }
565:
566: if (endOfVolume && NT_SUCCESS(ntStatus)) {
567:
568: status = STATUS_NO_DATA_DETECTED;
569:
570: }
571:
572: Irp->IoStatus.Status = ntStatus;
573:
574: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
575: IoCompleteRequest(Irp, 0);
576: KeLowerIrql(currentIrql);
577:
578: return ntStatus;
579:
580:
581: } // end Q117Read()
582:
583:
584: NTSTATUS
585: q117Write(
586: IN PDEVICE_OBJECT DeviceObject,
587: IN PIRP Irp
588: )
589:
590: /*++
591:
592: Routine Description:
593:
594: This is the tape class driver IO handler routine.
595:
596: Arguments:
597:
598: DeviceObject
599: Irp - IO request
600:
601: Return Value:
602:
603: NT Status
604:
605: --*/
606:
607: {
608:
609: PIO_STACK_LOCATION currentIrpStack;
610: KIRQL currentIrql;
611: STATUS status;
612: NTSTATUS ntStatus;
613: PVOID usrBuf;
614: PQ117_CONTEXT context;
615:
616: context = DeviceObject->DeviceExtension;
617: currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
618:
619: //
620: // Make sure we are in write mode
621: //
622: status = q117OpenForWrite(context);
623:
624: if (!status) {
625:
626: //
627: // Return the results of the call to the port driver.
628: //
629: usrBuf = MmGetSystemAddressForMdl(Irp->MdlAddress);
630:
631: status = q117WriteTape(usrBuf,currentIrpStack->Parameters.Write.Length,context);
632: //
633: // Set the amount written to the amount we copied out of the buffer
634: //
635: if (!status || status == EarlyWarning)
636: Irp->IoStatus.Information = currentIrpStack->Parameters.Write.Length;
637: }
638:
639: ntStatus = q117ConvertStatus(DeviceObject, status);
640:
641: Irp->IoStatus.Status = ntStatus;
642:
643: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
644: IoCompleteRequest(Irp, 0);
645: KeLowerIrql(currentIrql);
646:
647: return ntStatus;
648:
649: } // end Q117Write()
650:
651: NTSTATUS
652: q117ConvertStatus(
653: IN PDEVICE_OBJECT DeviceObject,
654: IN STATUS Status
655: )
656: {
657: NTSTATUS ntStatus;
658: PQ117_CONTEXT context;
659: BOOLEAN suppressLog = FALSE;
660:
661: context = DeviceObject->DeviceExtension;
662:
663: switch(Status) {
664: case NoVols:
665: case InvalVol:
666: case EndOfVol:
667: // or maybe STATUS_END_OF_RECORDED_DATA?
668: ntStatus = STATUS_NO_DATA_DETECTED;
669: suppressLog = TRUE;
670: break;
671:
672: case EarlyWarning:
673: ntStatus = STATUS_END_OF_MEDIA;
674: suppressLog = TRUE;
675: break;
676:
677: case NoTape:
678: ntStatus = STATUS_NO_MEDIA_IN_DEVICE;
679: break;
680:
681: case NoErr:
682: ntStatus = STATUS_SUCCESS;
683: break;
684:
685: #ifndef NO_MARKS
686: case FileMark:
687: case LongFileMark:
688: case ShortFileMark:
689: ntStatus = STATUS_FILEMARK_DETECTED;
690: suppressLog = TRUE;
691: break;
692:
693: case SetMark:
694: ntStatus = STATUS_SETMARK_DETECTED;
695: suppressLog = TRUE;
696: break;
697: #endif
698:
699: case UnknownFormat:
700: case Unformat:
701: case BadFmt:
702: ntStatus = STATUS_UNRECOGNIZED_MEDIA;
703: break;
704:
705: case FMemErr:
706: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
707: break;
708:
709: case WProt:
710: ntStatus = STATUS_MEDIA_WRITE_PROTECTED;
711: break;
712:
713: case NewCart:
714: ntStatus = STATUS_MEDIA_CHANGED;
715: break;
716:
717: case UpdErr:
718: case BadTape:
719: ntStatus = STATUS_DATA_ERROR;
720: break;
721:
722: case RdncUnsc:
723: ntStatus = STATUS_CRC_ERROR;
724: break;
725:
726: default:
727: CheckedDump(QIC117DBGP,("Error %d reported\n",Status));
728: ntStatus = (NTSTATUS)(STATUS_SEVERITY_WARNING << 30);
729: ntStatus |= (FILE_DEVICE_TAPE << 16) & 0x3fff0000;
730: ntStatus |= Status & 0x0000ffff;
731:
732: }
733:
734: if (Status != NoErr && !suppressLog) {
735: NTSTATUS logStatus = q117MapStatus(Status);
736:
737: if (logStatus != QIC117_NOTAPE) {
738: CheckedDump(QIC117SHOWTD,("Error %d logged\n",Status));
739:
740: q117LogError(
741: DeviceObject,
742: context->ErrorSequence++,
743: context->MajorFunction,
744: 0,
745: Status,
746: ntStatus,
747: logStatus
748: );
749: }
750:
751: } else {
752: #if DBG
753: if (Status) {
754: CheckedDump(QIC117SHOWTD,("Error %d reported to API\n",Status));
755: }
756: #endif
757: }
758:
759: return ntStatus;
760: }
761:
762: NTSTATUS q117MapStatus(
763: IN STATUS Status
764: )
765: {
766: NTSTATUS mapped;
767:
768: switch(Status) {
769: case UnusTape:
770: mapped = QIC117_UNUSTAPE;
771: break;
772: case BadTape:
773: mapped = QIC117_BADTAPE;
774: break;
775: case FMemErr:
776: mapped = QIC117_FMEMERR;
777: break;
778: case TapeFull:
779: mapped = QIC117_TAPEFULL;
780: break;
781: case VolFull:
782: mapped = QIC117_VOLFULL;
783: break;
784: case RdncUnsc:
785: mapped = QIC117_RDNCUNSC;
786: break;
787: case EndOfVol:
788: mapped = QIC117_ENDOFVOL;
789: break;
790: case FCodeErr:
791: mapped = QIC117_FCODEERR;
792: break;
793: case UpdErr:
794: mapped = QIC117_UPDERR;
795: break;
796: case InvalVol:
797: mapped = QIC117_INVALVOL;
798: break;
799: case NoVols:
800: mapped = QIC117_NOVOLS;
801: break;
802: case Unformat:
803: mapped = QIC117_UNFORMAT;
804: break;
805: case UnknownFormat:
806: mapped = QIC117_UNKNOWNFORMAT;
807: break;
808: case BadBlk:
809: mapped = QIC117_BADBLK;
810: break;
811: case EndTapeErr:
812: mapped = QIC117_ENDTAPEERR;
813: break;
814: case DriveFlt:
815: mapped = QIC117_DRIVEFLT;
816: break;
817: case WProt:
818: mapped = QIC117_WPROT;
819: break;
820: case NoTape:
821: mapped = QIC117_NOTAPE;
822: break;
823: case SeekErr:
824: mapped = QIC117_SEEKERR;
825: break;
826: case NoDrive:
827: mapped = QIC117_NODRIVE;
828: break;
829: case InvalCmd:
830: mapped = QIC117_INVALCMD;
831: break;
832: case CodeErr:
833: mapped = QIC117_CODEERR;
834: break;
835: case NECFlt:
836: mapped = QIC117_NECFLT;
837: break;
838: case NoFDC:
839: mapped = QIC117_NOFDC;
840: break;
841: case BadFmt:
842: mapped = QIC117_BADFMT;
843: break;
844: case CmdFlt:
845: mapped = QIC117_CMDFLT;
846: break;
847: case BadNEC:
848: mapped = QIC117_BADNEC;
849: break;
850: case BadReq:
851: mapped = QIC117_BADREQ;
852: break;
853: case TooFast:
854: mapped = QIC117_TOOFAST;
855: break;
856: case NoData:
857: mapped = QIC117_NODATA;
858: break;
859: case DAbort:
860: mapped = QIC117_DABORT;
861: break;
862: case TapeFlt:
863: mapped = QIC117_TAPEFLT;
864: break;
865: case UnspRate:
866: mapped = QIC117_UNSPRATE;
867: break;
868: case Already:
869: mapped = QIC117_ALREADY;
870: break;
871: case TooNoisy:
872: mapped = QIC117_TOONOISY;
873: break;
874: case TimeOut:
875: mapped = QIC117_TIMEOUT;
876: break;
877: case BadMark:
878: mapped = QIC117_BADMARK;
879: break;
880: case NewCart:
881: mapped = QIC117_NEWCART;
882: break;
883: case WrongFmt:
884: mapped = QIC117_WRONGFMT;
885: break;
886: case FmtMisMatch:
887: mapped = QIC117_FMTMISMATCH;
888: break;
889: case IncompTapeFmt:
890: mapped = QIC117_INCOMPTAPEFMT;
891: break;
892: case SCSIFmtMsmtch:
893: mapped = QIC117_SCSIFMTMSMTCH;
894: break;
895: case QIC40InEagle:
896: mapped = QIC117_QIC40INEAGLE;
897: break;
898: case QIC80InEagle:
899: mapped = QIC117_QIC80INEAGLE;
900: break;
901: case ControllerBusy:
902: mapped = QIC117_CONTROLLERBUSY;
903: break;
904: case InQue:
905: mapped = QIC117_INQUE;
906: break;
907: case SplitRequests:
908: mapped = QIC117_SPLITREQUESTS;
909: break;
910: case EarlyWarning:
911: mapped = QIC117_EARLYWARNING;
912: break;
913: default:
914: mapped = QIC117_BOGUS;
915: }
916: return mapped;
917: }
918:
919: NTSTATUS
920: q117DeviceControl(
921: IN PDEVICE_OBJECT DeviceObject,
922: IN PIRP Irp
923: )
924:
925: /*++
926:
927: Routine Description:
928:
929: This routine is the dispatcher for device control requests. It
930: looks at the IOCTL code and calls the appropriate tape device
931: routine.
932:
933: Arguments:
934:
935: DeviceObject
936: Irp - Request packet
937:
938: Return Value:
939:
940: --*/
941:
942: {
943: PIO_STACK_LOCATION irpStack;
944: KIRQL currentIrql;
945: NTSTATUS status;
946: PQ117_CONTEXT context;
947:
948: context = DeviceObject->DeviceExtension;
949: irpStack = IoGetCurrentIrpStackLocation(Irp);
950:
951: status = 0;
952:
953: CheckedDump(QIC117SHOWPOLL,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
954:
955: switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
956:
957: case IOCTL_TAPE_GET_DRIVE_PARAMS:
958:
959: status = q117IoCtlGetDriveParameters(DeviceObject, Irp);
960: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_GET_DRIVE_PARAMS done"));
961: break;
962:
963: case IOCTL_TAPE_SET_DRIVE_PARAMS:
964:
965: status = q117IoCtlSetDriveParameters(DeviceObject, Irp);
966: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_DRIVE_PARAMS done"));
967: break;
968:
969: case IOCTL_TAPE_GET_MEDIA_PARAMS:
970:
971: status = q117IoCtlGetMediaParameters(DeviceObject, Irp);
972: CheckedDump(QIC117SHOWPOLL,("IOCTL_TAPE_GET_MEDIA_PARAMS done"));
973: break;
974:
975: case IOCTL_TAPE_SET_MEDIA_PARAMS:
976:
977: status = q117IoCtlSetMediaParameters(DeviceObject, Irp);
978: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_MEDIA_PARAMS done\n"));
979: break;
980:
981: case IOCTL_TAPE_CREATE_PARTITION:
982:
983: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_CREATE_PARTITION attempted\n"));
984: status = STATUS_INVALID_DEVICE_REQUEST;
985: break;
986:
987: case IOCTL_TAPE_ERASE:
988:
989: status = q117IoCtlErase(DeviceObject, Irp);
990: CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
991: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_ERASE done"));
992: break;
993:
994: case IOCTL_TAPE_PREPARE:
995:
996: status = q117IoCtlPrepare(DeviceObject, Irp);
997: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_PREPARE done"));
998: break;
999:
1000: case IOCTL_TAPE_WRITE_MARKS:
1001:
1002: status = q117IoCtlWriteMarks(DeviceObject, Irp);
1003: CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
1004: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_WRITE_MARKS done"));
1005: break;
1006:
1007: case IOCTL_TAPE_GET_POSITION:
1008:
1009: status = q117IoCtlGetPosition(DeviceObject, Irp);
1010: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_GET_POSITION done"));
1011: break;
1012:
1013: case IOCTL_TAPE_SET_POSITION:
1014:
1015: status = q117IoCtlSetPosition(DeviceObject, Irp);
1016: CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
1017: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_POSITION done"));
1018: break;
1019:
1020: case IOCTL_TAPE_GET_STATUS:
1021:
1022: status = q117IoCtlGetStatus (DeviceObject, Irp);
1023: CheckedDump(QIC117SHOWPOLL,("IOCTL_TAPE_GET_STATUS done"));
1024: break;
1025:
1026: case IOCTL_CMS_WRITE_ABS_BLOCK:
1027:
1028: status = q117IoCtlWriteAbs(DeviceObject, Irp);
1029: CheckedDump(QIC117SHOWTD,("IOCTL_CMS_WRITE_ABS_BLOCK done"));
1030: break;
1031:
1032: case IOCTL_CMS_READ_ABS_BLOCK:
1033:
1034: status = q117IoCtlReadAbs(DeviceObject, Irp);
1035: CheckedDump(QIC117SHOWTD,("IOCTL_CMS_READ_ABS_BLOCK done"));
1036: break;
1037:
1038:
1039: default:
1040:
1041: status = STATUS_INVALID_DEVICE_REQUEST;
1042:
1043: } // end switch()
1044:
1045: //
1046: // Complete the request.
1047: //
1048:
1049: CheckedDump(QIC117SHOWTD,(" -- Status: %x\n",status));
1050: Irp->IoStatus.Status = status;
1051:
1052: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
1053: IoCompleteRequest(Irp, 2);
1054: KeLowerIrql(currentIrql);
1055:
1056: return status;
1057:
1058: } // end Q117DeviceControl()
1059:
1060:
1061: NTSTATUS
1062: q117Create (
1063: IN PDEVICE_OBJECT DeviceObject,
1064: IN PIRP Irp
1065: )
1066:
1067: /*++
1068:
1069: Routine Description:
1070:
1071: This routine handles CREATE/OPEN requests and does
1072: nothing more than return successful status.
1073:
1074: Arguments:
1075:
1076: DeviceObject
1077: Irp
1078:
1079: Return Value:
1080:
1081: NT Status
1082:
1083: --*/
1084:
1085: {
1086: KIRQL currentIrql;
1087: PQ117_CONTEXT context;
1088: NTSTATUS ntStatus;
1089:
1090: context = DeviceObject->DeviceExtension;
1091:
1092: if (!context->DriverOpened) {
1093:
1094: ntStatus = q117ConvertStatus(DeviceObject, q117Start(context));
1095:
1096: //
1097: // If everything went OK, then flag that the driver is now open
1098: //
1099: if (NT_SUCCESS(ntStatus)) {
1100: context->DriverOpened = TRUE;
1101: } else {
1102: q117Stop(context);
1103: }
1104:
1105: } else {
1106:
1107: ntStatus = STATUS_DEVICE_BUSY;
1108:
1109: }
1110:
1111: Irp->IoStatus.Status = ntStatus;
1112:
1113: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
1114: IoCompleteRequest(Irp, 0);
1115: KeLowerIrql(currentIrql);
1116:
1117: return ntStatus;
1118:
1119: } // end Q117Create()
1120:
1121: NTSTATUS
1122: q117Close (
1123: IN PDEVICE_OBJECT DeviceObject,
1124: IN PIRP Irp
1125: )
1126:
1127: /*++
1128:
1129: Routine Description:
1130:
1131:
1132: Arguments:
1133:
1134: DeviceObject
1135: Irp
1136:
1137: Return Value:
1138:
1139: NT Status
1140:
1141: --*/
1142:
1143: {
1144: KIRQL currentIrql;
1145: PQ117_CONTEXT context;
1146: NTSTATUS ntStatus;
1147:
1148: context = DeviceObject->DeviceExtension;
1149:
1150: ntStatus = q117ConvertStatus(DeviceObject, q117Stop(context));
1151:
1152: context->DriverOpened = FALSE;
1153:
1154: Irp->IoStatus.Status = ntStatus;
1155:
1156: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
1157: IoCompleteRequest(Irp, 0);
1158: KeLowerIrql(currentIrql);
1159:
1160: return ntStatus;
1161:
1162: } // end Q117Close()
1163:
1164: VOID
1165: q117LogError(
1166: IN PDEVICE_OBJECT DeviceObject,
1167: IN ULONG SequenceNumber,
1168: IN UCHAR MajorFunctionCode,
1169: IN UCHAR RetryCount,
1170: IN ULONG UniqueErrorValue,
1171: IN NTSTATUS FinalStatus,
1172: IN NTSTATUS SpecificIOStatus
1173: )
1174:
1175: /*++
1176:
1177: Routine Description:
1178:
1179: This routine allocates an error log entry, copies the supplied data
1180: to it, and requests that it be written to the error log file.
1181:
1182: Arguments:
1183:
1184: DeviceObject - a pointer to the device object associated with the
1185: device that had the error.
1186:
1187: SequenceNumber - A ulong value that is unique to an IRP over the
1188: life of the irp in this driver - 0 generally means an error not
1189: associated with an irp.
1190:
1191: MajorFunctionCode - If there is an error associated with the irp,
1192: this is the major function code of that irp.
1193:
1194: RetryCount - The number of times a particular operation has been
1195: retried.
1196:
1197: UniqueErrorValue - A unique long word that identifies the particular
1198: call to this function.
1199:
1200: FinalStatus - The final status given to the irp that was associated
1201: with this error. If this log entry is being made during one of
1202: the retries this value will be STATUS_SUCCESS.
1203:
1204: SpecificIOStatus - The IO status for a particular error.
1205:
1206: Return Value:
1207:
1208: None.
1209:
1210: --*/
1211:
1212: {
1213: PIO_ERROR_LOG_PACKET errorLogEntry;
1214:
1215: errorLogEntry = IoAllocateErrorLogEntry(
1216: DeviceObject,
1217: sizeof(IO_ERROR_LOG_PACKET)
1218: );
1219:
1220: if ( errorLogEntry != NULL ) {
1221: errorLogEntry->ErrorCode = SpecificIOStatus;
1222: errorLogEntry->SequenceNumber = SequenceNumber;
1223: errorLogEntry->MajorFunctionCode = MajorFunctionCode;
1224: errorLogEntry->RetryCount = RetryCount;
1225: errorLogEntry->UniqueErrorValue = UniqueErrorValue;
1226: errorLogEntry->FinalStatus = FinalStatus;
1227: errorLogEntry->DumpDataSize = 0;
1228: IoWriteErrorLogEntry(errorLogEntry);
1229:
1230: }
1231:
1232: }
1233: #ifdef NOT_NOW
1234:
1235: VOID
1236: q117Cancel(
1237: IN PDEVICE_OBJECT DeviceObject,
1238: IN PIRP Irp
1239: )
1240:
1241: /*++
1242:
1243: Routine Description:
1244:
1245: This routine is called from the I/O system when a request is cancelled.
1246:
1247: N.B. The cancel spinlock is already held upon entry to this routine.
1248:
1249: Arguments:
1250:
1251: DeviceObject - Pointer to class device object.
1252:
1253: Irp - Pointer to the request packet to be cancelled.
1254:
1255: Return Value:
1256:
1257: None.
1258:
1259: --*/
1260:
1261: {
1262:
1263: CheckedDump(QIC117INFO,("q117Cancel: enter\n"));
1264:
1265: if (Irp == DeviceObject->CurrentIrp) {
1266:
1267: //
1268: // The current request is being cancelled. Set the CurrentIrp to
1269: // null and release the cancel spinlock before starting the next packet.
1270: //
1271:
1272: DeviceObject->CurrentIrp = NULL;
1273: IoReleaseCancelSpinLock(Irp->CancelIrql);
1274: IoStartNextPacket(DeviceObject, TRUE);
1275:
1276: } else {
1277:
1278: //
1279: // Cancel a request in the device queue. Remove it from queue and
1280: // release the cancel spinlock.
1281: //
1282:
1283: if (TRUE != KeRemoveEntryDeviceQueue(
1284: &DeviceObject->DeviceQueue,
1285: &Irp->Tail.Overlay.DeviceQueueEntry
1286: )) {
1287: CheckedDump(QIC117SHOWTD,(
1288: "q117Cancel: Irp 0x%x not in device queue?!?\n",
1289: Irp
1290: ));
1291: }
1292: IoReleaseCancelSpinLock(Irp->CancelIrql);
1293: }
1294:
1295: //
1296: // Complete the request with STATUS_CANCELLED.
1297: //
1298:
1299: Irp->IoStatus.Status = STATUS_CANCELLED;
1300: Irp->IoStatus.Information = 0;
1301: IoCompleteRequest (Irp, IO_NO_INCREMENT);
1302:
1303: CheckedDump(QIC117INFO,("q117Cancel: exit\n"));
1304:
1305: return;
1306: }
1307: #endif
1308:
1309: NTSTATUS
1310: q117Cleanup(
1311: IN PDEVICE_OBJECT DeviceObject,
1312: IN PIRP Irp
1313: )
1314:
1315: /*++
1316:
1317: Routine Description:
1318:
1319: This routine is the dispatch routine for cleanup requests.
1320: All queued q117 requests are completed with STATUS_CANCELLED,
1321: and the lower level driver's queue is cleared.
1322:
1323: Arguments:
1324:
1325: DeviceObject - Pointer to class device object.
1326:
1327: Irp - Pointer to the request packet.
1328:
1329: Return Value:
1330:
1331: Status is returned.
1332:
1333: --*/
1334:
1335: {
1336: KIRQL currentIrql;
1337: KIRQL cancelIrql;
1338: PKDEVICE_QUEUE_ENTRY packet;
1339: PIRP currentIrp;
1340:
1341: CheckedDump(QIC117INFO,("q117Cleanup: enter\n"));
1342:
1343: /* clear everything from the low-level driver */
1344: q117ClearQueue(
1345: DeviceObject->DeviceExtension
1346: );
1347: //
1348: // Raise IRQL to DISPATCH_LEVEL.
1349: //
1350:
1351: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
1352:
1353: //
1354: // Acquire the cancel spinlock.
1355: //
1356:
1357: IoAcquireCancelSpinLock(&cancelIrql);
1358:
1359: //
1360: // Complete all queued requests with STATUS_CANCELLED.
1361: // Start with the real CurrentIrp, and run down the list of requests in the
1362: // device queue. Be sure to set the real CurrentIrp to NULL, so that
1363: // the interrupt service callback routine won't attempt to complete it.
1364: //
1365:
1366: currentIrp = DeviceObject->CurrentIrp;
1367: DeviceObject->CurrentIrp = NULL;
1368:
1369: while (currentIrp != NULL) {
1370:
1371: //
1372: // Remove the CurrentIrp from the cancellable state.
1373: //
1374: //
1375:
1376: IoSetCancelRoutine(currentIrp, NULL);
1377:
1378: //
1379: // Set Status to CANCELLED, release the cancel spinlock,
1380: // and complete the request. Note that the IRQL is reset to
1381: // DISPATCH_LEVEL when we release the cancel spinlock.
1382: //
1383:
1384: currentIrp->IoStatus.Status = STATUS_CANCELLED;
1385: currentIrp->IoStatus.Information = 0;
1386:
1387: IoReleaseCancelSpinLock(cancelIrql);
1388: IoCompleteRequest(currentIrp, IO_NO_INCREMENT);
1389:
1390: //
1391: // Reacquire the cancel spinlock.
1392: //
1393:
1394: IoAcquireCancelSpinLock(&cancelIrql);
1395:
1396: //
1397: // Dequeue the next packet (IRP) from the device work queue.
1398: //
1399:
1400: packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
1401: if (packet != NULL) {
1402: currentIrp =
1403: CONTAINING_RECORD(packet, IRP, Tail.Overlay.DeviceQueueEntry);
1404: } else {
1405: currentIrp = (PIRP) NULL;
1406: }
1407: } // end while
1408:
1409: //
1410: // Release the cancel spinlock and lower IRQL.
1411: //
1412:
1413: IoReleaseCancelSpinLock(cancelIrql);
1414: KeLowerIrql(currentIrql);
1415:
1416: //
1417: // Complete the cleanup request with STATUS_SUCCESS.
1418: //
1419:
1420: Irp->IoStatus.Status = STATUS_SUCCESS;
1421: Irp->IoStatus.Information = 0;
1422: IoCompleteRequest (Irp, IO_NO_INCREMENT);
1423:
1424: CheckedDump(QIC117INFO,("q117Cleanup: exit\n"));
1425:
1426: return(STATUS_SUCCESS);
1427:
1428: }
1429:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.