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

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

removed INT 3 from memcpy (haha, got ya!); removed obsolete atapi_execute_cdb_pp func

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_END);
96
97 if (rc > 0) {
98 /* couldn't map all S/G elements */
99 ata_max_sg_cnt(io, sg_indx, (USHORT) rc, &sg_cnt, &count);
100 }
101 } while (rc > 0 && sg_cnt > 0);
102
103 if (rc == 0) {
104 add_workspace(iorb)->blocks = count;
105 add_workspace(iorb)->ppfunc = ata_read_pp;
106
107 } else if (rc > 0) {
108 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
109
110 } else {
111 iorb_seterr(iorb, IOERR_CMD_ADD_SOFTWARE_FAILURE);
112 }
113
114 return(rc);
115}
116
117/******************************************************************************
118 * Verify readability of sectors on AHCI device. This function is not expected
119 * to be called.
120 */
121int atapi_verify(IORBH _far *iorb, int slot)
122{
123 dprintf("atapi_verify called\n");
124 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
125 return(-1);
126}
127
128/******************************************************************************
129 * Write sectors to AHCI device. This function is not expected to be called.
130 */
131int atapi_write(IORBH _far *iorb, int slot)
132{
133 dprintf("atapi_write called\n");
134 iorb_seterr(iorb, IOERR_CMD_NOT_SUPPORTED);
135 return(-1);
136}
137
138/******************************************************************************
139 * Execute ATAPI command.
140 */
141int atapi_execute_cdb(IORBH _far *iorb, int slot)
142{
143 IORB_ADAPTER_PASSTHRU _far *pt = (IORB_ADAPTER_PASSTHRU _far *) iorb;
144 int rc;
145
146 /* we do not perform the S/G limitation recovery loop here:
147 * "ADDs are not required to iterate commands through the CDB PassThru
148 * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
149 */
150 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
151 iorb_unit_port(iorb),
152 iorb_unit_device(iorb),
153 slot, ATA_CMD_PACKET,
154 AP_ATAPI_CMD, (void _far *) pt->pControllerCmd,
155 pt->ControllerCmdLen,
156 AP_SGLIST, pt->pSGList, pt->cSGList,
157 AP_END);
158
159 if (rc == 0) {
160 add_workspace(iorb)->blocks = pt->cSGList;
161 /* no pp func needed */
162
163 } else if (rc > 0) {
164 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
165
166 } else {
167 iorb_seterr(iorb, IOERR_CMD_ADD_SOFTWARE_FAILURE);
168 }
169
170 return(rc);
171}
172
173
174/******************************************************************************
175 * Request sense information for a failed command.
176 *
177 * NOTE: This function must be called right after an ATAPI command has failed
178 * and before any other commands are queued on the corresponding device.
179 * This function is typically called in the port restart context hook
180 * which is triggered by an AHCI error interrupt.
181 *
182 */
183int atapi_req_sense(IORBH _far *iorb, int slot)
184{
185 ADD_WORKSPACE _far *aws = add_workspace(iorb);
186 ATAPI_CDB_REQ_SENSE cdb;
187 int rc;
188
189 /* allocate sense buffer in ADD workspace */
190 aws->buf = malloc(ATAPI_SENSE_LEN);
191 if (aws->buf == NULL) {
192 iorb_seterr(iorb, IOERR_CMD_SW_RESOURCE);
193 return(-1);
194 }
195 memset(aws->buf, 0x00, ATAPI_SENSE_LEN);
196
197 /* prepare request sense command */
198 memset(&cdb, 0x00, sizeof(cdb));
199 cdb.cmd = ATAPI_CMD_REQUEST_SENSE;
200 aws->ppfunc = atapi_req_sense_pp;
201 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
202 iorb_unit_port(iorb),
203 iorb_unit_device(iorb),
204 slot,
205 ATA_CMD_PACKET,
206 AP_ATAPI_CMD, (void _far*) &cdb, sizeof(cdb),
207 AP_VADDR, (void _far *) aws->buf, ATAPI_SENSE_LEN,
208 AP_END);
209
210 if (rc > 0) {
211 /* should never happen - we got 64 bytes here */
212 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
213
214 } else {
215 /* we failed to get info about an error -> return
216 * non specific device error
217 */
218 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
219 }
220
221 return(rc);
222}
223
224/******************************************************************************
225 * Post processing function for ATAPI request sense; examines the sense
226 * data returned and maps sense info to IORB error info.
227 */
228static void atapi_req_sense_pp(IORBH _far *iorb)
229{
230 ADD_WORKSPACE _far *aws = add_workspace(iorb);
231 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
232
233 /* map sense data to some IOERR_ value */
234 switch (ATAPI_GET_SENSE(psd)) {
235
236 case ASENSE_NO_SENSE:
237 case ASENSE_RECOVERED_ERROR:
238 /* no error */
239 break;
240
241 case ASENSE_NOT_READY:
242 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
243 break;
244
245 case ASENSE_UNIT_ATTENTION:
246 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
247 break;
248
249 case ASENSE_MEDIUM_ERROR:
250 iorb_seterr(iorb, IOERR_MEDIA);
251 break;
252
253 case ASENSE_ILLEGAL_REQUEST:
254 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
255 break;
256
257 case ASENSE_DATA_PROTECT:
258 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
259 break;
260
261 case ASENSE_BLANK_CHECK:
262 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
263 break;
264
265 case ASENSE_ABORTED_COMMAND:
266 case ASENSE_COPY_ABORTED:
267 iorb_seterr(iorb, IOERR_CMD_ABORTED);
268 break;
269
270 default:
271 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
272 break;
273 }
274
275 /* free sense buffer */
276 aws_free(aws);
277
278}
Note: See TracBrowser for help on using the repository browser.