SCSI work flow

来源:互联网 发布:高三励志语录知乎 编辑:程序博客网 时间:2024/04/28 01:06

static int queuecommand_lck(structscsi_cmnd *srb,

                            void(*done)(struct scsi_cmnd *))

{

         structus_data *us = host_to_us(srb->device->host);

 

         /*check for state-transition errors */

         if(us->srb != NULL) {

                   printk(KERN_ERRUSB_STORAGE "Error in %s: us->srb = %p\n",

                            __func__,us->srb);

                   returnSCSI_MLQUEUE_HOST_BUSY;

         }

 

         /*fail the command if we are disconnecting */

         if(test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {

                   usb_stor_dbg(us,"Fail command during disconnect\n");

                   srb->result= DID_NO_CONNECT << 16;

                   done(srb);

                   return0;

         }

 

         /*enqueue the command and wake up the control thread */

         srb->scsi_done= done;

         us->srb= srb;

         complete(&us->cmnd_ready);

 

         return0;

}

 

SCSI 有一个单独的thread来处理所收到的SCSIcommand, 这一个thread 处于sleep状态, 只到有收到新的command或者移除SCSI module才会被wakeup.

有新的command进来时, queuecommand_lck() function调用complete()function来trigger 该thread.

 

/* Second part of general USB mass-storageprobing */

int usb_stor_probe2(struct us_data *us)

{

……

         /*Acquire all the other resources and add the host */

         result= usb_stor_acquire_resources(us);

……

}

 

/* Initialize all the dynamic resources weneed */

static int usb_stor_acquire_resources(structus_data *us)

{

         intp;

         structtask_struct *th;

 

         us->current_urb= usb_alloc_urb(0, GFP_KERNEL);

         if(!us->current_urb) {

                   usb_stor_dbg(us,"URB allocation failed\n");

                   return-ENOMEM;

         }

 

         /*Just before we start our control thread, initialize

          * the device if it needs initialization */

         if(us->unusual_dev->initFunction) {

                   p= us->unusual_dev->initFunction(us);

                   if(p)

                            returnp;

         }

 

         /*Start up our control thread */

         th= kthread_run(usb_stor_control_thread, us,"usb-storage");

         if(IS_ERR(th)) {

                   dev_warn(&us->pusb_intf->dev,

                                     "Unableto start control thread\n");

                   returnPTR_ERR(th);

         }

         us->ctl_thread= th;

 

         return0;

}

 

 

static int usb_stor_control_thread(void *__us)

{

         structus_data *us = (struct us_data *)__us;

         structScsi_Host *host = us_to_host(us);

 

         for(;;) {

                   usb_stor_dbg(us,"*** thread sleeping\n");

                   if(wait_for_completion_interruptible(&us->cmnd_ready))

                            break;

 

                   usb_stor_dbg(us,"*** thread awakened\n");

 

                   /*lock the device pointers */

                   mutex_lock(&(us->dev_mutex));

……

}

……

                   /*we've got a command, let's do it! */

                   else{

                            US_DEBUG(usb_stor_show_command(us,us->srb));

                            us->proto_handler(us->srb,us);

                            usb_mark_last_busy(us->pusb_dev);

                   }

……

}

 

 

void usb_stor_transparent_scsi_command(structscsi_cmnd *srb,

                                            struct us_data *us)

{

         /*send the command to the transport layer */

         usb_stor_invoke_transport(srb, us);

}

 

 

/* Invoke the transport and basicerror-handling/recovery methods

 *

 *This is used by the protocol layers to actually send the message to

 *the device and receive the response.

 */

void usb_stor_invoke_transport(structscsi_cmnd *srb, struct us_data *us)

{

         intneed_auto_sense;

         intresult;

 

         /*send the command to the transport layer */

         scsi_set_resid(srb,0);

         result= us->transport(srb, us);

……

}

 

int usb_stor_Bulk_transport(structscsi_cmnd *srb, struct us_data *us)

{

         structbulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;

         structbulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;

         unsignedint transfer_length = scsi_bufflen(srb);

         unsignedint residue;

         intresult;

         intfake_sense = 0;

         unsignedint cswlen;

         unsignedint cbwlen = US_BULK_CB_WRAP_LEN;

         ……

         /*See flow chart on pg 15 of the Bulk Only Transport spec for

          * an explanation of how this code works.

          */

 

         /*get CSW for device status */

         usb_stor_dbg(us,"Attempting to get CSW...\n");

         result= usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,

                                     bcs,US_BULK_CS_WRAP_LEN, &cswlen);

 

         /*Some broken devices add unnecessary zero-length packets to the

          * end of their data transfers.  Such packets show up as 0-length

          * CSWs. If we encounter such a thing, try to read the CSW again.

          */

         if(result == USB_STOR_XFER_SHORT && cswlen == 0) {

                   usb_stor_dbg(us,"Received 0-length CSW; retrying...\n");

                   result= usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,

                                     bcs,US_BULK_CS_WRAP_LEN, &cswlen);

         }

         ……

         /*based on the status code, we report good or bad */

         switch(bcs->Status) {

                   caseUS_BULK_STAT_OK:

                            /*device babbled -- return fake sense data */

                            if(fake_sense) {

                                     memcpy(srb->sense_buffer,

                                            usb_stor_sense_invalidCDB,

                                            sizeof(usb_stor_sense_invalidCDB));

                                     returnUSB_STOR_TRANSPORT_NO_SENSE;

                            }

 

                            /*command good -- note that data could be short */

                            returnUSB_STOR_TRANSPORT_GOOD;

 

                   caseUS_BULK_STAT_FAIL:

                            /*command failed */

                            returnUSB_STOR_TRANSPORT_FAILED;

 

                   caseUS_BULK_STAT_PHASE:

                            /*phase error -- note that a transport reset will be

                             * invoked by the invoke_transport() function

                             */

                            returnUSB_STOR_TRANSPORT_ERROR;

         }

 

         /*we should never get here, but if we do, we're in trouble */

         returnUSB_STOR_TRANSPORT_ERROR;

}

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 没有检测到sd卡怎么办 e站图片配额用尽怎么办 内存卡密码忘了怎么办 电脑上酷狗音乐播放失败怎么办 播放失败不支持该文件怎么办 手机山寨云资源失效怎么办 支付密码输错了怎么办 微信密码锁定了怎么办 电脑网易云音乐闪退怎么办 逆战耳机电流声怎么办 肠道感染一直吃药治不好怎么办 如果24小时以后还没到账该怎么办 在游戏平台充值没到账该怎么办 充值豪华黄钻没到账该怎么办 起点签到签满了怎么办 ipad锁屏声音小怎么办 扣扣邮箱文件超大了怎么办 网易邮箱图片已过期怎么办 邮箱里面的文件过期了怎么办 邮箱发的文件过期了怎么办 邮箱发送的文件过期怎么办 小米4s开不开机怎么办 小米平板关机后开不开机怎么办 公司老板跑路了社保怎么办 公司老板跑路社保怎么办 公司被公安局查封社保怎么办 小米四开不了机怎么办 小米的手机后壳裂了怎么办 公司没钱拖欠员工社保怎么办 小米note充不进去电怎么办 公司欠社保没交怎么办 公司不给转社保怎么办 小米note充电特别慢怎么办 小米小米note2充电慢怎么办 小米note充电红灯不闪烁怎么办 小米note充电红灯闪烁怎么办 小米note2突然充电慢怎么办 充电小米note2手机闪烁怎么办 小米6x上网慢怎么办 小米5数据上网慢怎么办 小米5c照相模糊怎么办