Ejemplo n.º 1
0
/*
 * This routine writes into the chipset registers
 * PIO setup/active/recovery timings.
 */
static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
{
	ide_hwif_t *hwif	= drive->hwif;
	struct pci_dev *dev	= to_pci_dev(hwif->dev);
	struct ide_timing *t	= ide_timing_find_mode(XFER_PIO_0 + pio);
	unsigned long setup_count;
	unsigned int cycle_time;
	u8 arttim = 0;

	static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
	static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};

	cycle_time = ide_pio_cycle_time(drive, pio);

	program_cycle_times(drive, cycle_time, t->active);

	setup_count = quantize_timing(t->setup,
			1000 / (ide_pci_clk ? ide_pci_clk : 33));

	/*
	 * The primary channel has individual address setup timing registers
	 * for each drive and the hardware selects the slowest timing itself.
	 * The secondary channel has one common register and we have to select
	 * the slowest address setup timing ourselves.
	 */
	if (hwif->channel) {
		ide_drive_t *pair = ide_get_pair_dev(drive);

		ide_set_drivedata(drive, (void *)setup_count);

		if (pair)
			setup_count = max_t(u8, setup_count,
					(unsigned long)ide_get_drivedata(pair));
	}

	if (setup_count > 5)		/* shouldn't actually happen... */
		setup_count = 5;
	cmdprintk("Final address setup count: %d\n", setup_count);

	/*
	 * Program the address setup clocks into the ARTTIM registers.
	 * Avoid clearing the secondary channel's interrupt bit.
	 */
	(void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);
	if (hwif->channel)
		arttim &= ~ARTTIM23_INTR_CH1;
	arttim &= ~0xc0;
	arttim |= setup_values[setup_count];
	(void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
	cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
}
Ejemplo n.º 2
0
/*
 * This routine calculates active/recovery counts and then writes them into
 * the chipset registers.
 */
static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
{
	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
	int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
	u8  cycle_count, active_count, recovery_count, drwtim;
	static const u8 recovery_values[] =
		{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
	static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};

	cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",
		  cycle_time, active_time);

	cycle_count	= quantize_timing( cycle_time, clock_time);
	active_count	= quantize_timing(active_time, clock_time);
	recovery_count	= cycle_count - active_count;

	/*
	 * In case we've got too long recovery phase, try to lengthen
	 * the active phase
	 */
	if (recovery_count > 16) {
		active_count += recovery_count - 16;
		recovery_count = 16;
	}
	if (active_count > 16)		/* shouldn't actually happen... */
	 	active_count = 16;

	cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
		  cycle_count, active_count, recovery_count);

	/*
	 * Convert values to internal chipset representation
	 */
	recovery_count = recovery_values[recovery_count];
 	active_count  &= 0x0f;

	/* Program the active/recovery counts into the DRWTIM register */
	drwtim = (active_count << 4) | recovery_count;
	(void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
	cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
}
Ejemplo n.º 3
0
static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted)
{
    int setup_time, active_time, recovery_time;
    int clock_time, pio_mode, cycle_time;
    u8 recovery_count2, cycle_count;
    int setup_count, active_count, recovery_count;
    int bus_speed = system_bus_clock();
    /*byte b;*/
    ide_pio_data_t  d;

    switch (mode_wanted) {
    case 8: /* set prefetch off */
    case 9: /* set prefetch on */
        mode_wanted &= 1;
        /*set_prefetch_mode(index, mode_wanted);*/
        cmdprintk("%s: %sabled cmd640 prefetch\n",
                  drive->name, mode_wanted ? "en" : "dis");
        return;
    }

    mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
    pio_mode = d.pio_mode;
    cycle_time = d.cycle_time;

    /*
     * I copied all this complicated stuff from cmd640.c and made a few
     * minor changes.  For now I am just going to pray that it is correct.
     */
    if (pio_mode > 5)
        pio_mode = 5;
    setup_time  = ide_pio_timings[pio_mode].setup_time;
    active_time = ide_pio_timings[pio_mode].active_time;
    recovery_time = cycle_time - (setup_time + active_time);
    clock_time = 1000 / bus_speed;
    cycle_count = (cycle_time + clock_time - 1) / clock_time;

    setup_count = (setup_time + clock_time - 1) / clock_time;

    active_count = (active_time + clock_time - 1) / clock_time;

    recovery_count = (recovery_time + clock_time - 1) / clock_time;
    recovery_count2 = cycle_count - (setup_count + active_count);
    if (recovery_count2 > recovery_count)
        recovery_count = recovery_count2;
    if (recovery_count > 16) {
        active_count += recovery_count - 16;
        recovery_count = 16;
    }
    if (active_count > 16)
        active_count = 16; /* maximum allowed by cmd646 */

    /*
     * In a perfect world, we might set the drive pio mode here
     * (using WIN_SETFEATURE) before continuing.
     *
     * But we do not, because:
     *	1) this is the wrong place to do it
     *		(proper is do_special() in ide.c)
     * 	2) in practice this is rarely, if ever, necessary
     */
    program_drive_counts (drive, setup_count, active_count, recovery_count);

    cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, "
              "clocks=%d/%d/%d\n",
              drive->name, pio_mode, mode_wanted, cycle_time,
              d.overridden ? " (overriding vendor mode)" : "",
              setup_count, active_count, recovery_count);
}
Ejemplo n.º 4
0
/*
 * This routine writes the prepared setup/active/recovery counts
 * for a drive into the cmd646 chipset registers to active them.
 */
