SCSI_START_STOP_UNIT implementation question

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi All,

I was looking at do_start_stop() function in f_mass_storage.c and have a
small question regarding its implementation.
According to the SCSI spec if the LOEJ bit of the START_STOP_UNIT CBW is 1
and so is the START bit - the medium should be loaded. I don’t see this
implemented in do_start_stop(). According to the code if START = 1 but the
lun is closed we return error.  According to my understanding if START =1
and the lun is closed and LOEJ = 1 then the lun should be reopened.

Please advice.

Below is the implementation of do_start_stop() for your convenience.

static int do_start_stop(struct fsg_common *common)
{
                struct fsg_lun    *curlun = common->curlun;
                int                           loej, start;

                if (!curlun) {
                                return -EINVAL;
                } else if (!curlun->removable) {
                                curlun->sense_data = SS_INVALID_COMMAND;
                                return -EINVAL;
                } else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away
Immed */
                                   (common->cmnd[4] & ~0x03) != 0) { /* Mask
LoEj, Start */
                                curlun->sense_data =
SS_INVALID_FIELD_IN_CDB;
                                return -EINVAL;
                }

                loej  = common->cmnd[4] & 0x02;
                start = common->cmnd[4] & 0x01;

                /* Our emulation doesn't support mounting; the medium is
                * available for use as soon as it is loaded. */
                if (start) {
                                if (!fsg_lun_is_open(curlun)) {
                                                curlun->sense_data =
SS_MEDIUM_NOT_PRESENT;
                                                return -EINVAL;
                                }
                                return 0;
                }

                /* Are we allowed to unload the media? */
                if (curlun->prevent_medium_removal) {
                                LDBG(curlun, "unload attempt prevented\n");
                                curlun->sense_data =
SS_MEDIUM_REMOVAL_PREVENTED;
                                return -EINVAL;
                }

                if (!loej)
                                return 0;

                /* Simulate an unload/eject */
                if (common->ops && common->ops->pre_eject) {
                                int r = common->ops->pre_eject(common,
curlun,
                                                                            
           curlun - common->luns);
                                if (unlikely(r < 0))
                                                return r;
                                else if (r)
                                                return 0;
                }

                up_read(&common->filesem);
                down_write(&common->filesem);
                fsg_lun_close(curlun);
                up_write(&common->filesem);
                down_read(&common->filesem);

                return common->ops && common->ops->post_eject
                                ? min(0, common->ops->post_eject(common,
curlun,
                                      curlun - common->luns))
                                : 0;
}

Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

?פט÷{.nַ+‰·?®‰­†+%?ֻ?±י?¶¥?w?÷{.nַ+‰·¥?{±‏כ‏)ם…זטw*jg¬±¨¶‰????¢j?¾«‏G«?י?¢¸¢·¦j:+v‰¨?wטj״m¶??‏ר¯ש®w¥‏?א‏f£¢·h??ג?ת?†?¥



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux