
The following patch adds the ability to call-out from the ide_ident routine to a board-specific routine to set the PIO mode of an attached device.
This feature is controlled by the preprocessor variable CONFIG_TUNE_CFA.
cmd_ide.c is modified to use the "drive identify information" read from the device to compute a pio mode in the range 0 to 6. This is then passed to a board-specific routine, ide_set_piomode, to set the mode in hardware.
Two other files are touched: file ata.h, to include word 163, which is the "advanced CF parameters", and file ide.h, to add a prototype for the board-specific routine (again controlled by the CONFIG_TUNE_CFA variable).
Please let me know if this or some variation on the idea would be acceptible.
Steve
diff --git a/common/cmd_ide.c b/common/cmd_ide.c index b4d9719..00b85db 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -1054,6 +1054,10 @@ static void ide_ident (block_dev_desc_t *dev_desc) int do_retry = 0; #endif
+#ifdef CONFIG_TUNE_CFA + int pio_mode; +#endif + #if 0 int mode, cycle_time; #endif @@ -1169,6 +1173,40 @@ static void ide_ident (block_dev_desc_t *dev_desc) else dev_desc->removable = 0;
+#ifdef CONFIG_TUNE_CFA + /* Mode 0 - 2 only, are directly determined by word 51. */ + pio_mode = iop->tPIO; + if(pio_mode > 2) { + printf("WARNING: Invalid PIO (word 51 = %d).\n", pio_mode); + pio_mode = 0; /* Force it to dead slow, and hope for the best... */ + } + + /* Any CompactFlash Storage Card that supports PIO mode 3 or above + * shall set bit 1 of word 53 to one and support the fields contained + * in words 64 through 70. + */ + if(iop->field_valid & 0x02) { + /* Mode 3 and above are possible. Check in order from slow + * to fast, so we wind up with the highest mode allowed. + */ + if(iop->eide_pio_modes & 0x01) { + pio_mode = 3; + } + if(iop->eide_pio_modes & 0x02) { + pio_mode = 4; + } + if((iop->cf_advanced_caps & 0x07) == 0x01) { + pio_mode = 5; + } + if((iop->cf_advanced_caps & 0x07) == 0x02) { + pio_mode = 6; + } + } + + /* System-specific, depends on bus speeds, etc. */ + ide_set_piomode(pio_mode); +#endif /* CONFIG_TUNE_CFA */ + #if 0 /* * Drive PIO mode autoselection diff --git a/include/ata.h b/include/ata.h index aa6e90d..3269636 100644 --- a/include/ata.h +++ b/include/ata.h @@ -294,7 +294,9 @@ typedef struct hd_driveid { unsigned short words130_155[26];/* reserved vendor words 130-155 */ unsigned short word156; unsigned short words157_159[3];/* reserved vendor words 157-159 */ - unsigned short words160_255[95];/* reserved words 160-255 */ + unsigned short words160_162[3];/* reserved words 160-162 */ + unsigned short cf_advanced_caps; + unsigned short words164_255[92];/* reserved words 164-255 */ } hd_driveid_t;
diff --git a/include/ide.h b/include/ide.h index 222f4f8..ae4624b 100644 --- a/include/ide.h +++ b/include/ide.h @@ -54,4 +54,9 @@ void ide_init(void); ulong ide_read(int device, lbaint_t blknr, ulong blkcnt, void *buffer); ulong ide_write(int device, lbaint_t blknr, ulong blkcnt, void *buffer);
+#ifdef CONFIG_TUNE_CFA +/* Returns 0 on success, else returns 1. pio_mode can be 0 through 6. */ +extern int ide_set_piomode(int pio_mode); +#endif + #endif /* _IDE_H */