Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b352e57d authored by Alan Cox's avatar Alan Cox Committed by Jeff Garzik
Browse files

[PATCH] libata: Add CompactFlash support



The CFA world has some additional rules and drive modes we need to support for
newer expansion cards and on embedded boxes

Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent cea0d336
Loading
Loading
Loading
Loading
+54 −8
Original line number Diff line number Diff line
@@ -386,9 +386,13 @@ static const char *ata_mode_string(unsigned int xfer_mask)
		"PIO2",
		"PIO3",
		"PIO4",
		"PIO5",
		"PIO6",
		"MWDMA0",
		"MWDMA1",
		"MWDMA2",
		"MWDMA3",
		"MWDMA4",
		"UDMA/16",
		"UDMA/25",
		"UDMA/33",
@@ -875,6 +879,23 @@ static unsigned int ata_id_xfermask(const u16 *id)

	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;

	if (ata_id_is_cfa(id)) {
		/*
		 *	Process compact flash extended modes
		 */
		int pio = id[163] & 0x7;
		int dma = (id[163] >> 3) & 7;

		if (pio)
			pio_mask |= (1 << 5);
		if (pio > 1)
			pio_mask |= (1 << 6);
		if (dma)
			mwdma_mask |= (1 << 3);
		if (dma > 1)
			mwdma_mask |= (1 << 4);
	}

	udma_mask = 0;
	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
@@ -1356,6 +1377,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
	struct ata_port *ap = dev->ap;
	const u16 *id = dev->id;
	unsigned int xfer_mask;
	char revbuf[7];		/* XYZ-99\0 */
	int rc;

	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
