|
|
1.1 root 1: This sample program consists of two parts. First, all the necessary
2: source code is provided to compile a Win32 sample program that sends
3: an IOCtl_SCSI_MINIPORT request with a custom ControlCode to the SCSI
4: miniport driver. Second, a detailed description is provided that
5: explains what changes the driver writer has to make to a SCSI
6: miniport driver to allow it to properly recognize and handle the
7: corresponding IOCtl request from the Win32 sample program.
8:
9: Part 1 - Win32 sample
10:
11: The SCSI Miniport IOCtl sample, SMPI.C, demonstrates how a Win32
12: application sends a user defined IOCtl Control Code to a SCSI
13: miniport driver. This is a simple program that is composed of four
14: steps.
15:
16: Step 1, a handle is obtained to the SCSI miniport driver using the
17: Win32 API, CreateFile. The name of the file to be opened is
18: \\.\Scsi0:. As an alternative, a drive letter can be substituted for
19: \\.\Scsi0: (e.g. - \\.\C:). This will map to the appropriate SCSI
20: miniport driver that is responsible for C:.
21:
22: Step 2, the SRB_IO_CONTROL structure is filled out. The following
23: items must be completed :
24:
25: HeaderLength - must be the size of an SRB_IO_CONTROL structure
26: ControlCode - while strictly optional, this entry should be
27: considered mandatory. The ControlCode value is used to
28: further sub-divide IOCTL_SCSI_MINIPORT requests. The
29: contents of ControlCode are defined by the SCSI miniport
30: driver writer.
31: Length - the size of the data buffer immediately following the
32: SRB_IO_CONTROL structure. If no additional data buffer
33: is used, then this must be set to 0.
34:
35: The following items of the SRB_IO_CONTROL structure are optional :
36:
37: Signature - these 8 bytes are available to help prevent IOCtl
38: conflicts between various vendors
39: Timeout - indicates the minimum time in seconds before the
40: request has timed out. There is no maximum Timeout for
41: IOCTL_SCSI_MINIPORT. Note, for IOCTL_SCSI_PASS_THROUGH,
42: the maximum time out value is 108000 seconds (30 minutes).
43: ReturnCode - this entry is filled in by the SCSI miniport to
44: inform the Win32 application of the results of the
45: requested action. The contents of ReturnCode are defined
46: by the SCSI miniport Driver writer.
47:
48: In the SMPI.C sample, two customer defined ControlCodes are used,
49: SMP_RETURN_3F and SMP_PRINT_STRING. The first requires
50: no additional data buffer. The second requires that a contiguous
51: data buffer be appended at the end of the SRB_IO_CONTROL structure.
52: The ControlCodes are defined by the SCSI miniport driver (see below).
53:
54: Step 3, send the SRB_IO_CONTROL structure to the SCSI miniport driver
55: via the DeviceIoControl Win32 API. The dwIoControlCode must be
56: IOCTL_SCSI_MINIPORT. This particular dwIoControlCode is not
57: currently defined in any of the Win32 SDK header files and must be
58: defined in your own personal header file. It is defined in the
59: Windows NT DDK header file, NTDDSCSI.H. Including a Windows NT
60: DDK header file in a Win32 source file has been avoided strictly to
61: demonstrate the ability to write a Win32 application that accesses a
62: device driver without having the Windows NT DDK.
63:
64: Step 4, close the handle to the SCSI miniport driver.
65:
66: In SMPI.C, steps 2 and 3 are repeated to demonstrate the two
67: ControlCodes, SMP_RETURN_3F and SMP_PRINT_STRING. The
68: first requires no extra data buffer and so 'length' is set to 0. The
69: second does require additional buffer space. The value of 100 is
70: used as it makes the buffer large enough to handle up to 100 bytes of
71: data returned by the SCSI miniport driver.
72:
73: When strings are manipulated via the _memXXX functions, the
74: terminating null is not used. When using strXXX commands, the
75: terminating null is used. strlen does not include the terminating
76: null in it's total.
77:
78: Part 2 - SCSI Miniport Driver
79:
80: The SCSI miniport driver writer is free to define the ControlCode to
81: any value. Microsoft has provided a template for defining such
82: values and the driver writer can use this template for determining
83: their ControlCode values, but are not obligated to do so. In this
84: sample, SMP_RETURN_3F was defined using the template and
85: SMP_PRINT_STRING was defined with a random number.
86:
87: If the microsoft template is to be used, then the Windows NT DDK
88: header file, DEVIOCTL.H, should be consulted before defining a new
89: IOCtl. Also, the "Kernel-mode Driver Design Guide" contains
90: additional information on page B-12. There are two documentation
91: errors on this page. First, the bit pattern should be :
92:
93: bit(s) purpose
94: ------ -------
95: 0,1 Transfer type
96: 2-12 Function Code
97: 13 Customer bit
98: 14,15 Required Access
99: 16-30 Device type
100: 31 Common bit
101:
102: The second documentation error states that the Function Code values
103: can be 0x00 to 0x7F for Microsoft defined IOCtls and 0x80 to 0xFF for
104: user defined IOCtls. This should be 0x000 to 0x7FF for Microsoft
105: defined IOCtls and 0x800 to 0xFFF for user defined IOCtls. The
106: Function Code field defines the function and the Customer bit
107: determines whether the function is defined by Microsoft or a
108: customer.
109:
110: The following should be added to the SCSI minport driver's header
111: file :
112:
113: //
114: // IOCtl definitions
115: //
116:
117: //
118: // Define the various device type values. Note that values used by Microsoft
119: // Corporation are in the range 0x0000 - 0x7FFF, and 0x8000 - 0xFFFF are
120: // reserved for use by customers.
121: //
122:
123: #define IOCTL_SCSI_MINIPORT_IO_CONTROL 0x8001
124:
125: //
126: // Macro definition for defining IOCTL and FSCTL function control codes.
127: // Note that function codes 0x000 - 0x7FF are reserved for Microsoft
128: // Corporation, and 0x800 - 0xFFF are reserved for customers.
129: //
130:
131: #define RETURNCODE0x0000003F 0x850
132:
133: #define SMP_RETURN_3F CTL_CODE(IOCTL_SCSI_MINIPORT_IO_CONTROL, RETURNCODE0x0000003F, METHOD_BUFFERED, FILE_ANY_ACCESS)
134: #define SMP_PRINT_STRING 0x80000001
135:
136: PCHAR Signature="MyDrvr";
137: PCHAR DrvrString="This string was placed in the data area by the SCSI miniport driver\n";
138:
139: typedef struct {
140: SRB_IO_CONTROL sic;
141: UCHAR ucDataBuffer[512];
142: } SRB_BUFFER, *PSRB_BUFFER;
143:
144: The following should be added to the SCSI miniport driver's source
145: code :
146:
147: #include <miniport.h>
148: #include <devioctl.h>
149: #include <ntddscsi.h>
150: #include "mydriver.h"
151:
152: and the following should be added to the SCSI miniport driver's
153: StartIo routine :
154:
155: case SRB_FUNCTION_IO_CONTROL:
156:
157: if (!memcmp(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,Signature,strlen(Signature))) {
158:
159: DebugPrint((1,"MyDriverStartIo: MiniportIOCtl not supported\n"));
160:
161: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
162:
163: ScsiPortNotification(RequestComplete,
164: CardPtr,
165: Srb);
166: break;
167: }
168:
169:
170: DebugPrint((1,"MyDriverStartIo: Miniport IOCtl received\n"));
171:
172: DebugPrint((3,"MyDriverStartIo: Srb->DataBuffer->ControlCode = %Xh\n",
173: ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode));
174:
175: switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
176:
177: case SMP_RETURN_3F :
178:
179: Srb->SrbStatus = SRB_STATUS_SUCCESS;
180:
181: ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ReturnCode =
182: (ULONG) 0x0000003FL;
183:
184: ScsiPortNotification(RequestComplete,
185: CardPtr,
186: Srb);
187: break;
188:
189: case SMP_PRINT_STRING :
190:
191: Srb->SrbStatus = SRB_STATUS_SUCCESS;
192:
193: DebugPrint((0,"%s",((PSRB_BUFFER)(Srb->DataBuffer))->ucDataBuffer));
194:
195: strcpy(((PSRB_BUFFER)(Srb->DataBuffer))->ucDataBuffer,DrvrString);
196:
197: ScsiPortNotification(RequestComplete,
198: CardPtr,
199: Srb);
200: break;
201:
202: default :
203:
204: DebugPrint((1,"MyDriverStartIo: MiniportIOCtl not supported\n"));
205:
206: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
207:
208: ScsiPortNotification(RequestComplete,
209: CardPtr,
210: Srb);
211: break;
212:
213: } // end switch
214:
215: break;
216:
217:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.