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

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, &reg48);
 	pci_read_config_word(dev, 0x4a, &reg4a);
 
-#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)