Commit 64f09c98 authored by Jeff Garzik's avatar Jeff Garzik
Browse files

/spare/repo/libata-dev branch 'chs-support'

parents 14be71f4 98ed72de
Loading
Loading
Loading
Loading
+115 −25
Original line number Diff line number Diff line
@@ -62,6 +62,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);
@@ -1131,7 +1132,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;
@@ -1229,9 +1230,9 @@ retry:
	 * 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;
	}

@@ -1251,16 +1252,25 @@ retry:
		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;
@@ -1269,14 +1279,42 @@ retry:
				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 */
@@ -2143,6 +2181,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 - Unmap DMA memory associated with command
 *	@qc: Command containing DMA memory to be released
@@ -3156,9 +3242,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;
}
+179 −112
Original line number Diff line number Diff line
@@ -504,77 +504,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 = (sect >> 16) & 0xff;
	tf->lbam = (sect >> 8) & 0xff;
	tf->lbal = sect & 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->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;
}
@@ -602,11 +632,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) {
@@ -616,90 +649,114 @@ 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];
		} else {
			/* if we don't support LBA48 addressing, the request
			 * -may- be too large. */
			if ((scsicmd[2] & 0xf0) || scsicmd[7])
				return 1;
		n_block |= ((u32)scsicmd[7]) << 8;
		n_block |= ((u32)scsicmd[8]);

			/* stores LBA27:24 in lower 4 bits of device reg */
			tf->device |= scsicmd[2];
		VPRINTK("ten-byte command\n");
	} else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
		block |= ((u64)scsicmd[2]) << 8;
		block |= ((u64)scsicmd[3]);

			qc->nsect = scsicmd[8];
		}
		n_block |= ((u32)scsicmd[4]);
		if (!n_block)
			n_block = 256;
	
		tf->nsect = scsicmd[8];
		tf->lbal = scsicmd[5];
		tf->lbam = scsicmd[4];
		tf->lbah = scsicmd[3];
		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("ten-byte command\n");
		if (qc->nsect == 0) /* we don't support length==0 cmds */
		VPRINTK("sixteen-byte command\n");
	} else {
		DPRINTK("no-byte command\n");
		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;
		}
	/* Check and compose ATA command */
	if (!n_block)
		/* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */
		return 1;

		tf->lbal = scsicmd[3];
		tf->lbam = scsicmd[2];
		tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
	if (lba) {
		if (lba48) {
			/* The request -may- be too large for LBA48. */
			if ((block >> 48) || (n_block > 65536))
				return 1;

		VPRINTK("six-byte command\n");
		return 0;
	}
			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 */

	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])
			/* The request -may- be too large for LBA28. */
			if ((block >> 28) || (n_block > 256))
				return 1;

		if (lba48) {
			tf->hob_nsect = scsicmd[12];
			tf->hob_lbal = scsicmd[6];
			tf->hob_lbam = scsicmd[5];
			tf->hob_lbah = scsicmd[4];
			tf->device |= (block >> 24) & 0xf;
		}
	
		qc->nsect = n_block;
		tf->nsect = n_block & 0xff;

			qc->nsect = ((unsigned int)scsicmd[12] << 8) |
					scsicmd[13];
		tf->lbah = (block >> 16) & 0xff;
		tf->lbam = (block >> 8) & 0xff;
		tf->lbal = block & 0xff;

		tf->device |= ATA_LBA;
	} else { 
			/* once again, filter out impossible non-zero values */
			if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
			    (scsicmd[6] & 0xf0))
				return 1;
		/* CHS */
		u32 sect, head, cyl, track;

			/* stores LBA27:24 in lower 4 bits of device reg */
			tf->device |= scsicmd[6];
		/* The request -may- be too large for CHS addressing. */
		if ((block >> 28) || (n_block > 256))
			return 1;
			
			qc->nsect = scsicmd[13];
		}
		/* Convert LBA to CHS */
		track = (u32)block / dev->sectors;
		cyl   = track / dev->heads;
		head  = track % dev->heads;
		sect  = (u32)block % dev->sectors + 1;

		tf->nsect = scsicmd[13];
		tf->lbal = scsicmd[9];
		tf->lbam = scsicmd[8];
		tf->lbah = scsicmd[7];
		DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", 
			(u32)block, track, cyl, head, sect);
		
		VPRINTK("sixteen-byte command\n");
		if (qc->nsect == 0) /* we don't support length==0 cmds */
		/* 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;
		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)
@@ -1246,10 +1303,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 */

	if (args->cmd->cmnd[0] == READ_CAPACITY) {
+14 −0
Original line number Diff line number Diff line
@@ -132,6 +132,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,
@@ -181,6 +182,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 {
@@ -250,6 +252,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;
+6 −0
Original line number Diff line number Diff line
@@ -97,6 +97,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 */
@@ -282,6 +283,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 {