Skip to content

Commit

Permalink
pata_sis: Implement MWDMA for the UDMA 133 capable chips
Browse files Browse the repository at this point in the history
Bartlomiej pointed out that while this got fixed in the old driver whoever
did it didn't port it across.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
  • Loading branch information
Alan Cox authored and Jeff Garzik committed Dec 3, 2009
1 parent 10734fc commit f20941f
Showing 1 changed file with 69 additions and 22 deletions.
91 changes: 69 additions & 22 deletions drivers/ata/pata_sis.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,24 +252,25 @@ static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
}

/**
* sis_133_set_piomode - Initialize host controller PATA PIO timings
* sis_133_do_piomode - Initialize host controller PATA PIO/DMA timings
* @ap: Port whose timings we are configuring
* @adev: Device we are configuring for.
*
* Set PIO mode for device, in host controller PCI config space. This
* function handles PIO set up for the later ATA133 devices.
* function handles PIO set up for the later ATA133 devices. The same
* timings are used for MWDMA.
*
* LOCKING:
* None (inherited from caller).
*/

static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
static void sis_133_do_piomode(struct ata_port *ap, struct ata_device *adev,
int speed)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int port = 0x40;
u32 t1;
u32 reg54;
int speed = adev->pio_mode - XFER_PIO_0;

const u32 timing133[] = {
0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */
Expand Down Expand Up @@ -304,6 +305,42 @@ static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(pdev, port, t1);
}

/**
* sis_133_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Device we are configuring for.
*
* Set PIO mode for device, in host controller PCI config space. This
* function handles PIO set up for the later ATA133 devices.
*
* LOCKING:
* None (inherited from caller).
*/

static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
{

sis_133_do_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
}

/**
* mwdma_clip_to_pio - clip MWDMA mode
* @adev: device
*
* As the SiS shared MWDMA and PIO timings we must program the equivalent
* PIO timing for the MWDMA mode but we must not program one higher than
* the permitted PIO timing of the device.
*/

static int mwdma_clip_to_pio(struct ata_device *adev)
{
const int mwdma_to_pio[3] = {
XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
};
return min(mwdma_to_pio[adev->dma_mode - XFER_MW_DMA_0],
adev->pio_mode - XFER_PIO_0);
}

/**
* sis_old_set_dmamode - Initialize host controller PATA DMA timings
* @ap: Port whose timings we are configuring
Expand Down Expand Up @@ -332,6 +369,7 @@ static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
if (adev->dma_mode < XFER_UDMA_0) {
/* bits 3-0 hold recovery timing bits 8-10 active timing and
the higher bits are dependant on the device */
speed = mwdma_clip_to_pio(adev);
timing &= ~0x870F;
timing |= mwdma_bits[speed];
} else {
Expand Down Expand Up @@ -372,6 +410,7 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
if (adev->dma_mode < XFER_UDMA_0) {
/* bits 3-0 hold recovery timing bits 8-10 active timing and
the higher bits are dependant on the device, bit 15 udma */
speed = mwdma_clip_to_pio(adev);
timing &= ~0x870F;
timing |= mwdma_bits[speed];
} else {
Expand All @@ -389,7 +428,7 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
* @adev: Device to program
*
* Set UDMA/MWDMA mode for device, in host controller PCI config space.
* Handles UDMA66 and early UDMA100 devices.
* Handles later UDMA100 devices.
*
* LOCKING:
* None (inherited from caller).
Expand All @@ -400,21 +439,25 @@ static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = sis_old_port_base(adev);
u8 timing;
u16 timing;

const u8 udma_bits[] = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};
const u16 udma_bits[] = {
0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100};
const u8 mwdma_bits[] = { 0x08, 0x32, 0x31 };

pci_read_config_byte(pdev, drive_pci + 1, &timing);
pci_read_config_word(pdev, drive_pci, &timing);

if (adev->dma_mode < XFER_UDMA_0) {
/* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
speed = mwdma_clip_to_pio(adev);
timing &= ~0x80FF;
timing |= mwdma_bits[speed];
} else {
/* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
speed = adev->dma_mode - XFER_UDMA_0;
timing &= ~0x8F;
timing &= ~0x8F00;
timing |= udma_bits[speed];
}
pci_write_config_byte(pdev, drive_pci + 1, timing);
pci_write_config_word(pdev, drive_pci, timing);
}

/**
Expand All @@ -434,21 +477,26 @@ static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *a
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = sis_old_port_base(adev);
u8 timing;
/* Low 4 bits are timing */
static const u8 udma_bits[] = { 0x8F, 0x8A, 0x87, 0x85, 0x83, 0x82, 0x81};
u16 timing;
/* Bits 15-12 are timing */
static const u16 udma_bits[] = {
0x8F00, 0x8A00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100
};
static const u8 mwdma_bits[] = { 0x08, 0x32, 0x31 };

pci_read_config_byte(pdev, drive_pci + 1, &timing);
pci_read_config_word(pdev, drive_pci, &timing);

if (adev->dma_mode < XFER_UDMA_0) {
/* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */
speed = mwdma_clip_to_pio(adev);
timing &= ~0x80FF;
timing = mwdma_bits[speed];
} else {
/* Bit 7 is UDMA on/off, bit 0-3 are cycle time */
speed = adev->dma_mode - XFER_UDMA_0;
timing &= ~0x8F;
timing &= ~0x8F00;
timing |= udma_bits[speed];
}
pci_write_config_byte(pdev, drive_pci + 1, timing);
pci_write_config_word(pdev, drive_pci, timing);
}

/**
Expand Down Expand Up @@ -479,13 +527,12 @@ static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
if (reg54 & 0x40000000)
port = 0x70;
port += (8 * ap->port_no) + (4 * adev->devno);

pci_read_config_dword(pdev, port, &t1);

if (adev->dma_mode < XFER_UDMA_0) {
t1 &= ~0x00000004;
/* FIXME: need data sheet to add MWDMA here. Also lacking on
ide/pci driver */
speed = mwdma_clip_to_pio(adev);
sis_133_do_piomode(ap, adev, speed);
t1 &= ~4; /* UDMA off */
} else {
speed = adev->dma_mode - XFER_UDMA_0;
/* if & 8 no UDMA133 - need info for ... */
Expand Down

0 comments on commit f20941f

Please sign in to comment.