/*
* linux/drivers/ide/pci/siimage.c Version 1.11 Jan 27, 2007
*
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
* Copyright (C) 2007 MontaVista Software, Inc.
*
* May be copied or modified under the terms of the GNU General Public License
*
* Documentation for CMD680:
* http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2
*
* Documentation for SiI 3112:
* http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
*
* Errata and other documentation only available under NDA.
*
*
* FAQ Items:
* If you are using Marvell SATA-IDE adapters with Maxtor drives
* ensure the system is set up for ATA100/UDMA5 not UDMA6.
*
* If you are using WD drives with SATA bridges you must set the
* drive to "Single". "Master" will hang
*
* If you have strange problems with nVidia chipset systems please
* see the SI support documentation and update your system BIOS
* if neccessary
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
/**
* pdev_is_sata - check if device is SATA
* @pdev: PCI device to check
*
* Returns true if this is a SATA controller
*/
static int pdev_is_sata(struct pci_dev *pdev)
{
switch(pdev->device)
{
case PCI_DEVICE_ID_SII_3112:
case PCI_DEVICE_ID_SII_1210SA:
return 1;
case PCI_DEVICE_ID_SII_680:
return 0;
}
BUG();
return 0;
}
/**
* is_sata - check if hwif is SATA
* @hwif: interface to check
*
* Returns true if this is a SATA controller
*/
static inline int is_sata(ide_hwif_t *hwif)
{
return pdev_is_sata(hwif->pci_dev);
}
/**
* siimage_selreg - return register base
* @hwif: interface
* @r: config offset
*
* Turn a config register offset into the right address in either
* PCI space or MMIO space to access the control register in question
* Thankfully this is a configuration operation so isnt performance
* criticial.
*/
static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
{
unsigned long base = (unsigned long)hwif->hwif_data;
base += 0xA0 + r;
if(hwif->mmio)
base += (hwif->channel << 6);
else
base += (hwif->channel << 4);
return base;
}
/**
* siimage_seldev - return register base
* @hwif: interface
* @r: config offset
*
* Turn a config register offset into the right address in either
* PCI space or MMIO space to access the control register in question
* including accounting for the unit shift.
*/
static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long base = (unsigned long)hwif->hwif_data;
base += 0xA0 + r;
if(hwif->mmio)
base += (hwif->channel << 6);
else
base += (hwif->channel << 4);
base |= drive->select.b.unit << drive->select.b.unit;
return base;
}
/**
* siimage_ratemask - Compute available modes
* @drive: IDE drive
*
* Compute the available speeds for the devices on the interface.
* For the CMD680 this depends on the clocking mode (scsc), for the
* SI3312 SATA controller life is a bit simpler. Enforce UDMA33
* as a limit if there is no 80pin cable present.
*/
static byte siimage_ratemask (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 mode = 0, scsc = 0;
unsigned long base = (unsigned long) hwif->hwif_data;
if (hwif->mmio)
scsc = hwif->INB(base + 0x4A);
else
pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
if(is_sata(hwif))
{
if(strstr(drive->id->model, "Maxtor"))
return 3;
return 4;
}
if ((scsc & 0x30) == 0x10) /* 133 */
mode = 4;
else if ((scsc & 0x30) == 0x20) /* 2xPCI */
mode = 4;
else if ((scsc & 0x30) == 0x00) /* 100 */
mode = 3;
else /* Disabled ? */
BUG();
if (!eighty_ninty_three(drive))
mode = min(mode, (u8)1);
return mode;
}
/**
* siimage_taskfile_timing - turn timing data to a mode
* @hwif: interface to query
*
* Read the timing data for the interface and return the
* mode that is being used.
*/