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

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

changed atapi command bits; ATAPI commands are still not working

File size: 8.8 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_FEATURES, ATAPI_FEAT_DMA | ATAPI_FEAT_DMA_TO_HOST,
96 AP_SECTOR_28, ATAPI_LBA_DMA,
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
148 /* we do not perform the S/G limitation recovery loop here:
149 * "ADDs are not required to iterate commands through the CDB PassThru
150 * mechanism:" -- Storage Device Driver Reference, Scatter/Gather Lists
151 */
152 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
153 iorb_unit_port(iorb),
154 iorb_unit_device(iorb),
155 slot, ATA_CMD_PACKET,
156 AP_ATAPI_CMD, (void _far *) pt->pControllerCmd,
157 pt->ControllerCmdLen,
158 AP_SGLIST, pt->pSGList, pt->cSGList,
159 /* TODO: do we have to clear DMA_TO_HOST bit for
160 * write, mode select etc. commands?
161 */
162 AP_FEATURES, ATAPI_FEAT_DMA | ATAPI_FEAT_DMA_TO_HOST,
163 AP_SECTOR_28, ATAPI_LBA_DMA,
164 AP_END);
165
166 if (rc) {
167 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
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_6 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 cdb.trans_len = (u8) ATAPI_SENSE_LEN;
201
202 aws->ppfunc = atapi_req_sense_pp;
203 rc = ata_cmd(ad_infos + iorb_unit_adapter(iorb),
204 iorb_unit_port(iorb),
205 iorb_unit_device(iorb),
206 slot,
207 ATA_CMD_PACKET,
208 AP_ATAPI_CMD, (void _far*) &cdb, sizeof(cdb),
209 AP_VADDR, (void _far *) aws->buf, ATAPI_SENSE_LEN,
210 AP_FEATURES, ATAPI_FEAT_DMA,
211 AP_SECTOR_28, ATAPI_LBA_DMA,
212 AP_END);
213
214 if (rc > 0) {
215 /* should never happen - we got 64 bytes here */
216 iorb_seterr(iorb, IOERR_CMD_SGLIST_BAD);
217
218 } else {
219 /* we failed to get info about an error -> return
220 * non specific device error
221 */
222 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
223 }
224
225 return(rc);
226}
227
228/******************************************************************************
229 * Post processing function for ATAPI request sense; examines the sense
230 * data returned and maps sense info to IORB error info.
231 */
232static void atapi_req_sense_pp(IORBH _far *iorb)
233{
234 ADD_WORKSPACE _far *aws = add_workspace(iorb);
235 ATAPI_SENSE_DATA *psd = (ATAPI_SENSE_DATA *) aws->buf;
236
237 /* map sense data to some IOERR_ value */
238 switch (ATAPI_GET_SENSE(psd)) {
239
240 case ASENSE_NO_SENSE:
241 case ASENSE_RECOVERED_ERROR:
242 /* no error */
243 break;
244
245 case ASENSE_NOT_READY:
246 iorb_seterr(iorb, IOERR_UNIT_NOT_READY);
247 break;
248
249 case ASENSE_UNIT_ATTENTION:
250 iorb_seterr(iorb, IOERR_MEDIA_CHANGED);
251 break;
252
253 case ASENSE_MEDIUM_ERROR:
254 iorb_seterr(iorb, IOERR_MEDIA);
255 break;
256
257 case ASENSE_ILLEGAL_REQUEST:
258 iorb_seterr(iorb, IOERR_CMD_SYNTAX);
259 break;
260
261 case ASENSE_DATA_PROTECT:
262 iorb_seterr(iorb, IOERR_MEDIA_WRITE_PROTECT);
263 break;
264
265 case ASENSE_BLANK_CHECK:
266 iorb_seterr(iorb, IOERR_MEDIA_NOT_FORMATTED);
267 break;
268
269 case ASENSE_ABORTED_COMMAND:
270 case ASENSE_COPY_ABORTED:
271 iorb_seterr(iorb, IOERR_CMD_ABORTED);
272 break;
273
274 default:
275 iorb_seterr(iorb, IOERR_DEVICE_NONSPECIFIC);
276 break;
277 }
278
279 /* free sense buffer */
280 aws_free(aws);
281
282}
Note: See TracBrowser for help on using the repository browser.