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

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