static u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
{
	u16 *id = drive->id;
	int pio_mode = -1, overridden = 0;

	if (mode_wanted != 255)
		return min_t(u8, mode_wanted, max_mode);

	if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
		pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);

	if (pio_mode != -1) {
		printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
	} else {
		pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
		if (pio_mode > 2) {	/* 2 is maximum allowed tPIO value */
			pio_mode = 2;
			overridden = 1;
		}

		if (id[ATA_ID_FIELD_VALID] & 2) {	      /* ATA2? */
			if (ata_id_is_cfa(id) && (id[ATA_ID_CFA_MODES] & 7))
				pio_mode = 4 + min_t(int, 2,
						     id[ATA_ID_CFA_MODES] & 7);
			else if (ata_id_has_iordy(id)) {
				if (id[ATA_ID_PIO_MODES] & 7) {
					overridden = 0;
					if (id[ATA_ID_PIO_MODES] & 4)
						pio_mode = 5;
					else if (id[ATA_ID_PIO_MODES] & 2)
						pio_mode = 4;
					else
						pio_mode = 3;
				}
			}
		}

		if (overridden)
			printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
					 drive->name);
	}
Exemple #2
0
static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) {
	int interface_number;
	int drive_number;
	int clock_time; /* ns */
	int max_pio;
	int mc_time, av_time, ds_time;
	struct hd_driveid* id;
	int readahead;	/* there is a global named read_ahead */

	if (pio_mode != 255) {
		cmd640_set_mode(drive, pio_mode);
		return;
	}

	interface_number = HWIF(drive)->index;
	drive_number = drive->select.b.unit;
	clock_time = 1000/bus_speed;
	id = drive->id;
	if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) {
		ds_time = pio_timings[max_pio].ds_time;
	} else {
		max_pio = id->tPIO;
		ds_time = pio_timings[max_pio].ds_time;
		if (id->field_valid & 2) {
			if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
				if (id->eide_pio_modes & 4) max_pio = 5;
				else if (id->eide_pio_modes & 2) max_pio = 4;
				else max_pio = 3;
				ds_time = id->eide_pio_iordy;
			} else {
				ds_time = id->eide_pio;
			}
			if (ds_time == 0)
				ds_time = pio_timings[max_pio].ds_time;
		}

		/*
		 * Conservative "downgrade"
		 */
		if (max_pio < 4 && max_pio != 0) {
			max_pio -= 1;
			ds_time = pio_timings[max_pio].ds_time;		
		}
	}
	mc_time = pio_timings[max_pio].mc_time;
	av_time = pio_timings[max_pio].av_time;
	cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
				interface_number*2 + drive_number);
	set_pio_mode(interface_number, drive_number, max_pio);
	cmd640_set_timing(interface_number, drive_number);

	/*
	 * Disable (or set) readahead mode
	 */

	readahead = 0;
	if (cmd640_chip_version > 1) {	/* Mmmm.. probably should be > 2 ?? */
		readahead = known_drive_readahead(id->model);
		if (readahead == -1)
	        	readahead = 1;	/* Mmmm.. probably be 0 ?? */
		set_readahead_mode(readahead, interface_number, drive_number);
	}   

	printk ("Mode and Timing set to PIO%d, Readahead is %s\n", 
		max_pio, readahead ? "enabled" : "disabled");
}