@@ -1399,6 +1421,15 @@ int ata_dev_configure(struct ata_device *dev, int print_info)

	/* ATA-specific feature tests */
	if (dev->class == ATA_DEV_ATA) {
		if (ata_id_is_cfa(id)) {
			if (id[162] & 1) /* CPRM may make this media unusable */
				ata_dev_printk(dev, KERN_WARNING, "ata%u: device %u  supports DRM functions and may not be fully accessable.\n",
					ap->id, dev->devno);
			snprintf(revbuf, 7, "CFA");
		}
		else
			snprintf(revbuf, 7, "ATA-%d",  ata_id_major_version(id));

		dev->n_sectors = ata_id_n_sectors(id);

		if (ata_id_has_lba(id)) {
@@ -1417,9 +1448,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info)

			/* print device info to dmesg */
			if (ata_msg_drv(ap) && print_info)
				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
				ata_dev_printk(dev, KERN_INFO, "%s, "
					"max %s, %Lu sectors: %s %s\n",
					ata_id_major_version(id),
					revbuf,
					ata_mode_string(xfer_mask),
					(unsigned long long)dev->n_sectors,
					lba_desc, ncq_desc);
@@ -1440,9 +1471,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info)

			/* print device info to dmesg */
			if (ata_msg_drv(ap) && print_info)
				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
				ata_dev_printk(dev, KERN_INFO, "%s, "
					"max %s, %Lu sectors: CHS %u/%u/%u\n",
					ata_id_major_version(id),
					revbuf,
					ata_mode_string(xfer_mask),
					(unsigned long long)dev->n_sectors,
					dev->cylinders, dev->heads,
@@ -1900,10 +1931,11 @@ int sata_set_spd(struct ata_port *ap)
 * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
 */
/*
 * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
 * PIO 0-4, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
 * These were taken from ATA/ATAPI-6 standard, rev 0a, except
 * for PIO 5, which is a nonstandard extension and UDMA6, which
 * is currently supported only by Maxtor drives.
 * for UDMA6, which is currently supported only by Maxtor drives.
 *
 * For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0.
 */

static const struct ata_timing ata_timing[] = {
@@ -1913,6 +1945,8 @@ static const struct ata_timing ata_timing[] = {
	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },

	{ XFER_MW_DMA_4,  25,   0,   0,   0,  55,  20,  80,   0 },
	{ XFER_MW_DMA_3,  25,   0,   0,   0,  65,  25, 100,   0 },
	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
@@ -1927,7 +1961,8 @@ static const struct ata_timing ata_timing[] = {
	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },

/*	{ XFER_PIO_5,     20,  50,  30, 100,  50,  30, 100,   0 }, */
	{ XFER_PIO_6,     10,  55,  20,  80,  55,  20,  80,   0 },
	{ XFER_PIO_5,     15,  65,  25, 100,  65,  25, 100,   0 },
	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },

@@ -3062,6 +3097,17 @@ static void ata_dev_xfermask(struct ata_device *dev)
				       dev->mwdma_mask, dev->udma_mask);
	xfer_mask &= ata_id_xfermask(dev->id);

	/*
	 *	CFA Advanced TrueIDE timings are not allowed on a shared
	 *	cable
	 */
	if (ata_dev_pair(dev)) {
		/* No PIO5 or PIO6 */
		xfer_mask &= ~(0x03 << (ATA_SHIFT_PIO + 5));
		/* No MWDMA3 or MWDMA 4 */
		xfer_mask &= ~(0x03 << (ATA_SHIFT_MWDMA + 3));
	}

	if (ata_dma_blacklisted(dev)) {
		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
		ata_dev_printk(dev, KERN_WARNING,
+19 −1
Original line number Diff line number Diff line
@@ -170,12 +170,16 @@ enum {
	XFER_UDMA_2		= 0x42,
	XFER_UDMA_1		= 0x41,
	XFER_UDMA_0		= 0x40,
	XFER_MW_DMA_4		= 0x24,	/* CFA only */
	XFER_MW_DMA_3		= 0x23,	/* CFA only */
	XFER_MW_DMA_2		= 0x22,
	XFER_MW_DMA_1		= 0x21,
	XFER_MW_DMA_0		= 0x20,
	XFER_SW_DMA_2		= 0x12,
	XFER_SW_DMA_1		= 0x11,
	XFER_SW_DMA_0		= 0x10,
	XFER_PIO_6		= 0x0E,	/* CFA only */
	XFER_PIO_5		= 0x0D,	/* CFA only */
	XFER_PIO_4		= 0x0C,
	XFER_PIO_3		= 0x0B,
	XFER_PIO_2		= 0x0A,
@@ -274,7 +278,6 @@ struct ata_taskfile {
};

#define ata_id_is_ata(id)	(((id)[0] & (1 << 15)) == 0)
#define ata_id_is_cfa(id)	((id)[0] == 0x848A)
#define ata_id_is_sata(id)	((id)[93] == 0)
#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
@@ -306,6 +309,9 @@ static inline unsigned int ata_id_major_version(const u16 *id)
{
	unsigned int mver;

	if (id[ATA_ID_MAJOR_VER] == 0xFFFF)
		return 0;

	for (mver = 14; mver >= 1; mver--)
		if (id[ATA_ID_MAJOR_VER] & (1 << mver))
			break;
@@ -324,6 +330,18 @@ static inline int ata_id_current_chs_valid(const u16 *id)
		id[56];    /* sectors in current translation */
}

static inline int ata_id_is_cfa(const u16 *id)
{
	u16 v = id[0];
	if (v == 0x848A)	/* Standard CF */
		return 1;
	/* Could be CF hiding as standard ATA */
	if (ata_id_major_version(id) >= 3 &&  id[82] != 0xFFFF &&
			(id[82] & ( 1 << 2)))
		return 1;
	return 0;
}

static inline int atapi_cdb_len(const u16 *dev_id)
{
	u16 tmp = dev_id[0] & 0x3;
+2 −2
Original line number Diff line number Diff line
@@ -225,8 +225,8 @@ enum {
	/* encoding various smaller bitmaps into a single
	 * unsigned int bitmap
	 */
	ATA_BITS_PIO		= 5,
	ATA_BITS_MWDMA		= 3,
	ATA_BITS_PIO		= 7,
	ATA_BITS_MWDMA		= 5,
	ATA_BITS_UDMA		= 8,

	ATA_SHIFT_PIO		= 0,