source: trunk/src/os2ahci/atapi.c@ 111

Last change on this file since 111 was 111, checked in by Markus Thielen, 14 years ago

added support for os2trace (buggy; messages get swallowed); reverted last change that ignored unknown command line arguments

File size: 15.2 KB
Line 
1/******************************************************************************
2 * atapi.c - ATAPI command processing
3 *
4 * Copyright (c) 2011 thi.guten Software Development
5 * Copyright (c) 2011 Mensys B.V.
6 *
7 * Authors: Christian Mueller, Markus Thielen
8 *
9 * Parts copied from/inspired by the Linux AHCI driver;
10 * those parts are (c) Linux AHCI/ATA maintainers
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include "os2ahci.h"
28#include "ata.h"
29#include "atapi.h"
30
31/* need this for the SCSI status block */
32#include <scsi.h>
33
34/* -------------------------- macros and constants ------------------------- */
35
36/* ------------------------ typedefs and structures ------------------------ */
37
38/* -------------------------- function prototypes -------------------------- */
39
40static void atapi_req_sense_pp (IORBH _far *iorb);
41static int atapi_pad_cdb (u8 _far *cmd_in, u16 cmd_in_len,
42 u8 _far *cmd_out, u16 _far *cmd_out_len);
43
44/* ------------------------ global/static variables ------------------------ */
45
46/* ----------------------------- start of code ----------------------------- */
47
48/******************************************************************************
49 * Get device or media geometry. This function is not expected to be called.
50 */
51int atapi_get_geometry(IORBH _far *iorb, int slot)
52{
53 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
54 return(-1);
55}
56
57/******************************************************************************
58 * Test whether unit is ready. This function is not expected to be called.
59 */
60int atapi_unit_ready(IORBH _far *iorb, int slot)
61{
62 ddprintf("atapi_unit_ready called\n");
63 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
64 return(-1);
65}
66
67/******************************************************************************
68 * Read sectors from AHCI device.
69 */
70int atapi_read(IORBH _far *iorb, int slot)
71{
72 IORB_EXECUTEIO _far *io = (IORB_EXECUTEIO _far *) iorb;
73 ATAPI_CDB_12 cdb;
74 AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
75 USHORT count = io->BlockCount - io->BlocksXferred;
76 USHORT sg_indx;
77 USHORT sg_cnt;
78 int p = iorb_unit_port(iorb);
79 int d = iorb_unit_device(iorb);
80 int rc;
81
82 if (io->BlockCount == 0) {
83 /* NOP; return -1 without error in IORB to indicate success */
84 return(-1);
85 }
86
87 if (add_workspace(iorb)->unaligned) {
88 /* unaligned S/G addresses present; need to use double buffers */
89 return(atapi_read_unaligned(iorb, slot));
90 }
91
92 /* translate read command to SCSI/ATAPI READ12 command.
93 * READ12 seems to be the most supported READ variant - according to MMC,
94 * and it's enough even for BluRay.
95 */
96 memset(&cdb, 0x00, sizeof(cdb));
97 cdb.cmd = ATAPI_CMD_READ_12;
98 SET_CDB_32(cdb.lba, io->RBA + io->BlocksXferred);
99
100 do {
101 /* update sector count (might have been updated due to S/G limitations) */
102 SET_CDB_32(cdb.trans_len, (u32) count);
103
104 /* update S/G count and index */
105 sg_indx = ata_get_sg_indx(io);
106 sg_cnt = io->cSGList - sg_indx;
107
108 /* issue command */
109 rc = ata_cmd(ai, p, d, slot, ATA_CMD_PACKET,
110 AP_ATAPI_CMD, (void _far *) &cdb, sizeof(cdb),
111 AP_SGLIST, io->pSGList + sg_indx, (u16) sg_cnt,
112 AP_DEVICE, 0x40,
113 AP_FEATURES, ATAPI_FEAT_DMA | ATAPI_FEAT_DMA_TO_HOST,
114 AP_END);
115
116 if (rc > 0) {
117 /* couldn't map all S/G elements */
118 ata_max_sg_cnt(io, sg_indx, (USHORT) rc, &sg_cnt, &count);
119 }
120 } while (rc > 0 && sg_cnt > 0);
121
122 if (rc == 0) {
123 add_workspace(iorb)->blocks = count;
124 add_workspace(iorb)->ppfunc = ata_read_pp;
125
126 } else if (rc > 0) {
127 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
128
129 } else if (rc == ATA_CMD_UNALIGNED_ADDR) {
130 /* unaligned S/G addresses detected; need to use double buffers */
131 add_workspace(iorb)->unaligned = 1;
132 return(atapi_read_unaligned(iorb, slot));
133
134 } else {
135 iorb_seterr(iorb, IOERR_CMD_ADD_SOFTWARE_FAILURE);
136 }
137
138 return(rc);
139}
140
141/******************************************************************************
142 * Read sectors from AHCI device with unaligned S/G element addresses. AHCI
143 * only allows aligned S/G addresses while OS/2 doesn't have these kind of
144 * restrictions. This doesn't happen very often but when it does, we need to
145 * use a transfer buffer and copy the data manually.
146 */
147int atapi_read_unaligned(IORBH _far *iorb, int slot)
148{
149 IORB_EXECUTEIO _far *io = (IORB_EXECUTEIO _far *) iorb;
150 ADD_WORKSPACE _far *aws = add_workspace(iorb);
151 ATAPI_CDB_12 cdb;
152 AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
153 int p = iorb_unit_port(iorb);
154 int d = iorb_unit_device(iorb);
155 int rc;
156
157 /* translate read command to SCSI/ATAPI READ12 command.
158 * READ12 seems to be the most supported READ variant - according to MMC,
159 * and it's enough even for BluRay.
160 */
161 memset(&cdb, 0x00, sizeof(cdb));
162 cdb.cmd = ATAPI_CMD_READ_12;
163 SET_CDB_32(cdb.lba, io->RBA + io->BlocksXferred);
164 SET_CDB_32(cdb.trans_len, 1);
165
166 /* allocate transfer buffer */
167 if ((aws->buf = malloc(io->BlockSize)) == NULL) {
168 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
169 return(-1);
170 }
171
172 rc = ata_cmd(ai, p, d, slot, ATA_CMD_PACKET,
173 AP_ATAPI_CMD, (void _far *) &cdb, sizeof(cdb),
174 AP_VADDR, (void _far *) aws->buf, (u16) io->BlockSize,
175 AP_DEVICE, 0x40,
176 AP_FEATURES, ATAPI_FEAT_DMA | ATAPI_FEAT_DMA_TO_HOST,
177 AP_END);
178
179 if (rc == 0) {
180 add_workspace(iorb)->blocks = 1;
181 add_workspace(iorb)->ppfunc = ata_read_pp;
182
183 } else if (rc > 0) {
184 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
185
186 } else {
187 iorb_seterr(iorb, IOERR_CMD_ADD_SOFTWARE_FAILURE);
188 }
189
190 return(rc);
191}
192
193/******************************************************************************
194 * Verify readability of sectors on AHCI device. This function is not expected
195 * to be called.
196 */
197int atapi_verify(IORBH _far *iorb, int slot)
198{
199 ddprintf("atapi_verify called\n");
200 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
201 return(-1);
202}
203
204/******************************************************************************
205 * Write sectors to AHCI device. This function is not expected to be called.
206 */
207int atapi_write(IORBH _far *iorb, int slot)
208{
209 ddprintf("atapi_write called\n");
210 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
211 return(-1);
212}
213
214/******************************************************************************
215 * Execute ATAPI command.
216 */
217int atapi_execute_cdb(IORBH _far *iorb, int slot)
218{
219 IORB_ADAPTER_PASSTHRU _far *pt = (IORB_ADAPTER_PASSTHRU _far *) iorb;
220 int rc;
221 u8 cdb[ATAPI_MAX_CDB_LEN];
222 u16 cdb_len;
223
224 if (pt->ControllerCmdLen > ATAPI_MAX_CDB_LEN) {
225 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
226 return -1;
227 }
228 /* AHCI requires 12 or 16 byte commands */
229 atapi_pad_cdb(pt->pControllerCmd, pt->ControllerCmdLen,
230 (u8 _far *) cdb, (u16 _far *) &cdb_len);
231
232 if (cdb[0] == 0x12 || cdb[0] == 0x5a) {
233 /* somebody sets the direction flag incorrectly for those commands */
234 pt->Flags |= PT_DIRECTION_IN;
235 }
236
237 /* we do not perform the S/G limitation recovery loop here:
238 * "ADDs are not required to iterate commands through the CDB PassThru
239 * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
240 */
241 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb), iorb_unit_port(iorb),
242 iorb_unit_device(iorb), slot, ATA_CMD_PACKET,
243 AP_ATAPI_CMD, (void _far *) cdb, cdb_len,
244 AP_SGLIST, pt->pSGList, pt->cSGList,
245 AP_WRITE, !(pt->Flags & PT_DIRECTION_IN),
246 AP_FEATURES, ATAPI_FEAT_DMA,
247 AP_FEATURES, (pt->Flags & PT_DIRECTION_IN) ? ATAPI_FEAT_DMA_TO_HOST : 0,
248 AP_END);
249
250 if (rc) {
251 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
252 }
253
254 return(rc);
255}
256
257
258/******************************************************************************
259 * Request sense information for a failed command.
260 *
261 * NOTE: This function must be called right after an ATAPI command has failed
262 * and before any other commands are queued on the corresponding device.
263 * This function is typically called in the port restart context hook
264 * which is triggered by an AHCI error interrupt.
265 *
266 */
267int atapi_req_sense(IORBH _far *iorb, int slot)
268{
269 SCSI_STATUS_BLOCK _far *ssb;
270 ADD_WORKSPACE _far *aws = add_workspace(iorb);
271 int rc;
272 u8 cdb[ATAPI_MIN_CDB_LEN];
273 ATAPI_CDB_6 _far *pcdb = (ATAPI_CDB_6 _far *) cdb;
274 size_t sense_buf_len = ATAPI_SENSE_LEN;
275
276 if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
277 iorb->StatusBlockLen >= sizeof(*ssb) && iorb->pStatusBlock != 0) {
278
279 /* don't request sense data if caller asked us not to; the flag
280 * STATUS_DISABLE_REQEST_SENSE is not defined in the old DDK we've been
281 * using so we'll use the hard-coded value (0x0008) */
282 ssb = (SCSI_STATUS_BLOCK _far *) (((u32) iorb & 0xffff0000U) +
283 (u16) iorb->pStatusBlock);
284 if (ssb->Flags & 0x0008U) {
285 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
286 return(-1);
287 }
288
289 /* if the sense buffer requested is larger than our default, adjust
290 * the length accordingly to satisfy the caller's requirements. */
291 if (ssb->SenseData != NULL && ssb->ReqSenseLen > sense_buf_len) {
292 sense_buf_len = ssb->ReqSenseLen;
293 }
294 }
295
296 /* allocate sense buffer in ADD workspace */
297 if ((aws->buf = malloc(sense_buf_len)) == NULL) {
298 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
299 return(-1);
300 }
301 memset(aws->buf, 0x00, sense_buf_len);
302
303 /* prepare request sense command */
304 memset(cdb, 0x00, sizeof(cdb));
305 pcdb->cmd = ATAPI_CMD_REQUEST_SENSE;
306 pcdb->trans_len = (u8) sense_buf_len;
307
308 aws->ppfunc = atapi_req_sense_pp;
309 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
310 iorb_unit_port(iorb),
311 iorb_unit_device(iorb),
312 slot,
313 ATA_CMD_PACKET,
314 AP_ATAPI_CMD, (void _far*) cdb, sizeof(cdb),
315 AP_VADDR, (void _far *) aws->buf, sense_buf_len,
316 AP_FEATURES, ATAPI_FEAT_DMA,
317 AP_END);
318
319 if (rc > 0) {
320 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
321
322 } else if (rc < 0) {
323 /* we failed to get info about an error -> return
324 * non specific device error
325 */
326 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
327 }
328
329 return(rc);
330}
331
332/******************************************************************************
333 * Post processing function for ATAPI request sense; examines the sense
334 * data returned and maps sense info to IORB error info.
335 */
336static void atapi_req_sense_pp(IORBH _far *iorb)
337{
338 SCSI_STATUS_BLOCK _far *ssb;
339 ADD_WORKSPACE _far *aws = add_workspace(iorb);
340 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
341
342 dphex(psd, sizeof(*psd), TRACE_MINOR_SENSE_BUF, "sense buffer:\n");
343
344 if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
345 iorb->StatusBlockLen >= sizeof(*ssb) && iorb->pStatusBlock != 0) {
346
347 /* copy sense data to IORB */
348 ssb = (SCSI_STATUS_BLOCK _far *) (((u32) iorb & 0xffff0000U) +
349 (u16) iorb->pStatusBlock);
350 ssb->AdapterErrorCode = 0;
351 ssb->TargetStatus = SCSI_STAT_CHECKCOND;
352 ssb->ResidualLength = 0;
353 memset(ssb->AdapterDiagInfo, 0x00, sizeof(ssb->AdapterDiagInfo));
354
355 if (ssb->SenseData != NULL) {
356 memcpy(ssb->SenseData, psd, ssb->ReqSenseLen);
357 ssb->Flags |= STATUS_SENSEDATA_VALID;
358 }
359 iorb->Status |= IORB_STATUSBLOCK_AVAIL;
360 }
361
362 /* map sense data to some IOERR_ value */
363 switch (ATAPI_GET_SENSE(psd)) {
364
365 case ASENSE_NO_SENSE:
366 case ASENSE_RECOVERED_ERROR:
367 /* no error; this shouldn't happen because we'll only call
368 * atapi_req_sense() if we received an error interrupt */
369 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
370 break;
371
372 case ASENSE_NOT_READY:
373 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
374 break;
375
376 case ASENSE_UNIT_ATTENTION:
377 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
378 break;
379
380 case ASENSE_MEDIUM_ERROR:
381 iorb_seterr(iorb, IOERR_MEDIA);
382 break;
383
384 case ASENSE_ILLEGAL_REQUEST:
385 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
386 break;
387
388 case ASENSE_DATA_PROTECT:
389 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
390 break;
391
392 case ASENSE_BLANK_CHECK:
393 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
394 break;
395
396 case ASENSE_ABORTED_COMMAND:
397 case ASENSE_COPY_ABORTED:
398 iorb_seterr(iorb, IOERR_CMD_ABORTED);
399 break;
400
401 default:
402 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
403 break;
404 }
405
406 /* mark IORB as complete */
407 aws->complete = 1;
408}
409
410/******************************************************************************
411 * Pad ATAPI commands; AHCI requires ATAPI commands to be either 12 or
412 * 16 bytes in length. This func converts commands that have a 12 byte
413 * equivalent, and pads the others to 12 bytes.
414 * cmd_out buffer is expected to be ATAPI_MAX_CDB_LEN in size.
415 * returns 0 on success, != 0 if the command can't be converted.
416 */
417int atapi_pad_cdb(u8 _far *cmd_in, u16 cmd_in_len,
418 u8 _far *cmd_out, u16 _far *cmd_out_len)
419{
420 ATAPI_CDB_12 _far *p12;
421 u32 tmp;
422
423 if (cmd_in_len == ATAPI_MIN_CDB_LEN || cmd_in_len == ATAPI_MAX_CDB_LEN) {
424 /* command does not need to be converted */
425 memcpy(cmd_out, cmd_in, cmd_in_len);
426 *cmd_out_len = cmd_in_len;
427 return 0;
428 }
429
430 memset(cmd_out, 0x00, ATAPI_MAX_CDB_LEN);
431 p12 = (ATAPI_CDB_12 _far *) cmd_out;
432 /* we always convert to 12 byte CDBs */
433 *cmd_out_len = ATAPI_MIN_CDB_LEN;
434
435 /* check if command can be converted */
436 switch (cmd_in[0]) {
437
438 case ATAPI_CMD_READ_6:
439 case ATAPI_CMD_WRITE_6:
440 /* convert from 6 to 12 byte equivalent */
441 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
442 p12->flags = cmd_in[1] & 0xc0; /* 6byte cmds have no flags (FUA etc.) */
443 tmp = GET_CDB_24(cmd_in + 1) & 0x1fffffUL;
444 SET_CDB_32(p12->lba, tmp);
445 SET_CDB_32(p12->trans_len, cmd_in[4]);
446 p12->control = cmd_in[5];
447 break;
448
449 case ATAPI_CMD_READ_10:
450 case ATAPI_CMD_WRITE_10:
451 /* convert from 10 byte to 12 byte equivalent */
452 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
453 p12->flags = cmd_in[1];
454 p12->control = cmd_in[9];
455 memcpy(p12->lba, cmd_in + 2, 4);
456 tmp = GET_CDB_16(cmd_in + 7);
457 SET_CDB_32(p12->trans_len, tmp);
458 break;
459
460 default:
461 /* pad with zeroes to 12 bytes */
462 memset(cmd_out, 0x00, ATAPI_MIN_CDB_LEN);
463 memcpy(cmd_out, cmd_in, cmd_in_len);
464 break;
465 }
466
467 return 0;
468}
469
Note: See TracBrowser for help on using the repository browser.