diff options
| -rw-r--r-- | drivers/ata/libata-core.c | 133 | ||||
| -rw-r--r-- | drivers/ata/libata-scsi.c | 120 | ||||
| -rw-r--r-- | drivers/ata/libata.h | 4 |
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 | */ |
| 210 | int ata_rwcmd_protocol(struct ata_queued_cmd *qc) | 211 | static 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 | */ | ||
| 304 | int 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 | ||
| 1266 | static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) | 1266 | static 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 */ | ||
| 1420 | invalid_fld: | 1328 | invalid_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; | |||
| 51 | extern int atapi_dmadir; | 51 | extern int atapi_dmadir; |
| 52 | extern int libata_fua; | 52 | extern int libata_fua; |
| 53 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); | 53 | extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); |
| 54 | extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); | 54 | extern 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); | ||
| 55 | extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); | 57 | extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); |
| 56 | extern void ata_dev_disable(struct ata_device *dev); | 58 | extern void ata_dev_disable(struct ata_device *dev); |
| 57 | extern void ata_port_flush_task(struct ata_port *ap); | 59 | extern void ata_port_flush_task(struct ata_port *ap); |
