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

Last change on this file since 204 was 204, checked in by David Azarewicz, 5 years ago

Variable name changes.

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