Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b740d884 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz
Browse files

serverworks: always tune CSB6



Switch the driver to always program DMA/PIO timings and set device transfer
mode instead of trusting BIOS on CSB6 controllers (libata pata_serverworks.c
driver is also doing things this way and there were no problems reported so
far).  While doing conversion I noticed that the old code had many issues:

* the code was assuming that hwif->dma_status is always valid
  (which obviously isn't true if hwif->dma_base == NULL)

* value of "(ultra_timing >> (4*unit)) & ~(0xF0)" expression wasn't checked
  to fit into udma_modes[5]

* code validating DMA timings didn't validate corresponding PIO timings

* extra CSB5 PIO register wasn't validated et all

* hwif->ide_dma_off_quietly() is always called before ide_set_dma() (which in
  turn calls hwif->speedproc() method - svwks_tune_chipset() in this case)
  so the code depending on DMA capable bit of DMA status to be set was never
  executed (=> the code was never validating DMA timings despite actually
  enabling DMA if the PIO timings were OK!)

* on resume driver dependend entirely on BIOS to restore timings and set
  transfer mode on the device

While at it:

There is no need to read PIO/MWDMA timings now so don't do it.

Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Acked-by: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
parent 71d441dd
Loading
Loading
Loading
Loading
+2 −75
Original line number Original line Diff line number Diff line
/*
/*
 * linux/drivers/ide/pci/serverworks.c		Version 0.11	Jun 2 2007
 * linux/drivers/ide/pci/serverworks.c		Version 0.20	Jun 3 2007
 *
 *
 * Copyright (C) 1998-2000 Michel Aubry
 * Copyright (C) 1998-2000 Michel Aubry
 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -152,83 +152,10 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
		drive->media == ide_disk && speed >= XFER_UDMA_0)
		drive->media == ide_disk && speed >= XFER_UDMA_0)
			BUG();
			BUG();


	pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
	pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
	pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
	pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
	pci_read_config_word(dev, 0x4A, &csb5_pio);
	pci_read_config_word(dev, 0x4A, &csb5_pio);
	pci_read_config_byte(dev, 0x54, &ultra_enable);
	pci_read_config_byte(dev, 0x54, &ultra_enable);


	/* If we are in RAID mode (eg AMI MegaIDE) then we can't it
	   turns out trust the firmware configuration */

	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
		goto oem_setup_failed;

	/* Per Specified Design by OEM, and ASIC Architect */
	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
		if (!drive->init_speed) {
			u8 dma_stat = inb(hwif->dma_status);

			if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
			    ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
				drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
				return 0;
			} else if ((dma_timing) &&
				   ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
				u8 dmaspeed;

				switch (dma_timing & 0x77) {
				case 0x20:
					dmaspeed = XFER_MW_DMA_2;
					break;
				case 0x21:
					dmaspeed = XFER_MW_DMA_1;
					break;
				case 0x77:
					dmaspeed = XFER_MW_DMA_0;
					break;
				default:
					goto dma_pio;
				}

				drive->current_speed = drive->init_speed = dmaspeed;
				return 0;
			}
dma_pio:
			if (pio_timing) {
				u8 piospeed;

				switch (pio_timing & 0x7f) {
				case 0x20:
					piospeed = XFER_PIO_4;
					break;
				case 0x22:
					piospeed = XFER_PIO_3;
					break;
				case 0x34:
					piospeed = XFER_PIO_2;
					break;
				case 0x47:
					piospeed = XFER_PIO_1;
					break;
				case 0x5d:
					piospeed = XFER_PIO_0;
					break;
				default:
					goto oem_setup_failed;
				}

				drive->current_speed = drive->init_speed = piospeed;
				return 0;
			}
		}
	}

oem_setup_failed:

	pio_timing	= 0;
	dma_timing	= 0;
	ultra_timing	&= ~(0x0F << (4*unit));
	ultra_timing	&= ~(0x0F << (4*unit));
	ultra_enable	&= ~(0x01 << drive->dn);
	ultra_enable	&= ~(0x01 << drive->dn);
	csb5_pio	&= ~(0x0F << (4*drive->dn));
	csb5_pio	&= ~(0x0F << (4*drive->dn));