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

Last change on this file since 77 was 77, checked in by chris, 14 years ago
  • Further fixes to automatic ATAPI sense handling, now supporting sense buffers larger than 64 bytes if requested by initiator (cdrecord wanted 96 bytes)
  • Separate, and internally handled, spinlock for libc malloc/free calls to reduce chances of memory corruption if somebody forgets to get the driver-level spinlock before calling malloc/free. There was no real problem with that, just some awkward code fragments which look much better now.
  • Link power management implemented
  • More generic support for adapter/port options so all of them can now have a global, adapter or port scope
  • Generic support for inverting driver options (i.e. turn them off with '!')
  • Thorough PCI scan is now the default; the reason it wasn't so far was a delay in Virtualbox but that was never a problem on real hardware
  • SCSI emulation for ATAPI devices; this can be enabled on global, adapter or port scope
File size: 12.9 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), iorb_unit_port(iorb),
171 iorb_unit_device(iorb), slot, ATA_CMD_PACKET,
172 AP_ATAPI_CMD, (void _far *) cdb, cdb_len,
173 AP_SGLIST, pt->pSGList, pt->cSGList,
174 AP_WRITE, !(pt->Flags & PT_DIRECTION_IN),
175 AP_FEATURES, ATAPI_FEAT_DMA,
176 AP_FEATURES, (pt->Flags & PT_DIRECTION_IN) ? ATAPI_FEAT_DMA_TO_HOST : 0,
177 AP_END);
178
179 if (rc) {
180 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
181 }
182
183 return(rc);
184}
185
186
187/******************************************************************************
188 * Request sense information for a failed command.
189 *
190 * NOTE: This function must be called right after an ATAPI command has failed
191 * and before any other commands are queued on the corresponding device.
192 * This function is typically called in the port restart context hook
193 * which is triggered by an AHCI error interrupt.
194 *
195 */
196int atapi_req_sense(IORBH _far *iorb, int slot)
197{
198 SCSI_STATUS_BLOCK _far *ssb;
199 ADD_WORKSPACE _far *aws = add_workspace(iorb);
200 int rc;
201 u8 cdb[ATAPI_MIN_CDB_LEN];
202 ATAPI_CDB_6 _far *pcdb = (ATAPI_CDB_6 _far *) cdb;
203 size_t sense_buf_len = ATAPI_SENSE_LEN;
204
205 if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
206 iorb->StatusBlockLen >= sizeof(*ssb) && iorb->pStatusBlock != 0) {
207
208 /* don't request sense data if caller asked us not to; the flag
209 * STATUS_DISABLE_REQEST_SENSE is not defined in the old DDK we've been
210 * using so we'll use the hard-coded value (0x0008) */
211 ssb = (SCSI_STATUS_BLOCK _far *) (((u32) iorb & 0xffff0000U) +
212 (u16) iorb->pStatusBlock);
213 if (ssb->Flags & 0x0008U) {
214 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
215 return(-1);
216 }
217
218 /* if the sense buffer requested is larger than our default, adjust
219 * the length accordingly to satisfy the caller's requirements. */
220 if (ssb->SenseData != NULL && ssb->ReqSenseLen > sense_buf_len) {
221 sense_buf_len = ssb->ReqSenseLen;
222 }
223 }
224
225 /* allocate sense buffer in ADD workspace */
226 if ((aws->buf = malloc(sense_buf_len)) == NULL) {
227 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
228 return(-1);
229 }
230 memset(aws->buf, 0x00, sense_buf_len);
231
232 /* prepare request sense command */
233 memset(cdb, 0x00, sizeof(cdb));
234 pcdb->cmd = ATAPI_CMD_REQUEST_SENSE;
235 pcdb->trans_len = (u8) sense_buf_len;
236
237 aws->ppfunc = atapi_req_sense_pp;
238 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
239 iorb_unit_port(iorb),
240 iorb_unit_device(iorb),
241 slot,
242 ATA_CMD_PACKET,
243 AP_ATAPI_CMD, (void _far*) cdb, sizeof(cdb),
244 AP_VADDR, (void _far *) aws->buf, sense_buf_len,
245 AP_FEATURES, ATAPI_FEAT_DMA,
246 AP_END);
247
248 if (rc > 0) {
249 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
250
251 } else if (rc < 0) {
252 /* we failed to get info about an error -> return
253 * non specific device error
254 */
255 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
256 }
257
258 return(rc);
259}
260
261/******************************************************************************
262 * Post processing function for ATAPI request sense; examines the sense
263 * data returned and maps sense info to IORB error info.
264 */
265static void atapi_req_sense_pp(IORBH _far *iorb)
266{
267 SCSI_STATUS_BLOCK _far *ssb;
268 ADD_WORKSPACE _far *aws = add_workspace(iorb);
269 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
270
271 dphex(psd, sizeof(*psd), "sense buffer:\n");
272
273 if ((iorb->RequestControl & IORB_REQ_STATUSBLOCK) &&
274 iorb->StatusBlockLen >= sizeof(*ssb) && iorb->pStatusBlock != 0) {
275
276 /* copy sense data to IORB */
277 ssb = (SCSI_STATUS_BLOCK _far *) (((u32) iorb & 0xffff0000U) +
278 (u16) iorb->pStatusBlock);
279 ssb->AdapterErrorCode = 0;
280 ssb->TargetStatus = SCSI_STAT_CHECKCOND;
281 ssb->ResidualLength = 0;
282 memset(ssb->AdapterDiagInfo, 0x00, sizeof(ssb->AdapterDiagInfo));
283
284 if (ssb->SenseData != NULL) {
285 memcpy(ssb->SenseData, psd, ssb->ReqSenseLen);
286 ssb->Flags |= STATUS_SENSEDATA_VALID;
287 }
288 iorb->Status |= IORB_STATUSBLOCK_AVAIL;
289 }
290
291 /* map sense data to some IOERR_ value */
292 switch (ATAPI_GET_SENSE(psd)) {
293
294 case ASENSE_NO_SENSE:
295 case ASENSE_RECOVERED_ERROR:
296 /* no error; this shouldn't happen because we'll only call
297 * atapi_req_sense() if we received an error interrupt */
298 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
299 break;
300
301 case ASENSE_NOT_READY:
302 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
303 break;
304
305 case ASENSE_UNIT_ATTENTION:
306 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
307 break;
308
309 case ASENSE_MEDIUM_ERROR:
310 iorb_seterr(iorb, IOERR_MEDIA);
311 break;
312
313 case ASENSE_ILLEGAL_REQUEST:
314 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
315 break;
316
317 case ASENSE_DATA_PROTECT:
318 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
319 break;
320
321 case ASENSE_BLANK_CHECK:
322 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
323 break;
324
325 case ASENSE_ABORTED_COMMAND:
326 case ASENSE_COPY_ABORTED:
327 iorb_seterr(iorb, IOERR_CMD_ABORTED);
328 break;
329
330 default:
331 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
332 break;
333 }
334
335 /* mark IORB as complete */
336 aws->complete = 1;
337}
338
339/******************************************************************************
340 * Pad ATAPI commands; AHCI requires ATAPI commands to be either 12 or
341 * 16 bytes in length. This func converts commands that have a 12 byte
342 * equivalent, and pads the others to 12 bytes.
343 * cmd_out buffer is expected to be ATAPI_MAX_CDB_LEN in size.
344 * returns 0 on success, != 0 if the command can't be converted.
345 */
346int atapi_pad_cdb(u8 _far *cmd_in, u16 cmd_in_len,
347 u8 _far *cmd_out, u16 _far *cmd_out_len)
348{
349 ATAPI_CDB_12 _far *p12;
350 u32 tmp;
351
352 if (cmd_in_len == ATAPI_MIN_CDB_LEN || cmd_in_len == ATAPI_MAX_CDB_LEN) {
353 /* command does not need to be converted */
354 memcpy(cmd_out, cmd_in, cmd_in_len);
355 *cmd_out_len = cmd_in_len;
356 return 0;
357 }
358
359 memset(cmd_out, 0x00, ATAPI_MAX_CDB_LEN);
360 p12 = (ATAPI_CDB_12 _far *) cmd_out;
361 /* we always convert to 12 byte CDBs */
362 *cmd_out_len = ATAPI_MIN_CDB_LEN;
363
364 /* check if command can be converted */
365 switch (cmd_in[0]) {
366
367 case ATAPI_CMD_READ_6:
368 case ATAPI_CMD_WRITE_6:
369 /* convert from 6 to 12 byte equivalent */
370 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
371 p12->flags = cmd_in[1] & 0xc0; /* 6byte cmds have no flags (FUA etc.) */
372 tmp = GET_CDB_24(cmd_in + 1) & 0x1fffffUL;
373 SET_CDB_32(p12->lba, tmp);
374 SET_CDB_32(p12->trans_len, cmd_in[4]);
375 p12->control = cmd_in[5];
376 break;
377
378 case ATAPI_CMD_READ_10:
379 case ATAPI_CMD_WRITE_10:
380 /* convert from 10 byte to 12 byte equivalent */
381 p12->cmd = 0xa0 | (cmd_in[0] & 0x0f);
382 p12->flags = cmd_in[1];
383 p12->control = cmd_in[9];
384 memcpy(p12->lba, cmd_in + 2, 4);
385 tmp = GET_CDB_16(cmd_in + 7);
386 SET_CDB_32(p12->trans_len, tmp);
387 break;
388
389 default:
390 /* pad with zeroes to 12 bytes */
391 memset(cmd_out, 0x00, ATAPI_MIN_CDB_LEN);
392 memcpy(cmd_out, cmd_in, cmd_in_len);
393 break;
394 }
395
396 return 0;
397}
398
Note: See TracBrowser for help on using the repository browser.