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

Last change on this file since 169 was 155, checked in by David Azarewicz, 12 years ago

debugging updates

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