mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 09:02:00 +00:00
[PATCH] libata: add 40pin "short" cable support, honour drive side speed detection
[deweerdt@free.fr: build fix] Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Frederik Deweerdt <deweerdt@free.fr> Cc: Tejun Heo <htejun@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
2f27ce0362
commit
fc085150b4
@ -93,7 +93,7 @@
|
|||||||
#include <linux/libata.h>
|
#include <linux/libata.h>
|
||||||
|
|
||||||
#define DRV_NAME "ata_piix"
|
#define DRV_NAME "ata_piix"
|
||||||
#define DRV_VERSION "2.00ac6"
|
#define DRV_VERSION "2.00ac7"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
|
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 "
|
MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
|
||||||
"device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
|
"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
|
* piix_pata_cbl_detect - Probe host controller cable detect info
|
||||||
* @ap: Port for which cable detect info is desired
|
* @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)
|
static void ich_pata_cbl_detect(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||||
|
const struct ich_laptop *lap = &ich_laptop[0];
|
||||||
u8 tmp, mask;
|
u8 tmp, mask;
|
||||||
|
|
||||||
/* no 80c support in host controller? */
|
/* no 80c support in host controller? */
|
||||||
if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
|
if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
|
||||||
goto cbl40;
|
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 */
|
/* check BIOS cable detect results */
|
||||||
mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
|
mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
|
||||||
pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
|
pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
|
||||||
|
@ -3119,6 +3119,13 @@ static void ata_dev_xfermask(struct ata_device *dev)
|
|||||||
*/
|
*/
|
||||||
if (ap->cbl == ATA_CBL_PATA40)
|
if (ap->cbl == ATA_CBL_PATA40)
|
||||||
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
|
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,
|
xfer_mask &= ata_pack_xfermask(dev->pio_mask,
|
||||||
dev->mwdma_mask, dev->udma_mask);
|
dev->mwdma_mask, dev->udma_mask);
|
||||||
|
@ -78,7 +78,7 @@ static int ali_c2_cable_detect(struct ata_port *ap)
|
|||||||
implement the detect logic */
|
implement the detect logic */
|
||||||
|
|
||||||
if (ali_cable_override(pdev))
|
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
|
/* Host view cable detect 0x4A bit 0 primary bit 1 secondary
|
||||||
Bit set for 40 pin */
|
Bit set for 40 pin */
|
||||||
|
@ -200,8 +200,9 @@ enum {
|
|||||||
ATA_CBL_NONE = 0,
|
ATA_CBL_NONE = 0,
|
||||||
ATA_CBL_PATA40 = 1,
|
ATA_CBL_PATA40 = 1,
|
||||||
ATA_CBL_PATA80 = 2,
|
ATA_CBL_PATA80 = 2,
|
||||||
ATA_CBL_PATA_UNK = 3,
|
ATA_CBL_PATA40_SHORT = 3, /* 40 wire cable to high UDMA spec */
|
||||||
ATA_CBL_SATA = 4,
|
ATA_CBL_PATA_UNK = 4,
|
||||||
|
ATA_CBL_SATA = 5,
|
||||||
|
|
||||||
/* SATA Status and Control Registers */
|
/* SATA Status and Control Registers */
|
||||||
SCR_STATUS = 0,
|
SCR_STATUS = 0,
|
||||||
@ -342,6 +343,15 @@ static inline int ata_id_is_cfa(const u16 *id)
|
|||||||
return 0;
|
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)
|
static inline int atapi_cdb_len(const u16 *dev_id)
|
||||||
{
|
{
|
||||||
u16 tmp = dev_id[0] & 0x3;
|
u16 tmp = dev_id[0] & 0x3;
|
||||||
|
Loading…
Reference in New Issue
Block a user