11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003		Vojtech Pavlik <vojtech@suse.cz>
5e13ee546bb06453939014c7b854e77fb643fd6f1Bartlomiej Zolnierkiewicz * Copyright (C) 2007-2009	Bartlomiej Zolnierkiewicz
66b8cf7724bd0f8ae1f61937c5f40f4dbbda40960Bartlomiej Zolnierkiewicz *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * May be copied or modified under the terms of the GNU General Public License
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks :
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SiS Taiwan		: for direct support and hardware.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Daniela Engert	: for initial ATA100 advices and numerous others.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt	:
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			  for checking code correctness, providing patches.
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Original tests and design on the SiS620 chipset.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ATA100 tests and design on the SiS735 chipset.
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ATA16/33 support from specs
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ATA133 961/962/963 fixes by Vojtech Pavlik <vojtech@suse.cz>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation:
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	SiS chipset documentation available under NDA to companies only
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      (not to individuals).
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip.
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Later SiS chipsets integrated the 5513 functionality into the NorthBridge,
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can figure out that we have a more modern and more capable 5513 by looking
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the respective NorthBridge IDs.
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ID, while the now ATA-133 capable 5513 still has the same PCI ID.
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fortunately the 5513 can be 'unmasked' by fiddling with some config space
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bits, changing its device id to the true one - 5517 for 961 and 5518 for
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 962/963.
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz#define DRV_NAME "sis5513"
55ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz
5625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* registers layout and init values are chipset family dependent */
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_16		0x01
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_33		0x02
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_66		0x03
611eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi#define ATA_100a	0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_100		0x05
631eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi#define ATA_133a	0x06 /* SiS961b with 133 support */
641eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi#define ATA_133		0x07 /* SiS962/963 */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 chipset_family;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Devices supported
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct {
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *name;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 host_id;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 chipset_family;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 flags;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} SiSHostChipInfo[] = {
7747d4b9066df023670a61e74565a75293cf15a441David Wang	{ "SiS968",	PCI_DEVICE_ID_SI_968,	ATA_133  },
7847d4b9066df023670a61e74565a75293cf15a441David Wang	{ "SiS966",	PCI_DEVICE_ID_SI_966,	ATA_133  },
7914351f8e573442e2437d4b177fa10075aaefd5c9Aurelien Jarno	{ "SiS965",	PCI_DEVICE_ID_SI_965,	ATA_133  },
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS745",	PCI_DEVICE_ID_SI_745,	ATA_100  },
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS735",	PCI_DEVICE_ID_SI_735,	ATA_100  },
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS733",	PCI_DEVICE_ID_SI_733,	ATA_100  },
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS635",	PCI_DEVICE_ID_SI_635,	ATA_100  },
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS633",	PCI_DEVICE_ID_SI_633,	ATA_100  },
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS730",	PCI_DEVICE_ID_SI_730,	ATA_100a },
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS550",	PCI_DEVICE_ID_SI_550,	ATA_100a },
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS640",	PCI_DEVICE_ID_SI_640,	ATA_66   },
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS630",	PCI_DEVICE_ID_SI_630,	ATA_66   },
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS620",	PCI_DEVICE_ID_SI_620,	ATA_66   },
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS540",	PCI_DEVICE_ID_SI_540,	ATA_66   },
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS530",	PCI_DEVICE_ID_SI_530,	ATA_66   },
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5600",	PCI_DEVICE_ID_SI_5600,	ATA_33   },
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5598",	PCI_DEVICE_ID_SI_5598,	ATA_33   },
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5597",	PCI_DEVICE_ID_SI_5597,	ATA_33   },
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5591/2",	PCI_DEVICE_ID_SI_5591,	ATA_33   },
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5582",	PCI_DEVICE_ID_SI_5582,	ATA_33   },
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5581",	PCI_DEVICE_ID_SI_5581,	ATA_33   },
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5596",	PCI_DEVICE_ID_SI_5596,	ATA_16   },
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5571",	PCI_DEVICE_ID_SI_5571,	ATA_16   },
104d266ab88938e49aa95f1965ee020df1b1d4c5761Alan Cox	{ "SiS5517",	PCI_DEVICE_ID_SI_5517,	ATA_16   },
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS551x",	PCI_DEVICE_ID_SI_5511,	ATA_16   },
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Cycle time bits and values vary across chip dma capabilities
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   These three arrays hold the register layout and the values to set.
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
1131eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchistatic u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
1141eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchistatic u8 cycle_time_range[]  = { 0, 0, 2, 3, 3, 4, 4 };
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
1161eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
1171eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  0,  0, 0, 0, 0, 0, 0 }, /* no UDMA */
1181eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  3,  2, 1, 0, 0, 0, 0 }, /* ATA_33 */
1191eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  7,  5, 3, 2, 1, 0, 0 }, /* ATA_66 */
1201eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  7,  5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
1211eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi				      different cycle_time range and offset */
1221eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 11,  7, 5, 4, 2, 1, 0 }, /* ATA_100 */
1231eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
1241eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   See SiS962 data sheet for more detail */
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
1291eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
1301eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
1311eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 2, 1, 1, 0, 0, 0, 0 },
1321eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 4, 3, 2, 1, 0, 0, 0 },
1331eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 4, 3, 2, 1, 0, 0, 0 },
1341eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 6, 4, 3, 1, 1, 1, 0 },
1351eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 9, 6, 4, 2, 2, 2, 2 },
1361eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 9, 6, 4, 2, 2, 2, 2 },
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize time, Active time, Recovery time vary across
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   IDE clock settings. These 3 arrays hold the register value
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 ini_time_value[][8] = {
1421eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 0, 0, 0, 0, 0, 0, 0, 0 },
1431eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 0, 0, 0, 0, 0, 0, 0, 0 },
1441eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 2, 1, 0, 0, 0, 1, 0, 0 },
1451eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 4, 3, 1, 1, 1, 3, 1, 1 },
1461eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 4, 3, 1, 1, 1, 3, 1, 1 },
1471eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 6, 4, 2, 2, 2, 4, 2, 2 },
1481eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 9, 6, 3, 3, 3, 6, 3, 3 },
1491eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 9, 6, 3, 3, 3, 6, 3, 3 },
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 act_time_value[][8] = {
1521eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  0,  0,  0,  0, 0,  0,  0, 0 },
1531eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  0,  0,  0,  0, 0,  0,  0, 0 },
1541eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  9,  9,  9,  2, 2,  7,  2, 2 },
1551eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 19, 19, 19,  5, 4, 14,  5, 4 },
1561eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 19, 19, 19,  5, 4, 14,  5, 4 },
1571eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 28, 28, 28,  7, 6, 21,  7, 6 },
1581eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 38, 38, 38, 10, 9, 28, 10, 9 },
1591eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 38, 38, 38, 10, 9, 28, 10, 9 },
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 rco_time_value[][8] = {
1621eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  0,  0, 0,  0, 0,  0,  0, 0 },
1631eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  0,  0, 0,  0, 0,  0,  0, 0 },
1641eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{  9,  2, 0,  2, 0,  7,  1, 1 },
1651eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 19,  5, 1,  5, 2, 16,  3, 2 },
1661eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 19,  5, 1,  5, 2, 16,  3, 2 },
1671eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 30,  9, 3,  9, 4, 25,  6, 4 },
1681eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 40, 12, 4, 12, 5, 34, 12, 5 },
1691eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	{ 40, 12, 4, 12, 5, 34, 12, 5 },
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Printing configuration
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Used for chipset type printing at boot time */
1761eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchistatic char *chipset_capability[] = {
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA", "ATA 16",
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA 33", "ATA 66",
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA 100 (1st gen)", "ATA 100 (2nd gen)",
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA 133 (1st gen)", "ATA 133 (2nd gen)"
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configuration functions
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
186c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
187c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewiczstatic u8 sis_ata133_get_base(ide_drive_t *drive)
188c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz{
18936501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
190c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u32 reg54 = 0;
191c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
192c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	pci_read_config_dword(dev, 0x54, &reg54);
193c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
194c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4;
195c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz}
196c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
197c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewiczstatic void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
198c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz{
19936501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
200c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u16 t1 = 0;
201c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u8 drive_pci = 0x40 + drive->dn * 2;
202c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
203c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	const u16 pio_timings[]   = { 0x000, 0x607, 0x404, 0x303, 0x301 };
204c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 };
205c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
206c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	pci_read_config_word(dev, drive_pci, &t1);
207c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
208c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	/* clear active/recovery timings */
209c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	t1 &= ~0x070f;
210c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	if (mode >= XFER_MW_DMA_0) {
211c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		if (chipset_family > ATA_16)
212c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz			t1 &= ~0x8000;	/* disable UDMA */
213c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		t1 |= mwdma_timings[mode - XFER_MW_DMA_0];
214c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	} else
215c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		t1 |= pio_timings[mode - XFER_PIO_0];
216c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
217c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	pci_write_config_word(dev, drive_pci, t1);
218c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz}
219c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
220c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewiczstatic void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
221c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz{
22236501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
223c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u8 t1, drive_pci = 0x40 + drive->dn * 2;
224c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
225c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	/* timing bits: 7:4 active 3:0 recovery */
226c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	const u8 pio_timings[]   = { 0x00, 0x67, 0x44, 0x33, 0x31 };
227c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 };
228c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
229c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	if (mode >= XFER_MW_DMA_0) {
230c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		u8 t2 = 0;
231c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
232c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		pci_read_config_byte(dev, drive_pci, &t2);
233c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		t2 &= ~0x80;	/* disable UDMA */
234c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		pci_write_config_byte(dev, drive_pci, t2);
235c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
236c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		t1 = mwdma_timings[mode - XFER_MW_DMA_0];
237c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	} else
238c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		t1 = pio_timings[mode - XFER_PIO_0];
239c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
240c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	pci_write_config_byte(dev, drive_pci + 1, t1);
241c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz}
242c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
243c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewiczstatic void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
244c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz{
24536501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
246c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u32 t1 = 0;
247c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
248c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
249c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	pci_read_config_dword(dev, drive_pci, &t1);
250c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
251c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	t1 &= 0xc0c00fff;
252c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	clk = (t1 & 0x08) ? ATA_133 : ATA_100;
253c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	if (mode >= XFER_MW_DMA_0) {
254c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		t1 &= ~0x04;	/* disable UDMA */
255c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		idx = mode - XFER_MW_DMA_0 + 5;
2563dfd6433ff4d037262a4b8bede022e1d4bac06e3Adrian Bunk	} else
257c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		idx = mode - XFER_PIO_0;
258c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	t1 |= ini_time_value[clk][idx] << 12;
259c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	t1 |= act_time_value[clk][idx] << 16;
260c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	t1 |= rco_time_value[clk][idx] << 24;
261c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
262c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	pci_write_config_dword(dev, drive_pci, t1);
263c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz}
264c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
265c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewiczstatic void sis_program_timings(ide_drive_t *drive, const u8 mode)
266c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz{
267c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	if (chipset_family < ATA_100)		/* ATA_16/33/66/100a */
268c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		sis_ata16_program_timings(drive, mode);
269c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	else if (chipset_family < ATA_133)	/* ATA_100/133a */
270c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		sis_ata100_program_timings(drive, mode);
271c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	else					/* ATA_133 */
272c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz		sis_ata133_program_timings(drive, mode);
273c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz}
274c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz
2751eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchistatic void config_drive_art_rwp(ide_drive_t *drive)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
277898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
27836501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev	= to_pci_dev(hwif->dev);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg4bh		= 0;
280d83fca58d3229f3b23a92a72c3428da8faf09940Bartlomiej Zolnierkiewicz	u8 rw_prefetch		= 0;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(dev, 0x4b, &reg4bh);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
284e13ee546bb06453939014c7b854e77fb643fd6f1Bartlomiej Zolnierkiewicz	rw_prefetch = reg4bh & ~(0x11 << drive->dn);
285e13ee546bb06453939014c7b854e77fb643fd6f1Bartlomiej Zolnierkiewicz
286d83fca58d3229f3b23a92a72c3428da8faf09940Bartlomiej Zolnierkiewicz	if (drive->media == ide_disk)
287e13ee546bb06453939014c7b854e77fb643fd6f1Bartlomiej Zolnierkiewicz		rw_prefetch |= 0x11 << drive->dn;
288d83fca58d3229f3b23a92a72c3428da8faf09940Bartlomiej Zolnierkiewicz
289e13ee546bb06453939014c7b854e77fb643fd6f1Bartlomiej Zolnierkiewicz	if (reg4bh != rw_prefetch)
290e13ee546bb06453939014c7b854e77fb643fd6f1Bartlomiej Zolnierkiewicz		pci_write_config_byte(dev, 0x4b, rw_prefetch);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
293e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void sis_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_drive_art_rwp(drive);
296e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz	sis_program_timings(drive, drive->pio_mode);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
299428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewiczstatic void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30136501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
302428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	u32 regdw = 0;
303428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
304428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
305428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	pci_read_config_dword(dev, drive_pci, &regdw);
306428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
307428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	regdw |= 0x04;
308428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	regdw &= 0xfffff00f;
309428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	/* check if ATA133 enable */
310428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	clk = (regdw & 0x08) ? ATA_133 : ATA_100;
311428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	idx = mode - XFER_UDMA_0;
312428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	regdw |= cycle_time_value[clk][idx] << 4;
313428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	regdw |= cvs_time_value[clk][idx] << 8;
314428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
315428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	pci_write_config_dword(dev, drive_pci, regdw);
316428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz}
317428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
318428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewiczstatic void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
319428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz{
32036501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
321428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
322428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
323428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	pci_read_config_byte(dev, drive_pci + 1, &reg);
324428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
325428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	/* force the UDMA bit on if we want to use UDMA */
326428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	reg |= 0x80;
327428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	/* clean reg cycle time bits */
328428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
329428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	/* set reg cycle time bits */
330428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
331428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
332428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	pci_write_config_byte(dev, drive_pci + 1, reg);
333428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz}
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
335428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewiczstatic void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
336428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz{
337428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	if (chipset_family >= ATA_133)	/* ATA_133 */
338428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz		sis_ata133_program_udma_timings(drive, mode);
339428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz	else				/* ATA_33/66/100a/100/133a */
340428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz		sis_ata33_program_udma_timings(drive, mode);
341428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz}
342428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz
3438776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewiczstatic void sis_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
344428c6440ef933a3d9df5adfeb2cbb3ea7ebb6a68Bartlomiej Zolnierkiewicz{
3458776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz	const u8 speed = drive->dma_mode;
3468776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz
3474db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz	if (speed >= XFER_UDMA_0)
3484db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz		sis_program_udma_timings(drive, speed);
3494db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz	else
3504db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz		sis_program_timings(drive, speed);
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
353ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic u8 sis_ata133_udma_filter(ide_drive_t *drive)
3543160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz{
35536501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
356c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u32 regdw = 0;
357c77a89cd98d99819f23a4a08e5e17ee1f13f6e4dBartlomiej Zolnierkiewicz	u8 drive_pci = sis_ata133_get_base(drive);
3583160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz
3593160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz	pci_read_config_dword(dev, drive_pci, &regdw);
3603160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz
3613160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz	/* if ATA133 disable, we should not set speed above UDMA5 */
3623160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz	return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
3633160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz}
3643160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz
365fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic int sis_find_family(struct pci_dev *dev)
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *host;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chipset_family = 0;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37440cddf2cbd02aa830254afcd5a1a21b4e882a189Alan Cox		host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!host)
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		chipset_family = SiSHostChipInfo[i].chipset_family;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Special case for SiS630 : 630S/ET is ATA_100a */
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
38344c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok			if (host->revision >= 0x30)
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				chipset_family = ATA_100a;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
38640cddf2cbd02aa830254afcd5a1a21b4e882a189Alan Cox		pci_dev_put(host);
3871eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi
388ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz		printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
38928cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			pci_name(dev), SiSHostChipInfo[i].name,
39028cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			chipset_capability[chipset_family]);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chipset_family) { /* Belongs to pci-quirks */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u32 idemisc;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u16 trueid;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Disable ID masking and register remapping */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_dword(dev, 0x54, &idemisc);
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_dword(dev, 0x54, idemisc);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (trueid == 0x5518) {
405ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz				printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
40628cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz					pci_name(dev));
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				chipset_family = ATA_133;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi				/* Check for 5513 compatibility mapping
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * We must use this, else the port enabled code will fail,
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * as it expects the enablebits at 0x4a.
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((idemisc & 0x40000000) == 0) {
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
415ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz					printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
41628cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz						pci_name(dev));
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chipset_family) { /* Belongs to pci-quirks */
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pci_dev *lpc_bridge;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u16 trueid;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 prefctl;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 idecfg;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_byte(dev, 0x4a, &idecfg);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, 0x4a, idecfg);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (trueid == 0x5517) { /* SiS 961/961B */
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
435b1489009963b8c5132f2ffe23483e811d9ae5607Alan Cox				lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(dev, 0x49, &prefctl);
437b1489009963b8c5132f2ffe23483e811d9ae5607Alan Cox				pci_dev_put(lpc_bridge);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43944c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok				if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
440ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz					printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
44128cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz						pci_name(dev));
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					chipset_family = ATA_133a;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
444ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz					printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
44528cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz						pci_name(dev));
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					chipset_family = ATA_100;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4514764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz	return chipset_family;
4524764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz}
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4542ed0ef543ae3f3ea4f8bd0433fb1fed22625a309Bartlomiej Zolnierkiewiczstatic int init_chipset_sis5513(struct pci_dev *dev)
4554764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz{
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make general config ops here
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   1/ tell IDE channels to operate in Compatibility mode only
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   2/ tell old chips to allow per drive IDE timings */
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	u8 reg;
4611eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	u16 regw;
4621eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi
4631eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	switch (chipset_family) {
4641eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_133:
4651eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* SiS962 operation mode */
4661eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_read_config_word(dev, 0x50, &regw);
4671eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		if (regw & 0x08)
4681eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi			pci_write_config_word(dev, 0x50, regw&0xfff7);
4691eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_read_config_word(dev, 0x52, &regw);
4701eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		if (regw & 0x08)
4711eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi			pci_write_config_word(dev, 0x52, regw&0xfff7);
4721eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		break;
4731eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_133a:
4741eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_100:
4751eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* Fixup latency */
4761eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
4771eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* Set compatibility bit */
4781eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_read_config_byte(dev, 0x49, &reg);
4791eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		if (!(reg & 0x01))
4801eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi			pci_write_config_byte(dev, 0x49, reg|0x01);
4811eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		break;
4821eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_100a:
4831eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_66:
4841eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* Fixup latency */
4851eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
4861eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi
4871eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* On ATA_66 chips the bit was elsewhere */
4881eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_read_config_byte(dev, 0x52, &reg);
4891eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		if (!(reg & 0x04))
4901eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi			pci_write_config_byte(dev, 0x52, reg|0x04);
4911eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		break;
4921eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_33:
4931eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* On ATA_33 we didn't have a single bit to set */
4941eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_read_config_byte(dev, 0x09, &reg);
4951eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		if ((reg & 0x0f) != 0x00)
4961eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi			pci_write_config_byte(dev, 0x09, reg&0xf0);
4971eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	case ATA_16:
4981eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		/* force per drive recovery and active timings
4991eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		   needed on ATA_33 and below chips */
5001eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		pci_read_config_byte(dev, 0x52, &reg);
5011eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		if (!(reg & 0x08))
5021eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi			pci_write_config_byte(dev, 0x52, reg|0x08);
5031eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi		break;
5041eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	}
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
509f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewiczstruct sis_laptop {
510f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	u16 device;
511f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	u16 subvendor;
512f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	u16 subdevice;
513f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz};
514f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz
515f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewiczstatic const struct sis_laptop sis_laptop[] = {
516f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	/* devid, subvendor, subdev */
517f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
5181955f6814fb58ffa06af4873a445307d60b23fb1David Lamparter	{ 0x5513, 0x1734, 0x105f },	/* FSC Amilo A1630 */
519a1d85864d30181a71243193ed01d322dc0618dc6Gabriel Craciunescu	{ 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
520f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	/* end marker */
521f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	{ 0, }
522f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz};
523f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz
524f454cbe8cd38b6d447e74ddaf012017fea42717eBartlomiej Zolnierkiewiczstatic u8 sis_cable_detect(ide_hwif_t *hwif)
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
52636501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *pdev = to_pci_dev(hwif->dev);
527f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	const struct sis_laptop *lap = &sis_laptop[0];
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 ata66 = 0;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
530f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	while (lap->device) {
531f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz		if (lap->device == pdev->device &&
532f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz		    lap->subvendor == pdev->subsystem_vendor &&
533f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz		    lap->subdevice == pdev->subsystem_device)
534f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz			return ATA_CBL_PATA40_SHORT;
535f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz		lap++;
536f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz	}
537f2befd9e80b39a5aa54d65cf59b6a5feb9a8117eBartlomiej Zolnierkiewicz
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family >= ATA_133) {
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u16 regw = 0;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u16 reg_addr = hwif->channel ? 0x52: 0x50;
54136501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz		pci_read_config_word(pdev, reg_addr, &regw);
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ata66 = (regw & 0x8000) ? 0 : 1;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chipset_family >= ATA_66) {
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 reg48h = 0;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 mask = hwif->channel ? 0x20 : 0x10;
54636501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz		pci_read_config_byte(pdev, 0x48, &reg48h);
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ata66 = (reg48h & mask) ? 0 : 1;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
54949521f97ccd3c2bf6e71a91cea8fe65d170fa4fbBartlomiej Zolnierkiewicz
55049521f97ccd3c2bf6e71a91cea8fe65d170fa4fbBartlomiej Zolnierkiewicz	return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
553ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops sis_port_ops = {
554ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_pio_mode		= sis_set_pio_mode,
555ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_dma_mode		= sis_set_dma_mode,
556ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.cable_detect		= sis_cable_detect,
557ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz};
5583160d5416f39da9d9221fec7cb9d64399b706bbcBartlomiej Zolnierkiewicz
559ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops sis_ata133_port_ops = {
560ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_pio_mode		= sis_set_pio_mode,
561ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_dma_mode		= sis_set_dma_mode,
562ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.udma_filter		= sis_ata133_udma_filter,
563ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.cable_detect		= sis_cable_detect,
564ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz};
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
566fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic const struct ide_port_info sis5513_chipset = {
567ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz	.name		= DRV_NAME,
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init_chipset	= init_chipset_sis5513,
5691eb3c2ee1d20cc03d538232c05b8f320de6b1401Paolo Ciarrocchi	.enablebits	= { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
5702467922a560bb7e6eb4635435760ad0a2197ffccBartlomiej Zolnierkiewicz	.host_flags	= IDE_HFLAG_NO_AUTODMA,
5714099d14322149c7a467e4997b87be4ba8eb78697Bartlomiej Zolnierkiewicz	.pio_mask	= ATA_PIO4,
5725f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz	.mwdma_mask	= ATA_MWDMA2,
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
575fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic int sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5774764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz	struct ide_port_info d = sis5513_chipset;
5784764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz	u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
579cd18f69f845dc8c769f0ef65046b7a113b8aba87Bartlomiej Zolnierkiewicz	int rc;
580cd18f69f845dc8c769f0ef65046b7a113b8aba87Bartlomiej Zolnierkiewicz
581cd18f69f845dc8c769f0ef65046b7a113b8aba87Bartlomiej Zolnierkiewicz	rc = pci_enable_device(dev);
582cd18f69f845dc8c769f0ef65046b7a113b8aba87Bartlomiej Zolnierkiewicz	if (rc)
583cd18f69f845dc8c769f0ef65046b7a113b8aba87Bartlomiej Zolnierkiewicz		return rc;
5844764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz
5854764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz	if (sis_find_family(dev) == 0)
5864764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz		return -ENOTSUPP;
5874764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz
588ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	if (chipset_family >= ATA_133)
589ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz		d.port_ops = &sis_ata133_port_ops;
590ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	else
591ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz		d.port_ops = &sis_port_ops;
592ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz
5934764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz	d.udma_mask = udma_rates[chipset_family];
5944764b68405ac918e9ac9939b1a2d1469102e5af7Bartlomiej Zolnierkiewicz
5956cdf6eb357c2681596b7b1672b92396ba82333d4Bartlomiej Zolnierkiewicz	return ide_pci_init_one(dev, &d, NULL);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
598fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic void sis5513_remove(struct pci_dev *dev)
5991ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz{
6001ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz	ide_pci_remove(dev);
6011ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz	pci_disable_device(dev);
6021ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz}
6031ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz
6049cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewiczstatic const struct pci_device_id sis5513_pci_tbl[] = {
6059cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 },
6069cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 },
6079cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 },
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, },
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
612a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewiczstatic struct pci_driver sis5513_pci_driver = {
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "SIS_IDE",
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= sis5513_pci_tbl,
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= sis5513_init_one,
616fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartman	.remove		= sis5513_remove,
617feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz	.suspend	= ide_pci_suspend,
618feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz	.resume		= ide_pci_resume,
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62182ab1eeceba6705cd5a8815c48eb03af1dada744Bartlomiej Zolnierkiewiczstatic int __init sis5513_ide_init(void)
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
623a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz	return ide_pci_register_driver(&sis5513_pci_driver);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewiczstatic void __exit sis5513_ide_exit(void)
6271ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz{
628a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz	pci_unregister_driver(&sis5513_pci_driver);
6291ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz}
6301ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewicz
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sis5513_ide_init);
6321ceb906b4062954e92295191402e9214345ee0e9Bartlomiej Zolnierkiewiczmodule_exit(sis5513_ide_exit);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI driver module for SIS IDE");
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
637