From 36c2d3062ecc6ab85f8e237180eb134464c48418 Mon Sep 17 00:00:00 2001 From: "Steven A. Falco" Date: Fri, 15 Aug 2008 15:34:10 -0400 Subject: Add a hook to allow board-specific PIO mode setting. This patch adds a hook whereby a board-specific routine can be called to configure hardware for a PIO mode. The prototype for the board-specific routine is: int inline ide_set_piomode(int pio_mode) ide_set_piomode should be prepared to configure hardware for a pio_mode between 0 and 6, inclusive. It should return 0 on success or 1 on failure. Signed-off-by: Steven A. Falco diff --git a/common/cmd_ide.c b/common/cmd_ide.c index d6ba79f..0691007 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -543,6 +543,16 @@ __ide_inb(int dev, int port) unsigned char inline ide_inb(int dev, int port) __attribute__((weak, alias("__ide_inb"))); +#ifdef CONFIG_TUNE_PIO +int inline +__ide_set_piomode(int pio_mode) +{ + return 0; +} +int inline ide_set_piomode(int pio_mode) + __attribute__((weak, alias("__ide_set_piomode"))); +#endif + void ide_init (void) { @@ -1053,6 +1063,10 @@ static void ide_ident (block_dev_desc_t *dev_desc) int do_retry = 0; #endif +#ifdef CONFIG_TUNE_PIO + int pio_mode; +#endif + #if 0 int mode, cycle_time; #endif @@ -1168,6 +1182,38 @@ static void ide_ident (block_dev_desc_t *dev_desc) else dev_desc->removable = 0; +#ifdef CONFIG_TUNE_PIO + /* 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 (ata_id_is_cfa((u16 *)iop)) { + 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_PIO */ + #if 0 /* * Drive PIO mode autoselection diff --git a/include/ata.h b/include/ata.h index b669423..2396769 100644 --- a/include/ata.h +++ b/include/ata.h @@ -236,7 +236,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; -- cgit v0.10.2