Loading drivers/scsi/libata-core.c +115 −25 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ static unsigned int ata_busy_sleep (struct ata_port *ap, unsigned long tmout_pat, unsigned long tmout); static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift); Loading Loading @@ -1008,7 +1009,7 @@ static inline void ata_dump_id(struct ata_device *dev) static void ata_dev_identify(struct ata_port *ap, unsigned int device) { struct ata_device *dev = &ap->device[device]; unsigned int i; unsigned int major_version; u16 tmp; unsigned long xfer_modes; u8 status; Loading Loading @@ -1106,9 +1107,9 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) * common ATA, ATAPI feature tests */ /* we require LBA and DMA support (bits 8 & 9 of word 49) */ if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) { printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id); /* we require DMA support (bits 8 of word 49) */ if (!ata_id_has_dma(dev->id)) { printk(KERN_DEBUG "ata%u: no dma\n", ap->id); goto err_out_nosup; } Loading @@ -1128,16 +1129,25 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) if (!ata_id_is_ata(dev->id)) /* sanity check */ goto err_out_nosup; /* get major version */ tmp = dev->id[ATA_ID_MAJOR_VER]; for (i = 14; i >= 1; i--) if (tmp & (1 << i)) for (major_version = 14; major_version >= 1; major_version--) if (tmp & (1 << major_version)) break; /* we require at least ATA-3 */ if (i < 3) { printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id); goto err_out_nosup; } /* * The exact sequence expected by certain pre-ATA4 drives is: * SRST RESET * IDENTIFY * INITIALIZE DEVICE PARAMETERS * anything else.. * Some drives were very specific about that exact sequence. */ if (major_version < 4 || (!ata_id_has_lba(dev->id))) ata_dev_init_params(ap, dev); if (ata_id_has_lba(dev->id)) { dev->flags |= ATA_DFLAG_LBA; if (ata_id_has_lba48(dev->id)) { dev->flags |= ATA_DFLAG_LBA48; Loading @@ -1146,14 +1156,42 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) dev->n_sectors = ata_id_u32(dev->id, 60); } ap->host->max_cmd_len = 16; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", ap->id, device, major_version, ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA"); } else { /* CHS */ /* Default translation */ dev->cylinders = dev->id[1]; dev->heads = dev->id[3]; dev->sectors = dev->id[6]; dev->n_sectors = dev->cylinders * dev->heads * dev->sectors; if (ata_id_current_chs_valid(dev->id)) { /* Current CHS translation is valid. */ dev->cylinders = dev->id[54]; dev->heads = dev->id[55]; dev->sectors = dev->id[56]; dev->n_sectors = ata_id_u32(dev->id, 57); } /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n", printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n", ap->id, device, major_version, ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " lba48" : ""); (int)dev->cylinders, (int)dev->heads, (int)dev->sectors); } ap->host->max_cmd_len = 16; } /* ATAPI-specific feature tests */ Loading Loading @@ -1946,6 +1984,54 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) DPRINTK("EXIT\n"); } /** * ata_dev_init_params - Issue INIT DEV PARAMS command * @ap: Port associated with device @dev * @dev: Device to which command will be sent * * LOCKING: */ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev) { DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; int rc; unsigned long flags; u16 sectors = dev->id[6]; u16 heads = dev->id[3]; /* Number of sectors per track 1-255. Number of heads 1-16 */ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) return; /* set up init dev params taskfile */ DPRINTK("init dev params \n"); qc = ata_qc_new_init(ap, dev); BUG_ON(qc == NULL); qc->tf.command = ATA_CMD_INIT_DEV_PARAMS; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; qc->tf.protocol = ATA_PROT_NODATA; qc->tf.nsect = sectors; qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; spin_lock_irqsave(&ap->host_set->lock, flags); rc = ata_qc_issue(qc); spin_unlock_irqrestore(&ap->host_set->lock, flags); if (rc) ata_port_disable(ap); else wait_for_completion(&wait); DPRINTK("EXIT\n"); } /** * ata_sg_clean - * @qc: Loading Loading @@ -2736,9 +2822,13 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, ata_tf_init(ap, &qc->tf, dev->devno); if (dev->flags & ATA_DFLAG_LBA) { qc->tf.flags |= ATA_TFLAG_LBA; if (dev->flags & ATA_DFLAG_LBA48) qc->tf.flags |= ATA_TFLAG_LBA48; } } return qc; } Loading drivers/scsi/libata-scsi.c +177 −103 Original line number Diff line number Diff line Loading @@ -435,77 +435,107 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; unsigned int lba = tf->flags & ATA_TFLAG_LBA; unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; u64 dev_sectors = qc->dev->n_sectors; u64 sect = 0; u32 n_sect = 0; u64 block = 0; u32 n_block = 0; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; tf->device |= ATA_LBA; if (scsicmd[0] == VERIFY) { sect |= ((u64)scsicmd[2]) << 24; sect |= ((u64)scsicmd[3]) << 16; sect |= ((u64)scsicmd[4]) << 8; sect |= ((u64)scsicmd[5]); block |= ((u64)scsicmd[2]) << 24; block |= ((u64)scsicmd[3]) << 16; block |= ((u64)scsicmd[4]) << 8; block |= ((u64)scsicmd[5]); n_sect |= ((u32)scsicmd[7]) << 8; n_sect |= ((u32)scsicmd[8]); n_block |= ((u32)scsicmd[7]) << 8; n_block |= ((u32)scsicmd[8]); } else if (scsicmd[0] == VERIFY_16) { sect |= ((u64)scsicmd[2]) << 56; sect |= ((u64)scsicmd[3]) << 48; sect |= ((u64)scsicmd[4]) << 40; sect |= ((u64)scsicmd[5]) << 32; sect |= ((u64)scsicmd[6]) << 24; sect |= ((u64)scsicmd[7]) << 16; sect |= ((u64)scsicmd[8]) << 8; sect |= ((u64)scsicmd[9]); 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_sect |= ((u32)scsicmd[10]) << 24; n_sect |= ((u32)scsicmd[11]) << 16; n_sect |= ((u32)scsicmd[12]) << 8; n_sect |= ((u32)scsicmd[13]); n_block |= ((u32)scsicmd[10]) << 24; n_block |= ((u32)scsicmd[11]) << 16; n_block |= ((u32)scsicmd[12]) << 8; n_block |= ((u32)scsicmd[13]); } else return 1; if (!n_sect) if (!n_block) return 1; if (sect >= dev_sectors) if (block >= dev_sectors) return 1; if ((sect + n_sect) > dev_sectors) if ((block + n_block) > dev_sectors) return 1; if (lba48) { if (n_sect > (64 * 1024)) if (n_block > (64 * 1024)) return 1; } else { if (n_sect > 256) if (n_block > 256) return 1; } if (lba) { if (lba48) { tf->command = ATA_CMD_VERIFY_EXT; tf->hob_nsect = (n_sect >> 8) & 0xff; tf->hob_nsect = (n_block >> 8) & 0xff; tf->hob_lbah = (sect >> 40) & 0xff; tf->hob_lbam = (sect >> 32) & 0xff; tf->hob_lbal = (sect >> 24) & 0xff; tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { tf->command = ATA_CMD_VERIFY; tf->device |= (sect >> 24) & 0xf; tf->device |= (block >> 24) & 0xf; } tf->nsect = n_sect & 0xff; tf->nsect = n_block & 0xff; tf->lbah = (block >> 16) & 0xff; tf->lbam = (block >> 8) & 0xff; tf->lbal = block & 0xff; tf->device |= ATA_LBA; } else { /* CHS */ u32 sect, head, cyl, track; /* 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; tf->lbah = (sect >> 16) & 0xff; tf->lbam = (sect >> 8) & 0xff; tf->lbal = sect & 0xff; tf->command = ATA_CMD_VERIFY; tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ tf->lbal = sect; tf->lbam = cyl; tf->lbah = cyl >> 8; tf->device |= head; } return 0; } Loading Loading @@ -533,11 +563,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; unsigned int lba = tf->flags & ATA_TFLAG_LBA; unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; u64 block = 0; u32 n_block = 0; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = qc->dev->xfer_protocol; tf->device |= ATA_LBA; if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 || scsicmd[0] == READ_16) { Loading @@ -547,80 +580,111 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) 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]; block |= ((u64)scsicmd[2]) << 24; block |= ((u64)scsicmd[3]) << 16; block |= ((u64)scsicmd[4]) << 8; block |= ((u64)scsicmd[5]); qc->nsect = ((unsigned int)scsicmd[7] << 8) | scsicmd[8]; n_block |= ((u32)scsicmd[7]) << 8; n_block |= ((u32)scsicmd[8]); VPRINTK("ten-byte command\n"); } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { block |= ((u64)scsicmd[2]) << 8; block |= ((u64)scsicmd[3]); n_block |= ((u32)scsicmd[4]); VPRINTK("six-byte command\n"); } 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 { /* if we don't support LBA48 addressing, the request * -may- be too large. */ if ((scsicmd[2] & 0xf0) || scsicmd[7]) DPRINTK("no-byte command\n"); return 1; } /* stores LBA27:24 in lower 4 bits of device reg */ tf->device |= scsicmd[2]; /* Check and compose ATA command */ if (!n_block) /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */ return 1; qc->nsect = scsicmd[8]; } if (lba) { if (lba48) { /* The request -may- be too large for LBA48. */ if ((block >> 48) || (n_block > 65536)) return 1; tf->nsect = scsicmd[8]; tf->lbal = scsicmd[5]; tf->lbam = scsicmd[4]; tf->lbah = scsicmd[3]; tf->hob_nsect = (n_block >> 8) & 0xff; VPRINTK("ten-byte command\n"); return 0; } tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { /* LBA28 */ if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { qc->nsect = tf->nsect = scsicmd[4]; tf->lbal = scsicmd[3]; tf->lbam = scsicmd[2]; tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */ /* The request -may- be too large for LBA28. */ if ((block >> 28) || (n_block > 256)) return 1; VPRINTK("six-byte command\n"); return 0; tf->device |= (block >> 24) & 0xf; } 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; qc->nsect = n_block; tf->nsect = n_block & 0xff; if (lba48) { tf->hob_nsect = scsicmd[12]; tf->hob_lbal = scsicmd[6]; tf->hob_lbam = scsicmd[5]; tf->hob_lbah = scsicmd[4]; tf->lbah = (block >> 16) & 0xff; tf->lbam = (block >> 8) & 0xff; tf->lbal = block & 0xff; qc->nsect = ((unsigned int)scsicmd[12] << 8) | scsicmd[13]; tf->device |= ATA_LBA; } else { /* once again, filter out impossible non-zero values */ if (scsicmd[4] || scsicmd[5] || scsicmd[12] || (scsicmd[6] & 0xf0)) /* CHS */ u32 sect, head, cyl, track; /* The request -may- be too large for CHS addressing. */ if ((block >> 28) || (n_block > 256)) return 1; /* stores LBA27:24 in lower 4 bits of device reg */ tf->device |= scsicmd[6]; /* Convert LBA to CHS */ track = (u32)block / dev->sectors; cyl = track / dev->heads; head = track % dev->heads; sect = (u32)block % dev->sectors + 1; qc->nsect = scsicmd[13]; } DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", (u32)block, track, cyl, head, sect); tf->nsect = scsicmd[13]; tf->lbal = scsicmd[9]; tf->lbam = scsicmd[8]; tf->lbah = scsicmd[7]; /* 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; VPRINTK("sixteen-byte command\n"); return 0; 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) Loading Loading @@ -1167,10 +1231,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, VPRINTK("ENTER\n"); if (ata_id_has_lba(args->id)) { if (ata_id_has_lba48(args->id)) n_sectors = ata_id_u64(args->id, 100); else n_sectors = ata_id_u32(args->id, 60); } else { /* CHS default translation */ n_sectors = args->id[1] * args->id[3] * args->id[6]; if (ata_id_current_chs_valid(args->id)) /* CHS current translation */ n_sectors = ata_id_u32(args->id, 57); } n_sectors--; /* ATA TotalUserSectors - 1 */ tmp = n_sectors; /* note: truncates, if lba48 */ Loading include/linux/ata.h +14 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,7 @@ enum { ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, Loading Loading @@ -174,6 +175,7 @@ enum { ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ }; enum ata_tf_protocols { Loading Loading @@ -242,6 +244,18 @@ struct ata_taskfile { ((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 0]) ) static inline int ata_id_current_chs_valid(u16 *id) { /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command has not been issued to the device then the values of id[54] to id[56] are vendor specific. */ return (id[53] & 0x01) && /* Current translation valid */ id[54] && /* cylinders in current translation */ id[55] && /* heads in current translation */ id[55] <= 16 && id[56]; /* sectors in current translation */ } static inline int atapi_cdb_len(u16 *dev_id) { u16 tmp = dev_id[0] & 0x3; Loading include/linux/libata.h +6 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ enum { ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ ATA_DFLAG_LBA = (1 << 3), /* device supports LBA */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ Loading Loading @@ -278,6 +279,11 @@ struct ata_device { u8 xfer_protocol; /* taskfile xfer protocol */ u8 read_cmd; /* opcode to use on read */ u8 write_cmd; /* opcode to use on write */ /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ u16 heads; /* Number of heads */ u16 sectors; /* Number of sectors per track */ }; struct ata_port { Loading Loading
drivers/scsi/libata-core.c +115 −25 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ static unsigned int ata_busy_sleep (struct ata_port *ap, unsigned long tmout_pat, unsigned long tmout); static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift); Loading Loading @@ -1008,7 +1009,7 @@ static inline void ata_dump_id(struct ata_device *dev) static void ata_dev_identify(struct ata_port *ap, unsigned int device) { struct ata_device *dev = &ap->device[device]; unsigned int i; unsigned int major_version; u16 tmp; unsigned long xfer_modes; u8 status; Loading Loading @@ -1106,9 +1107,9 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) * common ATA, ATAPI feature tests */ /* we require LBA and DMA support (bits 8 & 9 of word 49) */ if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) { printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id); /* we require DMA support (bits 8 of word 49) */ if (!ata_id_has_dma(dev->id)) { printk(KERN_DEBUG "ata%u: no dma\n", ap->id); goto err_out_nosup; } Loading @@ -1128,16 +1129,25 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) if (!ata_id_is_ata(dev->id)) /* sanity check */ goto err_out_nosup; /* get major version */ tmp = dev->id[ATA_ID_MAJOR_VER]; for (i = 14; i >= 1; i--) if (tmp & (1 << i)) for (major_version = 14; major_version >= 1; major_version--) if (tmp & (1 << major_version)) break; /* we require at least ATA-3 */ if (i < 3) { printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id); goto err_out_nosup; } /* * The exact sequence expected by certain pre-ATA4 drives is: * SRST RESET * IDENTIFY * INITIALIZE DEVICE PARAMETERS * anything else.. * Some drives were very specific about that exact sequence. */ if (major_version < 4 || (!ata_id_has_lba(dev->id))) ata_dev_init_params(ap, dev); if (ata_id_has_lba(dev->id)) { dev->flags |= ATA_DFLAG_LBA; if (ata_id_has_lba48(dev->id)) { dev->flags |= ATA_DFLAG_LBA48; Loading @@ -1146,14 +1156,42 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) dev->n_sectors = ata_id_u32(dev->id, 60); } ap->host->max_cmd_len = 16; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", ap->id, device, major_version, ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA"); } else { /* CHS */ /* Default translation */ dev->cylinders = dev->id[1]; dev->heads = dev->id[3]; dev->sectors = dev->id[6]; dev->n_sectors = dev->cylinders * dev->heads * dev->sectors; if (ata_id_current_chs_valid(dev->id)) { /* Current CHS translation is valid. */ dev->cylinders = dev->id[54]; dev->heads = dev->id[55]; dev->sectors = dev->id[56]; dev->n_sectors = ata_id_u32(dev->id, 57); } /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n", printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n", ap->id, device, major_version, ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " lba48" : ""); (int)dev->cylinders, (int)dev->heads, (int)dev->sectors); } ap->host->max_cmd_len = 16; } /* ATAPI-specific feature tests */ Loading Loading @@ -1946,6 +1984,54 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) DPRINTK("EXIT\n"); } /** * ata_dev_init_params - Issue INIT DEV PARAMS command * @ap: Port associated with device @dev * @dev: Device to which command will be sent * * LOCKING: */ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev) { DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; int rc; unsigned long flags; u16 sectors = dev->id[6]; u16 heads = dev->id[3]; /* Number of sectors per track 1-255. Number of heads 1-16 */ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) return; /* set up init dev params taskfile */ DPRINTK("init dev params \n"); qc = ata_qc_new_init(ap, dev); BUG_ON(qc == NULL); qc->tf.command = ATA_CMD_INIT_DEV_PARAMS; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; qc->tf.protocol = ATA_PROT_NODATA; qc->tf.nsect = sectors; qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; spin_lock_irqsave(&ap->host_set->lock, flags); rc = ata_qc_issue(qc); spin_unlock_irqrestore(&ap->host_set->lock, flags); if (rc) ata_port_disable(ap); else wait_for_completion(&wait); DPRINTK("EXIT\n"); } /** * ata_sg_clean - * @qc: Loading Loading @@ -2736,9 +2822,13 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, ata_tf_init(ap, &qc->tf, dev->devno); if (dev->flags & ATA_DFLAG_LBA) { qc->tf.flags |= ATA_TFLAG_LBA; if (dev->flags & ATA_DFLAG_LBA48) qc->tf.flags |= ATA_TFLAG_LBA48; } } return qc; } Loading
drivers/scsi/libata-scsi.c +177 −103 Original line number Diff line number Diff line Loading @@ -435,77 +435,107 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; unsigned int lba = tf->flags & ATA_TFLAG_LBA; unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; u64 dev_sectors = qc->dev->n_sectors; u64 sect = 0; u32 n_sect = 0; u64 block = 0; u32 n_block = 0; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; tf->device |= ATA_LBA; if (scsicmd[0] == VERIFY) { sect |= ((u64)scsicmd[2]) << 24; sect |= ((u64)scsicmd[3]) << 16; sect |= ((u64)scsicmd[4]) << 8; sect |= ((u64)scsicmd[5]); block |= ((u64)scsicmd[2]) << 24; block |= ((u64)scsicmd[3]) << 16; block |= ((u64)scsicmd[4]) << 8; block |= ((u64)scsicmd[5]); n_sect |= ((u32)scsicmd[7]) << 8; n_sect |= ((u32)scsicmd[8]); n_block |= ((u32)scsicmd[7]) << 8; n_block |= ((u32)scsicmd[8]); } else if (scsicmd[0] == VERIFY_16) { sect |= ((u64)scsicmd[2]) << 56; sect |= ((u64)scsicmd[3]) << 48; sect |= ((u64)scsicmd[4]) << 40; sect |= ((u64)scsicmd[5]) << 32; sect |= ((u64)scsicmd[6]) << 24; sect |= ((u64)scsicmd[7]) << 16; sect |= ((u64)scsicmd[8]) << 8; sect |= ((u64)scsicmd[9]); 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_sect |= ((u32)scsicmd[10]) << 24; n_sect |= ((u32)scsicmd[11]) << 16; n_sect |= ((u32)scsicmd[12]) << 8; n_sect |= ((u32)scsicmd[13]); n_block |= ((u32)scsicmd[10]) << 24; n_block |= ((u32)scsicmd[11]) << 16; n_block |= ((u32)scsicmd[12]) << 8; n_block |= ((u32)scsicmd[13]); } else return 1; if (!n_sect) if (!n_block) return 1; if (sect >= dev_sectors) if (block >= dev_sectors) return 1; if ((sect + n_sect) > dev_sectors) if ((block + n_block) > dev_sectors) return 1; if (lba48) { if (n_sect > (64 * 1024)) if (n_block > (64 * 1024)) return 1; } else { if (n_sect > 256) if (n_block > 256) return 1; } if (lba) { if (lba48) { tf->command = ATA_CMD_VERIFY_EXT; tf->hob_nsect = (n_sect >> 8) & 0xff; tf->hob_nsect = (n_block >> 8) & 0xff; tf->hob_lbah = (sect >> 40) & 0xff; tf->hob_lbam = (sect >> 32) & 0xff; tf->hob_lbal = (sect >> 24) & 0xff; tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { tf->command = ATA_CMD_VERIFY; tf->device |= (sect >> 24) & 0xf; tf->device |= (block >> 24) & 0xf; } tf->nsect = n_sect & 0xff; tf->nsect = n_block & 0xff; tf->lbah = (block >> 16) & 0xff; tf->lbam = (block >> 8) & 0xff; tf->lbal = block & 0xff; tf->device |= ATA_LBA; } else { /* CHS */ u32 sect, head, cyl, track; /* 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; tf->lbah = (sect >> 16) & 0xff; tf->lbam = (sect >> 8) & 0xff; tf->lbal = sect & 0xff; tf->command = ATA_CMD_VERIFY; tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ tf->lbal = sect; tf->lbam = cyl; tf->lbah = cyl >> 8; tf->device |= head; } return 0; } Loading Loading @@ -533,11 +563,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; unsigned int lba = tf->flags & ATA_TFLAG_LBA; unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; u64 block = 0; u32 n_block = 0; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = qc->dev->xfer_protocol; tf->device |= ATA_LBA; if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 || scsicmd[0] == READ_16) { Loading @@ -547,80 +580,111 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) 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]; block |= ((u64)scsicmd[2]) << 24; block |= ((u64)scsicmd[3]) << 16; block |= ((u64)scsicmd[4]) << 8; block |= ((u64)scsicmd[5]); qc->nsect = ((unsigned int)scsicmd[7] << 8) | scsicmd[8]; n_block |= ((u32)scsicmd[7]) << 8; n_block |= ((u32)scsicmd[8]); VPRINTK("ten-byte command\n"); } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { block |= ((u64)scsicmd[2]) << 8; block |= ((u64)scsicmd[3]); n_block |= ((u32)scsicmd[4]); VPRINTK("six-byte command\n"); } 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 { /* if we don't support LBA48 addressing, the request * -may- be too large. */ if ((scsicmd[2] & 0xf0) || scsicmd[7]) DPRINTK("no-byte command\n"); return 1; } /* stores LBA27:24 in lower 4 bits of device reg */ tf->device |= scsicmd[2]; /* Check and compose ATA command */ if (!n_block) /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */ return 1; qc->nsect = scsicmd[8]; } if (lba) { if (lba48) { /* The request -may- be too large for LBA48. */ if ((block >> 48) || (n_block > 65536)) return 1; tf->nsect = scsicmd[8]; tf->lbal = scsicmd[5]; tf->lbam = scsicmd[4]; tf->lbah = scsicmd[3]; tf->hob_nsect = (n_block >> 8) & 0xff; VPRINTK("ten-byte command\n"); return 0; } tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { /* LBA28 */ if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { qc->nsect = tf->nsect = scsicmd[4]; tf->lbal = scsicmd[3]; tf->lbam = scsicmd[2]; tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */ /* The request -may- be too large for LBA28. */ if ((block >> 28) || (n_block > 256)) return 1; VPRINTK("six-byte command\n"); return 0; tf->device |= (block >> 24) & 0xf; } 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; qc->nsect = n_block; tf->nsect = n_block & 0xff; if (lba48) { tf->hob_nsect = scsicmd[12]; tf->hob_lbal = scsicmd[6]; tf->hob_lbam = scsicmd[5]; tf->hob_lbah = scsicmd[4]; tf->lbah = (block >> 16) & 0xff; tf->lbam = (block >> 8) & 0xff; tf->lbal = block & 0xff; qc->nsect = ((unsigned int)scsicmd[12] << 8) | scsicmd[13]; tf->device |= ATA_LBA; } else { /* once again, filter out impossible non-zero values */ if (scsicmd[4] || scsicmd[5] || scsicmd[12] || (scsicmd[6] & 0xf0)) /* CHS */ u32 sect, head, cyl, track; /* The request -may- be too large for CHS addressing. */ if ((block >> 28) || (n_block > 256)) return 1; /* stores LBA27:24 in lower 4 bits of device reg */ tf->device |= scsicmd[6]; /* Convert LBA to CHS */ track = (u32)block / dev->sectors; cyl = track / dev->heads; head = track % dev->heads; sect = (u32)block % dev->sectors + 1; qc->nsect = scsicmd[13]; } DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", (u32)block, track, cyl, head, sect); tf->nsect = scsicmd[13]; tf->lbal = scsicmd[9]; tf->lbam = scsicmd[8]; tf->lbah = scsicmd[7]; /* 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; VPRINTK("sixteen-byte command\n"); return 0; 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) Loading Loading @@ -1167,10 +1231,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, VPRINTK("ENTER\n"); if (ata_id_has_lba(args->id)) { if (ata_id_has_lba48(args->id)) n_sectors = ata_id_u64(args->id, 100); else n_sectors = ata_id_u32(args->id, 60); } else { /* CHS default translation */ n_sectors = args->id[1] * args->id[3] * args->id[6]; if (ata_id_current_chs_valid(args->id)) /* CHS current translation */ n_sectors = ata_id_u32(args->id, 57); } n_sectors--; /* ATA TotalUserSectors - 1 */ tmp = n_sectors; /* note: truncates, if lba48 */ Loading
include/linux/ata.h +14 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,7 @@ enum { ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, Loading Loading @@ -174,6 +175,7 @@ enum { ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ }; enum ata_tf_protocols { Loading Loading @@ -242,6 +244,18 @@ struct ata_taskfile { ((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 0]) ) static inline int ata_id_current_chs_valid(u16 *id) { /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command has not been issued to the device then the values of id[54] to id[56] are vendor specific. */ return (id[53] & 0x01) && /* Current translation valid */ id[54] && /* cylinders in current translation */ id[55] && /* heads in current translation */ id[55] <= 16 && id[56]; /* sectors in current translation */ } static inline int atapi_cdb_len(u16 *dev_id) { u16 tmp = dev_id[0] & 0x3; Loading
include/linux/libata.h +6 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ enum { ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ ATA_DFLAG_LBA = (1 << 3), /* device supports LBA */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ Loading Loading @@ -278,6 +279,11 @@ struct ata_device { u8 xfer_protocol; /* taskfile xfer protocol */ u8 read_cmd; /* opcode to use on read */ u8 write_cmd; /* opcode to use on write */ /* for CHS addressing */ u16 cylinders; /* Number of cylinders */ u16 heads; /* Number of heads */ u16 sectors; /* Number of sectors per track */ }; struct ata_port { Loading