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); }
/* * 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); }
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); }
/* * 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); }