tf->flags |= ATA_TFLAG_WRITE;
}
+ /* Calculate the SCSI LBA and transfer length. */
if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
- if (lba48) {
- tf->hob_nsect = scsicmd[7];
- tf->hob_lbal = scsicmd[2];
-
- qc->nsect = ((unsigned int)scsicmd[7] << 8) |
- scsicmd[8];
- } else {
- /* if we don't support LBA48 addressing, the request
- * -may- be too large. */
- if ((scsicmd[2] & 0xf0) || scsicmd[7])
- return 1;
-
- /* stores LBA27:24 in lower 4 bits of device reg */
- tf->device |= scsicmd[2];
-
- qc->nsect = scsicmd[8];
- }
+ block |= ((u64)scsicmd[2]) << 24;
+ block |= ((u64)scsicmd[3]) << 16;
+ block |= ((u64)scsicmd[4]) << 8;
+ block |= ((u64)scsicmd[5]);
- tf->nsect = scsicmd[8];
- tf->lbal = scsicmd[5];
- tf->lbam = scsicmd[4];
- tf->lbah = scsicmd[3];
+ n_block |= ((u32)scsicmd[7]) << 8;
+ n_block |= ((u32)scsicmd[8]);
VPRINTK("ten-byte command\n");
- if (qc->nsect == 0) /* we don't support length==0 cmds */
- return 1;
- return 0;
- }
-
- if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
- qc->nsect = tf->nsect = scsicmd[4];
- if (!qc->nsect) {
- qc->nsect = 256;
- if (lba48)
- tf->hob_nsect = 1;
- }
-
- tf->lbal = scsicmd[3];
- tf->lbam = scsicmd[2];
- tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
-
+ } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
+ block |= ((u64)scsicmd[2]) << 8;
+ block |= ((u64)scsicmd[3]);
++
+ n_block |= ((u32)scsicmd[4]);
++ if (!n_block)
++ n_block = 256;
+
VPRINTK("six-byte command\n");
- return 0;
+ } else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
+ block |= ((u64)scsicmd[2]) << 56;
+ block |= ((u64)scsicmd[3]) << 48;
+ block |= ((u64)scsicmd[4]) << 40;
+ block |= ((u64)scsicmd[5]) << 32;
+ block |= ((u64)scsicmd[6]) << 24;
+ block |= ((u64)scsicmd[7]) << 16;
+ block |= ((u64)scsicmd[8]) << 8;
+ block |= ((u64)scsicmd[9]);
+
+ n_block |= ((u32)scsicmd[10]) << 24;
+ n_block |= ((u32)scsicmd[11]) << 16;
+ n_block |= ((u32)scsicmd[12]) << 8;
+ n_block |= ((u32)scsicmd[13]);
+
+ VPRINTK("sixteen-byte command\n");
+ } else {
+ DPRINTK("no-byte command\n");
+ return 1;
}
- if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
- /* rule out impossible LBAs and sector counts */
- if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
- return 1;
+ /* Check and compose ATA command */
+ if (!n_block)
+ /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */
+ return 1;
+ if (lba) {
if (lba48) {
- tf->hob_nsect = scsicmd[12];
- tf->hob_lbal = scsicmd[6];
- tf->hob_lbam = scsicmd[5];
- tf->hob_lbah = scsicmd[4];
-
- qc->nsect = ((unsigned int)scsicmd[12] << 8) |
- scsicmd[13];
- } else {
- /* once again, filter out impossible non-zero values */
- if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
- (scsicmd[6] & 0xf0))
+ /* The request -may- be too large for LBA48. */
+ if ((block >> 48) || (n_block > 65536))
return 1;
- /* stores LBA27:24 in lower 4 bits of device reg */
- tf->device |= scsicmd[6];
+ tf->hob_nsect = (n_block >> 8) & 0xff;
+
+ tf->hob_lbah = (block >> 40) & 0xff;
+ tf->hob_lbam = (block >> 32) & 0xff;
+ tf->hob_lbal = (block >> 24) & 0xff;
+ } else {
+ /* LBA28 */
+
+ /* The request -may- be too large for LBA28. */
+ if ((block >> 28) || (n_block > 256))
+ return 1;
- qc->nsect = scsicmd[13];
+ tf->device |= (block >> 24) & 0xf;
}
+
+ qc->nsect = n_block;
+ tf->nsect = n_block & 0xff;
- tf->nsect = scsicmd[13];
- tf->lbal = scsicmd[9];
- tf->lbam = scsicmd[8];
- tf->lbah = scsicmd[7];
+ tf->lbah = (block >> 16) & 0xff;
+ tf->lbam = (block >> 8) & 0xff;
+ tf->lbal = block & 0xff;
- VPRINTK("sixteen-byte command\n");
- if (qc->nsect == 0) /* we don't support length==0 cmds */
+ tf->device |= ATA_LBA;
+ } else {
+ /* CHS */
+ u32 sect, head, cyl, track;
+
+ /* The request -may- be too large for CHS addressing. */
+ if ((block >> 28) || (n_block > 256))
return 1;
- return 0;
+
+ /* Convert LBA to CHS */
+ track = (u32)block / dev->sectors;
+ cyl = track / dev->heads;
+ head = track % dev->heads;
+ sect = (u32)block % dev->sectors + 1;
+
+ DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n",
+ (u32)block, track, cyl, head, sect);
+
+ /* Check whether the converted CHS can fit.
+ Cylinder: 0-65535
+ Head: 0-15
+ Sector: 1-255*/
+ if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
+ return 1;
+
+ qc->nsect = n_block;
+ tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+ tf->lbal = sect;
+ tf->lbam = cyl;
+ tf->lbah = cyl >> 8;
+ tf->device |= head;
}
- DPRINTK("no-byte command\n");
- return 1;
+ return 0;
}
static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)