Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 53604
b: refs/heads/master
c: 0e9b4e5
h: refs/heads/master
v: v3
  • Loading branch information
Bartlomiej Zolnierkiewicz committed May 5, 2007
1 parent ab71500 commit ea4c1d5
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 69 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 247b03f8dc4c01659030889f7fb4574013974ac6
refs/heads/master: 0e9b4e535fec7e2a189952670937adfbe2826b63
126 changes: 58 additions & 68 deletions trunk/drivers/ide/pci/it821x.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

/*
* linux/drivers/ide/pci/it821x.c Version 0.09 December 2004
* linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007
*
* Copyright (C) 2004 Red Hat <alan@redhat.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* May be copied or modified under the terms of the GNU General Public License
* Based in part on the ITE vendor provided SCSI driver.
Expand Down Expand Up @@ -104,6 +105,7 @@ static int it8212_noraid;
/**
* it821x_program - program the PIO/MWDMA registers
* @drive: drive to tune
* @timing: timing info
*
* Program the PIO/MWDMA timing for this channel according to the
* current clock.
Expand All @@ -127,6 +129,7 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
/**
* it821x_program_udma - program the UDMA registers
* @drive: drive to tune
* @timing: timing info
*
* Program the UDMA timing for this drive according to the
* current clock.
Expand All @@ -153,10 +156,9 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
}
}


/**
* it821x_clock_strategy
* @hwif: hardware interface
* @drive: drive to set up
*
* Select between the 50 and 66Mhz base clocks to get the best
* results for this interface.
Expand All @@ -182,8 +184,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
altclock = itdev->want[0][1];
}

/* Master doesn't care does the slave ? */
if(clock == ATA_ANY)
/*
* if both clocks can be used for the mode with the higher priority
* use the clock needed by the mode with the lower priority
*/
if (clock == ATA_ANY)
clock = altclock;

/* Nobody cares - keep the same clock */
Expand Down Expand Up @@ -240,37 +245,56 @@ static u8 it821x_ratemask (ide_drive_t *drive)
}

/**
* it821x_tuneproc - tune a drive
* it821x_tunepio - tune a drive
* @drive: drive to tune
* @mode_wanted: the target operating mode
*
* Load the timing settings for this device mode into the
* controller. By the time we are called the mode has been
* modified as neccessary to handle the absence of seperate
* master/slave timers for MWDMA/PIO.
* @pio: the desired PIO mode
*
* This code is only used in pass through mode.
* Try to tune the drive/host to the desired PIO mode taking into
* the consideration the maximum PIO mode supported by the other
* device on the cable.
*/

static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted)
static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
{
ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int unit = drive->select.b.unit;
ide_drive_t *pair = &hwif->drives[1 - unit];

/* Spec says 89 ref driver uses 88 */
static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };

if(itdev->smart)
return;
/*
* Compute the best PIO mode we can for a given device. We must
* pick a speed that does not cause problems with the other device
* on the cable.
*/
if (pair) {
u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL);
/* trim PIO to the slowest of the master/slave */
if (pair_pio < set_pio)
set_pio = pair_pio;
}

if (itdev->smart)
goto set_drive_speed;

/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
itdev->want[unit][1] = pio_want[mode_wanted];
itdev->want[unit][1] = pio_want[set_pio];
itdev->want[unit][0] = 1; /* PIO is lowest priority */
itdev->pio[unit] = pio[mode_wanted];
itdev->pio[unit] = pio[set_pio];
it821x_clock_strategy(drive);
it821x_program(drive, itdev->pio[unit]);

set_drive_speed:
return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
}

static void it821x_tuneproc(ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
(void)it821x_tunepio(drive, pio);
}

/**
Expand Down Expand Up @@ -353,40 +377,6 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)

}

/**
* config_it821x_chipset_for_pio - set drive timings
* @drive: drive to tune
* @speed we want
*
* Compute the best pio mode we can for a given device. We must
* pick a speed that does not cause problems with the other device
* on the cable.
*/

static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed)
{
u8 unit = drive->select.b.unit;
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *pair = &hwif->drives[1-unit];
u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
u8 pair_pio;

/* We have to deal with this mess in pairs */
if(pair != NULL) {
pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL);
/* Trim PIO to the slowest of the master/slave */
if(pair_pio < set_pio)
set_pio = pair_pio;
}
it821x_tuneproc(drive, set_pio);
speed = XFER_PIO_0 + set_pio;
/* XXX - We trim to the lowest of the pair so the other drive
will always be fine at this point until we do hotplug passthru */

if (set_speed)
(void) ide_config_drive_speed(drive, speed);
}

/**
* it821x_dma_read - DMA hook
* @drive: drive for DMA
Expand Down Expand Up @@ -450,15 +440,17 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed);

if(!itdev->smart) {
switch(speed) {
case XFER_PIO_4:
case XFER_PIO_3:
case XFER_PIO_2:
case XFER_PIO_1:
case XFER_PIO_0:
it821x_tuneproc(drive, (speed - XFER_PIO_0));
break;
switch (speed) {
case XFER_PIO_4:
case XFER_PIO_3:
case XFER_PIO_2:
case XFER_PIO_1:
case XFER_PIO_0:
return it821x_tunepio(drive, speed - XFER_PIO_0);
}

if (itdev->smart == 0) {
switch (speed) {
/* MWDMA tuning is really hard because our MWDMA and PIO
timings are kept in the same place. We can switch in the
host dma on/off callbacks */
Expand Down Expand Up @@ -498,14 +490,12 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, it821x_ratemask(drive));

if (speed) {
config_it821x_chipset_for_pio(drive, 0);
it821x_tune_chipset(drive, speed);
if (speed == 0)
return 0;

return ide_dma_enable(drive);
}
it821x_tune_chipset(drive, speed);

return 0;
return ide_dma_enable(drive);
}

/**
Expand All @@ -523,7 +513,7 @@ static int it821x_config_drive_for_dma (ide_drive_t *drive)
if (ide_use_dma(drive) && config_chipset_for_dma(drive))
return 0;

config_it821x_chipset_for_pio(drive, 1);
it821x_tuneproc(drive, 255);

return -1;
}
Expand Down

0 comments on commit ea4c1d5

Please sign in to comment.