patch-2.3.40 linux/drivers/block/cmd646.c

Next file: linux/drivers/block/cmd64x.c
Previous file: linux/drivers/block/amd7409.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.39/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c
@@ -1,289 +0,0 @@
-/* $Id: cmd646.c,v 1.15 1999/07/23 01:48:37 davem Exp $
- * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
- *           Note, this driver is not used at all on other systems because
- *           there the "BIOS" has done all of the following already.
- *           Due to massive hardware bugs, UltraDMA is only supported
- *           on the 646U2 and not on the 646U.
- *
- * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 1998       David S. Miller (davem@dm.cobaltmicro.com)
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-static int cmd646_config_drive_for_dma(ide_drive_t *drive)
-{
-	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
-
-	/* Even if the drive is not _currently_ in a DMA
-	 * mode, we succeed, and we'll enable it manually
-	 * below in cmd646_dma_onoff.
-	 *
-	 * This is done for disks only, CDROMs and other
-	 * IDE devices are just too quirky.
-	 */
-	if((id != NULL) &&
-	   ((id->capability & 1) != 0) &&
-	   hwif->autodma &&
-	   (drive->media == ide_disk)) {
-		if(id->field_valid & 0x0004) {
-			if(id->dma_ultra & 0x0007)
-				return hwif->dmaproc(ide_dma_on, drive);
-		}
-		if(id->field_valid & 0x0002)
-			if((id->dma_mword & 0x0004) || (id->dma_1word & 0x0004))
-				return hwif->dmaproc(ide_dma_on, drive);
-	}
-	return hwif->dmaproc(ide_dma_off_quietly, drive);
-}
-
-/* This is fun.  -DaveM */
-#define IDE_SETXFER		SETFEATURES_XFER
-#define IDE_SETFEATURE		WIN_SETFEATURES
-#define IDE_DMA2_ENABLE		XFER_MW_DMA_2
-#define IDE_DMA1_ENABLE		XFER_MW_DMA_1
-#define IDE_DMA0_ENABLE		XFER_MW_DMA_0
-#define IDE_UDMA2_ENABLE	XFER_UDMA_2
-#define IDE_UDMA1_ENABLE	XFER_UDMA_1
-#define IDE_UDMA0_ENABLE	XFER_UDMA_0
-
-static __inline__ unsigned char dma2_bits_to_command(unsigned char bits)
-{
-	if(bits & 0x04)
-		return IDE_DMA2_ENABLE;
-	if(bits & 0x02)
-		return IDE_DMA1_ENABLE;
-	return IDE_DMA0_ENABLE;
-}
-
-static __inline__ unsigned char udma2_bits_to_command(unsigned char bits)
-{
-	if(bits & 0x04)
-		return IDE_UDMA2_ENABLE;
-	if(bits & 0x02)
-		return IDE_UDMA1_ENABLE;
-	return IDE_UDMA0_ENABLE;
-}
-
-static __inline__ int wait_for_ready(ide_drive_t *drive)
-{
-	int timeout = 100;
-	byte stat;
-
-	while(--timeout) {
-		stat = GET_STAT();
-
-		printk("STAT(%2x) ", stat);
-		if(!(stat & BUSY_STAT)) {
-			if((stat & READY_STAT) || (stat & ERR_STAT))
-				break;
-		}
-		udelay(100);
-	}
-	if((stat & ERR_STAT) || timeout <= 0)
-		return 1;
-	return 0;
-}
-
-static void cmd646_do_setfeature(ide_drive_t *drive, byte command)
-{
-#if 0
-	(void) ide_config_drive_speed(drive, command);
-#else
-	unsigned long flags;
-	byte old_select;
-
-	save_flags(flags);
-	cli();
-	printk("SELECT ");
-	old_select = IN_BYTE(IDE_SELECT_REG);
-	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
-	printk("SETXFER ");
-	OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG);
-	printk("CMND ");
-	OUT_BYTE(command, IDE_NSECTOR_REG);
-	printk("wait ");
-	if(wait_for_ready(drive))
-		goto out;
-	printk("SETFEATURE ");
-	OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG);
-	printk("wait ");
-	(void) wait_for_ready(drive);
-out:
-	OUT_BYTE(old_select, IDE_SELECT_REG);
-	restore_flags(flags);
-#endif
-}
-
-static void cmd646_dma2_enable(ide_drive_t *drive, unsigned long dma_base)
-{
-	byte unit = (drive->select.b.unit & 0x01);
-	byte bits = (drive->id->dma_mword | drive->id->dma_1word) & 0x07;
-
-	printk("CMD646: MDMA enable [");
-	if((((drive->id->dma_mword & 0x0007) << 8) !=
-	    (drive->id->dma_mword & 0x0700)))
-		cmd646_do_setfeature(drive, dma2_bits_to_command(bits));
-	printk("DMA_CAP ");
-	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-	printk("DONE]\n");
-}
-
-static void cmd646_udma_enable(ide_drive_t *drive, unsigned long dma_base)
-{
-	byte unit = (drive->select.b.unit & 0x01);
-	byte udma_ctrl, bits = drive->id->dma_ultra & 0x07;
-	byte udma_timing_bits;
-
-	printk("CMD646: UDMA enable [");
-	if(((drive->id->dma_ultra & 0x0007) << 8) !=
-	   (drive->id->dma_ultra & 0x0700))
-		cmd646_do_setfeature(drive, udma2_bits_to_command(bits));
-
-	/* Enable DMA and UltraDMA */
-	printk("DMA_CAP ");
-	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-
-	udma_ctrl = inb(dma_base + 3);
-
-	/* Put this channel into UDMA mode. */
-	printk("UDMA_CTRL ");
-	udma_ctrl |= (1 << unit);
-
-	/* Set UDMA2 usable timings. */
-	if(bits & 0x04)
-		udma_timing_bits = 0x10;
-	else if(bits & 0x02)
-		udma_timing_bits = 0x20;
-	else
-		udma_timing_bits = 0x30;
-	udma_ctrl &= ~(0x30 << (unit * 2));
-	udma_ctrl |=  (udma_timing_bits << (unit * 2));
-
-	outb(udma_ctrl, dma_base+3);
-	printk("DONE]\n");
-}
-
-static int cmd646_dma_onoff(ide_drive_t *drive, int enable)
-{
-	if(enable) {
-		ide_hwif_t *hwif = HWIF(drive);
-		unsigned long dma_base = hwif->dma_base;
-		struct hd_driveid *id = drive->id;
-		unsigned int class_rev;
-
-		/* UltraDMA only supported on PCI646U and PCI646U2,
-		 * which correspond to revisions 0x03 and 0x05 respectively.
-		 * Actually, although the CMD tech support people won't
-		 * tell me the details, the 0x03 revision cannot support
-		 * UDMA correctly without hardware modifications, and even
-		 * then it only works with Quantum disks due to some
-		 * hold time assumptions in the 646U part which are fixed
-		 * in the 646U2.
-		 * So we only do UltraDMA on revision 0x05 chipsets.
-		 */
-		pci_read_config_dword(hwif->pci_dev,
-				      PCI_CLASS_REVISION,
-				      &class_rev);
-		class_rev &= 0xff;
-		if((class_rev == 0x05) &&
-		   (id->field_valid & 0x0004) &&
-		   (id->dma_ultra & 0x07)) {
-			/* UltraDMA modes. */
-			cmd646_udma_enable(drive, dma_base);
-		} else {
-			/* Normal MultiWord DMA modes. */
-			cmd646_dma2_enable(drive, dma_base);
-		}
-	}
-	drive->using_dma = enable;
-	return 0;
-}
-
-static int cmd646_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	if(func == ide_dma_check)
-		return cmd646_config_drive_for_dma(drive);
-	else if(func == ide_dma_on || func == ide_dma_off || func == ide_dma_off_quietly)
-		return cmd646_dma_onoff(drive, (func == ide_dma_on));
-
-	/* Other cases are done by generic IDE-DMA code. */
-	return ide_dmaproc(func, drive);
-}
-
-/*
- * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
- * event order for DMA transfers.
- */
-static int cmd646_1_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long dma_base = hwif->dma_base;
-	byte dma_stat;
-
-	if (func == ide_dma_end) {
-		drive->waiting_for_dma = 0;
-		dma_stat = inb(dma_base+2);		/* get DMA status */
-		outb(inb(dma_base)&~1, dma_base);	/* stop DMA */
-		outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
-		return (dma_stat & 7) != 4;	/* verify good DMA status */
-	}
-
-	/* Other cases are done by generic IDE-DMA code. */
-	return cmd646_dmaproc(func, drive);
-}
-
-void __init ide_init_cmd646 (ide_hwif_t *hwif)
-{
-	struct pci_dev *dev = hwif->pci_dev;
-	unsigned char mrdmode;
-	unsigned int class_rev;
-
-	pci_read_config_dword(hwif->pci_dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
-
-	hwif->chipset = ide_cmd646;
-
-	/* Set a good latency timer and cache line size value. */
-	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-#ifdef __sparc_v9__
-	(void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);
-#endif
-
-	/* Setup interrupts. */
-	(void) pci_read_config_byte(dev, 0x71, &mrdmode);
-	mrdmode &= ~(0x30);
-	(void) pci_write_config_byte(dev, 0x71, mrdmode);
-
-	/* Use MEMORY READ LINE for reads.
-	 * NOTE: Although not mentioned in the PCI0646U specs,
-	 *       these bits are write only and won't be read
-	 *       back as set or not.  The PCI0646U2 specs clarify
-	 *       this point.
-	 */
-	(void) pci_write_config_byte(dev, 0x71, mrdmode | 0x02);
-
-	/* Set reasonable active/recovery/address-setup values. */
-	(void) pci_write_config_byte(dev, 0x53, 0x40);
-	(void) pci_write_config_byte(dev, 0x54, 0x3f);
-	(void) pci_write_config_byte(dev, 0x55, 0x40);
-	(void) pci_write_config_byte(dev, 0x56, 0x3f);
-	(void) pci_write_config_byte(dev, 0x57, 0x5c);
-	(void) pci_write_config_byte(dev, 0x58, 0x3f);
-	(void) pci_write_config_byte(dev, 0x5b, 0x3f);
-
-	if (hwif->dma_base) {
-		if (class_rev == 0x01) {
-			hwif->dmaproc = &cmd646_1_dmaproc;
-		} else {
-			hwif->dmaproc = &cmd646_dmaproc;
-		}
-	}
-}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)