sis5513.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/ide/pci/sis5513.c	Version 0.16ac+vp	Jun 18, 2003
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003		Vojtech Pavlik <vojtech@suse.cz>
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/config.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h>
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h>
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ide-timing.h"
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DISPLAY_SIS_TIMINGS
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* registers layout and init values are chipset family dependant */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_16		0x01
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_33		0x02
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_66		0x03
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_100a	0x04 // SiS730/SiS550 is ATA100 with ATA66 layout
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_100		0x05
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_133a	0x06 // SiS961b with 133 support
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATA_133		0x07 // SiS962/963
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 chipset_family;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Devices supported
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct {
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *name;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 host_id;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 chipset_family;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 flags;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} SiSHostChipInfo[] = {
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS745",	PCI_DEVICE_ID_SI_745,	ATA_100  },
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS735",	PCI_DEVICE_ID_SI_735,	ATA_100  },
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS733",	PCI_DEVICE_ID_SI_733,	ATA_100  },
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS635",	PCI_DEVICE_ID_SI_635,	ATA_100  },
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS633",	PCI_DEVICE_ID_SI_633,	ATA_100  },
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS730",	PCI_DEVICE_ID_SI_730,	ATA_100a },
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS550",	PCI_DEVICE_ID_SI_550,	ATA_100a },
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS640",	PCI_DEVICE_ID_SI_640,	ATA_66   },
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS630",	PCI_DEVICE_ID_SI_630,	ATA_66   },
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS620",	PCI_DEVICE_ID_SI_620,	ATA_66   },
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS540",	PCI_DEVICE_ID_SI_540,	ATA_66   },
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS530",	PCI_DEVICE_ID_SI_530,	ATA_66   },
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5600",	PCI_DEVICE_ID_SI_5600,	ATA_33   },
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5598",	PCI_DEVICE_ID_SI_5598,	ATA_33   },
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5597",	PCI_DEVICE_ID_SI_5597,	ATA_33   },
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5591/2",	PCI_DEVICE_ID_SI_5591,	ATA_33   },
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5582",	PCI_DEVICE_ID_SI_5582,	ATA_33   },
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5581",	PCI_DEVICE_ID_SI_5581,	ATA_33   },
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5596",	PCI_DEVICE_ID_SI_5596,	ATA_16   },
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS5571",	PCI_DEVICE_ID_SI_5571,	ATA_16   },
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ "SiS551x",	PCI_DEVICE_ID_SI_5511,	ATA_16   },
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Cycle time bits and values vary across chip dma capabilities
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   These three arrays hold the register layout and the values to set.
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 cycle_time_range[] = {0,0,2,3,3,4,4};
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0}, /* no udma */
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0}, /* no udma */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{3,2,1,0,0,0,0}, /* ATA_33 */
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{7,5,3,2,1,0,0}, /* ATA_66 */
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{11,7,5,4,2,1,0}, /* ATA_100 */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{15,10,7,5,3,2,1}, /* ATA_133 */
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   See SiS962 data sheet for more detail */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0}, /* no udma */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0}, /* no udma */
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{2,1,1,0,0,0,0},
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{4,3,2,1,0,0,0},
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{4,3,2,1,0,0,0},
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{6,4,3,1,1,1,0},
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{9,6,4,2,2,2,2},
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{9,6,4,2,2,2,2},
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize time, Active time, Recovery time vary across
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   IDE clock settings. These 3 arrays hold the register value
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 ini_time_value[][8] = {
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0,0},
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0,0},
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{2,1,0,0,0,1,0,0},
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{4,3,1,1,1,3,1,1},
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{4,3,1,1,1,3,1,1},
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{6,4,2,2,2,4,2,2},
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{9,6,3,3,3,6,3,3},
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{9,6,3,3,3,6,3,3},
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 act_time_value[][8] = {
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0,0},
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0,0},
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{9,9,9,2,2,7,2,2},
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{19,19,19,5,4,14,5,4},
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{19,19,19,5,4,14,5,4},
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{28,28,28,7,6,21,7,6},
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{38,38,38,10,9,28,10,9},
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{38,38,38,10,9,28,10,9},
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 rco_time_value[][8] = {
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0,0},
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0,0,0,0,0,0,0,0},
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{9,2,0,2,0,7,1,1},
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{19,5,1,5,2,16,3,2},
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{19,5,1,5,2,16,3,2},
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{30,9,3,9,4,25,6,4},
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{40,12,4,12,5,34,12,5},
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{40,12,4,12,5,34,12,5},
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Printing configuration
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Used for chipset type printing at boot time */
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* chipset_capability[] = {
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA", "ATA 16",
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA 33", "ATA 66",
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA 100 (1st gen)", "ATA 100 (2nd gen)",
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ATA 133 (1st gen)", "ATA 133 (2nd gen)"
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h>
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h>
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 sis_proc = 0;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_dev *bmide_dev;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* cable_type[] = {
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"80 pins",
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"40 pins"
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* recovery_time[] ={
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"12 PCICLK", "1 PCICLK",
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"2 PCICLK", "3 PCICLK",
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"4 PCICLK", "5 PCICLCK",
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"6 PCICLK", "7 PCICLCK",
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"8 PCICLK", "9 PCICLCK",
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"10 PCICLK", "11 PCICLK",
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"13 PCICLK", "14 PCICLK",
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"15 PCICLK", "15 PCICLK"
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* active_time[] = {
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"8 PCICLK", "1 PCICLCK",
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"2 PCICLK", "3 PCICLK",
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"4 PCICLK", "5 PCICLK",
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"6 PCICLK", "12 PCICLK"
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* cycle_time[] = {
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Reserved", "2 CLK",
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"3 CLK", "4 CLK",
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"5 CLK", "6 CLK",
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"7 CLK", "8 CLK",
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"9 CLK", "10 CLK",
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"11 CLK", "12 CLK",
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"13 CLK", "14 CLK",
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"15 CLK", "16 CLK"
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Generic add master or slave info function */
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* get_drives_info (char *buffer, u8 pos)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg00, reg01, reg10, reg11; /* timing registers */
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 regdw0, regdw1;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char* p = buffer;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Postwrite/Prefetch */
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family < ATA_133) {
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(bmide_dev, 0x4b, &reg00);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "Drive %d:        Postwrite %s \t \t Postwrite %s\n",
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled",
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled");
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                Prefetch  %s \t \t Prefetch  %s\n",
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled",
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled");
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(bmide_dev, 0x40+2*pos, &reg00);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(bmide_dev, 0x41+2*pos, &reg01);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(bmide_dev, 0x44+2*pos, &reg10);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 reg54h;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 drive_pci = 0x40;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(bmide_dev, 0x54, &reg54h);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (reg54h & 0x40000000) {
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// Configuration space remapped to 0x70
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			drive_pci = 0x70;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos, &regdw0);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+4*pos+8, &regdw1);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "Drive %d:\n", pos);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* UDMA */
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family >= ATA_133) {
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                UDMA %s \t \t \t UDMA %s\n",
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (regdw0 & 0x04) ? "Enabled" : "Disabled",
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (regdw1 & 0x04) ? "Enabled" : "Disabled");
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                UDMA Cycle Time    %s \t UDMA Cycle Time    %s\n",
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     cycle_time[(regdw0 & 0xF0) >> 4],
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     cycle_time[(regdw1 & 0xF0) >> 4]);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chipset_family >= ATA_33) {
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                UDMA %s \t \t \t UDMA %s\n",
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg01 & 0x80) ? "Enabled" : "Disabled",
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg11 & 0x80) ? "Enabled" : "Disabled");
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                UDMA Cycle Time    ");
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(chipset_family) {
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_33:	p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_66:
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100a:	p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100:
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_133a:	p += sprintf(p, cycle_time[reg01 & 0x0F]); break;
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:	p += sprintf(p, "?"); break;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, " \t UDMA Cycle Time    ");
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(chipset_family) {
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_33:	p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_66:
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100a:	p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100:
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_133a:  p += sprintf(p, cycle_time[reg11 & 0x0F]); break;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:	p += sprintf(p, "?"); break;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "\n");
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family < ATA_133) {	/* else case TODO */
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Data Active */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                Data Active Time   ");
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(chipset_family) {
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_16: /* confirmed */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_33:
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_66:
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100:
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default: p += sprintf(p, "?"); break;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, " \t Data Active Time   ");
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(chipset_family) {
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_16:
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_33:
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_66:
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100:
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default: p += sprintf(p, "?"); break;
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "\n");
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Data Recovery */
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* warning: may need (reg&0x07) for pre ATA66 chips */
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "                Data Recovery Time %s \t Data Recovery Time %s\n",
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return p;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* get_masters_info(char* buffer)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return get_drives_info(buffer, 0);
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* get_slaves_info(char* buffer)
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return get_drives_info(buffer, 1);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Main get_info, called on /proc/ide/sis reads */
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis_get_info (char *buffer, char **addr, off_t offset, int count)
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *p = buffer;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 reg2, reg3;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p += sprintf(p, "\nSiS 5513 ");
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(chipset_family) {
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_16: p += sprintf(p, "DMA 16"); break;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_33: p += sprintf(p, "Ultra 33"); break;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_66: p += sprintf(p, "Ultra 66"); break;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_100a:
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_100: p += sprintf(p, "Ultra 100"); break;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_133a:
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case ATA_133: p += sprintf(p, "Ultra 133"); break;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default: p+= sprintf(p, "Unknown???"); break;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p += sprintf(p, " chipset\n");
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p += sprintf(p, "--------------- Primary Channel "
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     "---------------- Secondary Channel "
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     "-------------\n");
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Status */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(bmide_dev, 0x4a, &reg);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family == ATA_133) {
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_word(bmide_dev, 0x50, &reg2);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_word(bmide_dev, 0x52, &reg3);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p += sprintf(p, "Channel Status: ");
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family < ATA_66) {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "%s \t \t \t \t %s\n",
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg & 0x04) ? "On" : "Off",
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg & 0x02) ? "On" : "Off");
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chipset_family < ATA_133) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "%s \t \t \t \t %s \n",
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg & 0x02) ? "On" : "Off",
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg & 0x04) ? "On" : "Off");
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else { /* ATA_133 */
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "%s \t \t \t \t %s \n",
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg2 & 0x02) ? "On" : "Off",
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg3 & 0x02) ? "On" : "Off");
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Operation Mode */
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(bmide_dev, 0x09, &reg);
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p += sprintf(p, "Operation Mode: %s \t \t \t %s \n",
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (reg & 0x01) ? "Native" : "Compatible",
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (reg & 0x04) ? "Native" : "Compatible");
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 80-pin cable ? */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family >= ATA_133) {
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "Cable Type:     %s \t \t \t %s\n",
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg2 & 0x01) ? cable_type[1] : cable_type[0],
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg3 & 0x01) ? cable_type[1] : cable_type[0]);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chipset_family > ATA_33) {
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(bmide_dev, 0x48, &reg);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "Cable Type:     %s \t \t \t %s\n",
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg & 0x10) ? cable_type[1] : cable_type[0],
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     (reg & 0x20) ? cable_type[1] : cable_type[0]);
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Prefetch Count */
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family < ATA_133) {
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_word(bmide_dev, 0x4c, &reg2);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_word(bmide_dev, 0x4e, &reg3);
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n",
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     reg2, reg3);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = get_masters_info(p);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = get_slaves_info(p);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len = (p - buffer) - offset;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*addr = buffer + offset;
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return len > count ? count : len;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 sis5513_ratemask (ide_drive_t *drive)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 rates[] = { 0, 0, 1, 2, 3, 3, 4, 4 };
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 mode = rates[chipset_family];
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!eighty_ninty_three(drive))
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = min(mode, (u8)1);
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mode;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configuration functions
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Enables per-drive prefetch and postwrite */
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void config_drive_art_rwp (ide_drive_t *drive)
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ide_hwif_t *hwif	= HWIF(drive);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev	= hwif->pci_dev;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reg4bh		= 0;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 rw_prefetch		= (0x11 << drive->dn);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drive->media != ide_disk)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(dev, 0x4b, &reg4bh);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((reg4bh & rw_prefetch) != rw_prefetch)
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set per-drive active and recovery time */
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ide_hwif_t *hwif	= HWIF(drive);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev	= hwif->pci_dev;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8			timing, drive_pci, test1, test2;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 xfer_pio = drive->id->eide_pio_modes;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_drive_art_rwp(drive);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (xfer_pio> 4)
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xfer_pio = 0;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drive->id->eide_pio_iordy > 0) {
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (xfer_pio = 5;
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(xfer_pio > 0) &&
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(drive->id->eide_pio_iordy > eide_pio_timing[xfer_pio]);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			xfer_pio--);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   (drive->id->eide_pio_modes & 2) ? 0x04 :
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	timing = (xfer_pio >= pio) ? xfer_pio : pio;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drive_pci = 0x40;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family >= ATA_133) {
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 reg54h;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(dev, 0x54, &reg54h);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (reg54h & 0x40000000) drive_pci = 0x70;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		drive_pci += ((drive->dn)*0x4);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		drive_pci += ((drive->dn)*0x2);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register layout changed with newer ATA100 chips */
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family < ATA_100) {
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(dev, drive_pci, &test1);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(dev, drive_pci+1, &test2);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Clear active and recovery timings */
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test1 &= ~0x0F;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test2 &= ~0x07;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(timing) {
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 4:		test1 |= 0x01; test2 |= 0x03; break;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 3:		test1 |= 0x03; test2 |= 0x03; break;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 2:		test1 |= 0x04; test2 |= 0x04; break;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 1:		test1 |= 0x07; test2 |= 0x06; break;
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:	break;
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_write_config_byte(dev, drive_pci, test1);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_write_config_byte(dev, drive_pci+1, test2);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chipset_family < ATA_133) {
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(timing) { /*		active  recovery
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  v     v */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 4:		test1 = 0x30|0x01; break;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 3:		test1 = 0x30|0x03; break;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 2:		test1 = 0x40|0x04; break;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 1:		test1 = 0x60|0x07; break;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:	break;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_write_config_byte(dev, drive_pci, test1);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else { /* ATA_133 */
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 test3;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(dev, drive_pci, &test3);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test3 &= 0xc0c00fff;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test3 & 0x08) {
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test3 |= (unsigned long)ini_time_value[ATA_133][timing] << 12;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test3 |= (unsigned long)act_time_value[ATA_133][timing] << 16;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test3 |= (unsigned long)rco_time_value[ATA_133][timing] << 24;
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test3 |= (unsigned long)ini_time_value[ATA_100][timing] << 12;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test3 |= (unsigned long)act_time_value[ATA_100][timing] << 16;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test3 |= (unsigned long)rco_time_value[ATA_100][timing] << 24;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_write_config_dword(dev, drive_pci, test3);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int config_chipset_for_pio (ide_drive_t *drive, u8 pio)
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pio == 255)
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pio = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_art_rwp_pio(drive, pio);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ide_config_drive_speed(drive, XFER_PIO_0 + min_t(u8, pio, 4));
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed)
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ide_hwif_t *hwif	= HWIF(drive);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev	= hwif->pci_dev;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 drive_pci, reg, speed;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 regdw;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* See config_art_rwp_pio for drive pci config registers */
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drive_pci = 0x40;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family >= ATA_133) {
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 reg54h;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(dev, 0x54, &reg54h);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (reg54h & 0x40000000) drive_pci = 0x70;
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		drive_pci += ((drive->dn)*0x4);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_dword(dev, (unsigned long)drive_pci, &regdw);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable UDMA bit for non UDMA modes on UDMA chips */
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (speed < XFER_UDMA_0) {
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regdw &= 0xfffffffb;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		drive_pci += ((drive->dn)*0x2);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(dev, drive_pci+1, &reg);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable UDMA bit for non UDMA modes on UDMA chips */
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reg &= 0x7F;
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, drive_pci+1, reg);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Config chip for mode */
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(speed) {
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_6:
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_5:
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_4:
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_3:
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_2:
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_1:
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_UDMA_0:
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (chipset_family >= ATA_133) {
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				regdw |= 0x04;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				regdw &= 0xfffff00f;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* check if ATA133 enable */
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (regdw & 0x08) {
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* if ATA133 disable, we should not set speed above UDMA5 */
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (speed > XFER_UDMA_5)
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						speed = XFER_UDMA_5;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Force the UDMA bit on if we want to use UDMA */
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				reg |= 0x80;
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* clean reg cycle time bits */
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 << cycle_time_offset[chipset_family]);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* set reg cycle time bits */
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					<< cycle_time_offset[chipset_family];
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_write_config_byte(dev, drive_pci+1, reg);
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_MW_DMA_2:
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_MW_DMA_1:
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_MW_DMA_0:
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_SW_DMA_2:
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_SW_DMA_1:
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_SW_DMA_0:
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4));
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3));
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2));
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1));
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case XFER_PIO_0:
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:	 return((int) config_chipset_for_pio(drive, 0));
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((int) ide_config_drive_speed(drive, speed));
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sis5513_tune_drive (ide_drive_t *drive, u8 pio)
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void) config_chipset_for_pio(drive, pio);
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four))
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int config_chipset_for_dma (ide_drive_t *drive)
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 speed	= ide_dma_speed(drive, sis5513_ratemask(drive));
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n",
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       drive->dn, drive->id->dma_ultra);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(speed))
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sis5513_tune_chipset(drive, speed);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ide_dma_enable(drive);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis5513_config_drive_xfer_rate (ide_drive_t *drive)
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ide_hwif_t *hwif	= HWIF(drive);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct hd_driveid *id	= drive->id;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drive->init_speed = 0;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (id && (id->capability & 1) && drive->autodma) {
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ide_use_dma(drive)) {
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (config_chipset_for_dma(drive))
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return hwif->ide_dma_on(drive);
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fast_ata_pio;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if ((id->capability & 8) || (id->field_valid & 2)) {
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfast_ata_pio:
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sis5513_tune_drive(drive, 5);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hwif->ide_dma_off_quietly(drive);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* IORDY not supported */
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* initiates/aborts (U)DMA read/write operations on a drive. */
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis5513_config_xfer_rate (ide_drive_t *drive)
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_drive_art_rwp(drive);
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_art_rwp_pio(drive, 5);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return sis5513_config_drive_xfer_rate(drive);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  Future simpler config_xfer_rate :
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   When ide_find_best_mode is made bad-drive aware
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   - remove config_drive_xfer_rate and config_chipset_for_dma,
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   - replace config_xfer_rate with the following
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis5513_config_xfer_rate (ide_drive_t *drive)
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 w80 = HWIF(drive)->udma_four;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 speed;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_drive_art_rwp(drive);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	config_art_rwp_pio(drive, 5);
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	speed = ide_find_best_mode(drive,
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(chipset_family >= ATA_33 ? XFER_UDMA : 0) |
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) |
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) |
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0));
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sis5513_tune_chipset(drive, speed);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return HWIF(drive)->ide_dma_on(drive);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return HWIF(drive)->ide_dma_off_quietly(drive);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Chip detection and general config */
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name)
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *host;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chipset_family = 0;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		host = pci_find_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!host)
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		chipset_family = SiSHostChipInfo[i].chipset_family;
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Special case for SiS630 : 630S/ET is ATA_100a */
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 hostrev;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_byte(host, PCI_REVISION_ID, &hostrev);
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (hostrev >= 0x30)
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				chipset_family = ATA_100a;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "SIS5513: %s %s controller\n",
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chipset_family) { /* Belongs to pci-quirks */
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u32 idemisc;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u16 trueid;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Disable ID masking and register remapping */
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_dword(dev, 0x54, &idemisc);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_dword(dev, 0x54, idemisc);
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (trueid == 0x5518) {
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				chipset_family = ATA_133;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Check for 5513 compability mapping
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * We must use this, else the port enabled code will fail,
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * as it expects the enablebits at 0x4a.
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((idemisc & 0x40000000) == 0) {
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chipset_family) { /* Belongs to pci-quirks */
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pci_dev *lpc_bridge;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u16 trueid;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 prefctl;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 idecfg;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 sbrev;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_byte(dev, 0x4a, &idecfg);
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_write_config_byte(dev, 0x4a, idecfg);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (trueid == 0x5517) { /* SiS 961/961B */
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(dev, 0x49, &prefctl);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (sbrev == 0x10 && (prefctl & 0x80)) {
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					chipset_family = ATA_133a;
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n");
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					chipset_family = ATA_100;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chipset_family)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make general config ops here
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   1/ tell IDE channels to operate in Compatibility mode only
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   2/ tell old chips to allow per drive IDE timings */
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 reg;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u16 regw;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(chipset_family) {
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_133:
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* SiS962 operation mode */
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_word(dev, 0x50, &regw);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (regw & 0x08)
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_word(dev, 0x50, regw&0xfff7);
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_word(dev, 0x52, &regw);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (regw & 0x08)
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_word(dev, 0x52, regw&0xfff7);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_133a:
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100:
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Fixup latency */
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Set compatibility bit */
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(dev, 0x49, &reg);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!(reg & 0x01)) {
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_byte(dev, 0x49, reg|0x01);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_100a:
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_66:
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Fixup latency */
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* On ATA_66 chips the bit was elsewhere */
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(dev, 0x52, &reg);
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!(reg & 0x04)) {
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_byte(dev, 0x52, reg|0x04);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_33:
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* On ATA_33 we didn't have a single bit to set */
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(dev, 0x09, &reg);
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((reg & 0x0f) != 0x00) {
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_byte(dev, 0x09, reg&0xf0);
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case ATA_16:
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* force per drive recovery and active timings
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   needed on ATA_33 and below chips */
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_read_config_byte(dev, 0x52, &reg);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!(reg & 0x08)) {
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					pci_write_config_byte(dev, 0x52, reg|0x08);
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!sis_proc) {
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sis_proc = 1;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bmide_dev = dev;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ide_pci_create_host_proc("sis", sis_get_info);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 ata66 = 0;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family >= ATA_133) {
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u16 regw = 0;
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u16 reg_addr = hwif->channel ? 0x52: 0x50;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_word(hwif->pci_dev, reg_addr, &regw);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ata66 = (regw & 0x8000) ? 0 : 1;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (chipset_family >= ATA_66) {
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 reg48h = 0;
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 mask = hwif->channel ? 0x20 : 0x10;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ata66 = (reg48h & mask) ? 0 : 1;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return ata66;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_hwif_sis5513 (ide_hwif_t *hwif)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->autodma = 0;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!hwif->irq)
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwif->irq = hwif->channel ? 15 : 14;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->tuneproc = &sis5513_tune_drive;
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->speedproc = &sis5513_tune_chipset;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(hwif->dma_base)) {
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwif->drives[0].autotune = 1;
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwif->drives[1].autotune = 1;
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->atapi_dma = 1;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->ultra_mask = 0x7f;
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->mwdma_mask = 0x07;
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->swdma_mask = 0x07;
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chipset_family)
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(hwif->udma_four))
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwif->udma_four = ata66_sis5513(hwif);
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chipset_family > ATA_16) {
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwif->ide_dma_check = &sis5513_config_xfer_rate;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!noautodma)
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			hwif->autodma = 1;
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->drives[0].autodma = hwif->autodma;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwif->drives[1].autodma = hwif->autodma;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ide_pci_device_t sis5513_chipset __devinitdata = {
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "SIS5513",
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init_chipset	= init_chipset_sis5513,
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init_hwif	= init_hwif_sis5513,
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.channels	= 2,
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.autodma	= NOAUTODMA,
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.bootable	= ON_BOARD,
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ide_setup_pci_device(dev, &sis5513_chipset);
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id sis5513_pci_tbl[] = {
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, },
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver driver = {
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "SIS_IDE",
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= sis5513_pci_tbl,
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= sis5513_init_one,
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sis5513_ide_init(void)
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ide_pci_register_driver(&driver);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sis5513_ide_init);
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI driver module for SIS IDE");
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TODO:
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	- CLEANUP
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	- Use drivers/ide/ide-timing.h !
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	- More checks in the config registers (force values instead of
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	  relying on the BIOS setting them correctly).
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	- Further optimisations ?
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	  . for example ATA66+ regs 0x48 & 0x4A
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
985