xref: /haiku/src/add-ons/kernel/busses/scsi/usb/proto_common.c (revision cd552c7a15cc10c36dae8d7439ba1d6c0bb168c5)
1 /*
2  * Copyright (c) 2003-2005 by Siarzhuk Zharski <imker@gmx.li>
3  * Distributed under the terms of the BSD License.
4  *
5  */
6 
7 #include <string.h>
8 
9 #include "usb_scsi.h"
10 
11 #include "device_info.h"
12 #include "proto_common.h"
13 #include "tracing.h"
14 #include "usb_defs.h"
15 #include "scsi_commands.h"
16 
17 /**
18   \fn:bulk_callback
19   \param cookie:???
20   \param status:???
21   \param data:???
22   \param actual_len:???
23   \return:???
24 
25   ???
26 */
27 void bulk_callback(void  *cookie,
28                    uint32 status,
29                    void  *data,
30                    uint32 actual_len)
31 {
32   TRACE_BULK_CALLBACK(status, actual_len);
33   if(cookie){
34     usb_device_info *udi = (usb_device_info *)cookie;
35     udi->status = status;
36     udi->data = data;
37     udi->actual_len = actual_len;
38     if(udi->status != B_CANCELED)
39       release_sem(udi->trans_sem);
40   }
41 }
42 
43 /**
44   \fn:exec_io
45   \param udi: ???
46   \return:???
47 
48   ???
49 */
50 status_t process_data_io(usb_device_info *udi,
51                            //sg_buffer *sgb,
52                            iovec *sg_data, int32 sg_count,
53                            EDirection dir)
54 {
55   status_t status = B_OK;
56   usb_pipe pipe = (dir == eDirIn) ? udi->pipe_in : udi->pipe_out;
57 //  TRACE_DATA_IO_SG(data_sg, sglist_count);
58   status = (*udi->usb_m->queue_bulk_v)(pipe, sg_data, sg_count, bulk_callback, udi);
59   if(status == B_OK){
60     status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/);
61     if(status == B_OK){
62       status = udi->status;
63       if(udi->status == B_DEV_STALLED){
64         status_t st=(*udi->usb_m->clear_feature)(pipe, USB_FEATURE_ENDPOINT_HALT);
65         TRACE_ALWAYS("clear_on_STALL:%08x\n",st);
66       }
67     }else{
68       TRACE_ALWAYS("process_data_io:acquire_sem failed:%08x\n", status);
69       (*udi->usb_m->cancel_queued_transfers)(pipe);
70     }
71   } else {
72     TRACE_ALWAYS("process_data_io:queue_bulk_v failed:%08x\n", status);
73   }
74   TRACE_DATA_IO("process_data_io:processed:%d;status:%08x\n", udi->actual_len, status);
75   return status;
76 }
77 
78 void transfer_callback(struct _usb_device_info *udi,
79                                     CCB_SCSIIO *ccbio,
80                                          int32 residue,
81                                      status_t status)
82 {
83   ccbio->cam_resid = residue;
84   switch(status){
85   case B_OK:
86     ccbio->cam_ch.cam_status = CAM_REQ_CMP;
87     break;
88   case B_CMD_FAILED:
89   case B_CMD_UNKNOWN:{
90       size_t sense_data_len = (0 != ccbio->cam_sense_len) ?
91                                      ccbio->cam_sense_len : SSD_MIN_SIZE;
92       uchar *sense_data_ptr = (NULL != ccbio->cam_sense_ptr) ?
93                                         ccbio->cam_sense_ptr : (uchar*)&udi->autosense_data;
94       uint8 lun = ((ccbio->cam_ch.cam_target_lun) << CMD_LUN_SHIFT) & CMD_LUN;
95       scsi_cmd_generic_6 cmd = { REQUEST_SENSE, {lun, 0}, sense_data_len, 0};
96       /* transform command as required by protocol */
97       uint8 *rcmd    = udi->scsi_command_buf;
98       uint8 rcmdlen  = sizeof(udi->scsi_command_buf);
99       iovec sense_sg = { sense_data_ptr, sense_data_len };
100       TRACE("transfer_callback:requesting sense information "
101                                               "due status:%08x\n", status);
102       memset(&udi->autosense_data, 0, SSD_FULL_SIZE); /* just to be sure */
103       if(B_OK != (*udi->transform_m->transform)(udi, (uint8 *)&cmd, sizeof(cmd), &rcmd, &rcmdlen)){
104         TRACE_ALWAYS("transfer_callback: REQUEST SENSE command transform failed\n");
105         ccbio->cam_ch.cam_status = CAM_IDE; //?????????
106         break;
107       }
108     /* transfer command to device. SCSI status will be handled in callback */
109       (*udi->protocol_m->transfer)(udi, rcmd, rcmdlen, &sense_sg, 1, sense_data_len,
110                                                                eDirIn, ccbio, sense_callback);
111     }
112     break;
113   case B_CMD_WIRE_FAILED:
114     ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR;
115     break;
116   default:
117     TRACE_ALWAYS("transfer_callback:unknown status:%08x\n", status);
118     ccbio->cam_ch.cam_status = CAM_IDE;
119     break;
120   }
121 }
122 
123 void sense_callback(struct _usb_device_info *udi,
124                                  CCB_SCSIIO *ccbio,
125                                        int32 residue,
126                                     status_t status)
127 {
128   ccbio->cam_sense_resid = residue;
129   switch(status){
130   case B_CMD_UNKNOWN:
131   case B_CMD_FAILED:
132   case B_OK:{
133       bool b_own_data = (ccbio->cam_sense_ptr == NULL);
134       scsi_sense_data *sense_data = b_own_data ?
135                           &udi->autosense_data : (scsi_sense_data *)ccbio->cam_sense_ptr;
136       int data_len = (ccbio->cam_sense_len != 0) ? ccbio->cam_sense_len : SSD_MIN_SIZE;
137       TRACE_SENSE_DATA((uint8*)sense_data, data_len);
138       if((sense_data->flags & SSD_KEY) == SSD_KEY_NO_SENSE){
139         /* no problems. normal case for CB handling */
140         TRACE("sense_callback: key OK\n");
141         ccbio->cam_ch.cam_status = CAM_REQ_CMP;
142       } else {
143         if(!b_own_data){ /* we have used CCBIO provided buffer for sense data */
144           TRACE("sense_callback:sense info OK????:%08x \n", sense_data);
145           ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR | CAM_AUTOSNS_VALID;
146           ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION;
147         } else {
148           /*TODO: ?????????????????????????????????????? */
149           ccbio->cam_ch.cam_status = CAM_REQ_CMP;
150    //       ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR /*| CAM_AUTOSNS_VALID*/;
151    //       ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION;
152           TRACE("sense_callback: sense still not handled...\n");
153         }
154       }
155     }
156     break;
157   default:
158     TRACE_ALWAYS("sense_callback:unknown status:%08x\n", status);
159   case B_CMD_WIRE_FAILED:
160     ccbio->cam_ch.cam_status = CAM_AUTOSENSE_FAIL;
161     break;
162   }
163 }
164 
165