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

Last change on this file since 75 was 75, checked in by chris, 15 years ago

atapi.c:

  • Extended workaround for incorrect direction bits to "mode sense" commands; now there's no bus lockup and subsequent port reset during boot anymore.

ahci.c:

  • Fixed timeout handling -- we use milliseconds internally while the IORB uses seconds
  • Replaced IORB completion code with a macro to improve IORB debug logging

ctxhook.c:

  • Fixed an issue which would fail to clear a port command bit if the IORB in question was not the one that caused the port engine to stop. As a result, a subsequent sanity check caused an unecessary port reset. The result was that ejecting a CD via WPS' drive object would cause the next command to fail, a reset to occur and the tray to close again right away
  • Replaced IORB completion code with a macro to improve IORB debug logging
  • added spinlocks around aws_free()

os2ahci.c

  • Replaced IORB completion code with a macro to improve IORB debug logging
  • Improved IORB debug logging to make it easier to spot the lifetime of an IORB without having to read between the lines

os2ahci.h

  • Added macro to complete an IORB including the corresponding debug log
File size: 12.7 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
153 if (pt->ControllerCmdLen > ATAPI_MAX_CDB_LEN) {
154 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
155 return -1;
156 }
157 /* AHCI requires 12 or 16 byte commands */
158 atapi_pad_cdb(pt->pControllerCmd, pt->ControllerCmdLen,
159 (u8 _far *) cdb, (u16 _far *) &cdb_len);
160
161 if (cdb[0] == 0x12 || cdb[0] == 0x5a) {
162 /* somebody sets the direction flag incorrectly for those commands */
163 pt->Flags |= PT_DIRECTION_IN;
164 }
165
166 /* we do not perform the S/G limitation recovery loop here:
167 * "ADDs are not required to iterate commands through the CDB PassThru
168 * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
169 */
170 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
171 iorb_unit_port(iorb),
172 iorb_unit_device(iorb),
173 slot, ATA_CMD_PACKET,
174 AP_ATAPI_CMD, (void _far *) cdb, cdb_len,
175 AP_SGLIST, pt->pSGList, pt->cSGList,
176 AP_WRITE, !(pt->Flags & PT_DIRECTION_IN),
177 AP_FEATURES, ATAPI_FEAT_DMA,
178 AP_FEATURES, (pt->Flags & PT_DIRECTION_IN) ? ATAPI_FEAT_DMA_TO_HOST : 0,
179 AP_END);
180
181 if (rc) {
182 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
183 }
184
185 return(rc);
186}
187
188
189/******************************************************************************
190 * Request sense information for a failed command.
191 *
192 * NOTE: This function must be called right after an ATAPI command has failed
193 * and before any other commands are queued on the corresponding device.
194 * This function is typically called in the port restart context hook
195 * which is triggered by an AHCI error interrupt.
196 *
197 */
198int atapi_req_sense(IORBH _far *iorb, int slot)
199{
200 SCSI_STATUS_BLOCK _far *ssb;
201 ADD_WORKSPACE _far *aws = add_workspace(iorb);
202 int rc;
203 u8 cdb[ATAPI_MIN_CDB_LEN];
204 ATAPI_CDB_6 _far *pcdb = (ATAPI_CDB_6 _far *) cdb;
205
206 if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
207 iorb->StatusBlockLen >= sizeof(*ssb) && iorb->pStatusBlock != 0) {
208
209 /* don't request sense data if caller asked us not to; the flag
210 * STATUS_DISABLE_REQEST_SENSE is not defined in the old DDK we've been
211 * using so we'll use the hard-coded value (0x0008) */
212 ssb = (SCSI_STATUS_BLOCK _far *) (((u32) iorb & 0xffff0000U) +
213 (u16) iorb->pStatusBlock);
214 if (ssb->Flags & 0x0008U) {
215 /* set a generic error code and skip automatic sense code handling */
216 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
217 return(-1);
218 }
219 }
220
221 /* allocate sense buffer in ADD workspace */
222 if ((aws->buf = malloc(ATAPI_SENSE_LEN)) == NULL) {
223 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
224 return(-1);
225 }
226 memset(aws->buf, 0x00, ATAPI_SENSE_LEN);
227
228 /* prepare request sense command */
229 memset(cdb, 0x00, sizeof(cdb));
230 pcdb->cmd = ATAPI_CMD_REQUEST_SENSE;
231 pcdb->trans_len = (u8) ATAPI_SENSE_LEN;
232
233 aws->ppfunc = atapi_req_sense_pp;
234 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
235 iorb_unit_port(iorb),
236 iorb_unit_device(iorb),
237 slot,
238 ATA_CMD_PACKET,
239 AP_ATAPI_CMD, (void _far*) cdb, sizeof(cdb),
240 AP_VADDR, (void _far *) aws->buf, ATAPI_SENSE_LEN,
241 AP_FEATURES, ATAPI_FEAT_DMA,
242 AP_END);
243
244 if (rc > 0) {
245 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
246
247 } else if (rc < 0) {
248 /* we failed to get info about an error -> return
249 * non specific device error
250 */
251 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
252 }
253
254 return(rc);
255}
256
257/******************************************************************************
258 * Post processing function for ATAPI request sense; examines the sense
259 * data returned and maps sense info to IORB error info.
260 */
261static void atapi_req_sense_pp(IORBH _far *iorb)
262{
263 SCSI_STATUS_BLOCK _far *ssb;
264 ADD_WORKSPACE _far *aws = add_workspace(iorb);
265 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
266
267 dphex(psd, sizeof(*psd), "sense buffer:\n");
268
269 if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
270 iorb->StatusBlockLen >= sizeof(*ssb) && iorb->pStatusBlock != 0) {
271
272 /* copy sense data to IORB */
273 ssb = (SCSI_STATUS_BLOCK _far *) (((u32) iorb & 0xffff0000U) +
274 (u16) iorb->pStatusBlock);
275 ssb->AdapterErrorCode = 0;
276 ssb->TargetStatus = SCSI_STAT_CHECKCOND;
277 ssb->ResidualLength = 0;
278 memset(ssb->AdapterDiagInfo, 0x00, sizeof(ssb->AdapterDiagInfo));
279
280 if (ssb->SenseData != NULL) {
281 memcpy(ssb->SenseData, psd, max(ssb->ReqSenseLen, ATAPI_SENSE_LEN));
282 ssb->Flags != STATUS_SENSEDATA_VALID;
283 }
284 }
285
286 /* map sense data to some IOERR_ value */
287 switch (ATAPI_GET_SENSE(psd)) {
288
289 case ASENSE_NO_SENSE:
290 case ASENSE_RECOVERED_ERROR:
291 /* no error; this shouldn't happen because we'll only call
292 * atapi_req_sense() if we received an error interrupt */
293 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
294 break;
295
296 case ASENSE_NOT_READY:
297 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
298 break;
299
300 case ASENSE_UNIT_ATTENTION:
301 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
302 break;
303
304 case ASENSE_MEDIUM_ERROR:
305 iorb_seterr(iorb, IOERR_MEDIA);
306 break;
307
308 case ASENSE_ILLEGAL_REQUEST:
309 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
310 break;
311
312 case ASENSE_DATA_PROTECT:
313 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
314 break;
315
316 case ASENSE_BLANK_CHECK:
317 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
318 break;
319
320 case ASENSE_ABORTED_COMMAND:
321 case ASENSE_COPY_ABORTED:
322 iorb_seterr(iorb, IOERR_CMD_ABORTED);
323 break;
324
325 default:
326 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
327 break;
328 }
329
330 /* mark IORB as complete */
331 aws->complete = 1;
332}
333
334/******************************************************************************
335 * pad atapi commands; AHCI requires ATAPI commands to be either 12 or
336 * 16 bytes in length. This func converts commands that have a 12 byte
337 * equivalent, and pads the others to 12 bytes.
338 * cmd_out buffer is expected to be ATAPI_MAX_CDB_LEN in size.
339 * returns 0 on success, != 0 if the command can't be converted.
340 */
341int atapi_pad_cdb(u8 _far *cmd_in, u16 cmd_in_len,
342 u8 _far *cmd_out, u16 _far *cmd_out_len)
343{
344 ATAPI_CDB_12 _far *p12;
345
346 if (cmd_in_len == ATAPI_MIN_CDB_LEN || cmd_in_len == ATAPI_MAX_CDB_LEN) {
347 /* command does not need to be converted */
348 memcpy(cmd_out, cmd_in, cmd_in_len);
349 *cmd_out_len = cmd_in_len;
350 return 0;
351 }
352
353 memset(cmd_out, 0x00, ATAPI_MAX_CDB_LEN);
354 p12 = (ATAPI_CDB_12 _far *) cmd_out;
355 /* we always convert to 12 byte CDBs */
356 *cmd_out_len = ATAPI_MIN_CDB_LEN;
357
358 /* check if command can be converted */
359 switch (cmd_in[0]) {
360
361 case ATAPI_CMD_READ_6:
362 case ATAPI_CMD_WRITE_6:
363 /* convert from 6 to 12 byte equivalent */
364 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
365 p12->flags = cmd_in[1] & 0xc0; /* 6byte cmds have no flags (FUA etc.) */
366 SET_CDB_32(p12->lba, (u32) cmd_in[3] | (u32) cmd_in[2] << 8 |
367 (u32) (cmd_in[1] & 0x1f) << 16);
368 SET_CDB_32(p12->trans_len, (u32) cmd_in[4]);
369 p12->control = cmd_in[5];
370 break;
371
372 case ATAPI_CMD_READ_10:
373 case ATAPI_CMD_WRITE_10:
374 /* convert from 10 byte to 12 byte equivalent */
375 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
376 p12->flags = cmd_in[1];
377 memcpy(p12->lba, cmd_in + 2, 4);
378 SET_CDB_32(p12->trans_len, (u32) GET_CDB_16(cmd_in + 7));
379 p12->control = cmd_in[9];
380 break;
381
382 default:
383 /* pad with zeroes to 12 bytes */
384 memset(cmd_out, 0x00, ATAPI_MIN_CDB_LEN);
385 memcpy(cmd_out, cmd_in, cmd_in_len);
386 break;
387 }
388
389 return 0;
390}
391
Note: See TracBrowser for help on using the repository browser.