aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-14 08:47:10 -0500
committerTejun Heo <htejun@gmail.com>2006-12-03 03:56:24 -0500
commitbd056d7eeb55d696556ee4f5ee2acb67b2d16df4 (patch)
treef6ca604abc43d73d42354d977f1bcedd262dbcda /drivers/ata
parent2432697ba0ce312d60be5009ffe1fa054a761bb9 (diff)
[PATCH] libata: separate out rw ATA taskfile building into ata_build_rw_tf()
Separate out rw ATA taskfile building from ata_scsi_rw_xlat() into ata_build_rw_tf(). This will be used to improve media error handling. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c133
-rw-r--r--drivers/ata/libata-scsi.c120
-rw-r--r--drivers/ata/libata.h4
3 files changed, 145 insertions, 112 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 0a5103b707c6..4ac53ef0e4b0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -199,7 +199,8 @@ static const u8 ata_rw_cmds[] = {
199 199
200/** 200/**
201 * ata_rwcmd_protocol - set taskfile r/w commands and protocol 201 * ata_rwcmd_protocol - set taskfile r/w commands and protocol
202 * @qc: command to examine and configure 202 * @tf: command to examine and configure
203 * @dev: device tf belongs to
203 * 204 *
204 * Examine the device configuration and tf->flags to calculate 205 * Examine the device configuration and tf->flags to calculate
205 * the proper read/write commands and protocol to use. 206 * the proper read/write commands and protocol to use.
@@ -207,10 +208,8 @@ static const u8 ata_rw_cmds[] = {
207 * LOCKING: 208 * LOCKING:
208 * caller. 209 * caller.
209 */ 210 */
210int ata_rwcmd_protocol(struct ata_queued_cmd *qc) 211static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev)
211{ 212{
212 struct ata_taskfile *tf = &qc->tf;
213 struct ata_device *dev = qc->dev;
214 u8 cmd; 213 u8 cmd;
215 214
216 int index, fua, lba48, write; 215 int index, fua, lba48, write;
@@ -222,7 +221,7 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
222 if (dev->flags & ATA_DFLAG_PIO) { 221 if (dev->flags & ATA_DFLAG_PIO) {
223 tf->protocol = ATA_PROT_PIO; 222 tf->protocol = ATA_PROT_PIO;
224 index = dev->multi_count ? 0 : 8; 223 index = dev->multi_count ? 0 : 8;
225 } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) { 224 } else if (lba48 && (dev->ap->flags & ATA_FLAG_PIO_LBA48)) {
226 /* Unable to use DMA due to host limitation */ 225 /* Unable to use DMA due to host limitation */
227 tf->protocol = ATA_PROT_PIO; 226 tf->protocol = ATA_PROT_PIO;
228 index = dev->multi_count ? 0 : 8; 227 index = dev->multi_count ? 0 : 8;
@@ -283,6 +282,130 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
283} 282}
284 283
285/** 284/**
285 * ata_build_rw_tf - Build ATA taskfile for given read/write request
286 * @tf: Target ATA taskfile
287 * @dev: ATA device @tf belongs to
288 * @block: Block address
289 * @n_block: Number of blocks
290 * @tf_flags: RW/FUA etc...
291 * @tag: tag
292 *
293 * LOCKING:
294 * None.
295 *
296 * Build ATA taskfile @tf for read/write request described by
297 * @block, @n_block, @tf_flags and @tag on @dev.
298 *
299 * RETURNS:
300 *
301 * 0 on success, -ERANGE if the request is too large for @dev,
302 * -EINVAL if the request is invalid.
303 */
304int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
305 u64 block, u32 n_block, unsigned int tf_flags,
306 unsigned int tag)
307{
308 tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
309 tf->flags |= tf_flags;
310
311 if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF |
312 ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
313 /* yay, NCQ */
314 if (!lba_48_ok(block, n_block))
315 return -ERANGE;
316
317 tf->protocol = ATA_PROT_NCQ;
318 tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
319
320 if (tf->flags & ATA_TFLAG_WRITE)
321 tf->command = ATA_CMD_FPDMA_WRITE;
322 else
323 tf->command = ATA_CMD_FPDMA_READ;
324
325 tf->nsect = tag << 3;
326 tf->hob_feature = (n_block >> 8) & 0xff;
327 tf->feature = n_block & 0xff;
328
329 tf->hob_lbah = (block >> 40) & 0xff;
330 tf->hob_lbam = (block >> 32) & 0xff;
331 tf->hob_lbal = (block >> 24) & 0xff;
332 tf->lbah = (block >> 16) & 0xff;
333 tf->lbam = (block >> 8) & 0xff;
334 tf->lbal = block & 0xff;
335
336 tf->device = 1 << 6;
337 if (tf->flags & ATA_TFLAG_FUA)
338 tf->device |= 1 << 7;
339 } else if (dev->flags & ATA_DFLAG_LBA) {
340 tf->flags |= ATA_TFLAG_LBA;
341
342 if (lba_28_ok(block, n_block)) {
343 /* use LBA28 */
344 tf->device |= (block >> 24) & 0xf;
345 } else if (lba_48_ok(block, n_block)) {
346 if (!(dev->flags & ATA_DFLAG_LBA48))
347 return -ERANGE;
348
349 /* use LBA48 */
350 tf->flags |= ATA_TFLAG_LBA48;
351
352 tf->hob_nsect = (n_block >> 8) & 0xff;
353
354 tf->hob_lbah = (block >> 40) & 0xff;
355 tf->hob_lbam = (block >> 32) & 0xff;
356 tf->hob_lbal = (block >> 24) & 0xff;
357 } else
358 /* request too large even for LBA48 */
359 return -ERANGE;
360
361 if (unlikely(ata_rwcmd_protocol(tf, dev) < 0))
362 return -EINVAL;
363
364 tf->nsect = n_block & 0xff;
365
366 tf->lbah = (block >> 16) & 0xff;
367 tf->lbam = (block >> 8) & 0xff;
368 tf->lbal = block & 0xff;
369
370 tf->device |= ATA_LBA;
371 } else {
372 /* CHS */
373 u32 sect, head, cyl, track;
374
375 /* The request -may- be too large for CHS addressing. */
376 if (!lba_28_ok(block, n_block))
377 return -ERANGE;
378
379 if (unlikely(ata_rwcmd_protocol(tf, dev) < 0))
380 return -EINVAL;
381
382 /* Convert LBA to CHS */
383 track = (u32)block / dev->sectors;
384 cyl = track / dev->heads;
385 head = track % dev->heads;
386 sect = (u32)block % dev->sectors + 1;
387
388 DPRINTK("block %u track %u cyl %u head %u sect %u\n",
389 (u32)block, track, cyl, head, sect);
390
391 /* Check whether the converted CHS can fit.
392 Cylinder: 0-65535
393 Head: 0-15
394 Sector: 1-255*/
395 if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
396 return -ERANGE;
397
398 tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
399 tf->lbal = sect;
400 tf->lbam = cyl;
401 tf->lbah = cyl >> 8;
402 tf->device |= head;
403 }
404
405 return 0;
406}
407
408/**
286 * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask 409 * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask
287 * @pio_mask: pio_mask 410 * @pio_mask: pio_mask
288 * @mwdma_mask: mwdma_mask 411 * @mwdma_mask: mwdma_mask
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d250858d201c..8eaace94d963 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1265,17 +1265,14 @@ nothing_to_do:
1265 1265
1266static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) 1266static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
1267{ 1267{
1268 struct ata_taskfile *tf = &qc->tf; 1268 unsigned int tf_flags = 0;
1269 struct ata_device *dev = qc->dev;
1270 u64 block; 1269 u64 block;
1271 u32 n_block; 1270 u32 n_block;
1272 1271 int rc;
1273 qc->flags |= ATA_QCFLAG_IO;
1274 tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
1275 1272
1276 if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || 1273 if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
1277 scsicmd[0] == WRITE_16) 1274 scsicmd[0] == WRITE_16)
1278 tf->flags |= ATA_TFLAG_WRITE; 1275 tf_flags |= ATA_TFLAG_WRITE;
1279 1276
1280 /* Calculate the SCSI LBA, transfer length and FUA. */ 1277 /* Calculate the SCSI LBA, transfer length and FUA. */
1281 switch (scsicmd[0]) { 1278 switch (scsicmd[0]) {
@@ -1283,7 +1280,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
1283 case WRITE_10: 1280 case WRITE_10:
1284 scsi_10_lba_len(scsicmd, &block, &n_block); 1281 scsi_10_lba_len(scsicmd, &block, &n_block);
1285 if (unlikely(scsicmd[1] & (1 << 3))) 1282 if (unlikely(scsicmd[1] & (1 << 3)))
1286 tf->flags |= ATA_TFLAG_FUA; 1283 tf_flags |= ATA_TFLAG_FUA;
1287 break; 1284 break;
1288 case READ_6: 1285 case READ_6:
1289 case WRITE_6: 1286 case WRITE_6:
@@ -1299,7 +1296,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
1299 case WRITE_16: 1296 case WRITE_16:
1300 scsi_16_lba_len(scsicmd, &block, &n_block); 1297 scsi_16_lba_len(scsicmd, &block, &n_block);
1301 if (unlikely(scsicmd[1] & (1 << 3))) 1298 if (unlikely(scsicmd[1] & (1 << 3)))
1302 tf->flags |= ATA_TFLAG_FUA; 1299 tf_flags |= ATA_TFLAG_FUA;
1303 break; 1300 break;
1304 default: 1301 default:
1305 DPRINTK("no-byte command\n"); 1302 DPRINTK("no-byte command\n");
@@ -1317,106 +1314,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
1317 */ 1314 */
1318 goto nothing_to_do; 1315 goto nothing_to_do;
1319 1316
1320 if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ_OFF | 1317 qc->flags |= ATA_QCFLAG_IO;
1321 ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) { 1318 qc->nsect = n_block;
1322 /* yay, NCQ */
1323 if (!lba_48_ok(block, n_block))
1324 goto out_of_range;
1325
1326 tf->protocol = ATA_PROT_NCQ;
1327 tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
1328
1329 if (tf->flags & ATA_TFLAG_WRITE)
1330 tf->command = ATA_CMD_FPDMA_WRITE;
1331 else
1332 tf->command = ATA_CMD_FPDMA_READ;
1333
1334 qc->nsect = n_block;
1335
1336 tf->nsect = qc->tag << 3;
1337 tf->hob_feature = (n_block >> 8) & 0xff;
1338 tf->feature = n_block & 0xff;
1339
1340 tf->hob_lbah = (block >> 40) & 0xff;
1341 tf->hob_lbam = (block >> 32) & 0xff;
1342 tf->hob_lbal = (block >> 24) & 0xff;
1343 tf->lbah = (block >> 16) & 0xff;
1344 tf->lbam = (block >> 8) & 0xff;
1345 tf->lbal = block & 0xff;
1346
1347 tf->device = 1 << 6;
1348 if (tf->flags & ATA_TFLAG_FUA)
1349 tf->device |= 1 << 7;
1350 } else if (dev->flags & ATA_DFLAG_LBA) {
1351 tf->flags |= ATA_TFLAG_LBA;
1352
1353 if (lba_28_ok(block, n_block)) {
1354 /* use LBA28 */
1355 tf->device |= (block >> 24) & 0xf;
1356 } else if (lba_48_ok(block, n_block)) {
1357 if (!(dev->flags & ATA_DFLAG_LBA48))
1358 goto out_of_range;
1359
1360 /* use LBA48 */
1361 tf->flags |= ATA_TFLAG_LBA48;
1362
1363 tf->hob_nsect = (n_block >> 8) & 0xff;
1364
1365 tf->hob_lbah = (block >> 40) & 0xff;
1366 tf->hob_lbam = (block >> 32) & 0xff;
1367 tf->hob_lbal = (block >> 24) & 0xff;
1368 } else
1369 /* request too large even for LBA48 */
1370 goto out_of_range;
1371
1372 if (unlikely(ata_rwcmd_protocol(qc) < 0))
1373 goto invalid_fld;
1374
1375 qc->nsect = n_block;
1376 tf->nsect = n_block & 0xff;
1377
1378 tf->lbah = (block >> 16) & 0xff;
1379 tf->lbam = (block >> 8) & 0xff;
1380 tf->lbal = block & 0xff;
1381
1382 tf->device |= ATA_LBA;
1383 } else {
1384 /* CHS */
1385 u32 sect, head, cyl, track;
1386
1387 /* The request -may- be too large for CHS addressing. */
1388 if (!lba_28_ok(block, n_block))
1389 goto out_of_range;
1390
1391 if (unlikely(ata_rwcmd_protocol(qc) < 0))
1392 goto invalid_fld;
1393
1394 /* Convert LBA to CHS */
1395 track = (u32)block / dev->sectors;
1396 cyl = track / dev->heads;
1397 head = track % dev->heads;
1398 sect = (u32)block % dev->sectors + 1;
1399
1400 DPRINTK("block %u track %u cyl %u head %u sect %u\n",
1401 (u32)block, track, cyl, head, sect);
1402
1403 /* Check whether the converted CHS can fit.
1404 Cylinder: 0-65535
1405 Head: 0-15
1406 Sector: 1-255*/
1407 if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
1408 goto out_of_range;
1409
1410 qc->nsect = n_block;
1411 tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
1412 tf->lbal = sect;
1413 tf->lbam = cyl;
1414 tf->lbah = cyl >> 8;
1415 tf->device |= head;
1416 }
1417 1319
1418 return 0; 1320 rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
1321 qc->tag);
1322 if (likely(rc == 0))
1323 return 0;
1419 1324
1325 if (rc == -ERANGE)
1326 goto out_of_range;
1327 /* treat all other errors as -EINVAL, fall through */
1420invalid_fld: 1328invalid_fld:
1421 ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0); 1329 ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0);
1422 /* "Invalid field in cbd" */ 1330 /* "Invalid field in cbd" */
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index ca6f36c13115..60576b1237e4 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -51,7 +51,9 @@ extern int atapi_enabled;
51extern int atapi_dmadir; 51extern int atapi_dmadir;
52extern int libata_fua; 52extern int libata_fua;
53extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); 53extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
54extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); 54extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
55 u64 block, u32 n_block, unsigned int tf_flags,
56 unsigned int tag);
55extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); 57extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
56extern void ata_dev_disable(struct ata_device *dev); 58extern void ata_dev_disable(struct ata_device *dev);
57extern void ata_port_flush_task(struct ata_port *ap); 59extern void ata_port_flush_task(struct ata_port *ap);