static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count)
{
    unsigned long flags;
    struct pci_dev *dev = HWIF(drive)->pci_dev;
    ide_drive_t *drives = HWIF(drive)->drives;
    u8 temp_b;
    static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
    static const u8 recovery_counts[] =
    {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
    static const u8 arttim_regs[2][2] = {
        { ARTTIM0, ARTTIM1 },
        { ARTTIM23, ARTTIM23 }
    };
    static const u8 drwtim_regs[2][2] = {
        { DRWTIM0, DRWTIM1 },
        { DRWTIM2, DRWTIM3 }
    };
    int channel = (int) HWIF(drive)->channel;
    int slave = (drives != drive);  /* Is this really the best way to determine this?? */

    cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n",
              setup_count, active_count, recovery_count, drive->present);
    /*
     * Set up address setup count registers.
     * Primary interface has individual count/timing registers for
     * each drive.  Secondary interface has one common set of registers,
     * for address setup so we merge these timings, using the slowest
     * value.
     */
    if (channel) {
        drive->drive_data = setup_count;
        setup_count = IDE_MAX(drives[0].drive_data,
                              drives[1].drive_data);
        cmdprintk("Secondary interface, setup_count = %d\n",
                  setup_count);
    }

    /*
     * Convert values to internal chipset representation
     */
    setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count];
    active_count &= 0xf; /* Remember, max value is 16 */
    recovery_count = (int) recovery_counts[recovery_count];

    cmdprintk("Final values = %d,%d,%d\n",
              setup_count, active_count, recovery_count);

    /*
     * Now that everything is ready, program the new timings
     */
    local_irq_save(flags);
    /*
     * Program the address_setup clocks into ARTTIM reg,
     * and then the active/recovery counts into the DRWTIM reg
     */
    (void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b);
    (void) pci_write_config_byte(dev, arttim_regs[channel][slave],
                                 ((u8) setup_count) | (temp_b & 0x3f));
    (void) pci_write_config_byte(dev, drwtim_regs[channel][slave],
                                 (u8) ((active_count << 4) | recovery_count));
    cmdprintk ("Write %x to %x\n",
               ((u8) setup_count) | (temp_b & 0x3f),
               arttim_regs[channel][slave]);
    cmdprintk ("Write %x to %x\n",
               (u8) ((active_count << 4) | recovery_count),
               drwtim_regs[channel][slave]);
    local_irq_restore(flags);
}