Line 0
Link Here
|
|
|
1 |
--- libk3bdevice/k3bscsicommand_bsd.cpp.orig 2012-03-22 03:26:44.000000000 +0600 |
2 |
+++ libk3bdevice/k3bscsicommand_bsd.cpp 2012-03-22 03:11:30.000000000 +0600 |
3 |
@@ -17,6 +17,7 @@ |
4 |
#include "k3bdevice.h" |
5 |
|
6 |
#include <k3bdebug.h> |
7 |
+#include <kdebug.h> |
8 |
|
9 |
#include <stdio.h> |
10 |
#include <errno.h> |
11 |
@@ -24,41 +25,44 @@ |
12 |
#include <cam/scsi/scsi_message.h> |
13 |
#include <cam/scsi/scsi_pass.h> |
14 |
|
15 |
-#define ERRCODE(s) ((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13])) |
16 |
-#define EMEDIUMTYPE EINVAL |
17 |
-#define ENOMEDIUM ENODEV |
18 |
-#define CREAM_ON_ERRNO(s) do { \ |
19 |
- switch ((s)[12]) \ |
20 |
- { case 0x04: errno=EAGAIN; break; \ |
21 |
- case 0x20: errno=ENODEV; break; \ |
22 |
- case 0x21: if ((s)[13]==0) errno=ENOSPC; \ |
23 |
- else errno=EINVAL; \ |
24 |
- break; \ |
25 |
- case 0x30: errno=EMEDIUMTYPE; break; \ |
26 |
- case 0x3A: errno=ENOMEDIUM; break; \ |
27 |
- } \ |
28 |
-} while(0) |
29 |
+namespace /*anonymous*/ |
30 |
+{ |
31 |
+ inline int sense_to_err( const struct scsi_sense_data& s ) |
32 |
+ { |
33 |
+ int errorCode, senseKey, addSenseCode, addSenseCodeQual; |
34 |
+ scsi_extract_sense( (struct scsi_sense_data*) &s, &errorCode, |
35 |
+ &senseKey, &addSenseCode, &addSenseCodeQual ); |
36 |
+ return (errorCode << 24) | (senseKey << 16) | |
37 |
+ (addSenseCode << 8) | addSenseCodeQual; |
38 |
+ } |
39 |
+} |
40 |
|
41 |
|
42 |
|
43 |
class K3bDevice::ScsiCommand::Private |
44 |
{ |
45 |
+ typedef union ccb CCB; |
46 |
public: |
47 |
- union ccb ccb; |
48 |
+ Private(); |
49 |
+ int transport( const Device* device, TransportDirection dir, void* data, size_t len ); |
50 |
+ unsigned char& operator[]( size_t i ); |
51 |
+ void clear(); |
52 |
+ const CCB& get_ccb() { return ccb; } |
53 |
+ |
54 |
+ private: |
55 |
+ CCB ccb; |
56 |
}; |
57 |
|
58 |
|
59 |
void K3bDevice::ScsiCommand::clear() |
60 |
{ |
61 |
- memset (&d->ccb,0,sizeof(ccb)); |
62 |
+ d->clear(); |
63 |
} |
64 |
|
65 |
|
66 |
unsigned char& K3bDevice::ScsiCommand::operator[]( size_t i ) |
67 |
{ |
68 |
- if( d->ccb.csio.cdb_len < i+1 ) |
69 |
- d->ccb.csio.cdb_len = i+1; |
70 |
- return d->ccb.csio.cdb_io.cdb_bytes[i]; |
71 |
+ return (*d)[i]; |
72 |
} |
73 |
|
74 |
int K3bDevice::ScsiCommand::transport( TransportDirection dir, |
75 |
@@ -79,130 +83,103 @@ |
76 |
m_device->usageUnlock(); |
77 |
return -1; |
78 |
} |
79 |
- d->ccb.ccb_h.path_id = m_device->handle()->path_id; |
80 |
- d->ccb.ccb_h.target_id = m_device->handle()->target_id; |
81 |
- d->ccb.ccb_h.target_lun = m_device->handle()->target_lun; |
82 |
- |
83 |
- k3bDebug() << "(K3bDevice::ScsiCommand) transport command " << QString::number((int)d->ccb.csio.cdb_io.cdb_bytes[0], 16) << ", length: " << (int)d->ccb.csio.cdb_len << endl; |
84 |
- int ret=0; |
85 |
- int direction = CAM_DEV_QFRZDIS; |
86 |
- if (!len) |
87 |
- direction |= CAM_DIR_NONE; |
88 |
- else |
89 |
- direction |= (dir & TR_DIR_READ)?CAM_DIR_IN : CAM_DIR_OUT; |
90 |
- cam_fill_csio (&(d->ccb.csio), 1, 0 /* NULL */, direction, MSG_SIMPLE_Q_TAG, (u_int8_t *)data, len, sizeof(d->ccb.csio.sense_data), d->ccb.csio.cdb_len, 30*1000); |
91 |
- unsigned char * sense = (unsigned char *)&d->ccb.csio.sense_data; |
92 |
|
93 |
- ret = cam_send_ccb(m_device->handle(), &d->ccb); |
94 |
+ int ret = d->transport( m_device, dir, data, len ); |
95 |
+ if( ret != 0 ) { |
96 |
+ const struct scsi_sense_data& s = d->get_ccb().csio.sense_data; |
97 |
+ int errorCode, senseKey, addSenseCode, addSenseCodeQual; |
98 |
+ scsi_extract_sense( (struct scsi_sense_data*) &s, &errorCode, &senseKey, |
99 |
+ &addSenseCode, &addSenseCodeQual ); |
100 |
+ debugError( d->get_ccb().csio.cdb_io.cdb_bytes[0], |
101 |
+ errorCode, |
102 |
+ senseKey, |
103 |
+ addSenseCode, |
104 |
+ addSenseCodeQual ); |
105 |
+ } |
106 |
+ |
107 |
+ if( needToClose ) |
108 |
+ m_device->close(); |
109 |
+ m_device->usageUnlock(); |
110 |
|
111 |
- if (ret < 0) { |
112 |
- k3bDebug() << "(K3bDevice::ScsiCommand) transport failed: " << ret << endl; |
113 |
+ return ret; |
114 |
+} |
115 |
|
116 |
- if( needToClose ) |
117 |
- m_device->close(); |
118 |
+K3bDevice::ScsiCommand::Private::Private() |
119 |
+ { |
120 |
+ clear(); |
121 |
+ } |
122 |
|
123 |
- m_device->usageUnlock(); |
124 |
+void K3bDevice::ScsiCommand::Private::clear() |
125 |
+ { |
126 |
+ memset( &ccb, 0, sizeof(ccb) ); |
127 |
+ } |
128 |
|
129 |
- struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; |
130 |
- debugError( d->ccb.csio.cdb_io.cdb_bytes[0], |
131 |
- senset->error_code & SSD_ERRCODE, |
132 |
- senset->flags & SSD_KEY, |
133 |
- senset->add_sense_code, |
134 |
- senset->add_sense_code_qual ); |
135 |
- |
136 |
- int result = (((senset->error_code & SSD_ERRCODE)<<24) & 0xF000 | |
137 |
- ((senset->flags & SSD_KEY)<<16) & 0x0F00 | |
138 |
- (senset->add_sense_code<<8) & 0x00F0 | |
139 |
- (senset->add_sense_code_qual) & 0x000F ); |
140 |
+ unsigned char& K3bDevice::ScsiCommand::Private::operator[]( size_t i ) |
141 |
+ { |
142 |
+ if( ccb.csio.cdb_len < i + 1 ) |
143 |
+ ccb.csio.cdb_len = i + 1; |
144 |
+ return ccb.csio.cdb_io.cdb_bytes[i]; |
145 |
+ } |
146 |
|
147 |
- return result ? result : ret; |
148 |
+ int K3bDevice::ScsiCommand::Private::transport( const Device* device, TransportDirection dir, void* data, size_t len ) |
149 |
+ { |
150 |
+ ccb.ccb_h.path_id = device->handle()->path_id; |
151 |
+ ccb.ccb_h.target_id = device->handle()->target_id; |
152 |
+ ccb.ccb_h.target_lun = device->handle()->target_lun; |
153 |
+ |
154 |
+ k3bDebug() << "(K3bDevice::ScsiCommand) transport command " << commandString(ccb.csio.cdb_io.cdb_bytes[0]) |
155 |
+ << " (" << QString::number((int)ccb.csio.cdb_io.cdb_bytes[0], 16) << "), length: " << (int)ccb.csio.cdb_len; |
156 |
+ int direction = CAM_DEV_QFRZDIS; |
157 |
+ if (!len) |
158 |
+ direction |= CAM_DIR_NONE; |
159 |
+ else |
160 |
+ direction |= (dir & TR_DIR_READ) ? CAM_DIR_IN : CAM_DIR_OUT; |
161 |
+ |
162 |
+ cam_fill_csio( &(ccb.csio), 1, NULL, direction, MSG_SIMPLE_Q_TAG, (uint8_t*)data, len, sizeof(ccb.csio.sense_data), ccb.csio.cdb_len, 30*1000 ); |
163 |
+ int ret = cam_send_ccb( device->handle(), &ccb ); |
164 |
+ if( ret < 0 ) { |
165 |
+ kdError() << "(K3bDevice::ScsiCommand) transport cam_send_ccb failed: ret = " << ret |
166 |
+ << ", errno = " << errno << ", cam_errbuf = " << cam_errbuf; |
167 |
+ return 1; |
168 |
} |
169 |
|
170 |
- else if ((d->ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { |
171 |
- if( needToClose ) |
172 |
- m_device->close(); |
173 |
- m_device->usageUnlock(); |
174 |
+ else if( (ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP ) { |
175 |
+ k3bDebug() << "(K3bDevice::ScsiCommand) transport succeeded"; |
176 |
return 0; |
177 |
} |
178 |
|
179 |
- errno = EIO; |
180 |
- // FreeBSD 5-CURRENT since 2003-08-24, including 5.2 fails to |
181 |
- // pull sense data automatically, at least for ATAPI transport, |
182 |
- // so I reach for it myself... |
183 |
- if ((d->ccb.csio.scsi_status==SCSI_STATUS_CHECK_COND) && |
184 |
- !(d->ccb.ccb_h.status&CAM_AUTOSNS_VALID)) |
185 |
- { |
186 |
- u_int8_t _sense[18]; |
187 |
- u_int32_t resid=d->ccb.csio.resid; |
188 |
- |
189 |
- memset(_sense,0,sizeof(_sense)); |
190 |
- |
191 |
- operator[](0) = 0x03; // REQUEST SENSE |
192 |
- d->ccb.csio.cdb_io.cdb_bytes[4] = sizeof(_sense); |
193 |
- d->ccb.csio.cdb_len = 6; |
194 |
- d->ccb.csio.ccb_h.flags |= CAM_DIR_IN|CAM_DIS_AUTOSENSE; |
195 |
- d->ccb.csio.data_ptr = _sense; |
196 |
- d->ccb.csio.dxfer_len = sizeof(_sense); |
197 |
- d->ccb.csio.sense_len = 0; |
198 |
- |
199 |
- ret = cam_send_ccb(m_device->handle(), &d->ccb); |
200 |
+ k3bDebug() << "(K3bDevice::ScsiCommand) transport command failed: scsi_status = " << QString::number(ccb.csio.scsi_status, 16); |
201 |
|
202 |
- d->ccb.csio.resid = resid; |
203 |
- if (ret<0) |
204 |
+ if( ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND && |
205 |
+ !(ccb.ccb_h.status & CAM_AUTOSNS_VALID) && |
206 |
+ ccb.csio.cdb_io.cdb_bytes[0] != MMC_REQUEST_SENSE ) |
207 |
+ { |
208 |
+ k3bDebug() << "(K3bDevice::ScsiCommand) transport requesting sense data"; |
209 |
+ |
210 |
+ struct scsi_sense_data sense; |
211 |
+ ScsiCommand::Private cmd; |
212 |
+ cmd[0] = MMC_REQUEST_SENSE; |
213 |
+ cmd[4] = SSD_MIN_SIZE; |
214 |
+ cmd[5] = 0; // Necessary to set the proper command length |
215 |
+ |
216 |
+ memset( &sense, 0, sizeof(sense) ); |
217 |
+ ret = cmd.transport( device, TR_DIR_READ, &sense, SSD_MIN_SIZE ); |
218 |
+ if( ret < 0 ) |
219 |
{ |
220 |
- k3bDebug() << "(K3bDevice::ScsiCommand) transport failed (2): " << ret << endl; |
221 |
- ret = -1; |
222 |
- struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; |
223 |
- debugError( d->ccb.csio.cdb_io.cdb_bytes[0], |
224 |
- senset->error_code & SSD_ERRCODE, |
225 |
- senset->flags & SSD_KEY, |
226 |
- senset->add_sense_code, |
227 |
- senset->add_sense_code_qual ); |
228 |
- |
229 |
- if( needToClose ) |
230 |
- m_device->close(); |
231 |
- m_device->usageUnlock(); |
232 |
- |
233 |
- return -1; |
234 |
+ kdWarning() << "(K3bDevice::ScsiCommand) transport getting sense data failed: " << ret; |
235 |
+ return 1; |
236 |
} |
237 |
- if ((d->ccb.ccb_h.status&CAM_STATUS_MASK) != CAM_REQ_CMP) |
238 |
- { |
239 |
- k3bDebug() << "(K3bDevice::ScsiCommand) transport failed (3): " << ret << endl; |
240 |
- errno=EIO,-1; |
241 |
- ret = -1; |
242 |
- struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; |
243 |
- debugError( d->ccb.csio.cdb_io.cdb_bytes[0], |
244 |
- senset->error_code & SSD_ERRCODE, |
245 |
- senset->flags & SSD_KEY, |
246 |
- senset->add_sense_code, |
247 |
- senset->add_sense_code_qual ); |
248 |
- |
249 |
- if( needToClose ) |
250 |
- m_device->close(); |
251 |
- m_device->usageUnlock(); |
252 |
|
253 |
- return -1; |
254 |
- } |
255 |
- |
256 |
- memcpy(sense,_sense,sizeof(_sense)); |
257 |
+ ccb.csio.sense_data = sense; |
258 |
+ ccb.ccb_h.status |= CAM_AUTOSNS_VALID; |
259 |
} |
260 |
|
261 |
- ret = ERRCODE(sense); |
262 |
- k3bDebug() << "(K3bDevice::ScsiCommand) transport failed (4): " << ret << endl; |
263 |
- if (ret == 0) |
264 |
- ret = -1; |
265 |
- else |
266 |
- CREAM_ON_ERRNO(((unsigned char *)&d->ccb.csio.sense_data)); |
267 |
- struct scsi_sense_data* senset = (struct scsi_sense_data*)sense; |
268 |
- debugError( d->ccb.csio.cdb_io.cdb_bytes[0], |
269 |
- senset->error_code & SSD_ERRCODE, |
270 |
- senset->flags & SSD_KEY, |
271 |
- senset->add_sense_code, |
272 |
- senset->add_sense_code_qual ); |
273 |
- |
274 |
- if( needToClose ) |
275 |
- m_device->close(); |
276 |
- m_device->usageUnlock(); |
277 |
- |
278 |
+ if( !(ccb.ccb_h.status & CAM_AUTOSNS_VALID) ) |
279 |
+ k3bDebug() << "(K3bDevice::ScsiCommand) sense data is not available"; |
280 |
+ |
281 |
+ ret = sense_to_err(ccb.csio.sense_data); |
282 |
+ if( ret == 0 ) |
283 |
+ ret = 1; |
284 |
+ k3bDebug() << "(K3bDevice::ScsiCommand) transport failed: " << ret; |
285 |
return ret; |
286 |
} |