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

Last change on this file since 63 was 63, checked in by markus, 15 years ago

added feature byte to ATAPI commands; fixed request sense CDB

File size: 8.4 KB
Line 
1/******************************************************************************
2 * atapi.c - ATAPI command processing
3 *
4 * Copyright (c) 2010 Christian Mueller, Markus Thielen.
5 * Parts copied from/inspired by the Linux AHCI driver;
6 * those parts are (c) Linux AHCI/ATA maintainers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include "os2ahci.h"
24#include "ata.h"
25#include "atapi.h"
26
27/* -------------------------- macros and constants ------------------------- */
28
29/* ------------------------ typedefs and structures ------------------------ */
30
31/* -------------------------- function prototypes -------------------------- */
32
33static void atapi_req_sense_pp (IORBH _far *iorb);
34
35
36/* ------------------------ global/static variables ------------------------ */
37
38/* ----------------------------- start of code ----------------------------- */
39
40/******************************************************************************
41 * Get device or media geometry. This function is not expected to be called.
42 */
43int atapi_get_geometry(IORBH _far *iorb, int slot)
44{
45 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
46 return(-1);
47}
48
49/******************************************************************************
50 * Test whether unit is ready. This function is not expected to be called.
51 */
52int atapi_unit_ready(IORBH _far *iorb, int slot)
53{
54 dprintf("atapi_unit_ready called\n");
55 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
56 return(-1);
57}
58
59/******************************************************************************
60 * Read sectors from AHCI device.
61 */
62int atapi_read(IORBH _far *iorb, int slot)
63{
64 IORB_EXECUTEIO _far *io = (IORB_EXECUTEIO _far *) iorb;
65 ATAPI_CDB_12 cdb;
66 AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
67 USHORT count = io->BlockCount - io->BlocksXferred;
68 USHORT sg_indx;
69 USHORT sg_cnt;
70 int p = iorb_unit_port(iorb);
71 int d = iorb_unit_device(iorb);
72 int rc;
73
74 /* translate read command to SCSI/ATAPI READ12 command.
75 * READ12 seems to be the most supported READ variant - according to MMC,
76 * and its enough even for BluRay.
77 */
78 memset(&cdb, 0x00, sizeof(cdb));
79 cdb.cmd = ATAPI_CMD_READ_12;
80 SET_CDB_32(cdb.lba, io->RBA + io->BlocksXferred);
81
82 do {
83 /* update sector count (might have been updated due to S/G limitations) */
84 SET_CDB_32(cdb.trans_len, (u32) count);
85
86 /* update S/G count and index */
87 sg_indx = ata_get_sg_indx(io);
88 sg_cnt = io->cSGList - sg_indx;
89
90 /* issue command */
91 rc = ata_cmd(ai, p, d, slot, ATA_CMD_PACKET,
92 AP_ATAPI_CMD, (void _far *) &cdb, sizeof(cdb),
93 AP_SGLIST, io->pSGList + sg_indx, (u16) sg_cnt,
94 AP_DEVICE, 0x4000,
95 AP_FEATURES, 0x0001,
96 AP_END);
97
98 if (rc > 0) {
99 /* couldn't map all S/G elements */
100 ata_max_sg_cnt(io, sg_indx, (USHORT) rc, &sg_cnt, &count);
101 }
102 } while (rc > 0 && sg_cnt > 0);
103
104 if (rc == 0) {
105 add_workspace(iorb)->blocks = count;
106 add_workspace(iorb)->ppfunc = ata_read_pp;
107
108 } else if (rc > 0) {
109 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
110
111 } else {
112 iorb_seterr(iorb, IOERR_CMD_ADD_SOFTWARE_FAILURE);
113 }
114
115 return(rc);
116}
117
118/******************************************************************************
119 * Verify readability of sectors on AHCI device. This function is not expected
120 * to be called.
121 */
122int atapi_verify(IORBH _far *iorb, int slot)
123{
124 dprintf("atapi_verify called\n");
125 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
126 return(-1);
127}
128
129/******************************************************************************
130 * Write sectors to AHCI device. This function is not expected to be called.
131 */
132int atapi_write(IORBH _far *iorb, int slot)
133{
134 dprintf("atapi_write called\n");
135 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
136 return(-1);
137}
138
139/******************************************************************************
140 * Execute ATAPI command.
141 */
142int atapi_execute_cdb(IORBH _far *iorb, int slot)
143{
144 IORB_ADAPTER_PASSTHRU _far *pt = (IORB_ADAPTER_PASSTHRU _far *) iorb;
145 int rc;
146
147 /* we do not perform the S/G limitation recovery loop here:
148 * "ADDs are not required to iterate commands through the CDB PassThru
149 * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
150 */
151 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
152 iorb_unit_port(iorb),
153 iorb_unit_device(iorb),
154 slot, ATA_CMD_PACKET,
155 AP_ATAPI_CMD, (void _far *) pt->pControllerCmd,
156 pt->ControllerCmdLen,
157 AP_SGLIST, pt->pSGList, pt->cSGList,
158 AP_FEATURES, 0x0001,
159 AP_END);
160
161 if (rc) {
162 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
163 }
164
165 return(rc);
166}
167
168
169/******************************************************************************
170 * Request sense information for a failed command.
171 *
172 * NOTE: This function must be called right after an ATAPI command has failed
173 * and before any other commands are queued on the corresponding device.
174 * This function is typically called in the port restart context hook
175 * which is triggered by an AHCI error interrupt.
176 *
177 */
178int atapi_req_sense(IORBH _far *iorb, int slot)
179{
180 ADD_WORKSPACE _far *aws = add_workspace(iorb);
181 ATAPI_CDB_6 cdb;
182 int rc;
183
184 /* allocate sense buffer in ADD workspace */
185 aws->buf = malloc(ATAPI_SENSE_LEN);
186 if (aws->buf == NULL) {
187 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
188 return(-1);
189 }
190 memset(aws->buf, 0x00, ATAPI_SENSE_LEN);
191
192 /* prepare request sense command */
193 memset(&cdb, 0x00, sizeof(cdb));
194 cdb.cmd = ATAPI_CMD_REQUEST_SENSE;
195 cdb.trans_len = (u8) ATAPI_SENSE_LEN;
196
197 aws->ppfunc = atapi_req_sense_pp;
198 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
199 iorb_unit_port(iorb),
200 iorb_unit_device(iorb),
201 slot,
202 ATA_CMD_PACKET,
203 AP_ATAPI_CMD, (void _far*) &cdb, sizeof(cdb),
204 AP_VADDR, (void _far *) aws->buf, ATAPI_SENSE_LEN,
205 AP_END);
206
207 if (rc > 0) {
208 /* should never happen - we got 64 bytes here */
209 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
210
211 } else {
212 /* we failed to get info about an error -> return
213 * non specific device error
214 */
215 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
216 }
217
218 return(rc);
219}
220
221/******************************************************************************
222 * Post processing function for ATAPI request sense; examines the sense
223 * data returned and maps sense info to IORB error info.
224 */
225static void atapi_req_sense_pp(IORBH _far *iorb)
226{
227 ADD_WORKSPACE _far *aws = add_workspace(iorb);
228 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
229
230 /* map sense data to some IOERR_ value */
231 switch (ATAPI_GET_SENSE(psd)) {
232
233 case ASENSE_NO_SENSE:
234 case ASENSE_RECOVERED_ERROR:
235 /* no error */
236 break;
237
238 case ASENSE_NOT_READY:
239 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
240 break;
241
242 case ASENSE_UNIT_ATTENTION:
243 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
244 break;
245
246 case ASENSE_MEDIUM_ERROR:
247 iorb_seterr(iorb, IOERR_MEDIA);
248 break;
249
250 case ASENSE_ILLEGAL_REQUEST:
251 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
252 break;
253
254 case ASENSE_DATA_PROTECT:
255 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
256 break;
257
258 case ASENSE_BLANK_CHECK:
259 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
260 break;
261
262 case ASENSE_ABORTED_COMMAND:
263 case ASENSE_COPY_ABORTED:
264 iorb_seterr(iorb, IOERR_CMD_ABORTED);
265 break;
266
267 default:
268 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
269 break;
270 }
271
272 /* free sense buffer */
273 aws_free(aws);
274
275}
Note: See TracBrowser for help on using the repository browser.