18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
38c2ecf20Sopenharmony_ci * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
48c2ecf20Sopenharmony_ci * Copyright (C) 2003		Vojtech Pavlik <vojtech@suse.cz>
58c2ecf20Sopenharmony_ci * Copyright (C) 2007-2009	Bartlomiej Zolnierkiewicz
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * May be copied or modified under the terms of the GNU General Public License
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Thanks :
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * SiS Taiwan		: for direct support and hardware.
138c2ecf20Sopenharmony_ci * Daniela Engert	: for initial ATA100 advices and numerous others.
148c2ecf20Sopenharmony_ci * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt	:
158c2ecf20Sopenharmony_ci *			  for checking code correctness, providing patches.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * Original tests and design on the SiS620 chipset.
198c2ecf20Sopenharmony_ci * ATA100 tests and design on the SiS735 chipset.
208c2ecf20Sopenharmony_ci * ATA16/33 support from specs
218c2ecf20Sopenharmony_ci * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw>
228c2ecf20Sopenharmony_ci * ATA133 961/962/963 fixes by Vojtech Pavlik <vojtech@suse.cz>
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Documentation:
258c2ecf20Sopenharmony_ci *	SiS chipset documentation available under NDA to companies only
268c2ecf20Sopenharmony_ci *      (not to individuals).
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/*
308c2ecf20Sopenharmony_ci * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original
318c2ecf20Sopenharmony_ci * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511
328c2ecf20Sopenharmony_ci * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip.
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Later SiS chipsets integrated the 5513 functionality into the NorthBridge,
358c2ecf20Sopenharmony_ci * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We
368c2ecf20Sopenharmony_ci * can figure out that we have a more modern and more capable 5513 by looking
378c2ecf20Sopenharmony_ci * for the respective NorthBridge IDs.
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513
408c2ecf20Sopenharmony_ci * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI
418c2ecf20Sopenharmony_ci * ID, while the now ATA-133 capable 5513 still has the same PCI ID.
428c2ecf20Sopenharmony_ci * Fortunately the 5513 can be 'unmasked' by fiddling with some config space
438c2ecf20Sopenharmony_ci * bits, changing its device id to the true one - 5517 for 961 and 5518 for
448c2ecf20Sopenharmony_ci * 962/963.
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#include <linux/types.h>
488c2ecf20Sopenharmony_ci#include <linux/module.h>
498c2ecf20Sopenharmony_ci#include <linux/kernel.h>
508c2ecf20Sopenharmony_ci#include <linux/pci.h>
518c2ecf20Sopenharmony_ci#include <linux/init.h>
528c2ecf20Sopenharmony_ci#include <linux/ide.h>
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define DRV_NAME "sis5513"
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* registers layout and init values are chipset family dependent */
578c2ecf20Sopenharmony_ci#undef ATA_16
588c2ecf20Sopenharmony_ci#define ATA_16		0x01
598c2ecf20Sopenharmony_ci#define ATA_33		0x02
608c2ecf20Sopenharmony_ci#define ATA_66		0x03
618c2ecf20Sopenharmony_ci#define ATA_100a	0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
628c2ecf20Sopenharmony_ci#define ATA_100		0x05
638c2ecf20Sopenharmony_ci#define ATA_133a	0x06 /* SiS961b with 133 support */
648c2ecf20Sopenharmony_ci#define ATA_133		0x07 /* SiS962/963 */
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic u8 chipset_family;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/*
698c2ecf20Sopenharmony_ci * Devices supported
708c2ecf20Sopenharmony_ci */
718c2ecf20Sopenharmony_cistatic const struct {
728c2ecf20Sopenharmony_ci	const char *name;
738c2ecf20Sopenharmony_ci	u16 host_id;
748c2ecf20Sopenharmony_ci	u8 chipset_family;
758c2ecf20Sopenharmony_ci	u8 flags;
768c2ecf20Sopenharmony_ci} SiSHostChipInfo[] = {
778c2ecf20Sopenharmony_ci	{ "SiS968",	PCI_DEVICE_ID_SI_968,	ATA_133  },
788c2ecf20Sopenharmony_ci	{ "SiS966",	PCI_DEVICE_ID_SI_966,	ATA_133  },
798c2ecf20Sopenharmony_ci	{ "SiS965",	PCI_DEVICE_ID_SI_965,	ATA_133  },
808c2ecf20Sopenharmony_ci	{ "SiS745",	PCI_DEVICE_ID_SI_745,	ATA_100  },
818c2ecf20Sopenharmony_ci	{ "SiS735",	PCI_DEVICE_ID_SI_735,	ATA_100  },
828c2ecf20Sopenharmony_ci	{ "SiS733",	PCI_DEVICE_ID_SI_733,	ATA_100  },
838c2ecf20Sopenharmony_ci	{ "SiS635",	PCI_DEVICE_ID_SI_635,	ATA_100  },
848c2ecf20Sopenharmony_ci	{ "SiS633",	PCI_DEVICE_ID_SI_633,	ATA_100  },
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	{ "SiS730",	PCI_DEVICE_ID_SI_730,	ATA_100a },
878c2ecf20Sopenharmony_ci	{ "SiS550",	PCI_DEVICE_ID_SI_550,	ATA_100a },
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	{ "SiS640",	PCI_DEVICE_ID_SI_640,	ATA_66   },
908c2ecf20Sopenharmony_ci	{ "SiS630",	PCI_DEVICE_ID_SI_630,	ATA_66   },
918c2ecf20Sopenharmony_ci	{ "SiS620",	PCI_DEVICE_ID_SI_620,	ATA_66   },
928c2ecf20Sopenharmony_ci	{ "SiS540",	PCI_DEVICE_ID_SI_540,	ATA_66   },
938c2ecf20Sopenharmony_ci	{ "SiS530",	PCI_DEVICE_ID_SI_530,	ATA_66   },
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	{ "SiS5600",	PCI_DEVICE_ID_SI_5600,	ATA_33   },
968c2ecf20Sopenharmony_ci	{ "SiS5598",	PCI_DEVICE_ID_SI_5598,	ATA_33   },
978c2ecf20Sopenharmony_ci	{ "SiS5597",	PCI_DEVICE_ID_SI_5597,	ATA_33   },
988c2ecf20Sopenharmony_ci	{ "SiS5591/2",	PCI_DEVICE_ID_SI_5591,	ATA_33   },
998c2ecf20Sopenharmony_ci	{ "SiS5582",	PCI_DEVICE_ID_SI_5582,	ATA_33   },
1008c2ecf20Sopenharmony_ci	{ "SiS5581",	PCI_DEVICE_ID_SI_5581,	ATA_33   },
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	{ "SiS5596",	PCI_DEVICE_ID_SI_5596,	ATA_16   },
1038c2ecf20Sopenharmony_ci	{ "SiS5571",	PCI_DEVICE_ID_SI_5571,	ATA_16   },
1048c2ecf20Sopenharmony_ci	{ "SiS5517",	PCI_DEVICE_ID_SI_5517,	ATA_16   },
1058c2ecf20Sopenharmony_ci	{ "SiS551x",	PCI_DEVICE_ID_SI_5511,	ATA_16   },
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci/* Cycle time bits and values vary across chip dma capabilities
1098c2ecf20Sopenharmony_ci   These three arrays hold the register layout and the values to set.
1108c2ecf20Sopenharmony_ci   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
1138c2ecf20Sopenharmony_cistatic u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
1148c2ecf20Sopenharmony_cistatic u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
1158c2ecf20Sopenharmony_cistatic u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
1168c2ecf20Sopenharmony_ci	{  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
1178c2ecf20Sopenharmony_ci	{  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
1188c2ecf20Sopenharmony_ci	{  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
1198c2ecf20Sopenharmony_ci	{  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
1208c2ecf20Sopenharmony_ci	{  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
1218c2ecf20Sopenharmony_ci				      different cycle_time range and offset */
1228c2ecf20Sopenharmony_ci	{ 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
1238c2ecf20Sopenharmony_ci	{ 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
1248c2ecf20Sopenharmony_ci	{ 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
1258c2ecf20Sopenharmony_ci};
1268c2ecf20Sopenharmony_ci/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
1278c2ecf20Sopenharmony_ci   See SiS962 data sheet for more detail */
1288c2ecf20Sopenharmony_cistatic u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
1298c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
1308c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
1318c2ecf20Sopenharmony_ci	{ 2, 1, 1, 0, 0, 0, 0 },
1328c2ecf20Sopenharmony_ci	{ 4, 3, 2, 1, 0, 0, 0 },
1338c2ecf20Sopenharmony_ci	{ 4, 3, 2, 1, 0, 0, 0 },
1348c2ecf20Sopenharmony_ci	{ 6, 4, 3, 1, 1, 1, 0 },
1358c2ecf20Sopenharmony_ci	{ 9, 6, 4, 2, 2, 2, 2 },
1368c2ecf20Sopenharmony_ci	{ 9, 6, 4, 2, 2, 2, 2 },
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci/* Initialize time, Active time, Recovery time vary across
1398c2ecf20Sopenharmony_ci   IDE clock settings. These 3 arrays hold the register value
1408c2ecf20Sopenharmony_ci   for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
1418c2ecf20Sopenharmony_cistatic u8 ini_time_value[][8] = {
1428c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
1438c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
1448c2ecf20Sopenharmony_ci	{ 2, 1, 0, 0, 0, 1, 0, 0 },
1458c2ecf20Sopenharmony_ci	{ 4, 3, 1, 1, 1, 3, 1, 1 },
1468c2ecf20Sopenharmony_ci	{ 4, 3, 1, 1, 1, 3, 1, 1 },
1478c2ecf20Sopenharmony_ci	{ 6, 4, 2, 2, 2, 4, 2, 2 },
1488c2ecf20Sopenharmony_ci	{ 9, 6, 3, 3, 3, 6, 3, 3 },
1498c2ecf20Sopenharmony_ci	{ 9, 6, 3, 3, 3, 6, 3, 3 },
1508c2ecf20Sopenharmony_ci};
1518c2ecf20Sopenharmony_cistatic u8 act_time_value[][8] = {
1528c2ecf20Sopenharmony_ci	{  0,  0,  0,  0, 0,  0,  0, 0 },
1538c2ecf20Sopenharmony_ci	{  0,  0,  0,  0, 0,  0,  0, 0 },
1548c2ecf20Sopenharmony_ci	{  9,  9,  9,  2, 2,  7,  2, 2 },
1558c2ecf20Sopenharmony_ci	{ 19, 19, 19,  5, 4, 14,  5, 4 },
1568c2ecf20Sopenharmony_ci	{ 19, 19, 19,  5, 4, 14,  5, 4 },
1578c2ecf20Sopenharmony_ci	{ 28, 28, 28,  7, 6, 21,  7, 6 },
1588c2ecf20Sopenharmony_ci	{ 38, 38, 38, 10, 9, 28, 10, 9 },
1598c2ecf20Sopenharmony_ci	{ 38, 38, 38, 10, 9, 28, 10, 9 },
1608c2ecf20Sopenharmony_ci};
1618c2ecf20Sopenharmony_cistatic u8 rco_time_value[][8] = {
1628c2ecf20Sopenharmony_ci	{  0,  0, 0,  0, 0,  0,  0, 0 },
1638c2ecf20Sopenharmony_ci	{  0,  0, 0,  0, 0,  0,  0, 0 },
1648c2ecf20Sopenharmony_ci	{  9,  2, 0,  2, 0,  7,  1, 1 },
1658c2ecf20Sopenharmony_ci	{ 19,  5, 1,  5, 2, 16,  3, 2 },
1668c2ecf20Sopenharmony_ci	{ 19,  5, 1,  5, 2, 16,  3, 2 },
1678c2ecf20Sopenharmony_ci	{ 30,  9, 3,  9, 4, 25,  6, 4 },
1688c2ecf20Sopenharmony_ci	{ 40, 12, 4, 12, 5, 34, 12, 5 },
1698c2ecf20Sopenharmony_ci	{ 40, 12, 4, 12, 5, 34, 12, 5 },
1708c2ecf20Sopenharmony_ci};
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci/*
1738c2ecf20Sopenharmony_ci * Printing configuration
1748c2ecf20Sopenharmony_ci */
1758c2ecf20Sopenharmony_ci/* Used for chipset type printing at boot time */
1768c2ecf20Sopenharmony_cistatic char *chipset_capability[] = {
1778c2ecf20Sopenharmony_ci	"ATA", "ATA 16",
1788c2ecf20Sopenharmony_ci	"ATA 33", "ATA 66",
1798c2ecf20Sopenharmony_ci	"ATA 100 (1st gen)", "ATA 100 (2nd gen)",
1808c2ecf20Sopenharmony_ci	"ATA 133 (1st gen)", "ATA 133 (2nd gen)"
1818c2ecf20Sopenharmony_ci};
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci/*
1848c2ecf20Sopenharmony_ci * Configuration functions
1858c2ecf20Sopenharmony_ci */
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic u8 sis_ata133_get_base(ide_drive_t *drive)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
1908c2ecf20Sopenharmony_ci	u32 reg54 = 0;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	pci_read_config_dword(dev, 0x54, &reg54);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
2008c2ecf20Sopenharmony_ci	u16 t1 = 0;
2018c2ecf20Sopenharmony_ci	u8 drive_pci = 0x40 + drive->dn * 2;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	const u16 pio_timings[]   = { 0x000, 0x607, 0x404, 0x303, 0x301 };
2048c2ecf20Sopenharmony_ci	const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 };
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	pci_read_config_word(dev, drive_pci, &t1);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* clear active/recovery timings */
2098c2ecf20Sopenharmony_ci	t1 &= ~0x070f;
2108c2ecf20Sopenharmony_ci	if (mode >= XFER_MW_DMA_0) {
2118c2ecf20Sopenharmony_ci		if (chipset_family > ATA_16)
2128c2ecf20Sopenharmony_ci			t1 &= ~0x8000;	/* disable UDMA */
2138c2ecf20Sopenharmony_ci		t1 |= mwdma_timings[mode - XFER_MW_DMA_0];
2148c2ecf20Sopenharmony_ci	} else
2158c2ecf20Sopenharmony_ci		t1 |= pio_timings[mode - XFER_PIO_0];
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	pci_write_config_word(dev, drive_pci, t1);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
2238c2ecf20Sopenharmony_ci	u8 t1, drive_pci = 0x40 + drive->dn * 2;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	/* timing bits: 7:4 active 3:0 recovery */
2268c2ecf20Sopenharmony_ci	const u8 pio_timings[]   = { 0x00, 0x67, 0x44, 0x33, 0x31 };
2278c2ecf20Sopenharmony_ci	const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 };
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	if (mode >= XFER_MW_DMA_0) {
2308c2ecf20Sopenharmony_ci		u8 t2 = 0;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci		pci_read_config_byte(dev, drive_pci, &t2);
2338c2ecf20Sopenharmony_ci		t2 &= ~0x80;	/* disable UDMA */
2348c2ecf20Sopenharmony_ci		pci_write_config_byte(dev, drive_pci, t2);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci		t1 = mwdma_timings[mode - XFER_MW_DMA_0];
2378c2ecf20Sopenharmony_ci	} else
2388c2ecf20Sopenharmony_ci		t1 = pio_timings[mode - XFER_PIO_0];
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	pci_write_config_byte(dev, drive_pci + 1, t1);
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
2468c2ecf20Sopenharmony_ci	u32 t1 = 0;
2478c2ecf20Sopenharmony_ci	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	pci_read_config_dword(dev, drive_pci, &t1);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	t1 &= 0xc0c00fff;
2528c2ecf20Sopenharmony_ci	clk = (t1 & 0x08) ? ATA_133 : ATA_100;
2538c2ecf20Sopenharmony_ci	if (mode >= XFER_MW_DMA_0) {
2548c2ecf20Sopenharmony_ci		t1 &= ~0x04;	/* disable UDMA */
2558c2ecf20Sopenharmony_ci		idx = mode - XFER_MW_DMA_0 + 5;
2568c2ecf20Sopenharmony_ci	} else
2578c2ecf20Sopenharmony_ci		idx = mode - XFER_PIO_0;
2588c2ecf20Sopenharmony_ci	t1 |= ini_time_value[clk][idx] << 12;
2598c2ecf20Sopenharmony_ci	t1 |= act_time_value[clk][idx] << 16;
2608c2ecf20Sopenharmony_ci	t1 |= rco_time_value[clk][idx] << 24;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	pci_write_config_dword(dev, drive_pci, t1);
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic void sis_program_timings(ide_drive_t *drive, const u8 mode)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	if (chipset_family < ATA_100)		/* ATA_16/33/66/100a */
2688c2ecf20Sopenharmony_ci		sis_ata16_program_timings(drive, mode);
2698c2ecf20Sopenharmony_ci	else if (chipset_family < ATA_133)	/* ATA_100/133a */
2708c2ecf20Sopenharmony_ci		sis_ata100_program_timings(drive, mode);
2718c2ecf20Sopenharmony_ci	else					/* ATA_133 */
2728c2ecf20Sopenharmony_ci		sis_ata133_program_timings(drive, mode);
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic void config_drive_art_rwp(ide_drive_t *drive)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	ide_hwif_t *hwif	= drive->hwif;
2788c2ecf20Sopenharmony_ci	struct pci_dev *dev	= to_pci_dev(hwif->dev);
2798c2ecf20Sopenharmony_ci	u8 reg4bh		= 0;
2808c2ecf20Sopenharmony_ci	u8 rw_prefetch		= 0;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	pci_read_config_byte(dev, 0x4b, &reg4bh);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	rw_prefetch = reg4bh & ~(0x11 << drive->dn);
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	if (drive->media == ide_disk)
2878c2ecf20Sopenharmony_ci		rw_prefetch |= 0x11 << drive->dn;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	if (reg4bh != rw_prefetch)
2908c2ecf20Sopenharmony_ci		pci_write_config_byte(dev, 0x4b, rw_prefetch);
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_cistatic void sis_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	config_drive_art_rwp(drive);
2968c2ecf20Sopenharmony_ci	sis_program_timings(drive, drive->pio_mode);
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
3028c2ecf20Sopenharmony_ci	u32 regdw = 0;
3038c2ecf20Sopenharmony_ci	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	pci_read_config_dword(dev, drive_pci, &regdw);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	regdw |= 0x04;
3088c2ecf20Sopenharmony_ci	regdw &= 0xfffff00f;
3098c2ecf20Sopenharmony_ci	/* check if ATA133 enable */
3108c2ecf20Sopenharmony_ci	clk = (regdw & 0x08) ? ATA_133 : ATA_100;
3118c2ecf20Sopenharmony_ci	idx = mode - XFER_UDMA_0;
3128c2ecf20Sopenharmony_ci	regdw |= cycle_time_value[clk][idx] << 4;
3138c2ecf20Sopenharmony_ci	regdw |= cvs_time_value[clk][idx] << 8;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	pci_write_config_dword(dev, drive_pci, regdw);
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_cistatic void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
3218c2ecf20Sopenharmony_ci	u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	pci_read_config_byte(dev, drive_pci + 1, &reg);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/* force the UDMA bit on if we want to use UDMA */
3268c2ecf20Sopenharmony_ci	reg |= 0x80;
3278c2ecf20Sopenharmony_ci	/* clean reg cycle time bits */
3288c2ecf20Sopenharmony_ci	reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
3298c2ecf20Sopenharmony_ci	/* set reg cycle time bits */
3308c2ecf20Sopenharmony_ci	reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	pci_write_config_byte(dev, drive_pci + 1, reg);
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cistatic void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	if (chipset_family >= ATA_133)	/* ATA_133 */
3388c2ecf20Sopenharmony_ci		sis_ata133_program_udma_timings(drive, mode);
3398c2ecf20Sopenharmony_ci	else				/* ATA_33/66/100a/100/133a */
3408c2ecf20Sopenharmony_ci		sis_ata33_program_udma_timings(drive, mode);
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic void sis_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	const u8 speed = drive->dma_mode;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	if (speed >= XFER_UDMA_0)
3488c2ecf20Sopenharmony_ci		sis_program_udma_timings(drive, speed);
3498c2ecf20Sopenharmony_ci	else
3508c2ecf20Sopenharmony_ci		sis_program_timings(drive, speed);
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic u8 sis_ata133_udma_filter(ide_drive_t *drive)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
3568c2ecf20Sopenharmony_ci	u32 regdw = 0;
3578c2ecf20Sopenharmony_ci	u8 drive_pci = sis_ata133_get_base(drive);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	pci_read_config_dword(dev, drive_pci, &regdw);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/* if ATA133 disable, we should not set speed above UDMA5 */
3628c2ecf20Sopenharmony_ci	return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cistatic int sis_find_family(struct pci_dev *dev)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	struct pci_dev *host;
3688c2ecf20Sopenharmony_ci	int i = 0;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	chipset_family = 0;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci		host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci		if (!host)
3778c2ecf20Sopenharmony_ci			continue;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci		chipset_family = SiSHostChipInfo[i].chipset_family;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		/* Special case for SiS630 : 630S/ET is ATA_100a */
3828c2ecf20Sopenharmony_ci		if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
3838c2ecf20Sopenharmony_ci			if (host->revision >= 0x30)
3848c2ecf20Sopenharmony_ci				chipset_family = ATA_100a;
3858c2ecf20Sopenharmony_ci		}
3868c2ecf20Sopenharmony_ci		pci_dev_put(host);
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci		printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
3898c2ecf20Sopenharmony_ci			pci_name(dev), SiSHostChipInfo[i].name,
3908c2ecf20Sopenharmony_ci			chipset_capability[chipset_family]);
3918c2ecf20Sopenharmony_ci	}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	if (!chipset_family) { /* Belongs to pci-quirks */
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci			u32 idemisc;
3968c2ecf20Sopenharmony_ci			u16 trueid;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci			/* Disable ID masking and register remapping */
3998c2ecf20Sopenharmony_ci			pci_read_config_dword(dev, 0x54, &idemisc);
4008c2ecf20Sopenharmony_ci			pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));
4018c2ecf20Sopenharmony_ci			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
4028c2ecf20Sopenharmony_ci			pci_write_config_dword(dev, 0x54, idemisc);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci			if (trueid == 0x5518) {
4058c2ecf20Sopenharmony_ci				printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
4068c2ecf20Sopenharmony_ci					pci_name(dev));
4078c2ecf20Sopenharmony_ci				chipset_family = ATA_133;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci				/* Check for 5513 compatibility mapping
4108c2ecf20Sopenharmony_ci				 * We must use this, else the port enabled code will fail,
4118c2ecf20Sopenharmony_ci				 * as it expects the enablebits at 0x4a.
4128c2ecf20Sopenharmony_ci				 */
4138c2ecf20Sopenharmony_ci				if ((idemisc & 0x40000000) == 0) {
4148c2ecf20Sopenharmony_ci					pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
4158c2ecf20Sopenharmony_ci					printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
4168c2ecf20Sopenharmony_ci						pci_name(dev));
4178c2ecf20Sopenharmony_ci				}
4188c2ecf20Sopenharmony_ci			}
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (!chipset_family) { /* Belongs to pci-quirks */
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci			struct pci_dev *lpc_bridge;
4248c2ecf20Sopenharmony_ci			u16 trueid;
4258c2ecf20Sopenharmony_ci			u8 prefctl;
4268c2ecf20Sopenharmony_ci			u8 idecfg;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci			pci_read_config_byte(dev, 0x4a, &idecfg);
4298c2ecf20Sopenharmony_ci			pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
4308c2ecf20Sopenharmony_ci			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
4318c2ecf20Sopenharmony_ci			pci_write_config_byte(dev, 0x4a, idecfg);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci			if (trueid == 0x5517) { /* SiS 961/961B */
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci				lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
4368c2ecf20Sopenharmony_ci				pci_read_config_byte(dev, 0x49, &prefctl);
4378c2ecf20Sopenharmony_ci				pci_dev_put(lpc_bridge);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci				if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
4408c2ecf20Sopenharmony_ci					printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
4418c2ecf20Sopenharmony_ci						pci_name(dev));
4428c2ecf20Sopenharmony_ci					chipset_family = ATA_133a;
4438c2ecf20Sopenharmony_ci				} else {
4448c2ecf20Sopenharmony_ci					printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
4458c2ecf20Sopenharmony_ci						pci_name(dev));
4468c2ecf20Sopenharmony_ci					chipset_family = ATA_100;
4478c2ecf20Sopenharmony_ci				}
4488c2ecf20Sopenharmony_ci			}
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	return chipset_family;
4528c2ecf20Sopenharmony_ci}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_cistatic int init_chipset_sis5513(struct pci_dev *dev)
4558c2ecf20Sopenharmony_ci{
4568c2ecf20Sopenharmony_ci	/* Make general config ops here
4578c2ecf20Sopenharmony_ci	   1/ tell IDE channels to operate in Compatibility mode only
4588c2ecf20Sopenharmony_ci	   2/ tell old chips to allow per drive IDE timings */
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	u8 reg;
4618c2ecf20Sopenharmony_ci	u16 regw;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	switch (chipset_family) {
4648c2ecf20Sopenharmony_ci	case ATA_133:
4658c2ecf20Sopenharmony_ci		/* SiS962 operation mode */
4668c2ecf20Sopenharmony_ci		pci_read_config_word(dev, 0x50, &regw);
4678c2ecf20Sopenharmony_ci		if (regw & 0x08)
4688c2ecf20Sopenharmony_ci			pci_write_config_word(dev, 0x50, regw&0xfff7);
4698c2ecf20Sopenharmony_ci		pci_read_config_word(dev, 0x52, &regw);
4708c2ecf20Sopenharmony_ci		if (regw & 0x08)
4718c2ecf20Sopenharmony_ci			pci_write_config_word(dev, 0x52, regw&0xfff7);
4728c2ecf20Sopenharmony_ci		break;
4738c2ecf20Sopenharmony_ci	case ATA_133a:
4748c2ecf20Sopenharmony_ci	case ATA_100:
4758c2ecf20Sopenharmony_ci		/* Fixup latency */
4768c2ecf20Sopenharmony_ci		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
4778c2ecf20Sopenharmony_ci		/* Set compatibility bit */
4788c2ecf20Sopenharmony_ci		pci_read_config_byte(dev, 0x49, &reg);
4798c2ecf20Sopenharmony_ci		if (!(reg & 0x01))
4808c2ecf20Sopenharmony_ci			pci_write_config_byte(dev, 0x49, reg|0x01);
4818c2ecf20Sopenharmony_ci		break;
4828c2ecf20Sopenharmony_ci	case ATA_100a:
4838c2ecf20Sopenharmony_ci	case ATA_66:
4848c2ecf20Sopenharmony_ci		/* Fixup latency */
4858c2ecf20Sopenharmony_ci		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		/* On ATA_66 chips the bit was elsewhere */
4888c2ecf20Sopenharmony_ci		pci_read_config_byte(dev, 0x52, &reg);
4898c2ecf20Sopenharmony_ci		if (!(reg & 0x04))
4908c2ecf20Sopenharmony_ci			pci_write_config_byte(dev, 0x52, reg|0x04);
4918c2ecf20Sopenharmony_ci		break;
4928c2ecf20Sopenharmony_ci	case ATA_33:
4938c2ecf20Sopenharmony_ci		/* On ATA_33 we didn't have a single bit to set */
4948c2ecf20Sopenharmony_ci		pci_read_config_byte(dev, 0x09, &reg);
4958c2ecf20Sopenharmony_ci		if ((reg & 0x0f) != 0x00)
4968c2ecf20Sopenharmony_ci			pci_write_config_byte(dev, 0x09, reg&0xf0);
4978c2ecf20Sopenharmony_ci		fallthrough;
4988c2ecf20Sopenharmony_ci	case ATA_16:
4998c2ecf20Sopenharmony_ci		/* force per drive recovery and active timings
5008c2ecf20Sopenharmony_ci		   needed on ATA_33 and below chips */
5018c2ecf20Sopenharmony_ci		pci_read_config_byte(dev, 0x52, &reg);
5028c2ecf20Sopenharmony_ci		if (!(reg & 0x08))
5038c2ecf20Sopenharmony_ci			pci_write_config_byte(dev, 0x52, reg|0x08);
5048c2ecf20Sopenharmony_ci		break;
5058c2ecf20Sopenharmony_ci	}
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	return 0;
5088c2ecf20Sopenharmony_ci}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_cistruct sis_laptop {
5118c2ecf20Sopenharmony_ci	u16 device;
5128c2ecf20Sopenharmony_ci	u16 subvendor;
5138c2ecf20Sopenharmony_ci	u16 subdevice;
5148c2ecf20Sopenharmony_ci};
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic const struct sis_laptop sis_laptop[] = {
5178c2ecf20Sopenharmony_ci	/* devid, subvendor, subdev */
5188c2ecf20Sopenharmony_ci	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
5198c2ecf20Sopenharmony_ci	{ 0x5513, 0x1734, 0x105f },	/* FSC Amilo A1630 */
5208c2ecf20Sopenharmony_ci	{ 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
5218c2ecf20Sopenharmony_ci	/* end marker */
5228c2ecf20Sopenharmony_ci	{ 0, }
5238c2ecf20Sopenharmony_ci};
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_cistatic u8 sis_cable_detect(ide_hwif_t *hwif)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(hwif->dev);
5288c2ecf20Sopenharmony_ci	const struct sis_laptop *lap = &sis_laptop[0];
5298c2ecf20Sopenharmony_ci	u8 ata66 = 0;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	while (lap->device) {
5328c2ecf20Sopenharmony_ci		if (lap->device == pdev->device &&
5338c2ecf20Sopenharmony_ci		    lap->subvendor == pdev->subsystem_vendor &&
5348c2ecf20Sopenharmony_ci		    lap->subdevice == pdev->subsystem_device)
5358c2ecf20Sopenharmony_ci			return ATA_CBL_PATA40_SHORT;
5368c2ecf20Sopenharmony_ci		lap++;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	if (chipset_family >= ATA_133) {
5408c2ecf20Sopenharmony_ci		u16 regw = 0;
5418c2ecf20Sopenharmony_ci		u16 reg_addr = hwif->channel ? 0x52: 0x50;
5428c2ecf20Sopenharmony_ci		pci_read_config_word(pdev, reg_addr, &regw);
5438c2ecf20Sopenharmony_ci		ata66 = (regw & 0x8000) ? 0 : 1;
5448c2ecf20Sopenharmony_ci	} else if (chipset_family >= ATA_66) {
5458c2ecf20Sopenharmony_ci		u8 reg48h = 0;
5468c2ecf20Sopenharmony_ci		u8 mask = hwif->channel ? 0x20 : 0x10;
5478c2ecf20Sopenharmony_ci		pci_read_config_byte(pdev, 0x48, &reg48h);
5488c2ecf20Sopenharmony_ci		ata66 = (reg48h & mask) ? 0 : 1;
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistatic const struct ide_port_ops sis_port_ops = {
5558c2ecf20Sopenharmony_ci	.set_pio_mode		= sis_set_pio_mode,
5568c2ecf20Sopenharmony_ci	.set_dma_mode		= sis_set_dma_mode,
5578c2ecf20Sopenharmony_ci	.cable_detect		= sis_cable_detect,
5588c2ecf20Sopenharmony_ci};
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic const struct ide_port_ops sis_ata133_port_ops = {
5618c2ecf20Sopenharmony_ci	.set_pio_mode		= sis_set_pio_mode,
5628c2ecf20Sopenharmony_ci	.set_dma_mode		= sis_set_dma_mode,
5638c2ecf20Sopenharmony_ci	.udma_filter		= sis_ata133_udma_filter,
5648c2ecf20Sopenharmony_ci	.cable_detect		= sis_cable_detect,
5658c2ecf20Sopenharmony_ci};
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic const struct ide_port_info sis5513_chipset = {
5688c2ecf20Sopenharmony_ci	.name		= DRV_NAME,
5698c2ecf20Sopenharmony_ci	.init_chipset	= init_chipset_sis5513,
5708c2ecf20Sopenharmony_ci	.enablebits	= { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
5718c2ecf20Sopenharmony_ci	.host_flags	= IDE_HFLAG_NO_AUTODMA,
5728c2ecf20Sopenharmony_ci	.pio_mask	= ATA_PIO4,
5738c2ecf20Sopenharmony_ci	.mwdma_mask	= ATA_MWDMA2,
5748c2ecf20Sopenharmony_ci};
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_cistatic int sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	struct ide_port_info d = sis5513_chipset;
5798c2ecf20Sopenharmony_ci	u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
5808c2ecf20Sopenharmony_ci	int rc;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	rc = pci_enable_device(dev);
5838c2ecf20Sopenharmony_ci	if (rc)
5848c2ecf20Sopenharmony_ci		return rc;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	if (sis_find_family(dev) == 0)
5878c2ecf20Sopenharmony_ci		return -ENOTSUPP;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (chipset_family >= ATA_133)
5908c2ecf20Sopenharmony_ci		d.port_ops = &sis_ata133_port_ops;
5918c2ecf20Sopenharmony_ci	else
5928c2ecf20Sopenharmony_ci		d.port_ops = &sis_port_ops;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	d.udma_mask = udma_rates[chipset_family];
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	return ide_pci_init_one(dev, &d, NULL);
5978c2ecf20Sopenharmony_ci}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cistatic void sis5513_remove(struct pci_dev *dev)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	ide_pci_remove(dev);
6028c2ecf20Sopenharmony_ci	pci_disable_device(dev);
6038c2ecf20Sopenharmony_ci}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic const struct pci_device_id sis5513_pci_tbl[] = {
6068c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 },
6078c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 },
6088c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 },
6098c2ecf20Sopenharmony_ci	{ 0, },
6108c2ecf20Sopenharmony_ci};
6118c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cistatic struct pci_driver sis5513_pci_driver = {
6148c2ecf20Sopenharmony_ci	.name		= "SIS_IDE",
6158c2ecf20Sopenharmony_ci	.id_table	= sis5513_pci_tbl,
6168c2ecf20Sopenharmony_ci	.probe		= sis5513_init_one,
6178c2ecf20Sopenharmony_ci	.remove		= sis5513_remove,
6188c2ecf20Sopenharmony_ci	.suspend	= ide_pci_suspend,
6198c2ecf20Sopenharmony_ci	.resume		= ide_pci_resume,
6208c2ecf20Sopenharmony_ci};
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic int __init sis5513_ide_init(void)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	return ide_pci_register_driver(&sis5513_pci_driver);
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_cistatic void __exit sis5513_ide_exit(void)
6288c2ecf20Sopenharmony_ci{
6298c2ecf20Sopenharmony_ci	pci_unregister_driver(&sis5513_pci_driver);
6308c2ecf20Sopenharmony_ci}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_cimodule_init(sis5513_ide_init);
6338c2ecf20Sopenharmony_cimodule_exit(sis5513_ide_exit);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ciMODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
6368c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI driver module for SIS IDE");
6378c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
638