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

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

fixed ATAPI packet commands; added cache flush in shutdown handler; allow write cache for NCQ commands

File size: 11.0 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);
34static int atapi_pad_cdb (u8 _far *cmd_in, u16 cmd_in_len,
35 u8 _far *cmd_out, u16 _far *cmd_out_len);
36
37/* ------------------------ global/static variables ------------------------ */
38
39/* ----------------------------- start of code ----------------------------- */
40
41/******************************************************************************
42 * Get device or media geometry. This function is not expected to be called.
43 */
44int atapi_get_geometry(IORBH _far *iorb, int slot)
45{
46 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
47 return(-1);
48}
49
50/******************************************************************************
51 * Test whether unit is ready. This function is not expected to be called.
52 */
53int atapi_unit_ready(IORBH _far *iorb, int slot)
54{
55 dprintf("atapi_unit_ready called\n");
56 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
57 return(-1);
58}
59
60/******************************************************************************
61 * Read sectors from AHCI device.
62 */
63int atapi_read(IORBH _far *iorb, int slot)
64{
65 IORB_EXECUTEIO _far *io = (IORB_EXECUTEIO _far *) iorb;
66 ATAPI_CDB_12 cdb;
67 AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
68 USHORT count = io->BlockCount - io->BlocksXferred;
69 USHORT sg_indx;
70 USHORT sg_cnt;
71 int p = iorb_unit_port(iorb);
72 int d = iorb_unit_device(iorb);
73 int rc;
74
75 /* translate read command to SCSI/ATAPI READ12 command.
76 * READ12 seems to be the most supported READ variant - according to MMC,
77 * and it's enough even for BluRay.
78 */
79 memset(&cdb, 0x00, sizeof(cdb));
80 cdb.cmd = ATAPI_CMD_READ_12;
81 SET_CDB_32(cdb.lba, io->RBA + io->BlocksXferred);
82
83 do {
84 /* update sector count (might have been updated due to S/G limitations) */
85 SET_CDB_32(cdb.trans_len, (u32) count);
86
87 /* update S/G count and index */
88 sg_indx = ata_get_sg_indx(io);
89 sg_cnt = io->cSGList - sg_indx;
90
91 /* issue command */
92 rc = ata_cmd(ai, p, d, slot, ATA_CMD_PACKET,
93 AP_ATAPI_CMD, (void _far *) &cdb, sizeof(cdb),
94 AP_SGLIST, io->pSGList + sg_indx, (u16) sg_cnt,
95 AP_DEVICE, 0x4000,
96 AP_FEATURES, ATAPI_FEAT_DMA | ATAPI_FEAT_DMA_TO_HOST,
97 AP_END);
98
99 if (rc > 0) {
100 /* couldn't map all S/G elements */
101 ata_max_sg_cnt(io, sg_indx, (USHORT) rc, &sg_cnt, &count);
102 }
103 } while (rc > 0 && sg_cnt > 0);
104
105 if (rc == 0) {
106 add_workspace(iorb)->blocks = count;
107 add_workspace(iorb)->ppfunc = ata_read_pp;
108
109 } else if (rc > 0) {
110 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
111
112 } else {
113 iorb_seterr(iorb, IOERR_CMD_ADD_SOFTWARE_FAILURE);
114 }
115
116 return(rc);
117}
118
119/******************************************************************************
120 * Verify readability of sectors on AHCI device. This function is not expected
121 * to be called.
122 */
123int atapi_verify(IORBH _far *iorb, int slot)
124{
125 dprintf("atapi_verify called\n");
126 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
127 return(-1);
128}
129
130/******************************************************************************
131 * Write sectors to AHCI device. This function is not expected to be called.
132 */
133int atapi_write(IORBH _far *iorb, int slot)
134{
135 dprintf("atapi_write called\n");
136 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
137 return(-1);
138}
139
140/******************************************************************************
141 * Execute ATAPI command.
142 */
143int atapi_execute_cdb(IORBH _far *iorb, int slot)
144{
145 IORB_ADAPTER_PASSTHRU _far *pt = (IORB_ADAPTER_PASSTHRU _far *) iorb;
146 int rc;
147 u8 cdb[ATAPI_MAX_CDB_LEN];
148 u16 cdb_len;
149
150 if (pt->ControllerCmdLen > ATAPI_MAX_CDB_LEN) {
151 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
152 return -1;
153 }
154 /* AHCI requires 12 or 16 byte commands */
155 atapi_pad_cdb(pt->pControllerCmd, pt->ControllerCmdLen,
156 (u8 _far *) cdb, (u16 _far *) &cdb_len);
157
158 /* we do not perform the S/G limitation recovery loop here:
159 * "ADDs are not required to iterate commands through the CDB PassThru
160 * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
161 */
162 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
163 iorb_unit_port(iorb),
164 iorb_unit_device(iorb),
165 slot, ATA_CMD_PACKET,
166 AP_ATAPI_CMD, (void _far *) cdb, cdb_len,
167 AP_SGLIST, pt->pSGList, pt->cSGList,
168 AP_WRITE, !(pt->Flags & PT_DIRECTION_IN),
169 AP_FEATURES, ATAPI_FEAT_DMA,
170 AP_FEATURES, (pt->Flags & PT_DIRECTION_IN) ? ATAPI_FEAT_DMA_TO_HOST : 0,
171 AP_END);
172
173 if (rc) {
174 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
175 }
176
177 return(rc);
178}
179
180
181/******************************************************************************
182 * Request sense information for a failed command.
183 *
184 * NOTE: This function must be called right after an ATAPI command has failed
185 * and before any other commands are queued on the corresponding device.
186 * This function is typically called in the port restart context hook
187 * which is triggered by an AHCI error interrupt.
188 *
189 */
190int atapi_req_sense(IORBH _far *iorb, int slot)
191{
192 ADD_WORKSPACE _far *aws = add_workspace(iorb);
193 int rc;
194 u8 cdb[ATAPI_MIN_CDB_LEN];
195 ATAPI_CDB_6 _far *pcdb = (ATAPI_CDB_6 _far *) cdb;
196
197 /* allocate sense buffer in ADD workspace */
198 aws->buf = malloc(ATAPI_SENSE_LEN);
199 if (aws->buf == NULL) {
200 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
201 return(-1);
202 }
203 memset(aws->buf, 0x00, ATAPI_SENSE_LEN);
204
205 /* prepare request sense command */
206 memset(cdb, 0x00, sizeof(cdb));
207 pcdb->cmd = ATAPI_CMD_REQUEST_SENSE;
208 pcdb->trans_len = (u8) ATAPI_SENSE_LEN;
209
210 aws->ppfunc = atapi_req_sense_pp;
211 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
212 iorb_unit_port(iorb),
213 iorb_unit_device(iorb),
214 slot,
215 ATA_CMD_PACKET,
216 AP_ATAPI_CMD, (void _far*) cdb, sizeof(cdb),
217 AP_VADDR, (void _far *) aws->buf, ATAPI_SENSE_LEN,
218 AP_FEATURES, ATAPI_FEAT_DMA,
219 AP_END);
220
221 if (rc > 0) {
222 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
223
224 } else if (rc < 0) {
225 /* we failed to get info about an error -> return
226 * non specific device error
227 */
228 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
229 }
230
231 return(rc);
232}
233
234/******************************************************************************
235 * Post processing function for ATAPI request sense; examines the sense
236 * data returned and maps sense info to IORB error info.
237 */
238static void atapi_req_sense_pp(IORBH _far *iorb)
239{
240 ADD_WORKSPACE _far *aws = add_workspace(iorb);
241 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
242
243 ddphex(psd, sizeof(psd), "sense buffer:\n");
244
245 /* map sense data to some IOERR_ value */
246 switch (ATAPI_GET_SENSE(psd)) {
247
248 case ASENSE_NO_SENSE:
249 case ASENSE_RECOVERED_ERROR:
250 /* no error */
251 break;
252
253 case ASENSE_NOT_READY:
254 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
255 break;
256
257 case ASENSE_UNIT_ATTENTION:
258 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
259 break;
260
261 case ASENSE_MEDIUM_ERROR:
262 iorb_seterr(iorb, IOERR_MEDIA);
263 break;
264
265 case ASENSE_ILLEGAL_REQUEST:
266 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
267 break;
268
269 case ASENSE_DATA_PROTECT:
270 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
271 break;
272
273 case ASENSE_BLANK_CHECK:
274 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
275 break;
276
277 case ASENSE_ABORTED_COMMAND:
278 case ASENSE_COPY_ABORTED:
279 iorb_seterr(iorb, IOERR_CMD_ABORTED);
280 break;
281
282 default:
283 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
284 break;
285 }
286
287 /* mark IORB as complete */
288 aws->complete = 1;
289}
290
291/******************************************************************************
292 * pad atapi commands; AHCI requires ATAPI commands to be either 12 or
293 * 16 bytes in length. This func converts commands that have a 12 byte
294 * equivalent, and pads the others to 12 bytes.
295 * cmd_out buffer is expected to be ATAPI_MAX_CDB_LEN in size.
296 * returns 0 on success, != 0 if the command can't be converted.
297 */
298int atapi_pad_cdb(u8 _far *cmd_in, u16 cmd_in_len,
299 u8 _far *cmd_out, u16 _far *cmd_out_len)
300{
301 ATAPI_CDB_12 _far *p12;
302
303 if (cmd_in_len == ATAPI_MIN_CDB_LEN || cmd_in_len == ATAPI_MAX_CDB_LEN) {
304 /* command does not need to be converted */
305 memcpy(cmd_out, cmd_in, cmd_in_len);
306 *cmd_out_len = cmd_in_len;
307 return 0;
308 }
309
310 memset(cmd_out, 0x00, ATAPI_MAX_CDB_LEN);
311 p12 = (ATAPI_CDB_12 _far *) cmd_out;
312 /* we always convert to 12 byte CDBs */
313 *cmd_out_len = ATAPI_MIN_CDB_LEN;
314
315 /* check if command can be converted */
316 switch (cmd_in[0]) {
317
318 case ATAPI_CMD_READ_6:
319 case ATAPI_CMD_WRITE_6:
320 /* convert from 6 to 12 byte equivalent */
321 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
322 p12->flags = cmd_in[1] & 0xc0; /* 6byte cmds have no flags (FUA etc.) */
323 SET_CDB_32(p12->lba, (u32) cmd_in[3] | (u32) cmd_in[2] << 8 |
324 (u32) (cmd_in[1] & 0x1f) << 16);
325 SET_CDB_32(p12->trans_len, (u32) cmd_in[4]);
326 p12->control = cmd_in[5];
327 break;
328
329 case ATAPI_CMD_READ_10:
330 case ATAPI_CMD_WRITE_10:
331 /* convert from 10 byte to 12 byte equivalent */
332 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
333 p12->flags = cmd_in[1];
334 memcpy(p12->lba, cmd_in + 2, 4);
335 SET_CDB_32(p12->trans_len, (u32) GET_CDB_16(cmd_in + 7));
336 p12->control = cmd_in[9];
337 break;
338
339 default:
340 /* pad with zeroes to 12 bytes */
341 memset(cmd_out, 0x00, ATAPI_MIN_CDB_LEN);
342 memcpy(cmd_out, cmd_in, cmd_in_len);
343 break;
344 }
345
346 return 0;
347}
348
Note: See TracBrowser for help on using the repository browser.