Commit 9382310f authored by Jens Axboe's avatar Jens Axboe

sis5513 update

parent 49bbaa0c
/* /*
* linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002 * linux/drivers/ide/sis5513.c Version 0.14 July 24, 2002
* *
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
* *
* Original tests and design on the SiS620/5513 chipset. * Original tests and design on the SiS620/5513 chipset.
* ATA100 tests and design on the SiS735/5513 chipset. * ATA100 tests and design on the SiS735/5513 chipset.
* ATA16/33 design from specs * ATA16/33 support from specs
* ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw>
*/ */
/* /*
* TODO: * TODO:
* - Get ridden of SisHostChipInfo[] completness dependancy. * - Get ridden of SisHostChipInfo[] completness dependancy.
* - Get ATA-133 datasheets, implement ATA-133 init code.
* - Study drivers/ide/ide-timing.h. * - Study drivers/ide/ide-timing.h.
* - Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them * - Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them
* or remove ATA_00 define * or remove ATA_00 define
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include "ide_modes.h" #include "ide_modes.h"
#include "sis5513.h"
/* When DEBUG is defined it outputs initial PCI config register /* When DEBUG is defined it outputs initial PCI config register
values and changes made to them by the driver */ values and changes made to them by the driver */
...@@ -58,7 +59,6 @@ ...@@ -58,7 +59,6 @@
/* When BROKEN_LEVEL is defined it limits the DMA mode /* When BROKEN_LEVEL is defined it limits the DMA mode
at boot time to its value */ at boot time to its value */
// #define BROKEN_LEVEL XFER_SW_DMA_0 // #define BROKEN_LEVEL XFER_SW_DMA_0
#define DISPLAY_SIS_TIMINGS
/* Miscellaneaous flags */ /* Miscellaneaous flags */
#define SIS5513_LATENCY 0x01 #define SIS5513_LATENCY 0x01
...@@ -71,44 +71,33 @@ ...@@ -71,44 +71,33 @@
#define ATA_66 0x03 #define ATA_66 0x03
#define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout #define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout
#define ATA_100 0x05 #define ATA_100 0x05
#define ATA_133 0x06 #define ATA_133a 0x06 // SiS961b with 133 support
#define ATA_133 0x07 // SiS962
/* 2/ variable holding the controller chipset family value */ /* 2/ variable holding the controller chipset family value */
static unsigned char chipset_family; static u8 chipset_family;
/* /*
* Debug code: following IDE config registers' changes * Debug code: following IDE config registers' changes
*/ */
#ifdef DEBUG #ifdef DEBUG
/* Copy of IDE Config registers 0x00 -> 0x57 /* Copy of IDE Config registers fewer will be used
Fewer might be used depending on the actual chipset */ * Some odd chipsets hang if unused registers are accessed
static unsigned char ide_regs_copy[0x58]; * -> We only access them in #DEBUG code (then we'll see if SiS did
* it right from day one) */
static byte sis5513_max_config_register(void) { static u8 ide_regs_copy[0xff];
switch(chipset_family) {
case ATA_00:
case ATA_16: return 0x4f;
case ATA_33: return 0x52;
case ATA_66:
case ATA_100a:
case ATA_100:
case ATA_133:
default: return 0x57;
}
}
/* Read config registers, print differences from previous read */ /* Read config registers, print differences from previous read */
static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) {
int i; int i;
byte reg_val; u8 reg_val;
byte changed=0; u8 changed=0;
byte max = sis5513_max_config_register();
printk("SIS5513: %s, changed registers:\n", info); printk("SIS5513: %s, changed registers:\n", info);
for(i=0; i<=max; i++) { for(i=0; i<=0xff; i++) {
pci_read_config_byte(dev, i, &reg_val); pci_read_config_byte(dev, i, &reg_val);
if (reg_val != ide_regs_copy[i]) { if (reg_val != ide_regs_copy[i]) {
printk("%0#x: %0#x -> %0#x\n", printk("%02x: %02x -> %02x\n",
i, ide_regs_copy[i], reg_val); i, ide_regs_copy[i], reg_val);
ide_regs_copy[i]=reg_val; ide_regs_copy[i]=reg_val;
changed=1; changed=1;
...@@ -123,39 +112,26 @@ static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { ...@@ -123,39 +112,26 @@ static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) {
/* Load config registers, no printing */ /* Load config registers, no printing */
static void sis5513_load_registers(struct pci_dev* dev) { static void sis5513_load_registers(struct pci_dev* dev) {
int i; int i;
byte max = sis5513_max_config_register();
for(i=0; i<=max; i++) { for(i=0; i<=0xff; i++) {
pci_read_config_byte(dev, i, &(ide_regs_copy[i])); pci_read_config_byte(dev, i, &(ide_regs_copy[i]));
} }
} }
/* Print a register */ /* Print config space registers a la "lspci -vxxx" */
static void sis5513_print_register(int reg) {
printk(" %0#x:%0#x", reg, ide_regs_copy[reg]);
}
/* Print valuable registers */
static void sis5513_print_registers(struct pci_dev* dev, char* marker) { static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
int i; int i,j;
byte max = sis5513_max_config_register();
sis5513_load_registers(dev); sis5513_load_registers(dev);
printk("SIS5513 %s\n", marker); printk("SIS5513 %s\n", marker);
printk("SIS5513 dump:");
for(i=0x00; i<0x40; i++) {
if ((i % 0x10)==0) printk("\n ");
sis5513_print_register(i);
}
for(; i<49; i++) {
sis5513_print_register(i);
}
printk("\n ");
for(; i<=max; i++) { for(i=0; i<=0xf; i++) {
sis5513_print_register(i); printk("SIS5513 dump: %d" "0:", i);
for(j=0; j<=0xf; j++) {
printk(" %02x", ide_regs_copy[(i<<16)+j]);
} }
printk("\n"); printk("\n");
}
} }
#endif #endif
...@@ -165,21 +141,30 @@ static void sis5513_print_registers(struct pci_dev* dev, char* marker) { ...@@ -165,21 +141,30 @@ static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
*/ */
static const struct { static const struct {
const char *name; const char *name;
unsigned short host_id; u16 host_id;
unsigned char chipset_family; u8 chipset_family;
unsigned char flags; u8 flags;
} SiSHostChipInfo[] = { } SiSHostChipInfo[] = {
{ "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY }, { "SiS752", PCI_DEVICE_ID_SI_752, ATA_133, 0 },
{ "SiS745", PCI_DEVICE_ID_SI_745, ATA_100, SIS5513_LATENCY }, { "SiS751", PCI_DEVICE_ID_SI_751, ATA_133, 0 },
{ "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, SIS5513_LATENCY }, { "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 }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY },
{ "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY },
{ "SiS650", PCI_DEVICE_ID_SI_650, ATA_100, SIS5513_LATENCY }, { "SiS652", PCI_DEVICE_ID_SI_652, ATA_133, 0 },
{ "SiS645", PCI_DEVICE_ID_SI_645, ATA_100, SIS5513_LATENCY }, { "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 }, { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100, SIS5513_LATENCY },
{ "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY }, { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY },
{ "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY }, { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY },
{ "SiS620", PCI_DEVICE_ID_SI_620, 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}, { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66, 0},
{ "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0}, { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0},
{ "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0}, { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0},
...@@ -193,21 +178,68 @@ static const struct { ...@@ -193,21 +178,68 @@ static const struct {
/* Cycle time bits and values vary accross chip dma capabilities /* Cycle time bits and values vary accross chip dma capabilities
These three arrays hold the register layout and the values to set. These three arrays hold the register layout and the values to set.
Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
static byte cycle_time_range[] = {0,0,2,3,3,4,4}; /* {ATA_00, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
{0,0,0,0,0,0}, /* no udma */ static u8 cycle_time_range[] = {0,0,2,3,3,4,4};
{0,0,0,0,0,0}, /* no udma */ static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
{3,2,1,0,0,0}, {0,0,0,0,0,0,0}, /* no udma */
{7,5,3,2,1,0}, {0,0,0,0,0,0,0}, /* no udma */
{7,5,3,2,1,0}, {3,2,1,0,0,0,0}, /* ATA_33 */
{11,7,5,4,2,1}, {7,5,3,2,1,0,0}, /* ATA_66 */
{0,0,0,0,0,0} /* not yet known, ask SiS */ {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 accross 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 accross
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; static struct pci_dev *host_dev = NULL;
/* /*
* Printing configuration * Printing configuration
*/ */
...@@ -215,8 +247,8 @@ static struct pci_dev *host_dev = NULL; ...@@ -215,8 +247,8 @@ static struct pci_dev *host_dev = NULL;
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
static int sis_get_info(char *, char **, off_t, int); static u8 sis_proc = 0;
extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */
static struct pci_dev *bmide_dev; static struct pci_dev *bmide_dev;
static char* cable_type[] = { static char* cable_type[] = {
...@@ -249,17 +281,25 @@ static char* cycle_time[] = { ...@@ -249,17 +281,25 @@ static char* cycle_time[] = {
"7 CLK", "8 CLK", "7 CLK", "8 CLK",
"9 CLK", "10 CLK", "9 CLK", "10 CLK",
"11 CLK", "12 CLK", "11 CLK", "12 CLK",
"Reserved", "Reserved", "13 CLK", "14 CLK",
"Reserved", "Reserved" "15 CLK", "16 CLK"
};
static char* chipset_capability[] = {
"ATA", "ATA 16",
"ATA 33", "ATA 66",
"ATA 100", "ATA 100",
"ATA 133", "ATA 133"
}; };
/* Generic add master or slave info function */ /* Generic add master or slave info function */
static char* get_drives_info (char *buffer, byte pos) static char* get_drives_info (char *buffer, u8 pos)
{ {
byte reg00, reg01, reg10, reg11; /* timing registers */ u8 reg00, reg01, reg10, reg11; /* timing registers */
char* p = buffer; char* p = buffer;
/* Postwrite/Prefetch */ /* Postwrite/Prefetch */
if (chipset_family < ATA_133) {
pci_read_config_byte(bmide_dev, 0x4b, &reg00); pci_read_config_byte(bmide_dev, 0x4b, &reg00);
p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n", p += sprintf(p, "Drive %d: Postwrite %s \t \t Postwrite %s\n",
pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled", pos, (reg00 & (0x10 << pos)) ? "Enabled" : "Disabled",
...@@ -267,11 +307,12 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -267,11 +307,12 @@ static char* get_drives_info (char *buffer, byte pos)
p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n",
(reg00 & (0x01 << pos)) ? "Enabled" : "Disabled", (reg00 & (0x01 << pos)) ? "Enabled" : "Disabled",
(reg00 & (0x04 << pos)) ? "Enabled" : "Disabled"); (reg00 & (0x04 << pos)) ? "Enabled" : "Disabled");
pci_read_config_byte(bmide_dev, 0x40+2*pos, &reg00); pci_read_config_byte(bmide_dev, 0x40+2*pos, &reg00);
pci_read_config_byte(bmide_dev, 0x41+2*pos, &reg01); pci_read_config_byte(bmide_dev, 0x41+2*pos, &reg01);
pci_read_config_byte(bmide_dev, 0x44+2*pos, &reg10); pci_read_config_byte(bmide_dev, 0x44+2*pos, &reg10);
pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11); pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
}
/* UDMA */ /* UDMA */
if (chipset_family >= ATA_33) { if (chipset_family >= ATA_33) {
...@@ -284,7 +325,8 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -284,7 +325,8 @@ static char* get_drives_info (char *buffer, byte pos)
case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
case ATA_66: case ATA_66:
case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
case ATA_100: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; case ATA_100:
case ATA_133a: p += sprintf(p, cycle_time[reg01 & 0x0F]); break;
case ATA_133: case ATA_133:
default: p += sprintf(p, "133+ ?"); break; default: p += sprintf(p, "133+ ?"); break;
} }
...@@ -293,7 +335,8 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -293,7 +335,8 @@ static char* get_drives_info (char *buffer, byte pos)
case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
case ATA_66: case ATA_66:
case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
case ATA_100: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; case ATA_100:
case ATA_133a: p += sprintf(p, cycle_time[reg11 & 0x0F]); break;
case ATA_133: case ATA_133:
default: p += sprintf(p, "133+ ?"); break; default: p += sprintf(p, "133+ ?"); break;
} }
...@@ -308,7 +351,8 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -308,7 +351,8 @@ static char* get_drives_info (char *buffer, byte pos)
case ATA_33: case ATA_33:
case ATA_66: case ATA_66:
case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break;
case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; case ATA_100:
case ATA_133a: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break;
case ATA_133: case ATA_133:
default: p += sprintf(p, "133+ ?"); break; default: p += sprintf(p, "133+ ?"); break;
} }
...@@ -319,7 +363,8 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -319,7 +363,8 @@ static char* get_drives_info (char *buffer, byte pos)
case ATA_33: case ATA_33:
case ATA_66: case ATA_66:
case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break;
case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; case ATA_100:
case ATA_133a: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break;
case ATA_133: case ATA_133:
default: p += sprintf(p, "133+ ?"); break; default: p += sprintf(p, "133+ ?"); break;
} }
...@@ -327,8 +372,10 @@ static char* get_drives_info (char *buffer, byte pos) ...@@ -327,8 +372,10 @@ static char* get_drives_info (char *buffer, byte pos)
/* Data Recovery */ /* Data Recovery */
/* warning: may need (reg&0x07) for pre ATA66 chips */ /* warning: may need (reg&0x07) for pre ATA66 chips */
if (chipset_family < ATA_133) {
p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n",
recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]); recovery_time[reg00 & 0x0f], recovery_time[reg10 & 0x0f]);
}
return p; return p;
} }
...@@ -347,7 +394,7 @@ static char* get_slaves_info(char* buffer) ...@@ -347,7 +394,7 @@ static char* get_slaves_info(char* buffer)
static int sis_get_info (char *buffer, char **addr, off_t offset, int count) static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
{ {
char *p = buffer; char *p = buffer;
byte reg; u8 reg;
u16 reg2, reg3; u16 reg2, reg3;
p += sprintf(p, "\nSiS 5513 "); p += sprintf(p, "\nSiS 5513 ");
...@@ -358,8 +405,9 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -358,8 +405,9 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
case ATA_66: p += sprintf(p, "Ultra 66"); break; case ATA_66: p += sprintf(p, "Ultra 66"); break;
case ATA_100a: case ATA_100a:
case ATA_100: p += sprintf(p, "Ultra 100"); break; case ATA_100: p += sprintf(p, "Ultra 100"); break;
case ATA_133: case ATA_133a:
default: p+= sprintf(p, "Ultra 133+"); break; case ATA_133: p += sprintf(p, "Ultra 133"); break;
default: p+= sprintf(p, "Unknown???"); break;
} }
p += sprintf(p, " chipset\n"); p += sprintf(p, " chipset\n");
p += sprintf(p, "--------------- Primary Channel " p += sprintf(p, "--------------- Primary Channel "
...@@ -368,15 +416,23 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -368,15 +416,23 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
/* Status */ /* Status */
pci_read_config_byte(bmide_dev, 0x4a, &reg); pci_read_config_byte(bmide_dev, 0x4a, &reg);
if (chipset_family == ATA_133) {
pci_read_config_word(bmide_dev, 0x50, &reg2);
pci_read_config_word(bmide_dev, 0x52, &reg3);
}
p += sprintf(p, "Channel Status: "); p += sprintf(p, "Channel Status: ");
if (chipset_family < ATA_66) { if (chipset_family < ATA_66) {
p += sprintf(p, "%s \t \t \t \t %s\n", p += sprintf(p, "%s \t \t \t \t %s\n",
(reg & 0x04) ? "On" : "Off", (reg & 0x04) ? "On" : "Off",
(reg & 0x02) ? "On" : "Off"); (reg & 0x02) ? "On" : "Off");
} else { } else if (chipset_family < ATA_133) {
p += sprintf(p, "%s \t \t \t \t %s \n", p += sprintf(p, "%s \t \t \t \t %s \n",
(reg & 0x02) ? "On" : "Off", (reg & 0x02) ? "On" : "Off",
(reg & 0x04) ? "On" : "Off"); (reg & 0x04) ? "On" : "Off");
} else { /* ATA_133 */
p += sprintf(p, "%s \t \t \t \t %s \n",
(reg2 & 0x02) ? "On" : "Off",
(reg3 & 0x02) ? "On" : "Off");
} }
/* Operation Mode */ /* Operation Mode */
...@@ -386,7 +442,11 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -386,7 +442,11 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
(reg & 0x04) ? "Native" : "Compatible"); (reg & 0x04) ? "Native" : "Compatible");
/* 80-pin cable ? */ /* 80-pin cable ? */
if (chipset_family > ATA_33) { if (chipset_family >= ATA_133) {
p += sprintf(p, "Cable Type: %s \t \t \t %s\n",
(reg2 & 0x01) ? cable_type[1] : cable_type[0],
(reg3 & 0x01) ? cable_type[1] : cable_type[0]);
} else if (chipset_family > ATA_33) {
pci_read_config_byte(bmide_dev, 0x48, &reg); pci_read_config_byte(bmide_dev, 0x48, &reg);
p += sprintf(p, "Cable Type: %s \t \t \t %s\n", p += sprintf(p, "Cable Type: %s \t \t \t %s\n",
(reg & 0x10) ? cable_type[1] : cable_type[0], (reg & 0x10) ? cable_type[1] : cable_type[0],
...@@ -394,10 +454,12 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -394,10 +454,12 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
} }
/* Prefetch Count */ /* Prefetch Count */
if (chipset_family < ATA_133) {
pci_read_config_word(bmide_dev, 0x4c, &reg2); pci_read_config_word(bmide_dev, 0x4c, &reg2);
pci_read_config_word(bmide_dev, 0x4e, &reg3); pci_read_config_word(bmide_dev, 0x4e, &reg3);
p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n",
reg2, reg3); reg2, reg3);
}
p = get_masters_info(p); p = get_masters_info(p);
p = get_slaves_info(p); p = get_slaves_info(p);
...@@ -406,51 +468,37 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -406,51 +468,37 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
} }
#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ #endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */
static u8 sis5513_ratemask (ide_drive_t *drive)
byte sis_proc = 0;
static byte sis5513_ratemask (ide_drive_t *drive)
{ {
// struct pci_dev *dev = HWIF(drive)->pci_dev; #if 0
byte mode = 0x00; u8 rates[] = { 0, 0, 1, 2, 3, 3, 4, 4 };
u8 mode = rates[chipset_family];
#else
u8 mode;
switch(chipset_family) { switch(chipset_family) {
case ATA_133: // { mode |= 0x04; break; } case ATA_133:
case ATA_133a:
mode = 4;
break;
case ATA_100: case ATA_100:
case ATA_100a: { mode |= 0x03; break; } case ATA_100a:
case ATA_66: { mode |= 0x02; break; } mode = 3;
case ATA_33: { mode |= 0x01; break; } break;
case ATA_66:
mode = 2;
break;
case ATA_33:
return 1;
case ATA_16: case ATA_16:
case ATA_00: case ATA_00:
default: default:
return (mode &= ~0xF8); return 0;
}
if (!eighty_ninty_three(drive)) {
mode &= ~0xFE;
mode |= 0x01;
}
return (mode &= ~0xF8);
}
static byte sis5513_ratefilter (ide_drive_t *drive, byte speed)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
byte mode = sis5513_ratemask(drive);
switch(mode) {
case 0x04: while (speed > XFER_UDMA_6) speed--; break;
case 0x03: while (speed > XFER_UDMA_5) speed--; break;
case 0x02: while (speed > XFER_UDMA_4) speed--; break;
case 0x01: while (speed > XFER_UDMA_2) speed--; break;
case 0x00:
default: while (speed > XFER_MW_DMA_2) speed--; break;
break;
} }
#else #endif
while (speed > XFER_PIO_4) speed--; if (!eighty_ninty_three(drive))
#endif /* CONFIG_BLK_DEV_IDEDMA */ mode = min(mode, (u8)1);
// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); return mode;
return speed;
} }
/* /*
...@@ -462,8 +510,8 @@ static void config_drive_art_rwp (ide_drive_t *drive) ...@@ -462,8 +510,8 @@ static void config_drive_art_rwp (ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
byte reg4bh = 0; u8 reg4bh = 0;
byte rw_prefetch = (0x11 << drive->dn); u8 rw_prefetch = (0x11 << drive->dn);
#ifdef DEBUG #ifdef DEBUG
printk("SIS5513: config_drive_art_rwp, drive %d\n", drive->dn); printk("SIS5513: config_drive_art_rwp, drive %d\n", drive->dn);
...@@ -483,15 +531,15 @@ static void config_drive_art_rwp (ide_drive_t *drive) ...@@ -483,15 +531,15 @@ static void config_drive_art_rwp (ide_drive_t *drive)
/* Set per-drive active and recovery time */ /* Set per-drive active and recovery time */
static void config_art_rwp_pio (ide_drive_t *drive, byte pio) static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
byte timing, drive_pci, test1, test2; u8 timing, drive_pci, test1, test2;
unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; u16 eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
unsigned short xfer_pio = drive->id->eide_pio_modes; u16 xfer_pio = drive->id->eide_pio_modes;
#ifdef DEBUG #ifdef DEBUG
sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start"); sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start");
...@@ -517,16 +565,21 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio) ...@@ -517,16 +565,21 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
timing = (xfer_pio >= pio) ? xfer_pio : pio; timing = (xfer_pio >= pio) ? xfer_pio : pio;
#ifdef DEBUG #ifdef DEBUG
printk("SIS5513: config_drive_art_rwp_pio, drive %d, pio %d, timing %d\n", printk("SIS5513: config_drive_art_rwp_pio, "
"drive %d, pio %d, timing %d\n",
drive->dn, pio, timing); drive->dn, pio, timing);
#endif #endif
switch(drive->dn) { /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */
case 0: drive_pci = 0x40; break; drive_pci = 0x40;
case 1: drive_pci = 0x42; break; /* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */
case 2: drive_pci = 0x44; break; if (chipset_family >= ATA_133) {
case 3: drive_pci = 0x46; break; u32 reg54h;
default: return; pci_read_config_dword(dev, 0x54, &reg54h);
if (reg54h & 0x40000000) drive_pci = 0x70;
drive_pci += ((drive->dn)*0x4);
} else {
drive_pci += ((drive->dn)*0x2);
} }
/* register layout changed with newer ATA100 chips */ /* register layout changed with newer ATA100 chips */
...@@ -547,7 +600,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio) ...@@ -547,7 +600,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
} }
pci_write_config_byte(dev, drive_pci, test1); pci_write_config_byte(dev, drive_pci, test1);
pci_write_config_byte(dev, drive_pci+1, test2); pci_write_config_byte(dev, drive_pci+1, test2);
} else { } else if (chipset_family < ATA_133) {
switch(timing) { /* active recovery switch(timing) { /* active recovery
v v */ v v */
case 4: test1 = 0x30|0x01; break; case 4: test1 = 0x30|0x01; break;
...@@ -557,6 +610,20 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio) ...@@ -557,6 +610,20 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
default: break; default: break;
} }
pci_write_config_byte(dev, drive_pci, test1); pci_write_config_byte(dev, drive_pci, test1);
} else { /* ATA_133 */
u32 test3;
pci_read_config_dword(dev, drive_pci, &test3);
test3 &= 0xc0c00fff;
if (test3 & 0x08) {
test3 |= (unsigned long)ini_time_value[ATA_133-ATA_00][timing] << 12;
test3 |= (unsigned long)act_time_value[ATA_133-ATA_00][timing] << 16;
test3 |= (unsigned long)rco_time_value[ATA_133-ATA_00][timing] << 24;
} else {
test3 |= (unsigned long)ini_time_value[ATA_100-ATA_00][timing] << 12;
test3 |= (unsigned long)act_time_value[ATA_100-ATA_00][timing] << 16;
test3 |= (unsigned long)rco_time_value[ATA_100-ATA_00][timing] << 24;
}
pci_write_config_dword(dev, drive_pci, test3);
} }
#ifdef DEBUG #ifdef DEBUG
...@@ -564,9 +631,13 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio) ...@@ -564,9 +631,13 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
#endif #endif
} }
static int config_chipset_for_pio (ide_drive_t *drive, byte pio) static int config_chipset_for_pio (ide_drive_t *drive, u8 pio)
{ {
byte speed; #if 0
config_art_rwp_pio(drive, pio);
return ide_config_drive_speed(drive, (XFER_PIO_0 + pio));
#else
u8 speed;
switch(pio) { switch(pio) {
case 4: speed = XFER_PIO_4; break; case 4: speed = XFER_PIO_4; break;
...@@ -577,58 +648,83 @@ static int config_chipset_for_pio (ide_drive_t *drive, byte pio) ...@@ -577,58 +648,83 @@ static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
} }
config_art_rwp_pio(drive, pio); config_art_rwp_pio(drive, pio);
return (ide_config_drive_speed(drive, speed)); return ide_config_drive_speed(drive, speed);
#endif
} }
static int sis5513_tune_chipset (ide_drive_t *drive, byte xferspeed) static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
byte speed = sis5513_ratefilter(drive, xferspeed);
byte drive_pci, reg; u8 drive_pci, reg;
u32 regdw;
#ifdef DEBUG #ifdef DEBUG
sis5513_load_verify_registers(dev, "sis5513_tune_chipset start"); sis5513_load_verify_registers(dev, "sis5513_tune_chipset start");
printk("SIS5513: sis5513_tune_chipset, drive %d, speed %d\n", printk("SIS5513: sis5513_tune_chipset, drive %d, speed %d\n",
drive->dn, speed); drive->dn, speed);
#endif #endif
#if 1
switch(drive->dn) {
case 0: drive_pci = 0x40; break;
case 1: drive_pci = 0x42; break;
case 2: drive_pci = 0x44; break;
case 3: drive_pci = 0x46; break;
default: return ide_dma_off;
}
#else
// drive_pci = (0x40 + ((drive->dn) *2));
// drive_pci = 0x40;
// drive_pci |= ((drive->dn) << 1);
#endif
#ifdef BROKEN_LEVEL #ifdef BROKEN_LEVEL
#ifdef DEBUG #ifdef DEBUG
printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", speed, BROKEN_LEVEL); printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", xferspeed, BROKEN_LEVEL);
#endif #endif
if (speed > BROKEN_LEVEL) speed = BROKEN_LEVEL; if (xferspeed > BROKEN_LEVEL) xferspeed = BROKEN_LEVEL;
#endif #endif
u8 speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed);
/* See config_art_rwp_pio for drive pci config registers */
drive_pci = 0x40;
if (chipset_family >= ATA_133) {
u32 reg54h;
pci_read_config_dword(dev, 0x54, &reg54h);
if (reg54h & 0x40000000) drive_pci = 0x70;
drive_pci += ((drive->dn)*0x4);
pci_read_config_dword(dev, (unsigned long)drive_pci, &regdw);
/* Disable UDMA bit for non UDMA modes on UDMA chips */
if (speed < XFER_UDMA_0) {
regdw &= 0xfffffffb;
pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
}
} else {
drive_pci += ((drive->dn)*0x2);
pci_read_config_byte(dev, drive_pci+1, &reg); pci_read_config_byte(dev, drive_pci+1, &reg);
/* Disable UDMA bit for non UDMA modes on UDMA chips */ /* Disable UDMA bit for non UDMA modes on UDMA chips */
if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
reg &= 0x7F; reg &= 0x7F;
pci_write_config_byte(dev, drive_pci+1, reg); pci_write_config_byte(dev, drive_pci+1, reg);
} }
}
/* Config chip for mode */ /* Config chip for mode */
switch(speed) { switch(speed) {
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
case XFER_UDMA_6:
case XFER_UDMA_5: case XFER_UDMA_5:
case XFER_UDMA_4: case XFER_UDMA_4:
case XFER_UDMA_3: case XFER_UDMA_3:
case XFER_UDMA_2: case XFER_UDMA_2:
case XFER_UDMA_1: case XFER_UDMA_1:
case XFER_UDMA_0: case XFER_UDMA_0:
if (chipset_family >= ATA_133) {
regdw |= 0x04;
regdw &= 0xfffff00f;
/* check if ATA133 enable */
if (regdw & 0x08) {
regdw |= (unsigned long)cycle_time_value[ATA_133-ATA_00][speed-XFER_UDMA_0] << 4;
regdw |= (unsigned long)cvs_time_value[ATA_133-ATA_00][speed-XFER_UDMA_0] << 8;
} else {
/* if ATA133 disable, we should not set speed above UDMA5 */
if (speed > XFER_UDMA_5)
speed = XFER_UDMA_5;
regdw |= (unsigned long)cycle_time_value[ATA_100-ATA_00][speed-XFER_UDMA_0] << 4;
regdw |= (unsigned long)cvs_time_value[ATA_100-ATA_00][speed-XFER_UDMA_0] << 8;
}
pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
} else {
/* Force the UDMA bit on if we want to use UDMA */ /* Force the UDMA bit on if we want to use UDMA */
reg |= 0x80; reg |= 0x80;
/* clean reg cycle time bits */ /* clean reg cycle time bits */
...@@ -638,6 +734,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -638,6 +734,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte xferspeed)
reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0] reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0]
<< cycle_time_offset[chipset_family]; << cycle_time_offset[chipset_family];
pci_write_config_byte(dev, drive_pci+1, reg); pci_write_config_byte(dev, drive_pci+1, reg);
}
break; break;
case XFER_MW_DMA_2: case XFER_MW_DMA_2:
case XFER_MW_DMA_1: case XFER_MW_DMA_1:
...@@ -660,7 +757,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -660,7 +757,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, byte xferspeed)
return ((int) ide_config_drive_speed(drive, speed)); return ((int) ide_config_drive_speed(drive, speed));
} }
static void sis5513_tune_drive (ide_drive_t *drive, byte pio) static void sis5513_tune_drive (ide_drive_t *drive, u8 pio)
{ {
(void) config_chipset_for_pio(drive, pio); (void) config_chipset_for_pio(drive, pio);
} }
...@@ -671,127 +768,75 @@ static void sis5513_tune_drive (ide_drive_t *drive, byte pio) ...@@ -671,127 +768,75 @@ static void sis5513_tune_drive (ide_drive_t *drive, byte pio)
*/ */
static int config_chipset_for_dma (ide_drive_t *drive) static int config_chipset_for_dma (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; u8 speed = ide_dma_speed(drive, sis5513_ratemask(drive));
byte mode = sis5513_ratemask(drive);
byte speed = 0;
#ifdef DEBUG #ifdef DEBUG
printk("SIS5513: config_chipset_for_dma, drive %d ultra %d\n", printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x, udma_66 %x\n",
drive->dn, mode); drive->dn, drive->id->dma_ultra);
#endif #endif
switch(mode) { if (!(speed))
case 0x04: return 0;
if (id->dma_ultra & 0x0040)
{ speed = XFER_UDMA_6; break; }
case 0x03:
if (id->dma_ultra & 0x0020)
{ speed = XFER_UDMA_5; break; }
case 0x02:
if (id->dma_ultra & 0x0010)
{ speed = XFER_UDMA_4; break; }
if (id->dma_ultra & 0x0008)
{ speed = XFER_UDMA_3; break; }
case 0x01:
if (id->dma_ultra & 0x0004)
{ speed = XFER_UDMA_2; break; }
if (id->dma_ultra & 0x0002)
{ speed = XFER_UDMA_1; break; }
if (id->dma_ultra & 0x0001)
{ speed = XFER_UDMA_0; break; }
case 0x00:
if (id->dma_mword & 0x0004)
{ speed = XFER_MW_DMA_2; break; }
if (id->dma_mword & 0x0002)
{ speed = XFER_MW_DMA_1; break; }
if (id->dma_mword & 0x0001)
{ speed = XFER_MW_DMA_0; break; }
if (id->dma_1word & 0x0004)
{ speed = XFER_SW_DMA_2; break; }
if (id->dma_1word & 0x0002)
{ speed = XFER_SW_DMA_1; break; }
if (id->dma_1word & 0x0001)
{ speed = XFER_SW_DMA_0; break; }
default:
return ((int) ide_dma_off_quietly);
}
sis5513_tune_chipset(drive, speed); sis5513_tune_chipset(drive, speed);
// return ((int) ide_dma_on); return ide_dma_enable(drive);
return ((int) ((id->dma_ultra >> 14) & 3) ? ide_dma_on :
((id->dma_ultra >> 11) & 7) ? ide_dma_on :
((id->dma_ultra >> 8) & 7) ? ide_dma_on :
((id->dma_mword >> 8) & 7) ? ide_dma_on :
((id->dma_1word >> 8) & 7) ? ide_dma_on :
ide_dma_off_quietly);
} }
static int config_drive_xfer_rate (ide_drive_t *drive) static int sis5513_config_drive_xfer_rate (ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
ide_dma_action_t dma_func = ide_dma_off_quietly;
drive->init_speed = 0; drive->init_speed = 0;
if (id && (id->capability & 1) && HWIF(drive)->autodma) { if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive)) { if (hwif->ide_dma_bad_drive(drive))
dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
}
dma_func = ide_dma_off_quietly;
if (id->field_valid & 4) { if (id->field_valid & 4) {
if (id->dma_ultra & 0x003F) { if (id->dma_ultra & hwif->ultra_mask) {
/* Force if Capable UltraDMA */ /* Force if Capable UltraDMA */
dma_func = config_chipset_for_dma(drive); int dma = config_chipset_for_dma(drive);
if ((id->field_valid & 2) && if ((id->field_valid & 2) && !dma)
(dma_func != ide_dma_on))
goto try_dma_modes; goto try_dma_modes;
} }
} else if (id->field_valid & 2) { } else if (id->field_valid & 2) {
try_dma_modes: try_dma_modes:
if ((id->dma_mword & 0x0007) || if ((id->dma_mword & hwif->mwdma_mask) ||
(id->dma_1word & 0x0007)) { (id->dma_1word & hwif->swdma_mask)) {
/* Force if Capable regular DMA modes */ /* Force if Capable regular DMA modes */
dma_func = config_chipset_for_dma(drive); if (!config_chipset_for_dma(drive))
if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if ((ide_dmaproc(ide_dma_good_drive, drive)) && } else if (hwif->ide_dma_good_drive(drive) &&
(id->eide_dma_time > 150)) { (id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */ /* Consult the list of known "good" drives */
dma_func = config_chipset_for_dma(drive); if (!config_chipset_for_dma(drive))
if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} else { } else {
goto fast_ata_pio; goto fast_ata_pio;
} }
} else if ((id->capability & 8) || (id->field_valid & 2)) { } else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio: fast_ata_pio:
dma_func = ide_dma_off_quietly;
no_dma_set: no_dma_set:
sis5513_tune_drive(drive, 5); sis5513_tune_drive(drive, 5);
return hwif->ide_dma_off_quietly(drive);
} }
return hwif->ide_dma_on(drive);
return HWIF(drive)->dmaproc(dma_func, drive);
} }
/* initiates/aborts (U)DMA read/write operations on a drive. */ /* initiates/aborts (U)DMA read/write operations on a drive. */
int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) static int sis5513_config_xfer_rate (ide_drive_t *drive)
{ {
switch (func) {
case ide_dma_check:
config_drive_art_rwp(drive); config_drive_art_rwp(drive);
config_art_rwp_pio(drive, 5); config_art_rwp_pio(drive, 5);
return config_drive_xfer_rate(drive); return sis5513_config_drive_xfer_rate(drive);
default:
break;
}
return ide_dmaproc(func, drive); /* use standard DMA stuff */
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
/* Chip detection and general config */ /* Chip detection and general config */
unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name)
{ {
struct pci_dev *host; struct pci_dev *host;
int i = 0; int i = 0;
...@@ -806,7 +851,37 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) ...@@ -806,7 +851,37 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
host_dev = host; host_dev = host;
chipset_family = SiSHostChipInfo[i].chipset_family; chipset_family = SiSHostChipInfo[i].chipset_family;
/* check 100/133 chipset family */
if (chipset_family == ATA_133) {
u32 reg54h;
u16 reg02h;
pci_read_config_dword(dev, 0x54, &reg54h);
pci_write_config_dword(dev, 0x54, (reg54h & 0x7fffffff));
pci_read_config_word(dev, 0x02, &reg02h);
pci_write_config_dword(dev, 0x54, reg54h);
/* devid 5518 here means SiS962 or later
which supports ATA133 */
if (reg02h != 0x5518) {
u8 reg49h;
unsigned long sbrev;
/* SiS961 family */
/*
* FIXME !!! GAK!!!!!!!!!! PCI DIRECT POKING
*/
outl(0x80001008, 0x0cf8);
sbrev = inl(0x0cfc);
pci_read_config_byte(dev, 0x49, &reg49h);
if (((sbrev & 0xff) == 0x10) && (reg49h & 0x80))
chipset_family = ATA_133a;
else
chipset_family = ATA_100;
}
}
printk(SiSHostChipInfo[i].name); printk(SiSHostChipInfo[i].name);
printk(" %s controller", chipset_capability[chipset_family]);
printk("\n"); printk("\n");
#ifdef DEBUG #ifdef DEBUG
...@@ -814,7 +889,7 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) ...@@ -814,7 +889,7 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
#endif #endif
if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ u8 latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
} }
} }
...@@ -823,9 +898,19 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) ...@@ -823,9 +898,19 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
1/ tell IDE channels to operate in Compabitility mode only 1/ tell IDE channels to operate in Compabitility mode only
2/ tell old chips to allow per drive IDE timings */ 2/ tell old chips to allow per drive IDE timings */
if (host_dev) { if (host_dev) {
byte reg; u8 reg;
u16 regw;
switch(chipset_family) { switch(chipset_family) {
case ATA_133: case ATA_133:
/* SiS962 operation mode */
pci_read_config_word(dev, 0x50, &regw);
if (regw & 0x08)
pci_write_config_word(dev, 0x50, regw&0xfff7);
pci_read_config_word(dev, 0x52, &regw);
if (regw & 0x08)
pci_write_config_word(dev, 0x52, regw&0xfff7);
break;
case ATA_133a:
case ATA_100: case ATA_100:
/* Set compatibility bit */ /* Set compatibility bit */
pci_read_config_byte(dev, 0x49, &reg); pci_read_config_byte(dev, 0x49, &reg);
...@@ -863,7 +948,7 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) ...@@ -863,7 +948,7 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
if (!sis_proc) { if (!sis_proc) {
sis_proc = 1; sis_proc = 1;
bmide_dev = dev; bmide_dev = dev;
sis_display_info = &sis_get_info; ide_pci_register_host_proc(&sis_procs[0]);
} }
#endif #endif
} }
...@@ -873,55 +958,90 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) ...@@ -873,55 +958,90 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
return 0; return 0;
} }
unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) static unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
{ {
byte reg48h = 0, ata66 = 0; u8 ata66 = 0;
byte mask = hwif->channel ? 0x20 : 0x10;
if (chipset_family >= ATA_133) {
u16 regw = 0;
u16 reg_addr = hwif->channel ? 0x52: 0x50;
pci_read_config_word(hwif->pci_dev, reg_addr, &regw);
ata66 = (regw & 0x8000) ? 0 : 1;
} else if (chipset_family >= ATA_66) {
u8 reg48h = 0;
u8 mask = hwif->channel ? 0x20 : 0x10;
pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h); pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
if (chipset_family >= ATA_66) {
ata66 = (reg48h & mask) ? 0 : 1; ata66 = (reg48h & mask) ? 0 : 1;
} }
return ata66; return ata66;
} }
void __init ide_init_sis5513 (ide_hwif_t *hwif) static void __init init_hwif_sis5513 (ide_hwif_t *hwif)
{ {
hwif->autodma = 0;
if (!hwif->irq)
hwif->irq = hwif->channel ? 15 : 14; hwif->irq = hwif->channel ? 15 : 14;
hwif->tuneproc = &sis5513_tune_drive; hwif->tuneproc = &sis5513_tune_drive;
hwif->speedproc = &sis5513_tune_chipset; hwif->speedproc = &sis5513_tune_chipset;
if (!(hwif->dma_base)) {
hwif->drives[0].autotune = 1; hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1; hwif->drives[1].autotune = 1;
hwif->autodma = 0;
if (!(hwif->dma_base))
return; return;
}
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x7f;
hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (host_dev) { if (!host_dev)
if (chipset_family > ATA_16) return;
hwif->dmaproc = &sis5513_dmaproc;
else if (!(hwif->udma_four))
hwif->autodma = 0; hwif->udma_four = ata66_sis5513(hwif);
}
# ifdef CONFIG_IDEDMA_AUTO if (chipset_family > ATA_16) {
hwif->ide_dma_check = &sis5513_config_xfer_rate;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
# endif /* CONFIG_IDEDMA_AUTO */ }
#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
#endif
return; return;
} }
extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); static void __init init_dma_sis5513 (ide_hwif_t *hwif, unsigned long dmabase)
void __init fixup_device_sis5513 (struct pci_dev *dev, ide_pci_device_t *d)
{ {
if (dev->resource[0].start != 0x01F1) ide_setup_dma(hwif, dmabase, 8);
ide_register_xp_fix(dev); }
printk("%s: IDE controller on PCI bus %02x dev %02x\n", extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
d->name, dev->bus->number, dev->devfn);
static void __init init_setup_sis5513 (struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d); ide_setup_pci_device(dev, d);
} }
int __init sis5513_scan_pcidev (struct pci_dev *dev)
{
ide_pci_device_t *d;
if (dev->vendor != PCI_VENDOR_ID_SI)
return 0;
for (d = sis5513_chipsets; d && d->vendor && d->device; ++d) {
if (((d->vendor == dev->vendor) &&
(d->device == dev->device)) &&
(d->init_setup)) {
d->init_setup(dev, d);
return 1;
}
}
return 0;
}
#ifndef SIS5513_H
#define SIS5513_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_SIS_TIMINGS
#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static u8 sis_proc;
static int sis_get_info(char *, char **, off_t, int);
static ide_pci_host_proc_t sis_procs[] __initdata = {
{
name: "sis",
set: 1,
get_info: sis_get_info,
parent: NULL,
},
};
#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */
static void init_setup_sis5513(struct pci_dev *, ide_pci_device_t *);
static unsigned int init_chipset_sis5513(struct pci_dev *, const char *);
static void init_hwif_sis5513(ide_hwif_t *);
static void init_dma_sis5513(ide_hwif_t *, unsigned long);
static ide_pci_device_t sis5513_chipsets[] __initdata = {
{
vendor: PCI_VENDOR_ID_SI,
device: PCI_DEVICE_ID_SI_5513,
name: "SIS5513",
init_setup: init_setup_sis5513,
init_chipset: init_chipset_sis5513,
init_iops: NULL,
init_hwif: init_hwif_sis5513,
init_dma: init_dma_sis5513,
channels: 2,
autodma: NOAUTODMA,
enablebits: {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
bootable: ON_BOARD,
extra: 0
},{
vendor: 0,
device: 0,
channels: 0,
bootable: EOL,
}
};
#endif /* SIS5513_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment