2 * bulkonly.c - USB driver stack project for Windows NT 4.0
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "usbdriver.h"
25 #define OLYMPUS_CSW( pdev_EXT, staTUS ) \
26 ( ( ( pdev_EXT )->flags & UMSS_DEV_FLAG_OLYMPUS_DEV ) ? ( ( staTUS ) == CSW_OLYMPUS_SIGNATURE ) : FALSE )
28 BOOLEAN
umss_clear_pass_through_length(PIO_PACKET io_packet
);
30 NTSTATUS
umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext
);
32 VOID
umss_bulkonly_send_cbw_completion(IN PURB purb
, IN PVOID context
);
34 VOID
umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext
);
36 VOID
umss_sync_submit_urb_completion(PURB purb
, PVOID context
);
38 NTSTATUS
umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext
, PURB purb
);
40 VOID
umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext
);
42 VOID
umss_bulkonly_transfer_data_complete(PURB purb
, PVOID reference
);
44 VOID
umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference
);
46 VOID
umss_bulkonly_reset_recovery(IN PVOID reference
);
48 VOID
umss_bulkonly_get_status_complete(IN PURB purb
, IN PVOID context
);
53 Handler for all I/O requests using bulk-only protocol.
57 DeviceExtension - Device extension for our FDO.
65 umss_bulkonly_startio(IN PUMSS_DEVICE_EXTENSION pdev_ext
, IN PIO_PACKET io_packet
)
67 PCOMMAND_BLOCK_WRAPPER cbw
;
70 if (pdev_ext
== NULL
|| io_packet
== NULL
|| io_packet
->pirp
== NULL
)
71 return STATUS_INVALID_PARAMETER
;
73 pdev_ext
->retry
= TRUE
;
74 RtlCopyMemory(&pdev_ext
->io_packet
, io_packet
, sizeof(pdev_ext
->io_packet
));
76 // Setup the command block wrapper for this request
78 cbw
->dCBWSignature
= CBW_SIGNATURE
;
80 cbw
->dCBWDataTransferLength
= io_packet
->data_length
;
81 cbw
->bmCBWFlags
= (io_packet
->flags
& USB_DIR_IN
) ? 0x80 : 0;
82 cbw
->bCBWLun
= io_packet
->lun
;
83 cbw
->bCBWLength
= io_packet
->cdb_length
;
84 RtlCopyMemory(cbw
->CBWCB
, io_packet
->cdb
, sizeof(cbw
->CBWCB
));
86 RtlZeroMemory(&pdev_ext
->csw
, sizeof(pdev_ext
->csw
));
87 // Send the command block wrapper to the device.
88 // Calls UMSS_BulkOnlySendCBWComplete when transfer completes.
89 status
= umss_bulk_transfer(pdev_ext
,
91 cbw
, sizeof(COMMAND_BLOCK_WRAPPER
), umss_bulkonly_send_cbw_completion
);
98 umss_bulk_transfer(IN PUMSS_DEVICE_EXTENSION pdev_ext
,
99 IN UCHAR trans_dir
, IN PVOID buf
, IN ULONG buf_length
, IN PURBCOMPLETION completion
)
103 DEV_HANDLE endp_handle
;
105 if (pdev_ext
== NULL
|| buf
== NULL
|| completion
== NULL
)
106 return STATUS_INVALID_PARAMETER
;
108 if (buf_length
> (ULONG
) MAX_BULK_TRANSFER_LENGTH
)
109 return STATUS_INVALID_PARAMETER
;
111 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
114 return STATUS_NO_MEMORY
;
116 if (trans_dir
== USB_DIR_OUT
)
118 endp_handle
= usb_make_handle((pdev_ext
->dev_handle
>> 16), pdev_ext
->if_idx
, pdev_ext
->out_endp_idx
);
122 endp_handle
= usb_make_handle((pdev_ext
->dev_handle
>> 16), pdev_ext
->if_idx
, pdev_ext
->in_endp_idx
);
125 UsbBuildInterruptOrBulkTransferRequest(purb
, endp_handle
, buf
, buf_length
, completion
, pdev_ext
, 0);
126 dev_mgr_register_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
, purb
);
127 status
= usb_submit_urb(pdev_ext
->dev_mgr
, purb
);
128 if (status
== STATUS_PENDING
)
133 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
143 umss_bulkonly_send_cbw_completion(IN PURB purb
, IN PVOID context
)
146 PUMSS_DEVICE_EXTENSION pdev_ext
;
148 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) context
;
150 status
= purb
->status
;
151 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
153 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_SENSE
)
155 usb_free_mem(purb
->data_buffer
);
156 purb
->data_buffer
= NULL
;
157 purb
->data_length
= 0;
160 if (status
!= STATUS_SUCCESS
)
162 if (usb_halted(status
))
164 //Schedule a work-item to do a reset recovery
165 if (!umss_schedule_workitem
166 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
168 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
173 // Device failed CBW without stalling, so complete with error
174 umss_complete_request(pdev_ext
, status
);
179 // CBW was accepted by device, so start data phase of I/O operation
180 umss_bulkonly_transfer_data(pdev_ext
);
190 //can only be called at passive level
192 umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext
, PURB purb
)
196 if (pdev_ext
== NULL
|| purb
== NULL
)
197 return STATUS_INVALID_PARAMETER
;
199 purb
->completion
= umss_sync_submit_urb_completion
;
200 purb
->context
= (PVOID
) pdev_ext
;
202 dev_mgr_register_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
, purb
);
203 status
= usb_submit_urb(pdev_ext
->dev_mgr
, purb
);
204 if (status
== STATUS_PENDING
)
206 KeWaitForSingleObject(&pdev_ext
->sync_event
, Executive
, KernelMode
, TRUE
, NULL
);
207 status
= purb
->status
;
210 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
216 umss_sync_submit_urb_completion(PURB purb
, PVOID context
)
218 PUMSS_DEVICE_EXTENSION pdev_ext
;
220 if (purb
== NULL
|| context
== NULL
)
223 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) context
;
224 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
225 KeSetEvent(&pdev_ext
->sync_event
, 0, FALSE
);
232 Worker function used to execute a reset recovery after a stall.
236 Reference - Our device extension.
244 umss_bulkonly_reset_recovery(IN PVOID reference
)
246 PUMSS_DEVICE_EXTENSION pdev_ext
;
249 DEV_HANDLE endp_handle
;
251 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) reference
;
252 usb_dbg_print(DBGLVL_MAXIMUM
, ("umss_bulkonly_reset_recovery(): entering...\n"));
253 // Steps for reset recovery:
254 // 1. Send device a mass storage reset command on the default endpoint.
255 // 2. Reset the bulk-in endpoint.
256 // 3. Reset the bulk-out endpoint.
257 // 4. Complete the original I/O request with error.
260 // Build the mass storage reset command
261 UsbBuildVendorRequest(&urb
, pdev_ext
->dev_handle
| 0xffff, //default pipe
262 NULL
, //no extra data
264 0x21, //class, interface
265 BULK_ONLY_MASS_STORAGE_RESET
,
267 pdev_ext
->pif_desc
->bInterfaceNumber
,
272 // Send mass storage reset command to device
273 status
= umss_sync_submit_urb(pdev_ext
, &urb
);
275 if (status
!= STATUS_SUCCESS
)
277 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_reset_recovery(): Reset Recovery failed!\n"));
281 //Reset Bulk-in endpoint
282 endp_handle
= usb_make_handle((pdev_ext
->dev_handle
>> 16), pdev_ext
->if_idx
, pdev_ext
->in_endp_idx
);
283 status
= umss_reset_pipe(pdev_ext
, endp_handle
);
285 if (!NT_SUCCESS(status
))
287 usb_dbg_print(DBGLVL_MINIMUM
,
288 ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-in endpoint\n"));
291 //Reset Bulk-out endpoint
292 endp_handle
= usb_make_handle((pdev_ext
->dev_handle
>> 16), pdev_ext
->if_idx
, pdev_ext
->out_endp_idx
);
293 status
= umss_reset_pipe(pdev_ext
, endp_handle
);
295 if (!NT_SUCCESS(status
))
297 usb_dbg_print(DBGLVL_MINIMUM
,
298 ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-out endpoint\n"));
301 umss_complete_request(pdev_ext
, status
);
307 Schedules a bulk data transfer to/from the device.
311 DeviceExtension - Our FDO's device extension.
319 umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext
)
322 ULONG data_buf_length
;
324 UCHAR trans_dir
= USB_DIR_IN
; // FIXME: Initialize this properly!
326 // Steps for data phase
327 // 1. Get data buffer fragment (either SGD list, flat buffer, or none).
328 // 2. Schedule data transfer if neccessary.
329 // 3. Repeat 1-2 until all data transferred, or endpoint stalls.
330 // 4. Move to status phase.
332 // Get next data buffer element, if any
333 data_buf
= umss_get_buffer(pdev_ext
, &data_buf_length
);
335 if (NULL
== data_buf
)
337 //No data to transfer, so move to status phase
338 umss_bulkonly_get_status(pdev_ext
);
342 // Schedule the data transfer.
343 // Calls umss_bulkonly_transfer_data_complete when transfer completes.
345 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
)
346 trans_dir
= (UCHAR
) ((pdev_ext
->cbw
.bmCBWFlags
& USB_DIR_IN
) ? USB_DIR_IN
: USB_DIR_OUT
);
347 else if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_SENSE
)
348 trans_dir
= USB_DIR_IN
;
350 if ((status
= umss_bulk_transfer(pdev_ext
,
354 umss_bulkonly_transfer_data_complete
)) != STATUS_PENDING
)
356 umss_complete_request(pdev_ext
, status
);
364 Completion handler for bulk data transfer requests.
367 umss_bulkonly_transfer_data_complete(PURB purb
, PVOID reference
)
370 PUMSS_DEVICE_EXTENSION pdev_ext
;
371 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) reference
;
373 status
= purb
->status
;
375 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
377 if (status
!= STATUS_SUCCESS
)
380 // clear the data length if this is a scsi pass through request
382 umss_clear_pass_through_length(&pdev_ext
->io_packet
);
384 // Device failed data phase
385 // Check if we need to clear stalled pipe
386 if (usb_halted(status
))
389 buf
= usb_alloc_mem(NonPagedPool
, 32);
390 buf
[0] = (ULONG
) pdev_ext
;
391 buf
[1] = (ULONG
) purb
->endp_handle
;
393 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_transfer_data_complete(): transfer data error!\n"));
394 if (!umss_schedule_workitem
395 ((PVOID
) buf
, umss_bulkonly_reset_pipe_and_get_status
, pdev_ext
->dev_mgr
,
396 pdev_ext
->dev_handle
))
398 usb_free_mem(buf
), buf
= NULL
;
399 usb_dbg_print(DBGLVL_MINIMUM
,
400 ("umss_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n"));
402 umss_complete_request(pdev_ext
, status
);
408 umss_complete_request(pdev_ext
, status
);
413 // Start next part of data phase
414 //umss_bulkonly_transfer_data( pdev_ext );
415 umss_bulkonly_get_status(pdev_ext
);
416 //umss_complete_request( pdev_ext, status );
422 return; // STATUS_MORE_PROCESSING_REQUIRED;
427 umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference
)
429 PUMSS_DEVICE_EXTENSION pdev_ext
;
430 DEV_HANDLE endp_handle
;
433 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_reset_pipe_and_get_status(): entering...\n"));
435 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) (((PULONG
) reference
)[0]);
436 endp_handle
= (DEV_HANDLE
) ((PULONG
) reference
)[1];
437 usb_free_mem(reference
);
440 // Reset the endpoint
441 if ((status
= umss_reset_pipe(pdev_ext
, endp_handle
)) != STATUS_SUCCESS
)
443 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe failed\n"));
444 umss_complete_request(pdev_ext
, status
);
447 // Data phase is finished since the endpoint stalled, so go to status phase
448 usb_dbg_print(DBGLVL_MINIMUM
,
449 ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe succeeds, continue to get status\n"));
450 umss_bulkonly_get_status(pdev_ext
);
454 umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext
)
457 // Schedule bulk transfer to get command status wrapper from device
458 status
= umss_bulk_transfer(pdev_ext
,
461 sizeof(COMMAND_STATUS_WRAPPER
), umss_bulkonly_get_status_complete
);
462 if (status
!= STATUS_PENDING
)
464 umss_complete_request(pdev_ext
, status
);
471 Completion handler for bulk data transfer request.
475 DeviceObject - Previous device object.
476 Irp - Irp used for sending command.
481 Driver-originated IRPs always return STATUS_MORE_PROCESSING_REQUIRED.
485 umss_bulkonly_get_status_complete(IN PURB purb
, IN PVOID context
)
488 PUMSS_DEVICE_EXTENSION pdev_ext
;
489 PCOMMAND_STATUS_WRAPPER csw
;
491 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) context
;
492 status
= purb
->status
;
494 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
496 csw
= &(pdev_ext
->csw
);
497 if (status
== STATUS_SUCCESS
&&
498 ((csw
->dCSWSignature
== CSW_SIGNATURE
) || OLYMPUS_CSW(pdev_ext
, csw
->dCSWSignature
)))
500 if (csw
->bCSWStatus
== CSW_STATUS_PASSED
)
502 // Received valid CSW with good status
504 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
&&
505 (pdev_ext
->io_packet
.flags
& IOP_FLAG_REQ_SENSE
) && pdev_ext
->io_packet
.sense_data
!= NULL
)
506 UMSS_FORGE_GOOD_SENSE(pdev_ext
->io_packet
.sense_data
)
507 umss_complete_request(pdev_ext
, STATUS_SUCCESS
);
509 else if (csw
->bCSWStatus
== CSW_STATUS_FAILED
)
511 // start a request sense if necessary
512 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_REQ_SENSE
) &&
513 (pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
)
515 if (umss_bulkonly_send_sense_req(pdev_ext
) != STATUS_PENDING
)
517 // don't know how to handle.
518 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
522 // fall through to free the urb
527 // error occurred, reset device
528 if (!umss_schedule_workitem
529 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
531 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
537 // error occurred, reset device
538 if (!umss_schedule_workitem
539 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
541 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
545 else if ((status
!= STATUS_SUCCESS
) && (usb_halted(status
)) && (pdev_ext
->retry
))
547 // Device stalled CSW transfer, retry once before failing
549 pdev_ext
->retry
= FALSE
;
551 buf
= usb_alloc_mem(NonPagedPool
, 32);
552 buf
[0] = (ULONG
) pdev_ext
;
553 buf
[1] = (ULONG
) purb
->endp_handle
;
555 if (!umss_schedule_workitem
556 ((PVOID
) buf
, umss_bulkonly_reset_pipe_and_get_status
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
558 usb_free_mem(buf
), buf
= NULL
;
559 usb_dbg_print(DBGLVL_MINIMUM
,
560 ("umss_bulkonly_get_status_complete(): Failed to allocate work-item to reset pipe!\n"));
562 umss_complete_request(pdev_ext
, status
);
565 else if (status
!= STATUS_CANCELLED
)
567 // An error has occured. Reset the device.
568 if (!umss_schedule_workitem
569 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
571 usb_dbg_print(DBGLVL_MINIMUM
,
572 ("umss_bulkonly_get_status_complete(): Failed to schedule work-item to reset pipe!\n"));
574 umss_complete_request(pdev_ext
, status
);
579 // the request is canceled
580 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_get_status_complete(): the request is canceled\n"));
581 umss_complete_request(pdev_ext
, STATUS_CANCELLED
);
593 Queries Bulk-Only device for maximum LUN number
597 DeviceExtension - Our device extension.
601 Maximum LUN number for device, or 0 if error occurred.
605 umss_bulkonly_get_maxlun(IN PUMSS_DEVICE_EXTENSION pdev_ext
)
611 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
615 usb_dbg_print(DBGLVL_MINIMUM
,
616 ("umss_bulkonly_get_maxlun(): Failed to allocate URB, setting max LUN to 0\n"));
621 // Build the get max lun command
622 UsbBuildVendorRequest(purb
, (pdev_ext
->dev_handle
| 0xffff), &max_lun
, sizeof(max_lun
), 0xb1, //class, interface, in
623 BULK_ONLY_GET_MAX_LUN
, 0, pdev_ext
->pif_desc
->bInterfaceNumber
, NULL
, NULL
, 0);
625 // Send get max lun command to device
626 status
= umss_sync_submit_urb(pdev_ext
, purb
);
628 if (status
!= STATUS_PENDING
)
630 usb_dbg_print(DBGLVL_MINIMUM
,
631 ("umss_bulkonly_get_maxlun(): Get Max LUN command failed, setting max LUN to 0!\n"));
639 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_get_maxlun(): Max LUN = %x\n", max_lun
));
645 umss_get_buffer(PUMSS_DEVICE_EXTENSION pdev_ext
, ULONG
* buf_length
)
649 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
)
651 buffer
= (PVOID
) pdev_ext
->io_packet
.data_buffer
;
652 *buf_length
= pdev_ext
->io_packet
.data_length
;
654 else if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_SENSE
)
656 buffer
= (PVOID
) pdev_ext
->io_packet
.sense_data
;
657 *buf_length
= pdev_ext
->io_packet
.sense_data_length
;
669 umss_bulkonly_build_sense_cdb(PUMSS_DEVICE_EXTENSION pdev_ext
, PCOMMAND_BLOCK_WRAPPER cbw
)
674 if (pdev_ext
== NULL
|| cbw
== NULL
)
678 RtlZeroMemory(cdb
, MAX_CDB_LENGTH
);
679 sub_class
= pdev_ext
->pif_desc
->bInterfaceSubClass
;
681 cdb
[0] = SFF_REQUEST_SENSEE
;
682 cdb
[1] = pdev_ext
->io_packet
.lun
<< 5;
687 case UMSS_SUBCLASS_SFF8070I
:
688 case UMSS_SUBCLASS_UFI
:
690 cbw
->bCBWLength
= 12;
693 case UMSS_SUBCLASS_RBC
:
694 case UMSS_SUBCLASS_SCSI_TCS
:
706 umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext
)
708 PCOMMAND_BLOCK_WRAPPER cbw
;
711 if (pdev_ext
== NULL
|| pdev_ext
->io_packet
.sense_data
== NULL
712 || pdev_ext
->io_packet
.sense_data_length
< 18)
713 return STATUS_INVALID_PARAMETER
;
715 pdev_ext
->retry
= TRUE
;
717 cbw
= usb_alloc_mem(NonPagedPool
, sizeof(COMMAND_BLOCK_WRAPPER
));
718 RtlZeroMemory(cbw
, sizeof(COMMAND_BLOCK_WRAPPER
));
719 pdev_ext
->io_packet
.flags
&= ~IOP_FLAG_STAGE_MASK
;
720 pdev_ext
->io_packet
.flags
|= IOP_FLAG_STAGE_SENSE
;
722 cbw
->dCBWSignature
= CBW_SIGNATURE
;
724 cbw
->dCBWDataTransferLength
= pdev_ext
->io_packet
.sense_data_length
;
725 cbw
->bmCBWFlags
= USB_DIR_IN
;
728 if (umss_bulkonly_build_sense_cdb(pdev_ext
, cbw
) == FALSE
)
732 return STATUS_UNSUCCESSFUL
;
735 status
= umss_bulk_transfer(pdev_ext
,
737 cbw
, sizeof(COMMAND_BLOCK_WRAPPER
), umss_bulkonly_send_cbw_completion
);
739 if (status
!= STATUS_PENDING
)
748 umss_clear_pass_through_length(PIO_PACKET io_packet
)
751 // clear the respective data length to meet request of scsi pass through requirement.
756 PIO_STACK_LOCATION cur_stack
;
757 PSCSI_PASS_THROUGH pass_through
;
758 PSCSI_PASS_THROUGH_DIRECT pass_through_direct
;
760 if (io_packet
== NULL
)
763 if ((io_packet
->flags
& IOP_FLAG_SCSI_CTRL_TRANSFER
) == 0)
767 if (io_packet
->flags
& IOP_FLAG_STAGE_SENSE
)
770 cur_stack
= IoGetCurrentIrpStackLocation(io_packet
->pirp
);
771 ctrl_code
= cur_stack
->Parameters
.DeviceIoControl
.IoControlCode
;
772 if (ctrl_code
== IOCTL_SCSI_PASS_THROUGH_DIRECT
)
774 pass_through_direct
= io_packet
->pirp
->AssociatedIrp
.SystemBuffer
;
776 pass_through_direct
->SenseInfoLength
= 0;
778 pass_through_direct
->DataTransferLength
= 0;
780 else if (ctrl_code
== IOCTL_SCSI_PASS_THROUGH
)
782 pass_through
= io_packet
->pirp
->AssociatedIrp
.SystemBuffer
;
784 pass_through
->SenseInfoLength
= 0;
786 pass_through
->DataTransferLength
= 0;