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

Commit 2ba14a01 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (67 commits)
  fix drivers/ata/sata_fsl.c double-decl
  [libata] Prefer SCSI_SENSE_BUFFERSIZE to sizeof()
  pata_legacy: Merge winbond support
  ata_generic: Cenatek support
  pata_winbond: error return
  pata_serverworks: Fix cable types and cosmetics
  pata_mpc52xx: remove un-needed assignment
  libata: fix off-by-one in error categorization
  ahci: factor out AHCI enabling and enable AHCI before reading CAP
  ata_piix: implement SIDPR SCR access
  ata_piix: convert to prepare - activate initialization
  libata: factor out ata_pci_activate_sff_host() from ata_pci_one()
  [libata] Prefer SCSI_SENSE_BUFFERSIZE to sizeof()
  pata_legacy: resychronize with upstream changes and resubmit
  [libata] pata_legacy: typo fix
  [libata] pata_winbond: update for new ->data_xfer hook
  pata_pcmcia: convert to new data_xfer prototype
  libata annotations and fixes
  libata: use dev_driver_string() instead of "libata" in libata-sff.c
  ata_piix: kill unused constants and flags
  ...
parents 99f1c97d a984f58d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -459,6 +459,15 @@ config PATA_NETCELL

	  If unsure, say N.

config PATA_NINJA32
	tristate "Ninja32/Delkin Cardbus ATA support (Experimental)"
	depends on PCI && EXPERIMENTAL
	help
	  This option enables support for the Ninja32, Delkin and
	  possibly other brands of Cardbus ATA adapter

	  If unsure, say N.

config PATA_NS87410
	tristate "Nat Semi NS87410 PATA support (Experimental)"
	depends on PCI && EXPERIMENTAL
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ obj-$(CONFIG_PATA_IT821X) += pata_it821x.o
obj-$(CONFIG_PATA_IT8213)	+= pata_it8213.o
obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o
obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o
obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o
obj-$(CONFIG_PATA_NS87410)	+= pata_ns87410.o
obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o
obj-$(CONFIG_PATA_OPTI)		+= pata_opti.o
+42 −30
Original line number Diff line number Diff line
@@ -198,18 +198,18 @@ enum {
};

struct ahci_cmd_hdr {
	u32			opts;
	u32			status;
	u32			tbl_addr;
	u32			tbl_addr_hi;
	u32			reserved[4];
	__le32			opts;
	__le32			status;
	__le32			tbl_addr;
	__le32			tbl_addr_hi;
	__le32			reserved[4];
};

struct ahci_sg {
	u32			addr;
	u32			addr_hi;
	u32			reserved;
	u32			flags_size;
	__le32			addr;
	__le32			addr_hi;
	__le32			reserved;
	__le32			flags_size;
};

struct ahci_host_priv {
@@ -597,6 +597,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
	return __ahci_port_base(ap->host, ap->port_no);
}

static void ahci_enable_ahci(void __iomem *mmio)
{
	u32 tmp;

	/* turn on AHCI_EN */
	tmp = readl(mmio + HOST_CTL);
	if (!(tmp & HOST_AHCI_EN)) {
		tmp |= HOST_AHCI_EN;
		writel(tmp, mmio + HOST_CTL);
		tmp = readl(mmio + HOST_CTL);	/* flush && sanity check */
		WARN_ON(!(tmp & HOST_AHCI_EN));
	}
}

/**
 *	ahci_save_initial_config - Save and fixup initial config values
 *	@pdev: target PCI device
@@ -619,6 +633,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
	u32 cap, port_map;
	int i;

	/* make sure AHCI mode is enabled before accessing CAP */
	ahci_enable_ahci(mmio);

	/* Values prefixed with saved_ are written back to host after
	 * reset.  Values without are used for driver operation.
	 */
