📄 sis5513.c
字号:
/* * linux/drivers/ide/pci/sis5513.c Version 0.14ac Sept 11, 2002 * * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * May be copied or modified under the terms of the GNU General Public License * * * Thanks : * * SiS Taiwan : for direct support and hardware. * Daniela Engert : for initial ATA100 advices and numerous others. * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : * for checking code correctness, providing patches. * * * Original tests and design on the SiS620/5513 chipset. * ATA100 tests and design on the SiS735/5513 chipset. * ATA16/33 support from specs * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw> * * Documentation: * SiS chipset documentation available under NDA to companies not * individuals only. *//* * Notes/Special cases: * - SiS5513 derivatives usually have the same PCI IDE register layout when * supporting the same UDMA modes. * - There are exceptions : * . SiS730 and SiS550 use the same layout than ATA_66 chipsets but support * ATA_100 * . ATA_133 capable chipsets mark a shift in SiS chipset designs : previously * south and northbridge were integrated, making IDE (a southbridge function) * capabilities easily deduced from the northbridge PCI id. With ATA_133, * chipsets started to be split in the usual north/south bridges chips * -> the driver needs to detect the correct southbridge when faced to newest * northbridges. * . On ATA133 capable chipsets when bit 30 of dword at 0x54 is 1 the * configuration space is moved from 0x40 to 0x70. */#include <linux/config.h>#include <linux/types.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ide.h>#include <asm/io.h>#include <asm/irq.h>#include "ide_modes.h"#include "sis5513.h"/* When DEBUG is defined it outputs initial PCI config register values and changes made to them by the driver */// #define DEBUG/* When BROKEN_LEVEL is defined it limits the DMA mode at boot time to its value */// #define BROKEN_LEVEL XFER_SW_DMA_0/* Miscellaneous flags */#define SIS5513_LATENCY 0x01/* registers layout and init values are chipset family dependant *//* 1/ define families */#define ATA_00 0x00#define ATA_16 0x01#define ATA_33 0x02#define ATA_66 0x03#define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout#define ATA_100 0x05#define ATA_133a 0x06 // SiS961b with 133 support#define ATA_133 0x07 // SiS962/* 2/ variable holding the controller chipset family value */static u8 chipset_family;/* * Debug code: following IDE config registers' changes */#ifdef DEBUG/* Copy of IDE Config registers fewer will be used * Some odd chipsets hang if unused registers are accessed * -> We only access them in #DEBUG code (then we'll see if SiS did * it right from day one) */static u8 ide_regs_copy[0xff];/* Read config registers, print differences from previous read */static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { int i; u8 reg_val; u8 changed=0; printk("SIS5513: %s, changed registers:\n", info); for(i=0; i<=0xff; i++) { pci_read_config_byte(dev, i, ®_val); if (reg_val != ide_regs_copy[i]) { printk("%02x: %02x -> %02x\n", i, ide_regs_copy[i], reg_val); ide_regs_copy[i]=reg_val; changed=1; } } if (!changed) { printk("none\n"); }}/* Load config registers, no printing */static void sis5513_load_registers(struct pci_dev* dev) { int i; for(i=0; i<=0xff; i++) { pci_read_config_byte(dev, i, &(ide_regs_copy[i])); }}/* Print config space registers a la "lspci -vxxx" */static void sis5513_print_registers(struct pci_dev* dev, char* marker) { int i,j; sis5513_load_registers(dev); printk("SIS5513 %s\n", marker); for(i=0; i<=0xf; i++) { printk("SIS5513 dump: %d" "0:", i); for(j=0; j<=0xf; j++) { printk(" %02x", ide_regs_copy[(i<<16)+j]); } printk("\n"); }}#endif/* * Devices supported */static const struct { const char *name; u16 host_id; u8 chipset_family; u8 flags;} SiSHostChipInfo[] = { { "SiS752", PCI_DEVICE_ID_SI_752, ATA_133, 0 }, { "SiS751", PCI_DEVICE_ID_SI_751, ATA_133, 0 }, { "SiS750", PCI_DEVICE_ID_SI_750, ATA_133, 0 }, { "SiS748", PCI_DEVICE_ID_SI_748, ATA_133, 0 }, { "SiS746", PCI_DEVICE_ID_SI_746, ATA_133, 0 }, { "SiS745", PCI_DEVICE_ID_SI_745, ATA_133, 0 }, { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, 0 }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY }, { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, { "SiS652", PCI_DEVICE_ID_SI_652, ATA_133, 0 }, { "SiS651", PCI_DEVICE_ID_SI_651, ATA_133, 0 }, { "SiS650", PCI_DEVICE_ID_SI_650, ATA_133, 0 }, { "SiS648", PCI_DEVICE_ID_SI_648, ATA_133, 0 }, { "SiS646", PCI_DEVICE_ID_SI_646, ATA_133, 0 }, { "SiS645", PCI_DEVICE_ID_SI_645, ATA_133, 0 }, { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100, SIS5513_LATENCY }, { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY }, { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY }, { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66, SIS5513_LATENCY }, { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a, 0}, { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66, 0}, { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0}, { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0}, { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33, 0}, { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33, 0}, { "SiS5591", PCI_DEVICE_ID_SI_5591, ATA_33, 0}, { "SiS5513", PCI_DEVICE_ID_SI_5513, ATA_16, 0}, { "SiS5511", PCI_DEVICE_ID_SI_5511, ATA_16, 0},};/* Cycle time bits and values vary across chip dma capabilities These three arrays hold the register layout and the values to set. Indexed by chipset_family and (dma_mode - XFER_UDMA_0) *//* {ATA_00, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};static u8 cycle_time_range[] = {0,0,2,3,3,4,4};static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { {0,0,0,0,0,0,0}, /* no udma */ {0,0,0,0,0,0,0}, /* no udma */ {3,2,1,0,0,0,0}, /* ATA_33 */ {7,5,3,2,1,0,0}, /* ATA_66 */ {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */ {11,7,5,4,2,1,0}, /* ATA_100 */ {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */ {15,10,7,5,3,2,1}, /* ATA_133 */};/* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133 See SiS962 data sheet for more detail */static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { {0,0,0,0,0,0,0}, /* no udma */ {0,0,0,0,0,0,0}, /* no udma */ {2,1,1,0,0,0,0}, {4,3,2,1,0,0,0}, {4,3,2,1,0,0,0}, {6,4,3,1,1,1,0}, {9,6,4,2,2,2,2}, {9,6,4,2,2,2,2},};/* Initialize time, Active time, Recovery time vary across IDE clock settings. These 3 arrays hold the register value for PIO0/1/2/3/4 and DMA0/1/2 mode in order */static u8 ini_time_value[][8] = { {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {2,1,0,0,0,1,0,0}, {4,3,1,1,1,3,1,1}, {4,3,1,1,1,3,1,1}, {6,4,2,2,2,4,2,2}, {9,6,3,3,3,6,3,3}, {9,6,3,3,3,6,3,3},};static u8 act_time_value[][8] = { {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {9,9,9,2,2,7,2,2}, {19,19,19,5,4,14,5,4}, {19,19,19,5,4,14,5,4}, {28,28,28,7,6,21,7,6}, {38,38,38,10,9,28,10,9}, {38,38,38,10,9,28,10,9},};static u8 rco_time_value[][8] = { {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {9,2,0,2,0,7,1,1}, {19,5,1,5,2,16,3,2}, {19,5,1,5,2,16,3,2}, {30,9,3,9,4,25,6,4}, {40,12,4,12,5,34,12,5}, {40,12,4,12,5,34,12,5},};static struct pci_dev *host_dev = NULL;/* * Printing configuration *//* Used for chipset type printing at boot time */static char* chipset_capability[] = { "ATA", "ATA 16", "ATA 33", "ATA 66", "ATA 100", "ATA 100", "ATA 133", "ATA 133"};#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static u8 sis_proc = 0;static struct pci_dev *bmide_dev;static char* cable_type[] = { "80 pins", "40 pins"};static char* recovery_time[] ={ "12 PCICLK", "1 PCICLK", "2 PCICLK", "3 PCICLK", "4 PCICLK", "5 PCICLCK", "6 PCICLK", "7 PCICLCK", "8 PCICLK", "9 PCICLCK", "10 PCICLK", "11 PCICLK", "13 PCICLK", "14 PCICLK", "15 PCICLK", "15 PCICLK"};static char* active_time[] = { "8 PCICLK", "1 PCICLCK", "2 PCICLK", "3 PCICLK", "4 PCICLK", "5 PCICLK", "6 PCICLK", "12 PCICLK"};static char* cycle_time[] = { "Reserved", "2 CLK", "3 CLK", "4 CLK", "5 CLK", "6 CLK", "7 CLK", "8 CLK", "9 CLK", "10 CLK", "11 CLK", "12 CLK", "13 CLK", "14 CLK", "15 CLK", "16 CLK"};/* Generic add master or slave info function */static char* get_drives_info (char *buffer, u8 pos){ u8 reg00, reg01, reg10, reg11; /* timing registers */ u32 regdw0, regdw1; char* p = buffer;/* Postwrite/Prefetch */ if (chipset_family < ATA_133) { pci_read_config_byte(bmide_dev, 0x4b, ®00); p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", (reg00 & (0x40 << pos)) ? "Enabled" : "Disabled"); p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); pci_read_config_byte(bmide_dev, 0x40+2*pos, ®00); pci_read_config_byte(bmide_dev, 0x41+2*pos, ®01); pci_read_config_byte(bmide_dev, 0x44+2*pos, ®10); pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); } else { u32 reg54h; u8 drive_pci = 0x40; pci_read_config_dword(bmide_dev, 0x54, ®54h); if (reg54h & 0x40000000) { // Configuration space remapped to 0x70 drive_pci = 0x70; } pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+8*pos, ®dw0); pci_read_config_dword(bmide_dev, (unsigned long)drive_pci+8*pos+4, ®dw1); p += sprintf(p, "Drive %d:\n", pos); }/* UDMA */ if (chipset_family >= ATA_133) { p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", (regdw0 & 0x04) ? "Enabled" : "Disabled", (regdw1 & 0x04) ? "Enabled" : "Disabled"); p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", cycle_time[(regdw0 & 0xF0) >> 4], cycle_time[(regdw1 & 0xF0) >> 4]); } else if (chipset_family >= ATA_33) { p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", (reg01 & 0x80) ? "Enabled" : "Disabled", (reg11 & 0x80) ? "Enabled" : "Disabled"); p += sprintf(p, " UDMA Cycle Time "); switch(chipset_family) { case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; case ATA_66: case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; case ATA_100: case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } p += sprintf(p, " \t UDMA Cycle Time "); switch(chipset_family) { case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; case ATA_66: case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; case ATA_100: case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; case ATA_133:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -