Skip to content

Commit

Permalink
pata_hpt{37x|3x2n}: SATA mode filtering
Browse files Browse the repository at this point in the history
The Marvell bridge chips used on HighPoint SATA cards do not seem to support
the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes;  these cards are
based on HPT372/372A/372N/374 chips (judging from the vendor drivers), so
the Linux drivers need to have a mode_filter() method for these chips...

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
  • Loading branch information
Sergei Shtylyov authored and Jeff Garzik committed Jan 8, 2011
1 parent b27dcfb commit 8e834c2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 22 deletions.
54 changes: 44 additions & 10 deletions drivers/ata/pata_hpt37x.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
* Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
* Portions Copyright (C) 2005-2010 MontaVista Software, Inc.
*
* TODO
* Look into engine reset on timeout errors. Should not be required.
Expand All @@ -24,7 +24,7 @@
#include <linux/libata.h>

#define DRV_NAME "pata_hpt37x"
#define DRV_VERSION "0.6.15"
#define DRV_VERSION "0.6.16"

struct hpt_clock {
u8 xfer_speed;
Expand Down Expand Up @@ -301,6 +301,22 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
return mask;
}

/**
* hpt372_filter - mode selection filter
* @adev: ATA device
* @mask: mode mask
*
* The Marvell bridge chips used on the HighPoint SATA cards do not seem
* to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
*/
static unsigned long hpt372_filter(struct ata_device *adev, unsigned long mask)
{
if (ata_id_is_sata(adev->id))
mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);

return mask;
}

/**
* hpt37x_cable_detect - Detect the cable type
* @ap: ATA port to detect on
Expand Down Expand Up @@ -586,11 +602,11 @@ static struct ata_port_operations hpt370a_port_ops = {
};

/*
* Configuration for HPT372, HPT371, HPT302. Slightly different PIO
* and DMA mode setting functionality.
* Configuration for HPT371 and HPT302. Slightly different PIO and DMA
* mode setting functionality.
*/

static struct ata_port_operations hpt372_port_ops = {
static struct ata_port_operations hpt302_port_ops = {
.inherits = &ata_bmdma_port_ops,

.bmdma_stop = hpt37x_bmdma_stop,
Expand All @@ -602,7 +618,17 @@ static struct ata_port_operations hpt372_port_ops = {
};

/*
* Configuration for HPT374. Mode setting works like 372 and friends
* Configuration for HPT372. Mode setting works like 371 and 302
* but we have a mode filter.
*/

static struct ata_port_operations hpt372_port_ops = {
.inherits = &hpt302_port_ops,
.mode_filter = hpt372_filter,
};

/*
* Configuration for HPT374. Mode setting and filtering works like 372
* but we have a different cable detection procedure for function 1.
*/

Expand Down Expand Up @@ -753,14 +779,22 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT371, 372 and friends - UDMA133 */
/* HPT372 - UDMA133 */
static const struct ata_port_info info_hpt372 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt372_port_ops
};
/* HPT371, 302 - UDMA133 */
static const struct ata_port_info info_hpt302 = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt302_port_ops
};
/* HPT374 - UDMA100, function 1 uses different prereset method */
static const struct ata_port_info info_hpt374_fn0 = {
.flags = ATA_FLAG_SLAVE_POSS,
Expand Down Expand Up @@ -828,7 +862,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
} else {
switch(dev->device) {
case PCI_DEVICE_ID_TTI_HPT372:
/* 372N if rev >= 2*/
/* 372N if rev >= 2 */
if (rev >= 2)
return -ENODEV;
ppi[0] = &info_hpt372;
Expand All @@ -838,14 +872,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* 302N if rev > 1 */
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt372;
ppi[0] = &info_hpt302;
/* Check this */
chip_table = &hpt302;
break;
case PCI_DEVICE_ID_TTI_HPT371:
if (rev > 1)
return -ENODEV;
ppi[0] = &info_hpt372;
ppi[0] = &info_hpt302;
chip_table = &hpt371;
/* Single channel device, master is not present
but the BIOS (or us for non x86) must mark it
Expand Down
61 changes: 49 additions & 12 deletions drivers/ata/pata_hpt3x2n.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
* Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
* Portions Copyright (C) 2005-2010 MontaVista Software, Inc.
*
*
* TODO
Expand All @@ -25,7 +25,7 @@
#include <linux/libata.h>

#define DRV_NAME "pata_hpt3x2n"
#define DRV_VERSION "0.3.10"
#define DRV_VERSION "0.3.11"

enum {
HPT_PCI_FAST = (1 << 31),
Expand Down Expand Up @@ -112,6 +112,22 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)
return 0xffffffffU; /* silence compiler warning */
}

/**
* hpt372n_filter - mode selection filter
* @adev: ATA device
* @mask: mode mask
*
* The Marvell bridge chips used on the HighPoint SATA cards do not seem
* to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
*/
static unsigned long hpt372n_filter(struct ata_device *adev, unsigned long mask)
{
if (ata_id_is_sata(adev->id))
mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);

return mask;
}

/**
* hpt3x2n_cable_detect - Detect the cable type
* @ap: ATA port to detect on
Expand Down Expand Up @@ -328,10 +344,10 @@ static struct scsi_host_template hpt3x2n_sht = {
};

/*
* Configuration for HPT3x2n.
* Configuration for HPT302N/371N.
*/

static struct ata_port_operations hpt3x2n_port_ops = {
static struct ata_port_operations hpt3xxn_port_ops = {
.inherits = &ata_bmdma_port_ops,

.bmdma_stop = hpt3x2n_bmdma_stop,
Expand All @@ -345,6 +361,15 @@ static struct ata_port_operations hpt3x2n_port_ops = {
.prereset = hpt3x2n_pre_reset,
};

/*
* Configuration for HPT372N. Same as 302N/371N but we have a mode filter.
*/

static struct ata_port_operations hpt372n_port_ops = {
.inherits = &hpt3xxn_port_ops,
.mode_filter = &hpt372n_filter,
};

/**
* hpt3xn_calibrate_dpll - Calibrate the DPLL loop
* @dev: PCI device
Expand Down Expand Up @@ -437,15 +462,23 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)

static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
/* HPT372N and friends - UDMA133 */
static const struct ata_port_info info = {
/* HPT372N - UDMA133 */
static const struct ata_port_info info_hpt372n = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt3x2n_port_ops
.port_ops = &hpt372n_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
/* HPT302N and HPT371N - UDMA133 */
static const struct ata_port_info info_hpt3xxn = {
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA6,
.port_ops = &hpt3xxn_port_ops
};
const struct ata_port_info *ppi[] = { &info_hpt3xxn, NULL };
u8 rev = dev->revision;
u8 irqmask;
unsigned int pci_mhz;
Expand All @@ -461,24 +494,28 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)

switch(dev->device) {
case PCI_DEVICE_ID_TTI_HPT366:
/* 372N if rev >= 6 */
if (rev < 6)
return -ENODEV;
break;
goto hpt372n;
case PCI_DEVICE_ID_TTI_HPT371:
/* 371N if rev >= 2 */
if (rev < 2)
return -ENODEV;
/* 371N if rev > 1 */
break;
case PCI_DEVICE_ID_TTI_HPT372:
/* 372N if rev >= 2*/
/* 372N if rev >= 2 */
if (rev < 2)
return -ENODEV;
break;
goto hpt372n;
case PCI_DEVICE_ID_TTI_HPT302:
/* 302N if rev >= 2 */
if (rev < 2)
return -ENODEV;
break;
case PCI_DEVICE_ID_TTI_HPT372N:
hpt372n:
ppi[0] = &info_hpt372n;
break;
default:
printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);
Expand Down

0 comments on commit 8e834c2

Please sign in to comment.