SIS5513 ATA100 support
RFC 1/1 SIS5513 ATA100 support
Daniela,
here's my first patch to sis5513.c : this should set the correct timings for ATA100 chips (and hopefully say goodbye to heavy fs corruption in UDMA modes).
It compiles cleanly but is **not yet tested**. I'm currently waiting for ~30GB to move from my test drive to a safe location (gory details: source DMA drive, destination PIO drive, accross NFS on a 100kKiB :-P full-duplex Ethernet).
If there's an obvious mistake please tell me (I've a couple of hours to wait for the transfer before testing with and without the patch on a "blank" ATA-100 drive).
If others want to have a look or even (I repeat **not yet tested**) try this code **on backuped data** they're more than welcome.
If you want to have a quick look at the whole new sis5513.c :
http://gyver.homeip.net/sis5513.c
I'm now on to a more general sis5513.c cleanup :
1/ There is some suspicious code (sis_get_info seems broken to me from ATA66 on and config_art_rwp_pio is not yet ATA100-chip friendly) 2/ I'll probably move to per chip types funcs as the current generic ones become uglier and uglier at each new sis chipset).
LB
drivers/ide/sis5513.c +41 -11
@@ -32,11 +32,13 @@#define SIS5513_DEBUG_DRIVE_INFO 0static struct pci_dev *host_dev =NULL ; +static unsigned int capabilities =0 ;#define SIS5513_FLAG_ATA_00 0x00000000#define SIS5513_FLAG_ATA_16 0x00000001#define SIS5513_FLAG_ATA_33 0x00000002#define SIS5513_FLAG_ATA_66 0x00000004 +#define SIS5513_FLAG_ATA_100 0x00000008#define SIS5513_FLAG_LATENCY 0x00000010 static const struct {
@@ -48,15 +50,15 @@ { "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, }, { "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, { "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS635", PCI_DEVICE_ID_SI_635, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS635", PCI_DEVICE_ID_SI_635, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, { "SiS640", PCI_DEVICE_ID_SI_640, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS645", PCI_DEVICE_ID_SI_645, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS650", PCI_DEVICE_ID_SI_650, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS735", PCI_DEVICE_ID_SI_735, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS740", PCI_DEVICE_ID_SI_740, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS745", PCI_DEVICE_ID_SI_745, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS750", PCI_DEVICE_ID_SI_750, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS645", PCI_DEVICE_ID_SI_645, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS650", PCI_DEVICE_ID_SI_650, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS735", PCI_DEVICE_ID_SI_735, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS740", PCI_DEVICE_ID_SI_740, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS745", PCI_DEVICE_ID_SI_745, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS750", PCI_DEVICE_ID_SI_750, SIS5513_FLAG_ATA_100|SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, { "SiS5591", PCI_DEVICE_ID_SI_5591, SIS5513_FLAG_ATA_33, }, { "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, }, { "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, },
@@ -229,6 +231,7 @@byte sis_proc =0 ;extern char *ide_xfer_verbose (byte xfer_rate); +/* Enables Prefetch and Postwrite on drive */ static void config_drive_art_rwp (ide_drive_t *drive) {ide_hwif_t *hwif =HWIF (drive);
@@ -298,8 +301,8 @@* Do a blanket clear of active and recovery timings. */ - test1 &= ~0x07 ; - test2 &= ~0x0F ; + test1 &= ~0x0F ; + test2 &= ~0x07 ;switch (timing) {case 4 : test1 |=0x01 ; test2 |=0x03 ;break ;
@@ -379,6 +382,7 @@pci_read_config_byte (dev, drive_pci, &test1);pci_read_config_byte (dev, drive_pci|0x01 , &test2); +/* If not an UDMA mode switch off udma bit */ if ((speed <=XFER_MW_DMA_2 ) && (test2 &0x80 )) {pci_write_config_byte (dev, drive_pci|0x01 , test2 & ~0x80 );pci_read_config_byte (dev, drive_pci|0x01 , &test2);
@@ -386,7 +390,31 @@pci_write_config_byte (dev, drive_pci|0x01 , test2 & ~unmask); } -switch (speed) { +if (capabilities &SIS5513_FLAG_ATA_100 ) { +switch (speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA +case XFER_UDMA_5 : mask =0x01 ;break ; +case XFER_UDMA_4 : mask =0x02 ;break ; +case XFER_UDMA_3 : mask =0x04 ;break ; +case XFER_UDMA_2 : mask =0x05 ;break ; +case XFER_UDMA_1 : mask =0x07 ;break ; +case XFER_UDMA_0 : mask =0x0B ;break ; +case XFER_MW_DMA_2 : +case XFER_MW_DMA_1 : +case XFER_MW_DMA_0 : +case XFER_SW_DMA_2 : +case XFER_SW_DMA_1 : +case XFER_SW_DMA_0 :break ; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +case XFER_PIO_4 :return ((int )config_chipset_for_pio (drive,4 )); +case XFER_PIO_3 :return ((int )config_chipset_for_pio (drive,3 )); +case XFER_PIO_2 :return ((int )config_chipset_for_pio (drive,2 )); +case XFER_PIO_1 :return ((int )config_chipset_for_pio (drive,1 )); +case XFER_PIO_0 : +default :return ((int )config_chipset_for_pio (drive,0 )); + } + }else { +switch (speed) {#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_5 : mask =0x80 ;break ;case XFER_UDMA_4 : mask =0x90 ;break ;
@@ -407,6 +435,7 @@case XFER_PIO_1 :return ((int )config_chipset_for_pio (drive,1 ));case XFER_PIO_0 :default :return ((int )config_chipset_for_pio (drive,0 )); + } }if (speed >XFER_MW_DMA_2 )
@@ -583,6 +612,7 @@continue ; host_dev = host; + capabilities = SiSHostChipInfo[i].flags;printk (SiSHostChipInfo[i].name);printk ("\n" );if (SiSHostChipInfo[i].flags &SIS5513_FLAG_LATENCY ) {
Quoted 4 lines · Lionel Bouton
here's my first patch to
sis5513.c: this should set the correct timings for ATA100 chips (and hopefully say goodbye to heavy fs corruption in UDMA modes).
Problem not yet solved. I'm back to the drawing board but now I have a "reliable" way of triggering the problem.
Quoted 5 lines
It compiles cleanly but is **not yet tested**.
If there's an obvious mistake please tell me
Don't know yet if it's obvious, but there's one.
Quoted 3 lines
If others want to have a look or even (I repeat **not yet tested**) try this code **on backuped data** they're more than welcome.
Having a look at the code is always welcome. But don't waste your time and data testing...
Quoted 5 lines
If you want to have a quick look at the whole new
sis5513.c:
LB
Hello,
I'm back with new code.
This one doesn't work on my sis735 either :-( but after having triple-checked my code I don't see why :-((. Time to show the code to others...
If someone familiar with pci-ide code could just take a quick look...
The goal is only working ata-100 inits. There's code in sis5513.c that could use a little cleanup but I'll wait working ata-100 inits to work on that.
You have an edited (commented) diff from original sis5513.c and the real patch attached.
A complete new sis5513.c is available for more conveniance at :
http://gyver.homeip.net/sis5513.c
LB.
Reads better with attachements.
Hello,
I'm back with new code.
This one doesn't work on my sis735 either :-( but after having triple-checked my code I don't see why :-((. Time to show the code to others...
If someone familiar with pci-ide code could just take a quick look...
The goal is only working ata-100 inits. There's code in sis5513.c that could use a little cleanup but I'll wait working ata-100 inits to work on that.
You have an edited (commented) diff from original sis5513.c and the real patch attached.
A complete new sis5513.c is available for more conveniance at :
http://gyver.homeip.net/sis5513.c
LB.
+++ Add a Flag for chips supporting ata-100 +++
#define SIS5513_FLAG_ATA_16 0x00000001
#define SIS5513_FLAG_ATA_33 0x00000002
#define SIS5513_FLAG_ATA_66 0x00000004
+#define SIS5513_FLAG_ATA_100 0x00000008
#define SIS5513_FLAG_LATENCY 0x00000010
+++ Holds the flags of the detected chip +++
+static unsigned int capabilities = 0x00000000;
+
+++ Changed flags in order to reflect capabilities +++ ??? Are there some chips supporting ata-100 I missed ???
static const struct {
const char *name;
unsigned short host_id;
{ "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, },
{ "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
{ "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS635", PCI_DEVICE_ID_SI_635, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
+ { "SiS635", PCI_DEVICE_ID_SI_635, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
{ "SiS640", PCI_DEVICE_ID_SI_640, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS645", PCI_DEVICE_ID_SI_645, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS650", PCI_DEVICE_ID_SI_650, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS735", PCI_DEVICE_ID_SI_735, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS740", PCI_DEVICE_ID_SI_740, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS745", PCI_DEVICE_ID_SI_745, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
- { "SiS750", PCI_DEVICE_ID_SI_750, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, },
+ { "SiS645", PCI_DEVICE_ID_SI_645, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
+ { "SiS650", PCI_DEVICE_ID_SI_650, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
+ { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
+ { "SiS735", PCI_DEVICE_ID_SI_735, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
+ { "SiS740", PCI_DEVICE_ID_SI_740, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
+ { "SiS745", PCI_DEVICE_ID_SI_745, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, },
+ { "SiS750", PCI_DEVICE_ID_SI_750, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, { "SiS5591", PCI_DEVICE_ID_SI_5591, SIS5513_FLAG_ATA_33, },
{ "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, },
{ "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, },
+++ PIO timing register layout is different for ata-100 use the new one +++
+ if (capabilities && SIS5513_FLAG_ATA_100) {
+ switch(timing) { /* active recovery
+ v v */
+ case 4: test1 = 0x30|0x01; break; + case 3: test1 = 0x30|0x03; break; + case 2: test1 = 0x40|0x04; break; + case 1: test1 = 0x60|0x07; break;
+ default: break;
+ }
+ pci_write_config_byte(dev, drive_pci, test1);
+ return; /* temporary hack for tests */
+ }
+
pci_read_config_byte(dev, drive_pci, &test1); pci_read_config_byte(dev, drive_pci|0x01, &test2);
+++ The masks below were wrong from the beginning +++
* Do a blanket clear of active and recovery timings. */
- test1 &= ~0x07;
- test2 &= ~0x0F;
+ test1 &= ~0x0F;
+ test2 &= ~0x07;
+++ UDMA mode timing are set on a different base (10ns instead of 1/2 PCI_CLOCK) +++ +++ and the register layout is different too +++
- switch(speed) {
+ if (capabilities & SIS5513_FLAG_ATA_100) {
+ switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ case XFER_UDMA_5: mask = 0x01; break;
+ case XFER_UDMA_4: mask = 0x02; break;
+ case XFER_UDMA_3: mask = 0x04; break;
+ case XFER_UDMA_2: mask = 0x05; break;
+ case XFER_UDMA_1: mask = 0x07; break;
+ case XFER_UDMA_0: mask = 0x0B; break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_MW_DMA_0:
+ case XFER_SW_DMA_2:
+ case XFER_SW_DMA_1:
+ case XFER_SW_DMA_0: break;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4));
+ case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3));
+ case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2));
+ case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1));
+ case XFER_PIO_0:
+ default: return((int) config_chipset_for_pio(drive, 0));
+ }
+ } else {
+ switch(speed) {
#ifdef CONFIG_BLK_DEV_IDEDMA
case XFER_UDMA_5: mask = 0x80; break;
case XFER_UDMA_4: mask = 0x90; break;
@@ -407,10 +450,16 @@
case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1)); case XFER_PIO_0:
default: return((int) config_chipset_for_pio(drive, 0));
+ }
}
+++ Adapt the code to the register layout : 0x80 for UDMA enable +++ +++ doesn't have to use a pci_read_config before as we set the whole register +++
- if (speed > XFER_MW_DMA_2)
- pci_write_config_byte(dev, drive_pci|0x01, test2|mask);
+ if (speed > XFER_MW_DMA_2) {
+ if (capabilities & SIS5513_FLAG_ATA_100) {
+ pci_write_config_byte(dev, drive_pci|0x01, 0x80|mask);
+ } else {
+ pci_write_config_byte(dev, drive_pci|0x01, test2|mask);
+ }
+ }
drive->current_speed = speed;
return ((int) ide_config_drive_speed(drive, speed));
@@ -583,6 +632,7 @@
continue;
+++ Here (pci_init_sis5513) we store the capabilities flags +++ +++ used everywhere else to activate ata-100 specific code +++
host_dev = host;
+ capabilities = SiSHostChipInfo[i].flags;
printk(SiSHostChipInfo[i].name); printk("\n");
if (SiSHostChipInfo[i].flags & SIS5513_FLAG_LATENCY) {
@@ -592,12 +642,22 @@
}
+++ The Compatibility mode bit changed from reg52h bit 2 to reg49h bit 0 +++
if (host_dev) {
- byte reg52h = 0;
+ if (capabilities & SIS5513_FLAG_ATA_100) {
+ byte reg49h = 0;
- pci_read_config_byte(dev, 0x52, ®52h);
- if (!(reg52h & 0x04)) {
- /* set IDE controller to operate in Compabitility mode only */
- pci_write_config_byte(dev, 0x52, reg52h|0x04);
+ pci_read_config_byte(dev, 0x49, ®49h);
+ if (!(reg49h & 0x01)) {
+ /* set IDE controller to operate in Compabitility mode only */
+ pci_write_config_byte(dev, 0x49, reg49h|0x01);
+ }
+ } else {
+ byte reg52h = 0;
+
+ pci_read_config_byte(dev, 0x52, ®52h);
+ if (!(reg52h & 0x04)) {
+ /* set IDE controller to operate in Compabitility mode only */
+ pci_write_config_byte(dev, 0x52, reg52h|0x04);
+ }
}
#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS)
if (!sis_proc) {
sis5513.c renamed from usr/src/linux/drivers/ide/sis5513.c +78 -18
@@ -37,8 +37,11 @@#define SIS5513_FLAG_ATA_16 0x00000001#define SIS5513_FLAG_ATA_33 0x00000002#define SIS5513_FLAG_ATA_66 0x00000004 +#define SIS5513_FLAG_ATA_100 0x00000008#define SIS5513_FLAG_LATENCY 0x00000010 +static unsigned int capabilities =0x00000000 ; + static const struct { const char *name; unsigned short host_id;
@@ -48,15 +51,15 @@ { "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, }, { "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, { "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS635", PCI_DEVICE_ID_SI_635, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS635", PCI_DEVICE_ID_SI_635, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, { "SiS640", PCI_DEVICE_ID_SI_640, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS645", PCI_DEVICE_ID_SI_645, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS650", PCI_DEVICE_ID_SI_650, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS735", PCI_DEVICE_ID_SI_735, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS740", PCI_DEVICE_ID_SI_740, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS745", PCI_DEVICE_ID_SI_745, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, - { "SiS750", PCI_DEVICE_ID_SI_750, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS645", PCI_DEVICE_ID_SI_645, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, + { "SiS650", PCI_DEVICE_ID_SI_650, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, + { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, + { "SiS735", PCI_DEVICE_ID_SI_735, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, + { "SiS740", PCI_DEVICE_ID_SI_740, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, + { "SiS745", PCI_DEVICE_ID_SI_745, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, + { "SiS750", PCI_DEVICE_ID_SI_750, SIS5513_FLAG_ATA_100|SIS5513_FLAG_LATENCY, }, { "SiS5591", PCI_DEVICE_ID_SI_5591, SIS5513_FLAG_ATA_33, }, { "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, }, { "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, },
@@ -229,6 +232,7 @@byte sis_proc =0 ;extern char *ide_xfer_verbose (byte xfer_rate); +/* Enables Prefetch and Postwrite on drive */ static void config_drive_art_rwp (ide_drive_t *drive) {ide_hwif_t *hwif =HWIF (drive);
@@ -245,6 +249,7 @@pci_write_config_byte (dev,0x4b , reg4bh|rw_prefetch); } +/* Set active and recovery time */ static void config_art_rwp_pio (ide_drive_t *drive,byte pio) {ide_hwif_t *hwif =HWIF (drive);
@@ -291,6 +296,19 @@default :return ; } +if (capabilities &&SIS5513_FLAG_ATA_100 ) { +switch (timing) {/* active recovery +v v */ +case 4 : test1 =0x30 |0x01 ;break ; +case 3 : test1 =0x30 |0x03 ;break ; +case 2 : test1 =0x40 |0x04 ;break ; +case 1 : test1 =0x60 |0x07 ;break ; +default :break ; + } +pci_write_config_byte (dev, drive_pci, test1); +return ;/* temporary hack for tests */ + } +pci_read_config_byte (dev, drive_pci, &test1);pci_read_config_byte (dev, drive_pci|0x01 , &test2);
@@ -298,8 +316,8 @@* Do a blanket clear of active and recovery timings. */ - test1 &= ~0x07 ; - test2 &= ~0x0F ; + test1 &= ~0x0F ; + test2 &= ~0x07 ;switch (timing) {case 4 : test1 |=0x01 ; test2 |=0x03 ;break ;
@@ -379,6 +397,7 @@pci_read_config_byte (dev, drive_pci, &test1);pci_read_config_byte (dev, drive_pci|0x01 , &test2); +/* If not an UDMA mode switch off udma bit */ if ((speed <=XFER_MW_DMA_2 ) && (test2 &0x80 )) {pci_write_config_byte (dev, drive_pci|0x01 , test2 & ~0x80 );pci_read_config_byte (dev, drive_pci|0x01 , &test2);
@@ -386,7 +405,31 @@pci_write_config_byte (dev, drive_pci|0x01 , test2 & ~unmask); } -switch (speed) { +if (capabilities &SIS5513_FLAG_ATA_100 ) { +switch (speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA +case XFER_UDMA_5 : mask =0x01 ;break ; +case XFER_UDMA_4 : mask =0x02 ;break ; +case XFER_UDMA_3 : mask =0x04 ;break ; +case XFER_UDMA_2 : mask =0x05 ;break ; +case XFER_UDMA_1 : mask =0x07 ;break ; +case XFER_UDMA_0 : mask =0x0B ;break ; +case XFER_MW_DMA_2 : +case XFER_MW_DMA_1 : +case XFER_MW_DMA_0 : +case XFER_SW_DMA_2 : +case XFER_SW_DMA_1 : +case XFER_SW_DMA_0 :break ; +#endif /* CONFIG_BLK_DEV_IDEDMA */ +case XFER_PIO_4 :return ((int )config_chipset_for_pio (drive,4 )); +case XFER_PIO_3 :return ((int )config_chipset_for_pio (drive,3 )); +case XFER_PIO_2 :return ((int )config_chipset_for_pio (drive,2 )); +case XFER_PIO_1 :return ((int )config_chipset_for_pio (drive,1 )); +case XFER_PIO_0 : +default :return ((int )config_chipset_for_pio (drive,0 )); + } + }else { +switch (speed) {#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_5 : mask =0x80 ;break ;case XFER_UDMA_4 : mask =0x90 ;break ;
@@ -407,10 +450,16 @@case XFER_PIO_1 :return ((int )config_chipset_for_pio (drive,1 ));case XFER_PIO_0 :default :return ((int )config_chipset_for_pio (drive,0 )); + } } -if (speed >XFER_MW_DMA_2 ) -pci_write_config_byte (dev, drive_pci|0x01 , test2|mask); +if (speed >XFER_MW_DMA_2 ) { +if (capabilities &SIS5513_FLAG_ATA_100 ) { +pci_write_config_byte (dev, drive_pci|0x01 ,0x80 |mask); + }else { +pci_write_config_byte (dev, drive_pci|0x01 , test2|mask); + } + } drive->current_speed = speed;return ((int )ide_config_drive_speed (drive, speed));
@@ -583,6 +632,7 @@continue ; host_dev = host; + capabilities = SiSHostChipInfo[i].flags;printk (SiSHostChipInfo[i].name);printk ("\n" );if (SiSHostChipInfo[i].flags &SIS5513_FLAG_LATENCY ) {
@@ -592,12 +642,22 @@ }if (host_dev) { -byte reg52h =0 ; +if (capabilities &SIS5513_FLAG_ATA_100 ) { +byte reg49h =0 ; -pci_read_config_byte (dev,0x52 , ®52h); -if (!(reg52h &0x04 )) { -/* set IDE controller to operate in Compabitility mode only */ -pci_write_config_byte (dev,0x52 , reg52h|0x04 ); +pci_read_config_byte (dev,0x49 , ®49h); +if (!(reg49h &0x01 )) { +/* set IDE controller to operate in Compabitility mode only */ +pci_write_config_byte (dev,0x49 , reg49h|0x01 ); + } + }else { +byte reg52h =0 ; + +pci_read_config_byte (dev,0x52 , ®52h); +if (!(reg52h &0x04 )) { +/* set IDE controller to operate in Compabitility mode only */ +pci_write_config_byte (dev,0x52 , reg52h|0x04 ); + } }#if defined(DISPLAY_SIS_TIMINGS ) && defined(CONFIG_PROC_FS )if (!sis_proc) {