@@ -1036,19 +1053,17 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
static int ahci_reset_controller(struct ata_host *host)
{
	struct pci_dev *pdev = to_pci_dev(host->dev);
	struct ahci_host_priv *hpriv = host->private_data;
	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
	u32 tmp;

	/* we must be in AHCI mode, before using anything
	 * AHCI-specific, such as HOST_RESET.
	 */
	tmp = readl(mmio + HOST_CTL);
	if (!(tmp & HOST_AHCI_EN)) {
		tmp |= HOST_AHCI_EN;
		writel(tmp, mmio + HOST_CTL);
	}
	ahci_enable_ahci(mmio);

	/* global controller reset */
	tmp = readl(mmio + HOST_CTL);
	if ((tmp & HOST_RESET) == 0) {
		writel(tmp | HOST_RESET, mmio + HOST_CTL);
		readl(mmio + HOST_CTL); /* flush */
@@ -1067,8 +1082,7 @@ static int ahci_reset_controller(struct ata_host *host)
	}

	/* turn on AHCI mode */
	writel(HOST_AHCI_EN, mmio + HOST_CTL);
	(void) readl(mmio + HOST_CTL);	/* flush */
	ahci_enable_ahci(mmio);

	/* some registers might be cleared on reset.  restore initial values */
	ahci_restore_initial_config(host);
@@ -1078,9 +1092,11 @@ static int ahci_reset_controller(struct ata_host *host)

		/* configure PCS */
		pci_read_config_word(pdev, 0x92, &tmp16);
		tmp16 |= 0xf;
		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
			tmp16 |= hpriv->port_map;
			pci_write_config_word(pdev, 0x92, tmp16);
		}
	}

	return 0;
}
@@ -1480,35 +1496,31 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
{
	struct scatterlist *sg;
	struct ahci_sg *ahci_sg;
	unsigned int n_sg = 0;
	struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
	unsigned int si;

	VPRINTK("ENTER\n");

	/*
	 * Next, the S/G list.
	 */
	ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
	ata_for_each_sg(sg, qc) {
	for_each_sg(qc->sg, sg, qc->n_elem, si) {
		dma_addr_t addr = sg_dma_address(sg);
		u32 sg_len = sg_dma_len(sg);

		ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
		ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
		ahci_sg->flags_size = cpu_to_le32(sg_len - 1);

		ahci_sg++;
		n_sg++;
		ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
		ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
		ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
	}

	return n_sg;
	return si;
}

static void ahci_qc_prep(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	struct ahci_port_priv *pp = ap->private_data;
	int is_atapi = is_atapi_taskfile(&qc->tf);
	int is_atapi = ata_is_atapi(qc->tf.protocol);
	void *cmd_tbl;
	u32 opts;
	const u32 cmd_fis_len = 5; /* five dwords */
+36 −15
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
#include <linux/libata.h>

#define DRV_NAME "ata_generic"
#define DRV_VERSION "0.2.13"
#define DRV_VERSION "0.2.15"

/*
 *	A generic parallel ATA driver using libata
@@ -48,20 +48,41 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
	struct ata_port *ap = link->ap;
	int dma_enabled = 0;
	struct ata_device *dev;
	struct pci_dev *pdev = to_pci_dev(ap->host->dev);

	/* Bits 5 and 6 indicate if DMA is active on master/slave */
	if (ap->ioaddr.bmdma_addr)
		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);

	if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
		dma_enabled = 0xFF;

	ata_link_for_each_dev(dev, link) {
		if (ata_dev_enabled(dev)) {
		if (!ata_dev_enabled(dev))
			continue;

		/* We don't really care */
		dev->pio_mode = XFER_PIO_0;
		dev->dma_mode = XFER_MW_DMA_0;
		/* We do need the right mode information for DMA or PIO
		   and this comes from the current configuration flags */
		if (dma_enabled & (1 << (5 + dev->devno))) {
				ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
			unsigned int xfer_mask = ata_id_xfermask(dev->id);
			const char *name;

			if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA))
				name = ata_mode_string(xfer_mask);
			else {
				/* SWDMA perhaps? */
				name = "DMA";
				xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
			}

			ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
				       name);

			dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
			dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
			dev->flags &= ~ATA_DFLAG_PIO;
		} else {
			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
@@ -70,7 +91,6 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
			dev->flags |= ATA_DFLAG_PIO;
		}
	}
	}
	return 0;
}

@@ -185,6 +205,7 @@ static struct pci_device_id ata_generic[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },
	{ PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },
	{ PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
+317 −76
Original line number Diff line number Diff line
@@ -101,25 +101,39 @@ enum {
	ICH5_PMR		= 0x90, /* port mapping register */
	ICH5_PCS		= 0x92,	/* port control and status */
	PIIX_SCC		= 0x0A, /* sub-class code register */
	PIIX_SIDPR_BAR		= 5,
	PIIX_SIDPR_LEN		= 16,
	PIIX_SIDPR_IDX		= 0,
	PIIX_SIDPR_DATA		= 4,

	PIIX_FLAG_SCR		= (1 << 26), /* SCR available */
	PIIX_FLAG_AHCI		= (1 << 27), /* AHCI possible */
	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */
	PIIX_FLAG_SIDPR		= (1 << 29), /* SATA idx/data pair regs */

	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,
	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,

	/* combined mode.  if set, PATA is channel 0.
	 * if clear, PATA is channel 1.
	 */
	PIIX_PORT_ENABLED	= (1 << 0),
	PIIX_PORT_PRESENT	= (1 << 4),

	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
	PIIX_80C_SEC		= (1 << 7) | (1 << 6),

	/* constants for mapping table */
	P0			= 0,  /* port 0 */
	P1			= 1,  /* port 1 */
	P2			= 2,  /* port 2 */
	P3			= 3,  /* port 3 */
	IDE			= -1, /* IDE */
	NA			= -2, /* not avaliable */
	RV			= -3, /* reserved */

	PIIX_AHCI_DEVICE	= 6,

	/* host->flags bits */
	PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
};

enum piix_controller_ids {
	/* controller IDs */
	piix_pata_mwdma		= 0,	/* PIIX3 MWDMA only */
	piix_pata_mwdma,	/* PIIX3 MWDMA only */
	piix_pata_33,		/* PIIX4 at 33Mhz */
	ich_pata_33,		/* ICH up to UDMA 33 only */
	ich_pata_66,		/* ICH up to 66 Mhz */
@@ -133,20 +147,6 @@ enum {
	ich8m_apple_sata_ahci,	/* locks up on second port enable */
	tolapai_sata_ahci,
	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */

	/* constants for mapping table */
	P0			= 0,  /* port 0 */
	P1			= 1,  /* port 1 */
	P2			= 2,  /* port 2 */
	P3			= 3,  /* port 3 */
	IDE			= -1, /* IDE */
	NA			= -2, /* not avaliable */
	RV			= -3, /* reserved */

	PIIX_AHCI_DEVICE	= 6,

	/* host->flags bits */
	PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
};

struct piix_map_db {
@@ -157,6 +157,7 @@ struct piix_map_db {

struct piix_host_priv {
	const int *map;
	void __iomem *sidpr;
};

static int piix_init_one(struct pci_dev *pdev,
@@ -167,6 +168,9 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
static u8 piix_vmw_bmdma_status(struct ata_port *ap);
static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
static void piix_sidpr_error_handler(struct ata_port *ap);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int piix_pci_device_resume(struct pci_dev *pdev);
@@ -321,7 +325,6 @@ static const struct ata_port_operations piix_pata_ops = {
	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
	.cable_detect		= ata_cable_40wire,

	.irq_handler		= ata_interrupt,
	.irq_clear		= ata_bmdma_irq_clear,
	.irq_on			= ata_irq_on,

@@ -353,7 +356,6 @@ static const struct ata_port_operations ich_pata_ops = {
	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
	.cable_detect		= ich_pata_cable_detect,

	.irq_handler		= ata_interrupt,
	.irq_clear		= ata_bmdma_irq_clear,
	.irq_on			= ata_irq_on,

@@ -380,7 +382,6 @@ static const struct ata_port_operations piix_sata_ops = {
	.error_handler		= ata_bmdma_error_handler,
	.post_internal_cmd	= ata_bmdma_post_internal_cmd,

	.irq_handler		= ata_interrupt,
	.irq_clear		= ata_bmdma_irq_clear,
	.irq_on			= ata_irq_on,

@@ -419,6 +420,35 @@ static const struct ata_port_operations piix_vmw_ops = {
	.port_start		= ata_port_start,
};

static const struct ata_port_operations piix_sidpr_sata_ops = {
	.tf_load		= ata_tf_load,
	.tf_read		= ata_tf_read,
	.check_status		= ata_check_status,
	.exec_command		= ata_exec_command,
	.dev_select		= ata_std_dev_select,

	.bmdma_setup		= ata_bmdma_setup,
	.bmdma_start		= ata_bmdma_start,
	.bmdma_stop		= ata_bmdma_stop,
	.bmdma_status		= ata_bmdma_status,
	.qc_prep		= ata_qc_prep,
	.qc_issue		= ata_qc_issue_prot,
	.data_xfer		= ata_data_xfer,

	.scr_read		= piix_sidpr_scr_read,
	.scr_write		= piix_sidpr_scr_write,

	.freeze			= ata_bmdma_freeze,
	.thaw			= ata_bmdma_thaw,
	.error_handler		= piix_sidpr_error_handler,
	.post_internal_cmd	= ata_bmdma_post_internal_cmd,

	.irq_clear		= ata_bmdma_irq_clear,
	.irq_on			= ata_irq_on,

	.port_start		= ata_port_start,
};

static const struct piix_map_db ich5_map_db = {
	.mask = 0x7,
	.port_enable = 0x3,
@@ -526,7 +556,6 @@ static const struct piix_map_db *piix_map_db_table[] = {
static struct ata_port_info piix_port_info[] = {
	[piix_pata_mwdma] = 	/* PIIX3 MWDMA only */
	{
		.sht		= &piix_sht,
		.flags		= PIIX_PATA_FLAGS,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
@@ -535,7 +564,6 @@ static struct ata_port_info piix_port_info[] = {

	[piix_pata_33] =	/* PIIX4 at 33MHz */
	{
		.sht		= &piix_sht,
		.flags		= PIIX_PATA_FLAGS,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
@@ -545,7 +573,6 @@ static struct ata_port_info piix_port_info[] = {

	[ich_pata_33] = 	/* ICH0 - ICH at 33Mhz*/
	{
		.sht		= &piix_sht,
		.flags		= PIIX_PATA_FLAGS,
		.pio_mask 	= 0x1f,	/* pio 0-4 */
		.mwdma_mask	= 0x06, /* Check: maybe 0x07  */
@@ -555,7 +582,6 @@ static struct ata_port_info piix_port_info[] = {

	[ich_pata_66] = 	/* ICH controllers up to 66MHz */
	{
		.sht		= &piix_sht,
		.flags		= PIIX_PATA_FLAGS,
		.pio_mask 	= 0x1f,	/* pio 0-4 */
		.mwdma_mask	= 0x06, /* MWDMA0 is broken on chip */
@@ -565,7 +591,6 @@ static struct ata_port_info piix_port_info[] = {

	[ich_pata_100] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x06, /* mwdma1-2 */
@@ -575,7 +600,6 @@ static struct ata_port_info piix_port_info[] = {

	[ich5_sata] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
@@ -585,8 +609,7 @@ static struct ata_port_info piix_port_info[] = {

	[ich6_sata] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
		.flags		= PIIX_SATA_FLAGS,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -595,9 +618,7 @@ static struct ata_port_info piix_port_info[] = {

	[ich6_sata_ahci] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
				  PIIX_FLAG_AHCI,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -606,9 +627,7 @@ static struct ata_port_info piix_port_info[] = {

	[ich6m_sata_ahci] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
				  PIIX_FLAG_AHCI,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -617,9 +636,8 @@ static struct ata_port_info piix_port_info[] = {

	[ich8_sata_ahci] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
				  PIIX_FLAG_AHCI,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
				  PIIX_FLAG_SIDPR,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -628,9 +646,8 @@ static struct ata_port_info piix_port_info[] = {

	[ich8_2port_sata] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
				  PIIX_FLAG_AHCI,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
				  PIIX_FLAG_SIDPR,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -639,9 +656,7 @@ static struct ata_port_info piix_port_info[] = {

	[tolapai_sata_ahci] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
				  PIIX_FLAG_AHCI,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -650,9 +665,8 @@ static struct ata_port_info piix_port_info[] = {

	[ich8m_apple_sata_ahci] =
	{
		.sht		= &piix_sht,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
				  PIIX_FLAG_AHCI,
		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
				  PIIX_FLAG_SIDPR,
		.pio_mask	= 0x1f,	/* pio0-4 */
		.mwdma_mask	= 0x07, /* mwdma0-2 */
		.udma_mask	= ATA_UDMA6,
@@ -1001,6 +1015,180 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
	do_pata_set_dmamode(ap, adev, 1);
}

/*
 * Serial ATA Index/Data Pair Superset Registers access
 *
 * Beginning from ICH8, there's a sane way to access SCRs using index
 * and data register pair located at BAR5.  This creates an
 * interesting problem of mapping two SCRs to one port.
 *
 * Although they have separate SCRs, the master and slave aren't
 * independent enough to be treated as separate links - e.g. softreset
 * resets both.  Also, there's no protocol defined for hard resetting
 * singled device sharing the virtual port (no defined way to acquire
 * device signature).  This is worked around by merging the SCR values
 * into one sensible value and requesting follow-up SRST after
 * hardreset.
 *
 * SCR merging is perfomed in nibbles which is the unit contents in
 * SCRs are organized.  If two values are equal, the value is used.
 * When they differ, merge table which lists precedence of possible
 * values is consulted and the first match or the last entry when
 * nothing matches is used.  When there's no merge table for the
 * specific nibble, value from the first port is used.
 */
static const int piix_sidx_map[] = {
	[SCR_STATUS]	= 0,
	[SCR_ERROR]	= 2,
	[SCR_CONTROL]	= 1,
};

static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
{
	struct ata_port *ap = dev->link->ap;
	struct piix_host_priv *hpriv = ap->host->private_data;

	iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
		  hpriv->sidpr + PIIX_SIDPR_IDX);
}

static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
{
	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;

	piix_sidpr_sel(dev, reg);
	return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
}

static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
{
	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;

	piix_sidpr_sel(dev, reg);
	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
}

u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
{
	u32 val = 0;
	int i, mi;

	for (i = 0, mi = 0; i < 32 / 4; i++) {
		u8 c0 = (val0 >> (i * 4)) & 0xf;
		u8 c1 = (val1 >> (i * 4)) & 0xf;
		u8 merged = c0;
		const int *cur;

		/* if no merge preference, assume the first value */
		cur = merge_tbl[mi];
		if (!cur)
			goto done;
		mi++;

		/* if two values equal, use it */
		if (c0 == c1)
			goto done;

		/* choose the first match or the last from the merge table */
		while (*cur != -1) {
			if (c0 == *cur || c1 == *cur)
				break;
			cur++;
		}
		if (*cur == -1)
			cur--;
		merged = *cur;
	done:
		val |= merged << (i * 4);
	}

	return val;
}

static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
{
	const int * const sstatus_merge_tbl[] = {
		/* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
		/* SPD */ (const int []){ 2, 1, 0, -1 },
		/* IPM */ (const int []){ 6, 2, 1, 0, -1 },
		NULL,
	};
	const int * const scontrol_merge_tbl[] = {
		/* DET */ (const int []){ 1, 0, 4, 0, -1 },
		/* SPD */ (const int []){ 0, 2, 1, 0, -1 },
		/* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
		NULL,
	};
	u32 v0, v1;

	if (reg >= ARRAY_SIZE(piix_sidx_map))
		return -EINVAL;

	if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
		*val = piix_sidpr_read(&ap->link.device[0], reg);
		return 0;
	}

	v0 = piix_sidpr_read(&ap->link.device[0], reg);
	v1 = piix_sidpr_read(&ap->link.device[1], reg);

	switch (reg) {
	case SCR_STATUS:
		*val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
		break;
	case SCR_ERROR:
		*val = v0 | v1;
		break;
	case SCR_CONTROL:
		*val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
		break;
	}

	return 0;
}

static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
{
	if (reg >= ARRAY_SIZE(piix_sidx_map))
		return -EINVAL;

	piix_sidpr_write(&ap->link.device[0], reg, val);

	if (ap->flags & ATA_FLAG_SLAVE_POSS)
		piix_sidpr_write(&ap->link.device[1], reg, val);

	return 0;
}

static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
				unsigned long deadline)
{
	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
	int rc;

	/* do hardreset */
	rc = sata_link_hardreset(link, timing, deadline);
	if (rc) {
		ata_link_printk(link, KERN_ERR,
				"COMRESET failed (errno=%d)\n", rc);
		return rc;
	}

	/* TODO: phy layer with polling, timeouts, etc. */
	if (ata_link_offline(link)) {
		*class = ATA_DEV_NONE;
		return 0;
	}

	return -EAGAIN;
}

static void piix_sidpr_error_handler(struct ata_port *ap)
{
	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
			   piix_sidpr_hardreset, ata_std_postreset);
}

#ifdef CONFIG_PM
static int piix_broken_suspend(void)
{
@@ -1033,6 +1221,13 @@ static int piix_broken_suspend(void)
				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"),
			},
		},
		{
			.ident = "TECRA M6",
			.matches = {
				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"),
			},
		},
		{
			.ident = "TECRA M7",
			.matches = {
@@ -1047,6 +1242,13 @@ static int piix_broken_suspend(void)
				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"),
			},
		},
		{
			.ident = "Satellite R20",
			.matches = {
				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"),
			},
		},
		{
			.ident = "Satellite R25",
			.matches = {
@@ -1253,10 +1455,10 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
	return no_piix_dma;
}

static void __devinit piix_init_pcs(struct pci_dev *pdev,
				    struct ata_port_info *pinfo,
static void __devinit piix_init_pcs(struct ata_host *host,
				    const struct piix_map_db *map_db)
{
	struct pci_dev *pdev = to_pci_dev(host->dev);
	u16 pcs, new_pcs;

	pci_read_config_word(pdev, ICH5_PCS, &pcs);
@@ -1270,11 +1472,10 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
	}
}

static void __devinit piix_init_sata_map(struct pci_dev *pdev,
static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
					       struct ata_port_info *pinfo,
					       const struct piix_map_db *map_db)
{
	struct piix_host_priv *hpriv = pinfo[0].private_data;
	const int *map;
	int i, invalid_map = 0;
	u8 map_value;
@@ -1298,7 +1499,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
		case IDE:
			WARN_ON((i & 1) || map[i + 1] != IDE);
			pinfo[i / 2] = piix_port_info[ich_pata_100];
			pinfo[i / 2].private_data = hpriv;
			i++;
			printk(" IDE IDE");
			break;
@@ -1316,7 +1516,33 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
		dev_printk(KERN_ERR, &pdev->dev,
			   "invalid MAP value %u\n", map_value);

	hpriv->map = map;
	return map;
}

static void __devinit piix_init_sidpr(struct ata_host *host)
{
	struct pci_dev *pdev = to_pci_dev(host->dev);
	struct piix_host_priv *hpriv = host->private_data;
	int i;

	/* check for availability */
	for (i = 0; i < 4; i++)
		if (hpriv->map[i] == IDE)
			return;

	if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
		return;

	if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
	    pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
		return;

	if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
		return;

	hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
	host->ports[0]->ops = &piix_sidpr_sata_ops;
	host->ports[1]->ops = &piix_sidpr_sata_ops;
}

static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
@@ -1375,8 +1601,10 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	struct device *dev = &pdev->dev;
	struct ata_port_info port_info[2];
	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
	struct piix_host_priv *hpriv;
	unsigned long port_flags;
	struct ata_host *host;
	struct piix_host_priv *hpriv;
	int rc;

	if (!printed_version++)
		dev_printk(KERN_DEBUG, &pdev->dev,
@@ -1386,17 +1614,31 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (!in_module_init)
		return -ENODEV;

	port_info[0] = piix_port_info[ent->driver_data];
	port_info[1] = piix_port_info[ent->driver_data];

	port_flags = port_info[0].flags;

	/* enable device and prepare host */
	rc = pcim_enable_device(pdev);
	if (rc)
		return rc;

	/* SATA map init can change port_info, do it before prepping host */
	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
	if (!hpriv)
		return -ENOMEM;

	port_info[0] = piix_port_info[ent->driver_data];
	port_info[1] = piix_port_info[ent->driver_data];
	port_info[0].private_data = hpriv;
	port_info[1].private_data = hpriv;
	if (port_flags & ATA_FLAG_SATA)
		hpriv->map = piix_init_sata_map(pdev, port_info,
					piix_map_db_table[ent->driver_data]);

	port_flags = port_info[0].flags;
	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
	if (rc)
		return rc;
	host->private_data = hpriv;

	/* initialize controller */
	if (port_flags & PIIX_FLAG_AHCI) {
		u8 tmp;
		pci_read_config_byte(pdev, PIIX_SCC, &tmp);
@@ -1407,12 +1649,9 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		}
	}

	/* Initialize SATA map */
	if (port_flags & ATA_FLAG_SATA) {
		piix_init_sata_map(pdev, port_info,
				   piix_map_db_table[ent->driver_data]);
		piix_init_pcs(pdev, port_info,
			      piix_map_db_table[ent->driver_data]);
		piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
		piix_init_sidpr(host);
	}

	/* apply IOCFG bit18 quirk */
@@ -1431,12 +1670,14 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		/* This writes into the master table but it does not
		   really matter for this errata as we will apply it to
		   all the PIIX devices on the board */
		port_info[0].mwdma_mask = 0;
		port_info[0].udma_mask = 0;
		port_info[1].mwdma_mask = 0;
		port_info[1].udma_mask = 0;
		host->ports[0]->mwdma_mask = 0;
		host->ports[0]->udma_mask = 0;
		host->ports[1]->mwdma_mask = 0;
		host->ports[1]->udma_mask = 0;
	}
	return ata_pci_init_one(pdev, ppi);

	pci_set_master(pdev);
	return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
}

static int __init piix_init(void)
Loading