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
);
189 //can only be called at passive level
191 umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext
, PURB purb
)
195 if (pdev_ext
== NULL
|| purb
== NULL
)
196 return STATUS_INVALID_PARAMETER
;
198 purb
->completion
= umss_sync_submit_urb_completion
;
199 purb
->context
= (PVOID
) pdev_ext
;
201 dev_mgr_register_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
, purb
);
202 status
= usb_submit_urb(pdev_ext
->dev_mgr
, purb
);
203 if (status
== STATUS_PENDING
)
205 KeWaitForSingleObject(&pdev_ext
->sync_event
, Executive
, KernelMode
, TRUE
, NULL
);
206 status
= purb
->status
;
209 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
215 umss_sync_submit_urb_completion(PURB purb
, PVOID context
)
217 PUMSS_DEVICE_EXTENSION pdev_ext
;
219 if (purb
== NULL
|| context
== NULL
)
222 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) context
;
223 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
224 KeSetEvent(&pdev_ext
->sync_event
, 0, FALSE
);
231 Worker function used to execute a reset recovery after a stall.
235 Reference - Our device extension.
243 umss_bulkonly_reset_recovery(IN PVOID reference
)
245 PUMSS_DEVICE_EXTENSION pdev_ext
;
248 DEV_HANDLE endp_handle
;
250 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) reference
;
251 usb_dbg_print(DBGLVL_MAXIMUM
, ("umss_bulkonly_reset_recovery(): entering...\n"));
252 // Steps for reset recovery:
253 // 1. Send device a mass storage reset command on the default endpoint.
254 // 2. Reset the bulk-in endpoint.
255 // 3. Reset the bulk-out endpoint.
256 // 4. Complete the original I/O request with error.
259 // Build the mass storage reset command
260 UsbBuildVendorRequest(&urb
, pdev_ext
->dev_handle
| 0xffff, //default pipe
261 NULL
, //no extra data
263 0x21, //class, interface
264 BULK_ONLY_MASS_STORAGE_RESET
,
266 pdev_ext
->pif_desc
->bInterfaceNumber
,
271 // Send mass storage reset command to device
272 status
= umss_sync_submit_urb(pdev_ext
, &urb
);
274 if (status
!= STATUS_SUCCESS
)
276 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_reset_recovery(): Reset Recovery failed!\n"));
280 //Reset Bulk-in endpoint
281 endp_handle
= usb_make_handle((pdev_ext
->dev_handle
>> 16), pdev_ext
->if_idx
, pdev_ext
->in_endp_idx
);
282 status
= umss_reset_pipe(pdev_ext
, endp_handle
);
284 if (!NT_SUCCESS(status
))
286 usb_dbg_print(DBGLVL_MINIMUM
,
287 ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-in endpoint\n"));
290 //Reset Bulk-out endpoint
291 endp_handle
= usb_make_handle((pdev_ext
->dev_handle
>> 16), pdev_ext
->if_idx
, pdev_ext
->out_endp_idx
);
292 status
= umss_reset_pipe(pdev_ext
, endp_handle
);
294 if (!NT_SUCCESS(status
))
296 usb_dbg_print(DBGLVL_MINIMUM
,
297 ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-out endpoint\n"));
300 umss_complete_request(pdev_ext
, status
);
306 Schedules a bulk data transfer to/from the device.
310 DeviceExtension - Our FDO's device extension.
318 umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext
)
321 ULONG data_buf_length
;
323 UCHAR trans_dir
= USB_DIR_IN
; // FIXME: Initialize this properly!
325 // Steps for data phase
326 // 1. Get data buffer fragment (either SGD list, flat buffer, or none).
327 // 2. Schedule data transfer if neccessary.
328 // 3. Repeat 1-2 until all data transferred, or endpoint stalls.
329 // 4. Move to status phase.
331 // Get next data buffer element, if any
332 data_buf
= umss_get_buffer(pdev_ext
, &data_buf_length
);
334 if (NULL
== data_buf
)
336 //No data to transfer, so move to status phase
337 umss_bulkonly_get_status(pdev_ext
);
341 // Schedule the data transfer.
342 // Calls umss_bulkonly_transfer_data_complete when transfer completes.
344 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
)
345 trans_dir
= (UCHAR
) ((pdev_ext
->cbw
.bmCBWFlags
& USB_DIR_IN
) ? USB_DIR_IN
: USB_DIR_OUT
);
346 else if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_SENSE
)
347 trans_dir
= USB_DIR_IN
;
349 if ((status
= umss_bulk_transfer(pdev_ext
,
353 umss_bulkonly_transfer_data_complete
)) != STATUS_PENDING
)
355 umss_complete_request(pdev_ext
, status
);
363 Completion handler for bulk data transfer requests.
366 umss_bulkonly_transfer_data_complete(PURB purb
, PVOID reference
)
369 PUMSS_DEVICE_EXTENSION pdev_ext
;
370 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) reference
;
372 status
= purb
->status
;
374 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
376 if (status
!= STATUS_SUCCESS
)
379 // clear the data length if this is a scsi pass through request
381 umss_clear_pass_through_length(&pdev_ext
->io_packet
);
383 // Device failed data phase
384 // Check if we need to clear stalled pipe
385 if (usb_halted(status
))
388 buf
= usb_alloc_mem(NonPagedPool
, 32);
391 buf
[0] = (ULONG
) pdev_ext
;
392 buf
[1] = (ULONG
) purb
->endp_handle
;
394 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_transfer_data_complete(): transfer data error!\n"));
395 if (!umss_schedule_workitem
396 ((PVOID
) buf
, umss_bulkonly_reset_pipe_and_get_status
, pdev_ext
->dev_mgr
,
397 pdev_ext
->dev_handle
))
399 usb_free_mem(buf
), buf
= NULL
;
400 usb_dbg_print(DBGLVL_MINIMUM
,
401 ("umss_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n"));
403 umss_complete_request(pdev_ext
, status
);
409 umss_complete_request(pdev_ext
, status
);
414 // Start next part of data phase
415 //umss_bulkonly_transfer_data( pdev_ext );
416 umss_bulkonly_get_status(pdev_ext
);
417 //umss_complete_request( pdev_ext, status );
423 return; // STATUS_MORE_PROCESSING_REQUIRED;
428 umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference
)
430 PUMSS_DEVICE_EXTENSION pdev_ext
;
431 DEV_HANDLE endp_handle
;
434 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_reset_pipe_and_get_status(): entering...\n"));
436 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) (((PULONG
) reference
)[0]);
437 endp_handle
= (DEV_HANDLE
) ((PULONG
) reference
)[1];
438 usb_free_mem(reference
);
441 // Reset the endpoint
442 if ((status
= umss_reset_pipe(pdev_ext
, endp_handle
)) != STATUS_SUCCESS
)
444 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe failed\n"));
445 umss_complete_request(pdev_ext
, status
);
448 // Data phase is finished since the endpoint stalled, so go to status phase
449 usb_dbg_print(DBGLVL_MINIMUM
,
450 ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe succeeds, continue to get status\n"));
451 umss_bulkonly_get_status(pdev_ext
);
455 umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext
)
458 // Schedule bulk transfer to get command status wrapper from device
459 status
= umss_bulk_transfer(pdev_ext
,
462 sizeof(COMMAND_STATUS_WRAPPER
), umss_bulkonly_get_status_complete
);
463 if (status
!= STATUS_PENDING
)
465 umss_complete_request(pdev_ext
, status
);
472 Completion handler for bulk data transfer request.
476 DeviceObject - Previous device object.
477 Irp - Irp used for sending command.
482 Driver-originated IRPs always return STATUS_MORE_PROCESSING_REQUIRED.
486 umss_bulkonly_get_status_complete(IN PURB purb
, IN PVOID context
)
489 PUMSS_DEVICE_EXTENSION pdev_ext
;
490 PCOMMAND_STATUS_WRAPPER csw
;
492 pdev_ext
= (PUMSS_DEVICE_EXTENSION
) context
;
493 status
= purb
->status
;
495 dev_mgr_remove_irp(pdev_ext
->dev_mgr
, pdev_ext
->io_packet
.pirp
);
497 csw
= &(pdev_ext
->csw
);
498 if (status
== STATUS_SUCCESS
&&
499 ((csw
->dCSWSignature
== CSW_SIGNATURE
) || OLYMPUS_CSW(pdev_ext
, csw
->dCSWSignature
)))
501 if (csw
->bCSWStatus
== CSW_STATUS_PASSED
)
503 // Received valid CSW with good status
505 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
&&
506 (pdev_ext
->io_packet
.flags
& IOP_FLAG_REQ_SENSE
) && pdev_ext
->io_packet
.sense_data
!= NULL
)
507 UMSS_FORGE_GOOD_SENSE(pdev_ext
->io_packet
.sense_data
)
508 umss_complete_request(pdev_ext
, STATUS_SUCCESS
);
510 else if (csw
->bCSWStatus
== CSW_STATUS_FAILED
)
512 // start a request sense if necessary
513 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_REQ_SENSE
) &&
514 (pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
)
516 if (umss_bulkonly_send_sense_req(pdev_ext
) != STATUS_PENDING
)
518 // don't know how to handle.
519 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
523 // fall through to free the urb
528 // error occurred, reset device
529 if (!umss_schedule_workitem
530 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
532 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
538 // error occurred, reset device
539 if (!umss_schedule_workitem
540 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
542 umss_complete_request(pdev_ext
, STATUS_IO_DEVICE_ERROR
);
546 else if ((status
!= STATUS_SUCCESS
) && (usb_halted(status
)) && (pdev_ext
->retry
))
548 // Device stalled CSW transfer, retry once before failing
550 pdev_ext
->retry
= FALSE
;
552 buf
= usb_alloc_mem(NonPagedPool
, 32);
555 buf
[0] = (ULONG
) pdev_ext
;
556 buf
[1] = (ULONG
) purb
->endp_handle
;
558 if (!umss_schedule_workitem
559 ((PVOID
) buf
, umss_bulkonly_reset_pipe_and_get_status
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
561 usb_free_mem(buf
), buf
= NULL
;
562 usb_dbg_print(DBGLVL_MINIMUM
,
563 ("umss_bulkonly_get_status_complete(): Failed to allocate work-item to reset pipe!\n"));
565 umss_complete_request(pdev_ext
, status
);
568 else if (status
!= STATUS_CANCELLED
)
570 // An error has occured. Reset the device.
571 if (!umss_schedule_workitem
572 ((PVOID
) pdev_ext
, umss_bulkonly_reset_recovery
, pdev_ext
->dev_mgr
, pdev_ext
->dev_handle
))
574 usb_dbg_print(DBGLVL_MINIMUM
,
575 ("umss_bulkonly_get_status_complete(): Failed to schedule work-item to reset pipe!\n"));
577 umss_complete_request(pdev_ext
, status
);
582 // the request is canceled
583 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_get_status_complete(): the request is canceled\n"));
584 umss_complete_request(pdev_ext
, STATUS_CANCELLED
);
596 Queries Bulk-Only device for maximum LUN number
600 DeviceExtension - Our device extension.
604 Maximum LUN number for device, or 0 if error occurred.
608 umss_bulkonly_get_maxlun(IN PUMSS_DEVICE_EXTENSION pdev_ext
)
614 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
618 usb_dbg_print(DBGLVL_MINIMUM
,
619 ("umss_bulkonly_get_maxlun(): Failed to allocate URB, setting max LUN to 0\n"));
624 // Build the get max lun command
625 UsbBuildVendorRequest(purb
, (pdev_ext
->dev_handle
| 0xffff), &max_lun
, sizeof(max_lun
), 0xb1, //class, interface, in
626 BULK_ONLY_GET_MAX_LUN
, 0, pdev_ext
->pif_desc
->bInterfaceNumber
, NULL
, NULL
, 0);
628 // Send get max lun command to device
629 status
= umss_sync_submit_urb(pdev_ext
, purb
);
631 if (status
!= STATUS_PENDING
)
633 usb_dbg_print(DBGLVL_MINIMUM
,
634 ("umss_bulkonly_get_maxlun(): Get Max LUN command failed, setting max LUN to 0!\n"));
642 usb_dbg_print(DBGLVL_MINIMUM
, ("umss_bulkonly_get_maxlun(): Max LUN = %x\n", max_lun
));
648 umss_get_buffer(PUMSS_DEVICE_EXTENSION pdev_ext
, ULONG
* buf_length
)
652 if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_NORMAL
)
654 buffer
= (PVOID
) pdev_ext
->io_packet
.data_buffer
;
655 *buf_length
= pdev_ext
->io_packet
.data_length
;
657 else if ((pdev_ext
->io_packet
.flags
& IOP_FLAG_STAGE_MASK
) == IOP_FLAG_STAGE_SENSE
)
659 buffer
= (PVOID
) pdev_ext
->io_packet
.sense_data
;
660 *buf_length
= pdev_ext
->io_packet
.sense_data_length
;
672 umss_bulkonly_build_sense_cdb(PUMSS_DEVICE_EXTENSION pdev_ext
, PCOMMAND_BLOCK_WRAPPER cbw
)
677 if (pdev_ext
== NULL
|| cbw
== NULL
)
681 RtlZeroMemory(cdb
, MAX_CDB_LENGTH
);
682 sub_class
= pdev_ext
->pif_desc
->bInterfaceSubClass
;
684 cdb
[0] = SFF_REQUEST_SENSEE
;
685 cdb
[1] = pdev_ext
->io_packet
.lun
<< 5;
690 case UMSS_SUBCLASS_SFF8070I
:
691 case UMSS_SUBCLASS_UFI
:
693 cbw
->bCBWLength
= 12;
696 case UMSS_SUBCLASS_RBC
:
697 case UMSS_SUBCLASS_SCSI_TCS
:
709 umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext
)
711 PCOMMAND_BLOCK_WRAPPER cbw
;
714 if (pdev_ext
== NULL
|| pdev_ext
->io_packet
.sense_data
== NULL
715 || pdev_ext
->io_packet
.sense_data_length
< 18)
716 return STATUS_INVALID_PARAMETER
;
718 pdev_ext
->retry
= TRUE
;
720 cbw
= usb_alloc_mem(NonPagedPool
, sizeof(COMMAND_BLOCK_WRAPPER
));
721 if (!cbw
) return STATUS_NO_MEMORY
;
723 RtlZeroMemory(cbw
, sizeof(COMMAND_BLOCK_WRAPPER
));
724 pdev_ext
->io_packet
.flags
&= ~IOP_FLAG_STAGE_MASK
;
725 pdev_ext
->io_packet
.flags
|= IOP_FLAG_STAGE_SENSE
;
727 cbw
->dCBWSignature
= CBW_SIGNATURE
;
729 cbw
->dCBWDataTransferLength
= pdev_ext
->io_packet
.sense_data_length
;
730 cbw
->bmCBWFlags
= USB_DIR_IN
;
733 if (umss_bulkonly_build_sense_cdb(pdev_ext
, cbw
) == FALSE
)
737 return STATUS_UNSUCCESSFUL
;
740 status
= umss_bulk_transfer(pdev_ext
,
742 cbw
, sizeof(COMMAND_BLOCK_WRAPPER
), umss_bulkonly_send_cbw_completion
);
744 if (status
!= STATUS_PENDING
)
753 umss_clear_pass_through_length(PIO_PACKET io_packet
)
756 // clear the respective data length to meet request of scsi pass through requirement.
761 PIO_STACK_LOCATION cur_stack
;
762 PSCSI_PASS_THROUGH pass_through
;
763 PSCSI_PASS_THROUGH_DIRECT pass_through_direct
;
765 if (io_packet
== NULL
)
768 if ((io_packet
->flags
& IOP_FLAG_SCSI_CTRL_TRANSFER
) == 0)
772 if (io_packet
->flags
& IOP_FLAG_STAGE_SENSE
)
775 cur_stack
= IoGetCurrentIrpStackLocation(io_packet
->pirp
);
776 ctrl_code
= cur_stack
->Parameters
.DeviceIoControl
.IoControlCode
;
777 if (ctrl_code
== IOCTL_SCSI_PASS_THROUGH_DIRECT
)
779 pass_through_direct
= io_packet
->pirp
->AssociatedIrp
.SystemBuffer
;
781 pass_through_direct
->SenseInfoLength
= 0;
783 pass_through_direct
->DataTransferLength
= 0;
785 else if (ctrl_code
== IOCTL_SCSI_PASS_THROUGH
)
787 pass_through
= io_packet
->pirp
->AssociatedIrp
.SystemBuffer
;
789 pass_through
->SenseInfoLength
= 0;
791 pass_through
->DataTransferLength
= 0;