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