patch-2.3.6 linux/drivers/block/piix.c
Next file: linux/drivers/block/rd.c
Previous file: linux/drivers/block/ns87415.c
Back to the patch index
Back to the overall index
- Lines: 253
- Date:
Wed Jun 2 22:21:51 1999
- Orig file:
v2.3.5/linux/drivers/block/piix.c
- Orig date:
Fri May 14 18:55:14 1999
diff -u --recursive --new-file v2.3.5/linux/drivers/block/piix.c linux/drivers/block/piix.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/piix.c Version 0.22 March 29, 1999
+ * linux/drivers/block/piix.c Version 0.23 May 29, 1999
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer
@@ -13,10 +13,10 @@
* 41
* 43
*
- * | PIO 0 | c0 | 80 | 0 |
- * | PIO 2 | SW2 | d0 | 90 | 4 |
- * | PIO 3 | MW1 | e1 | a1 | 9 |
- * | PIO 4 | MW2 | e3 | a3 | b |
+ * | PIO 0 | c0 | 80 | 0 | piix_tune_drive(drive, 0);
+ * | PIO 2 | SW2 | d0 | 90 | 4 | piix_tune_drive(drive, 2);
+ * | PIO 3 | MW1 | e1 | a1 | 9 | piix_tune_drive(drive, 3);
+ * | PIO 4 | MW2 | e3 | a3 | b | piix_tune_drive(drive, 4);
*
* sitre = word40 & 0x4000; primary
* sitre = word42 & 0x4000; secondary
@@ -58,10 +58,40 @@
#include "ide_modes.h"
-#define PIIX_DMA_PROC 0
-#define PIIX_DEBUG_SET_XFER 0
#define PIIX_DEBUG_DRIVE_INFO 0
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ *
+ */
+static byte piix_dma_2_pio (byte xfer_rate) {
+ switch(xfer_rate) {
+ case XFER_UDMA_4:
+ case XFER_UDMA_3:
+ case XFER_UDMA_2:
+ case XFER_UDMA_1:
+ case XFER_UDMA_0:
+ case XFER_MW_DMA_2:
+ case XFER_PIO_4:
+ return 4;
+ case XFER_MW_DMA_1:
+ case XFER_PIO_3:
+ return 3;
+ case XFER_SW_DMA_2:
+ case XFER_PIO_2:
+ return 2;
+ case XFER_MW_DMA_0:
+ case XFER_SW_DMA_1:
+ case XFER_SW_DMA_0:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ case XFER_PIO_SLOW:
+ default:
+ return 0;
+ }
+}
+
/*
* Based on settings done by AMI BIOS
* (might be usefull if drive is not registered in CMOS for any reason).
@@ -70,19 +100,22 @@
{
unsigned long flags;
u16 master_data;
- byte slave_data, speed;
- int err;
- int is_slave = (&HWIF(drive)->drives[1] == drive);
- int master_port = HWIF(drive)->index ? 0x42 : 0x40;
- int slave_port = 0x44;
- /* ISP RTC */
- byte timings[][2] = { { 0, 0 },
- { 0, 0 },
- { 1, 0 },
- { 2, 1 },
- { 2, 3 }, };
-
+ byte slave_data;
+ int is_slave = (&HWIF(drive)->drives[1] == drive);
+ int master_port = HWIF(drive)->index ? 0x42 : 0x40;
+ int slave_port = 0x44;
+ /* ISP RTC */
+ byte timings[][2] = { { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+ { 2, 1 },
+ { 2, 3 }, };
+
+#if 1
+ pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+#else
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+#endif
pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
if (is_slave) {
master_data = master_data | 0x4000;
@@ -107,28 +140,15 @@
if (is_slave)
pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
restore_flags(flags);
-
- switch(pio) {
- case 4: speed = XFER_PIO_4;break;
- case 3: speed = XFER_PIO_3;break;
- case 2: speed = XFER_PIO_2;break;
- case 1: speed = XFER_PIO_1;break;
- default:
- speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
- break;
- }
-
- err = ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
}
-extern char *ide_xfer_verbose (byte xfer_rate);
-
static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
+ unsigned long flags;
int sitre;
short reg4042, reg44, reg48, reg4a;
byte speed;
@@ -144,23 +164,22 @@
pci_read_config_word(dev, 0x48, ®48);
pci_read_config_word(dev, 0x4a, ®4a);
-#if PIIX_DEBUG_SET_XFER
- printk("PIIX%s: DMA enable ",
- (dev->device == PCI_DEVICE_ID_INTEL_82371FB_0) ? "a" :
- (dev->device == PCI_DEVICE_ID_INTEL_82371FB_1) ? "b" :
- (dev->device == PCI_DEVICE_ID_INTEL_82371SB_1) ? "3" :
- (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? "4" : " UNKNOWN" );
-#endif /* PIIX_DEBUG_SET_XFER */
+ save_flags(flags);
+ cli();
if (id->dma_ultra && (ultra)) {
if (!(reg48 & u_flag)) {
pci_write_config_word(dev, 0x48, reg48|u_flag);
}
} else {
- pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+ if (reg48 & u_flag) {
+ pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+ }
}
if ((id->dma_ultra & 0x0004) && (ultra)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
if (!((id->dma_ultra >> 8) & 4)) {
drive->id->dma_ultra &= ~0x0F00;
drive->id->dma_ultra |= 0x0404;
@@ -171,6 +190,8 @@
}
speed = XFER_UDMA_2;
} else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
if (!((id->dma_ultra >> 8) & 2)) {
drive->id->dma_ultra &= ~0x0F00;
drive->id->dma_ultra |= 0x0202;
@@ -182,6 +203,8 @@
}
speed = XFER_UDMA_1;
} else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ drive->id->dma_mword &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
if (!((id->dma_ultra >> 8) & 1)) {
drive->id->dma_ultra &= ~0x0F00;
drive->id->dma_ultra |= 0x0101;
@@ -193,33 +216,46 @@
}
speed = XFER_UDMA_0;
} else if (id->dma_mword & 0x0004) {
- drive->id->dma_ultra &= ~0x0F0F;
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
if (!((id->dma_mword >> 8) & 4)) {
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_mword |= 0x0404;
}
speed = XFER_MW_DMA_2;
} else if (id->dma_mword & 0x0002) {
- drive->id->dma_ultra &= ~0x0F0F;
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_1word &= ~0x0F00;
if (!((id->dma_mword >> 8) & 2)) {
drive->id->dma_mword &= ~0x0F00;
drive->id->dma_mword |= 0x0202;
}
speed = XFER_MW_DMA_1;
} else if (id->dma_1word & 0x0004) {
- drive->id->dma_ultra &= ~0x0F0F;
- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ drive->id->dma_ultra &= ~0x0F00;
+ drive->id->dma_mword &= ~0x0F00;
if (!((id->dma_1word >> 8) & 4)) {
drive->id->dma_1word &= ~0x0F00;
drive->id->dma_1word |= 0x0404;
}
speed = XFER_SW_DMA_2;
} else {
- return ide_dma_off_quietly;
+#if 0
+ speed = XFER_PIO_0;
+#else
+ speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+#endif
}
+ restore_flags(flags);
+ piix_tune_drive(drive, piix_dma_2_pio(speed));
+
(void) ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
#if PIIX_DEBUG_DRIVE_INFO
@@ -241,7 +277,7 @@
int ultra = (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0;
switch (func) {
case ide_dma_check:
- return piix_config_drive_for_dma(drive, ultra);
+ return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive, ultra), drive);
default :
break;
}
@@ -252,7 +288,7 @@
void ide_init_piix (ide_hwif_t *hwif)
{
hwif->tuneproc = &piix_tune_drive;
-#if PIIX_DMA_PROC
- hwif->dmaproc = &piix_dmaproc;
-#endif /* PIIX_DMA_PROC */
+ if (hwif->dma_base) {
+ hwif->dmaproc = &piix_dmaproc;
+ }
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)