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

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

[PATCH] libata: add 40pin "short" cable support, honour drive side speed detection



[deweerdt@free.fr: build fix]
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarFrederik Deweerdt <deweerdt@free.fr>
Cc: Tejun Heo <htejun@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 2f27ce03
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@
#include <linux/libata.h>

#define DRV_NAME	"ata_piix"
#define DRV_VERSION	"2.00ac6"
#define DRV_VERSION	"2.00ac7"

enum {
	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
@@ -571,6 +571,23 @@ module_param(force_pcs, int, 0444);
MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
		 "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");

struct ich_laptop {
	u16 device;
	u16 subvendor;
	u16 subdevice;
};

/*
 *	List of laptops that use short cables rather than 80 wire
 */

static const struct ich_laptop ich_laptop[] = {
	/* devid, subvendor, subdev */
	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
	/* end marker */
	{ 0, }
};

/**
 *	piix_pata_cbl_detect - Probe host controller cable detect info
 *	@ap: Port for which cable detect info is desired
@@ -585,12 +602,24 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
static void ich_pata_cbl_detect(struct ata_port *ap)
{
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
	const struct ich_laptop *lap = &ich_laptop[0];
	u8 tmp, mask;

	/* no 80c support in host controller? */
	if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
		goto cbl40;

	/* Check for specials - Acer Aspire 5602WLMi */
	while (lap->device) {
		if (lap->device == pdev->device &&
		    lap->subvendor == pdev->subsystem_vendor &&
		    lap->subdevice == pdev->subsystem_device) {
			ap->cbl = ATA_CBL_PATA40_SHORT;
		    	return;
		}
		lap++;
	}

	/* check BIOS cable detect results */
	mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
	pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
+7 −0
Original line number Diff line number Diff line
@@ -3119,6 +3119,13 @@ static void ata_dev_xfermask(struct ata_device *dev)
	 */
	if (ap->cbl == ATA_CBL_PATA40)
		xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
	/* Apply drive side cable rule. Unknown or 80 pin cables reported
	 * host side are checked drive side as well. Cases where we know a
	 * 40wire cable is used safely for 80 are not checked here.
	 */
        if (ata_drive_40wire(dev->id) && (ap->cbl == ATA_CBL_PATA_UNK || ap->cbl == ATA_CBL_PATA80))
		xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);


	xfer_mask &= ata_pack_xfermask(dev->pio_mask,
				       dev->mwdma_mask, dev->udma_mask);
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ static int ali_c2_cable_detect(struct ata_port *ap)
	   implement the detect logic */

	if (ali_cable_override(pdev))
		return ATA_CBL_PATA80;
		return ATA_CBL_PATA40_SHORT;

	/* Host view cable detect 0x4A bit 0 primary bit 1 secondary
	   Bit set for 40 pin */
+12 −2
Original line number Diff line number Diff line
@@ -200,8 +200,9 @@ enum {
	ATA_CBL_NONE		= 0,
	ATA_CBL_PATA40		= 1,
	ATA_CBL_PATA80		= 2,
	ATA_CBL_PATA_UNK	= 3,
	ATA_CBL_SATA		= 4,
	ATA_CBL_PATA40_SHORT	= 3,		/* 40 wire cable to high UDMA spec */
	ATA_CBL_PATA_UNK	= 4,
	ATA_CBL_SATA		= 5,

	/* SATA Status and Control Registers */
	SCR_STATUS		= 0,
@@ -342,6 +343,15 @@ static inline int ata_id_is_cfa(const u16 *id)
	return 0;
}

static inline int ata_drive_40wire(const u16 *dev_id)
{
	if (ata_id_major_version(dev_id) >= 5 && ata_id_is_sata(dev_id))
		return 0;	/* SATA */
	if (dev_id[93] & 0x4000)
		return 0;	/* 80 wire */
	return 1;
}

static inline int atapi_cdb_len(const u16 *dev_id)
{
	u16 tmp = dev_id[0] & 0x3;