static void program_drive_counts(ide_drive_t *drive, unsigned int index)
{
	unsigned long flags;
	u8 setup_count    = setup_counts[index];
	u8 active_count   = active_counts[index];
	u8 recovery_count = recovery_counts[index];

	if (index > 1) {
		ide_drive_t *peer = ide_get_pair_dev(drive);
		unsigned int mate = index ^ 1;

		if (peer) {
			if (setup_count < setup_counts[mate])
				setup_count = setup_counts[mate];
			if (active_count < active_counts[mate])
				active_count = active_counts[mate];
			if (recovery_count < recovery_counts[mate])
				recovery_count = recovery_counts[mate];
		}
	}

	switch (setup_count) {
	case 4:	 setup_count = 0x00; break;
	case 3:	 setup_count = 0x80; break;
	case 1:
	case 2:	 setup_count = 0x40; break;
	default: setup_count = 0xc0; 
	}

	spin_lock_irqsave(&cmd640_lock, flags);
	setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
	__put_cmd640_reg(arttim_regs[index], setup_count);
	__put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
	spin_unlock_irqrestore(&cmd640_lock, flags);
}
Esempio n. 2
0
/*
 * This routine writes the prepared setup/active/recovery counts
 * for a drive into the cmd640 chipset registers to active them.
 */
static void program_drive_counts(ide_drive_t *drive, unsigned int index)
{
    unsigned long flags;
    u8 setup_count    = setup_counts[index];
    u8 active_count   = active_counts[index];
    u8 recovery_count = recovery_counts[index];

    /*
     * Set up address setup count and drive read/write timing registers.
     * Primary interface has individual count/timing registers for
     * each drive.  Secondary interface has one common set of registers,
     * so we merge the timings, using the slowest value for each timing.
     */
    if (index > 1) {
        ide_drive_t *peer = ide_get_pair_dev(drive);
        unsigned int mate = index ^ 1;

        if (peer) {
            if (setup_count < setup_counts[mate])
                setup_count = setup_counts[mate];
            if (active_count < active_counts[mate])
                active_count = active_counts[mate];
            if (recovery_count < recovery_counts[mate])
                recovery_count = recovery_counts[mate];
        }
    }

    /*
     * Convert setup_count to internal chipset representation
     */
    switch (setup_count) {
    case 4:
        setup_count = 0x00;
        break;
    case 3:
        setup_count = 0x80;
        break;
    case 1:
    case 2:
        setup_count = 0x40;
        break;
    default:
        setup_count = 0xc0; /* case 5 */
    }

    /*
     * Now that everything is ready, program the new timings
     */
    spin_lock_irqsave(&cmd640_lock, flags);
    /*
     * Program the address_setup clocks into ARTTIM reg,
     * and then the active/recovery counts into the DRWTIM reg
     * (this converts counts of 16 into counts of zero -- okay).
     */
    setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
    __put_cmd640_reg(arttim_regs[index], setup_count);
    __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
    spin_unlock_irqrestore(&cmd640_lock, flags);
}
Esempio n. 3
0
static void put_cmd640_reg(u16 reg, u8 val)
{
	unsigned long flags;

	spin_lock_irqsave(&cmd640_lock, flags);
	__put_cmd640_reg(reg, val);
	spin_unlock_irqrestore(&cmd640_lock, flags);
}
Esempio n. 4
0
/*
 * Sets prefetch mode for a drive.
 */
static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
{
	unsigned long flags;
	int reg = prefetch_regs[index];
	u8 b;

	spin_lock_irqsave(&cmd640_lock, flags);
	b = __get_cmd640_reg(reg);
	__set_prefetch_mode(drive, mode);
	if (mode)
		b &= ~prefetch_masks[index];	/* enable prefetch */
	else
		b |= prefetch_masks[index];	/* disable prefetch */
	__put_cmd640_reg(reg, b);
	spin_unlock_irqrestore(&cmd640_lock, flags);
}