All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] About PCI of U-BOOT of CANYONLANDS
@ 2009-03-17 13:08 Kazuaki Ichinohe
  2009-03-17 13:13 ` Stefan Roese
  2009-03-24  5:22 ` [U-Boot] [PATCH] Canyonlands SATA harddisk driver Kazuaki Ichinohe
  0 siblings, 2 replies; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-17 13:08 UTC (permalink / raw)
  To: u-boot

Hello!

I am testing the video display of U-BOOT by using PCI of CANYONLANDS.
I added the following lines.

#ifdef CONFIG_VIDEO
#define CONFIG_BIOSEMU
#define CONFIG_ATI_RADEON_FB
#define VIDEO_IO_OFFSET		0xD8000000
#define CONFIG_SYS_ISA_IO_BASE_ADDRESS	VIDEO_IO_OFFSET
#define CONFIG_VIDEO_SW_CURSOR
#define CONFIG_VIDEO_LOGO
#define CONFIG_CFB_CONSOLE
#define CONFIG_SPLASH_SCREEN
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_CMD_BMP
#endif /* #ifdef CONFIG_VIDEO */

However, if the memory space of PCI is read, the exception is generated.
Do you have any information for PCI of U-BOOT of CANYONLANDS?

Regards,
Kazuaki Ichinohe.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-17 13:08 [U-Boot] About PCI of U-BOOT of CANYONLANDS Kazuaki Ichinohe
@ 2009-03-17 13:13 ` Stefan Roese
  2009-03-18  1:28   ` Kazuaki Ichinohe
  2009-03-24  5:22 ` [U-Boot] [PATCH] Canyonlands SATA harddisk driver Kazuaki Ichinohe
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2009-03-17 13:13 UTC (permalink / raw)
  To: u-boot

On Tuesday 17 March 2009, Kazuaki Ichinohe wrote:
> I am testing the video display of U-BOOT by using PCI of CANYONLANDS.
> I added the following lines.
>
> #ifdef CONFIG_VIDEO
> #define CONFIG_BIOSEMU
> #define CONFIG_ATI_RADEON_FB
> #define VIDEO_IO_OFFSET		0xD8000000
> #define CONFIG_SYS_ISA_IO_BASE_ADDRESS	VIDEO_IO_OFFSET
> #define CONFIG_VIDEO_SW_CURSOR
> #define CONFIG_VIDEO_LOGO
> #define CONFIG_CFB_CONSOLE
> #define CONFIG_SPLASH_SCREEN
> #define CONFIG_VGA_AS_SINGLE_DEVICE
> #define CONFIG_CMD_BMP
> #endif /* #ifdef CONFIG_VIDEO */
>
> However, if the memory space of PCI is read, the exception is generated.
> Do you have any information for PCI of U-BOOT of CANYONLANDS?

PCI should be working on Canyonlands. At least it was the last time I tested. 
I never tested with an PCI Video card though.

Which U-Boot version are you using? What's the exact error message? Please 
post the complete bootlog.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-17 13:13 ` Stefan Roese
@ 2009-03-18  1:28   ` Kazuaki Ichinohe
  2009-03-18  9:07     ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-18  1:28 UTC (permalink / raw)
  To: u-boot

Hello,

Thank you for the reply.

U-boot version: u-boot-2009.01
boot log is the following.

U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)

?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 38 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
Machine Check Exception.
Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR: 
7060002
7
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 08000080 1FE3AD20 1FE3AF20 00000000 80003018 00000018 1FE401BC 
15A30439
GPR08: 1FF43408 88000000 05F5E101 1FF94E10 00000006 FDFFFFFF 1FFABD00 
1FFBF000
GPR16: FBFFFFFF FDFFFFFF DFFFFFFF FFFFFBFF FFFFFFFF FFFFFFFF FFFFFFFF 
FFFFFFFF
GPR24: FFFFFFFF 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFADF20 
1FE40198
Call backtrace:
1FF82AE8 1FF83458 1FF82498 1FF5FCDC 1FF42EF0 1FF41710 1E29AB51
machine check


U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)

?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 38 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
Machine Check Exception.
Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR: 
7060002
7
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 08000080 1FE3AD20 1FE3AF20 00000000 80003018 00000018 1FE401BC 
15AC08AD
GPR08: 1FF43408 88000000 05F5E101 1FF94E10 00000006 FDFFFFFF 1FFABD00 
1FFBF000
GPR16: FBFFFFFF FDFFFFFF DFFFFFFF FFFFFBFF 00000000 1FE3AC20 00000000 
1FF41450
GPR24: 1FF41D34 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFADF20 
1FE40198
Call backtrace:
1FF82AE8 1FF83458 1FF82498 1FF5FCDC 1FF42EF0 1FF41710 1E29AB51
machine check


U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)

?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 38 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
Machine Check Exception.
Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR: 
7060002
7
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 08000080 1FE3AD20 1FE3AF20 00000000 80003018 00000018 1FE401BC 
15A680AD
GPR08: 1FF43408 88000000 05F5E101 1FF94E10 00000006 FDFFFFFF 1FFABD00 
1FFBF000
GPR16: FBFFFFFF FDFFFFFF DFFFFFFF FFFFFBFF 00000000 1FE3AC20 00000000 
1FF41450
GPR24: 1FF41D34 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFADF20 
1FE40198
Call backtrace:
1FF82AE8 1FF83458 1FF82498 1FF5FCDC 1FF42EF0 1FF41710 1E29AB51
machine check


U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)

?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 38 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
Machine Check Exception.
Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR: 
7060002
7
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 08000080 1FE3AD20 1FE3AF20 00000000 80003018 00000018 1FE401BC 
15AC57B8
GPR08: 1FF43408 88000000 05F5E101 1FF94E10 00000006 FDFFFFFF 1FFABD00 
1FFBF000
GPR16: FBFFFFFF FDFFFFFF DFFFFFFF FFFFFBFF 00000000 1FE3AC20 00000000 
1FF41450
GPR24: 1FF41D34 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFADF20 
1FE40198
Call backtrace:
1FF82AE8 1FF83458 1FF82498 1FF5FCDC 1FF42EF0 1FF41710 1E29AB51
machine check


U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)

?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 38 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)

-----------------------------------------------------
The patch is appended.

diff -crN u-boot-2009.01/Makefile u-boot-2009.01-canyonlands/Makefile
*** u-boot-2009.01/Makefile	2009-01-26 10:35:44.000000000 +0900
--- u-boot-2009.01-canyonlands/Makefile	2009-01-26 11:08:19.000000000 +0900
***************
*** 148,154 ****
   CROSS_COMPILE =
   else
   ifeq ($(ARCH),ppc)
! CROSS_COMPILE = ppc_8xx-
   endif
   ifeq ($(ARCH),arm)
   CROSS_COMPILE = arm-linux-
--- 148,154 ----
   CROSS_COMPILE =
   else
   ifeq ($(ARCH),ppc)
! CROSS_COMPILE = ppc_4xxFP-
   endif
   ifeq ($(ARCH),arm)
   CROSS_COMPILE = arm-linux-
diff -crN u-boot-2009.01/board/amcc/canyonlands/config.mk 
u-boot-2009.01-canyonlands/board/amcc/canyonlands/config.mk
*** u-boot-2009.01/board/amcc/canyonlands/config.mk	2009-01-26 
10:35:50.000000000 +0900
--- u-boot-2009.01-canyonlands/board/amcc/canyonlands/config.mk 
2009-01-26 11:08:19.000000000 +0900
***************
*** 27,33 ****
   sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp

   ifndef TEXT_BASE
! TEXT_BASE = 0xFFFA0000
   endif

   PLATFORM_CPPFLAGS += -DCONFIG_440=1
--- 27,34 ----
   sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp

   ifndef TEXT_BASE
! #TEXT_BASE = 0xFFFA0000
! TEXT_BASE = 0xFFF80000
   endif

   PLATFORM_CPPFLAGS += -DCONFIG_440=1
diff -crN u-boot-2009.01/include/configs/amcc-common.h 
u-boot-2009.01-canyonlands/include/configs/amcc-common.h
*** u-boot-2009.01/include/configs/amcc-common.h	2009-01-26 
10:35:52.000000000 +0900
--- u-boot-2009.01-canyonlands/include/configs/amcc-common.h	2009-01-26 
11:08:19.000000000 +0900
***************
*** 233,238 ****
--- 233,278 ----
   	"fdt_file=" xstr(CONFIG_HOSTNAME) "/" xstr(CONFIG_HOSTNAME) ".dtb\0"

+ #define CONFIG_AMCC_DEF_ENV_AZBIL					\
+ 	"rootfs=/dev/sda6\0"						\
+ 	"eldk-rootfs=/dev/sda7\0"						\
+ 	"e2drv=0:2\0"							\
+ 	"udrv=0:3\0"							\
+ 	"atargs=setenv bootargs root=${rootfs} rw\0"			\
+ 	"ata_old=run atargs addtty addmisc;"				\
+ 		" disk ${kernel_addr_r} ${udrv};"			\
+ 		" bootm ${kernel_addr_r}\0"				\
+ 	"ata_ud_e2=run atargs addtty addmisc;"				\
+ 		" ext2load ide ${e2drv} ${kernel_addr_r} /${bootfile};"	\
+ 		" ext2load ide ${e2drv} ${fdt_addr_r} /${fdt_file};"	\
+ 		" fdt addr ${fdt_addr_r} 0x4000;"			\
+ 		" bootm ${kernel_addr_r} - ${fdt_addr_r}\0"		\
+ 	"ata_cu=run atargs addtty addmisc;"				\
+ 		" disk ${kernel_addr_cu} ${udrv};"			\
+ 		" bootm ${kernel_addr_cu}\0"				\
+ 	"ata_cu_e2=run atargs addtty addmisc;"				\
+ 		" ext2load ide ${e2drv} ${kernel_addr_cu} /${bootfile-cu};"	\
+ 		" bootm ${kernel_addr_cu}\0"				\
+ 	"cfargs=setenv bootargs root=${rootfs} rw\0"			\
+ 	"cfboot=run cfargs addtty addmisc;"				\
+ 		" disk ${kernel_addr_r} ${udrv};"			\
+ 		" bootm ${kernel_addr_r}\0"                             \
+ 	"satargs=setenv bootargs root=${rootfs} rw\0"			\
+ 	"flash_sata=run satargs addtty addmisc;"			\
+ 		"bootm ${kernel_addr} - ${fdt_addr}\0"			\
+ 	"eldkargs=setenv bootargs root=${eldk-rootfs} rw\0"			\
+ 	"eldk_boot=run eldkargs addtty addmisc;"				\
+ 		" ext2load ide ${e2drv} ${kernel_addr_r} /${bootfile};"	\
+ 		" ext2load ide ${e2drv} ${fdt_addr_r} /${fdt_file};"	\
+ 		" fdt addr ${fdt_addr_r} 0x4000;"			\
+ 		" bootm ${kernel_addr_r} - ${fdt_addr_r}\0"		\
+ 	"eldk_flash_sata=run eldkargs addtty addmisc;"			\
+ 		"bootm ${kernel_addr} - ${fdt_addr}\0"
+
+ /*
    * Default environment for arch/ppc booting,
    * for boards that are not ported to arch/powerpc yet
    */
***************
*** 259,264 ****
--- 299,314 ----
   		"bootm ${kernel_addr_r}\0"

   #define CONFIG_AMCC_DEF_ENV_NOR_UPD					\
+ 	"fload=tftp 200000 ${fdt_file}\0"	\
+ 	"fupdate=protect off all;"	\
+ 		"era 0xFC300000 0xFC31FFFF;"		\
+ 		"cp.b 0x200000 0xFC300000 0x20000\0" \
+ 	"fupd=run fload fupdate\0"						\
+ 	"kload=tftp 200000 " xstr(CONFIG_HOSTNAME) "/uImage\0"	\
+ 	"kupdate=protect off all;"	\
+ 		"era 0xFC000000 0xFC2FFFFF;"		\
+ 		"cp.b 0x200000 0xFC000000 0x300000\0" \
+ 	"kupd=run kload kupdate\0"						\
   	"load=tftp 200000 " xstr(CONFIG_HOSTNAME) "/u-boot.bin\0"	\
   	"update=protect off " xstr(CONFIG_SYS_MONITOR_BASE) " FFFFFFFF;"	\
   		"era " xstr(CONFIG_SYS_MONITOR_BASE) " FFFFFFFF;"		\
diff -crN u-boot-2009.01/include/configs/canyonlands.h 
u-boot-2009.01-canyonlands/include/configs/canyonlands.h
*** u-boot-2009.01/include/configs/canyonlands.h	2009-01-26 
10:35:53.000000000 +0900
--- u-boot-2009.01-canyonlands/include/configs/canyonlands.h	2009-03-18 
09:37:02.000000000 +0900
***************
*** 413,426 ****
    * Default environment variables
    */
   #if !defined(CONFIG_ARCHES)
   #define CONFIG_EXTRA_ENV_SETTINGS					\
   	CONFIG_AMCC_DEF_ENV						\
   	CONFIG_AMCC_DEF_ENV_POWERPC					\
   	CONFIG_AMCC_DEF_ENV_NOR_UPD					\
   	CONFIG_AMCC_DEF_ENV_NAND_UPD					\
   	"kernel_addr=fc000000\0"					\
! 	"fdt_addr=fc1e0000\0"						\
! 	"ramdisk_addr=fc200000\0"					\
   	"pciconfighost=1\0"						\
   	"pcie_mode=RP:RP\0"						\
   	""
--- 413,434 ----
    * Default environment variables
    */
   #if !defined(CONFIG_ARCHES)
+ #define CONFIG_ENV_OVERWRITE
+ #define CONFIG_ETHADDR			00:10:EC:00:FC:A3
+ #define CONFIG_ETH1ADDR			00:10:EC:80:FC:A3
+ #define CONFIG_IPADDR			10.10.67.40
+ #define CONFIG_SERVERIP			10.10.66.208
+ #define CONFIG_NETMASK			255.255.255.0
+ #define CONFIG_GATEWAYIP		10.10.67.1
   #define CONFIG_EXTRA_ENV_SETTINGS					\
   	CONFIG_AMCC_DEF_ENV						\
   	CONFIG_AMCC_DEF_ENV_POWERPC					\
+ 	CONFIG_AMCC_DEF_ENV_AZBIL					\
   	CONFIG_AMCC_DEF_ENV_NOR_UPD					\
   	CONFIG_AMCC_DEF_ENV_NAND_UPD					\
   	"kernel_addr=fc000000\0"					\
! 	"fdt_addr=fc300000\0"						\
! 	"ramdisk_addr=fc320000\0"					\
   	"pciconfighost=1\0"						\
   	"pcie_mode=RP:RP\0"						\
   	""
***************
*** 733,736 ****
--- 741,759 ----
   }
   #endif

+ #define CONFIG_VIDEO
+
+ #ifdef CONFIG_VIDEO
+ #define CONFIG_BIOSEMU
+ #define CONFIG_ATI_RADEON_FB
+ #define VIDEO_IO_OFFSET		0xD8000000
+ #define CONFIG_SYS_ISA_IO_BASE_ADDRESS	VIDEO_IO_OFFSET
+ #define CONFIG_VIDEO_SW_CURSOR
+ #define CONFIG_VIDEO_LOGO
+ #define CONFIG_CFB_CONSOLE
+ #define CONFIG_SPLASH_SCREEN
+ #define CONFIG_VGA_AS_SINGLE_DEVICE
+ #define CONFIG_CMD_BMP
+ #endif /* #ifdef CONFIG_VIDEO */
+
   #endif	/* __CONFIG_H */


Stefan Roese ????????:
> On Tuesday 17 March 2009, Kazuaki Ichinohe wrote:
>> I am testing the video display of U-BOOT by using PCI of CANYONLANDS.
>> I added the following lines.
>>
>> #ifdef CONFIG_VIDEO
>> #define CONFIG_BIOSEMU
>> #define CONFIG_ATI_RADEON_FB
>> #define VIDEO_IO_OFFSET		0xD8000000
>> #define CONFIG_SYS_ISA_IO_BASE_ADDRESS	VIDEO_IO_OFFSET
>> #define CONFIG_VIDEO_SW_CURSOR
>> #define CONFIG_VIDEO_LOGO
>> #define CONFIG_CFB_CONSOLE
>> #define CONFIG_SPLASH_SCREEN
>> #define CONFIG_VGA_AS_SINGLE_DEVICE
>> #define CONFIG_CMD_BMP
>> #endif /* #ifdef CONFIG_VIDEO */
>>
>> However, if the memory space of PCI is read, the exception is generated.
>> Do you have any information for PCI of U-BOOT of CANYONLANDS?
> 
> PCI should be working on Canyonlands. At least it was the last time I tested. 
> I never tested with an PCI Video card though.
> 
> Which U-Boot version are you using? What's the exact error message? Please 
> post the complete bootlog.
> 
> Best regards,
> Stefan
> 
> =====================================================================
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
> =====================================================================
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18  1:28   ` Kazuaki Ichinohe
@ 2009-03-18  9:07     ` Stefan Roese
  2009-03-18  9:13       ` Felix Radensky
  2009-03-18 12:03       ` Anatolij Gustschin
  0 siblings, 2 replies; 36+ messages in thread
From: Stefan Roese @ 2009-03-18  9:07 UTC (permalink / raw)
  To: u-boot

On Wednesday 18 March 2009, Kazuaki Ichinohe wrote:
> U-boot version: u-boot-2009.01
> boot log is the following.
>
> U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)
>
> ?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
>         Security/Kasumi support
>         Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>         Internal PCI arbiter disabled
>         32 kB I-Cache 32 kB D-Cache
> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
> I2C:   ready
> DTT:   1 is 38 C
> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
> FLASH: 64 MB
> NAND:  128 MiB
> PCI:   Bus Dev VenId DevId Class Int
>          00  06  1002  5960  0300  ff
>          00  06  1002  5940  0380  ff
> PCIE1: link is not up.
> PCIE1: initialization as root-complex failed
> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
> Machine Check Exception.
> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR:
> 70600027
> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

Anatolij, do you have any ideas what's going wrong here?

Thanks.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18  9:07     ` Stefan Roese
@ 2009-03-18  9:13       ` Felix Radensky
  2009-03-18  9:23         ` Stefan Roese
  2009-03-18 12:03       ` Anatolij Gustschin
  1 sibling, 1 reply; 36+ messages in thread
From: Felix Radensky @ 2009-03-18  9:13 UTC (permalink / raw)
  To: u-boot

Stefan Roese wrote:
> On Wednesday 18 March 2009, Kazuaki Ichinohe wrote:
>   
>> U-boot version: u-boot-2009.01
>> boot log is the following.
>>
>> U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)
>>
>> ?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
>>         Security/Kasumi support
>>         Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>>         Internal PCI arbiter disabled
>>         32 kB I-Cache 32 kB D-Cache
>> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
>> I2C:   ready
>> DTT:   1 is 38 C
>> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
>> FLASH: 64 MB
>> NAND:  128 MiB
>> PCI:   Bus Dev VenId DevId Class Int
>>          00  06  1002  5960  0300  ff
>>          00  06  1002  5940  0380  ff
>> PCIE1: link is not up.
>> PCIE1: initialization as root-complex failed
>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>> Machine Check Exception.
>> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
>> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR:
>> 70600027
>> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
>>     
>
> Anatolij, do you have any ideas what's going wrong here?
>
> Thanks.
>
>   
Looks like you have ATI cards in both PCI-E slots and also SATA
enabled. This cannot work, as SATA shares lines with x1 PCI-E
slot on Canyonlands.  Use J6 jumper to enable both PCI-E slots.

Felix.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18  9:13       ` Felix Radensky
@ 2009-03-18  9:23         ` Stefan Roese
  2009-03-18  9:34           ` Felix Radensky
  0 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2009-03-18  9:23 UTC (permalink / raw)
  To: u-boot

On Wednesday 18 March 2009, Felix Radensky wrote:
> >> PCI:   Bus Dev VenId DevId Class Int
> >>          00  06  1002  5960  0300  ff
> >>          00  06  1002  5940  0380  ff
> >> PCIE1: link is not up.
> >> PCIE1: initialization as root-complex failed
> >> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
> >> Machine Check Exception.
> >> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
> >> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR:
> >> 70600027
> >> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
> >
> > Anatolij, do you have any ideas what's going wrong here?
> >
> > Thanks.
>
> Looks like you have ATI cards in both PCI-E slots and also SATA
> enabled. This cannot work, as SATA shares lines with x1 PCI-E
> slot on Canyonlands.  Use J6 jumper to enable both PCI-E slots.

No, it's PCI and not PCIe.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18  9:23         ` Stefan Roese
@ 2009-03-18  9:34           ` Felix Radensky
  2009-03-18  9:39             ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Felix Radensky @ 2009-03-18  9:34 UTC (permalink / raw)
  To: u-boot

Stefan Roese wrote:
> On Wednesday 18 March 2009, Felix Radensky wrote:
>   
>>>> PCI:   Bus Dev VenId DevId Class Int
>>>>          00  06  1002  5960  0300  ff
>>>>          00  06  1002  5940  0380  ff
>>>> PCIE1: link is not up.
>>>> PCIE1: initialization as root-complex failed
>>>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>>>> Machine Check Exception.
>>>> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
>>>> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR:
>>>> 70600027
>>>> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
>>>>         
>>> Anatolij, do you have any ideas what's going wrong here?
>>>
>>> Thanks.
>>>       
>> Looks like you have ATI cards in both PCI-E slots and also SATA
>> enabled. This cannot work, as SATA shares lines with x1 PCI-E
>> slot on Canyonlands.  Use J6 jumper to enable both PCI-E slots.
>>     
>
> No, it's PCI and not PCIe.
>
> Best regards,
> Stefan
>
>   

I see. Sorry for the noise. I was confused by the presence of two devices,
and the fact that there's only one PCI slot on this board. It should be a
multifunction PCI device then.

Felix.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18  9:34           ` Felix Radensky
@ 2009-03-18  9:39             ` Stefan Roese
  0 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2009-03-18  9:39 UTC (permalink / raw)
  To: u-boot

On Wednesday 18 March 2009, Felix Radensky wrote:
> >> Looks like you have ATI cards in both PCI-E slots and also SATA
> >> enabled. This cannot work, as SATA shares lines with x1 PCI-E
> >> slot on Canyonlands.  Use J6 jumper to enable both PCI-E slots.
> >
> > No, it's PCI and not PCIe.
> >
> > Best regards,
> > Stefan
>
> I see. Sorry for the noise. I was confused by the presence of two devices,
> and the fact that there's only one PCI slot on this board. It should be a
> multifunction PCI device then.

Yep. :)

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18  9:07     ` Stefan Roese
  2009-03-18  9:13       ` Felix Radensky
@ 2009-03-18 12:03       ` Anatolij Gustschin
  2009-03-18 12:07         ` Kazuaki Ichinohe
  1 sibling, 1 reply; 36+ messages in thread
From: Anatolij Gustschin @ 2009-03-18 12:03 UTC (permalink / raw)
  To: u-boot

Hi Stefan, Kazuaki,

Stefan Roese wrote:
> On Wednesday 18 March 2009, Kazuaki Ichinohe wrote:
>> U-boot version: u-boot-2009.01
>> boot log is the following.
>>
>> U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)
>>
>> ?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
>>         Security/Kasumi support
>>         Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>>         Internal PCI arbiter disabled
>>         32 kB I-Cache 32 kB D-Cache
>> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
>> I2C:   ready
>> DTT:   1 is 38 C
>> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
>> FLASH: 64 MB
>> NAND:  128 MiB
>> PCI:   Bus Dev VenId DevId Class Int
>>          00  06  1002  5960  0300  ff
>>          00  06  1002  5940  0380  ff
>> PCIE1: link is not up.
>> PCIE1: initialization as root-complex failed
>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>> Machine Check Exception.
>> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
>> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR:
>> 70600027
>> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
> 
> Anatolij, do you have any ideas what's going wrong here?

one issue is incorrect VIDEO_IO_OFFSET in the board config file, it
should be 0xD0800000 instead of 0xD8000000, i think.

Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
test again?

Best regards,
Anatolij

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18 12:03       ` Anatolij Gustschin
@ 2009-03-18 12:07         ` Kazuaki Ichinohe
  2009-03-18 12:29           ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-18 12:07 UTC (permalink / raw)
  To: u-boot

Hi Anatolij !

 > Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
 > test again?

I'll try it.

Regards,
Kazuaki Ichinohe.

Anatolij Gustschin ????????:
> Hi Stefan, Kazuaki,
> 
> Stefan Roese wrote:
>> On Wednesday 18 March 2009, Kazuaki Ichinohe wrote:
>>> U-boot version: u-boot-2009.01
>>> boot log is the following.
>>>
>>> U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)
>>>
>>> ?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, EBC=100 MHz)
>>>         Security/Kasumi support
>>>         Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>>>         Internal PCI arbiter disabled
>>>         32 kB I-Cache 32 kB D-Cache
>>> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
>>> I2C:   ready
>>> DTT:   1 is 38 C
>>> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
>>> FLASH: 64 MB
>>> NAND:  128 MiB
>>> PCI:   Bus Dev VenId DevId Class Int
>>>          00  06  1002  5960  0300  ff
>>>          00  06  1002  5940  0380  ff
>>> PCIE1: link is not up.
>>> PCIE1: initialization as root-complex failed
>>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>>> Machine Check Exception.
>>> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
>>> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR:
>>> 70600027
>>> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
>> Anatolij, do you have any ideas what's going wrong here?
> 
> one issue is incorrect VIDEO_IO_OFFSET in the board config file, it
> should be 0xD0800000 instead of 0xD8000000, i think.
> 
> Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
> test again?
> 
> Best regards,
> Anatolij
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18 12:07         ` Kazuaki Ichinohe
@ 2009-03-18 12:29           ` Kazuaki Ichinohe
  2009-03-18 13:00             ` Kazuaki Ichinohe
       [not found]             ` <49C0EFB2.9020800@fsi.co.jp>
  0 siblings, 2 replies; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-18 12:29 UTC (permalink / raw)
  To: u-boot

Hi Anatolij, Stefan,

The exception was generated.

----------------------------------
U-Boot 2009.01 ( 3? 18 2009 - 21:16:24)

CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 39 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
Machine Check Exception.
Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR: 
00000000
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 08000080 1FE3AD20 1FE3AF20 00000000 80003018 00000018 1FE401BC 
1CA13040
GPR08: 1FF43408 88000000 05F5E101 1FF94E10 00000006 055671DE 1FFABD00 
1FFBF000
GPR16: FFFE21E8 FFFE21E8 FFFE2068 FFFE21E8 FFFE21E8 FFFE2068 FFFE2068 
FFFD572C
GPR24: E3000D80 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFADF20 
1FE40198
Call backtrace:
1FF82AE8 1FF83458 1FF82498 1FF5FCDC 1FF42EF0 1FF41710
machine check


Regards,
Kazuaki Ichinohe


Kazuaki Ichinohe ????????:
> Hi Anatolij !
> 
>  > Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
>  > test again?
> 
> I'll try it.
> 
> Regards,
> Kazuaki Ichinohe.
> 
> Anatolij Gustschin ????????:
>> Hi Stefan, Kazuaki,
>>
>> Stefan Roese wrote:
>>> On Wednesday 18 March 2009, Kazuaki Ichinohe wrote:
>>>> U-boot version: u-boot-2009.01
>>>> boot log is the following.
>>>>
>>>> U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)
>>>>
>>>> ?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, 
>>>> EBC=100 MHz)
>>>>         Security/Kasumi support
>>>>         Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>>>>         Internal PCI arbiter disabled
>>>>         32 kB I-Cache 32 kB D-Cache
>>>> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, 
>>>> Rev. 14
>>>> I2C:   ready
>>>> DTT:   1 is 38 C
>>>> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
>>>> FLASH: 64 MB
>>>> NAND:  128 MiB
>>>> PCI:   Bus Dev VenId DevId Class Int
>>>>          00  06  1002  5960  0300  ff
>>>>          00  06  1002  5940  0380  ff
>>>> PCIE1: link is not up.
>>>> PCIE1: initialization as root-complex failed
>>>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>>>> Machine Check Exception.
>>>> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
>>>> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 
>>>> DEAR:
>>>> 70600027
>>>> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
>>> Anatolij, do you have any ideas what's going wrong here?
>>
>> one issue is incorrect VIDEO_IO_OFFSET in the board config file, it
>> should be 0xD0800000 instead of 0xD8000000, i think.
>>
>> Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
>> test again?
>>
>> Best regards,
>> Anatolij
>>
> 
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18 12:29           ` Kazuaki Ichinohe
@ 2009-03-18 13:00             ` Kazuaki Ichinohe
       [not found]             ` <49C0EFB2.9020800@fsi.co.jp>
  1 sibling, 0 replies; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-18 13:00 UTC (permalink / raw)
  To: u-boot

Hi Anatolij, Stefan,

The memory space is displayed in BAR2 of the PCI configuration space.
The video driver accesses this memory space and the exception is generated.

  driver source: u-boot/drivers/video/ati_radeon_fb.c
  function name: void *video_hw_init(void)
  line         : 760line

I attach the log where the exception is generated.
I confirmed it by the source of the following patches.

----- patch ------
#undef CONFIG_VIDEO
#ifdef CONFIG_VIDEO
#define CONFIG_BIOSEMU
#define CONFIG_ATI_RADEON_FB
#define VIDEO_IO_OFFSET        0xD8000000
#define CONFIG_SYS_ISA_IO_BASE_ADDRESS    VIDEO_IO_OFFSET
#define CONFIG_VIDEO_SW_CURSOR
#define CONFIG_VIDEO_LOGO
#define CONFIG_CFB_CONSOLE
#define CONFIG_SPLASH_SCREEN
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_CMD_BMP
#endif /* #ifdef CONFIG_VIDEO */

----- exception log --------
U-Boot 2009.01 ( 3? 18 2009 - 18:52:14)

CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 39 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Net:   ppc_4xx_eth0, ppc_4xx_eth1

Type run flash_nfs to mount root filesystem over NFS

=> pci
Scanning PCI devices on bus 0
BusDevFun  VendorId   DeviceId   Device Class       Sub-Class
_____________________________________________________________
00.06.00   0x1002     0x5960     Display controller      0x00
00.06.01   0x1002     0x5940     Display controller      0x80
=> pci header 0.6.0
   vendor ID =                   0x1002
   device ID =                   0x5960
   command register =            0x0007
   status register =             0x02b0
   revision ID =                 0x01
   class code =                  0x03 (Display controller)
   sub class code =              0x00
   programming interface =       0x00
   cache line =                  0x08
   latency time =                0x80
   header type =                 0x80
   BIST =                        0x00
   base address 0 =              0x80000008
   base address 1 =              0x00001001
   base address 2 =              0x88000000
   base address 3 =              0x00000000
   base address 4 =              0x00000000
   base address 5 =              0x00000000
   cardBus CIS pointer =         0x00000000
   sub system vendor ID =        0x18bc
   sub system ID =               0x0580
   expansion ROM base address =  0x00000000
   interrupt line =              0xff
   interrupt pin =               0x01
   min Grant =                   0x08
   max Latency =                 0x00
=> md 0x88000000
88000000:Machine Check Exception.
Caused by (from msr): regs 1fe51c08 Data Read PLB Error
NIP: 1FF859DC XER: 00000000 LR: 1FF859AC REGS: 1fe51c08 TRAP: 0200 DEAR: 
00000000
MSR: 00029000 EE: 1 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 1FFB2178 1FE51CF8 1FE51F24 1FFA0528 1FFB2178 00000003 00000003 
2E6C1FF4
GPR08: 1FF5A408 00000020 05F5E101 2FAF080A 00000008 055661DE 1FFB0700 
1FF9F8F4
GPR16: 1FF9F870 1FFA0530 1FFA0528 1FF9F120 1FFABC34 1FE51D00 88000000 
88000000
GPR24: 1FE51D00 00000040 00000000 00000004 1FE51D00 00000004 1FFB2178 
88000000
Call backtrace:
1FF859AC 1FF702D4 1FF7B948 1FF7B04C 1FF7B1BC 1FF7DDD0 1FF59F64
1FF58710
machine check


U-Boot 2009.01 ( 3? 18 2009 - 18:52:14)

CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 40 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Net:   ppc_4xx_eth0, ppc_4xx_eth1

Type run flash_nfs to mount root filesystem over NFS

=>


Regards,
Kazuaki Ichinohe



Kazuaki Ichinohe ????????:
> Hi Anatolij, Stefan,
> 
> The exception was generated.
> 
> ----------------------------------
> U-Boot 2009.01 ( 3? 18 2009 - 21:16:24)
> 
> CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
>        Security/Kasumi support
>        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>        Internal PCI arbiter disabled
>        32 kB I-Cache 32 kB D-Cache
> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
> I2C:   ready
> DTT:   1 is 39 C
> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
> FLASH: 64 MB
> NAND:  128 MiB
> PCI:   Bus Dev VenId DevId Class Int
>         00  06  1002  5960  0300  ff
>         00  06  1002  5940  0380  ff
> PCIE1: link is not up.
> PCIE1: initialization as root-complex failed
> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
> Machine Check Exception.
> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 DEAR: 
> 00000000
> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
> 
> GPR00: 08000080 1FE3AD20 1FE3AF20 00000000 80003018 00000018 1FE401BC 
> 1CA13040
> GPR08: 1FF43408 88000000 05F5E101 1FF94E10 00000006 055671DE 1FFABD00 
> 1FFBF000
> GPR16: FFFE21E8 FFFE21E8 FFFE2068 FFFE21E8 FFFE21E8 FFFE2068 FFFE2068 
> FFFD572C
> GPR24: E3000D80 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFADF20 
> 1FE40198
> Call backtrace:
> 1FF82AE8 1FF83458 1FF82498 1FF5FCDC 1FF42EF0 1FF41710
> machine check
> 
> 
> Regards,
> Kazuaki Ichinohe
> 
> 
> Kazuaki Ichinohe ????????:
>> Hi Anatolij !
>>
>>  > Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
>>  > test again?
>>
>> I'll try it.
>>
>> Regards,
>> Kazuaki Ichinohe.
>>
>> Anatolij Gustschin ????????:
>>> Hi Stefan, Kazuaki,
>>>
>>> Stefan Roese wrote:
>>>> On Wednesday 18 March 2009, Kazuaki Ichinohe wrote:
>>>>> U-boot version: u-boot-2009.01
>>>>> boot log is the following.
>>>>>
>>>>> U-Boot 2009.01 ( 3? 18 2009 - 09:38:17)
>>>>>
>>>>> ?PU:   AMCC PowerPC 460EX Rev. A at 600 MHz (PLB=200, OPB=100, 
>>>>> EBC=100 MHz)
>>>>>         Security/Kasumi support
>>>>>         Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>>>>>         Internal PCI arbiter disabled
>>>>>         32 kB I-Cache 32 kB D-Cache
>>>>> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, 
>>>>> Rev. 14
>>>>> I2C:   ready
>>>>> DTT:   1 is 38 C
>>>>> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
>>>>> FLASH: 64 MB
>>>>> NAND:  128 MiB
>>>>> PCI:   Bus Dev VenId DevId Class Int
>>>>>          00  06  1002  5960  0300  ff
>>>>>          00  06  1002  5940  0380  ff
>>>>> PCIE1: link is not up.
>>>>> PCIE1: initialization as root-complex failed
>>>>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>>>>> Machine Check Exception.
>>>>> Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
>>>>> NIP: 1FF82B10 XER: 00000000 LR: 1FF82AE8 REGS: 1fe3ac30 TRAP: 0200 
>>>>> DEAR:
>>>>> 70600027
>>>>> MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
>>>> Anatolij, do you have any ideas what's going wrong here?
>>>
>>> one issue is incorrect VIDEO_IO_OFFSET in the board config file, it
>>> should be 0xD0800000 instead of 0xD8000000, i think.
>>>
>>> Kazuaki, could you please change VIDEO_IO_OFFSET to 0xD0800000 and
>>> test again?
>>>
>>> Best regards,
>>> Anatolij
>>>
>>
>>
> 
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
       [not found]             ` <49C0EFB2.9020800@fsi.co.jp>
@ 2009-03-18 14:48               ` Anatolij Gustschin
  2009-03-19  4:43                 ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Anatolij Gustschin @ 2009-03-18 14:48 UTC (permalink / raw)
  To: u-boot

Kazuaki Ichinohe wrote:
> Hi Anatolij, Stefan,
> 
> The memory space is displayed in BAR2 of the PCI configuration space.
> The video driver accesses this memory space and the exception is generated.
> 
>  driver source: u-boot/drivers/video/ati_radeon_fb.c
>  function name: void *video_hw_init(void)
>  line         : 760line

it seems that the driver is able to access memory space (registers, e.g.
in radeon_identify_vram() ) but cannot access framebuffer?

Please replace '#undef DEBUG' in drivers/video/ati_radeon_fb.c
with '#define DEBUG' and also enable CONFIG_VIDEO and use
#define VIDEO_IO_OFFSET 0xD0800000 and post the boot log again.

Thanks!

Best regards,
Anatolij


> 
> I attach the log where the exception is generated.
> I confirmed it by the source of the following patches.
> #undef CONFIG_VIDEO
> #ifdef CONFIG_VIDEO
> #define CONFIG_BIOSEMU
> #define CONFIG_ATI_RADEON_FB
> #define VIDEO_IO_OFFSET        0xD8000000
> #define CONFIG_SYS_ISA_IO_BASE_ADDRESS    VIDEO_IO_OFFSET
> #define CONFIG_VIDEO_SW_CURSOR
> #define CONFIG_VIDEO_LOGO
> #define CONFIG_CFB_CONSOLE
> #define CONFIG_SPLASH_SCREEN
> #define CONFIG_VGA_AS_SINGLE_DEVICE
> #define CONFIG_CMD_BMP
> #endif /* #ifdef CONFIG_VIDEO */
> 
> Regards,
> Kazuaki Ichinohe
> 

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-18 14:48               ` Anatolij Gustschin
@ 2009-03-19  4:43                 ` Kazuaki Ichinohe
  2009-03-19  9:16                   ` Anatolij Gustschin
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-19  4:43 UTC (permalink / raw)
  To: u-boot

Hi Anatolij,

This is a problem that the memory space of BAR2 is inaccessible.
Even if the value of VIDEO_IO_OFFSET is changed, the problem is not solved.

It is a log that you demanded as follows.
-------------------------------------------------
U-Boot 2009.01 ( 3? 19 2009 - 11:17:08)

CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 41 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
rinfo->mmio_base = 0x88000000
Machine Check Exception.
Caused by (from msr): regs 1fe3ac30 Data Read PLB Error
NIP: 1FF82B1C XER: 00000000 LR: 1FF82B0C REGS: 1fe3ac30 TRAP: 0200 DEAR: 
00000000
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 1FF82B0C 1FE3AD20 1FE3AF20 EF600300 00000000 00000000 00000000 
1CB844A4
GPR08: 1FF43408 88000000 05F5E101 2FAF080A 00000008 055671DE 1FFABF00 
1FFBF000
GPR16: 00000023 003F0000 00000001 00000001 10000020 00000000 0000023A 
E3000CC0
GPR24: 00000001 1FE3AF20 1FE3AF08 1FE3AE88 1FE3AE80 00003000 1FFAE120 
1FE40198
Call backtrace:
1FF82B0C 1FF834A8 1FF82498 1FF5FCDC 1FF42EF0 1FF41710
machine check

Regards,
Kazuaki Ichinohe


Anatolij Gustschin ????????:
> Kazuaki Ichinohe wrote:
>> Hi Anatolij, Stefan,
>>
>> The memory space is displayed in BAR2 of the PCI configuration space.
>> The video driver accesses this memory space and the exception is generated.
>>
>>  driver source: u-boot/drivers/video/ati_radeon_fb.c
>>  function name: void *video_hw_init(void)
>>  line         : 760line
> 
> it seems that the driver is able to access memory space (registers, e.g.
> in radeon_identify_vram() ) but cannot access framebuffer?
> 
> Please replace '#undef DEBUG' in drivers/video/ati_radeon_fb.c
> with '#define DEBUG' and also enable CONFIG_VIDEO and use
> #define VIDEO_IO_OFFSET 0xD0800000 and post the boot log again.
> 
> Thanks!
> 
> Best regards,
> Anatolij
> 
> 
>> I attach the log where the exception is generated.
>> I confirmed it by the source of the following patches.
>> #undef CONFIG_VIDEO
>> #ifdef CONFIG_VIDEO
>> #define CONFIG_BIOSEMU
>> #define CONFIG_ATI_RADEON_FB
>> #define VIDEO_IO_OFFSET        0xD8000000
>> #define CONFIG_SYS_ISA_IO_BASE_ADDRESS    VIDEO_IO_OFFSET
>> #define CONFIG_VIDEO_SW_CURSOR
>> #define CONFIG_VIDEO_LOGO
>> #define CONFIG_CFB_CONSOLE
>> #define CONFIG_SPLASH_SCREEN
>> #define CONFIG_VGA_AS_SINGLE_DEVICE
>> #define CONFIG_CMD_BMP
>> #endif /* #ifdef CONFIG_VIDEO */
>>
>> Regards,
>> Kazuaki Ichinohe
>>
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19  4:43                 ` Kazuaki Ichinohe
@ 2009-03-19  9:16                   ` Anatolij Gustschin
  2009-03-19 11:28                     ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Anatolij Gustschin @ 2009-03-19  9:16 UTC (permalink / raw)
  To: u-boot

Hi Kazuaki, Stefan,

Kazuaki Ichinohe wrote:

> This is a problem that the memory space of BAR2 is inaccessible.
> Even if the value of VIDEO_IO_OFFSET is changed, the problem is not solved.
> 
> It is a log that you demanded as follows.

Thanks! Now I see this too. Previously you have mentioned that
the driver crashed in u-boot/drivers/video/ati_radeon_fb.c, line 760.
But before this, a bunch of pci register accesses should be done already.
I only wanted to make sure that the driver really crashes while first
ATI register access.

Please, try the inlined patch below and see if BAR2 memory space
works with it. Thanks!

<snip>

>>> The memory space is displayed in BAR2 of the PCI configuration space.
>>> The video driver accesses this memory space and the exception is
>>> generated.
>>>
>>>  driver source: u-boot/drivers/video/ati_radeon_fb.c
>>>  function name: void *video_hw_init(void)
>>>  line         : 760line
>>
>> it seems that the driver is able to access memory space (registers, e.g.
>> in radeon_identify_vram() ) but cannot access framebuffer?
>>
>> Please replace '#undef DEBUG' in drivers/video/ati_radeon_fb.c
>> with '#define DEBUG' and also enable CONFIG_VIDEO and use
>> #define VIDEO_IO_OFFSET 0xD0800000 and post the boot log again.
>>


diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c
index e8871fc..9639547 100644
--- a/cpu/ppc4xx/4xx_pci.c
+++ b/cpu/ppc4xx/4xx_pci.c
@@ -550,10 +550,12 @@ int pci_440_init (struct pci_controller *hose)
 	out32r( PCIX0_POM0SA, 0 ); /* disable */
 	out32r( PCIX0_POM1SA, 0 ); /* disable */
 	out32r( PCIX0_POM2SA, 0 ); /* disable */
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#if defined(CONFIG_440SPE)
 	out32r( PCIX0_POM0LAL, 0x10000000 );
 	out32r( PCIX0_POM0LAH, 0x0000000c );
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+	out32r( PCIX0_POM0LAL, 0x20000000 );
+	out32r( PCIX0_POM0LAH, 0x0000000c );
 #else
 	out32r( PCIX0_POM0LAL, 0x00000000 );
 	out32r( PCIX0_POM0LAH, 0x00000003 );


Best regards,
Anatolij

--
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19  9:16                   ` Anatolij Gustschin
@ 2009-03-19 11:28                     ` Kazuaki Ichinohe
  2009-03-19 11:44                       ` Anatolij Gustschin
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-19 11:28 UTC (permalink / raw)
  To: u-boot

Hi Anatolij, Stefan,

Thank you for the reply.
I confirmed your patch source.
However, the exception was generated.

------------------------------------------------
U-Boot 2009.01 ( 3? 19 2009 - 18:41:36)

CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
        Security/Kasumi support
        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
        Internal PCI arbiter disabled
        32 kB I-Cache 32 kB D-Cache
Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
I2C:   ready
DTT:   1 is 39 C
DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
FLASH: 64 MB
NAND:  128 MiB
PCI:   Bus Dev VenId DevId Class Int
         00  06  1002  5960  0300  ff
         00  06  1002  5940  0380  ff
PCIE1: link is not up.
PCIE1: initialization as root-complex failed
Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
rinfo->mmio_base = 0x88000000
rinfo->fb_local_base = 0x59c00000
videoboot: Booting PCI video card bus 0, function 0, device 6
Machine Check Exception.
Caused by (from msr): regs 1fe3ab50 Data Write PLB Error
NIP: 1FF859E0 XER: 00000000 LR: 1FF87848 REGS: 1fe3ab50 TRAP: 0200 DEAR: 
00000000
MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00

GPR00: 1FF87848 1FE3AC40 1FE3AF20 D0801014 0000C000 1FE3AC4C 00000000 
00000001
GPR08: 00000000 1FF8595C 000006BD 00000000 00000006 055671DE 1FFABF00 
1FFBF000
GPR16: 1FF91D3C 1FFCC999 1FE37D40 1FE37D44 00000000 00000000 1FE401E0 
1FFFF890
GPR24: 1FFAAF88 1FFA6420 1FFFFC90 1FFFFC90 1FFFFC90 00001014 1FFAE314 
0000C000
Call backtrace:
1FF860E0 1FF87848 1FF8712C 1FF84AD0 1FF84644 1FF82B44 1FF834A8
1FF82498 1FF5FCDC 1FF42EF0 1FF41710
machine check


Regards,
Kazuaki Ichinohe

Anatolij Gustschin wrote:
> Hi Kazuaki, Stefan,
> 
> Kazuaki Ichinohe wrote:
> 
>> This is a problem that the memory space of BAR2 is inaccessible.
>> Even if the value of VIDEO_IO_OFFSET is changed, the problem is not solved.
>>
>> It is a log that you demanded as follows.
> 
> Thanks! Now I see this too. Previously you have mentioned that
> the driver crashed in u-boot/drivers/video/ati_radeon_fb.c, line 760.
> But before this, a bunch of pci register accesses should be done already.
> I only wanted to make sure that the driver really crashes while first
> ATI register access.
> 
> Please, try the inlined patch below and see if BAR2 memory space
> works with it. Thanks!
> 
> <snip>
> 
>>>> The memory space is displayed in BAR2 of the PCI configuration space.
>>>> The video driver accesses this memory space and the exception is
>>>> generated.
>>>>
>>>>  driver source: u-boot/drivers/video/ati_radeon_fb.c
>>>>  function name: void *video_hw_init(void)
>>>>  line         : 760line
>>> it seems that the driver is able to access memory space (registers, e.g.
>>> in radeon_identify_vram() ) but cannot access framebuffer?
>>>
>>> Please replace '#undef DEBUG' in drivers/video/ati_radeon_fb.c
>>> with '#define DEBUG' and also enable CONFIG_VIDEO and use
>>> #define VIDEO_IO_OFFSET 0xD0800000 and post the boot log again.
>>>
> 
> 
> diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c
> index e8871fc..9639547 100644
> --- a/cpu/ppc4xx/4xx_pci.c
> +++ b/cpu/ppc4xx/4xx_pci.c
> @@ -550,10 +550,12 @@ int pci_440_init (struct pci_controller *hose)
>  	out32r( PCIX0_POM0SA, 0 ); /* disable */
>  	out32r( PCIX0_POM1SA, 0 ); /* disable */
>  	out32r( PCIX0_POM2SA, 0 ); /* disable */
> -#if defined(CONFIG_440SPE) || \
> -    defined(CONFIG_460EX) || defined(CONFIG_460GT)
> +#if defined(CONFIG_440SPE)
>  	out32r( PCIX0_POM0LAL, 0x10000000 );
>  	out32r( PCIX0_POM0LAH, 0x0000000c );
> +#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
> +	out32r( PCIX0_POM0LAL, 0x20000000 );
> +	out32r( PCIX0_POM0LAH, 0x0000000c );
>  #else
>  	out32r( PCIX0_POM0LAL, 0x00000000 );
>  	out32r( PCIX0_POM0LAH, 0x00000003 );
> 
> 
> Best regards,
> Anatolij
> 
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19 11:28                     ` Kazuaki Ichinohe
@ 2009-03-19 11:44                       ` Anatolij Gustschin
  2009-03-19 12:09                         ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Anatolij Gustschin @ 2009-03-19 11:44 UTC (permalink / raw)
  To: u-boot

Kazuaki Ichinohe wrote:
> Hi Anatolij, Stefan,
> 
> Thank you for the reply.
> I confirmed your patch source.
> However, the exception was generated.
> 
> ------------------------------------------------
> U-Boot 2009.01 ( 3? 19 2009 - 18:41:36)
> 
> CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
>        Security/Kasumi support
>        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>        Internal PCI arbiter disabled
>        32 kB I-Cache 32 kB D-Cache
> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
> I2C:   ready
> DTT:   1 is 39 C
> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
> FLASH: 64 MB
> NAND:  128 MiB
> PCI:   Bus Dev VenId DevId Class Int
>         00  06  1002  5960  0300  ff
>         00  06  1002  5940  0380  ff
> PCIE1: link is not up.
> PCIE1: initialization as root-complex failed
> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
> rinfo->mmio_base = 0x88000000
> rinfo->fb_local_base = 0x59c00000
> videoboot: Booting PCI video card bus 0, function 0, device 6
> Machine Check Exception.

Now register access to BAR2 seems to work. What was the value
of VIDEO_IO_OFFSET used with this latest test?

Best regards,
Anatolij

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19 11:44                       ` Anatolij Gustschin
@ 2009-03-19 12:09                         ` Kazuaki Ichinohe
  2009-03-19 12:27                           ` Anatolij Gustschin
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-19 12:09 UTC (permalink / raw)
  To: u-boot

 > Now register access to BAR2 seems to work. What was the value
 > of VIDEO_IO_OFFSET used with this latest test?

VIDEO_IO_OFFSET is 0xD0800000

Regards,
Kazuaki Ichinohe

Anatolij Gustschin wrote:
> Kazuaki Ichinohe wrote:
>> Hi Anatolij, Stefan,
>>
>> Thank you for the reply.
>> I confirmed your patch source.
>> However, the exception was generated.
>>
>> ------------------------------------------------
>> U-Boot 2009.01 ( 3? 19 2009 - 18:41:36)
>>
>> CPU:   AMCC PowerPC 460EX Rev. A at 800 MHz (PLB=200, OPB=100, EBC=100 MHz)
>>        Security/Kasumi support
>>        Bootstrap Option H - Boot ROM Location I2C (Addr 0x52)
>>        Internal PCI arbiter disabled
>>        32 kB I-Cache 32 kB D-Cache
>> Board: Canyonlands - AMCC PPC460EX Evaluation Board, 1*PCIe/1*SATA, Rev. 14
>> I2C:   ready
>> DTT:   1 is 39 C
>> DRAM:  512 MB (ECC not enabled, 400 MHz, CL3)
>> FLASH: 64 MB
>> NAND:  128 MiB
>> PCI:   Bus Dev VenId DevId Class Int
>>         00  06  1002  5960  0300  ff
>>         00  06  1002  5940  0380  ff
>> PCIE1: link is not up.
>> PCIE1: initialization as root-complex failed
>> Video: ATI Radeon video card (1002, 5960) found @(0:6:0)
>> rinfo->mmio_base = 0x88000000
>> rinfo->fb_local_base = 0x59c00000
>> videoboot: Booting PCI video card bus 0, function 0, device 6
>> Machine Check Exception.
> 
> Now register access to BAR2 seems to work. What was the value
> of VIDEO_IO_OFFSET used with this latest test?
> 
> Best regards,
> Anatolij
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19 12:09                         ` Kazuaki Ichinohe
@ 2009-03-19 12:27                           ` Anatolij Gustschin
  2009-03-19 12:52                             ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Anatolij Gustschin @ 2009-03-19 12:27 UTC (permalink / raw)
  To: u-boot

Kazuaki Ichinohe wrote:
>> Now register access to BAR2 seems to work. What was the value
>> of VIDEO_IO_OFFSET used with this latest test?
> 
> VIDEO_IO_OFFSET is 0xD0800000

Try to set VIDEO_IO_OFFSET to 0xD8000000, it should work. The
value of 0xD0800000 is wrong, now I see it after double-checking
the PCI/IO map in the PPC460EX manual. Sorry, my fault.

Best regards,
Anatolij

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19 12:27                           ` Anatolij Gustschin
@ 2009-03-19 12:52                             ` Kazuaki Ichinohe
  2009-03-19 13:17                               ` Anatolij Gustschin
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-19 12:52 UTC (permalink / raw)
  To: u-boot

 > Try to set VIDEO_IO_OFFSET to 0xD8000000, it should work. The
 > value of 0xD0800000 is wrong, now I see it after double-checking
 > the PCI/IO map in the PPC460EX manual. Sorry, my fault.

The PCI memory space is accessible.
However, the video output cannot be confirmed.
Why ?

Regards,
Kazuaki Ichinohe

Anatolij Gustschin ????????:
> Kazuaki Ichinohe wrote:
>>> Now register access to BAR2 seems to work. What was the value
>>> of VIDEO_IO_OFFSET used with this latest test?
>> VIDEO_IO_OFFSET is 0xD0800000
> 
> Try to set VIDEO_IO_OFFSET to 0xD8000000, it should work. The
> value of 0xD0800000 is wrong, now I see it after double-checking
> the PCI/IO map in the PPC460EX manual. Sorry, my fault.
> 
> Best regards,
> Anatolij
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19 12:52                             ` Kazuaki Ichinohe
@ 2009-03-19 13:17                               ` Anatolij Gustschin
  2009-03-20 10:50                                 ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Anatolij Gustschin @ 2009-03-19 13:17 UTC (permalink / raw)
  To: u-boot

Kazuaki Ichinohe wrote:
>> Try to set VIDEO_IO_OFFSET to 0xD8000000, it should work. The
>> value of 0xD0800000 is wrong, now I see it after double-checking
>> the PCI/IO map in the PPC460EX manual. Sorry, my fault.
> 
> The PCI memory space is accessible.
> However, the video output cannot be confirmed.
> Why ?

It is hard to guess. Does the driver recognize video RAM size
correctly? Is the video RAM accessible? You can test it using
'md 0x80000000', 'mw 0x80000000 0xaa55aa55 1', 'md 0x80000000'
commands. If the video RAM access doesn't work, than the VGA BIOS
boot failed for some reason. Does your ATI card have two display
output connectors? Are these DVI or VGA output connectors? Try to
connect the display to another VGA connector if any.

Best regards,
Anatolij

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] About PCI of U-BOOT of CANYONLANDS
  2009-03-19 13:17                               ` Anatolij Gustschin
@ 2009-03-20 10:50                                 ` Kazuaki Ichinohe
  0 siblings, 0 replies; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-20 10:50 UTC (permalink / raw)
  To: u-boot

Hi Anatolij, Stefan,

I confirmed the video output.

 >> However, the video output cannot be confirmed.
Sorry, my fault.
We wish to express our gratitude.

Regards,
Kazuaki Ichinohe

Anatolij Gustschin ????????:
> Kazuaki Ichinohe wrote:
>>> Try to set VIDEO_IO_OFFSET to 0xD8000000, it should work. The
>>> value of 0xD0800000 is wrong, now I see it after double-checking
>>> the PCI/IO map in the PPC460EX manual. Sorry, my fault.
>> The PCI memory space is accessible.
>> However, the video output cannot be confirmed.
>> Why ?
> 
> It is hard to guess. Does the driver recognize video RAM size
> correctly? Is the video RAM accessible? You can test it using
> 'md 0x80000000', 'mw 0x80000000 0xaa55aa55 1', 'md 0x80000000'
> commands. If the video RAM access doesn't work, than the VGA BIOS
> boot failed for some reason. Does your ATI card have two display
> output connectors? Are these DVI or VGA output connectors? Try to
> connect the display to another VGA connector if any.
> 
> Best regards,
> Anatolij
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-17 13:08 [U-Boot] About PCI of U-BOOT of CANYONLANDS Kazuaki Ichinohe
  2009-03-17 13:13 ` Stefan Roese
@ 2009-03-24  5:22 ` Kazuaki Ichinohe
  2009-03-24 16:22   ` Stefan Roese
  1 sibling, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-24  5:22 UTC (permalink / raw)
  To: u-boot

This patch adds a SATA harddisk driver for the canyonlands.

[environment variable, boot script]
setenv bootargs root=/dev/sda7 rw
setenv bootargs ${bootargs} console=ttyS0,115200
setenv bootargs ${bootargs} console=ttyS0,115200
ext2load scsi 0:2 0x400000 /canyonlands/uImage
ext2load scsi 0:2 0x800000 /canyonlands/canyonlands.dtb
fdt addr 0x800000 0x4000
bootm 0x400000 - 0x800000


[confirmed hard disk]
Bootable disk
(1)maker: FUJITSU , type : MODEL No.MHW2040BS
(2)maker: HAGIWARA SYSCOM , type : HFD25S-032GT
(3)maker: TOSHIBA , type : MK4032GSX

UnBootable disk
(1) maker: FUJITSU , type : MHW2060BK
(2) maker: MTRON , type : MSD-SATA3525
(3) maker: SAMSUNG , type : HD250HJ

[patch]
diff -crN u-boot-2009.03/common/cmd_scsi.c
u-boot-2009.03-sata/common/cmd_scsi.c
*** u-boot-2009.03/common/cmd_scsi.c	2009-03-22 06:04:41.000000000 +0900
--- u-boot-2009.03-sata/common/cmd_scsi.c	2009-03-23 19:24:45.000000000
+0900
***************
*** 47,54 ****
--- 47,56 ----
  #define SCSI_DEV_ID  0x5288

  #else
+ #ifndef CONFIG_SATA_DWC
  #error no scsi device defined
  #endif
+ #endif


  static ccb tempccb;	/* temporary scsi command buffer */
***************
*** 179,184 ****
--- 181,187 ----
  {
  	int busdevfunc;

+ #ifndef CONFIG_SATA_DWC
  	busdevfunc=pci_find_device(SCSI_VEND_ID,SCSI_DEV_ID,0); /* get PCI
Device ID */
  	if(busdevfunc==-1) {
  		printf("Error SCSI Controller (%04X,%04X) not
found\n",SCSI_VEND_ID,SCSI_DEV_ID);
***************
*** 189,195 ****
--- 192,204 ----
  		printf("SCSI Controller (%04X,%04X) found
(%d:%d:%d)\n",SCSI_VEND_ID,SCSI_DEV_ID,(busdevfunc>>16)&0xFF,(busdevfunc>>11)&0x1F,(busdevfunc>>8)&0x7);
  	}
  #endif
+ #endif
+ #ifdef CONFIG_SATA_DWC
+ 	sata_dwc_probe();
+ #endif
+ #ifndef CONFIG_SATA_DWC
  	scsi_low_level_init(busdevfunc);
+ #endif
  	scsi_scan(1);
  }

***************
*** 444,451 ****

/****************************************************************************************
   * scsi_read
   */
!
  #define SCSI_MAX_READ_BLK 0xFFFF /* almost the maximum amount of the
scsi_ext command.. */

  ulong scsi_read(int device, ulong blknr, ulong blkcnt, void *buffer)
  {
--- 453,463 ----

/****************************************************************************************
   * scsi_read
   */
! #if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
! #define SCSI_MAX_READ_BLK 0xFF
! #else
  #define SCSI_MAX_READ_BLK 0xFFFF /* almost the maximum amount of the
scsi_ext command.. */
+ #endif

  ulong scsi_read(int device, ulong blknr, ulong blkcnt, void *buffer)
  {
diff -crN u-boot-2009.03/drivers/block/Makefile
u-boot-2009.03-sata/drivers/block/Makefile
*** u-boot-2009.03/drivers/block/Makefile	2009-03-22 06:04:41.000000000
+0900
--- u-boot-2009.03-sata/drivers/block/Makefile	2009-03-23
19:22:31.000000000 +0900
***************
*** 34,39 ****
--- 34,40 ----
  COBJS-$(CONFIG_IDE_SIL680) += sil680.o
  COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
  COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+ COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

  COBJS	:= $(COBJS-y)
  SRCS	:= $(COBJS:.o=.c)
diff -crN u-boot-2009.03/drivers/block/sata_dwc.c
u-boot-2009.03-sata/drivers/block/sata_dwc.c
*** u-boot-2009.03/drivers/block/sata_dwc.c	1970-01-01
09:00:00.000000000 +0900
--- u-boot-2009.03-sata/drivers/block/sata_dwc.c	2009-03-23
19:22:31.000000000 +0900
***************
*** 0 ****
--- 1,2166 ----
+ /*
+  * sata_dwc.c
+  *
+  * Synopsys DesignWare Cores (DWC) SATA host driver
+  *
+  * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+  *
+  * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+  * Copyright 2008 DENX Software Engineering
+  *
+  * Based on versions provided by AMCC and Synopsys which are:
+  *          Copyright 2006 Applied Micro Circuits Corporation
+  *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+  *
+  * This program is free software; you can redistribute  it and/or
modify it
+  * under  the terms of  the GNU General  Public License as published
by the
+  * Free Software Foundation;  either version 2 of the  License, or (at
your
+  * option) any later version.
+  *
+  */
+
+ #include <common.h>
+ #include <command.h>
+ #include <pci.h>
+ #include <asm/processor.h>
+ #include <asm/errno.h>
+ #include <asm/io.h>
+ #include <malloc.h>
+ #include <scsi.h>
+ #include <ata.h>
+ #include <linux/ctype.h>
+
+ /* sata_dwc.h */
+ #include "sata_dwc.h"
+
+ /* Base Address */
+ #define SATA_BASE_ADDR		0xe20d1000
+ #define SATA_DMA_REG_ADDR	0xe20d0800
+
+ /* SATA DMA driver Globals */
+ #define DMA_NUM_CHANS			1
+ #define DMA_NUM_CHAN_REGS		8
+
+ /* SATA DMA Register definitions */
+ #define AHB_DMA_BRST_DFLT		16	/* 4 data items burst length */
+
+ struct dmareg {
+ 	u32 low;		/* Low bits 0-31 */
+ 	u32 high;		/* High bits 32-63 */
+ };
+
+ /* DMA Per Channel registers */
+ struct dma_chan_regs {
+ 	struct dmareg sar;	/* Source Address */
+ 	struct dmareg dar;	/* Destination address */
+ 	struct dmareg llp;	/* Linked List Pointer */
+ 	struct dmareg ctl;	/* Control */
+ 	struct dmareg sstat;	/* Source Status not implemented in core */
+ 	struct dmareg dstat;	/* Destination Status not implemented in core */
+ 	struct dmareg sstatar;	/* Source Status Address not impl in core */
+ 	struct dmareg dstatar;	/* Destination Status Address not implemented */
+ 	struct dmareg cfg;	/* Config */
+ 	struct dmareg sgr;	/* Source Gather */
+ 	struct dmareg dsr;	/* Destination Scatter */
+ };
+
+ /* Generic Interrupt Registers */
+ struct dma_interrupt_regs {
+ 	struct dmareg tfr;	/* Transfer Interrupt */
+ 	struct dmareg block;	/* Block Interrupt */
+ 	struct dmareg srctran;	/* Source Transfer Interrupt */
+ 	struct dmareg dsttran;	/* Dest Transfer Interrupt */
+ 	struct dmareg error;	/* Error */
+ };
+
+ struct ahb_dma_regs {
+ 	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];	/* Channel
Registers */
+ 	struct dma_interrupt_regs	interrupt_raw;			/* Raw Interrupt */
+ 	struct dma_interrupt_regs	interrupt_status;		/* Interrupt Status */
+ 	struct dma_interrupt_regs	interrupt_mask;			/* Interrupt Mask */
+ 	struct dma_interrupt_regs	interrupt_clear;		/* Interrupt Clear */
+ 	struct dmareg			statusInt;			/* Interrupt combined */
+ 	struct dmareg			rq_srcreg;			/* Src Trans Req */
+ 	struct dmareg			rq_dstreg;			/* Dst Trans Req */
+ 	struct dmareg			rq_sgl_srcreg;			/* Sngl Src Trans Req */
+ 	struct dmareg			rq_sgl_dstreg;			/* Sngl Dst Trans Req */
+ 	struct dmareg			rq_lst_srcreg;			/* Last Src Trans Req */
+ 	struct dmareg			rq_lst_dstreg;			/* Last Dst Trans Req */
+ 	struct dmareg			dma_cfg;			/* DMA Config */
+ 	struct dmareg			dma_chan_en;			/* DMA Channel Enable */
+ 	struct dmareg			dma_id;				/* DMA ID */
+ 	struct dmareg			dma_test;			/* DMA Test */
+ 	struct dmareg			res1;				/* reserved */
+ 	struct dmareg			res2;				/* reserved */
+ 	/* DMA Comp Params
+ 	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
+ 	 * Param 4 = dma_param[2] ...
+ 	 */
+ 	struct dmareg			dma_params[6];
+ };
+
+ /* DMA Register Operation Bits */
+ #define DMA_EN			0x00000001		/* Enable AHB DMA */
+ #define DMA_CHANNEL(ch)		(0x00000001 << (ch))	/* Select channel */
+ #define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |	\
+ 				((0x000000001 << (ch)) << 8))		/* Enable channel */
+ #define DMA_DISABLE_CHAN(ch)	(0x00000000 | 	\
+ 				((0x000000001 << (ch)) << 8))		/* Disable channel */
+
+ #define SATA_DWC_MAX_PORTS	1
+ #define SATA_DWC_SCR_OFFSET	0x24
+ #define SATA_DWC_REG_OFFSET	0x64
+
+ /* DWC SATA Registers */
+ struct sata_dwc_regs {
+ 	u32 fptagr;		/* 1st party DMA tag */
+ 	u32 fpbor;		/* 1st party DMA buffer offset */
+ 	u32 fptcr;		/* 1st party DMA Xfr count */
+ 	u32 dmacr;		/* DMA Control */
+ 	u32 dbtsr;		/* DMA Burst Transac size */
+ 	u32 intpr;		/* Interrupt Pending */
+ 	u32 intmr;		/* Interrupt Mask */
+ 	u32 errmr;		/* Error Mask */
+ 	u32 llcr;		/* Link Layer Control */
+ 	u32 phycr;		/* PHY Control */
+ 	u32 physr;		/* PHY Status */
+ 	u32 rxbistpd;		/* Recvd BIST pattern def register */
+ 	u32 rxbistpd1;		/* Recvd BIST data dword1 */
+ 	u32 rxbistpd2;		/* Recvd BIST pattern data dword2 */
+ 	u32 txbistpd;		/* Trans BIST pattern def register */
+ 	u32 txbistpd1;		/* Trans BIST data dword1 */
+ 	u32 txbistpd2;		/* Trans BIST data dword2 */
+ 	u32 bistcr;		/* BIST Control Register */
+ 	u32 bistfctr;		/* BIST FIS Count Register */
+ 	u32 bistsr;		/* BIST Status Register */
+ 	u32 bistdecr;		/* BIST Dword Error count register */
+ 	u32 res[15];		/* Reserved locations */
+ 	u32 testr;		/* Test Register */
+ 	u32 versionr;		/* Version Register */
+ 	u32 idr;		/* ID Register */
+ 	u32 unimpl[192];	/* Unimplemented */
+ 	u32 dmadr[256];		/* FIFO Locations in DMA Mode */
+ };
+
+ /* DWC SATA Register Operations */
+ #define SATA_DWC_TXFIFO_DEPTH		0x01FF
+ #define SATA_DWC_RXFIFO_DEPTH		0x01FF
+
+ #define SATA_DWC_DBTSR_MWR(size)	((size/4) & SATA_DWC_TXFIFO_DEPTH)
+ #define SATA_DWC_DBTSR_MRD(size)	(((size/4) & SATA_DWC_RXFIFO_DEPTH)
<< 16)
+ #define SATA_DWC_INTPR_DMAT		0x00000001
+ #define SATA_DWC_INTPR_NEWFP		0x00000002
+ #define SATA_DWC_INTPR_PMABRT		0x00000004
+ #define SATA_DWC_INTPR_ERR		0x00000008
+ #define SATA_DWC_INTPR_NEWBIST		0x00000010
+ #define SATA_DWC_INTPR_IPF		0x10000000
+ #define SATA_DWC_INTMR_DMATM		0x00000001
+ #define SATA_DWC_INTMR_NEWFPM		0x00000002
+ #define SATA_DWC_INTMR_PMABRTM		0x00000004
+ #define SATA_DWC_INTMR_ERRM		0x00000008
+ #define SATA_DWC_INTMR_NEWBISTM		0x00000010
+
+ #define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
+ #define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
+
+ #define SATA_DWC_QCMD_MAX	32
+
+ /* This is all error bits, zero's are reserved fields. */
+ #define SATA_DWC_SERROR_ERR_BITS	0x0FFF0F03
+
+ /*
+  * Commonly used DWC SATA driver Macros
+  */
+ #define HSDEVP_FROM_AP(ap)	(struct
sata_dwc_device_port*)(ap)->private_data
+
+ struct sata_dwc_device {
+ 	struct device		*dev;		/* generic device struct */
+ 	struct ata_probe_ent    *pe;		/* ptr to probe-ent */
+ 	struct ata_host		*host;
+ 	u8			*reg_base;
+ 	struct sata_dwc_regs	*sata_dwc_regs;	/* DW Synopsys SATA specific */
+ 	int			irq_dma;
+ };
+
+ struct sata_dwc_device_port {
+ 	struct sata_dwc_device	*hsdev;
+ 	int			cmd_issued[SATA_DWC_QCMD_MAX];
+ 	u32			dma_chan[SATA_DWC_QCMD_MAX];
+ 	int			dma_pending[SATA_DWC_QCMD_MAX];
+ };
+
+ enum {
+ 	SATA_DWC_CMD_ISSUED_NOT		= 0,
+ 	SATA_DWC_CMD_ISSUED_PEND	= 1,
+ 	SATA_DWC_CMD_ISSUED_EXEC	= 2,
+ 	SATA_DWC_CMD_ISSUED_NODATA	= 3,
+
+ 	SATA_DWC_DMA_PENDING_NONE	= 0,
+ 	SATA_DWC_DMA_PENDING_TX		= 1,
+ 	SATA_DWC_DMA_PENDING_RX		= 2,
+ };
+
+ /* delay Macros */
+ #define msleep(a)	udelay(a * 1000)
+ #define ssleep(a)	msleep(a * 1000)
+
+ static int ata_probe_timeout = (ATA_TMOUT_INTERNAL / 100);
+
+ enum sata_dev_state {
+ 	SATA_INIT = 0,
+ 	SATA_READY = 1,
+ 	SATA_NODEVICE = 2,
+ 	SATA_ERROR = 3,
+ };
+ enum sata_dev_state dev_state = SATA_INIT;
+
+ /*
+  * Globals
+  */
+ static struct ahb_dma_regs		*sata_dma_regs = 0;
+ static struct ata_host			*phost;
+ static struct ata_port			ap;
+ static struct ata_port			*pap = &ap;
+ static struct ata_device		ata_device;
+ static struct sata_dwc_device_port	dwc_devp;
+
+ static void	*scr_addr_sstatus;
+ static char	temp_data_buf[512];
+ static u32	temp_n_block = 0;
+
+ /*
+  * Prototype
+  */
+ unsigned ata_exec_internal(struct ata_device *dev,
+ 			struct ata_taskfile *tf, const u8 *cdb,
+ 			int dma_dir, unsigned int buflen,
+ 			unsigned long timeout);
+ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable,u8
feature);
+ unsigned int ata_dev_init_params(struct ata_device *dev, u16 heads,
u16 sectors);
+ void clear_serror(void);
+ u8 ata_irq_on(struct ata_port *ap);
+ struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,unsigned
int tag);
+ int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+ 						u8 status, int in_wq);
+ void ata_tf_to_host(struct ata_port *ap,const struct ata_taskfile *tf);
+ unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc);
+ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
+ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+ u8 ata_check_altstatus(struct ata_port *ap);
+ static u8 ata_check_status(struct ata_port *ap);
+ void ata_dev_select(struct ata_port *ap, unsigned int device,unsigned
int wait,
+ 						unsigned int can_sleep);
+ void ata_qc_issue(struct ata_queued_cmd *qc);
+ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
+ int ata_dev_read_sectors(ccb *pccb);
+ void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+ void ata_qc_complete(struct ata_queued_cmd *qc);
+ void __ata_qc_complete(struct ata_queued_cmd *qc);
+ void fill_result_tf(struct ata_queued_cmd *qc);
+ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ void ata_mmio_data_xfer(struct ata_device *dev,
+ 			unsigned char *buf,unsigned int buflen);
+ void ata_pio_task(struct ata_port *arg_ap);
+ void __ata_port_freeze(struct ata_port *ap);
+ int ata_port_freeze(struct ata_port *ap);
+ void ata_qc_free(struct ata_queued_cmd *qc);
+ void ata_pio_sectors(struct ata_queued_cmd *qc);
+ void ata_pio_sector(struct ata_queued_cmd *qc);
+ void ata_pio_queue_task(struct ata_port *ap,
+ 			void *data,unsigned long delay);
+ void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq);
+ int sata_dwc_softreset(struct ata_port *ap);
+ void sata_dwc_probe(void);
+
+ u8 ata_check_altstatus(struct ata_port *ap)
+ {
+ 	u8 val = 0;
+ 	val = readb(ap->ioaddr.altstatus_addr);
+ 	return val;
+ }
+
+ int check_sata_dev_state(void)
+ {
+ 	static ccb tempccb;		/* temporary scsi command buffer */
+ 	ccb *pccb = (ccb *)&tempccb;
+ 	int ret = 0;
+ 	int i = 0;
+
+ 	while(1){
+ 		udelay (10000);		/* 10 ms */
+
+ 	        pccb->cmd[0] = SCSI_READ10;
+ 	        pccb->cmd[1] = 0;
+ 	        pccb->cmd[2] = 0;
+ 	        pccb->cmd[3] = 0;
+ 	        pccb->cmd[4] = 0;
+ 	        pccb->cmd[5] = 0;
+ 	        pccb->cmd[6] = 0;
+ 	        pccb->cmd[7] = 0;
+ 	        pccb->cmd[8] = 1;
+ 	        pccb->cmdlen = 10;
+ 		pccb->pdata = &temp_data_buf[0];	/* dummy */
+ 		pccb->datalen = 512;
+
+ 		/* Send Read Command */
+ 		ret =  ata_dev_read_sectors(pccb);
+
+ 		/* result TRUE => break */
+ 		if(ret == 0){
+ 			break;
+ 		}
+
+ 		i++;
+ 		if (i > (ATA_RESET_TIME * 100)){
+ 			printf("** TimeOUT **\n");
+ 			dev_state = SATA_NODEVICE;	/* set device status flag */
+ 			return FALSE;
+ 		}
+
+ 		if ((i >= 100) && ((i%100)==0)) {
+ 			printf(".");
+ 		}
+ 	}
+
+ 	/* Set device status flag */
+ 	dev_state = SATA_READY;
+
+ 	return TRUE;
+ }
+
+ void ata_id_string(const u16 *id, unsigned char *s,
+ 		unsigned int ofs, unsigned int len)
+ {
+ 	unsigned int c;
+
+ 	while (len > 0) {
+ 		c = id[ofs] >> 8;
+ 		*s = c;
+ 		s++;
+
+ 		c = id[ofs] & 0xff;
+ 		*s = c;
+ 		s++;
+
+ 		ofs++;
+ 		len -= 2;
+ 	}
+ }
+
+ static int waiting_for_reg_state(volatile u8 *offset,
+ 				int timeout_msec,
+ 				u32 sign)
+ {
+ 	int i;
+ 	u32 status;
+
+ 	for (i = 0; i < timeout_msec; i++){
+ 		status = readl(offset);
+ 		if ( ( status & sign ) != 0 ){
+ 			break;
+ 		}
+ 		msleep(1);
+ 	}
+
+ 	return (i < timeout_msec) ? 0 : -1;
+ }
+
+ static inline u32 qcmd_tag_to_mask(u8 tag)
+ {
+ 	return (0x00000001 << (tag & 0x1f));
+ }
+
+ static u8 ata_check_status(struct ata_port *ap)
+ {
+ 	u8 val = 0;
+ 	val = readb(ap->ioaddr.status_addr);
+ 	return val;
+ }
+
+ static u8 ata_busy_wait(struct ata_port *ap, unsigned int
bits,unsigned int max)
+ {
+ 	u8 status;
+
+ 	do {
+ 		udelay(10);
+ 		status = ata_check_status(ap);
+ 		max--;
+ 	} while (status != 0xff && (status & bits) && (max > 0));
+
+ 	return status;
+ }
+
+ static u8 ata_wait_idle(struct ata_port *ap)
+ {
+ 	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+ 	return status;
+ }
+
+ static int sata_dwc_scsiop_inq(ccb *pccb)
+ {
+ 	struct ata_device *ata_dev = &ata_device;
+ 	u16 *id;
+
+ 	/* Set IDENTIFY Data */
+ 	id = ata_dev->id;
+
+ 	/* make INQUIRY header */
+ 	u8 hdr[] = {
+ 		0,
+ 		0,
+ 		0x5,	/* claim SPC-3 version compatibility */
+ 		2,
+ 		95 - 4
+ 	};
+
+ 	/* set scsi removeable (RMB) bit per ata bit */
+ 	if (ata_id_removeable(id)){
+ 		hdr[1] |= (1 << 7);
+  	}
+
+ 	memcpy(pccb->pdata, hdr, sizeof(hdr));
+
+ 	if (pccb->datalen > 35) {
+ 		memcpy(&pccb->pdata[8], "ATA     ", 8);
+ 		ata_id_string(id, &pccb->pdata[16], ATA_ID_PROD, 16);
+ 		ata_id_string(id, &pccb->pdata[32], ATA_ID_FW_REV, 4);
+ 		if (pccb->pdata[32] == 0 || pccb->pdata[32] == ' '){
+ 			memcpy(&pccb->pdata[32], "n/a ", 4);
+ 		}
+ 	}
+
+ 	if (pccb->datalen > 63) {
+ 		const u8 versions[] = {
+ 			0x60,	/* SAM-3 (no version claimed) */
+ 			0x03,
+ 			0x20,	/* SBC-2 (no version claimed) */
+ 			0x02,
+ 			0x60	/* SPC-3 (no version claimed) */
+ 		};
+ 		memcpy(pccb->pdata + 59, versions, sizeof(versions));
+ 	}
+
+ 	return 0;
+ }
+
+ #define ATA_SCSI_PDATA_SET(idx, val) do { \
+                 if ((idx) < pccb->datalen) pccb->pdata[(idx)] =
(u8)(val); \
+ 		} while (0)
+
+ static int sata_dwc_scsiop_read_cap(ccb *pccb)
+ {
+ 	struct ata_device *ata_dev = &ata_device;
+ 	u32 last_lba;
+ 	last_lba = ata_dev->n_sectors;	/* LBA of the last block */
+
+ 	if (pccb->cmd[0] == SCSI_RD_CAPAC) {
+ 		if (last_lba >= 0xffffffffULL){
+ 			last_lba = 0xffffffff;
+ 		}
+
+ 		/* sector count, 32-bit */
+ 		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 3));
+ 		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 2));
+ 		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 1));
+ 		ATA_SCSI_PDATA_SET(3, last_lba);
+
+ 		/* buffer clear */
+ 		ATA_SCSI_PDATA_SET(4, 0);
+ 		ATA_SCSI_PDATA_SET(5, 0);
+
+ 		/* sector size */
+ 		ATA_SCSI_PDATA_SET(6, ATA_SECT_SIZE >> 8);
+ 		ATA_SCSI_PDATA_SET(7, ATA_SECT_SIZE & 0xff);
+
+ 	} else {
+ 		/* sector count, 64-bit */
+ 		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 7));
+ 		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 6));
+ 		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 5));
+ 		ATA_SCSI_PDATA_SET(3, last_lba >> (8 * 4));
+ 		ATA_SCSI_PDATA_SET(4, last_lba >> (8 * 3));
+ 		ATA_SCSI_PDATA_SET(5, last_lba >> (8 * 2));
+ 		ATA_SCSI_PDATA_SET(6, last_lba >> (8 * 1));
+ 		ATA_SCSI_PDATA_SET(7, last_lba);
+
+ 		/* sector size */
+ 		ATA_SCSI_PDATA_SET(10, ATA_SECT_SIZE >> 8);
+ 		ATA_SCSI_PDATA_SET(11, ATA_SECT_SIZE & 0xff);
+ 	}
+
+ 	return 0;
+ }
+
+ /*
+  * SCSI TEST UNIT READY command operation.
+  *      No operation.  Simply returns success to caller, to indicate
+  *      that the caller should successfully complete this SCSI command.
+  */
+ static int sata_dwc_scsiop_test_unit_ready(ccb *pccb)
+ {
+ 	/* No operation  */
+ 	return 0;
+ }
+
+ int scsi_exec(ccb *pccb)
+ {
+ 	int ret;
+
+ 	/* check device status */
+ 	if(dev_state != SATA_READY){
+ 		return FALSE;
+ 	}
+
+ 	switch (pccb->cmd[0]) {
+ 	case SCSI_READ10:
+ 		ret =  ata_dev_read_sectors(pccb);
+ 		break;
+ 	case SCSI_RD_CAPAC:
+ 		ret = sata_dwc_scsiop_read_cap(pccb);
+ 		break;
+ 	case SCSI_TST_U_RDY:
+ 		ret = sata_dwc_scsiop_test_unit_ready(pccb);
+ 		break;
+ 	case SCSI_INQUIRY:
+ 		ret = sata_dwc_scsiop_inq(pccb);
+ 		break;
+ 	default:
+ 		printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
+ 		return FALSE;
+ 	}
+
+ 	if (ret) {
+ 		debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
+ 		return FALSE;
+ 	}
+ 	return TRUE;
+ }
+
+ static const struct ata_port_info sata_dwc_port_info[] = {
+ 	{
+ 		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
+ 				ATA_FLAG_SRST | ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio 0-4 */
+ 		.mwdma_mask	= 0x07,
+ 		.udma_mask	= 0x7f,
+ 	},
+ };
+
+ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+ 		unsigned int flags, u16 *id)
+ {
+ 	struct ata_port *ap = pap;
+ 	unsigned int class = *p_class;
+ 	struct ata_taskfile tf;
+ 	unsigned int err_mask = 0;
+ 	const char *reason;
+ 	int may_fallback = 1, tried_spinup = 0;
+ 	u8 status;
+ 	int rc;
+
+ 	/* cheack BSY = 0 */
+ 	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+ 	if (status & ATA_BUSY) {
+ 		printf("BSY = 0 check. timeout.\n");
+ 		rc = FALSE;
+ 		return rc;
+ 	}
+
+         ata_dev_select(ap, dev->devno, 1, 1);	/* select device 0/1 */
+
+ retry:
+ 	memset(&tf, 0, sizeof(tf));
+ 	ap->print_id = 1;
+ 	ap->flags &= ~ATA_FLAG_DISABLED;
+ 	tf.ctl = ap->ctl;	/* 0x08 */
+ 	tf.device = ATA_DEVICE_OBS;
+ 	tf.command = ATA_CMD_ID_ATA;
+ 	tf.protocol = ATA_PROT_PIO;
+
+ 	/* Some devices choke if TF registers contain garbage.  Make
+ 	 * sure those are properly initialized.
+ 	 */
+ 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+ 	/* Device presence detection is unreliable on some
+ 	 * controllers.  Always poll IDENTIFY if available.
+ 	 */
+ 	tf.flags |= ATA_TFLAG_POLLING;
+
+ 	temp_n_block = 1;
+
+ 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+ 					sizeof(id[0]) * ATA_ID_WORDS, 0);
+
+ 	if (err_mask) {
+ 		if (err_mask & AC_ERR_NODEV_HINT) {
+ 			printf("NODEV after polling detection\n");
+ 			return -ENOENT;
+ 		}
+
+ 		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+ 			/* Device or controller might have reported
+ 			 * the wrong device class.  Give a shot at the
+ 			 * other IDENTIFY if the current one is
+ 			 * aborted by the device.
+ 			 */
+ 			if (may_fallback) {
+ 				may_fallback = 0;
+
+ 				if (class == ATA_DEV_ATA) {
+ 					class = ATA_DEV_ATAPI;
+ 				} else {
+ 					class = ATA_DEV_ATA;
+ 				}
+ 				goto retry;
+ 			}
+ 			/* Control reaches here iff the device aborted
+ 			 * both flavors of IDENTIFYs which happens
+ 			 * sometimes with phantom devices.
+ 			 */
+ 			printf("both IDENTIFYs aborted, assuming NODEV\n");
+ 			return -ENOENT;
+ 		}
+ 		rc = -EIO;
+ 		reason = "I/O error";
+ 		goto err_out;
+ 	}
+
+ 	/* Falling back doesn't make sense if ID data was read
+ 	 * successfully at least once.
+ 	 */
+ 	may_fallback = 0;
+
+ #ifdef __BIG_ENDIAN
+ 	unsigned int id_cnt;
+
+ 	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
+ 		id[id_cnt] = le16_to_cpu(id[id_cnt]);
+
+ #endif	/* __BIG_ENDIAN */
+
+ 	/* sanity check */
+ 	rc = -EINVAL;
+ 	reason = "device reports invalid type";
+
+ 	if (class == ATA_DEV_ATA) {
+ 		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)){
+ 			goto err_out;
+ 		}
+ 	} else {
+ 		if (ata_id_is_ata(id)){
+ 			goto err_out;
+ 		}
+ 	}
+ 	if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+ 		tried_spinup = 1;
+ 		/*
+ 		 * Drive powered-up in standby mode, and requires a specific
+ 		 * SET_FEATURES spin-up subcommand before it will accept
+ 		 * anything other than the original IDENTIFY command.
+ 		 */
+ 		err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+ 		if (err_mask && id[2] != 0x738c) {
+ 			rc = -EIO;
+ 			reason = "SPINUP failed";
+ 			goto err_out;
+ 		}
+ 		/*
+ 		 * If the drive initially returned incomplete IDENTIFY info,
+ 		 * we now must reissue the IDENTIFY command.
+ 		 */
+ 		if (id[2] == 0x37c8)
+ 			goto retry;
+ 	}
+
+ 	if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
+ 		/*
+ 		 * The exact sequence expected by certain pre-ATA4 drives is:
+ 		 * SRST RESET
+ 		 * IDENTIFY (optional in early ATA)
+ 		 * INITIALIZE DEVICE PARAMETERS (later IDE and ATA)
+ 		 * anything else..
+ 		 * Some drives were very specific about that exact sequence.
+ 		 *
+ 		 * Note that ATA4 says lba is mandatory so the second check
+ 		 * shoud never trigger.
+ 		 */
+ 		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+ 			err_mask = ata_dev_init_params(dev, id[3], id[6]);
+ 			if (err_mask) {
+ 				rc = -EIO;
+ 				reason = "INIT_DEV_PARAMS failed";
+ 				goto err_out;
+ 			}
+
+ 			/* current CHS translation info (id[53-58]) might be
+ 			 * changed. reread the identify device info.
+ 			 */
+ 			flags &= ~ATA_READID_POSTRESET;
+ 			goto retry;
+ 		}
+         }
+
+ 	*p_class = class;
+ 	return 0;
+
+ err_out:
+ 	return rc;
+ }
+
+ void ata_dev_select(struct ata_port *ap, unsigned int device,
+ 		unsigned int wait, unsigned int can_sleep)
+ {
+ 	if (wait){
+ 		ata_wait_idle(ap);
+ 	}
+
+ 	ata_std_dev_select(ap, device);
+
+ 	if (wait) {
+ 		ata_wait_idle(ap);
+ 	}
+ }
+
+ void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+ {
+ 	u8 tmp;
+
+ 	if (device == 0) {
+ 		tmp = ATA_DEVICE_OBS;
+ 	} else {
+ 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+ 	}
+
+ 	writeb(tmp, ap->ioaddr.device_addr);
+
+ 	/* needed; also flushes, for mmio */
+ 	readb(ap->ioaddr.altstatus_addr);
+
+ 	/* need delay 400nsec over */
+ 	udelay(1);
+ }
+
+ void ata_qc_reinit(struct ata_queued_cmd *qc)
+ {
+ 	qc->dma_dir = DMA_NONE;
+ 	qc->flags = 0;
+ 	qc->nbytes = qc->extrabytes = qc->curbytes = 0;
+ 	qc->n_elem = 0;
+ 	qc->err_mask = 0;
+ 	qc->sect_size = ATA_SECT_SIZE;
+ 	qc->nbytes = ATA_SECT_SIZE * temp_n_block;
+
+ 	memset(&qc->tf, 0, sizeof(qc->tf));
+ 	qc->tf.ctl = 0;
+ 	qc->tf.device = ATA_DEVICE_OBS;
+
+ 	/* init result_tf such that it indicates normal completion */
+ 	qc->result_tf.command = ATA_DRDY;
+ 	qc->result_tf.feature = 0;
+ }
+
+ unsigned ata_exec_internal(struct ata_device *dev,
+ 			struct ata_taskfile *tf, const u8 *cdb,
+ 			int dma_dir, unsigned int buflen,
+ 			unsigned long timeout)
+ {
+ 	struct ata_link *link = dev->link;
+ 	struct ata_port *ap = pap;
+ 	struct ata_queued_cmd *qc;
+ 	unsigned int tag, preempted_tag;
+ 	u32 preempted_sactive, preempted_qc_active;
+ 	int preempted_nr_active_links;
+ 	unsigned int err_mask;
+ 	int rc = 0;
+ 	u8 status;
+
+ 	/* cheack BSY = 0 */
+ 	status = ata_busy_wait(ap, ATA_BUSY, 300000);
+ 	if (status & ATA_BUSY) {
+ 		printf("BSY = 0 check. timeout.\n");
+ 		rc = FALSE;
+ 		return rc;
+ 	}
+
+ 	/* no internal command while frozen */
+ 	if (ap->pflags & ATA_PFLAG_FROZEN) {
+ 		return AC_ERR_SYSTEM;
+ 	}
+
+ 	tag = ATA_TAG_INTERNAL;
+
+ 	if (test_and_set_bit(tag, &ap->qc_allocated)){
+ 		printf("test_and_set_bit failed\n");
+ 	}
+
+ 	qc = __ata_qc_from_tag(ap, tag);
+ 	qc->tag = tag;
+ 	qc->ap = ap;
+ 	qc->dev = dev;
+
+ 	ata_qc_reinit(qc);
+
+ 	preempted_tag = link->active_tag;
+ 	preempted_sactive = link->sactive;
+ 	preempted_qc_active = ap->qc_active;
+ 	preempted_nr_active_links = ap->nr_active_links;
+ 	link->active_tag = ATA_TAG_POISON;
+ 	link->sactive = 0;
+ 	ap->qc_active = 0;
+ 	ap->nr_active_links = 0;
+
+ 	/* prepare & issue qc */
+ 	qc->tf = *tf;
+ 	if (cdb)
+ 		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+ 	qc->flags |= ATA_QCFLAG_RESULT_TF;
+ 	qc->dma_dir = dma_dir;
+ 	qc->private_data = 0;
+
+ 	ata_qc_issue(qc);
+
+ 	if (!timeout){
+ 		timeout = ata_probe_timeout * 1000 / HZ;
+ 	}
+
+ 	/* cheack BSY = 0 */
+ 	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+ 	if (status & ATA_BUSY) {
+ 		printf("BSY = 0 check. timeout.\n");
+ 		printf("altstatus = 0x%x.\n",status);
+ 		qc->err_mask |= AC_ERR_OTHER;
+ 		return qc->err_mask;
+ 	}
+
+ 	if(waiting_for_reg_state(ap->ioaddr.altstatus_addr,1000,0x8)){
+ 		printf("DRQ = 1 check timeout 1000msec\n");
+ 		u8 status = 0;
+ 		u8 errorStatus = 0;
+
+ 		status = readb( ap->ioaddr.altstatus_addr);
+ 		if ((status&0x01) != 0) {
+ 			errorStatus = readb( ap->ioaddr.feature_addr);
+ 			printf("ERROR STATUS = 0x%x\n",errorStatus);
+ 		}
+ 		qc->err_mask |= AC_ERR_OTHER;
+ 		return qc->err_mask;
+ 	}
+
+ 	status = ata_busy_wait(ap, ATA_BUSY, 10);
+ 	if (status & ATA_BUSY) {
+ 		printf("BSY = 0 check. timeout.\n");
+ 		qc->err_mask |= AC_ERR_OTHER;
+ 		return qc->err_mask;
+ 	}
+
+ 	ata_pio_task(ap);
+
+ 	if (!rc) {
+ 		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+ 			qc->err_mask |= AC_ERR_TIMEOUT;
+ 			ata_port_freeze(ap);
+ 		}
+ 	}
+
+ 	/* perform minimal error analysis */
+ 	if (qc->flags & ATA_QCFLAG_FAILED) {
+ 		if (qc->result_tf.command & (ATA_ERR | ATA_DF)){
+ 			qc->err_mask |= AC_ERR_DEV;
+ 		}
+
+ 		if (!qc->err_mask){
+ 			qc->err_mask |= AC_ERR_OTHER;
+ 		}
+
+ 		if (qc->err_mask & ~AC_ERR_OTHER){
+ 			qc->err_mask &= ~AC_ERR_OTHER;
+ 		}
+ 	}
+
+ 	/* finish up */
+ 	*tf = qc->result_tf;
+ 	err_mask = qc->err_mask;
+ 	ata_qc_free(qc);
+ 	link->active_tag = preempted_tag;
+ 	link->sactive = preempted_sactive;
+ 	ap->qc_active = preempted_qc_active;
+ 	ap->nr_active_links = preempted_nr_active_links;
+
+ 	if (ap->flags & ATA_FLAG_DISABLED) {
+ 		err_mask |= AC_ERR_SYSTEM;
+ 		ap->flags &= ~ATA_FLAG_DISABLED;
+ 	}
+
+ 	return err_mask;
+ }
+
+ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8
feature)
+ {
+ 	struct ata_taskfile tf;
+ 	struct ata_port *ap;
+ 	ap = pap;
+ 	unsigned int err_mask;
+
+ 	/* set up set-features taskfile */
+ 	memset(&tf, 0, sizeof(tf));
+ 	tf.ctl = ap->ctl;
+
+ 	tf.device = ATA_DEVICE_OBS;
+ 	tf.command = ATA_CMD_SET_FEATURES;
+ 	tf.feature = enable;
+ 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ 	tf.protocol = ATA_PROT_NODATA;
+ 	tf.nsect = feature;
+
+ 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+ 	return err_mask;
+ }
+
+ unsigned int ata_dev_init_params(struct ata_device *dev,
+ 				u16 heads, u16 sectors)
+ {
+ 	struct ata_taskfile tf;
+ 	struct ata_port *ap;
+ 	ap = pap;
+ 	unsigned int err_mask;
+
+ 	/* Number of sectors per track 1-255. Number of heads 1-16 */
+ 	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+ 			return AC_ERR_INVALID;
+
+ 	/* set up init dev params taskfile */
+ 	memset(&tf, 0, sizeof(tf));
+ 	tf.ctl = ap->ctl;
+ 	tf.device = ATA_DEVICE_OBS;
+ 	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+ 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ 	tf.protocol = ATA_PROT_NODATA;
+ 	tf.nsect = sectors;
+ 	tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+ 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+ 	if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
+ 		err_mask = 0;
+
+ 	return err_mask;
+ }
+
+ struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap, unsigned
int tag)
+ {
+ 	if (tag < ATA_MAX_QUEUE)
+ 		return &ap->qcmd[tag];
+ 	return NULL;
+ }
+
+ void ata_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_link *link = qc->dev->link;
+ 	u8 prot = qc->tf.protocol;
+
+ 	if (ata_is_ncq(prot)) {
+ 		if (!link->sactive)
+ 			ap->nr_active_links++;
+ 		link->sactive |= 1 << qc->tag;
+ 	} else {
+ 		ap->nr_active_links++;
+ 		link->active_tag = qc->tag;
+ 	}
+
+ 	qc->flags |= ATA_QCFLAG_ACTIVE;
+ 	ap->qc_active |= 1 << qc->tag;
+
+ 	if (qc->dev->flags & ATA_DFLAG_SLEEPING) {
+ 		msleep(1);	/* delay 1msec */
+ 		return;
+ 	}
+
+ 	qc->err_mask |= sata_dwc_qc_issue(qc);
+ 	if (qc->err_mask)
+ 		goto err;
+
+ 	return;
+ err:
+ 	ata_qc_complete(qc);
+ }
+
+ unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	ata_qc_issue_prot(qc);
+ 	return 0;
+ }
+
+ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ 	/* set command register */
+ 	writeb(tf->command, ap->ioaddr.command_addr);
+
+ 	/* read alternative status register */
+ 	readb(ap->ioaddr.altstatus_addr);
+
+ 	/* delay 400nsec over */
+ 	udelay(1);
+ }
+
+ void __ata_port_freeze(struct ata_port *ap)
+ {
+ 	printf("set port freeze.\n");
+ 	ap->pflags |= ATA_PFLAG_FROZEN;
+ }
+
+ int ata_port_freeze(struct ata_port *ap)
+ {
+ 	__ata_port_freeze(ap);
+ 	return 0;
+ }
+
+ unsigned int ata_tag_internal(unsigned int tag)
+ {
+ 	return tag == ATA_MAX_QUEUE - 1;
+ }
+
+ void ata_qc_complete(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_device *dev = qc->dev;
+ 	if (qc->err_mask)
+ 		qc->flags |= ATA_QCFLAG_FAILED;
+
+ 	if (qc->flags & ATA_QCFLAG_FAILED) {
+ 		if (!ata_tag_internal(qc->tag)) {
+ 			/* always fill result TF for failed qc */
+ 			fill_result_tf(qc);
+ 			return;
+ 		}
+ 	}
+ 	/* read result TF if requested */
+ 	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+ 		fill_result_tf(qc);
+
+ 	/* Some commands need post-processing after successful
+ 	 * completion.
+ 	 */
+ 	switch (qc->tf.command) {
+ 	case ATA_CMD_SET_FEATURES:
+ 		if (qc->tf.feature != SETFEATURES_WC_ON &&
+ 				qc->tf.feature != SETFEATURES_WC_OFF)
+ 			break;
+ 	case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+ 	case ATA_CMD_SET_MULTI: /* multi_count changed */
+ 		break;
+
+ 	case ATA_CMD_SLEEP:
+ 		dev->flags |= ATA_DFLAG_SLEEPING;
+ 		break;
+ 	}
+
+ 	__ata_qc_complete(qc);
+ }
+
+ void __ata_qc_complete(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_link *link = qc->dev->link;
+
+ 	/* command should be marked inactive atomically with qc completion */
+ 	link->active_tag = ATA_TAG_POISON;
+ 	ap->nr_active_links--;
+
+ 	/* clear exclusive status */
+ 	if (qc->flags & ATA_QCFLAG_CLEAR_EXCL && ap->excl_link == link)
+ 		ap->excl_link = NULL;
+
+ 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+ 	ap->qc_active &= ~(1 << qc->tag);
+ }
+
+ void fill_result_tf(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+
+ 	qc->result_tf.flags = qc->tf.flags;
+ 	ata_tf_read(ap, &qc->result_tf);
+ }
+
+ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ 	tf->command = ata_check_status(ap);
+ 	tf->feature = readb(ioaddr->error_addr);
+ 	tf->nsect = readb(ioaddr->nsect_addr);
+ 	tf->lbal = readb(ioaddr->lbal_addr);
+ 	tf->lbam = readb(ioaddr->lbam_addr);
+ 	tf->lbah = readb(ioaddr->lbah_addr);
+ 	tf->device = readb(ioaddr->device_addr);
+
+ 	if (tf->flags & ATA_TFLAG_LBA48) {
+ 		if (ioaddr->ctl_addr) {
+ 			writeb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+
+ 			tf->hob_feature = readb(ioaddr->error_addr);
+ 			tf->hob_nsect = readb(ioaddr->nsect_addr);
+ 			tf->hob_lbal = readb(ioaddr->lbal_addr);
+ 			tf->hob_lbam = readb(ioaddr->lbam_addr);
+ 			tf->hob_lbah = readb(ioaddr->lbah_addr);
+
+ 			writeb(tf->ctl, ioaddr->ctl_addr);
+ 			ap->last_ctl = tf->ctl;
+ 		} else {
+ 			printf("sata_dwc warnning register read.\n");
+ 		}
+ 	}
+ }
+
+ void ata_qc_free(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	unsigned int tag;
+ 	qc->flags = 0;
+ 	tag = qc->tag;
+ 	if (tag < ATA_MAX_QUEUE){
+ 		qc->tag = ATA_TAG_POISON;
+ 		clear_bit(tag, &ap->qc_allocated);
+ 	}
+ }
+
+ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+ 	if (tf->ctl != ap->last_ctl) {
+ 		if (ioaddr->ctl_addr){
+ 			writeb(tf->ctl, ioaddr->ctl_addr);
+ 		}
+ 		ap->last_ctl = tf->ctl;
+ 		ata_wait_idle(ap);
+ 	}
+
+ 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ 		writeb(tf->hob_feature, ioaddr->feature_addr);
+ 		writeb(tf->hob_nsect, ioaddr->nsect_addr);
+ 		writeb(tf->hob_lbal, ioaddr->lbal_addr);
+ 		writeb(tf->hob_lbam, ioaddr->lbam_addr);
+ 		writeb(tf->hob_lbah, ioaddr->lbah_addr);
+ 	}
+
+ 	if (is_addr) {
+ 		writeb(tf->feature, ioaddr->feature_addr);
+ 		writeb(tf->nsect, ioaddr->nsect_addr);
+ 		writeb(tf->lbal, ioaddr->lbal_addr);
+ 		writeb(tf->lbam, ioaddr->lbam_addr);
+ 		writeb(tf->lbah, ioaddr->lbah_addr);
+ 	}
+
+ 	if (tf->flags & ATA_TFLAG_DEVICE) {
+ 		writeb(tf->device, ioaddr->device_addr);
+ 	}
+
+ 	ata_wait_idle(ap);
+ }
+
+ void sata_dwc_exec_command_by_tag(struct ata_port *ap,
+ 				struct ata_taskfile *tf,
+ 				u8 tag, u32 cmd_issued)
+ {
+ 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+ 	hsdevp->cmd_issued[tag] = cmd_issued;
+
+ 	/* Clear SError before executing a new command.*/
+ 	clear_serror();
+ 	ata_exec_command(ap, tf);
+ }
+
+ void clear_serror(void)
+ {
+ 	u32 temp;
+ 	temp = in_le32((void __iomem *)scr_addr_sstatus + 4);
+
+ 	out_le32((void __iomem *)scr_addr_sstatus + 4, temp);
+ }
+
+ void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ 	ata_tf_load(ap, tf);
+ 	ata_exec_command(ap, tf);
+ }
+
+ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+
+ 	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+ 		switch (qc->tf.protocol) {
+ 		case ATA_PROT_PIO:
+ 		case ATA_PROT_NODATA:
+ 		case ATAPI_PROT_PIO:
+ 		case ATAPI_PROT_NODATA:
+ 			qc->tf.flags |= ATA_TFLAG_POLLING;
+ 			break;
+ 		default:
+ 			break;
+ 		}
+ 	}
+
+ 	/* select the device */
+ 	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+ 	/* start the command */
+ 	switch (qc->tf.protocol) {
+ 	case ATA_PROT_PIO:
+ 		if (qc->tf.flags & ATA_TFLAG_POLLING){
+ 			qc->tf.ctl |= ATA_NIEN;
+ 		}
+
+ 		ata_tf_to_host(ap, &qc->tf);
+
+ 		/* PIO data in protocol */
+ 		ap->hsm_task_state = HSM_ST;
+
+ 		if (qc->tf.flags & ATA_TFLAG_POLLING){
+ 			ata_pio_queue_task(ap, qc, 0);
+ 		}
+
+ 		break;
+
+ 	default:
+ 		return AC_ERR_SYSTEM;
+ 	}
+
+ 	return 0;
+ }
+
+ void ata_pio_task(struct ata_port *arg_ap)
+ {
+ 	struct ata_port *ap = arg_ap;
+ 	struct ata_queued_cmd *qc = ap->port_task_data;
+ 	u8 status;
+ 	int poll_next;
+
+ fsm_start:
+ 	/*
+ 	 * This is purely heuristic.  This is a fast path.
+ 	 * Sometimes when we enter, BSY will be cleared in
+ 	 * a chk-status or two.  If not, the drive is probably seeking
+ 	 * or something.  Snooze for a couple msecs, then
+ 	 * chk-status again.  If still busy, queue delayed work.
+ 	 */
+ 	status = ata_busy_wait(ap, ATA_BUSY, 5);
+ 	if (status & ATA_BUSY) {
+ 		msleep(2);
+ 		status = ata_busy_wait(ap, ATA_BUSY, 10);
+ 		if (status & ATA_BUSY) {
+ 			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+ 			return;
+ 		}
+ 	}
+
+ 	/* move the HSM */
+ 	poll_next = ata_hsm_move(ap, qc, status, 1);
+
+ 	/* another command or interrupt handler
+ 	 * may be running at this point.
+ 	 */
+ 	if (poll_next)
+ 		goto fsm_start;
+ }
+
+ void ata_pio_queue_task(struct ata_port *ap, void *data,unsigned long
delay)
+ {
+ 	ap->port_task_data = data;
+ }
+
+ unsigned int ac_err_mask(u8 status)
+ {
+ 	if (status & (ATA_BUSY | ATA_DRQ))
+ 		return AC_ERR_HSM;
+ 	if (status & (ATA_ERR | ATA_DF))
+ 		return AC_ERR_DEV;
+ 	return 0;
+ }
+
+ unsigned int __ac_err_mask(u8 status)
+ {
+ 	unsigned int mask = ac_err_mask(status);
+ 	if (mask == 0)
+ 		return AC_ERR_OTHER;
+ 	return mask;
+ }
+
+ int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+ 			u8 status, int in_wq)
+ {
+ 	int poll_next;
+
+ fsm_start:
+ 	switch (ap->hsm_task_state) {
+ 	case HSM_ST_FIRST:
+ 		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+ 		/* check device status */
+ 		if ((status & ATA_DRQ) == 0) {
+ 			/* handle BSY=0, DRQ=0 as error */
+ 			if (status & (ATA_ERR | ATA_DF)) {
+ 				/* device stops HSM for abort/error */
+ 				qc->err_mask |= AC_ERR_DEV;
+ 			} else {
+ 				/* HSM violation. Let EH handle this */
+ 				qc->err_mask |= AC_ERR_HSM;
+ 			}
+ 			ap->hsm_task_state = HSM_ST_ERR;
+ 			goto fsm_start;
+ 		}
+
+ 		/* Device should not ask for data transfer (DRQ=1)
+ 		 * when it finds something wrong.
+ 		 * We ignore DRQ here and stop the HSM by
+ 		 * changing hsm_task_state to HSM_ST_ERR and
+ 		 * let the EH abort the command or reset the device.
+ 		 */
+ 		if (status & (ATA_ERR | ATA_DF)) {
+ 			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+ 				printf("DRQ=1 with device error, "
+ 					"dev_stat 0x%X\n", status);
+ 				qc->err_mask |= AC_ERR_HSM;
+ 				ap->hsm_task_state = HSM_ST_ERR;
+ 				goto fsm_start;
+ 			}
+ 		}
+
+ 		if (qc->tf.protocol == ATA_PROT_PIO) {
+ 			/* PIO data out protocol.
+ 			 * send first data block.
+ 			 */
+ 			/* ata_pio_sectors() might change the state
+ 			 * to HSM_ST_LAST. so, the state is changed here
+ 			 * before ata_pio_sectors().
+ 			 */
+ 			ap->hsm_task_state = HSM_ST;
+ 			ata_pio_sectors(qc);
+ 		} else {
+ 			printf("protocol is not ATA_PROT_PIO \n");
+ 		}
+ 		break;
+
+ 	case HSM_ST:
+ 		/* complete command or read/write the data register */
+ 		/* ATA PIO protocol */
+ 		if ((status & ATA_DRQ) == 0) {
+ 			/* handle BSY=0, DRQ=0 as error */
+ 			if (status & (ATA_ERR | ATA_DF)){
+ 				/* device stops HSM for abort/error */
+ 				qc->err_mask |= AC_ERR_DEV;
+ 			} else {
+ 				/* HSM violation. Let EH handle this.
+ 				 * Phantom devices also trigger this
+ 				 * condition.  Mark hint.
+ 				 */
+ 				qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT;
+ 			}
+
+ 			ap->hsm_task_state = HSM_ST_ERR;
+ 			goto fsm_start;
+ 		}
+ 		/* For PIO reads, some devices may ask for
+ 		 * data transfer (DRQ=1) alone with ERR=1.
+ 		 * We respect DRQ here and transfer one
+ 		 * block of junk data before changing the
+ 		 * hsm_task_state to HSM_ST_ERR.
+ 		 *
+ 		 * For PIO writes, ERR=1 DRQ=1 doesn't make
+ 		 * sense since the data block has been
+ 		 * transferred to the device.
+ 		 */
+ 		if (status & (ATA_ERR | ATA_DF)) {
+ 			/* data might be corrputed */
+ 			qc->err_mask |= AC_ERR_DEV;
+
+ 			if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+ 				ata_pio_sectors(qc);
+ 				status = ata_wait_idle(ap);
+ 			}
+
+ 			if (status & (ATA_BUSY | ATA_DRQ)){
+ 				qc->err_mask |= AC_ERR_HSM;
+ 			}
+
+ 			/* ata_pio_sectors() might change the
+ 			 * state to HSM_ST_LAST. so, the state
+ 			 * is changed after ata_pio_sectors().
+ 			 */
+ 			ap->hsm_task_state = HSM_ST_ERR;
+ 			goto fsm_start;
+ 		}
+
+ 		ata_pio_sectors(qc);
+ 		if (ap->hsm_task_state == HSM_ST_LAST &&
+ 			(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+ 			/* all data read */
+ 			status = ata_wait_idle(ap);
+ 			goto fsm_start;
+ 		}
+
+ 		poll_next = 1;
+ 		break;
+
+ 	case HSM_ST_LAST:
+ 		if (!ata_ok(status)) {
+ 			qc->err_mask |= __ac_err_mask(status);
+ 			ap->hsm_task_state = HSM_ST_ERR;
+ 			goto fsm_start;
+ 		}
+
+ 		/* no more data to transfer */
+ 		ap->hsm_task_state = HSM_ST_IDLE;
+
+ 		/* complete taskfile transaction */
+ 		ata_hsm_qc_complete(qc, in_wq);
+
+ 		poll_next = 0;
+ 		break;
+
+ 	case HSM_ST_ERR:
+ 		/* make sure qc->err_mask is available to
+ 		 * know what's wrong and recover
+ 		 */
+ 		ap->hsm_task_state = HSM_ST_IDLE;
+
+ 		/* complete taskfile transaction */
+ 		ata_hsm_qc_complete(qc, in_wq);
+
+ 		poll_next = 0;
+ 		break;
+ 	default:
+ 		poll_next = 0;
+ 	}
+
+ 	return poll_next;
+ }
+
+ int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+ {
+ 	if (qc->tf.flags & ATA_TFLAG_POLLING)
+ 		return 1;
+
+ 	if (ap->hsm_task_state == HSM_ST_FIRST) {
+ 		if (ata_is_atapi(qc->tf.protocol) &&
+ 			!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+ 			return 1;
+ 	}
+
+ 	return 0;
+ }
+
+ void ata_pio_sectors(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap;
+ 	ap = pap;
+ 	qc->pdata = ap->pdata;
+
+ 	if (is_multi_taskfile(&qc->tf)) {
+ 		/* READ/WRITE MULTIPLE */
+ 		unsigned int nsect;
+
+ 		nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
+ 			qc->dev->multi_count);
+ 		while (nsect--)
+ 			ata_pio_sector(qc);
+ 	} else {
+ 		ata_pio_sector(qc);
+ 	}
+
+ 	readb(qc->ap->ioaddr.altstatus_addr);
+ 	udelay(1);
+ }
+
+ void ata_pio_sector(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	unsigned int offset;
+ 	unsigned char *buf;
+
+ 	if (qc->curbytes == qc->nbytes - qc->sect_size){
+ 		ap->hsm_task_state = HSM_ST_LAST;
+ 	}
+
+ 	offset = qc->curbytes;
+
+ 	/* check cmd and set buffer */
+ 	switch (qc->tf.command) {
+ 	case ATA_CMD_ID_ATA:		/* IDENTIFY */
+ 		buf = &ata_device.id[0];
+ 		break;
+ 	case ATA_CMD_PIO_READ_EXT:	/* READ SECTORS EX 0x24 */
+ 	case ATA_CMD_PIO_READ:		/* READ SECTORS 0x20 */
+ 		buf = qc->pdata + offset;
+ 		break;
+ 	default:
+ 		buf = &temp_data_buf[0];
+ 	}		
+
+ 	/* data xfer */
+ 	ata_mmio_data_xfer(qc->dev, buf, qc->sect_size);
+
+ 	qc->curbytes += qc->sect_size;
+
+ }
+
+ void ata_mmio_data_xfer(struct ata_device *dev, unsigned char *buf,
+ 				unsigned int buflen)
+ {
+ 	struct ata_port *ap = pap;
+ 	void __iomem *data_addr = ap->ioaddr.data_addr;
+ 	unsigned int words = buflen >> 1;
+ 	u16 *buf16 = (u16 *)buf;
+ 	unsigned int i = 0;
+
+ 	udelay(100);
+ 	/* Transfer */
+ 	for(i=0; i < words; i++)
+ 		buf16[i] = cpu_to_le16(readw(data_addr));
+
+ 	/* Transfer trailing 1 byte, if any. */
+ 	if (buflen & 0x01) {
+ 		__le16 align_buf[1] = { 0 };
+ 		unsigned char *trailing_buf = buf + buflen - 1;
+
+ 		align_buf[0] = cpu_to_le16(readw(data_addr));
+ 		memcpy(trailing_buf, align_buf, 1);
+ 		words++;
+ 	}
+ }
+
+ void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+ 	struct ata_port *ap = qc->ap;
+
+ 	if (in_wq) {
+ 		/* EH might have kicked in while host lock is
+ 		 * released.
+ 		 */
+ 		qc = &ap->qcmd[qc->tag];
+ 		if (qc) {
+ 			if (!(qc->err_mask & AC_ERR_HSM)) {
+ 				ata_irq_on(ap);
+ 				ata_qc_complete(qc);
+ 			} else {
+ 				ata_port_freeze(ap);
+ 			}
+ 		}
+ 	} else {
+ 		if (!(qc->err_mask & AC_ERR_HSM)) {
+ 			ata_qc_complete(qc);
+ 		} else {
+ 			ata_port_freeze(ap);
+ 		}
+ 	}
+ }
+
+ u8 ata_irq_on(struct ata_port *ap)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	u8 tmp;
+
+ 	ap->ctl &= ~ATA_NIEN;
+ 	ap->last_ctl = ap->ctl;
+
+ 	if (ioaddr->ctl_addr)
+ 		writeb(ap->ctl, ioaddr->ctl_addr);
+
+ 	tmp = ata_wait_idle(ap);
+
+ 	return tmp;
+ }
+
+ void sata_dwc_probe(void)
+ {
+ 	struct sata_dwc_device hsdev;
+ 	struct ata_host host;
+ 	struct ata_port_info pi = sata_dwc_port_info[0];
+ 	struct ata_device *ata_dev = &ata_device;
+ 	struct ata_link *link;
+         struct sata_dwc_device_port hsdevp = dwc_devp;
+ 	u8 *base = 0;
+ 	u8 *sata_dma_regs_addr = 0;
+ 	u32 idr, versionr;
+         u8 status;
+ 	unsigned long base_addr = 0;
+ 	int chan = 0;
+ 	int rc;
+ 	int i;
+ 	const u16 *id;
+ 	unsigned long xfer_mask;
+ 	char revbuf[7];         /* XYZ-99\0 */
+ 	unsigned long pio_mask, mwdma_mask, udma_mask;
+
+ 	phost = &host;	/* set grobal */
+
+ 	/* Base address */
+ 	base = (u8*)SATA_BASE_ADDR;
+
+ 	/* SATA register init */
+ 	hsdev.sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+
+ 	host.n_ports = SATA_DWC_MAX_PORTS;
+
+ 	for(i = 0; i < SATA_DWC_MAX_PORTS; i++){
+ 		ap.pflags |= ATA_PFLAG_INITIALIZING;
+ 		ap.flags = ATA_FLAG_DISABLED;
+ 		ap.print_id = -1;
+ 		ap.ctl = ATA_DEVCTL_OBS;
+ 		ap.host = &host;
+ 		ap.last_ctl = 0xFF;
+ 		ap.dev = &ata_device;
+
+ 		link = &ap.link;
+ 		link->ap = &ap;
+ 		link->pmp = 0;
+ 		link->active_tag = ATA_TAG_POISON;
+ 		link->hw_sata_spd_limit = 0;
+
+ 		ap.port_no = i;
+ 		host.ports[i] = &ap;
+ 	}
+
+ 	ap.pio_mask = pi.pio_mask;
+ 	ap.mwdma_mask = pi.mwdma_mask;
+ 	ap.udma_mask = pi.udma_mask;
+ 	ap.flags |= pi.flags;
+ 	ap.link.flags |= pi.link_flags;
+
+ 	/* Host port init */
+ 	host.ports[0]->ioaddr.cmd_addr = base;
+ 	host.ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
+ 	scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
+
+ 	/* sata_dwc setup port */
+ 	base_addr = (unsigned long)base;
+
+ 	host.ports[0]->ioaddr.cmd_addr = (void *)base_addr + 0x00;
+ 	host.ports[0]->ioaddr.data_addr = (void *)base_addr + 0x00;
+
+ 	host.ports[0]->ioaddr.error_addr = (void *)base_addr + 0x04;
+ 	host.ports[0]->ioaddr.feature_addr = (void *)base_addr + 0x04;
+
+ 	host.ports[0]->ioaddr.nsect_addr = (void *)base_addr + 0x08;
+
+ 	host.ports[0]->ioaddr.lbal_addr = (void *)base_addr + 0x0c;
+ 	host.ports[0]->ioaddr.lbam_addr = (void *)base_addr + 0x10;
+ 	host.ports[0]->ioaddr.lbah_addr = (void *)base_addr + 0x14;
+
+ 	host.ports[0]->ioaddr.device_addr = (void *)base_addr + 0x18;
+ 	host.ports[0]->ioaddr.command_addr = (void *)base_addr + 0x1c;
+ 	host.ports[0]->ioaddr.status_addr = (void *)base_addr + 0x1c;
+
+ 	host.ports[0]->ioaddr.altstatus_addr = (void *)base_addr + 0x20;
+ 	host.ports[0]->ioaddr.ctl_addr = (void *)base_addr + 0x20;
+
+ 	/* Get Host ID / Version */
+ 	idr = in_le32(&hsdev.sata_dwc_regs->idr);
+ 	versionr = in_le32(&hsdev.sata_dwc_regs->versionr);
+
+ 	/* DMA register init */
+ 	sata_dma_regs_addr = (u8*)SATA_DMA_REG_ADDR;
+ 	sata_dma_regs = (void *__iomem)sata_dma_regs_addr;
+
+ 	/* DMA channel Interrupt is disable. DMA Enable setup is next. */
+ 	for(chan = 0; chan < DMA_NUM_CHANS; chan++){
+ 		/* DMA Interrupt register(error) mask. */
+ 		out_le32(&(sata_dma_regs->interrupt_mask.error.low),
+ 				DMA_DISABLE_CHAN(chan));
+
+ 		/* DMA Interrupt register(transfer) mask. */
+ 		out_le32(&(sata_dma_regs->interrupt_mask.tfr.low),
+ 				DMA_DISABLE_CHAN(chan));
+ 	}
+
+ 	/* DMA Enable by DMAC Configuration Register */
+ 	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_EN);
+
+ 	/* Enable selective interrupts by setting the interrupt mask register */
+ 	out_le32(&hsdev.sata_dwc_regs->intmr,
+ 		SATA_DWC_INTMR_ERRM |
+ 		SATA_DWC_INTMR_NEWFPM |
+ 		SATA_DWC_INTMR_PMABRTM |
+ 		SATA_DWC_INTMR_DMATM);
+
+ 	/* Unmask the error bits that should trigger an error interrupt by
+ 	 * setting the error mask register.
+ 	 */
+ 	out_le32(&hsdev.sata_dwc_regs->errmr,SATA_DWC_SERROR_ERR_BITS);
+
+ 	hsdev.host = ap.host;
+ 	memset(&hsdevp, 0, sizeof(hsdevp));
+ 	hsdevp.hsdev = &hsdev;
+
+ 	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
+ 		hsdevp.cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
+
+ 	if (ap.port_no == 0)  {
+ 		out_le32(&hsdev.sata_dwc_regs->dmacr,SATA_DWC_DMACR_TXRXCH_CLEAR);
+
+ 		out_le32(&hsdev.sata_dwc_regs->dbtsr,
+ 			(SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+ 			SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
+ 	}
+
+ 	/* Clear any error bits before libata starts issuing commands */
+ 	out_le32((void __iomem *)scr_addr_sstatus + 4,
+ 		in_le32((void __iomem *)scr_addr_sstatus + 4));
+
+ 	/* check altstatus register (find device) */
+ 	status = ata_check_altstatus(&ap);
+
+ 	if(status == 0x7f){
+ 		printf("Hard Disk not found.\n");
+ 		dev_state = SATA_NODEVICE;
+ 		return;
+ 	}
+
+ 	/* waiting for device ready. time out 30sec */
+ 	printf("waitng for device ready.");
+ 	i = 0;
+ 	while(1){
+ 		udelay (10000);         /* 10 ms */
+
+ 		/* read altstatus */
+ 		status = ata_check_altstatus(&ap);
+
+ 		/* status is not busy => break */
+ 		if((status &  ATA_BUSY) == 0){
+ 			printf("\n");
+ 			break;
+ 		}
+ 		
+ 		i++;
+ 		if (i > (ATA_RESET_TIME * 100)) {
+ 			printf("** TimeOUT **\n");
+
+ 			/* bussy set devise state flag */
+ 			dev_state = SATA_NODEVICE;
+ 			return;
+ 		}
+ 		if ((i >= 100) && ((i%100)==0)) {
+ 			printf(".");
+ 		}
+ 	}
+
+ 	/* softreset */
+ 	rc = sata_dwc_softreset(&ap);
+
+ 	if(rc){
+ 		printf("sata_dwc : error. soft reset failed\n");
+ 	}
+
+ 	/* waiting for device ready. time out 30sec */
+ 	printf("waitng for device ready.");
+ 	i = 0;
+ 	while(1){
+ 		udelay (10000);         /* 10 ms */
+
+ 		/* read altstatus */
+ 		status = ata_check_altstatus(&ap);
+
+ 		/* status is not busy => break */
+ 		if((status &  ATA_BUSY) == 0){
+ 			printf("\n");
+ 			break;
+ 		}
+ 		
+ 		i++;
+ 		if (i > (ATA_RESET_TIME * 100)) {
+ 			printf("** TimeOUT **\n");
+
+ 			/* bussy set devise state flag */
+ 			dev_state = SATA_NODEVICE;
+ 			return;
+ 		}
+ 		if ((i >= 100) && ((i%100)==0)) {
+ 			printf(".");
+ 		}
+ 	}
+
+ 	udelay (1000);         /* before IDENTIFY command safety delay 1 ms */
+
+ 	/* IDENTIFY command send */
+ 	rc = ata_dev_read_id(ata_dev, &ata_dev->class,
+ 			ATA_READID_POSTRESET,ata_dev->id);
+
+ 	if(rc){
+ 		printf("sata_dwc : error. IDENTIFY Command failed\n");
+ 	}
+
+ 	/* SATA drives indicate we have a bridge. We don't know which
+ 	 * end of the link the bridge is which is a problem
+ 	 */
+ 	if (ata_id_is_sata(ata_dev->id))
+ 		ap.cbl = ATA_CBL_SATA;
+
+ 	id = ata_dev->id;
+
+ 	/* initialize to be configured parameters */
+ 	ata_dev->flags &= ~ATA_DFLAG_CFG_MASK;
+ 	ata_dev->max_sectors = 0;
+ 	ata_dev->cdb_len = 0;
+ 	ata_dev->n_sectors = 0;
+ 	ata_dev->cylinders = 0;
+ 	ata_dev->heads = 0;
+ 	ata_dev->sectors = 0;
+
+ 	/* Usual case. Word 53 indicates word 64 is valid */
+ 	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+ 		pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+ 		pio_mask <<= 3;
+ 		pio_mask |= 0x7;
+ 	} else {
+ 		/* If word 64 isn't valid then Word 51 high byte holds
+ 		 * the PIO timing number for the maximum. Turn it into
+ 		 * a mask.
+ 		 */
+ 		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
+ 		if (mode < 5){   /* Valid PIO range */
+ 			pio_mask = (2 << mode) - 1;
+ 		} else {
+ 			pio_mask = 1;
+ 		}
+ 	}
+
+ 	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+ 	if (ata_id_is_cfa(id)) {
+ 		/*
+ 		 *	Process compact flash extended modes
+ 		 */
+ 		int pio = id[163] & 0x7;
+ 		int dma = (id[163] >> 3) & 7;
+
+ 		if (pio)
+ 			pio_mask |= (1 << 5);
+ 		if (pio > 1)
+ 			pio_mask |= (1 << 6);
+ 		if (dma)
+ 			mwdma_mask |= (1 << 3);
+ 		if (dma > 1)
+ 			mwdma_mask |= (1 << 4);
+ 	}
+
+ 	udma_mask = 0;
+ 	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+ 		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+ 	xfer_mask = (pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO |
+ 		(mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA |
+ 		(udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
+
+ 	/* ATA-specific feature tests */
+ 	if (ata_dev->class == ATA_DEV_ATA) {
+ 		if (ata_id_is_cfa(id)) {
+ 			if (id[162] & 1) /* CPRM may make this media unusable */
+ 				printf("supports DRM functions and may "
+ 					"not be fully accessable.\n");
+ 			sprintf(revbuf, "%s", "CFA");
+ 		} else {
+ 			/* Warn the user if the device has TPM extensions */
+ 			if (ata_id_has_tpm(id))
+ 				printf("supports DRM functions and may "
+ 						"not be fully accessable.\n");
+ 		}
+
+ 		/* set n_secters */
+ 		ata_dev->n_sectors = ata_id_n_sectors((u16*)id);
+
+ 		if (ata_dev->id[59] & 0x100)
+ 			ata_dev->multi_count = ata_dev->id[59] & 0xff;
+
+ 		if (ata_id_has_lba(id)) {
+ 			const char *lba_desc;
+ 			char ncq_desc[20];
+
+ 			lba_desc = "LBA";
+ 			ata_dev->flags |= ATA_DFLAG_LBA;
+ 			if (ata_id_has_lba48(id)) {
+ 				ata_dev->flags |= ATA_DFLAG_LBA48;
+ 				lba_desc = "LBA48";
+
+ 				if (ata_dev->n_sectors >= (1UL << 28) &&
+ 					ata_id_has_flush_ext(id))
+ 					ata_dev->flags |= ATA_DFLAG_FLUSH_EXT;
+ 			}
+ 			/* config NCQ */
+ 			if (!ata_id_has_ncq(ata_dev->id)) {
+ 				ncq_desc[0] = '\0';
+ 			}
+
+ 			if (ata_dev->horkage & ATA_HORKAGE_NONCQ) {
+ 				sprintf(ncq_desc, "%s", "NCQ (not used)");
+ 			}
+
+ 			if (ap.flags & ATA_FLAG_NCQ) {
+ 				ata_dev->flags |= ATA_DFLAG_NCQ;
+ 			}
+ 		}
+ 		ata_dev->cdb_len = 16;
+ 	}
+ 	/* determine max_sectors */
+ 	ata_dev->max_sectors = ATA_MAX_SECTORS;
+ 	if (ata_dev->flags & ATA_DFLAG_LBA48)
+ 		ata_dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
+ 	if (!(ata_dev->horkage & ATA_HORKAGE_IPM)) {
+ 		if (ata_id_has_hipm(ata_dev->id))
+ 			ata_dev->flags |= ATA_DFLAG_HIPM;
+ 		if (ata_id_has_dipm(ata_dev->id))
+ 			ata_dev->flags |= ATA_DFLAG_DIPM;
+ 	}
+
+ 	if ((ap.cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ata_dev->id))) {
+ 		ata_dev->udma_mask &= ATA_UDMA5;
+ 		ata_dev->max_sectors = ATA_MAX_SECTORS;
+ 	}
+
+ 	if (ata_dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+ 		printf("Drive reports diagnostics failure."
+ 				"This may indicate a drive\n");
+ 		printf("fault or invalid emulation."
+ 				"Contact drive vendor for information.\n");
+ 	}
+
+ 	/* Hard Disk status check : test send READ Command */
+ 	rc = check_sata_dev_state();
+ }
+
+ int sata_dwc_softreset(struct ata_port *ap)
+ {
+ 	u8 nsect,lbal = 0;
+ 	u8 tmp = 0;
+ 	u32 serror = 0;
+ 	u8 status = 0;
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ 	/* read SCR ERROR */
+ 	serror = in_le32((void *)ap->ioaddr.scr_addr + (SCR_ERROR * 4));
+
+ 	/* device check */
+ 	writeb(0x55, ioaddr->nsect_addr);
+ 	writeb(0xaa, ioaddr->lbal_addr);
+ 	writeb(0xaa, ioaddr->nsect_addr);
+ 	writeb(0x55, ioaddr->lbal_addr);
+ 	writeb(0x55, ioaddr->nsect_addr);
+ 	writeb(0xaa, ioaddr->lbal_addr);
+
+ 	nsect = readb(ioaddr->nsect_addr);
+ 	lbal = readb(ioaddr->lbal_addr);
+
+ 	if ((nsect == 0x55) && (lbal == 0xaa)){
+ 		/* we found a device */
+ 		printf("we found a device\n");
+ 	} else {
+ 		/* nothing found */
+ 		printf("Not found a device.\n");
+ 		dev_state = SATA_NODEVICE;
+ 		return FALSE;
+ 	}
+
+ 	tmp = ATA_DEVICE_OBS;
+ 	writeb(tmp,ioaddr->device_addr);
+ 	writeb(ap->ctl,ioaddr->ctl_addr);
+
+ 	udelay(200);
+
+ 	/* set softreset */
+ 	writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+
+ 	udelay(200);
+ 	writeb(ap->ctl,ioaddr->ctl_addr);
+
+ 	/* wait a while before cheking status */
+ 	msleep(150);
+ 	status = ata_check_status(ap);
+
+ 	msleep(50);
+ 	ata_check_status(ap);
+
+ 	while (1) {
+ 		u8 status = ata_check_status(ap);
+
+ 		if (!(status & ATA_BUSY)){
+ 			break;
+ 		}
+
+ 		status = in_le32((void *)ap->ioaddr.scr_addr + (SCR_STATUS * 4));
+ 		if(status == 0xff || (status & 0xf) != 0x3){
+ 		}
+
+ 		printf("Hard Disk status is BUSY.\n");
+ 		msleep(50);
+ 	}
+
+ 	tmp = ATA_DEVICE_OBS;
+ 	writeb(tmp,ioaddr->device_addr);
+
+ 	nsect = readb(ioaddr->nsect_addr);
+ 	lbal = readb(ioaddr->lbal_addr);
+
+ 	return 0;
+ }
+
+ void scsi_bus_reset()
+ {
+ 	struct ata_port *ap = pap;
+
+ 	/* check device state */
+ 	if(dev_state != SATA_READY){
+ 		printf("no devices available\n");
+ 		return;
+ 	}
+
+ 	/*soft reset process*/
+ 	sata_dwc_softreset(ap);
+ }
+
+ void scsi_print_error(ccb * pccb)
+ {
+ 	/*The ahci error info can be read in the ahci driver*/
+ }
+
+ int ata_dev_read_sectors(ccb *pccb)
+ {
+ 	struct ata_port *ap = pap;
+ 	struct ata_device *dev = &ata_device;
+ 	struct ata_taskfile tf;
+ 	unsigned int class = ATA_DEV_ATA;
+ 	unsigned int err_mask = 0;
+ 	const char *reason;
+ 	int may_fallback = 1;
+ 	int rc;
+
+ 	u32 block=0;
+ 	u32 n_block=0;
+
+ 	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+
+ retry:
+ 	memset(&tf, 0, sizeof(tf));
+ 	tf.ctl = ap->ctl;	/*ap->ctl = 0x08 */
+ 	ap->print_id = 1;
+ 	ap->flags &= ~ATA_FLAG_DISABLED;
+
+ 	/* set pdata */
+ 	ap->pdata = pccb->pdata;
+
+ 	tf.device = ATA_DEVICE_OBS;
+
+ 	block |= ((u32)pccb->cmd[2]) << 24;
+ 	block |= ((u32)pccb->cmd[3]) << 16;
+ 	block |= ((u32)pccb->cmd[4]) << 8;
+ 	block |= ((u32)pccb->cmd[5]);
+
+ 	n_block |= ((u32)pccb->cmd[7]) << 8;
+ 	n_block |= ((u32)pccb->cmd[8]);
+
+ 	/* trying temp to n_block */
+ 	temp_n_block = n_block;
+
+
+ #ifdef CONFIG_LBA48
+ 	tf.command = ATA_CMD_PIO_READ_EXT;  /* READ SECTOR(S) EXT 0x24 */
+ 	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+ 	tf.hob_feature = 31;
+ 	tf.feature = 31;
+ 	tf.hob_nsect = (n_block >> 8) & 0xff;
+ 	tf.nsect = n_block & 0xff;
+
+ 	tf.hob_lbah = 0x0;
+ 	tf.hob_lbam = 0x0;
+ 	tf.hob_lbal = (block >> 24) & 0xff;
+ 	tf.lbah = (block >> 16) & 0xff;
+ 	tf.lbam = (block >> 8) & 0xff;
+ 	tf.lbal = block & 0xff;
+
+ 	tf.device = 1 << 6;
+ 	if (tf.flags & ATA_TFLAG_FUA)
+ 		tf.device |= 1 << 7;
+ #else	/* LBA24  */
+ 	tf.command = ATA_CMD_PIO_READ;  /* READ SECTOR(S) 0x20 */
+ 	tf.flags |= ATA_TFLAG_LBA ;
+
+ 	tf.feature = 31;
+ 	tf.nsect = n_block & 0xff;
+
+ 	tf.lbah = (block >> 16) & 0xff;
+ 	tf.lbam = (block >> 8) & 0xff;
+ 	tf.lbal = block & 0xff;
+
+ 	tf.device = (block >> 24) & 0xf;
+
+ 	tf.device |= 1 << 6;
+ 	if (tf.flags & ATA_TFLAG_FUA)
+ 		tf.device |= 1 << 7;
+
+ #endif	/* CONFIG_LBA48 */
+
+ 	tf.protocol = ATA_PROT_PIO;
+
+ 	/* Some devices choke if TF registers contain garbage.  Make
+ 	 * sure those are properly initialized.
+ 	 */
+ 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ 	tf.flags |= ATA_TFLAG_POLLING;
+
+ 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+ 	if (err_mask) {
+ 		if (err_mask & AC_ERR_NODEV_HINT) {
+ 			printf("READ_SECTORS NODEV after polling detection\n");
+ 			return -ENOENT;
+ 		}
+
+ 		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+ 			/* Device or controller might have reported
+ 			 * the wrong device class.  Give a shot at the
+ 			 * other IDENTIFY if the current one is
+ 			 * aborted by the device.
+ 			 */
+ 			if (may_fallback) {
+ 				may_fallback = 0;
+
+ 				if (class == ATA_DEV_ATA) {
+ 					class = ATA_DEV_ATAPI;
+ 				} else {
+ 					class = ATA_DEV_ATA;
+ 				}
+ 				goto retry;
+ 			}
+ 			/* Control reaches here iff the device aborted
+ 			 * both flavors of IDENTIFYs which happens
+ 			 * sometimes with phantom devices.
+ 			 */
+ 			printf("both IDENTIFYs aborted, assuming NODEV\n");
+ 			return -ENOENT;
+ 		}
+
+ 		rc = -EIO;
+ 		reason = "I/O error";
+ 		goto err_out;
+ 	}
+
+ 	/* Falling back doesn't make sense if ID data was read
+ 	 * successfully at least once.
+ 	 */
+ 	may_fallback = 0;
+
+ 	/* sanity check */
+ 	rc = -EINVAL;
+ 	reason = "device reports invalid type";
+
+ 	return 0;
+
+ err_out:
+ 	printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+ 	return rc;
+ }
diff -crN u-boot-2009.03/drivers/block/sata_dwc.h
u-boot-2009.03-sata/drivers/block/sata_dwc.h
*** u-boot-2009.03/drivers/block/sata_dwc.h	1970-01-01
09:00:00.000000000 +0900
--- u-boot-2009.03-sata/drivers/block/sata_dwc.h	2009-03-23
19:22:31.000000000 +0900
***************
*** 0 ****
--- 1,495 ----
+ /*
+  * sata_dwc.h
+  *
+  * Synopsys DesignWare Cores (DWC) SATA host driver
+  *
+  * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+  *
+  * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+  * Copyright 2008 DENX Software Engineering
+  *
+  * Based on versions provided by AMCC and Synopsys which are:
+  *          Copyright 2006 Applied Micro Circuits Corporation
+  *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+  *
+  * This program is free software; you can redistribute  it and/or
modify it
+  * under  the terms of  the GNU General  Public License as published
by the
+  * Free Software Foundation;  either version 2 of the  License, or (at
your
+  * option) any later version.
+  *
+  */
+
+ #ifndef _SATA_DWC_H_
+ #define _SATA_DWC_H_
+
+ #define HZ 100
+
+ #define READ 0
+ #define WRITE 1
+
+ static int ata_id_has_hipm(const u16 *id)
+ {
+ 	u16 val = id[76];
+
+ 	if (val == 0 || val == 0xffff)
+ 		return -1;
+
+ 	return val & (1 << 9);
+ }
+
+ static int ata_id_has_dipm(const u16 *id)
+ {
+ 	u16 val = id[78];
+
+ 	if (val == 0 || val == 0xffff)
+ 		return -1;
+
+ 	return val & (1 << 3);
+ }
+
+ enum {
+ 	ATA_READID_POSTRESET	= (1 << 0),	/* reading ID after reset */
+
+ 	ATA_DNXFER_PIO		= 0,	/* speed down PIO */
+ 	ATA_DNXFER_DMA		= 1,	/* speed down DMA */
+ 	ATA_DNXFER_40C		= 2,	/* apply 40c cable limit */
+ 	ATA_DNXFER_FORCE_PIO	= 3,	/* force PIO */
+ 	ATA_DNXFER_FORCE_PIO0	= 4,	/* force PIO0 */
+
+ 	ATA_DNXFER_QUIET	= (1 << 31),
+ };
+
+ enum hsm_task_states {
+ 	HSM_ST_IDLE,		/* no command on going */
+ 	HSM_ST_FIRST,		/* (waiting the device to)
+ 				 * write CDB or first data block */
+ 	HSM_ST,			/* (waiting the device to) transfer data */
+ 	HSM_ST_LAST,		/* (waiting the device to) complete command */
+ 	HSM_ST_ERR,		/* error */
+ };
+
+ #define	ATA_SHORT_PAUSE		((HZ >> 6) + 1)
+
+ typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+
+ struct ata_queued_cmd {
+ 	struct ata_port		*ap;
+ 	struct ata_device	*dev;
+
+ 	struct ata_taskfile	tf;
+ 	u8			cdb[ATAPI_CDB_LEN];
+
+ 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
+ 	unsigned int		tag;
+ 	unsigned int		n_elem;
+
+ 	int			dma_dir;
+
+ 	unsigned int		sect_size;
+
+ 	unsigned int		nbytes;
+ 	unsigned int		extrabytes;
+ 	unsigned int		curbytes;
+
+ 	unsigned int		err_mask;
+ 	struct ata_taskfile	result_tf;
+
+ 	void			*private_data;
+ 	void			*lldd_task;
+ 	unsigned char		*pdata;
+ };
+
+ /* defines only for the constants which don't work cell as enums*/
+ #define ATA_TAG_POISON	0xfafbfcfdU
+
+ enum {
+ 	/* various global constants */
+ 	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+ 	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,	/* Worst case */
+ 	ATA_MAX_PORTS		= 8,
+ 	ATA_DEF_QUEUE		= 1,
+ 	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
+ 	ATA_MAX_QUEUE		= 32,
+ 	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
+ 	ATA_MAX_BUS		= 2,
+ 	ATA_DEF_BUSY_WAIT	= 10000,
+
+ 	ATAPI_MAX_DRAIN		= 16 << 10,
+
+ 	ATA_SHT_EMULATED	= 1,
+ 	ATA_SHT_CMD_PER_LUN	= 1,
+ 	ATA_SHT_THIS_ID		= -1,
+ 	ATA_SHT_USE_CLUSTERING	= 1,
+
+ 	/* struct ata_device stuff */
+ 	ATA_DFLAG_LBA		= (1 << 0),	/* device supports LBA */
+ 	ATA_DFLAG_LBA48		= (1 << 1),	/* device supports LBA48 */
+ 	ATA_DFLAG_CDB_INTR	= (1 << 2),	/* device asserts INTRQ */
+ 	ATA_DFLAG_NCQ		= (1 << 3),	/* device supports NCQ */
+ 	ATA_DFLAG_FLUSH_EXT	= (1 << 4),	/* do FLUSH_EXT instead of FLUSH */
+ 	ATA_DFLAG_ACPI_PENDING 	= (1 << 5),	/* ACPI resume action pending */
+ 	ATA_DFLAG_ACPI_FAILED	= (1 << 6),	/* ACPI on devcfg has failed */
+ 	ATA_DFLAG_AN		= (1 << 7),	/* AN configured */
+ 	ATA_DFLAG_HIPM		= (1 << 8),	/* device supports HIPM */
+ 	ATA_DFLAG_DIPM		= (1 << 9),	/* device supports DIPM */
+ 	ATA_DFLAG_DMADIR	= (1 << 10),	/* device requires DMADIR */
+ 	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
+
+ 	ATA_DFLAG_PIO		= (1 << 12),	/* device limited to PIO mode */
+ 	ATA_DFLAG_NCQ_OFF	= (1 << 13),	/* device limited to non-NCQ mode */
+ 	ATA_DFLAG_SPUNDOWN	= (1 << 14),	/* XXX: for spindown_compat */
+ 	ATA_DFLAG_SLEEPING	= (1 << 15),	/* device is sleeping */
+ 	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16),	/* data transfer not verified */
+ 	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
+
+ 	ATA_DFLAG_DETACH	= (1 << 24),
+ 	ATA_DFLAG_DETACHED	= (1 << 25),
+
+ 	/* struct ata_link flags */
+ 	ATA_LFLAG_HRST_TO_RESUME	= (1 << 0),	/* hardreset to resume link */
+ 	ATA_LFLAG_SKIP_D2H_BSY		= (1 << 1),	/* can't wait for the first D2H
+ 							 * Register FIS clearing BSY */
+ 	ATA_LFLAG_NO_SRST		= (1 << 2),	/* avoid softreset */
+ 	ATA_LFLAG_ASSUME_ATA		= (1 << 3),	/* assume ATA class */
+ 	ATA_LFLAG_ASSUME_SEMB		= (1 << 4),	/* assume SEMB class */
+ 	ATA_LFLAG_ASSUME_CLASS		= ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
+ 	ATA_LFLAG_NO_RETRY		= (1 << 5),	/* don't retry this link */
+ 	ATA_LFLAG_DISABLED		= (1 << 6),	/* link is disabled */
+
+ 	/* struct ata_port flags */
+ 	ATA_FLAG_SLAVE_POSS	= (1 << 0),
+ 	ATA_FLAG_SATA		= (1 << 1),
+ 	ATA_FLAG_NO_LEGACY	= (1 << 2),	/* no legacy mode check */
+ 	ATA_FLAG_MMIO		= (1 << 3),	/* use MMIO, not PIO */
+ 	ATA_FLAG_SRST		= (1 << 4),	/* (obsolete) use ATA SRST, not E.D.D. */
+ 	ATA_FLAG_SATA_RESET	= (1 << 5),	/* (obsolete) use COMRESET */
+ 	ATA_FLAG_NO_ATAPI	= (1 << 6),	/* No ATAPI support */
+ 	ATA_FLAG_PIO_DMA	= (1 << 7),	/* PIO cmds via DMA */
+ 	ATA_FLAG_PIO_LBA48	= (1 << 8),	/* Host DMA engine is LBA28 only */
+ 	ATA_FLAG_PIO_POLLING	= (1 << 9),	/* use polling PIO if LLD
+ 						* doesn't handle PIO interrupts */
+ 	ATA_FLAG_NCQ		= (1 << 10),	/* host supports NCQ */
+ 	ATA_FLAG_DEBUGMSG	= (1 << 13),
+ 	ATA_FLAG_IGN_SIMPLEX	= (1 << 15),	/* ignore SIMPLEX */
+ 	ATA_FLAG_NO_IORDY	= (1 << 16),	/* controller lacks iordy */
+ 	ATA_FLAG_ACPI_SATA	= (1 << 17),	/* need native SATA ACPI layout */
+ 	ATA_FLAG_AN		= (1 << 18),	/* controller supports AN */
+ 	ATA_FLAG_PMP		= (1 << 19),	/* controller supports PMP */
+ 	ATA_FLAG_IPM		= (1 << 20),	/* driver can handle IPM */
+
+ 	ATA_FLAG_DISABLED	= (1 << 23),	/* port is disabled, ignore it */
+
+ 	/* struct ata_port pflags */
+ 	ATA_PFLAG_EH_PENDING		= (1 << 0),	/* EH pending */
+ 	ATA_PFLAG_EH_IN_PROGRESS	= (1 << 1),	/* EH in progress */
+ 	ATA_PFLAG_FROZEN		= (1 << 2),	/* port is frozen */
+ 	ATA_PFLAG_RECOVERED		= (1 << 3),	/* recovery action performed */
+ 	ATA_PFLAG_LOADING		= (1 << 4),	/* boot/loading probe */
+ 	ATA_PFLAG_UNLOADING		= (1 << 5),	/* module is unloading */
+ 	ATA_PFLAG_SCSI_HOTPLUG		= (1 << 6),	/* SCSI hotplug scheduled */
+ 	ATA_PFLAG_INITIALIZING		= (1 << 7),	/* being initialized, don't touch */
+ 	ATA_PFLAG_RESETTING		= (1 << 8),	/* reset in progress */
+ 	ATA_PFLAG_SUSPENDED		= (1 << 17),	/* port is suspended (power) */
+ 	ATA_PFLAG_PM_PENDING		= (1 << 18),	/* PM operation pending */
+
+ 	/* struct ata_queued_cmd flags */
+ 	ATA_QCFLAG_ACTIVE	= (1 << 0),	/* cmd not yet ack'd to scsi lyer */
+ 	ATA_QCFLAG_DMAMAP	= (1 << 1),	/* SG table is DMA mapped */
+ 	ATA_QCFLAG_IO		= (1 << 3),	/* standard IO command */
+ 	ATA_QCFLAG_RESULT_TF	= (1 << 4),	/* result TF requested */
+ 	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5),	/* clear excl_link on completion */
+ 	ATA_QCFLAG_QUIET	= (1 << 6),	/* don't report device error */
+
+ 	ATA_QCFLAG_FAILED	= (1 << 16),	/* cmd failed and is owned by EH */
+ 	ATA_QCFLAG_SENSE_VALID	= (1 << 17),	/* sense data valid */
+ 	ATA_QCFLAG_EH_SCHEDULED	= (1 << 18),	/* EH scheduled (obsolete) */
+
+ 	/* host set flags */
+ 	ATA_HOST_SIMPLEX	= (1 << 0),
+ 	ATA_HOST_STARTED	= (1 << 1),	/* Host started */
+
+ 	/* various lengths of time */
+ 	ATA_TMOUT_BOOT			= 30 * 100,	/* heuristic */
+ 	ATA_TMOUT_BOOT_QUICK		= 7 * 100,	/* heuristic */
+ 	ATA_TMOUT_INTERNAL		= 30 * 100,
+ 	ATA_TMOUT_INTERNAL_QUICK	= 5 * 100,
+
+ 	/* FIXME: GoVault needs 2s but we can't afford that without
+ 	 * parallel probing.  800ms is enough for iVDR disk
+ 	 * HHD424020F7SV00.  Increase to 2secs when parallel probing
+ 	 * is in place.
+ 	 */
+ 	ATA_TMOUT_FF_WAIT	= 4 * 100 / 5,
+
+ 	/* ATA bus states */
+ 	BUS_UNKNOWN		= 0,
+ 	BUS_DMA			= 1,
+ 	BUS_IDLE		= 2,
+ 	BUS_NOINTR		= 3,
+ 	BUS_NODATA		= 4,
+ 	BUS_TIMER		= 5,
+ 	BUS_PIO			= 6,
+ 	BUS_EDD			= 7,
+ 	BUS_IDENTIFY		= 8,
+ 	BUS_PACKET		= 9,
+
+ 	/* SATA port states */
+ 	PORT_UNKNOWN		= 0,
+ 	PORT_ENABLED		= 1,
+ 	PORT_DISABLED		= 2,
+
+ 	/* encoding various smaller bitmaps into a single
+ 	 * unsigned long bitmap
+ 	 */
+ 	ATA_NR_PIO_MODES	= 7,
+ 	ATA_NR_MWDMA_MODES	= 5,
+ 	ATA_NR_UDMA_MODES	= 8,
+
+ 	ATA_SHIFT_PIO		= 0,
+ 	ATA_SHIFT_MWDMA		= ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
+ 	ATA_SHIFT_UDMA		= ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
+
+ 	/* size of buffer to pad xfers ending on unaligned boundaries */
+ 	ATA_DMA_PAD_SZ		= 4,
+
+ 	/* ering size */
+ 	ATA_ERING_SIZE		= 32,
+
+ 	ATA_DEFER_LINK		= 1,
+ 	ATA_DEFER_PORT		= 2,
+
+ 	/* desc_len for ata_eh_info and context */
+ 	ATA_EH_DESC_LEN		= 80,
+
+ 	/* reset / recovery action types */
+ 	ATA_EH_REVALIDATE	= (1 << 0),
+ 	ATA_EH_SOFTRESET	= (1 << 1),
+ 	ATA_EH_HARDRESET	= (1 << 2),
+ 	ATA_EH_ENABLE_LINK	= (1 << 3),
+ 	ATA_EH_LPM		= (1 << 4),	/* link power management action */
+
+ 	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+ 	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+ 	/* ata_eh_info->flags */
+ 	ATA_EHI_HOTPLUGGED	= (1 << 0),	/* could have been hotplugged */
+ 	ATA_EHI_RESUME_LINK	= (1 << 1),	/* resume link (reset modifier) */
+ 	ATA_EHI_NO_AUTOPSY	= (1 << 2),	/* no autopsy */
+ 	ATA_EHI_QUIET		= (1 << 3),	/* be quiet */
+
+ 	ATA_EHI_DID_SOFTRESET	= (1 << 16),	/* already soft-reset this port */
+ 	ATA_EHI_DID_HARDRESET	= (1 << 17),	/* already soft-reset this port */
+ 	ATA_EHI_PRINTINFO	= (1 << 18),	/* print configuration info */
+ 	ATA_EHI_SETMODE		= (1 << 19),	/* configure transfer mode */
+ 	ATA_EHI_POST_SETMODE	= (1 << 20),	/* revaildating after setmode */
+
+ 	ATA_EHI_DID_RESET       = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+ 	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+ 	/* max tries if error condition is still set after ->error_handler */
+ 	ATA_EH_MAX_TRIES	= 5,
+
+ 	/* how hard are we gonna try to probe/recover devices */
+ 	ATA_PROBE_MAX_TRIES	= 3,
+ 	ATA_EH_DEV_TRIES	= 3,
+ 	ATA_EH_PMP_TRIES	= 5,
+ 	ATA_EH_PMP_LINK_TRIES	= 3,
+
+ 	SATA_PMP_SCR_TIMEOUT	= 250,
+
+ 	/* Horkage types. May be set by libata or controller on drives
+ 	(some horkage may be drive/controller pair dependant */
+
+ 	ATA_HORKAGE_DIAGNOSTIC	= (1 << 0),	/* Failed boot diag */
+ 	ATA_HORKAGE_NODMA	= (1 << 1),	/* DMA problems */
+ 	ATA_HORKAGE_NONCQ	= (1 << 2),	/* Don't use NCQ */
+ 	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),	/* Limit max sects to 128 */
+ 	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),	/* Broken HPA */
+ 	ATA_HORKAGE_SKIP_PM	= (1 << 5),	/* Skip PM operations */
+ 	ATA_HORKAGE_HPA_SIZE	= (1 << 6),	/* native size off by one */
+ 	ATA_HORKAGE_IPM		= (1 << 7),	/* Link PM problems */
+ 	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */
+ 	ATA_HORKAGE_STUCK_ERR	= (1 << 9),	/* stuck ERR on next PACKET */
+
+ 	/* DMA mask for user DMA control: User visible values; DO NOT renumber */
+ 	ATA_DMA_MASK_ATA	= (1 << 0),	/* DMA on ATA Disk */
+ 	ATA_DMA_MASK_ATAPI	= (1 << 1),	/* DMA on ATAPI */
+ 	ATA_DMA_MASK_CFA	= (1 << 2),	/* DMA on CF Card */
+
+ 	/* ATAPI command types */
+ 	ATAPI_READ		= 0,		/* READs */
+ 	ATAPI_WRITE		= 1,		/* WRITEs */
+ 	ATAPI_READ_CD		= 2,		/* READ CD [MSF] */
+ 	ATAPI_PASS_THRU		= 3,		/* SAT pass-thru */
+ 	ATAPI_MISC		= 4,		/* the rest */
+ };
+
+ enum ata_completion_errors {
+ 	AC_ERR_DEV		= (1 << 0),	/* device reported error */
+ 	AC_ERR_HSM		= (1 << 1),	/* host state machine violation */
+ 	AC_ERR_TIMEOUT		= (1 << 2),	/* timeout */
+ 	AC_ERR_MEDIA		= (1 << 3),	/* media error */
+ 	AC_ERR_ATA_BUS		= (1 << 4),	/* ATA bus error */
+ 	AC_ERR_HOST_BUS		= (1 << 5),	/* host bus error */
+ 	AC_ERR_SYSTEM		= (1 << 6),	/* system error */
+ 	AC_ERR_INVALID		= (1 << 7),	/* invalid argument */
+ 	AC_ERR_OTHER		= (1 << 8),	/* unknown */
+ 	AC_ERR_NODEV_HINT	= (1 << 9),	/* polling device detection hint */
+ 	AC_ERR_NCQ		= (1 << 10),	/* marker for offending NCQ qc */
+ };
+
+ enum ata_xfer_mask {
+ 	ATA_MASK_PIO	= ((1LU << ATA_NR_PIO_MODES) - 1) << ATA_SHIFT_PIO,
+ 	ATA_MASK_MWDMA	= ((1LU << ATA_NR_MWDMA_MODES) - 1) << ATA_SHIFT_MWDMA,
+ 	ATA_MASK_UDMA	= ((1LU << ATA_NR_UDMA_MODES) - 1) << ATA_SHIFT_UDMA,
+ };
+
+ struct ata_port_info {
+ 	struct scsi_host_template	*sht;
+ 	unsigned long			flags;
+ 	unsigned long			link_flags;
+ 	unsigned long			pio_mask;
+ 	unsigned long			mwdma_mask;
+ 	unsigned long			udma_mask;
+ 	const struct ata_port_operations *port_ops;
+ 	void				*private_data;
+ };
+
+ struct ata_ioports {
+ 	void __iomem		*cmd_addr;
+ 	void __iomem		*data_addr;
+ 	void __iomem		*error_addr;
+ 	void __iomem		*feature_addr;
+ 	void __iomem		*nsect_addr;
+ 	void __iomem		*lbal_addr;
+ 	void __iomem		*lbam_addr;
+ 	void __iomem		*lbah_addr;
+ 	void __iomem		*device_addr;
+ 	void __iomem		*status_addr;
+ 	void __iomem		*command_addr;
+ 	void __iomem		*altstatus_addr;
+ 	void __iomem		*ctl_addr;
+ 	void __iomem		*bmdma_addr;
+ 	void __iomem		*scr_addr;
+ };
+
+ struct ata_host {
+ 	void __iomem * const	*iomap;
+ 	unsigned int		n_ports;
+ 	void			*private_data;
+ 	const struct ata_port_operations *ops;
+ 	unsigned long		flags;
+ 	struct ata_port		*simplex_claimed;	/* channel owning the DMA */
+ 	struct ata_port		*ports[0];
+ };
+
+ struct ata_port_stats {
+ 	unsigned long		unhandled_irq;
+ 	unsigned long		idle_irq;
+ 	unsigned long		rw_reqbuf;
+ };
+
+ struct ata_device {
+ 	struct ata_link		*link;
+ 	unsigned int		devno;		/* 0 or 1 */
+ 	unsigned long		flags;		/* ATA_DFLAG_xxx */
+ 	unsigned int		horkage;	/* List of broken features */
+ 	struct scsi_device	*sdev;		/* attached SCSI device */
+ #ifdef CONFIG_ATA_ACPI
+ 	acpi_handle		acpi_handle;
+ 	union acpi_object	*gtf_cache;
+ #endif
+ 	/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
+ 	u64			n_sectors;	/* size of device, if ATA */
+ 	unsigned int		class;		/* ATA_DEV_xxx */
+
+ 	union {
+ 		u16		id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+ 		u32		gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+ 	};
+
+ 	u8			pio_mode;
+ 	u8			dma_mode;
+ 	u8			xfer_mode;
+ 	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
+
+ 	unsigned int		multi_count;	/* sectors count for
+ 						 *READ/WRITE MULTIPLE */
+ 	unsigned int		max_sectors;    /* per-device max sectors */
+ 	unsigned int		cdb_len;
+
+ 	/* per-dev xfer mask */
+ 	unsigned long		pio_mask;
+ 	unsigned long		mwdma_mask;
+ 	unsigned long		udma_mask;
+
+ 	/* for CHS addressing */
+ 	u16			cylinders;	/* Number of cylinders */
+ 	u16			heads;		/* Number of heads */
+ 	u16			sectors;	/* Number of sectors per track */
+
+ 	/* error history */
+ 	int			spdn_cnt;
+ };
+
+ enum dma_data_direction {
+ 	DMA_BIDIRECTIONAL = 0,
+ 	DMA_TO_DEVICE = 1,
+ 	DMA_FROM_DEVICE = 2,
+ 	DMA_NONE = 3,
+ };
+
+ struct ata_link {
+ 	struct ata_port		*ap;
+ 	int			pmp;		/* port multiplier port # */
+ 	unsigned int		active_tag;	/* active tag on this link */
+ 	u32			sactive;	/* active NCQ commands */
+
+ 	unsigned int		flags;		/* ATA_LFLAG_xxx */
+
+ 	unsigned int		hw_sata_spd_limit;
+ 	unsigned int		sata_spd_limit;
+ 	unsigned int		sata_spd;	/* current SATA PHY speed */
+
+ 	struct ata_device	device[2];
+ };
+
+ struct ata_port {
+ 	unsigned long		flags;		/* ATA_FLAG_xxx */
+ 	unsigned int		pflags;		/* ATA_PFLAG_xxx */
+ 	unsigned int		print_id;	/* user visible unique port ID */
+ 	unsigned int            port_no;	/* 0 based port no. inside the host */
+
+ 	struct ata_ioports	ioaddr;		/* ATA cmd/ctl/dma register blocks */
+
+ 	u8			ctl;		/* cache of ATA control register */
+ 	u8			last_ctl;	/* Cache last written value */
+ 	unsigned int		pio_mask;
+ 	unsigned int		mwdma_mask;
+ 	unsigned int		udma_mask;
+ 	unsigned int		cbl;		/* cable type; ATA_CBL_xxx */
+
+ 	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+ 	unsigned long		qc_allocated;
+ 	unsigned int		qc_active;
+ 	int			nr_active_links;	/* #links with active qcs */
+
+ 	struct ata_link		link;		/* host default link */
+
+ 	int			nr_pmp_links;	/* nr of available PMP links */
+ 	struct ata_link		*pmp_link;	/* array of PMP links */
+ 	struct ata_link		*excl_link;	/* for PMP qc exclusion */
+
+ 	struct ata_port_stats	stats;
+ 	struct ata_host		*host;
+
+ 	struct device		*dev;
+ 	void			*port_task_data;
+
+ 	unsigned int		hsm_task_state;
+
+ 	u32			msg_enable;
+ 	void			*private_data;
+ 	unsigned char		*pdata;
+ };
+ #endif	/* _SATA_DWC_H_ */
diff -crN u-boot-2009.03/include/configs/canyonlands.h
u-boot-2009.03-sata/include/configs/canyonlands.h
*** u-boot-2009.03/include/configs/canyonlands.h	2009-03-22
06:04:41.000000000 +0900
--- u-boot-2009.03-sata/include/configs/canyonlands.h	2009-03-24
13:04:12.000000000 +0900
***************
*** 34,39 ****
--- 34,40 ----
  #ifdef CONFIG_CANYONLANDS
  #define CONFIG_460EX		1	/* Specific PPC460EX		*/
  #define CONFIG_HOSTNAME		canyonlands
+ #define CONFIG_SATA_DWC			/* PPC460EX SATA support	*/
  #else
  #define CONFIG_460GT		1	/* Specific PPC460GT		*/
  #ifdef CONFIG_GLACIER
***************
*** 454,459 ****
--- 455,463 ----
  #define CONFIG_CMD_SDRAM
  #define CONFIG_CMD_SNTP
  #define CONFIG_CMD_USB
+ #if defined(CONFIG_SATA_DWC)
+ #define CONFIG_CMD_SCSI
+ #endif
  #elif defined(CONFIG_GLACIER)
  #define CONFIG_CMD_DATE
  #define CONFIG_CMD_DTT
***************
*** 517,522 ****
--- 521,537 ----
  #endif /* CONFIG_460GT */

  /*-----------------------------------------------------------------------
+  * S-ATA driver setup
+  *----------------------------------------------------------------------*/
+ #ifdef CONFIG_SATA_DWC
+ #define CONFIG_LIBATA
+ #define CONFIG_SYS_SCSI_MAX_SCSI_ID	1	/* SCSI ID */
+ #define CONFIG_SYS_SCSI_MAX_LUN		1	/* SCSI LUN */
+ #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID *
CONFIG_SYS_SCSI_MAX_LUN)
+ #define CONFIG_SYS_SCSI_MAXDEVICE	CONFIG_SYS_SCSI_MAX_DEVICE
+ #endif
+
+ /*-----------------------------------------------------------------------
   * External Bus Controller (EBC) Setup
   *----------------------------------------------------------------------*/


Regards,
Kazuaki Ichinohe.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-24  5:22 ` [U-Boot] [PATCH] Canyonlands SATA harddisk driver Kazuaki Ichinohe
@ 2009-03-24 16:22   ` Stefan Roese
  2009-03-25 11:32     ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2009-03-24 16:22 UTC (permalink / raw)
  To: u-boot

On Tuesday 24 March 2009, Kazuaki Ichinohe wrote:
> This patch adds a SATA harddisk driver for the canyonlands.

Thanks.

But your patch is linewrapped and therefor hard to read and can't be applied. 
And the commit message could be a little more descriptive. And please don't 
forget to add you Signed-off-by line next time.

As a general comment I suggest that you take a look at:

http://www.denx.de/wiki/view/U-Boot/Patches

to see how patches should be posted to the list. Best would be to use the git 
tools (git format-patch and git send-email) for patch submission.

I'll make a review in more depth when you send a patch that's not linewrapped.

Thanks again.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-24 16:22   ` Stefan Roese
@ 2009-03-25 11:32     ` Kazuaki Ichinohe
  2009-03-25 16:04       ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-25 11:32 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

Thank you for the reply.
This is the patch that corrects the point.

Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>
---

[patch]
diff -purN u-boot-2009.03/common/cmd_scsi.c u-boot-2009.03-sata/common/cmd_scsi.c
--- u-boot-2009.03/common/cmd_scsi.c	2009-03-22 06:04:41.000000000 +0900
+++ u-boot-2009.03-sata/common/cmd_scsi.c	2009-03-25 18:53:29.000000000 +0900
@@ -47,8 +47,10 @@
  #define SCSI_DEV_ID  0x5288

  #else
+#ifndef CONFIG_SATA_DWC
  #error no scsi device defined
  #endif
+#endif


  static ccb tempccb;	/* temporary scsi command buffer */
@@ -179,6 +181,7 @@ void scsi_init(void)
  {
  	int busdevfunc;

+#ifndef CONFIG_SATA_DWC
  	busdevfunc=pci_find_device(SCSI_VEND_ID,SCSI_DEV_ID,0); /* get PCI Device ID */
  	if(busdevfunc==-1) {
  		printf("Error SCSI Controller (%04X,%04X) not found\n",SCSI_VEND_ID,SCSI_DEV_ID);
@@ -189,7 +192,13 @@ void scsi_init(void)
  		printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",SCSI_VEND_ID,SCSI_DEV_ID,(busdevfunc>>16)&0xFF,(busdevfunc>>11)&0x1F,(busdevfunc>>8)&0x7);
  	}
  #endif
+#endif
+#ifdef CONFIG_SATA_DWC
+	sata_dwc_probe();
+#endif
+#ifndef CONFIG_SATA_DWC
  	scsi_low_level_init(busdevfunc);
+#endif
  	scsi_scan(1);
  }

@@ -444,8 +453,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag,
  /****************************************************************************************
   * scsi_read
   */
-
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SCSI_MAX_READ_BLK 0xFF
+#else
  #define SCSI_MAX_READ_BLK 0xFFFF /* almost the maximum amount of the scsi_ext command.. */
+#endif

  ulong scsi_read(int device, ulong blknr, ulong blkcnt, void *buffer)
  {
diff -purN u-boot-2009.03/drivers/block/Makefile u-boot-2009.03-sata/drivers/block/Makefile
--- u-boot-2009.03/drivers/block/Makefile	2009-03-22 06:04:41.000000000 +0900
+++ u-boot-2009.03-sata/drivers/block/Makefile	2009-03-23 19:22:31.000000000 +0900
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil
  COBJS-$(CONFIG_IDE_SIL680) += sil680.o
  COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
  COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

  COBJS	:= $(COBJS-y)
  SRCS	:= $(COBJS:.o=.c)
diff -purN u-boot-2009.03/drivers/block/sata_dwc.c u-boot-2009.03-sata/drivers/block/sata_dwc.c
--- u-boot-2009.03/drivers/block/sata_dwc.c	1970-01-01 09:00:00.000000000 +0900
+++ u-boot-2009.03-sata/drivers/block/sata_dwc.c	2009-03-25 18:02:07.000000000 +0900
@@ -0,0 +1,2175 @@
+/*
+ * sata_dwc.c
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU
+ * General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <scsi.h>
+#include <ata.h>
+#include <linux/ctype.h>
+
+/* sata_dwc.h */
+#include "sata_dwc.h"
+
+/* Base Address */
+#define SATA_BASE_ADDR		0xe20d1000
+#define SATA_DMA_REG_ADDR	0xe20d0800
+
+/* SATA DMA driver Globals */
+#define DMA_NUM_CHANS			1
+#define DMA_NUM_CHAN_REGS		8
+
+/* SATA DMA Register definitions */
+#define AHB_DMA_BRST_DFLT		16	/* 4 data items burst length */
+
+struct dmareg {
+	u32 low;		/* Low bits 0-31 */
+	u32 high;		/* High bits 32-63 */
+};
+
+/* DMA Per Channel registers */
+struct dma_chan_regs {
+	struct dmareg sar;	/* Source Address */
+	struct dmareg dar;	/* Destination address */
+	struct dmareg llp;	/* Linked List Pointer */
+	struct dmareg ctl;	/* Control */
+	struct dmareg sstat;	/* Source Status not implemented in core */
+	struct dmareg dstat;	/* Destination Status not implemented in core */
+	struct dmareg sstatar;	/* Source Status Address not impl in core */
+	struct dmareg dstatar;	/* Destination Status Address not implemented */
+	struct dmareg cfg;	/* Config */
+	struct dmareg sgr;	/* Source Gather */
+	struct dmareg dsr;	/* Destination Scatter */
+};
+
+/* Generic Interrupt Registers */
+struct dma_interrupt_regs {
+	struct dmareg tfr;	/* Transfer Interrupt */
+	struct dmareg block;	/* Block Interrupt */
+	struct dmareg srctran;	/* Source Transfer Interrupt */
+	struct dmareg dsttran;	/* Dest Transfer Interrupt */
+	struct dmareg error;	/* Error */
+};
+
+struct ahb_dma_regs {
+	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];
+	struct dma_interrupt_regs	interrupt_raw;		/* Raw Interrupt */
+	struct dma_interrupt_regs	interrupt_status;	/* Interrupt Status */
+	struct dma_interrupt_regs	interrupt_mask;		/* Interrupt Mask */
+	struct dma_interrupt_regs	interrupt_clear;	/* Interrupt Clear */
+	struct dmareg			statusInt;		/* Interrupt combined */
+	struct dmareg			rq_srcreg;		/* Src Trans Req */
+	struct dmareg			rq_dstreg;		/* Dst Trans Req */
+	struct dmareg			rq_sgl_srcreg;		/* Sngl Src Trans Req */
+	struct dmareg			rq_sgl_dstreg;		/* Sngl Dst Trans Req */
+	struct dmareg			rq_lst_srcreg;		/* Last Src Trans Req */
+	struct dmareg			rq_lst_dstreg;		/* Last Dst Trans Req */
+	struct dmareg			dma_cfg;		/* DMA Config */
+	struct dmareg			dma_chan_en;		/* DMA Channel Enable */
+	struct dmareg			dma_id;			/* DMA ID */
+	struct dmareg			dma_test;		/* DMA Test */
+	struct dmareg			res1;			/* reserved */
+	struct dmareg			res2;			/* reserved */
+	/* DMA Comp Params
+	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
+	 * Param 4 = dma_param[2] ...
+	 */
+	struct dmareg			dma_params[6];
+};
+
+/* DMA Register Operation Bits */
+#define DMA_EN			0x00000001		/* Enable AHB DMA */
+#define DMA_CHANNEL(ch)		(0x00000001 << (ch))	/* Select channel */
+#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |	\
+				((0x000000001 << (ch)) << 8))	/* Enable channel */
+#define DMA_DISABLE_CHAN(ch)	(0x00000000 | 	\
+				((0x000000001 << (ch)) << 8))	/* Disable channel */
+
+#define SATA_DWC_MAX_PORTS	1
+#define SATA_DWC_SCR_OFFSET	0x24
+#define SATA_DWC_REG_OFFSET	0x64
+
+/* DWC SATA Registers */
+struct sata_dwc_regs {
+	u32 fptagr;		/* 1st party DMA tag */
+	u32 fpbor;		/* 1st party DMA buffer offset */
+	u32 fptcr;		/* 1st party DMA Xfr count */
+	u32 dmacr;		/* DMA Control */
+	u32 dbtsr;		/* DMA Burst Transac size */
+	u32 intpr;		/* Interrupt Pending */
+	u32 intmr;		/* Interrupt Mask */
+	u32 errmr;		/* Error Mask */
+	u32 llcr;		/* Link Layer Control */
+	u32 phycr;		/* PHY Control */
+	u32 physr;		/* PHY Status */
+	u32 rxbistpd;		/* Recvd BIST pattern def register */
+	u32 rxbistpd1;		/* Recvd BIST data dword1 */
+	u32 rxbistpd2;		/* Recvd BIST pattern data dword2 */
+	u32 txbistpd;		/* Trans BIST pattern def register */
+	u32 txbistpd1;		/* Trans BIST data dword1 */
+	u32 txbistpd2;		/* Trans BIST data dword2 */
+	u32 bistcr;		/* BIST Control Register */
+	u32 bistfctr;		/* BIST FIS Count Register */
+	u32 bistsr;		/* BIST Status Register */
+	u32 bistdecr;		/* BIST Dword Error count register */
+	u32 res[15];		/* Reserved locations */
+	u32 testr;		/* Test Register */
+	u32 versionr;		/* Version Register */
+	u32 idr;		/* ID Register */
+	u32 unimpl[192];	/* Unimplemented */
+	u32 dmadr[256];		/* FIFO Locations in DMA Mode */
+};
+
+/* DWC SATA Register Operations */
+#define SATA_DWC_TXFIFO_DEPTH		0x01FF
+#define SATA_DWC_RXFIFO_DEPTH		0x01FF
+
+#define SATA_DWC_DBTSR_MWR(size)	((size/4) & SATA_DWC_TXFIFO_DEPTH)
+#define SATA_DWC_DBTSR_MRD(size)	(((size/4) &	\
+					SATA_DWC_RXFIFO_DEPTH) << 16)
+#define SATA_DWC_INTPR_DMAT		0x00000001
+#define SATA_DWC_INTPR_NEWFP		0x00000002
+#define SATA_DWC_INTPR_PMABRT		0x00000004
+#define SATA_DWC_INTPR_ERR		0x00000008
+#define SATA_DWC_INTPR_NEWBIST		0x00000010
+#define SATA_DWC_INTPR_IPF		0x10000000
+#define SATA_DWC_INTMR_DMATM		0x00000001
+#define SATA_DWC_INTMR_NEWFPM		0x00000002
+#define SATA_DWC_INTMR_PMABRTM		0x00000004
+#define SATA_DWC_INTMR_ERRM		0x00000008
+#define SATA_DWC_INTMR_NEWBISTM		0x00000010
+
+#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
+#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
+
+#define SATA_DWC_QCMD_MAX	32
+
+/* This is all error bits, zero's are reserved fields. */
+#define SATA_DWC_SERROR_ERR_BITS	0x0FFF0F03
+
+/*
+ * Commonly used DWC SATA driver Macros
+ */
+#define HSDEVP_FROM_AP(ap)	(struct sata_dwc_device_port*)	\
+				(ap)->private_data
+
+struct sata_dwc_device {
+	struct device		*dev;		/* generic device struct */
+	struct ata_probe_ent    *pe;		/* ptr to probe-ent */
+	struct ata_host		*host;
+	u8			*reg_base;
+	struct sata_dwc_regs	*sata_dwc_regs;	/* DW Synopsys SATA specific */
+	int			irq_dma;
+};
+
+struct sata_dwc_device_port {
+	struct sata_dwc_device	*hsdev;
+	int			cmd_issued[SATA_DWC_QCMD_MAX];
+	u32			dma_chan[SATA_DWC_QCMD_MAX];
+	int			dma_pending[SATA_DWC_QCMD_MAX];
+};
+
+enum {
+	SATA_DWC_CMD_ISSUED_NOT		= 0,
+	SATA_DWC_CMD_ISSUED_PEND	= 1,
+	SATA_DWC_CMD_ISSUED_EXEC	= 2,
+	SATA_DWC_CMD_ISSUED_NODATA	= 3,
+
+	SATA_DWC_DMA_PENDING_NONE	= 0,
+	SATA_DWC_DMA_PENDING_TX		= 1,
+	SATA_DWC_DMA_PENDING_RX		= 2,
+};
+
+/* delay Macros */
+#define msleep(a)	udelay(a * 1000)
+#define ssleep(a)	msleep(a * 1000)
+
+static int ata_probe_timeout = (ATA_TMOUT_INTERNAL / 100);
+
+enum sata_dev_state {
+	SATA_INIT = 0,
+	SATA_READY = 1,
+	SATA_NODEVICE = 2,
+	SATA_ERROR = 3,
+};
+enum sata_dev_state dev_state = SATA_INIT;
+
+/*
+ * Globals
+ */
+static struct ahb_dma_regs		*sata_dma_regs = 0;
+static struct ata_host			*phost;
+static struct ata_port			ap;
+static struct ata_port			*pap = &ap;
+static struct ata_device		ata_device;
+static struct sata_dwc_device_port	dwc_devp;
+
+static void	*scr_addr_sstatus;
+static char	temp_data_buf[512];
+static u32	temp_n_block = 0;
+
+/*
+ * Prototype
+ */
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout);
+unsigned int ata_dev_set_feature(struct ata_device *dev,
+			u8 enable,u8 feature);
+unsigned int ata_dev_init_params(struct ata_device *dev,
+			u16 heads, u16 sectors);
+void clear_serror(void);
+u8 ata_irq_on(struct ata_port *ap);
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+			unsigned int tag);
+int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq);
+void ata_tf_to_host(struct ata_port *ap,const struct ata_taskfile *tf);
+unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc);
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
+unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+u8 ata_check_altstatus(struct ata_port *ap);
+static u8 ata_check_status(struct ata_port *ap);
+void ata_dev_select(struct ata_port *ap, unsigned int device,
+			unsigned int wait, unsigned int can_sleep);
+void ata_qc_issue(struct ata_queued_cmd *qc);
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
+int ata_dev_read_sectors(ccb *pccb);
+void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+void ata_qc_complete(struct ata_queued_cmd *qc);
+void __ata_qc_complete(struct ata_queued_cmd *qc);
+void fill_result_tf(struct ata_queued_cmd *qc);
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+void ata_mmio_data_xfer(struct ata_device *dev,
+			unsigned char *buf,unsigned int buflen);
+void ata_pio_task(struct ata_port *arg_ap);
+void __ata_port_freeze(struct ata_port *ap);
+int ata_port_freeze(struct ata_port *ap);
+void ata_qc_free(struct ata_queued_cmd *qc);
+void ata_pio_sectors(struct ata_queued_cmd *qc);
+void ata_pio_sector(struct ata_queued_cmd *qc);
+void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay);
+void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq);
+int sata_dwc_softreset(struct ata_port *ap);
+void sata_dwc_probe(void);
+
+u8 ata_check_altstatus(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.altstatus_addr);
+	return val;
+}
+
+int check_sata_dev_state(void)
+{
+	static ccb tempccb;		/* temporary scsi command buffer */
+	ccb *pccb = (ccb *)&tempccb;
+	int ret = 0;
+	int i = 0;
+
+	while(1){
+		udelay (10000);		/* 10 ms */
+
+	        pccb->cmd[0] = SCSI_READ10;
+	        pccb->cmd[1] = 0;
+	        pccb->cmd[2] = 0;
+	        pccb->cmd[3] = 0;
+	        pccb->cmd[4] = 0;
+	        pccb->cmd[5] = 0;
+	        pccb->cmd[6] = 0;
+	        pccb->cmd[7] = 0;
+	        pccb->cmd[8] = 1;
+	        pccb->cmdlen = 10;
+		pccb->pdata = &temp_data_buf[0];	/* dummy */
+		pccb->datalen = 512;
+
+		/* Send Read Command */
+		ret =  ata_dev_read_sectors(pccb);
+
+		/* result TRUE => break */
+		if(ret == 0){
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)){
+			printf("** TimeOUT **\n");
+			dev_state = SATA_NODEVICE;	/* set device status flag */
+			return FALSE;
+		}
+
+		if ((i >= 100) && ((i%100)==0)) {
+			printf(".");
+		}
+	}
+
+	/* Set device status flag */
+	dev_state = SATA_READY;
+
+	return TRUE;
+}
+
+void ata_id_string(const u16 *id, unsigned char *s,
+		unsigned int ofs, unsigned int len)
+{
+	unsigned int c;
+
+	while (len > 0) {
+		c = id[ofs] >> 8;
+		*s = c;
+		s++;
+
+		c = id[ofs] & 0xff;
+		*s = c;
+		s++;
+
+		ofs++;
+		len -= 2;
+	}
+}
+
+static int waiting_for_reg_state(volatile u8 *offset,
+				int timeout_msec,
+				u32 sign)
+{
+	int i;
+	u32 status;
+
+	for (i = 0; i < timeout_msec; i++){
+		status = readl(offset);
+		if ( ( status & sign ) != 0 ){
+			break;
+		}
+		msleep(1);
+	}
+
+	return (i < timeout_msec) ? 0 : -1;
+}
+
+static inline u32 qcmd_tag_to_mask(u8 tag)
+{
+	return (0x00000001 << (tag & 0x1f));
+}
+
+static u8 ata_check_status(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.status_addr);
+	return val;
+}
+
+static u8 ata_busy_wait(struct ata_port *ap,
+		unsigned int bits,unsigned int max)
+{
+	u8 status;
+
+	do {
+		udelay(10);
+		status = ata_check_status(ap);
+		max--;
+	} while (status != 0xff && (status & bits) && (max > 0));
+
+	return status;
+}
+
+static u8 ata_wait_idle(struct ata_port *ap)
+{
+	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	return status;
+}
+
+static int sata_dwc_scsiop_inq(ccb *pccb)
+{
+	struct ata_device *ata_dev = &ata_device;
+	u16 *id;
+
+	/* Set IDENTIFY Data */
+	id = ata_dev->id;
+
+	/* make INQUIRY header */
+	u8 hdr[] = {
+		0,
+		0,
+		0x5,	/* claim SPC-3 version compatibility */
+		2,
+		95 - 4
+	};
+
+	/* set scsi removeable (RMB) bit per ata bit */
+	if (ata_id_removeable(id)){
+		hdr[1] |= (1 << 7);
+ 	}
+
+	memcpy(pccb->pdata, hdr, sizeof(hdr));
+
+	if (pccb->datalen > 35) {
+		memcpy(&pccb->pdata[8], "ATA     ", 8);
+		ata_id_string(id, &pccb->pdata[16], ATA_ID_PROD, 16);
+		ata_id_string(id, &pccb->pdata[32], ATA_ID_FW_REV, 4);
+		if (pccb->pdata[32] == 0 || pccb->pdata[32] == ' '){
+			memcpy(&pccb->pdata[32], "n/a ", 4);
+		}
+	}
+
+	if (pccb->datalen > 63) {
+		const u8 versions[] = {
+			0x60,	/* SAM-3 (no version claimed) */
+			0x03,
+			0x20,	/* SBC-2 (no version claimed) */
+			0x02,
+			0x60	/* SPC-3 (no version claimed) */
+		};
+		memcpy(pccb->pdata + 59, versions, sizeof(versions));
+	}
+
+	return 0;
+}
+
+#define ATA_SCSI_PDATA_SET(idx, val) do { \
+	if ((idx) < pccb->datalen) pccb->pdata[(idx)] = (u8)(val); \
+	} while (0)
+
+static int sata_dwc_scsiop_read_cap(ccb *pccb)
+{
+	struct ata_device *ata_dev = &ata_device;
+	u32 last_lba;
+	last_lba = ata_dev->n_sectors;	/* LBA of the last block */
+
+	if (pccb->cmd[0] == SCSI_RD_CAPAC) {
+		if (last_lba >= 0xffffffffULL){
+			last_lba = 0xffffffff;
+		}
+
+		/* sector count, 32-bit */
+		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 3));
+		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 2));
+		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 1));
+		ATA_SCSI_PDATA_SET(3, last_lba);
+
+		/* buffer clear */
+		ATA_SCSI_PDATA_SET(4, 0);
+		ATA_SCSI_PDATA_SET(5, 0);
+
+		/* sector size */
+		ATA_SCSI_PDATA_SET(6, ATA_SECT_SIZE >> 8);
+		ATA_SCSI_PDATA_SET(7, ATA_SECT_SIZE & 0xff);
+
+	} else {
+		/* sector count, 64-bit */
+		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 7));
+		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 6));
+		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 5));
+		ATA_SCSI_PDATA_SET(3, last_lba >> (8 * 4));
+		ATA_SCSI_PDATA_SET(4, last_lba >> (8 * 3));
+		ATA_SCSI_PDATA_SET(5, last_lba >> (8 * 2));
+		ATA_SCSI_PDATA_SET(6, last_lba >> (8 * 1));
+		ATA_SCSI_PDATA_SET(7, last_lba);
+
+		/* sector size */
+		ATA_SCSI_PDATA_SET(10, ATA_SECT_SIZE >> 8);
+		ATA_SCSI_PDATA_SET(11, ATA_SECT_SIZE & 0xff);
+	}
+
+	return 0;
+}
+
+/*
+ * SCSI TEST UNIT READY command operation.
+ *      No operation.  Simply returns success to caller, to indicate
+ *      that the caller should successfully complete this SCSI command.
+ */
+static int sata_dwc_scsiop_test_unit_ready(ccb *pccb)
+{
+	/* No operation  */
+	return 0;
+}
+
+int scsi_exec(ccb *pccb)
+{
+	int ret;
+
+	/* check device status */
+	if(dev_state != SATA_READY){
+		return FALSE;
+	}
+
+	switch (pccb->cmd[0]) {
+	case SCSI_READ10:
+		ret =  ata_dev_read_sectors(pccb);
+		break;
+	case SCSI_RD_CAPAC:
+		ret = sata_dwc_scsiop_read_cap(pccb);
+		break;
+	case SCSI_TST_U_RDY:
+		ret = sata_dwc_scsiop_test_unit_ready(pccb);
+		break;
+	case SCSI_INQUIRY:
+		ret = sata_dwc_scsiop_inq(pccb);
+		break;
+	default:
+		printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
+		return FALSE;
+	}
+
+	if (ret) {
+		debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static const struct ata_port_info sata_dwc_port_info[] = {
+	{
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
+				ATA_FLAG_SRST | ATA_FLAG_NCQ,
+		.pio_mask	= 0x1f,	/* pio 0-4 */
+		.mwdma_mask	= 0x07,
+		.udma_mask	= 0x7f,
+	},
+};
+
+int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id)
+{
+	struct ata_port *ap = pap;
+	unsigned int class = *p_class;
+	struct ata_taskfile tf;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1, tried_spinup = 0;
+	u8 status;
+	int rc;
+
+	/* cheack BSY = 0 */
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+        ata_dev_select(ap, dev->devno, 1, 1);	/* select device 0/1 */
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+	tf.ctl = ap->ctl;	/* 0x08 */
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_ID_ATA;
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+	/* Device presence detection is unreliable on some
+	 * controllers.  Always poll IDENTIFY if available.
+	 */
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	temp_n_block = 1;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+					sizeof(id[0]) * ATA_ID_WORDS, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+#ifdef __BIG_ENDIAN
+	unsigned int id_cnt;
+
+	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
+		id[id_cnt] = le16_to_cpu(id[id_cnt]);
+
+#endif	/* __BIG_ENDIAN */
+
+	/* sanity check */
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	if (class == ATA_DEV_ATA) {
+		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)){
+			goto err_out;
+		}
+	} else {
+		if (ata_id_is_ata(id)){
+			goto err_out;
+		}
+	}
+	if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+		tried_spinup = 1;
+		/*
+		 * Drive powered-up in standby mode, and requires a specific
+		 * SET_FEATURES spin-up subcommand before it will accept
+		 * anything other than the original IDENTIFY command.
+		 */
+		err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+		if (err_mask && id[2] != 0x738c) {
+			rc = -EIO;
+			reason = "SPINUP failed";
+			goto err_out;
+		}
+		/*
+		 * If the drive initially returned incomplete IDENTIFY info,
+		 * we now must reissue the IDENTIFY command.
+		 */
+		if (id[2] == 0x37c8)
+			goto retry;
+	}
+
+	if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
+		/*
+		 * The exact sequence expected by certain pre-ATA4 drives is:
+		 * SRST RESET
+		 * IDENTIFY (optional in early ATA)
+		 * INITIALIZE DEVICE PARAMETERS (later IDE and ATA)
+		 * anything else..
+		 * Some drives were very specific about that exact sequence.
+		 *
+		 * Note that ATA4 says lba is mandatory so the second check
+		 * shoud never trigger.
+		 */
+		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+			err_mask = ata_dev_init_params(dev, id[3], id[6]);
+			if (err_mask) {
+				rc = -EIO;
+				reason = "INIT_DEV_PARAMS failed";
+				goto err_out;
+			}
+
+			/* current CHS translation info (id[53-58]) might be
+			 * changed. reread the identify device info.
+			 */
+			flags &= ~ATA_READID_POSTRESET;
+			goto retry;
+		}
+        }
+
+	*p_class = class;
+	return 0;
+
+err_out:
+	return rc;
+}
+
+void ata_dev_select(struct ata_port *ap, unsigned int device,
+		unsigned int wait, unsigned int can_sleep)
+{
+	if (wait){
+		ata_wait_idle(ap);
+	}
+
+	ata_std_dev_select(ap, device);
+
+	if (wait) {
+		ata_wait_idle(ap);
+	}
+}
+
+void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+{
+	u8 tmp;
+
+	if (device == 0) {
+		tmp = ATA_DEVICE_OBS;
+	} else {
+		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+	}
+
+	writeb(tmp, ap->ioaddr.device_addr);
+
+	/* needed; also flushes, for mmio */
+	readb(ap->ioaddr.altstatus_addr);
+
+	/* need delay 400nsec over */
+	udelay(1);
+}
+
+void ata_qc_reinit(struct ata_queued_cmd *qc)
+{
+	qc->dma_dir = DMA_NONE;
+	qc->flags = 0;
+	qc->nbytes = qc->extrabytes = qc->curbytes = 0;
+	qc->n_elem = 0;
+	qc->err_mask = 0;
+	qc->sect_size = ATA_SECT_SIZE;
+	qc->nbytes = ATA_SECT_SIZE * temp_n_block;
+
+	memset(&qc->tf, 0, sizeof(qc->tf));
+	qc->tf.ctl = 0;
+	qc->tf.device = ATA_DEVICE_OBS;
+
+	/* init result_tf such that it indicates normal completion */
+	qc->result_tf.command = ATA_DRDY;
+	qc->result_tf.feature = 0;
+}
+
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout)
+{
+	struct ata_link *link = dev->link;
+	struct ata_port *ap = pap;
+	struct ata_queued_cmd *qc;
+	unsigned int tag, preempted_tag;
+	u32 preempted_sactive, preempted_qc_active;
+	int preempted_nr_active_links;
+	unsigned int err_mask;
+	int rc = 0;
+	u8 status;
+
+	/* cheack BSY = 0 */
+	status = ata_busy_wait(ap, ATA_BUSY, 300000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	/* no internal command while frozen */
+	if (ap->pflags & ATA_PFLAG_FROZEN) {
+		return AC_ERR_SYSTEM;
+	}
+
+	tag = ATA_TAG_INTERNAL;
+
+	if (test_and_set_bit(tag, &ap->qc_allocated)){
+		printf("test_and_set_bit failed\n");
+	}
+
+	qc = __ata_qc_from_tag(ap, tag);
+	qc->tag = tag;
+	qc->ap = ap;
+	qc->dev = dev;
+
+	ata_qc_reinit(qc);
+
+	preempted_tag = link->active_tag;
+	preempted_sactive = link->sactive;
+	preempted_qc_active = ap->qc_active;
+	preempted_nr_active_links = ap->nr_active_links;
+	link->active_tag = ATA_TAG_POISON;
+	link->sactive = 0;
+	ap->qc_active = 0;
+	ap->nr_active_links = 0;
+
+	/* prepare & issue qc */
+	qc->tf = *tf;
+	if (cdb)
+		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+	qc->dma_dir = dma_dir;
+	qc->private_data = 0;
+
+	ata_qc_issue(qc);
+
+	if (!timeout){
+		timeout = ata_probe_timeout * 1000 / HZ;
+	}
+
+	/* cheack BSY = 0 */
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		printf("altstatus = 0x%x.\n",status);
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	if(waiting_for_reg_state(ap->ioaddr.altstatus_addr,1000,0x8)){
+		printf("DRQ = 1 check timeout 1000msec\n");
+		u8 status = 0;
+		u8 errorStatus = 0;
+
+		status = readb( ap->ioaddr.altstatus_addr);
+		if ((status&0x01) != 0) {
+			errorStatus = readb( ap->ioaddr.feature_addr);
+			printf("ERROR STATUS = 0x%x\n",errorStatus);
+		}
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	status = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	ata_pio_task(ap);
+
+	if (!rc) {
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			qc->err_mask |= AC_ERR_TIMEOUT;
+			ata_port_freeze(ap);
+		}
+	}
+
+	/* perform minimal error analysis */
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (qc->result_tf.command & (ATA_ERR | ATA_DF)){
+			qc->err_mask |= AC_ERR_DEV;
+		}
+
+		if (!qc->err_mask){
+			qc->err_mask |= AC_ERR_OTHER;
+		}
+
+		if (qc->err_mask & ~AC_ERR_OTHER){
+			qc->err_mask &= ~AC_ERR_OTHER;
+		}
+	}
+
+	/* finish up */
+	*tf = qc->result_tf;
+	err_mask = qc->err_mask;
+	ata_qc_free(qc);
+	link->active_tag = preempted_tag;
+	link->sactive = preempted_sactive;
+	ap->qc_active = preempted_qc_active;
+	ap->nr_active_links = preempted_nr_active_links;
+
+	if (ap->flags & ATA_FLAG_DISABLED) {
+		err_mask |= AC_ERR_SYSTEM;
+		ap->flags &= ~ATA_FLAG_DISABLED;
+	}
+
+	return err_mask;
+}
+
+unsigned int ata_dev_set_feature(struct ata_device *dev,
+				u8 enable, u8 feature)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	/* set up set-features taskfile */
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = enable;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = feature;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	return err_mask;
+}
+
+unsigned int ata_dev_init_params(struct ata_device *dev,
+				u16 heads, u16 sectors)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	/* Number of sectors per track 1-255. Number of heads 1-16 */
+	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+			return AC_ERR_INVALID;
+
+	/* set up init dev params taskfile */
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
+		err_mask = 0;
+
+	return err_mask;
+}
+
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+					unsigned int tag)
+{
+	if (tag < ATA_MAX_QUEUE)
+		return &ap->qcmd[tag];
+	return NULL;
+}
+
+void ata_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+	u8 prot = qc->tf.protocol;
+
+	if (ata_is_ncq(prot)) {
+		if (!link->sactive)
+			ap->nr_active_links++;
+		link->sactive |= 1 << qc->tag;
+	} else {
+		ap->nr_active_links++;
+		link->active_tag = qc->tag;
+	}
+
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+	ap->qc_active |= 1 << qc->tag;
+
+	if (qc->dev->flags & ATA_DFLAG_SLEEPING) {
+		msleep(1);	/* delay 1msec */
+		return;
+	}
+
+	qc->err_mask |= sata_dwc_qc_issue(qc);
+	if (qc->err_mask)
+		goto err;
+
+	return;
+err:
+	ata_qc_complete(qc);
+}
+
+unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
+{
+	ata_qc_issue_prot(qc);
+	return 0;
+}
+
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	/* set command register */
+	writeb(tf->command, ap->ioaddr.command_addr);
+
+	/* read alternative status register */
+	readb(ap->ioaddr.altstatus_addr);
+
+	/* delay 400nsec over */
+	udelay(1);
+}
+
+void __ata_port_freeze(struct ata_port *ap)
+{
+	printf("set port freeze.\n");
+	ap->pflags |= ATA_PFLAG_FROZEN;
+}
+
+int ata_port_freeze(struct ata_port *ap)
+{
+	__ata_port_freeze(ap);
+	return 0;
+}
+
+unsigned int ata_tag_internal(unsigned int tag)
+{
+	return tag == ATA_MAX_QUEUE - 1;
+}
+
+void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_device *dev = qc->dev;
+	if (qc->err_mask)
+		qc->flags |= ATA_QCFLAG_FAILED;
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (!ata_tag_internal(qc->tag)) {
+			/* always fill result TF for failed qc */
+			fill_result_tf(qc);
+			return;
+		}
+	}
+	/* read result TF if requested */
+	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+		fill_result_tf(qc);
+
+	/* Some commands need post-processing after successful
+	 * completion.
+	 */
+	switch (qc->tf.command) {
+	case ATA_CMD_SET_FEATURES:
+		if (qc->tf.feature != SETFEATURES_WC_ON &&
+				qc->tf.feature != SETFEATURES_WC_OFF)
+			break;
+	case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+	case ATA_CMD_SET_MULTI: /* multi_count changed */
+		break;
+
+	case ATA_CMD_SLEEP:
+		dev->flags |= ATA_DFLAG_SLEEPING;
+		break;
+	}
+
+	__ata_qc_complete(qc);
+}
+
+void __ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+
+	/* command should be marked inactive atomically with qc completion */
+	link->active_tag = ATA_TAG_POISON;
+	ap->nr_active_links--;
+
+	/* clear exclusive status */
+	if (qc->flags & ATA_QCFLAG_CLEAR_EXCL && ap->excl_link == link)
+		ap->excl_link = NULL;
+
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	ap->qc_active &= ~(1 << qc->tag);
+}
+
+void fill_result_tf(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	qc->result_tf.flags = qc->tf.flags;
+	ata_tf_read(ap, &qc->result_tf);
+}
+
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->command = ata_check_status(ap);
+	tf->feature = readb(ioaddr->error_addr);
+	tf->nsect = readb(ioaddr->nsect_addr);
+	tf->lbal = readb(ioaddr->lbal_addr);
+	tf->lbam = readb(ioaddr->lbam_addr);
+	tf->lbah = readb(ioaddr->lbah_addr);
+	tf->device = readb(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		if (ioaddr->ctl_addr) {
+			writeb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+
+			tf->hob_feature = readb(ioaddr->error_addr);
+			tf->hob_nsect = readb(ioaddr->nsect_addr);
+			tf->hob_lbal = readb(ioaddr->lbal_addr);
+			tf->hob_lbam = readb(ioaddr->lbam_addr);
+			tf->hob_lbah = readb(ioaddr->lbah_addr);
+
+			writeb(tf->ctl, ioaddr->ctl_addr);
+			ap->last_ctl = tf->ctl;
+		} else {
+			printf("sata_dwc warnning register read.\n");
+		}
+	}
+}
+
+void ata_qc_free(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int tag;
+	qc->flags = 0;
+	tag = qc->tag;
+	if (tag < ATA_MAX_QUEUE){
+		qc->tag = ATA_TAG_POISON;
+		clear_bit(tag, &ap->qc_allocated);
+	}
+}
+
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		if (ioaddr->ctl_addr){
+			writeb(tf->ctl, ioaddr->ctl_addr);
+		}
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writeb(tf->hob_feature, ioaddr->feature_addr);
+		writeb(tf->hob_nsect, ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, ioaddr->lbah_addr);
+	}
+
+	if (is_addr) {
+		writeb(tf->feature, ioaddr->feature_addr);
+		writeb(tf->nsect, ioaddr->nsect_addr);
+		writeb(tf->lbal, ioaddr->lbal_addr);
+		writeb(tf->lbam, ioaddr->lbam_addr);
+		writeb(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE) {
+		writeb(tf->device, ioaddr->device_addr);
+	}
+
+	ata_wait_idle(ap);
+}
+
+void sata_dwc_exec_command_by_tag(struct ata_port *ap,
+				struct ata_taskfile *tf,
+				u8 tag, u32 cmd_issued)
+{
+	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+	hsdevp->cmd_issued[tag] = cmd_issued;
+
+	/* Clear SError before executing a new command.*/
+	clear_serror();
+	ata_exec_command(ap, tf);
+}
+
+void clear_serror(void)
+{
+	u32 temp;
+	temp = in_le32((void __iomem *)scr_addr_sstatus + 4);
+
+	out_le32((void __iomem *)scr_addr_sstatus + 4, temp);
+}
+
+void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	ata_tf_load(ap, tf);
+	ata_exec_command(ap, tf);
+}
+
+unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+		switch (qc->tf.protocol) {
+		case ATA_PROT_PIO:
+		case ATA_PROT_NODATA:
+		case ATAPI_PROT_PIO:
+		case ATAPI_PROT_NODATA:
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* select the device */
+	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+	/* start the command */
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+		if (qc->tf.flags & ATA_TFLAG_POLLING){
+			qc->tf.ctl |= ATA_NIEN;
+		}
+
+		ata_tf_to_host(ap, &qc->tf);
+
+		/* PIO data in protocol */
+		ap->hsm_task_state = HSM_ST;
+
+		if (qc->tf.flags & ATA_TFLAG_POLLING){
+			ata_pio_queue_task(ap, qc, 0);
+		}
+
+		break;
+
+	default:
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+void ata_pio_task(struct ata_port *arg_ap)
+{
+	struct ata_port *ap = arg_ap;
+	struct ata_queued_cmd *qc = ap->port_task_data;
+	u8 status;
+	int poll_next;
+
+fsm_start:
+	/*
+	 * This is purely heuristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, queue delayed work.
+	 */
+	status = ata_busy_wait(ap, ATA_BUSY, 5);
+	if (status & ATA_BUSY) {
+		msleep(2);
+		status = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (status & ATA_BUSY) {
+			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+			return;
+		}
+	}
+
+	/* move the HSM */
+	poll_next = ata_hsm_move(ap, qc, status, 1);
+
+	/* another command or interrupt handler
+	 * may be running at this point.
+	 */
+	if (poll_next)
+		goto fsm_start;
+}
+
+void ata_pio_queue_task(struct ata_port *ap, void *data,unsigned long delay)
+{
+	ap->port_task_data = data;
+}
+
+unsigned int ac_err_mask(u8 status)
+{
+	if (status & (ATA_BUSY | ATA_DRQ))
+		return AC_ERR_HSM;
+	if (status & (ATA_ERR | ATA_DF))
+		return AC_ERR_DEV;
+	return 0;
+}
+
+unsigned int __ac_err_mask(u8 status)
+{
+	unsigned int mask = ac_err_mask(status);
+	if (mask == 0)
+		return AC_ERR_OTHER;
+	return mask;
+}
+
+int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq)
+{
+	int poll_next;
+
+fsm_start:
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+		/* check device status */
+		if ((status & ATA_DRQ) == 0) {
+			/* handle BSY=0, DRQ=0 as error */
+			if (status & (ATA_ERR | ATA_DF)) {
+				/* device stops HSM for abort/error */
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this */
+				qc->err_mask |= AC_ERR_HSM;
+			}
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Device should not ask for data transfer (DRQ=1)
+		 * when it finds something wrong.
+		 * We ignore DRQ here and stop the HSM by
+		 * changing hsm_task_state to HSM_ST_ERR and
+		 * let the EH abort the command or reset the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+				printf("DRQ=1 with device error, "
+					"dev_stat 0x%X\n", status);
+				qc->err_mask |= AC_ERR_HSM;
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+		}
+
+		if (qc->tf.protocol == ATA_PROT_PIO) {
+			/* PIO data out protocol.
+			 * send first data block.
+			 */
+			/* ata_pio_sectors() might change the state
+			 * to HSM_ST_LAST. so, the state is changed here
+			 * before ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST;
+			ata_pio_sectors(qc);
+		} else {
+			printf("protocol is not ATA_PROT_PIO \n");
+		}
+		break;
+
+	case HSM_ST:
+		/* complete command or read/write the data register */
+		/* ATA PIO protocol */
+		if ((status & ATA_DRQ) == 0) {
+			/* handle BSY=0, DRQ=0 as error */
+			if (status & (ATA_ERR | ATA_DF)){
+				/* device stops HSM for abort/error */
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this.
+				 * Phantom devices also trigger this
+				 * condition.  Mark hint.
+				 */
+				qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT;
+			}
+
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+		/* For PIO reads, some devices may ask for
+		 * data transfer (DRQ=1) alone with ERR=1.
+		 * We respect DRQ here and transfer one
+		 * block of junk data before changing the
+		 * hsm_task_state to HSM_ST_ERR.
+		 *
+		 * For PIO writes, ERR=1 DRQ=1 doesn't make
+		 * sense since the data block has been
+		 * transferred to the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			/* data might be corrputed */
+			qc->err_mask |= AC_ERR_DEV;
+
+			if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+				ata_pio_sectors(qc);
+				status = ata_wait_idle(ap);
+			}
+
+			if (status & (ATA_BUSY | ATA_DRQ)){
+				qc->err_mask |= AC_ERR_HSM;
+			}
+
+			/* ata_pio_sectors() might change the
+			 * state to HSM_ST_LAST. so, the state
+			 * is changed after ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ata_pio_sectors(qc);
+		if (ap->hsm_task_state == HSM_ST_LAST &&
+			(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+			/* all data read */
+			status = ata_wait_idle(ap);
+			goto fsm_start;
+		}
+
+		poll_next = 1;
+		break;
+
+	case HSM_ST_LAST:
+		if (!ata_ok(status)) {
+			qc->err_mask |= __ac_err_mask(status);
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* no more data to transfer */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		/* complete taskfile transaction */
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+
+	case HSM_ST_ERR:
+		/* make sure qc->err_mask is available to
+		 * know what's wrong and recover
+		 */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		/* complete taskfile transaction */
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+	default:
+		poll_next = 0;
+	}
+
+	return poll_next;
+}
+
+int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+	if (qc->tf.flags & ATA_TFLAG_POLLING)
+		return 1;
+
+	if (ap->hsm_task_state == HSM_ST_FIRST) {
+		if (ata_is_atapi(qc->tf.protocol) &&
+			!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+			return 1;
+	}
+
+	return 0;
+}
+
+void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap;
+	ap = pap;
+	qc->pdata = ap->pdata;
+
+	if (is_multi_taskfile(&qc->tf)) {
+		/* READ/WRITE MULTIPLE */
+		unsigned int nsect;
+
+		nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
+			qc->dev->multi_count);
+		while (nsect--)
+			ata_pio_sector(qc);
+	} else {
+		ata_pio_sector(qc);
+	}
+
+	readb(qc->ap->ioaddr.altstatus_addr);
+	udelay(1);
+}
+
+void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int offset;
+	unsigned char *buf;
+
+	if (qc->curbytes == qc->nbytes - qc->sect_size){
+		ap->hsm_task_state = HSM_ST_LAST;
+	}
+
+	offset = qc->curbytes;
+
+	/* check cmd and set buffer */
+	switch (qc->tf.command) {
+	case ATA_CMD_ID_ATA:		/* IDENTIFY */
+		buf = &ata_device.id[0];
+		break;
+	case ATA_CMD_PIO_READ_EXT:	/* READ SECTORS EX 0x24 */
+	case ATA_CMD_PIO_READ:		/* READ SECTORS 0x20 */
+		buf = qc->pdata + offset;
+		break;
+	default:
+		buf = &temp_data_buf[0];
+	}		
+
+	/* data xfer */
+	ata_mmio_data_xfer(qc->dev, buf, qc->sect_size);
+
+	qc->curbytes += qc->sect_size;
+
+}
+
+void ata_mmio_data_xfer(struct ata_device *dev, unsigned char *buf,
+				unsigned int buflen)
+{
+	struct ata_port *ap = pap;
+	void __iomem *data_addr = ap->ioaddr.data_addr;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *)buf;
+	unsigned int i = 0;
+
+	udelay(100);
+	/* Transfer */
+	for(i=0; i < words; i++)
+		buf16[i] = cpu_to_le16(readw(data_addr));
+
+	/* Transfer trailing 1 byte, if any. */
+	if (buflen & 0x01) {
+		__le16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		align_buf[0] = cpu_to_le16(readw(data_addr));
+		memcpy(trailing_buf, align_buf, 1);
+		words++;
+	}
+}
+
+void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (in_wq) {
+		/* EH might have kicked in while host lock is
+		 * released.
+		 */
+		qc = &ap->qcmd[qc->tag];
+		if (qc) {
+			if (!(qc->err_mask & AC_ERR_HSM)) {
+				ata_irq_on(ap);
+				ata_qc_complete(qc);
+			} else {
+				ata_port_freeze(ap);
+			}
+		}
+	} else {
+		if (!(qc->err_mask & AC_ERR_HSM)) {
+			ata_qc_complete(qc);
+		} else {
+			ata_port_freeze(ap);
+		}
+	}
+}
+
+u8 ata_irq_on(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 tmp;
+
+	ap->ctl &= ~ATA_NIEN;
+	ap->last_ctl = ap->ctl;
+
+	if (ioaddr->ctl_addr)
+		writeb(ap->ctl, ioaddr->ctl_addr);
+
+	tmp = ata_wait_idle(ap);
+
+	return tmp;
+}
+
+void sata_dwc_probe(void)
+{
+	struct sata_dwc_device hsdev;
+	struct ata_host host;
+	struct ata_port_info pi = sata_dwc_port_info[0];
+	struct ata_device *ata_dev = &ata_device;
+	struct ata_link *link;
+        struct sata_dwc_device_port hsdevp = dwc_devp;
+	u8 *base = 0;
+	u8 *sata_dma_regs_addr = 0;
+	u32 idr, versionr;
+        u8 status;
+	unsigned long base_addr = 0;
+	int chan = 0;
+	int rc;
+	int i;
+	const u16 *id;
+	unsigned long xfer_mask;
+	char revbuf[7];         /* XYZ-99\0 */
+	unsigned long pio_mask, mwdma_mask, udma_mask;
+
+	phost = &host;	/* set grobal */
+
+	/* Base address */
+	base = (u8*)SATA_BASE_ADDR;
+
+	/* SATA register init */
+	hsdev.sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+
+	host.n_ports = SATA_DWC_MAX_PORTS;
+
+	for(i = 0; i < SATA_DWC_MAX_PORTS; i++){
+		ap.pflags |= ATA_PFLAG_INITIALIZING;
+		ap.flags = ATA_FLAG_DISABLED;
+		ap.print_id = -1;
+		ap.ctl = ATA_DEVCTL_OBS;
+		ap.host = &host;
+		ap.last_ctl = 0xFF;
+		ap.dev = &ata_device;
+
+		link = &ap.link;
+		link->ap = &ap;
+		link->pmp = 0;
+		link->active_tag = ATA_TAG_POISON;
+		link->hw_sata_spd_limit = 0;
+
+		ap.port_no = i;
+		host.ports[i] = &ap;
+	}
+
+	ap.pio_mask = pi.pio_mask;
+	ap.mwdma_mask = pi.mwdma_mask;
+	ap.udma_mask = pi.udma_mask;
+	ap.flags |= pi.flags;
+	ap.link.flags |= pi.link_flags;
+
+	/* Host port init */
+	host.ports[0]->ioaddr.cmd_addr = base;
+	host.ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
+	scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
+
+	/* sata_dwc setup port */
+	base_addr = (unsigned long)base;
+
+	host.ports[0]->ioaddr.cmd_addr = (void *)base_addr + 0x00;
+	host.ports[0]->ioaddr.data_addr = (void *)base_addr + 0x00;
+
+	host.ports[0]->ioaddr.error_addr = (void *)base_addr + 0x04;
+	host.ports[0]->ioaddr.feature_addr = (void *)base_addr + 0x04;
+
+	host.ports[0]->ioaddr.nsect_addr = (void *)base_addr + 0x08;
+
+	host.ports[0]->ioaddr.lbal_addr = (void *)base_addr + 0x0c;
+	host.ports[0]->ioaddr.lbam_addr = (void *)base_addr + 0x10;
+	host.ports[0]->ioaddr.lbah_addr = (void *)base_addr + 0x14;
+
+	host.ports[0]->ioaddr.device_addr = (void *)base_addr + 0x18;
+	host.ports[0]->ioaddr.command_addr = (void *)base_addr + 0x1c;
+	host.ports[0]->ioaddr.status_addr = (void *)base_addr + 0x1c;
+
+	host.ports[0]->ioaddr.altstatus_addr = (void *)base_addr + 0x20;
+	host.ports[0]->ioaddr.ctl_addr = (void *)base_addr + 0x20;
+
+	/* Get Host ID / Version */
+	idr = in_le32(&hsdev.sata_dwc_regs->idr);
+	versionr = in_le32(&hsdev.sata_dwc_regs->versionr);
+
+	/* DMA register init */
+	sata_dma_regs_addr = (u8*)SATA_DMA_REG_ADDR;
+	sata_dma_regs = (void *__iomem)sata_dma_regs_addr;
+
+	/* DMA channel Interrupt is disable. DMA Enable setup is next. */
+	for(chan = 0; chan < DMA_NUM_CHANS; chan++){
+		/* DMA Interrupt register(error) mask. */
+		out_le32(&(sata_dma_regs->interrupt_mask.error.low),
+				DMA_DISABLE_CHAN(chan));
+
+		/* DMA Interrupt register(transfer) mask. */
+		out_le32(&(sata_dma_regs->interrupt_mask.tfr.low),
+				DMA_DISABLE_CHAN(chan));
+	}
+
+	/* DMA Enable by DMAC Configuration Register */
+	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_EN);
+
+	/* Enable selective interrupts by setting the interrupt mask register */
+	out_le32(&hsdev.sata_dwc_regs->intmr,
+		SATA_DWC_INTMR_ERRM |
+		SATA_DWC_INTMR_NEWFPM |
+		SATA_DWC_INTMR_PMABRTM |
+		SATA_DWC_INTMR_DMATM);
+
+	/* Unmask the error bits that should trigger an error interrupt by
+	 * setting the error mask register.
+	 */
+	out_le32(&hsdev.sata_dwc_regs->errmr,SATA_DWC_SERROR_ERR_BITS);
+
+	hsdev.host = ap.host;
+	memset(&hsdevp, 0, sizeof(hsdevp));
+	hsdevp.hsdev = &hsdev;
+
+	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
+		hsdevp.cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
+
+	if (ap.port_no == 0)  {
+		out_le32(&hsdev.sata_dwc_regs->dmacr,SATA_DWC_DMACR_TXRXCH_CLEAR);
+
+		out_le32(&hsdev.sata_dwc_regs->dbtsr,
+			(SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+			SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
+	}
+
+	/* Clear any error bits before libata starts issuing commands */
+	out_le32((void __iomem *)scr_addr_sstatus + 4,
+		in_le32((void __iomem *)scr_addr_sstatus + 4));
+
+	/* check altstatus register (find device) */
+	status = ata_check_altstatus(&ap);
+
+	if(status == 0x7f){
+		printf("Hard Disk not found.\n");
+		dev_state = SATA_NODEVICE;
+		return;
+	}
+
+	/* waiting for device ready. time out 30sec */
+	printf("waitng for device ready.");
+	i = 0;
+	while(1){
+		udelay (10000);         /* 10 ms */
+
+		/* read altstatus */
+		status = ata_check_altstatus(&ap);
+
+		/* status is not busy => break */
+		if((status &  ATA_BUSY) == 0){
+			printf("\n");
+			break;
+		}
+		
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			/* bussy set devise state flag */
+			dev_state = SATA_NODEVICE;
+			return;
+		}
+		if ((i >= 100) && ((i%100)==0)) {
+			printf(".");
+		}
+	}
+
+	/* softreset */
+	rc = sata_dwc_softreset(&ap);
+
+	if(rc){
+		printf("sata_dwc : error. soft reset failed\n");
+	}
+
+	/* waiting for device ready. time out 30sec */
+	printf("waitng for device ready.");
+	i = 0;
+	while(1){
+		udelay (10000);         /* 10 ms */
+
+		/* read altstatus */
+		status = ata_check_altstatus(&ap);
+
+		/* status is not busy => break */
+		if((status &  ATA_BUSY) == 0){
+			printf("\n");
+			break;
+		}
+		
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			/* bussy set devise state flag */
+			dev_state = SATA_NODEVICE;
+			return;
+		}
+		if ((i >= 100) && ((i%100)==0)) {
+			printf(".");
+		}
+	}
+
+	udelay (1000);         /* before IDENTIFY command safety delay 1 ms */
+
+	/* IDENTIFY command send */
+	rc = ata_dev_read_id(ata_dev, &ata_dev->class,
+			ATA_READID_POSTRESET,ata_dev->id);
+
+	if(rc){
+		printf("sata_dwc : error. IDENTIFY Command failed\n");
+	}
+
+	/* SATA drives indicate we have a bridge. We don't know which
+	 * end of the link the bridge is which is a problem
+	 */
+	if (ata_id_is_sata(ata_dev->id))
+		ap.cbl = ATA_CBL_SATA;
+
+	id = ata_dev->id;
+
+	/* initialize to be configured parameters */
+	ata_dev->flags &= ~ATA_DFLAG_CFG_MASK;
+	ata_dev->max_sectors = 0;
+	ata_dev->cdb_len = 0;
+	ata_dev->n_sectors = 0;
+	ata_dev->cylinders = 0;
+	ata_dev->heads = 0;
+	ata_dev->sectors = 0;
+
+	/* Usual case. Word 53 indicates word 64 is valid */
+	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+		pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+		pio_mask <<= 3;
+		pio_mask |= 0x7;
+	} else {
+		/* If word 64 isn't valid then Word 51 high byte holds
+		 * the PIO timing number for the maximum. Turn it into
+		 * a mask.
+		 */
+		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
+		if (mode < 5){   /* Valid PIO range */
+			pio_mask = (2 << mode) - 1;
+		} else {
+			pio_mask = 1;
+		}
+	}
+
+	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+	if (ata_id_is_cfa(id)) {
+		/*
+		 *	Process compact flash extended modes
+		 */
+		int pio = id[163] & 0x7;
+		int dma = (id[163] >> 3) & 7;
+
+		if (pio)
+			pio_mask |= (1 << 5);
+		if (pio > 1)
+			pio_mask |= (1 << 6);
+		if (dma)
+			mwdma_mask |= (1 << 3);
+		if (dma > 1)
+			mwdma_mask |= (1 << 4);
+	}
+
+	udma_mask = 0;
+	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+	xfer_mask = (pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO |
+		(mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA |
+		(udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
+
+	/* ATA-specific feature tests */
+	if (ata_dev->class == ATA_DEV_ATA) {
+		if (ata_id_is_cfa(id)) {
+			if (id[162] & 1) /* CPRM may make this media unusable */
+				printf("supports DRM functions and may "
+					"not be fully accessable.\n");
+			sprintf(revbuf, "%s", "CFA");
+		} else {
+			/* Warn the user if the device has TPM extensions */
+			if (ata_id_has_tpm(id))
+				printf("supports DRM functions and may "
+						"not be fully accessable.\n");
+		}
+
+		/* set n_secters */
+		ata_dev->n_sectors = ata_id_n_sectors((u16*)id);
+
+		if (ata_dev->id[59] & 0x100)
+			ata_dev->multi_count = ata_dev->id[59] & 0xff;
+
+		if (ata_id_has_lba(id)) {
+			const char *lba_desc;
+			char ncq_desc[20];
+
+			lba_desc = "LBA";
+			ata_dev->flags |= ATA_DFLAG_LBA;
+			if (ata_id_has_lba48(id)) {
+				ata_dev->flags |= ATA_DFLAG_LBA48;
+				lba_desc = "LBA48";
+
+				if (ata_dev->n_sectors >= (1UL << 28) &&
+					ata_id_has_flush_ext(id))
+					ata_dev->flags |= ATA_DFLAG_FLUSH_EXT;
+			}
+			/* config NCQ */
+			if (!ata_id_has_ncq(ata_dev->id)) {
+				ncq_desc[0] = '\0';
+			}
+
+			if (ata_dev->horkage & ATA_HORKAGE_NONCQ) {
+				sprintf(ncq_desc, "%s", "NCQ (not used)");
+			}
+
+			if (ap.flags & ATA_FLAG_NCQ) {
+				ata_dev->flags |= ATA_DFLAG_NCQ;
+			}
+		}
+		ata_dev->cdb_len = 16;
+	}
+	/* determine max_sectors */
+	ata_dev->max_sectors = ATA_MAX_SECTORS;
+	if (ata_dev->flags & ATA_DFLAG_LBA48)
+		ata_dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
+	if (!(ata_dev->horkage & ATA_HORKAGE_IPM)) {
+		if (ata_id_has_hipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_HIPM;
+		if (ata_id_has_dipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_DIPM;
+	}
+
+	if ((ap.cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ata_dev->id))) {
+		ata_dev->udma_mask &= ATA_UDMA5;
+		ata_dev->max_sectors = ATA_MAX_SECTORS;
+	}
+
+	if (ata_dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+		printf("Drive reports diagnostics failure."
+				"This may indicate a drive\n");
+		printf("fault or invalid emulation."
+				"Contact drive vendor for information.\n");
+	}
+
+	/* Hard Disk status check : test send READ Command */
+	rc = check_sata_dev_state();
+}
+
+int sata_dwc_softreset(struct ata_port *ap)
+{
+	u8 nsect,lbal = 0;
+	u8 tmp = 0;
+	u32 serror = 0;
+	u8 status = 0;
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	/* read SCR ERROR */
+	serror = in_le32((void *)ap->ioaddr.scr_addr + (SCR_ERROR * 4));
+
+	/* device check */
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+	writeb(0xaa, ioaddr->nsect_addr);
+	writeb(0x55, ioaddr->lbal_addr);
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa)){
+		/* we found a device */
+		printf("we found a device\n");
+	} else {
+		/* nothing found */
+		printf("Not found a device.\n");
+		dev_state = SATA_NODEVICE;
+		return FALSE;
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	udelay(200);
+
+	/* set softreset */
+	writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+
+	udelay(200);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	/* wait a while before cheking status */
+	msleep(150);
+	status = ata_check_status(ap);
+
+	msleep(50);
+	ata_check_status(ap);
+
+	while (1) {
+		u8 status = ata_check_status(ap);
+
+		if (!(status & ATA_BUSY)){
+			break;
+		}
+
+		status = in_le32((void *)ap->ioaddr.scr_addr + (SCR_STATUS * 4));
+		if(status == 0xff || (status & 0xf) != 0x3){
+		}
+
+		printf("Hard Disk status is BUSY.\n");
+		msleep(50);
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	return 0;
+}
+
+void scsi_bus_reset()
+{
+	struct ata_port *ap = pap;
+
+	/* check device state */
+	if(dev_state != SATA_READY){
+		printf("no devices available\n");
+		return;
+	}
+
+	/*soft reset process*/
+	sata_dwc_softreset(ap);
+}
+
+void scsi_print_error(ccb * pccb)
+{
+	/*The ahci error info can be read in the ahci driver*/
+}
+
+int ata_dev_read_sectors(ccb *pccb)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	u32 block=0;
+	u32 n_block=0;
+
+	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;	/*ap->ctl = 0x08 */
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	/* set pdata */
+	ap->pdata = pccb->pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	block |= ((u32)pccb->cmd[2]) << 24;
+	block |= ((u32)pccb->cmd[3]) << 16;
+	block |= ((u32)pccb->cmd[4]) << 8;
+	block |= ((u32)pccb->cmd[5]);
+
+	n_block |= ((u32)pccb->cmd[7]) << 8;
+	n_block |= ((u32)pccb->cmd[8]);
+
+	/* trying temp to n_block */
+	temp_n_block = n_block;
+
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_READ_EXT;  /* READ SECTOR(S) EXT 0x24 */
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else	/* LBA24  */
+	tf.command = ATA_CMD_PIO_READ;  /* READ SECTOR(S) 0x20 */
+	tf.flags |= ATA_TFLAG_LBA ;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif	/* CONFIG_LBA48 */
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	/* sanity check */
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return 0;
+
+err_out:
+	printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return rc;
+}
diff -purN u-boot-2009.03/drivers/block/sata_dwc.h u-boot-2009.03-sata/drivers/block/sata_dwc.h
--- u-boot-2009.03/drivers/block/sata_dwc.h	1970-01-01 09:00:00.000000000 +0900
+++ u-boot-2009.03-sata/drivers/block/sata_dwc.h	2009-03-25 17:27:01.000000000 +0900
@@ -0,0 +1,496 @@
+/*
+ * sata_dwc.h
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under  the terms of  the GNU
+ * General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+
+#ifndef _SATA_DWC_H_
+#define _SATA_DWC_H_
+
+#define HZ 100
+
+#define READ 0
+#define WRITE 1
+
+static int ata_id_has_hipm(const u16 *id)
+{
+	u16 val = id[76];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 9);
+}
+
+static int ata_id_has_dipm(const u16 *id)
+{
+	u16 val = id[78];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 3);
+}
+
+enum {
+	ATA_READID_POSTRESET	= (1 << 0),	/* reading ID after reset */
+
+	ATA_DNXFER_PIO		= 0,	/* speed down PIO */
+	ATA_DNXFER_DMA		= 1,	/* speed down DMA */
+	ATA_DNXFER_40C		= 2,	/* apply 40c cable limit */
+	ATA_DNXFER_FORCE_PIO	= 3,	/* force PIO */
+	ATA_DNXFER_FORCE_PIO0	= 4,	/* force PIO0 */
+
+	ATA_DNXFER_QUIET	= (1 << 31),
+};
+
+enum hsm_task_states {
+	HSM_ST_IDLE,		/* no command on going */
+	HSM_ST_FIRST,		/* (waiting the device to)
+				 * write CDB or first data block */
+	HSM_ST,			/* (waiting the device to) transfer data */
+	HSM_ST_LAST,		/* (waiting the device to) complete command */
+	HSM_ST_ERR,		/* error */
+};
+
+#define	ATA_SHORT_PAUSE		((HZ >> 6) + 1)
+
+typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+
+struct ata_queued_cmd {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
+
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
+	unsigned long		flags;		/* ATA_QCFLAG_xxx */
+	unsigned int		tag;
+	unsigned int		n_elem;
+
+	int			dma_dir;
+
+	unsigned int		sect_size;
+
+	unsigned int		nbytes;
+	unsigned int		extrabytes;
+	unsigned int		curbytes;
+
+	unsigned int		err_mask;
+	struct ata_taskfile	result_tf;
+
+	void			*private_data;
+	void			*lldd_task;
+	unsigned char		*pdata;
+};
+
+/* defines only for the constants which don't work cell as enums*/
+#define ATA_TAG_POISON	0xfafbfcfdU
+
+enum {
+	/* various global constants */
+	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,	/* Worst case */
+	ATA_MAX_PORTS		= 8,
+	ATA_DEF_QUEUE		= 1,
+	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
+	ATA_MAX_QUEUE		= 32,
+	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
+	ATA_MAX_BUS		= 2,
+	ATA_DEF_BUSY_WAIT	= 10000,
+
+	ATAPI_MAX_DRAIN		= 16 << 10,
+
+	ATA_SHT_EMULATED	= 1,
+	ATA_SHT_CMD_PER_LUN	= 1,
+	ATA_SHT_THIS_ID		= -1,
+	ATA_SHT_USE_CLUSTERING	= 1,
+
+	/* struct ata_device stuff */
+	ATA_DFLAG_LBA		= (1 << 0),	/* device supports LBA */
+	ATA_DFLAG_LBA48		= (1 << 1),	/* device supports LBA48 */
+	ATA_DFLAG_CDB_INTR	= (1 << 2),	/* device asserts INTRQ */
+	ATA_DFLAG_NCQ		= (1 << 3),	/* device supports NCQ */
+	ATA_DFLAG_FLUSH_EXT	= (1 << 4),	/* do FLUSH_EXT instead of FLUSH */
+	ATA_DFLAG_ACPI_PENDING 	= (1 << 5),	/* ACPI resume action pending */
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6),	/* ACPI on devcfg has failed */
+	ATA_DFLAG_AN		= (1 << 7),	/* AN configured */
+	ATA_DFLAG_HIPM		= (1 << 8),	/* device supports HIPM */
+	ATA_DFLAG_DIPM		= (1 << 9),	/* device supports DIPM */
+	ATA_DFLAG_DMADIR	= (1 << 10),	/* device requires DMADIR */
+	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
+
+	ATA_DFLAG_PIO		= (1 << 12),	/* device limited to PIO mode */
+	ATA_DFLAG_NCQ_OFF	= (1 << 13),	/* device limited to non-NCQ mode */
+	ATA_DFLAG_SPUNDOWN	= (1 << 14),	/* XXX: for spindown_compat */
+	ATA_DFLAG_SLEEPING	= (1 << 15),	/* device is sleeping */
+	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16),	/* data transfer not verified */
+	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
+
+	ATA_DFLAG_DETACH	= (1 << 24),
+	ATA_DFLAG_DETACHED	= (1 << 25),
+
+	/* struct ata_link flags */
+	ATA_LFLAG_HRST_TO_RESUME	= (1 << 0),	/* hardreset to resume link */
+	ATA_LFLAG_SKIP_D2H_BSY		= (1 << 1),	/* can't wait for the first D2H
+							 * Register FIS clearing BSY */
+	ATA_LFLAG_NO_SRST		= (1 << 2),	/* avoid softreset */
+	ATA_LFLAG_ASSUME_ATA		= (1 << 3),	/* assume ATA class */
+	ATA_LFLAG_ASSUME_SEMB		= (1 << 4),	/* assume SEMB class */
+	ATA_LFLAG_ASSUME_CLASS		= ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
+	ATA_LFLAG_NO_RETRY		= (1 << 5),	/* don't retry this link */
+	ATA_LFLAG_DISABLED		= (1 << 6),	/* link is disabled */
+
+	/* struct ata_port flags */
+	ATA_FLAG_SLAVE_POSS	= (1 << 0),
+	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LEGACY	= (1 << 2),	/* no legacy mode check */
+	ATA_FLAG_MMIO		= (1 << 3),	/* use MMIO, not PIO */
+	ATA_FLAG_SRST		= (1 << 4),	/* (obsolete) use ATA SRST, not E.D.D. */
+	ATA_FLAG_SATA_RESET	= (1 << 5),	/* (obsolete) use COMRESET */
+	ATA_FLAG_NO_ATAPI	= (1 << 6),	/* No ATAPI support */
+	ATA_FLAG_PIO_DMA	= (1 << 7),	/* PIO cmds via DMA */
+	ATA_FLAG_PIO_LBA48	= (1 << 8),	/* Host DMA engine is LBA28 only */
+	ATA_FLAG_PIO_POLLING	= (1 << 9),	/* use polling PIO if LLD
+						* doesn't handle PIO interrupts */
+	ATA_FLAG_NCQ		= (1 << 10),	/* host supports NCQ */
+	ATA_FLAG_DEBUGMSG	= (1 << 13),
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15),	/* ignore SIMPLEX */
+	ATA_FLAG_NO_IORDY	= (1 << 16),	/* controller lacks iordy */
+	ATA_FLAG_ACPI_SATA	= (1 << 17),	/* need native SATA ACPI layout */
+	ATA_FLAG_AN		= (1 << 18),	/* controller supports AN */
+	ATA_FLAG_PMP		= (1 << 19),	/* controller supports PMP */
+	ATA_FLAG_IPM		= (1 << 20),	/* driver can handle IPM */
+
+	ATA_FLAG_DISABLED	= (1 << 23),	/* port is disabled, ignore it */
+
+	/* struct ata_port pflags */
+	ATA_PFLAG_EH_PENDING		= (1 << 0),	/* EH pending */
+	ATA_PFLAG_EH_IN_PROGRESS	= (1 << 1),	/* EH in progress */
+	ATA_PFLAG_FROZEN		= (1 << 2),	/* port is frozen */
+	ATA_PFLAG_RECOVERED		= (1 << 3),	/* recovery action performed */
+	ATA_PFLAG_LOADING		= (1 << 4),	/* boot/loading probe */
+	ATA_PFLAG_UNLOADING		= (1 << 5),	/* module is unloading */
+	ATA_PFLAG_SCSI_HOTPLUG		= (1 << 6),	/* SCSI hotplug scheduled */
+	ATA_PFLAG_INITIALIZING		= (1 << 7),	/* being initialized, don't touch */
+	ATA_PFLAG_RESETTING		= (1 << 8),	/* reset in progress */
+	ATA_PFLAG_SUSPENDED		= (1 << 17),	/* port is suspended (power) */
+	ATA_PFLAG_PM_PENDING		= (1 << 18),	/* PM operation pending */
+
+	/* struct ata_queued_cmd flags */
+	ATA_QCFLAG_ACTIVE	= (1 << 0),	/* cmd not yet ack'd to scsi lyer */
+	ATA_QCFLAG_DMAMAP	= (1 << 1),	/* SG table is DMA mapped */
+	ATA_QCFLAG_IO		= (1 << 3),	/* standard IO command */
+	ATA_QCFLAG_RESULT_TF	= (1 << 4),	/* result TF requested */
+	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5),	/* clear excl_link on completion */
+	ATA_QCFLAG_QUIET	= (1 << 6),	/* don't report device error */
+
+	ATA_QCFLAG_FAILED	= (1 << 16),	/* cmd failed and is owned by EH */
+	ATA_QCFLAG_SENSE_VALID	= (1 << 17),	/* sense data valid */
+	ATA_QCFLAG_EH_SCHEDULED	= (1 << 18),	/* EH scheduled (obsolete) */
+
+	/* host set flags */
+	ATA_HOST_SIMPLEX	= (1 << 0),
+	ATA_HOST_STARTED	= (1 << 1),	/* Host started */
+
+	/* various lengths of time */
+	ATA_TMOUT_BOOT			= 30 * 100,	/* heuristic */
+	ATA_TMOUT_BOOT_QUICK		= 7 * 100,	/* heuristic */
+	ATA_TMOUT_INTERNAL		= 30 * 100,
+	ATA_TMOUT_INTERNAL_QUICK	= 5 * 100,
+
+	/* FIXME: GoVault needs 2s but we can't afford that without
+	 * parallel probing.  800ms is enough for iVDR disk
+	 * HHD424020F7SV00.  Increase to 2secs when parallel probing
+	 * is in place.
+	 */
+	ATA_TMOUT_FF_WAIT	= 4 * 100 / 5,
+
+	/* ATA bus states */
+	BUS_UNKNOWN		= 0,
+	BUS_DMA			= 1,
+	BUS_IDLE		= 2,
+	BUS_NOINTR		= 3,
+	BUS_NODATA		= 4,
+	BUS_TIMER		= 5,
+	BUS_PIO			= 6,
+	BUS_EDD			= 7,
+	BUS_IDENTIFY		= 8,
+	BUS_PACKET		= 9,
+
+	/* SATA port states */
+	PORT_UNKNOWN		= 0,
+	PORT_ENABLED		= 1,
+	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_NR_PIO_MODES	= 7,
+	ATA_NR_MWDMA_MODES	= 5,
+	ATA_NR_UDMA_MODES	= 8,
+
+	ATA_SHIFT_PIO		= 0,
+	ATA_SHIFT_MWDMA		= ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
+	ATA_SHIFT_UDMA		= ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
+
+	/* size of buffer to pad xfers ending on unaligned boundaries */
+	ATA_DMA_PAD_SZ		= 4,
+
+	/* ering size */
+	ATA_ERING_SIZE		= 32,
+
+	ATA_DEFER_LINK		= 1,
+	ATA_DEFER_PORT		= 2,
+
+	/* desc_len for ata_eh_info and context */
+	ATA_EH_DESC_LEN		= 80,
+
+	/* reset / recovery action types */
+	ATA_EH_REVALIDATE	= (1 << 0),
+	ATA_EH_SOFTRESET	= (1 << 1),
+	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_ENABLE_LINK	= (1 << 3),
+	ATA_EH_LPM		= (1 << 4),	/* link power management action */
+
+	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+	/* ata_eh_info->flags */
+	ATA_EHI_HOTPLUGGED	= (1 << 0),	/* could have been hotplugged */
+	ATA_EHI_RESUME_LINK	= (1 << 1),	/* resume link (reset modifier) */
+	ATA_EHI_NO_AUTOPSY	= (1 << 2),	/* no autopsy */
+	ATA_EHI_QUIET		= (1 << 3),	/* be quiet */
+
+	ATA_EHI_DID_SOFTRESET	= (1 << 16),	/* already soft-reset this port */
+	ATA_EHI_DID_HARDRESET	= (1 << 17),	/* already soft-reset this port */
+	ATA_EHI_PRINTINFO	= (1 << 18),	/* print configuration info */
+	ATA_EHI_SETMODE		= (1 << 19),	/* configure transfer mode */
+	ATA_EHI_POST_SETMODE	= (1 << 20),	/* revaildating after setmode */
+
+	ATA_EHI_DID_RESET       = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+	/* max tries if error condition is still set after ->error_handler */
+	ATA_EH_MAX_TRIES	= 5,
+
+	/* how hard are we gonna try to probe/recover devices */
+	ATA_PROBE_MAX_TRIES	= 3,
+	ATA_EH_DEV_TRIES	= 3,
+	ATA_EH_PMP_TRIES	= 5,
+	ATA_EH_PMP_LINK_TRIES	= 3,
+
+	SATA_PMP_SCR_TIMEOUT	= 250,
+
+	/* Horkage types. May be set by libata or controller on drives
+	(some horkage may be drive/controller pair dependant */
+
+	ATA_HORKAGE_DIAGNOSTIC	= (1 << 0),	/* Failed boot diag */
+	ATA_HORKAGE_NODMA	= (1 << 1),	/* DMA problems */
+	ATA_HORKAGE_NONCQ	= (1 << 2),	/* Don't use NCQ */
+	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),	/* Limit max sects to 128 */
+	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),	/* Broken HPA */
+	ATA_HORKAGE_SKIP_PM	= (1 << 5),	/* Skip PM operations */
+	ATA_HORKAGE_HPA_SIZE	= (1 << 6),	/* native size off by one */
+	ATA_HORKAGE_IPM		= (1 << 7),	/* Link PM problems */
+	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */
+	ATA_HORKAGE_STUCK_ERR	= (1 << 9),	/* stuck ERR on next PACKET */
+
+	/* DMA mask for user DMA control: User visible values; DO NOT renumber */
+	ATA_DMA_MASK_ATA	= (1 << 0),	/* DMA on ATA Disk */
+	ATA_DMA_MASK_ATAPI	= (1 << 1),	/* DMA on ATAPI */
+	ATA_DMA_MASK_CFA	= (1 << 2),	/* DMA on CF Card */
+
+	/* ATAPI command types */
+	ATAPI_READ		= 0,		/* READs */
+	ATAPI_WRITE		= 1,		/* WRITEs */
+	ATAPI_READ_CD		= 2,		/* READ CD [MSF] */
+	ATAPI_PASS_THRU		= 3,		/* SAT pass-thru */
+	ATAPI_MISC		= 4,		/* the rest */
+};
+
+enum ata_completion_errors {
+	AC_ERR_DEV		= (1 << 0),	/* device reported error */
+	AC_ERR_HSM		= (1 << 1),	/* host state machine violation */
+	AC_ERR_TIMEOUT		= (1 << 2),	/* timeout */
+	AC_ERR_MEDIA		= (1 << 3),	/* media error */
+	AC_ERR_ATA_BUS		= (1 << 4),	/* ATA bus error */
+	AC_ERR_HOST_BUS		= (1 << 5),	/* host bus error */
+	AC_ERR_SYSTEM		= (1 << 6),	/* system error */
+	AC_ERR_INVALID		= (1 << 7),	/* invalid argument */
+	AC_ERR_OTHER		= (1 << 8),	/* unknown */
+	AC_ERR_NODEV_HINT	= (1 << 9),	/* polling device detection hint */
+	AC_ERR_NCQ		= (1 << 10),	/* marker for offending NCQ qc */
+};
+
+enum ata_xfer_mask {
+	ATA_MASK_PIO	= ((1LU << ATA_NR_PIO_MODES) - 1) << ATA_SHIFT_PIO,
+	ATA_MASK_MWDMA	= ((1LU << ATA_NR_MWDMA_MODES) - 1) << ATA_SHIFT_MWDMA,
+	ATA_MASK_UDMA	= ((1LU << ATA_NR_UDMA_MODES) - 1) << ATA_SHIFT_UDMA,
+};
+
+struct ata_port_info {
+	struct scsi_host_template	*sht;
+	unsigned long			flags;
+	unsigned long			link_flags;
+	unsigned long			pio_mask;
+	unsigned long			mwdma_mask;
+	unsigned long			udma_mask;
+	const struct ata_port_operations *port_ops;
+	void				*private_data;
+};
+
+struct ata_ioports {
+	void __iomem		*cmd_addr;
+	void __iomem		*data_addr;
+	void __iomem		*error_addr;
+	void __iomem		*feature_addr;
+	void __iomem		*nsect_addr;
+	void __iomem		*lbal_addr;
+	void __iomem		*lbam_addr;
+	void __iomem		*lbah_addr;
+	void __iomem		*device_addr;
+	void __iomem		*status_addr;
+	void __iomem		*command_addr;
+	void __iomem		*altstatus_addr;
+	void __iomem		*ctl_addr;
+	void __iomem		*bmdma_addr;
+	void __iomem		*scr_addr;
+};
+
+struct ata_host {
+	void __iomem * const	*iomap;
+	unsigned int		n_ports;
+	void			*private_data;
+	const struct ata_port_operations *ops;
+	unsigned long		flags;
+	struct ata_port		*simplex_claimed;	/* channel owning the DMA */
+	struct ata_port		*ports[0];
+};
+
+struct ata_port_stats {
+	unsigned long		unhandled_irq;
+	unsigned long		idle_irq;
+	unsigned long		rw_reqbuf;
+};
+
+struct ata_device {
+	struct ata_link		*link;
+	unsigned int		devno;		/* 0 or 1 */
+	unsigned long		flags;		/* ATA_DFLAG_xxx */
+	unsigned int		horkage;	/* List of broken features */
+	struct scsi_device	*sdev;		/* attached SCSI device */
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	union acpi_object	*gtf_cache;
+#endif
+	/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
+	u64			n_sectors;	/* size of device, if ATA */
+	unsigned int		class;		/* ATA_DEV_xxx */
+
+	union {
+		u16		id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+		u32		gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+	};
+
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
+
+	unsigned int		multi_count;	/* sectors count for
+						 *READ/WRITE MULTIPLE */
+	unsigned int		max_sectors;    /* per-device max sectors */
+	unsigned int		cdb_len;
+
+	/* per-dev xfer mask */
+	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
+	unsigned long		udma_mask;
+
+	/* for CHS addressing */
+	u16			cylinders;	/* Number of cylinders */
+	u16			heads;		/* Number of heads */
+	u16			sectors;	/* Number of sectors per track */
+
+	/* error history */
+	int			spdn_cnt;
+};
+
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL = 0,
+	DMA_TO_DEVICE = 1,
+	DMA_FROM_DEVICE = 2,
+	DMA_NONE = 3,
+};
+
+struct ata_link {
+	struct ata_port		*ap;
+	int			pmp;		/* port multiplier port # */
+	unsigned int		active_tag;	/* active tag on this link */
+	u32			sactive;	/* active NCQ commands */
+
+	unsigned int		flags;		/* ATA_LFLAG_xxx */
+
+	unsigned int		hw_sata_spd_limit;
+	unsigned int		sata_spd_limit;
+	unsigned int		sata_spd;	/* current SATA PHY speed */
+
+	struct ata_device	device[2];
+};
+
+struct ata_port {
+	unsigned long		flags;		/* ATA_FLAG_xxx */
+	unsigned int		pflags;		/* ATA_PFLAG_xxx */
+	unsigned int		print_id;	/* user visible unique port ID */
+	unsigned int            port_no;	/* 0 based port no. inside the host */
+
+	struct ata_ioports	ioaddr;		/* ATA cmd/ctl/dma register blocks */
+
+	u8			ctl;		/* cache of ATA control register */
+	u8			last_ctl;	/* Cache last written value */
+	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
+	unsigned int		udma_mask;
+	unsigned int		cbl;		/* cable type; ATA_CBL_xxx */
+
+	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+	unsigned long		qc_allocated;
+	unsigned int		qc_active;
+	int			nr_active_links;	/* #links with active qcs */
+
+	struct ata_link		link;		/* host default link */
+
+	int			nr_pmp_links;	/* nr of available PMP links */
+	struct ata_link		*pmp_link;	/* array of PMP links */
+	struct ata_link		*excl_link;	/* for PMP qc exclusion */
+
+	struct ata_port_stats	stats;
+	struct ata_host		*host;
+
+	struct device		*dev;
+	void			*port_task_data;
+
+	unsigned int		hsm_task_state;
+
+	u32			msg_enable;
+	void			*private_data;
+	unsigned char		*pdata;
+};
+#endif	/* _SATA_DWC_H_ */
diff -purN u-boot-2009.03/include/configs/canyonlands.h u-boot-2009.03-sata/include/configs/canyonlands.h
--- u-boot-2009.03/include/configs/canyonlands.h	2009-03-22 06:04:41.000000000 +0900
+++ u-boot-2009.03-sata/include/configs/canyonlands.h	2009-03-25 17:31:40.000000000 +0900
@@ -34,6 +34,7 @@
  #ifdef CONFIG_CANYONLANDS
  #define CONFIG_460EX		1	/* Specific PPC460EX		*/
  #define CONFIG_HOSTNAME		canyonlands
+#define CONFIG_SATA_DWC			/* PPC460EX SATA support	*/
  #else
  #define CONFIG_460GT		1	/* Specific PPC460GT		*/
  #ifdef CONFIG_GLACIER
@@ -454,6 +455,9 @@
  #define CONFIG_CMD_SDRAM
  #define CONFIG_CMD_SNTP
  #define CONFIG_CMD_USB
+#if defined(CONFIG_SATA_DWC)
+#define CONFIG_CMD_SCSI
+#endif
  #elif defined(CONFIG_GLACIER)
  #define CONFIG_CMD_DATE
  #define CONFIG_CMD_DTT
@@ -517,6 +521,18 @@
  #endif /* CONFIG_460GT */

  /*-----------------------------------------------------------------------
+ * S-ATA driver setup
+ *----------------------------------------------------------------------*/
+#ifdef CONFIG_SATA_DWC
+#define CONFIG_LIBATA
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	1	/* SCSI ID */
+#define CONFIG_SYS_SCSI_MAX_LUN		1	/* SCSI LUN */
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+						CONFIG_SYS_SCSI_MAX_LUN)
+#define CONFIG_SYS_SCSI_MAXDEVICE	CONFIG_SYS_SCSI_MAX_DEVICE
+#endif
+
+/*-----------------------------------------------------------------------
   * External Bus Controller (EBC) Setup
   *----------------------------------------------------------------------*/



Regards,
Kazuaki Ichinohe

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-25 11:32     ` Kazuaki Ichinohe
@ 2009-03-25 16:04       ` Stefan Roese
  2009-03-26 10:56         ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2009-03-25 16:04 UTC (permalink / raw)
  To: u-boot

On Wednesday 25 March 2009, Kazuaki Ichinohe wrote:
> Hi Stefan,
>
> Thank you for the reply.
> This is the patch that corrects the point.
>
> Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>

OK, now you added your Signed-off-by line and the patch itself doesn't seem to 
be line wrapped. But the commit text above is not really describing the 
patch. Your first version was better.

Please find some more comments below.

> ---
>
> [patch]
> diff -purN u-boot-2009.03/common/cmd_scsi.c
> u-boot-2009.03-sata/common/cmd_scsi.c ---
> u-boot-2009.03/common/cmd_scsi.c	2009-03-22 06:04:41.000000000 +0900 +++
> u-boot-2009.03-sata/common/cmd_scsi.c	2009-03-25 18:53:29.000000000 +0900
> @@ -47,8 +47,10 @@
>   #define SCSI_DEV_ID  0x5288
>
>   #else
> +#ifndef CONFIG_SATA_DWC
>   #error no scsi device defined
>   #endif
> +#endif

Why do you add this 460EX SATA support to cmd_scsi.c? Wouldn't cmd_sata.c be a 
better place? Or did I miss something here?

<snip>

> +++ u-boot-2009.03-sata/drivers/block/sata_dwc.c	2009-03-25
> 18:02:07.000000000 +0900 @@ -0,0 +1,2175 @@
> +/*
> + * sata_dwc.c
> + *
> + * Synopsys DesignWare Cores (DWC) SATA host driver
> + *
> + * Author: Mark Miesfeld <mmiesfeld@amcc.com>
> + *
> + * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
> + * Copyright 2008 DENX Software Engineering
> + *
> + * Based on versions provided by AMCC and Synopsys which are:
> + *          Copyright 2006 Applied Micro Circuits Corporation
> + *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
> + *
> + * This program is free software; you can redistribute
> + * it and/or modify it under the terms of the GNU
> + * General Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License,
> + * or (at your option) any later version.
> + *
> + */

As it seems you added the Linux driver version with some changes so that it 
fits into U-Boot. You should document this in the commit text of this patch.

> +
> +#include <common.h>
> +#include <command.h>
> +#include <pci.h>
> +#include <asm/processor.h>
> +#include <asm/errno.h>
> +#include <asm/io.h>
> +#include <malloc.h>
> +#include <scsi.h>
> +#include <ata.h>
> +#include <linux/ctype.h>
> +
> +/* sata_dwc.h */
> +#include "sata_dwc.h"
> +
> +/* Base Address */
> +#define SATA_BASE_ADDR		0xe20d1000
> +#define SATA_DMA_REG_ADDR	0xe20d0800

These defines should be moved to another (Canyonlands specific) header. It 
could be that at some time another platform/board will be added using the 
same DesignWare SATA core but with different addresses.

<snip>

> +u8 ata_check_altstatus(struct ata_port *ap)
> +{
> +	u8 val = 0;
> +	val = readb(ap->ioaddr.altstatus_addr);
> +	return val;
> +}
> +
> +int check_sata_dev_state(void)
> +{
> +	static ccb tempccb;		/* temporary scsi command buffer */
> +	ccb *pccb = (ccb *)&tempccb;
> +	int ret = 0;
> +	int i = 0;
> +
> +	while(1){

Space after "while" please. Please check this file again. Here are multiple 
places where you don't have a space after the "while" or "if" statement.

> +		udelay (10000);		/* 10 ms */
> +
> +	        pccb->cmd[0] = SCSI_READ10;
> +	        pccb->cmd[1] = 0;
> +	        pccb->cmd[2] = 0;
> +	        pccb->cmd[3] = 0;
> +	        pccb->cmd[4] = 0;
> +	        pccb->cmd[5] = 0;
> +	        pccb->cmd[6] = 0;
> +	        pccb->cmd[7] = 0;
> +	        pccb->cmd[8] = 1;
> +	        pccb->cmdlen = 10;
> +		pccb->pdata = &temp_data_buf[0];	/* dummy */
> +		pccb->datalen = 512;
> +
> +		/* Send Read Command */
> +		ret =  ata_dev_read_sectors(pccb);
> +
> +		/* result TRUE => break */
> +		if(ret == 0){

Here again.

> +			break;
> +		}

And these curly braces are not needed (because of a single line statement). 
Please remove them,

> +
> +		i++;
> +		if (i > (ATA_RESET_TIME * 100)){
> +			printf("** TimeOUT **\n");
> +			dev_state = SATA_NODEVICE;	/* set device status flag */
> +			return FALSE;
> +		}
> +
> +		if ((i >= 100) && ((i%100)==0)) {
> +			printf(".");
> +		}

Again, single line statement.

> +	}
> +
> +	/* Set device status flag */
> +	dev_state = SATA_READY;
> +
> +	return TRUE;
> +}
> +
> +void ata_id_string(const u16 *id, unsigned char *s,
> +		unsigned int ofs, unsigned int len)
> +{
> +	unsigned int c;
> +
> +	while (len > 0) {
> +		c = id[ofs] >> 8;
> +		*s = c;
> +		s++;
> +
> +		c = id[ofs] & 0xff;
> +		*s = c;
> +		s++;
> +
> +		ofs++;
> +		len -= 2;
> +	}
> +}
> +
> +static int waiting_for_reg_state(volatile u8 *offset,
> +				int timeout_msec,
> +				u32 sign)
> +{
> +	int i;
> +	u32 status;
> +
> +	for (i = 0; i < timeout_msec; i++){
> +		status = readl(offset);
> +		if ( ( status & sign ) != 0 ){

This should be:

		if ((status & sign) != 0) {

> +			break;
> +		}

Remove curly braces.

> +		msleep(1);
> +	}
> +
> +	return (i < timeout_msec) ? 0 : -1;
> +}
> +
> +static inline u32 qcmd_tag_to_mask(u8 tag)
> +{
> +	return (0x00000001 << (tag & 0x1f));
> +}
> +
> +static u8 ata_check_status(struct ata_port *ap)
> +{
> +	u8 val = 0;
> +	val = readb(ap->ioaddr.status_addr);
> +	return val;
> +}
> +
> +static u8 ata_busy_wait(struct ata_port *ap,
> +		unsigned int bits,unsigned int max)
> +{
> +	u8 status;
> +
> +	do {
> +		udelay(10);
> +		status = ata_check_status(ap);
> +		max--;
> +	} while (status != 0xff && (status & bits) && (max > 0));
> +
> +	return status;
> +}
> +
> +static u8 ata_wait_idle(struct ata_port *ap)
> +{
> +	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
> +	return status;
> +}
> +
> +static int sata_dwc_scsiop_inq(ccb *pccb)
> +{
> +	struct ata_device *ata_dev = &ata_device;
> +	u16 *id;
> +
> +	/* Set IDENTIFY Data */
> +	id = ata_dev->id;
> +
> +	/* make INQUIRY header */
> +	u8 hdr[] = {
> +		0,
> +		0,
> +		0x5,	/* claim SPC-3 version compatibility */
> +		2,
> +		95 - 4
> +	};
> +
> +	/* set scsi removeable (RMB) bit per ata bit */
> +	if (ata_id_removeable(id)){
> +		hdr[1] |= (1 << 7);
> + 	}

Single line statement. Please remove the curly braces. There are most likely 
further places with this issue. I won't comment on them again. Please check 
the complete file for it.

> +
> +	memcpy(pccb->pdata, hdr, sizeof(hdr));
> +
> +	if (pccb->datalen > 35) {
> +		memcpy(&pccb->pdata[8], "ATA     ", 8);
> +		ata_id_string(id, &pccb->pdata[16], ATA_ID_PROD, 16);
> +		ata_id_string(id, &pccb->pdata[32], ATA_ID_FW_REV, 4);
> +		if (pccb->pdata[32] == 0 || pccb->pdata[32] == ' '){
> +			memcpy(&pccb->pdata[32], "n/a ", 4);
> +		}
> +	}
> +
> +	if (pccb->datalen > 63) {
> +		const u8 versions[] = {
> +			0x60,	/* SAM-3 (no version claimed) */
> +			0x03,
> +			0x20,	/* SBC-2 (no version claimed) */
> +			0x02,
> +			0x60	/* SPC-3 (no version claimed) */
> +		};
> +		memcpy(pccb->pdata + 59, versions, sizeof(versions));
> +	}
> +
> +	return 0;
> +}
> +
> +#define ATA_SCSI_PDATA_SET(idx, val) do { \
> +	if ((idx) < pccb->datalen) pccb->pdata[(idx)] = (u8)(val); \
> +	} while (0)
> +
> +static int sata_dwc_scsiop_read_cap(ccb *pccb)
> +{
> +	struct ata_device *ata_dev = &ata_device;
> +	u32 last_lba;
> +	last_lba = ata_dev->n_sectors;	/* LBA of the last block */
> +
> +	if (pccb->cmd[0] == SCSI_RD_CAPAC) {
> +		if (last_lba >= 0xffffffffULL){
> +			last_lba = 0xffffffff;
> +		}
> +
> +		/* sector count, 32-bit */
> +		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 3));
> +		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 2));
> +		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 1));
> +		ATA_SCSI_PDATA_SET(3, last_lba);
> +
> +		/* buffer clear */
> +		ATA_SCSI_PDATA_SET(4, 0);
> +		ATA_SCSI_PDATA_SET(5, 0);
> +
> +		/* sector size */
> +		ATA_SCSI_PDATA_SET(6, ATA_SECT_SIZE >> 8);
> +		ATA_SCSI_PDATA_SET(7, ATA_SECT_SIZE & 0xff);
> +
> +	} else {
> +		/* sector count, 64-bit */
> +		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 7));
> +		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 6));
> +		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 5));
> +		ATA_SCSI_PDATA_SET(3, last_lba >> (8 * 4));
> +		ATA_SCSI_PDATA_SET(4, last_lba >> (8 * 3));
> +		ATA_SCSI_PDATA_SET(5, last_lba >> (8 * 2));
> +		ATA_SCSI_PDATA_SET(6, last_lba >> (8 * 1));
> +		ATA_SCSI_PDATA_SET(7, last_lba);
> +
> +		/* sector size */
> +		ATA_SCSI_PDATA_SET(10, ATA_SECT_SIZE >> 8);
> +		ATA_SCSI_PDATA_SET(11, ATA_SECT_SIZE & 0xff);
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * SCSI TEST UNIT READY command operation.
> + *      No operation.  Simply returns success to caller, to indicate
> + *      that the caller should successfully complete this SCSI command.
> + */
> +static int sata_dwc_scsiop_test_unit_ready(ccb *pccb)
> +{
> +	/* No operation  */
> +	return 0;
> +}
> +
> +int scsi_exec(ccb *pccb)
> +{
> +	int ret;
> +
> +	/* check device status */
> +	if(dev_state != SATA_READY){
> +		return FALSE;
> +	}
> +
> +	switch (pccb->cmd[0]) {
> +	case SCSI_READ10:
> +		ret =  ata_dev_read_sectors(pccb);
> +		break;
> +	case SCSI_RD_CAPAC:
> +		ret = sata_dwc_scsiop_read_cap(pccb);
> +		break;
> +	case SCSI_TST_U_RDY:
> +		ret = sata_dwc_scsiop_test_unit_ready(pccb);
> +		break;
> +	case SCSI_INQUIRY:
> +		ret = sata_dwc_scsiop_inq(pccb);
> +		break;
> +	default:
> +		printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
> +		return FALSE;
> +	}
> +
> +	if (ret) {
> +		debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
> +		return FALSE;
> +	}
> +	return TRUE;
> +}
> +
> +static const struct ata_port_info sata_dwc_port_info[] = {
> +	{
> +		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
> +				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
> +				ATA_FLAG_SRST | ATA_FLAG_NCQ,
> +		.pio_mask	= 0x1f,	/* pio 0-4 */
> +		.mwdma_mask	= 0x07,
> +		.udma_mask	= 0x7f,
> +	},
> +};
> +
> +int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
> +		unsigned int flags, u16 *id)
> +{
> +	struct ata_port *ap = pap;
> +	unsigned int class = *p_class;
> +	struct ata_taskfile tf;
> +	unsigned int err_mask = 0;
> +	const char *reason;
> +	int may_fallback = 1, tried_spinup = 0;
> +	u8 status;
> +	int rc;
> +
> +	/* cheack BSY = 0 */
> +	status = ata_busy_wait(ap, ATA_BUSY, 30000);
> +	if (status & ATA_BUSY) {
> +		printf("BSY = 0 check. timeout.\n");
> +		rc = FALSE;
> +		return rc;
> +	}
> +
> +        ata_dev_select(ap, dev->devno, 1, 1);	/* select device 0/1 */
> +
> +retry:
> +	memset(&tf, 0, sizeof(tf));
> +	ap->print_id = 1;
> +	ap->flags &= ~ATA_FLAG_DISABLED;
> +	tf.ctl = ap->ctl;	/* 0x08 */
> +	tf.device = ATA_DEVICE_OBS;
> +	tf.command = ATA_CMD_ID_ATA;
> +	tf.protocol = ATA_PROT_PIO;
> +
> +	/* Some devices choke if TF registers contain garbage.  Make
> +	 * sure those are properly initialized.
> +	 */
> +	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
> +
> +	/* Device presence detection is unreliable on some
> +	 * controllers.  Always poll IDENTIFY if available.
> +	 */
> +	tf.flags |= ATA_TFLAG_POLLING;
> +
> +	temp_n_block = 1;
> +
> +	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
> +					sizeof(id[0]) * ATA_ID_WORDS, 0);
> +
> +	if (err_mask) {
> +		if (err_mask & AC_ERR_NODEV_HINT) {
> +			printf("NODEV after polling detection\n");
> +			return -ENOENT;
> +		}
> +
> +		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
> +			/* Device or controller might have reported
> +			 * the wrong device class.  Give a shot at the
> +			 * other IDENTIFY if the current one is
> +			 * aborted by the device.
> +			 */
> +			if (may_fallback) {
> +				may_fallback = 0;
> +
> +				if (class == ATA_DEV_ATA) {
> +					class = ATA_DEV_ATAPI;
> +				} else {
> +					class = ATA_DEV_ATA;
> +				}
> +				goto retry;
> +			}
> +			/* Control reaches here iff the device aborted
> +			 * both flavors of IDENTIFYs which happens
> +			 * sometimes with phantom devices.
> +			 */
> +			printf("both IDENTIFYs aborted, assuming NODEV\n");
> +			return -ENOENT;
> +		}
> +		rc = -EIO;
> +		reason = "I/O error";
> +		goto err_out;
> +	}
> +
> +	/* Falling back doesn't make sense if ID data was read
> +	 * successfully at least once.
> +	 */
> +	may_fallback = 0;
> +
> +#ifdef __BIG_ENDIAN
> +	unsigned int id_cnt;
> +
> +	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
> +		id[id_cnt] = le16_to_cpu(id[id_cnt]);
> +
> +#endif	/* __BIG_ENDIAN */

And what happens if the platform is little-endian? Doesn't the le16_to_cpu() 
function handle the conversion? I think you can remove the #ifdef and use 
this code unconditionally.

<big snip>

> u-boot-2009.03/drivers/block/sata_dwc.h	1970-01-01 09:00:00.000000000 +0900
> +++ u-boot-2009.03-sata/drivers/block/sata_dwc.h	2009-03-25
> 17:27:01.000000000 +0900 @@ -0,0 +1,496 @@
> +/*
> + * sata_dwc.h
> + *
> + * Synopsys DesignWare Cores (DWC) SATA host driver
> + *
> + * Author: Mark Miesfeld <mmiesfeld@amcc.com>
> + *
> + * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
> + * Copyright 2008 DENX Software Engineering
> + *
> + * Based on versions provided by AMCC and Synopsys which are:
> + *          Copyright 2006 Applied Micro Circuits Corporation
> + *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
> + *
> + * This program is free software; you can redistribute
> + * it and/or modify it under  the terms of  the GNU
> + * General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License,
> + * or (at your option) any later version.
> + *
> + */
> +
> +#ifndef _SATA_DWC_H_
> +#define _SATA_DWC_H_
> +
> +#define HZ 100
> +
> +#define READ 0
> +#define WRITE 1
> +
> +static int ata_id_has_hipm(const u16 *id)
> +{
> +	u16 val = id[76];
> +
> +	if (val == 0 || val == 0xffff)
> +		return -1;
> +
> +	return val & (1 << 9);
> +}

Don't add code to header. Only inline functions should be added here. So 
either add "inline" or move it to a ".c" file.

> +
> +static int ata_id_has_dipm(const u16 *id)
> +{
> +	u16 val = id[78];
> +
> +	if (val == 0 || val == 0xffff)
> +		return -1;
> +
> +	return val & (1 << 3);
> +}

Same here.

<snip>

> u-boot-2009.03/include/configs/canyonlands.h	2009-03-22 06:04:41.000000000
> +0900 +++ u-boot-2009.03-sata/include/configs/canyonlands.h	2009-03-25
> 17:31:40.000000000 +0900 @@ -34,6 +34,7 @@
>   #ifdef CONFIG_CANYONLANDS
>   #define CONFIG_460EX		1	/* Specific PPC460EX		*/
>   #define CONFIG_HOSTNAME		canyonlands
> +#define CONFIG_SATA_DWC			/* PPC460EX SATA support	*/

Not sure if we really should enable this per default on the Canyonlands 
platform. What's the size impact of this SATA support?

>   #else
>   #define CONFIG_460GT		1	/* Specific PPC460GT		*/
>   #ifdef CONFIG_GLACIER
> @@ -454,6 +455,9 @@
>   #define CONFIG_CMD_SDRAM
>   #define CONFIG_CMD_SNTP
>   #define CONFIG_CMD_USB
> +#if defined(CONFIG_SATA_DWC)
> +#define CONFIG_CMD_SCSI
> +#endif

Again, I think this should go into CMD_SATA instead of SCSI.

Thanks.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-25 16:04       ` Stefan Roese
@ 2009-03-26 10:56         ` Kazuaki Ichinohe
  2009-03-27 16:11           ` Stefan Roese
  2009-03-27 16:31           ` Wolfgang Denk
  0 siblings, 2 replies; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-26 10:56 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

Thank you for the reply.
My answer is described in the beginning.

 >> Hi Stefan,
 >>
 >> Thank you for the reply.
 >> This is the patch that corrects the point.
 >>
 >> Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>
 >
 > OK, now you added your Signed-off-by line and the patch itself doesn't seem to
 > be line wrapped. But the commit text above is not really describing the
 > patch. Your first version was better.

It will take care next time.


 >> ---
 >>
 >> [patch]
 >> diff -purN u-boot-2009.03/common/cmd_scsi.c
 >> u-boot-2009.03-sata/common/cmd_scsi.c ---
 >> u-boot-2009.03/common/cmd_scsi.c	2009-03-22 06:04:41.000000000 +0900 +++
 >> u-boot-2009.03-sata/common/cmd_scsi.c	2009-03-25 18:53:29.000000000 +0900
 >> @@ -47,8 +47,10 @@
 >>   #define SCSI_DEV_ID  0x5288
 >>
 >>   #else
 >> +#ifndef CONFIG_SATA_DWC
 >>   #error no scsi device defined
 >>   #endif
 >> +#endif
 >
 >Why do you add this 460EX SATA support to cmd_scsi.c? Wouldn't cmd_sata.c be a
 >better place? Or did I miss something here?

The cmd_scsi.c which define CONFIG_CMD_SCSI are modified
because I want to use scsiboot command of U-BOOT.


 >> +++ u-boot-2009.03-sata/drivers/block/sata_dwc.c	2009-03-25
 >> 18:02:07.000000000 +0900 @@ -0,0 +1,2175 @@
 >> +/*
 >> + * sata_dwc.c
 >> + *
 >> + * Synopsys DesignWare Cores (DWC) SATA host driver
 >> + *
 >> + * Author: Mark Miesfeld <mmiesfeld@amcc.com>
 >> + *
 >> + * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
 >> + * Copyright 2008 DENX Software Engineering
 >> + *
 >> + * Based on versions provided by AMCC and Synopsys which are:
 >> + *          Copyright 2006 Applied Micro Circuits Corporation
 >> + *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
 >> + *
 >> + * This program is free software; you can redistribute
 >> + * it and/or modify it under the terms of the GNU
 >> + * General Public License as published by the
 >> + * Free Software Foundation;  either version 2 of the  License,
 >> + * or (at your option) any later version.
 >> + *
 >> + */
 >
 >As it seems you added the Linux driver version with some changes so that it
 >fits into U-Boot. You should document this in the commit text of this patch.

I corrected.


 >> +
 >> +#include <common.h>
 >> +#include <command.h>
 >> +#include <pci.h>
 >> +#include <asm/processor.h>
 >> +#include <asm/errno.h>
 >> +#include <asm/io.h>
 >> +#include <malloc.h>
 >> +#include <scsi.h>
 >> +#include <ata.h>
 >> +#include <linux/ctype.h>
 >> +
 >> +/* sata_dwc.h */
 >> +#include "sata_dwc.h"
 >> +
 >> +/* Base Address */
 >> +#define SATA_BASE_ADDR		0xe20d1000
 >> +#define SATA_DMA_REG_ADDR	0xe20d0800
 >
 >These defines should be moved to another (Canyonlands specific) header. It
 >could be that at some time another platform/board will be added using the
 >same DesignWare SATA core but with different addresses.

I corrected.


 >> +u8 ata_check_altstatus(struct ata_port *ap)
 >> +{
 >> +	u8 val = 0;
 >> +	val = readb(ap->ioaddr.altstatus_addr);
 >> +	return val;
 >> +}
 >> +
 >> +int check_sata_dev_state(void)
 >> +{
 >> +	static ccb tempccb;		/* temporary scsi command buffer */
 >> +	ccb *pccb = (ccb *)&tempccb;
 >> +	int ret = 0;
 >> +	int i = 0;
 >> +
 >> +	while(1){
 >
 >Space after "while" please. Please check this file again. Here are multiple
 >places where you don't have a space after the "while" or "if" statement.

I corrected.


 >> +		udelay (10000);		/* 10 ms */>
 >> +
 >> +	        pccb->cmd[0] = SCSI_READ10;
 >> +	        pccb->cmd[1] = 0;
 >> +	        pccb->cmd[2] = 0;
 >> +	        pccb->cmd[3] = 0;
 >> +	        pccb->cmd[4] = 0;
 >> +	        pccb->cmd[5] = 0;
 >> +	        pccb->cmd[6] = 0;
 >> +	        pccb->cmd[7] = 0;
 >> +	        pccb->cmd[8] = 1;
 >> +	        pccb->cmdlen = 10;
 >> +		pccb->pdata = &temp_data_buf[0];	/* dummy */
 >> +		pccb->datalen = 512;
 >> +
 >> +		/* Send Read Command */
 >> +		ret =  ata_dev_read_sectors(pccb);
 >> +
 >> +		/* result TRUE => break */
 >> +		if(ret == 0){
 >
 >Here again.
 >
 > +			break;
 > +		}
 >
 >And these curly braces are not needed (because of a single line statement).
 >Please remove them,

I corrected.


 >> +	}
 >> +
 >> +	/* Set device status flag */
 >> +	dev_state = SATA_READY;
 >> +
 >> +	return TRUE;
 >> +}
 >> +
 >> +void ata_id_string(const u16 *id, unsigned char *s,
 >> +		unsigned int ofs, unsigned int len)
 >> +{
 >> +	unsigned int c;
 >> +
 >> +	while (len > 0) {
 >> +		c = id[ofs] >> 8;
 >> +		*s = c;
 >> +		s++;
 >> +
 >> +		c = id[ofs] & 0xff;
 >> +		*s = c;
 >> +		s++;
 >> +
 >> +		ofs++;
 >> +		len -= 2;
 >> +	}
 >> +}
 >> +
 >> +static int waiting_for_reg_state(volatile u8 *offset,
 >> +				int timeout_msec,
 >> +				u32 sign)
 >> +{
 >> +	int i;
 >> +	u32 status;
 >> +
 >> +	for (i = 0; i < timeout_msec; i++){
 >> +		status = readl(offset);
 >> +		if ( ( status & sign ) != 0 ){
 >
 >This should be:
 >
 >		if ((status & sign) != 0) {
 >

I corrected.


 >> +
 >> +	/* Falling back doesn't make sense if ID data was read
 >> +	 * successfully at least once.
 >> +	 */
 >> +	may_fallback = 0;
 >> +
 >> +#ifdef __BIG_ENDIAN
 >> +	unsigned int id_cnt;
 >> +
 >> +	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
 >> +		id[id_cnt] = le16_to_cpu(id[id_cnt]);
 >> +
 >> +#endif	/* __BIG_ENDIAN */
 >
 >
 >And what happens if the platform is little-endian? Doesn't the le16_to_cpu()
 >function handle the conversion? I think you can remove the #ifdef and use
 >this code unconditionally.

I corrected.


 >> u-boot-2009.03/drivers/block/sata_dwc.h	1970-01-01 09:00:00.000000000 +0900
 >> +++ u-boot-2009.03-sata/drivers/block/sata_dwc.h	2009-03-25
 >> 17:27:01.000000000 +0900 @@ -0,0 +1,496 @@
 >> +/*
 >> + * sata_dwc.h
 >> + *
 >> + * Synopsys DesignWare Cores (DWC) SATA host driver
 >> + *
 >> + * Author: Mark Miesfeld <mmiesfeld@amcc.com>
 >> + *
 >> + * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
 >> + * Copyright 2008 DENX Software Engineering
 >> + *
 >> + * Based on versions provided by AMCC and Synopsys which are:
 >> + *          Copyright 2006 Applied Micro Circuits Corporation
 >> + *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
 >> + *
 >> + * This program is free software; you can redistribute
 >> + * it and/or modify it under  the terms of  the GNU
 >> + * General  Public License as published by the
 >> + * Free Software Foundation;  either version 2 of the  License,
 >> + * or (at your option) any later version.
 >> + *
 >> + */
 >> +
 >> +#ifndef _SATA_DWC_H_
 >> +#define _SATA_DWC_H_
 >> +
 >> +#define HZ 100
 >> +
 >> +#define READ 0
 >> +#define WRITE 1
 >> +
 >> +static int ata_id_has_hipm(const u16 *id)
 >> +{
 >> +	u16 val = id[76];
 >> +
 >> +	if (val == 0 || val == 0xffff)
 >> +		return -1;
 >> +
 >> +	return val & (1 << 9);
 >> +}
 >
 >Don't add code to header. Only inline functions should be added here. So
 >either add "inline" or move it to a ".c" file.

I corrected.


 >> u-boot-2009.03/include/configs/canyonlands.h	2009-03-22 06:04:41.000000000
 >> +0900 +++ u-boot-2009.03-sata/include/configs/canyonlands.h	2009-03-25
 >> 17:31:40.000000000 +0900 @@ -34,6 +34,7 @@
 >>   #ifdef CONFIG_CANYONLANDS
 >>   #define CONFIG_460EX		1	/* Specific PPC460EX		*/
 >>   #define CONFIG_HOSTNAME		canyonlands
 >> +#define CONFIG_SATA_DWC			/* PPC460EX SATA support	*/
 >
 >Not sure if we really should enable this per default on the Canyonlands
 >platform. What's the size impact of this SATA support?

I excluded the above patch.

------------------------------------------
The confirmed patch is sent again.

This patch adds a SATA harddisk driver for the canyonlands.
Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>
---

[patch]
diff -purN u-boot-2009.03/common/cmd_scsi.c u-boot-2009.03-sata/common/cmd_scsi.c
--- u-boot-2009.03/common/cmd_scsi.c	2009-03-22 06:04:41.000000000 +0900
+++ u-boot-2009.03-sata/common/cmd_scsi.c	2009-03-25 18:53:29.000000000 +0900
@@ -47,8 +47,10 @@
  #define SCSI_DEV_ID  0x5288

  #else
+#ifndef CONFIG_SATA_DWC
  #error no scsi device defined
  #endif
+#endif


  static ccb tempccb;	/* temporary scsi command buffer */
@@ -179,6 +181,7 @@ void scsi_init(void)
  {
  	int busdevfunc;

+#ifndef CONFIG_SATA_DWC
  	busdevfunc=pci_find_device(SCSI_VEND_ID,SCSI_DEV_ID,0); /* get PCI Device ID */
  	if(busdevfunc==-1) {
  		printf("Error SCSI Controller (%04X,%04X) not found\n",SCSI_VEND_ID,SCSI_DEV_ID);
@@ -189,7 +192,13 @@ void scsi_init(void)
  		printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",SCSI_VEND_ID,SCSI_DEV_ID,(busdevfunc>>16)&0xFF,(busdevfunc>>11)&0x1F,(busdevfunc>>8)&0x7);
  	}
  #endif
+#endif
+#ifdef CONFIG_SATA_DWC
+	sata_dwc_probe();
+#endif
+#ifndef CONFIG_SATA_DWC
  	scsi_low_level_init(busdevfunc);
+#endif
  	scsi_scan(1);
  }

@@ -444,8 +453,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag,
  /****************************************************************************************
   * scsi_read
   */
-
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SCSI_MAX_READ_BLK 0xFF
+#else
  #define SCSI_MAX_READ_BLK 0xFFFF /* almost the maximum amount of the scsi_ext command.. */
+#endif

  ulong scsi_read(int device, ulong blknr, ulong blkcnt, void *buffer)
  {
diff -purN u-boot-2009.03/drivers/block/Makefile u-boot-2009.03-sata/drivers/block/Makefile
--- u-boot-2009.03/drivers/block/Makefile	2009-03-22 06:04:41.000000000 +0900
+++ u-boot-2009.03-sata/drivers/block/Makefile	2009-03-23 19:22:31.000000000 +0900
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil
  COBJS-$(CONFIG_IDE_SIL680) += sil680.o
  COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
  COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

  COBJS	:= $(COBJS-y)
  SRCS	:= $(COBJS:.o=.c)
diff -purN u-boot-2009.03/drivers/block/sata_dwc.c u-boot-2009.03-sata/drivers/block/sata_dwc.c
--- u-boot-2009.03/drivers/block/sata_dwc.c	1970-01-01 09:00:00.000000000 +0900
+++ u-boot-2009.03-sata/drivers/block/sata_dwc.c	2009-03-26 18:39:31.000000000 +0900
@@ -0,0 +1,2163 @@
+/*
+ * sata_dwc.c
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU
+ * General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 03-26-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <scsi.h>
+#include <ata.h>
+#include <linux/ctype.h>
+
+/* sata_dwc.h */
+#include "sata_dwc.h"
+
+/* SATA DMA driver Globals */
+#define DMA_NUM_CHANS			1
+#define DMA_NUM_CHAN_REGS		8
+
+/* SATA DMA Register definitions */
+#define AHB_DMA_BRST_DFLT		16	/* 4 data items burst length */
+
+struct dmareg {
+	u32 low;		/* Low bits 0-31 */
+	u32 high;		/* High bits 32-63 */
+};
+
+/* DMA Per Channel registers */
+struct dma_chan_regs {
+	struct dmareg sar;	/* Source Address */
+	struct dmareg dar;	/* Destination address */
+	struct dmareg llp;	/* Linked List Pointer */
+	struct dmareg ctl;	/* Control */
+	struct dmareg sstat;	/* Source Status not implemented in core */
+	struct dmareg dstat;	/* Destination Status not implemented in core */
+	struct dmareg sstatar;	/* Source Status Address not impl in core */
+	struct dmareg dstatar;	/* Destination Status Address not implemented */
+	struct dmareg cfg;	/* Config */
+	struct dmareg sgr;	/* Source Gather */
+	struct dmareg dsr;	/* Destination Scatter */
+};
+
+/* Generic Interrupt Registers */
+struct dma_interrupt_regs {
+	struct dmareg tfr;	/* Transfer Interrupt */
+	struct dmareg block;	/* Block Interrupt */
+	struct dmareg srctran;	/* Source Transfer Interrupt */
+	struct dmareg dsttran;	/* Dest Transfer Interrupt */
+	struct dmareg error;	/* Error */
+};
+
+struct ahb_dma_regs {
+	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];
+	struct dma_interrupt_regs	interrupt_raw;		/* Raw Interrupt */
+	struct dma_interrupt_regs	interrupt_status;	/* Interrupt Status */
+	struct dma_interrupt_regs	interrupt_mask;		/* Interrupt Mask */
+	struct dma_interrupt_regs	interrupt_clear;	/* Interrupt Clear */
+	struct dmareg			statusInt;		/* Interrupt combined */
+	struct dmareg			rq_srcreg;		/* Src Trans Req */
+	struct dmareg			rq_dstreg;		/* Dst Trans Req */
+	struct dmareg			rq_sgl_srcreg;		/* Sngl Src Trans Req */
+	struct dmareg			rq_sgl_dstreg;		/* Sngl Dst Trans Req */
+	struct dmareg			rq_lst_srcreg;		/* Last Src Trans Req */
+	struct dmareg			rq_lst_dstreg;		/* Last Dst Trans Req */
+	struct dmareg			dma_cfg;		/* DMA Config */
+	struct dmareg			dma_chan_en;		/* DMA Channel Enable */
+	struct dmareg			dma_id;			/* DMA ID */
+	struct dmareg			dma_test;		/* DMA Test */
+	struct dmareg			res1;			/* reserved */
+	struct dmareg			res2;			/* reserved */
+	/* DMA Comp Params
+	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
+	 * Param 4 = dma_param[2] ...
+	 */
+	struct dmareg			dma_params[6];
+};
+
+/* DMA Register Operation Bits */
+#define DMA_EN			0x00000001		/* Enable AHB DMA */
+#define DMA_CHANNEL(ch)		(0x00000001 << (ch))	/* Select channel */
+#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |	\
+				((0x000000001 << (ch)) << 8))	/* Enable channel */
+#define DMA_DISABLE_CHAN(ch)	(0x00000000 | 	\
+				((0x000000001 << (ch)) << 8))	/* Disable channel */
+
+#define SATA_DWC_MAX_PORTS	1
+#define SATA_DWC_SCR_OFFSET	0x24
+#define SATA_DWC_REG_OFFSET	0x64
+
+/* DWC SATA Registers */
+struct sata_dwc_regs {
+	u32 fptagr;		/* 1st party DMA tag */
+	u32 fpbor;		/* 1st party DMA buffer offset */
+	u32 fptcr;		/* 1st party DMA Xfr count */
+	u32 dmacr;		/* DMA Control */
+	u32 dbtsr;		/* DMA Burst Transac size */
+	u32 intpr;		/* Interrupt Pending */
+	u32 intmr;		/* Interrupt Mask */
+	u32 errmr;		/* Error Mask */
+	u32 llcr;		/* Link Layer Control */
+	u32 phycr;		/* PHY Control */
+	u32 physr;		/* PHY Status */
+	u32 rxbistpd;		/* Recvd BIST pattern def register */
+	u32 rxbistpd1;		/* Recvd BIST data dword1 */
+	u32 rxbistpd2;		/* Recvd BIST pattern data dword2 */
+	u32 txbistpd;		/* Trans BIST pattern def register */
+	u32 txbistpd1;		/* Trans BIST data dword1 */
+	u32 txbistpd2;		/* Trans BIST data dword2 */
+	u32 bistcr;		/* BIST Control Register */
+	u32 bistfctr;		/* BIST FIS Count Register */
+	u32 bistsr;		/* BIST Status Register */
+	u32 bistdecr;		/* BIST Dword Error count register */
+	u32 res[15];		/* Reserved locations */
+	u32 testr;		/* Test Register */
+	u32 versionr;		/* Version Register */
+	u32 idr;		/* ID Register */
+	u32 unimpl[192];	/* Unimplemented */
+	u32 dmadr[256];		/* FIFO Locations in DMA Mode */
+};
+
+/* DWC SATA Register Operations */
+#define SATA_DWC_TXFIFO_DEPTH		0x01FF
+#define SATA_DWC_RXFIFO_DEPTH		0x01FF
+
+#define SATA_DWC_DBTSR_MWR(size)	((size/4) & SATA_DWC_TXFIFO_DEPTH)
+#define SATA_DWC_DBTSR_MRD(size)	(((size/4) &	\
+					SATA_DWC_RXFIFO_DEPTH) << 16)
+#define SATA_DWC_INTPR_DMAT		0x00000001
+#define SATA_DWC_INTPR_NEWFP		0x00000002
+#define SATA_DWC_INTPR_PMABRT		0x00000004
+#define SATA_DWC_INTPR_ERR		0x00000008
+#define SATA_DWC_INTPR_NEWBIST		0x00000010
+#define SATA_DWC_INTPR_IPF		0x10000000
+#define SATA_DWC_INTMR_DMATM		0x00000001
+#define SATA_DWC_INTMR_NEWFPM		0x00000002
+#define SATA_DWC_INTMR_PMABRTM		0x00000004
+#define SATA_DWC_INTMR_ERRM		0x00000008
+#define SATA_DWC_INTMR_NEWBISTM		0x00000010
+
+#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
+#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
+
+#define SATA_DWC_QCMD_MAX	32
+
+/* This is all error bits, zero's are reserved fields. */
+#define SATA_DWC_SERROR_ERR_BITS	0x0FFF0F03
+
+/*
+ * Commonly used DWC SATA driver Macros
+ */
+#define HSDEVP_FROM_AP(ap)	(struct sata_dwc_device_port*)	\
+				(ap)->private_data
+
+struct sata_dwc_device {
+	struct device		*dev;		/* generic device struct */
+	struct ata_probe_ent    *pe;		/* ptr to probe-ent */
+	struct ata_host		*host;
+	u8			*reg_base;
+	struct sata_dwc_regs	*sata_dwc_regs;	/* DW Synopsys SATA specific */
+	int			irq_dma;
+};
+
+struct sata_dwc_device_port {
+	struct sata_dwc_device	*hsdev;
+	int			cmd_issued[SATA_DWC_QCMD_MAX];
+	u32			dma_chan[SATA_DWC_QCMD_MAX];
+	int			dma_pending[SATA_DWC_QCMD_MAX];
+};
+
+enum {
+	SATA_DWC_CMD_ISSUED_NOT		= 0,
+	SATA_DWC_CMD_ISSUED_PEND	= 1,
+	SATA_DWC_CMD_ISSUED_EXEC	= 2,
+	SATA_DWC_CMD_ISSUED_NODATA	= 3,
+
+	SATA_DWC_DMA_PENDING_NONE	= 0,
+	SATA_DWC_DMA_PENDING_TX		= 1,
+	SATA_DWC_DMA_PENDING_RX		= 2,
+};
+
+/* delay Macros */
+#define msleep(a)	udelay(a * 1000)
+#define ssleep(a)	msleep(a * 1000)
+
+static int ata_probe_timeout = (ATA_TMOUT_INTERNAL / 100);
+
+enum sata_dev_state {
+	SATA_INIT = 0,
+	SATA_READY = 1,
+	SATA_NODEVICE = 2,
+	SATA_ERROR = 3,
+};
+enum sata_dev_state dev_state = SATA_INIT;
+
+/*
+ * Globals
+ */
+static struct ahb_dma_regs		*sata_dma_regs = 0;
+static struct ata_host			*phost;
+static struct ata_port			ap;
+static struct ata_port			*pap = &ap;
+static struct ata_device		ata_device;
+static struct sata_dwc_device_port	dwc_devp;
+
+static void	*scr_addr_sstatus;
+static char	temp_data_buf[512];
+static u32	temp_n_block = 0;
+
+/*
+ * Prototype
+ */
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout);
+unsigned int ata_dev_set_feature(struct ata_device *dev,
+			u8 enable,u8 feature);
+unsigned int ata_dev_init_params(struct ata_device *dev,
+			u16 heads, u16 sectors);
+void clear_serror(void);
+u8 ata_irq_on(struct ata_port *ap);
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+			unsigned int tag);
+int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq);
+void ata_tf_to_host(struct ata_port *ap,const struct ata_taskfile *tf);
+unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc);
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
+unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+u8 ata_check_altstatus(struct ata_port *ap);
+static u8 ata_check_status(struct ata_port *ap);
+void ata_dev_select(struct ata_port *ap, unsigned int device,
+			unsigned int wait, unsigned int can_sleep);
+void ata_qc_issue(struct ata_queued_cmd *qc);
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
+int ata_dev_read_sectors(ccb *pccb);
+void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+void ata_qc_complete(struct ata_queued_cmd *qc);
+void __ata_qc_complete(struct ata_queued_cmd *qc);
+void fill_result_tf(struct ata_queued_cmd *qc);
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+void ata_mmio_data_xfer(struct ata_device *dev,
+			unsigned char *buf,unsigned int buflen);
+void ata_pio_task(struct ata_port *arg_ap);
+void __ata_port_freeze(struct ata_port *ap);
+int ata_port_freeze(struct ata_port *ap);
+void ata_qc_free(struct ata_queued_cmd *qc);
+void ata_pio_sectors(struct ata_queued_cmd *qc);
+void ata_pio_sector(struct ata_queued_cmd *qc);
+void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay);
+void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq);
+int sata_dwc_softreset(struct ata_port *ap);
+void sata_dwc_probe(void);
+
+static int ata_id_has_hipm(const u16 *id)
+{
+	u16 val = id[76];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 9);
+}
+
+static int ata_id_has_dipm(const u16 *id)
+{
+	u16 val = id[78];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 3);
+}
+
+u8 ata_check_altstatus(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.altstatus_addr);
+	return val;
+}
+
+int check_sata_dev_state(void)
+{
+	static ccb tempccb;		/* temporary scsi command buffer */
+	ccb *pccb = (ccb *)&tempccb;
+	int ret = 0;
+	int i = 0;
+
+	while (1) {
+		udelay (10000);		/* 10 ms */
+
+	        pccb->cmd[0] = SCSI_READ10;
+	        pccb->cmd[1] = 0;
+	        pccb->cmd[2] = 0;
+	        pccb->cmd[3] = 0;
+	        pccb->cmd[4] = 0;
+	        pccb->cmd[5] = 0;
+	        pccb->cmd[6] = 0;
+	        pccb->cmd[7] = 0;
+	        pccb->cmd[8] = 1;
+	        pccb->cmdlen = 10;
+		pccb->pdata = &temp_data_buf[0];	/* dummy */
+		pccb->datalen = 512;
+
+		/* Send Read Command */
+		ret =  ata_dev_read_sectors(pccb);
+
+		/* result TRUE => break */
+		if (ret == 0)
+			break;
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+			dev_state = SATA_NODEVICE;	/* set device status flag */
+			return FALSE;
+		}
+
+		if ((i >= 100) && ((i%100)==0))
+			printf(".");
+	}
+
+	/* Set device status flag */
+	dev_state = SATA_READY;
+
+	return TRUE;
+}
+
+void ata_id_string(const u16 *id, unsigned char *s,
+		unsigned int ofs, unsigned int len)
+{
+	unsigned int c;
+
+	while (len > 0) {
+		c = id[ofs] >> 8;
+		*s = c;
+		s++;
+
+		c = id[ofs] & 0xff;
+		*s = c;
+		s++;
+
+		ofs++;
+		len -= 2;
+	}
+}
+
+static int waiting_for_reg_state(volatile u8 *offset,
+				int timeout_msec,
+				u32 sign)
+{
+	int i;
+	u32 status;
+
+	for (i = 0; i < timeout_msec; i++) {
+		status = readl(offset);
+		if ((status & sign) != 0)
+			break;
+		msleep(1);
+	}
+
+	return (i < timeout_msec) ? 0 : -1;
+}
+
+static inline u32 qcmd_tag_to_mask(u8 tag)
+{
+	return (0x00000001 << (tag & 0x1f));
+}
+
+static u8 ata_check_status(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.status_addr);
+	return val;
+}
+
+static u8 ata_busy_wait(struct ata_port *ap,
+		unsigned int bits,unsigned int max)
+{
+	u8 status;
+
+	do {
+		udelay(10);
+		status = ata_check_status(ap);
+		max--;
+	} while (status != 0xff && (status & bits) && (max > 0));
+
+	return status;
+}
+
+static u8 ata_wait_idle(struct ata_port *ap)
+{
+	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	return status;
+}
+
+static int sata_dwc_scsiop_inq(ccb *pccb)
+{
+	struct ata_device *ata_dev = &ata_device;
+	u16 *id;
+
+	/* Set IDENTIFY Data */
+	id = ata_dev->id;
+
+	/* make INQUIRY header */
+	u8 hdr[] = {
+		0,
+		0,
+		0x5,	/* claim SPC-3 version compatibility */
+		2,
+		95 - 4
+	};
+
+	/* set scsi removeable (RMB) bit per ata bit */
+	if (ata_id_removeable(id))
+		hdr[1] |= (1 << 7);
+
+	memcpy(pccb->pdata, hdr, sizeof(hdr));
+
+	if (pccb->datalen > 35) {
+		memcpy(&pccb->pdata[8], "ATA     ", 8);
+		ata_id_string(id, &pccb->pdata[16], ATA_ID_PROD, 16);
+		ata_id_string(id, &pccb->pdata[32], ATA_ID_FW_REV, 4);
+		if (pccb->pdata[32] == 0 || pccb->pdata[32] == ' ')
+			memcpy(&pccb->pdata[32], "n/a ", 4);
+	}
+
+	if (pccb->datalen > 63) {
+		const u8 versions[] = {
+			0x60,	/* SAM-3 (no version claimed) */
+			0x03,
+			0x20,	/* SBC-2 (no version claimed) */
+			0x02,
+			0x60	/* SPC-3 (no version claimed) */
+		};
+		memcpy(pccb->pdata + 59, versions, sizeof(versions));
+	}
+
+	return 0;
+}
+
+#define ATA_SCSI_PDATA_SET(idx, val) do { \
+	if ((idx) < pccb->datalen) pccb->pdata[(idx)] = (u8)(val); \
+	} while (0)
+
+static int sata_dwc_scsiop_read_cap(ccb *pccb)
+{
+	struct ata_device *ata_dev = &ata_device;
+	u32 last_lba;
+	last_lba = ata_dev->n_sectors;	/* LBA of the last block */
+
+	if (pccb->cmd[0] == SCSI_RD_CAPAC) {
+		if (last_lba >= 0xffffffffULL)
+			last_lba = 0xffffffff;
+
+		/* sector count, 32-bit */
+		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 3));
+		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 2));
+		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 1));
+		ATA_SCSI_PDATA_SET(3, last_lba);
+
+		/* buffer clear */
+		ATA_SCSI_PDATA_SET(4, 0);
+		ATA_SCSI_PDATA_SET(5, 0);
+
+		/* sector size */
+		ATA_SCSI_PDATA_SET(6, ATA_SECT_SIZE >> 8);
+		ATA_SCSI_PDATA_SET(7, ATA_SECT_SIZE & 0xff);
+
+	} else {
+		/* sector count, 64-bit */
+		ATA_SCSI_PDATA_SET(0, last_lba >> (8 * 7));
+		ATA_SCSI_PDATA_SET(1, last_lba >> (8 * 6));
+		ATA_SCSI_PDATA_SET(2, last_lba >> (8 * 5));
+		ATA_SCSI_PDATA_SET(3, last_lba >> (8 * 4));
+		ATA_SCSI_PDATA_SET(4, last_lba >> (8 * 3));
+		ATA_SCSI_PDATA_SET(5, last_lba >> (8 * 2));
+		ATA_SCSI_PDATA_SET(6, last_lba >> (8 * 1));
+		ATA_SCSI_PDATA_SET(7, last_lba);
+
+		/* sector size */
+		ATA_SCSI_PDATA_SET(10, ATA_SECT_SIZE >> 8);
+		ATA_SCSI_PDATA_SET(11, ATA_SECT_SIZE & 0xff);
+	}
+
+	return 0;
+}
+
+/*
+ * SCSI TEST UNIT READY command operation.
+ *      No operation.  Simply returns success to caller, to indicate
+ *      that the caller should successfully complete this SCSI command.
+ */
+static int sata_dwc_scsiop_test_unit_ready(ccb *pccb)
+{
+	/* No operation  */
+	return 0;
+}
+
+int scsi_exec(ccb *pccb)
+{
+	int ret;
+
+	/* check device status */
+	if (dev_state != SATA_READY)
+		return FALSE;
+
+	switch (pccb->cmd[0]) {
+	case SCSI_READ10:
+		ret =  ata_dev_read_sectors(pccb);
+		break;
+	case SCSI_RD_CAPAC:
+		ret = sata_dwc_scsiop_read_cap(pccb);
+		break;
+	case SCSI_TST_U_RDY:
+		ret = sata_dwc_scsiop_test_unit_ready(pccb);
+		break;
+	case SCSI_INQUIRY:
+		ret = sata_dwc_scsiop_inq(pccb);
+		break;
+	default:
+		printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
+		return FALSE;
+	}
+
+	if (ret) {
+		debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static const struct ata_port_info sata_dwc_port_info[] = {
+	{
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
+				ATA_FLAG_SRST | ATA_FLAG_NCQ,
+		.pio_mask	= 0x1f,	/* pio 0-4 */
+		.mwdma_mask	= 0x07,
+		.udma_mask	= 0x7f,
+	},
+};
+
+int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id)
+{
+	struct ata_port *ap = pap;
+	unsigned int class = *p_class;
+	struct ata_taskfile tf;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1, tried_spinup = 0;
+	u8 status;
+	int rc;
+
+	/* cheack BSY = 0 */
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+        ata_dev_select(ap, dev->devno, 1, 1);	/* select device 0/1 */
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+	tf.ctl = ap->ctl;	/* 0x08 */
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_ID_ATA;
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+	/* Device presence detection is unreliable on some
+	 * controllers.  Always poll IDENTIFY if available.
+	 */
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	temp_n_block = 1;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+					sizeof(id[0]) * ATA_ID_WORDS, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	unsigned int id_cnt;
+
+	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
+		id[id_cnt] = le16_to_cpu(id[id_cnt]);
+
+
+	/* sanity check */
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	if (class == ATA_DEV_ATA) {
+		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
+			goto err_out;
+	} else {
+		if (ata_id_is_ata(id))
+			goto err_out;
+	}
+	if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+		tried_spinup = 1;
+		/*
+		 * Drive powered-up in standby mode, and requires a specific
+		 * SET_FEATURES spin-up subcommand before it will accept
+		 * anything other than the original IDENTIFY command.
+		 */
+		err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+		if (err_mask && id[2] != 0x738c) {
+			rc = -EIO;
+			reason = "SPINUP failed";
+			goto err_out;
+		}
+		/*
+		 * If the drive initially returned incomplete IDENTIFY info,
+		 * we now must reissue the IDENTIFY command.
+		 */
+		if (id[2] == 0x37c8)
+			goto retry;
+	}
+
+	if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
+		/*
+		 * The exact sequence expected by certain pre-ATA4 drives is:
+		 * SRST RESET
+		 * IDENTIFY (optional in early ATA)
+		 * INITIALIZE DEVICE PARAMETERS (later IDE and ATA)
+		 * anything else..
+		 * Some drives were very specific about that exact sequence.
+		 *
+		 * Note that ATA4 says lba is mandatory so the second check
+		 * shoud never trigger.
+		 */
+		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+			err_mask = ata_dev_init_params(dev, id[3], id[6]);
+			if (err_mask) {
+				rc = -EIO;
+				reason = "INIT_DEV_PARAMS failed";
+				goto err_out;
+			}
+
+			/* current CHS translation info (id[53-58]) might be
+			 * changed. reread the identify device info.
+			 */
+			flags &= ~ATA_READID_POSTRESET;
+			goto retry;
+		}
+        }
+
+	*p_class = class;
+	return 0;
+
+err_out:
+	return rc;
+}
+
+void ata_dev_select(struct ata_port *ap, unsigned int device,
+		unsigned int wait, unsigned int can_sleep)
+{
+	if (wait)
+		ata_wait_idle(ap);
+
+	ata_std_dev_select(ap, device);
+
+	if (wait)
+		ata_wait_idle(ap);
+}
+
+void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+{
+	u8 tmp;
+
+	if (device == 0) {
+		tmp = ATA_DEVICE_OBS;
+	} else {
+		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+	}
+
+	writeb(tmp, ap->ioaddr.device_addr);
+
+	/* needed; also flushes, for mmio */
+	readb(ap->ioaddr.altstatus_addr);
+
+	/* need delay 400nsec over */
+	udelay(1);
+}
+
+void ata_qc_reinit(struct ata_queued_cmd *qc)
+{
+	qc->dma_dir = DMA_NONE;
+	qc->flags = 0;
+	qc->nbytes = qc->extrabytes = qc->curbytes = 0;
+	qc->n_elem = 0;
+	qc->err_mask = 0;
+	qc->sect_size = ATA_SECT_SIZE;
+	qc->nbytes = ATA_SECT_SIZE * temp_n_block;
+
+	memset(&qc->tf, 0, sizeof(qc->tf));
+	qc->tf.ctl = 0;
+	qc->tf.device = ATA_DEVICE_OBS;
+
+	/* init result_tf such that it indicates normal completion */
+	qc->result_tf.command = ATA_DRDY;
+	qc->result_tf.feature = 0;
+}
+
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout)
+{
+	struct ata_link *link = dev->link;
+	struct ata_port *ap = pap;
+	struct ata_queued_cmd *qc;
+	unsigned int tag, preempted_tag;
+	u32 preempted_sactive, preempted_qc_active;
+	int preempted_nr_active_links;
+	unsigned int err_mask;
+	int rc = 0;
+	u8 status;
+
+	/* cheack BSY = 0 */
+	status = ata_busy_wait(ap, ATA_BUSY, 300000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	/* no internal command while frozen */
+	if (ap->pflags & ATA_PFLAG_FROZEN)
+		return AC_ERR_SYSTEM;
+
+	tag = ATA_TAG_INTERNAL;
+
+	if (test_and_set_bit(tag, &ap->qc_allocated))
+		printf("test_and_set_bit failed\n");
+
+	qc = __ata_qc_from_tag(ap, tag);
+	qc->tag = tag;
+	qc->ap = ap;
+	qc->dev = dev;
+
+	ata_qc_reinit(qc);
+
+	preempted_tag = link->active_tag;
+	preempted_sactive = link->sactive;
+	preempted_qc_active = ap->qc_active;
+	preempted_nr_active_links = ap->nr_active_links;
+	link->active_tag = ATA_TAG_POISON;
+	link->sactive = 0;
+	ap->qc_active = 0;
+	ap->nr_active_links = 0;
+
+	/* prepare & issue qc */
+	qc->tf = *tf;
+	if (cdb)
+		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+	qc->dma_dir = dma_dir;
+	qc->private_data = 0;
+
+	ata_qc_issue(qc);
+
+	if (!timeout)
+		timeout = ata_probe_timeout * 1000 / HZ;
+
+	/* cheack BSY = 0 */
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		printf("altstatus = 0x%x.\n",status);
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	if (waiting_for_reg_state(ap->ioaddr.altstatus_addr,1000,0x8)) {
+		printf("DRQ = 1 check timeout 1000msec\n");
+		u8 status = 0;
+		u8 errorStatus = 0;
+
+		status = readb( ap->ioaddr.altstatus_addr);
+		if ((status&0x01) != 0) {
+			errorStatus = readb( ap->ioaddr.feature_addr);
+			printf("ERROR STATUS = 0x%x\n",errorStatus);
+		}
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	status = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	ata_pio_task(ap);
+
+	if (!rc) {
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			qc->err_mask |= AC_ERR_TIMEOUT;
+			ata_port_freeze(ap);
+		}
+	}
+
+	/* perform minimal error analysis */
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (qc->result_tf.command & (ATA_ERR | ATA_DF))
+			qc->err_mask |= AC_ERR_DEV;
+
+		if (!qc->err_mask)
+			qc->err_mask |= AC_ERR_OTHER;
+
+		if (qc->err_mask & ~AC_ERR_OTHER)
+			qc->err_mask &= ~AC_ERR_OTHER;
+	}
+
+	/* finish up */
+	*tf = qc->result_tf;
+	err_mask = qc->err_mask;
+	ata_qc_free(qc);
+	link->active_tag = preempted_tag;
+	link->sactive = preempted_sactive;
+	ap->qc_active = preempted_qc_active;
+	ap->nr_active_links = preempted_nr_active_links;
+
+	if (ap->flags & ATA_FLAG_DISABLED) {
+		err_mask |= AC_ERR_SYSTEM;
+		ap->flags &= ~ATA_FLAG_DISABLED;
+	}
+
+	return err_mask;
+}
+
+unsigned int ata_dev_set_feature(struct ata_device *dev,
+				u8 enable, u8 feature)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	/* set up set-features taskfile */
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = enable;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = feature;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	return err_mask;
+}
+
+unsigned int ata_dev_init_params(struct ata_device *dev,
+				u16 heads, u16 sectors)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	/* Number of sectors per track 1-255. Number of heads 1-16 */
+	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+		return AC_ERR_INVALID;
+
+	/* set up init dev params taskfile */
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
+		err_mask = 0;
+
+	return err_mask;
+}
+
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+					unsigned int tag)
+{
+	if (tag < ATA_MAX_QUEUE)
+		return &ap->qcmd[tag];
+	return NULL;
+}
+
+void ata_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+	u8 prot = qc->tf.protocol;
+
+	if (ata_is_ncq(prot)) {
+		if (!link->sactive)
+			ap->nr_active_links++;
+		link->sactive |= 1 << qc->tag;
+	} else {
+		ap->nr_active_links++;
+		link->active_tag = qc->tag;
+	}
+
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+	ap->qc_active |= 1 << qc->tag;
+
+	if (qc->dev->flags & ATA_DFLAG_SLEEPING) {
+		msleep(1);	/* delay 1msec */
+		return;
+	}
+
+	qc->err_mask |= sata_dwc_qc_issue(qc);
+	if (qc->err_mask)
+		goto err;
+
+	return;
+err:
+	ata_qc_complete(qc);
+}
+
+unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
+{
+	ata_qc_issue_prot(qc);
+	return 0;
+}
+
+void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	/* set command register */
+	writeb(tf->command, ap->ioaddr.command_addr);
+
+	/* read alternative status register */
+	readb(ap->ioaddr.altstatus_addr);
+
+	/* delay 400nsec over */
+	udelay(1);
+}
+
+void __ata_port_freeze(struct ata_port *ap)
+{
+	printf("set port freeze.\n");
+	ap->pflags |= ATA_PFLAG_FROZEN;
+}
+
+int ata_port_freeze(struct ata_port *ap)
+{
+	__ata_port_freeze(ap);
+	return 0;
+}
+
+unsigned int ata_tag_internal(unsigned int tag)
+{
+	return tag == ATA_MAX_QUEUE - 1;
+}
+
+void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_device *dev = qc->dev;
+	if (qc->err_mask)
+		qc->flags |= ATA_QCFLAG_FAILED;
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (!ata_tag_internal(qc->tag)) {
+			/* always fill result TF for failed qc */
+			fill_result_tf(qc);
+			return;
+		}
+	}
+	/* read result TF if requested */
+	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+		fill_result_tf(qc);
+
+	/* Some commands need post-processing after successful
+	 * completion.
+	 */
+	switch (qc->tf.command) {
+	case ATA_CMD_SET_FEATURES:
+		if (qc->tf.feature != SETFEATURES_WC_ON &&
+				qc->tf.feature != SETFEATURES_WC_OFF)
+			break;
+	case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+	case ATA_CMD_SET_MULTI: /* multi_count changed */
+		break;
+
+	case ATA_CMD_SLEEP:
+		dev->flags |= ATA_DFLAG_SLEEPING;
+		break;
+	}
+
+	__ata_qc_complete(qc);
+}
+
+void __ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+
+	/* command should be marked inactive atomically with qc completion */
+	link->active_tag = ATA_TAG_POISON;
+	ap->nr_active_links--;
+
+	/* clear exclusive status */
+	if (qc->flags & ATA_QCFLAG_CLEAR_EXCL && ap->excl_link == link)
+		ap->excl_link = NULL;
+
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	ap->qc_active &= ~(1 << qc->tag);
+}
+
+void fill_result_tf(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	qc->result_tf.flags = qc->tf.flags;
+	ata_tf_read(ap, &qc->result_tf);
+}
+
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->command = ata_check_status(ap);
+	tf->feature = readb(ioaddr->error_addr);
+	tf->nsect = readb(ioaddr->nsect_addr);
+	tf->lbal = readb(ioaddr->lbal_addr);
+	tf->lbam = readb(ioaddr->lbam_addr);
+	tf->lbah = readb(ioaddr->lbah_addr);
+	tf->device = readb(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		if (ioaddr->ctl_addr) {
+			writeb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+
+			tf->hob_feature = readb(ioaddr->error_addr);
+			tf->hob_nsect = readb(ioaddr->nsect_addr);
+			tf->hob_lbal = readb(ioaddr->lbal_addr);
+			tf->hob_lbam = readb(ioaddr->lbam_addr);
+			tf->hob_lbah = readb(ioaddr->lbah_addr);
+
+			writeb(tf->ctl, ioaddr->ctl_addr);
+			ap->last_ctl = tf->ctl;
+		} else {
+			printf("sata_dwc warnning register read.\n");
+		}
+	}
+}
+
+void ata_qc_free(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int tag;
+	qc->flags = 0;
+	tag = qc->tag;
+	if (tag < ATA_MAX_QUEUE) {
+		qc->tag = ATA_TAG_POISON;
+		clear_bit(tag, &ap->qc_allocated);
+	}
+}
+
+void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		if (ioaddr->ctl_addr)
+			writeb(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writeb(tf->hob_feature, ioaddr->feature_addr);
+		writeb(tf->hob_nsect, ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, ioaddr->lbah_addr);
+	}
+
+	if (is_addr) {
+		writeb(tf->feature, ioaddr->feature_addr);
+		writeb(tf->nsect, ioaddr->nsect_addr);
+		writeb(tf->lbal, ioaddr->lbal_addr);
+		writeb(tf->lbam, ioaddr->lbam_addr);
+		writeb(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE)
+		writeb(tf->device, ioaddr->device_addr);
+
+	ata_wait_idle(ap);
+}
+
+void sata_dwc_exec_command_by_tag(struct ata_port *ap,
+				struct ata_taskfile *tf,
+				u8 tag, u32 cmd_issued)
+{
+	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+	hsdevp->cmd_issued[tag] = cmd_issued;
+
+	/* Clear SError before executing a new command.*/
+	clear_serror();
+	ata_exec_command(ap, tf);
+}
+
+void clear_serror(void)
+{
+	u32 temp;
+	temp = in_le32((void __iomem *)scr_addr_sstatus + 4);
+
+	out_le32((void __iomem *)scr_addr_sstatus + 4, temp);
+}
+
+void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
+{
+	ata_tf_load(ap, tf);
+	ata_exec_command(ap, tf);
+}
+
+unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+		switch (qc->tf.protocol) {
+		case ATA_PROT_PIO:
+		case ATA_PROT_NODATA:
+		case ATAPI_PROT_PIO:
+		case ATAPI_PROT_NODATA:
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* select the device */
+	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+	/* start the command */
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+		if (qc->tf.flags & ATA_TFLAG_POLLING) {
+			qc->tf.ctl |= ATA_NIEN;
+		}
+
+		ata_tf_to_host(ap, &qc->tf);
+
+		/* PIO data in protocol */
+		ap->hsm_task_state = HSM_ST;
+
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_pio_queue_task(ap, qc, 0);
+
+		break;
+
+	default:
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+void ata_pio_task(struct ata_port *arg_ap)
+{
+	struct ata_port *ap = arg_ap;
+	struct ata_queued_cmd *qc = ap->port_task_data;
+	u8 status;
+	int poll_next;
+
+fsm_start:
+	/*
+	 * This is purely heuristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, queue delayed work.
+	 */
+	status = ata_busy_wait(ap, ATA_BUSY, 5);
+	if (status & ATA_BUSY) {
+		msleep(2);
+		status = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (status & ATA_BUSY) {
+			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+			return;
+		}
+	}
+
+	/* move the HSM */
+	poll_next = ata_hsm_move(ap, qc, status, 1);
+
+	/* another command or interrupt handler
+	 * may be running at this point.
+	 */
+	if (poll_next)
+		goto fsm_start;
+}
+
+void ata_pio_queue_task(struct ata_port *ap, void *data,unsigned long delay)
+{
+	ap->port_task_data = data;
+}
+
+unsigned int ac_err_mask(u8 status)
+{
+	if (status & (ATA_BUSY | ATA_DRQ))
+		return AC_ERR_HSM;
+	if (status & (ATA_ERR | ATA_DF))
+		return AC_ERR_DEV;
+	return 0;
+}
+
+unsigned int __ac_err_mask(u8 status)
+{
+	unsigned int mask = ac_err_mask(status);
+	if (mask == 0)
+		return AC_ERR_OTHER;
+	return mask;
+}
+
+int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq)
+{
+	int poll_next;
+
+fsm_start:
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+		/* check device status */
+		if ((status & ATA_DRQ) == 0) {
+			/* handle BSY=0, DRQ=0 as error */
+			if (status & (ATA_ERR | ATA_DF)) {
+				/* device stops HSM for abort/error */
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this */
+				qc->err_mask |= AC_ERR_HSM;
+			}
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Device should not ask for data transfer (DRQ=1)
+		 * when it finds something wrong.
+		 * We ignore DRQ here and stop the HSM by
+		 * changing hsm_task_state to HSM_ST_ERR and
+		 * let the EH abort the command or reset the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+				printf("DRQ=1 with device error, "
+					"dev_stat 0x%X\n", status);
+				qc->err_mask |= AC_ERR_HSM;
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+		}
+
+		if (qc->tf.protocol == ATA_PROT_PIO) {
+			/* PIO data out protocol.
+			 * send first data block.
+			 */
+			/* ata_pio_sectors() might change the state
+			 * to HSM_ST_LAST. so, the state is changed here
+			 * before ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST;
+			ata_pio_sectors(qc);
+		} else {
+			printf("protocol is not ATA_PROT_PIO \n");
+		}
+		break;
+
+	case HSM_ST:
+		/* complete command or read/write the data register */
+		/* ATA PIO protocol */
+		if ((status & ATA_DRQ) == 0) {
+			/* handle BSY=0, DRQ=0 as error */
+			if (status & (ATA_ERR | ATA_DF)) {
+				/* device stops HSM for abort/error */
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this.
+				 * Phantom devices also trigger this
+				 * condition.  Mark hint.
+				 */
+				qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT;
+			}
+
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+		/* For PIO reads, some devices may ask for
+		 * data transfer (DRQ=1) alone with ERR=1.
+		 * We respect DRQ here and transfer one
+		 * block of junk data before changing the
+		 * hsm_task_state to HSM_ST_ERR.
+		 *
+		 * For PIO writes, ERR=1 DRQ=1 doesn't make
+		 * sense since the data block has been
+		 * transferred to the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			/* data might be corrputed */
+			qc->err_mask |= AC_ERR_DEV;
+
+			if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+				ata_pio_sectors(qc);
+				status = ata_wait_idle(ap);
+			}
+
+			if (status & (ATA_BUSY | ATA_DRQ))
+				qc->err_mask |= AC_ERR_HSM;
+
+			/* ata_pio_sectors() might change the
+			 * state to HSM_ST_LAST. so, the state
+			 * is changed after ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ata_pio_sectors(qc);
+		if (ap->hsm_task_state == HSM_ST_LAST &&
+			(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+			/* all data read */
+			status = ata_wait_idle(ap);
+			goto fsm_start;
+		}
+
+		poll_next = 1;
+		break;
+
+	case HSM_ST_LAST:
+		if (!ata_ok(status)) {
+			qc->err_mask |= __ac_err_mask(status);
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* no more data to transfer */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		/* complete taskfile transaction */
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+
+	case HSM_ST_ERR:
+		/* make sure qc->err_mask is available to
+		 * know what's wrong and recover
+		 */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		/* complete taskfile transaction */
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+	default:
+		poll_next = 0;
+	}
+
+	return poll_next;
+}
+
+int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+	if (qc->tf.flags & ATA_TFLAG_POLLING)
+			return 1;
+
+	if (ap->hsm_task_state == HSM_ST_FIRST) {
+		if (ata_is_atapi(qc->tf.protocol) &&
+			!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+			return 1;
+	}
+
+	return 0;
+}
+
+void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap;
+	ap = pap;
+	qc->pdata = ap->pdata;
+
+	if (is_multi_taskfile(&qc->tf)) {
+		/* READ/WRITE MULTIPLE */
+		unsigned int nsect;
+
+		nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
+			qc->dev->multi_count);
+		while (nsect--)
+			ata_pio_sector(qc);
+	} else {
+		ata_pio_sector(qc);
+	}
+
+	readb(qc->ap->ioaddr.altstatus_addr);
+	udelay(1);
+}
+
+void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int offset;
+	unsigned char *buf;
+
+	if (qc->curbytes == qc->nbytes - qc->sect_size)
+		ap->hsm_task_state = HSM_ST_LAST;
+
+	offset = qc->curbytes;
+
+	/* check cmd and set buffer */
+	switch (qc->tf.command) {
+	case ATA_CMD_ID_ATA:		/* IDENTIFY */
+		buf = (unsigned char *)&ata_device.id[0];
+		break;
+	case ATA_CMD_PIO_READ_EXT:	/* READ SECTORS EX 0x24 */
+	case ATA_CMD_PIO_READ:		/* READ SECTORS 0x20 */
+		buf = qc->pdata + offset;
+		break;
+	default:
+		buf = &temp_data_buf[0];
+	}		
+
+	/* data xfer */
+	ata_mmio_data_xfer(qc->dev, buf, qc->sect_size);
+
+	qc->curbytes += qc->sect_size;
+
+}
+
+void ata_mmio_data_xfer(struct ata_device *dev, unsigned char *buf,
+				unsigned int buflen)
+{
+	struct ata_port *ap = pap;
+	void __iomem *data_addr = ap->ioaddr.data_addr;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *)buf;
+	unsigned int i = 0;
+
+	udelay(100);
+	/* Transfer */
+	for (i=0; i < words; i++)
+		buf16[i] = cpu_to_le16(readw(data_addr));
+
+	/* Transfer trailing 1 byte, if any. */
+	if (buflen & 0x01) {
+		__le16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		align_buf[0] = cpu_to_le16(readw(data_addr));
+		memcpy(trailing_buf, align_buf, 1);
+		words++;
+	}
+}
+
+void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (in_wq) {
+		/* EH might have kicked in while host lock is
+		 * released.
+		 */
+		qc = &ap->qcmd[qc->tag];
+		if (qc) {
+			if (!(qc->err_mask & AC_ERR_HSM)) {
+				ata_irq_on(ap);
+				ata_qc_complete(qc);
+			} else {
+				ata_port_freeze(ap);
+			}
+		}
+	} else {
+		if (!(qc->err_mask & AC_ERR_HSM)) {
+			ata_qc_complete(qc);
+		} else {
+			ata_port_freeze(ap);
+		}
+	}
+}
+
+u8 ata_irq_on(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 tmp;
+
+	ap->ctl &= ~ATA_NIEN;
+	ap->last_ctl = ap->ctl;
+
+	if (ioaddr->ctl_addr)
+		writeb(ap->ctl, ioaddr->ctl_addr);
+
+	tmp = ata_wait_idle(ap);
+
+	return tmp;
+}
+
+void sata_dwc_probe(void)
+{
+	struct sata_dwc_device hsdev;
+	struct ata_host host;
+	struct ata_port_info pi = sata_dwc_port_info[0];
+	struct ata_device *ata_dev = &ata_device;
+	struct ata_link *link;
+        struct sata_dwc_device_port hsdevp = dwc_devp;
+	u8 *base = 0;
+	u8 *sata_dma_regs_addr = 0;
+	u32 idr, versionr;
+        u8 status;
+	unsigned long base_addr = 0;
+	int chan = 0;
+	int rc;
+	int i;
+	const u16 *id;
+	unsigned long xfer_mask;
+	char revbuf[7];         /* XYZ-99\0 */
+	unsigned long pio_mask, mwdma_mask, udma_mask;
+
+	phost = &host;	/* set grobal */
+
+	/* Base address */
+	base = (u8*)SATA_BASE_ADDR;
+
+	/* SATA register init */
+	hsdev.sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+
+	host.n_ports = SATA_DWC_MAX_PORTS;
+
+	for (i = 0; i < SATA_DWC_MAX_PORTS; i++) {
+		ap.pflags |= ATA_PFLAG_INITIALIZING;
+		ap.flags = ATA_FLAG_DISABLED;
+		ap.print_id = -1;
+		ap.ctl = ATA_DEVCTL_OBS;
+		ap.host = &host;
+		ap.last_ctl = 0xFF;
+		ap.dev = &ata_device;
+
+		link = &ap.link;
+		link->ap = &ap;
+		link->pmp = 0;
+		link->active_tag = ATA_TAG_POISON;
+		link->hw_sata_spd_limit = 0;
+
+		ap.port_no = i;
+		host.ports[i] = &ap;
+	}
+
+	ap.pio_mask = pi.pio_mask;
+	ap.mwdma_mask = pi.mwdma_mask;
+	ap.udma_mask = pi.udma_mask;
+	ap.flags |= pi.flags;
+	ap.link.flags |= pi.link_flags;
+
+	/* Host port init */
+	host.ports[0]->ioaddr.cmd_addr = base;
+	host.ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
+	scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
+
+	/* sata_dwc setup port */
+	base_addr = (unsigned long)base;
+
+	host.ports[0]->ioaddr.cmd_addr = (void *)base_addr + 0x00;
+	host.ports[0]->ioaddr.data_addr = (void *)base_addr + 0x00;
+
+	host.ports[0]->ioaddr.error_addr = (void *)base_addr + 0x04;
+	host.ports[0]->ioaddr.feature_addr = (void *)base_addr + 0x04;
+
+	host.ports[0]->ioaddr.nsect_addr = (void *)base_addr + 0x08;
+
+	host.ports[0]->ioaddr.lbal_addr = (void *)base_addr + 0x0c;
+	host.ports[0]->ioaddr.lbam_addr = (void *)base_addr + 0x10;
+	host.ports[0]->ioaddr.lbah_addr = (void *)base_addr + 0x14;
+
+	host.ports[0]->ioaddr.device_addr = (void *)base_addr + 0x18;
+	host.ports[0]->ioaddr.command_addr = (void *)base_addr + 0x1c;
+	host.ports[0]->ioaddr.status_addr = (void *)base_addr + 0x1c;
+
+	host.ports[0]->ioaddr.altstatus_addr = (void *)base_addr + 0x20;
+	host.ports[0]->ioaddr.ctl_addr = (void *)base_addr + 0x20;
+
+	/* Get Host ID / Version */
+	idr = in_le32(&hsdev.sata_dwc_regs->idr);
+	versionr = in_le32(&hsdev.sata_dwc_regs->versionr);
+
+	/* DMA register init */
+	sata_dma_regs_addr = (u8*)SATA_DMA_REG_ADDR;
+	sata_dma_regs = (void *__iomem)sata_dma_regs_addr;
+
+	/* DMA channel Interrupt is disable. DMA Enable setup is next. */
+	for (chan = 0; chan < DMA_NUM_CHANS; chan++) {
+		/* DMA Interrupt register(error) mask. */
+		out_le32(&(sata_dma_regs->interrupt_mask.error.low),
+				DMA_DISABLE_CHAN(chan));
+
+		/* DMA Interrupt register(transfer) mask. */
+		out_le32(&(sata_dma_regs->interrupt_mask.tfr.low),
+				DMA_DISABLE_CHAN(chan));
+	}
+
+	/* DMA Enable by DMAC Configuration Register */
+	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_EN);
+
+	/* Enable selective interrupts by setting the interrupt mask register */
+	out_le32(&hsdev.sata_dwc_regs->intmr,
+		SATA_DWC_INTMR_ERRM |
+		SATA_DWC_INTMR_NEWFPM |
+		SATA_DWC_INTMR_PMABRTM |
+		SATA_DWC_INTMR_DMATM);
+
+	/* Unmask the error bits that should trigger an error interrupt by
+	 * setting the error mask register.
+	 */
+	out_le32(&hsdev.sata_dwc_regs->errmr,SATA_DWC_SERROR_ERR_BITS);
+
+	hsdev.host = ap.host;
+	memset(&hsdevp, 0, sizeof(hsdevp));
+	hsdevp.hsdev = &hsdev;
+
+	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
+		hsdevp.cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
+
+	if (ap.port_no == 0) {
+		out_le32(&hsdev.sata_dwc_regs->dmacr,SATA_DWC_DMACR_TXRXCH_CLEAR);
+
+		out_le32(&hsdev.sata_dwc_regs->dbtsr,
+			(SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+			SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
+	}
+
+	/* Clear any error bits before libata starts issuing commands */
+	out_le32((void __iomem *)scr_addr_sstatus + 4,
+		in_le32((void __iomem *)scr_addr_sstatus + 4));
+
+	/* check altstatus register (find device) */
+	status = ata_check_altstatus(&ap);
+
+	if (status == 0x7f) {
+		printf("Hard Disk not found.\n");
+		dev_state = SATA_NODEVICE;
+		return;
+	}
+
+	/* waiting for device ready. time out 30sec */
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);         /* 10 ms */
+
+		/* read altstatus */
+		status = ata_check_altstatus(&ap);
+
+		/* status is not busy => break */
+		if ((status &  ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+		
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			/* bussy set devise state flag */
+			dev_state = SATA_NODEVICE;
+			return;
+		}
+		if ((i >= 100) && ((i%100)==0))
+			printf(".");
+	}
+
+	/* softreset */
+	rc = sata_dwc_softreset(&ap);
+
+	if (rc)
+		printf("sata_dwc : error. soft reset failed\n");
+
+	/* waiting for device ready. time out 30sec */
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);         /* 10 ms */
+
+		/* read altstatus */
+		status = ata_check_altstatus(&ap);
+
+		/* status is not busy => break */
+		if ((status &  ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+		
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			/* bussy set devise state flag */
+			dev_state = SATA_NODEVICE;
+			return;
+		}
+		if ((i >= 100) && ((i%100)==0))
+			printf(".");
+	}
+
+	udelay (1000);         /* before IDENTIFY command safety delay 1 ms */
+
+	/* IDENTIFY command send */
+	rc = ata_dev_read_id(ata_dev, &ata_dev->class,
+			ATA_READID_POSTRESET,ata_dev->id);
+
+	if (rc)
+		printf("sata_dwc : error. IDENTIFY Command failed\n");
+
+	/* SATA drives indicate we have a bridge. We don't know which
+	 * end of the link the bridge is which is a problem
+	 */
+	if (ata_id_is_sata(ata_dev->id))
+		ap.cbl = ATA_CBL_SATA;
+
+	id = ata_dev->id;
+
+	/* initialize to be configured parameters */
+	ata_dev->flags &= ~ATA_DFLAG_CFG_MASK;
+	ata_dev->max_sectors = 0;
+	ata_dev->cdb_len = 0;
+	ata_dev->n_sectors = 0;
+	ata_dev->cylinders = 0;
+	ata_dev->heads = 0;
+	ata_dev->sectors = 0;
+
+	/* Usual case. Word 53 indicates word 64 is valid */
+	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+		pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+		pio_mask <<= 3;
+		pio_mask |= 0x7;
+	} else {
+		/* If word 64 isn't valid then Word 51 high byte holds
+		 * the PIO timing number for the maximum. Turn it into
+		 * a mask.
+		 */
+		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
+		if (mode < 5) {   /* Valid PIO range */
+			pio_mask = (2 << mode) - 1;
+		} else {
+			pio_mask = 1;
+		}
+	}
+
+	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+	if (ata_id_is_cfa(id)) {
+		/*
+		 *	Process compact flash extended modes
+		 */
+		int pio = id[163] & 0x7;
+		int dma = (id[163] >> 3) & 7;
+
+		if (pio)
+			pio_mask |= (1 << 5);
+		if (pio > 1)
+			pio_mask |= (1 << 6);
+		if (dma)
+			mwdma_mask |= (1 << 3);
+		if (dma > 1)
+			mwdma_mask |= (1 << 4);
+	}
+
+	udma_mask = 0;
+	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+	xfer_mask = (pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO |
+		(mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA |
+		(udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
+
+	/* ATA-specific feature tests */
+	if (ata_dev->class == ATA_DEV_ATA) {
+		if (ata_id_is_cfa(id)) {
+			if (id[162] & 1) /* CPRM may make this media unusable */
+				printf("supports DRM functions and may "
+					"not be fully accessable.\n");
+			sprintf(revbuf, "%s", "CFA");
+		} else {
+			/* Warn the user if the device has TPM extensions */
+			if (ata_id_has_tpm(id))
+				printf("supports DRM functions and may "
+						"not be fully accessable.\n");
+		}
+
+		/* set n_secters */
+		ata_dev->n_sectors = ata_id_n_sectors((u16*)id);
+
+		if (ata_dev->id[59] & 0x100)
+			ata_dev->multi_count = ata_dev->id[59] & 0xff;
+
+		if (ata_id_has_lba(id)) {
+			const char *lba_desc;
+			char ncq_desc[20];
+
+			lba_desc = "LBA";
+			ata_dev->flags |= ATA_DFLAG_LBA;
+			if (ata_id_has_lba48(id)) {
+				ata_dev->flags |= ATA_DFLAG_LBA48;
+				lba_desc = "LBA48";
+
+				if (ata_dev->n_sectors >= (1UL << 28) &&
+					ata_id_has_flush_ext(id))
+					ata_dev->flags |= ATA_DFLAG_FLUSH_EXT;
+			}
+			/* config NCQ */
+			if (!ata_id_has_ncq(ata_dev->id))
+				ncq_desc[0] = '\0';
+
+			if (ata_dev->horkage & ATA_HORKAGE_NONCQ)
+				sprintf(ncq_desc, "%s", "NCQ (not used)");
+
+			if (ap.flags & ATA_FLAG_NCQ)
+				ata_dev->flags |= ATA_DFLAG_NCQ;
+		}
+		ata_dev->cdb_len = 16;
+	}
+	/* determine max_sectors */
+	ata_dev->max_sectors = ATA_MAX_SECTORS;
+	if (ata_dev->flags & ATA_DFLAG_LBA48)
+		ata_dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
+	if (!(ata_dev->horkage & ATA_HORKAGE_IPM)) {
+		if (ata_id_has_hipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_HIPM;
+		if (ata_id_has_dipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_DIPM;
+	}
+
+	if ((ap.cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ata_dev->id))) {
+		ata_dev->udma_mask &= ATA_UDMA5;
+		ata_dev->max_sectors = ATA_MAX_SECTORS;
+	}
+
+	if (ata_dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+		printf("Drive reports diagnostics failure."
+				"This may indicate a drive\n");
+		printf("fault or invalid emulation."
+				"Contact drive vendor for information.\n");
+	}
+
+	/* Hard Disk status check : test send READ Command */
+	rc = check_sata_dev_state();
+}
+
+int sata_dwc_softreset(struct ata_port *ap)
+{
+	u8 nsect,lbal = 0;
+	u8 tmp = 0;
+	u32 serror = 0;
+	u8 status = 0;
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	/* read SCR ERROR */
+	serror = in_le32((void *)ap->ioaddr.scr_addr + (SCR_ERROR * 4));
+
+	/* device check */
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+	writeb(0xaa, ioaddr->nsect_addr);
+	writeb(0x55, ioaddr->lbal_addr);
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa)) {
+		/* we found a device */
+		printf("we found a device\n");
+	} else {
+		/* nothing found */
+		printf("Not found a device.\n");
+		dev_state = SATA_NODEVICE;
+		return FALSE;
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	udelay(200);
+
+	/* set softreset */
+	writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+
+	udelay(200);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	/* wait a while before cheking status */
+	msleep(150);
+	status = ata_check_status(ap);
+
+	msleep(50);
+	ata_check_status(ap);
+
+	while (1) {
+		u8 status = ata_check_status(ap);
+
+		if (!(status & ATA_BUSY))
+			break;
+
+		printf("Hard Disk status is BUSY.\n");
+		msleep(50);
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	return 0;
+}
+
+void scsi_bus_reset()
+{
+	struct ata_port *ap = pap;
+
+	/* check device state */
+	if (dev_state != SATA_READY) {
+		printf("no devices available\n");
+		return;
+	}
+
+	/*soft reset process*/
+	sata_dwc_softreset(ap);
+}
+
+void scsi_print_error(ccb * pccb)
+{
+	/*The ahci error info can be read in the ahci driver*/
+}
+
+int ata_dev_read_sectors(ccb *pccb)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	u32 block=0;
+	u32 n_block=0;
+
+	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;	/*ap->ctl = 0x08 */
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	/* set pdata */
+	ap->pdata = pccb->pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	block |= ((u32)pccb->cmd[2]) << 24;
+	block |= ((u32)pccb->cmd[3]) << 16;
+	block |= ((u32)pccb->cmd[4]) << 8;
+	block |= ((u32)pccb->cmd[5]);
+
+	n_block |= ((u32)pccb->cmd[7]) << 8;
+	n_block |= ((u32)pccb->cmd[8]);
+
+	/* trying temp to n_block */
+	temp_n_block = n_block;
+
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_READ_EXT;  /* READ SECTOR(S) EXT 0x24 */
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else	/* LBA24  */
+	tf.command = ATA_CMD_PIO_READ;  /* READ SECTOR(S) 0x20 */
+	tf.flags |= ATA_TFLAG_LBA ;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif	/* CONFIG_LBA48 */
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	/* sanity check */
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return 0;
+
+err_out:
+	printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return rc;
+}
diff -purN u-boot-2009.03/drivers/block/sata_dwc.h u-boot-2009.03-sata/drivers/block/sata_dwc.h
--- u-boot-2009.03/drivers/block/sata_dwc.h	1970-01-01 09:00:00.000000000 +0900
+++ u-boot-2009.03-sata/drivers/block/sata_dwc.h	2009-03-26 18:39:46.000000000 +0900
@@ -0,0 +1,484 @@
+/*
+ * sata_dwc.h
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under  the terms of  the GNU
+ * General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 03-26-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+
+#ifndef _SATA_DWC_H_
+#define _SATA_DWC_H_
+
+#define HZ 100
+
+#define READ 0
+#define WRITE 1
+
+enum {
+	ATA_READID_POSTRESET	= (1 << 0),	/* reading ID after reset */
+
+	ATA_DNXFER_PIO		= 0,	/* speed down PIO */
+	ATA_DNXFER_DMA		= 1,	/* speed down DMA */
+	ATA_DNXFER_40C		= 2,	/* apply 40c cable limit */
+	ATA_DNXFER_FORCE_PIO	= 3,	/* force PIO */
+	ATA_DNXFER_FORCE_PIO0	= 4,	/* force PIO0 */
+
+	ATA_DNXFER_QUIET	= (1 << 31),
+};
+
+enum hsm_task_states {
+	HSM_ST_IDLE,		/* no command on going */
+	HSM_ST_FIRST,		/* (waiting the device to)
+				 * write CDB or first data block */
+	HSM_ST,			/* (waiting the device to) transfer data */
+	HSM_ST_LAST,		/* (waiting the device to) complete command */
+	HSM_ST_ERR,		/* error */
+};
+
+#define	ATA_SHORT_PAUSE		((HZ >> 6) + 1)
+
+struct ata_queued_cmd {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
+
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
+	unsigned long		flags;		/* ATA_QCFLAG_xxx */
+	unsigned int		tag;
+	unsigned int		n_elem;
+
+	int			dma_dir;
+
+	unsigned int		sect_size;
+
+	unsigned int		nbytes;
+	unsigned int		extrabytes;
+	unsigned int		curbytes;
+
+	unsigned int		err_mask;
+	struct ata_taskfile	result_tf;
+
+	void			*private_data;
+	void			*lldd_task;
+	unsigned char		*pdata;
+};
+
+typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+
+/* defines only for the constants which don't work cell as enums*/
+#define ATA_TAG_POISON	0xfafbfcfdU
+
+enum {
+	/* various global constants */
+	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,	/* Worst case */
+	ATA_MAX_PORTS		= 8,
+	ATA_DEF_QUEUE		= 1,
+	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
+	ATA_MAX_QUEUE		= 32,
+	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
+	ATA_MAX_BUS		= 2,
+	ATA_DEF_BUSY_WAIT	= 10000,
+
+	ATAPI_MAX_DRAIN		= 16 << 10,
+
+	ATA_SHT_EMULATED	= 1,
+	ATA_SHT_CMD_PER_LUN	= 1,
+	ATA_SHT_THIS_ID		= -1,
+	ATA_SHT_USE_CLUSTERING	= 1,
+
+	/* struct ata_device stuff */
+	ATA_DFLAG_LBA		= (1 << 0),	/* device supports LBA */
+	ATA_DFLAG_LBA48		= (1 << 1),	/* device supports LBA48 */
+	ATA_DFLAG_CDB_INTR	= (1 << 2),	/* device asserts INTRQ */
+	ATA_DFLAG_NCQ		= (1 << 3),	/* device supports NCQ */
+	ATA_DFLAG_FLUSH_EXT	= (1 << 4),	/* do FLUSH_EXT instead of FLUSH */
+	ATA_DFLAG_ACPI_PENDING 	= (1 << 5),	/* ACPI resume action pending */
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6),	/* ACPI on devcfg has failed */
+	ATA_DFLAG_AN		= (1 << 7),	/* AN configured */
+	ATA_DFLAG_HIPM		= (1 << 8),	/* device supports HIPM */
+	ATA_DFLAG_DIPM		= (1 << 9),	/* device supports DIPM */
+	ATA_DFLAG_DMADIR	= (1 << 10),	/* device requires DMADIR */
+	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
+
+	ATA_DFLAG_PIO		= (1 << 12),	/* device limited to PIO mode */
+	ATA_DFLAG_NCQ_OFF	= (1 << 13),	/* device limited to non-NCQ mode */
+	ATA_DFLAG_SPUNDOWN	= (1 << 14),	/* XXX: for spindown_compat */
+	ATA_DFLAG_SLEEPING	= (1 << 15),	/* device is sleeping */
+	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16),	/* data transfer not verified */
+	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
+
+	ATA_DFLAG_DETACH	= (1 << 24),
+	ATA_DFLAG_DETACHED	= (1 << 25),
+
+	/* struct ata_link flags */
+	ATA_LFLAG_HRST_TO_RESUME	= (1 << 0),	/* hardreset to resume link */
+	ATA_LFLAG_SKIP_D2H_BSY		= (1 << 1),	/* can't wait for the first D2H
+							 * Register FIS clearing BSY */
+	ATA_LFLAG_NO_SRST		= (1 << 2),	/* avoid softreset */
+	ATA_LFLAG_ASSUME_ATA		= (1 << 3),	/* assume ATA class */
+	ATA_LFLAG_ASSUME_SEMB		= (1 << 4),	/* assume SEMB class */
+	ATA_LFLAG_ASSUME_CLASS		= ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
+	ATA_LFLAG_NO_RETRY		= (1 << 5),	/* don't retry this link */
+	ATA_LFLAG_DISABLED		= (1 << 6),	/* link is disabled */
+
+	/* struct ata_port flags */
+	ATA_FLAG_SLAVE_POSS	= (1 << 0),
+	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LEGACY	= (1 << 2),	/* no legacy mode check */
+	ATA_FLAG_MMIO		= (1 << 3),	/* use MMIO, not PIO */
+	ATA_FLAG_SRST		= (1 << 4),	/* (obsolete) use ATA SRST, not E.D.D. */
+	ATA_FLAG_SATA_RESET	= (1 << 5),	/* (obsolete) use COMRESET */
+	ATA_FLAG_NO_ATAPI	= (1 << 6),	/* No ATAPI support */
+	ATA_FLAG_PIO_DMA	= (1 << 7),	/* PIO cmds via DMA */
+	ATA_FLAG_PIO_LBA48	= (1 << 8),	/* Host DMA engine is LBA28 only */
+	ATA_FLAG_PIO_POLLING	= (1 << 9),	/* use polling PIO if LLD
+						* doesn't handle PIO interrupts */
+	ATA_FLAG_NCQ		= (1 << 10),	/* host supports NCQ */
+	ATA_FLAG_DEBUGMSG	= (1 << 13),
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15),	/* ignore SIMPLEX */
+	ATA_FLAG_NO_IORDY	= (1 << 16),	/* controller lacks iordy */
+	ATA_FLAG_ACPI_SATA	= (1 << 17),	/* need native SATA ACPI layout */
+	ATA_FLAG_AN		= (1 << 18),	/* controller supports AN */
+	ATA_FLAG_PMP		= (1 << 19),	/* controller supports PMP */
+	ATA_FLAG_IPM		= (1 << 20),	/* driver can handle IPM */
+
+	ATA_FLAG_DISABLED	= (1 << 23),	/* port is disabled, ignore it */
+
+	/* struct ata_port pflags */
+	ATA_PFLAG_EH_PENDING		= (1 << 0),	/* EH pending */
+	ATA_PFLAG_EH_IN_PROGRESS	= (1 << 1),	/* EH in progress */
+	ATA_PFLAG_FROZEN		= (1 << 2),	/* port is frozen */
+	ATA_PFLAG_RECOVERED		= (1 << 3),	/* recovery action performed */
+	ATA_PFLAG_LOADING		= (1 << 4),	/* boot/loading probe */
+	ATA_PFLAG_UNLOADING		= (1 << 5),	/* module is unloading */
+	ATA_PFLAG_SCSI_HOTPLUG		= (1 << 6),	/* SCSI hotplug scheduled */
+	ATA_PFLAG_INITIALIZING		= (1 << 7),	/* being initialized, don't touch */
+	ATA_PFLAG_RESETTING		= (1 << 8),	/* reset in progress */
+	ATA_PFLAG_SUSPENDED		= (1 << 17),	/* port is suspended (power) */
+	ATA_PFLAG_PM_PENDING		= (1 << 18),	/* PM operation pending */
+
+	/* struct ata_queued_cmd flags */
+	ATA_QCFLAG_ACTIVE	= (1 << 0),	/* cmd not yet ack'd to scsi lyer */
+	ATA_QCFLAG_DMAMAP	= (1 << 1),	/* SG table is DMA mapped */
+	ATA_QCFLAG_IO		= (1 << 3),	/* standard IO command */
+	ATA_QCFLAG_RESULT_TF	= (1 << 4),	/* result TF requested */
+	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5),	/* clear excl_link on completion */
+	ATA_QCFLAG_QUIET	= (1 << 6),	/* don't report device error */
+
+	ATA_QCFLAG_FAILED	= (1 << 16),	/* cmd failed and is owned by EH */
+	ATA_QCFLAG_SENSE_VALID	= (1 << 17),	/* sense data valid */
+	ATA_QCFLAG_EH_SCHEDULED	= (1 << 18),	/* EH scheduled (obsolete) */
+
+	/* host set flags */
+	ATA_HOST_SIMPLEX	= (1 << 0),
+	ATA_HOST_STARTED	= (1 << 1),	/* Host started */
+
+	/* various lengths of time */
+	ATA_TMOUT_BOOT			= 30 * 100,	/* heuristic */
+	ATA_TMOUT_BOOT_QUICK		= 7 * 100,	/* heuristic */
+	ATA_TMOUT_INTERNAL		= 30 * 100,
+	ATA_TMOUT_INTERNAL_QUICK	= 5 * 100,
+
+	/* FIXME: GoVault needs 2s but we can't afford that without
+	 * parallel probing.  800ms is enough for iVDR disk
+	 * HHD424020F7SV00.  Increase to 2secs when parallel probing
+	 * is in place.
+	 */
+	ATA_TMOUT_FF_WAIT	= 4 * 100 / 5,
+
+	/* ATA bus states */
+	BUS_UNKNOWN		= 0,
+	BUS_DMA			= 1,
+	BUS_IDLE		= 2,
+	BUS_NOINTR		= 3,
+	BUS_NODATA		= 4,
+	BUS_TIMER		= 5,
+	BUS_PIO			= 6,
+	BUS_EDD			= 7,
+	BUS_IDENTIFY		= 8,
+	BUS_PACKET		= 9,
+
+	/* SATA port states */
+	PORT_UNKNOWN		= 0,
+	PORT_ENABLED		= 1,
+	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_NR_PIO_MODES	= 7,
+	ATA_NR_MWDMA_MODES	= 5,
+	ATA_NR_UDMA_MODES	= 8,
+
+	ATA_SHIFT_PIO		= 0,
+	ATA_SHIFT_MWDMA		= ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
+	ATA_SHIFT_UDMA		= ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
+
+	/* size of buffer to pad xfers ending on unaligned boundaries */
+	ATA_DMA_PAD_SZ		= 4,
+
+	/* ering size */
+	ATA_ERING_SIZE		= 32,
+
+	ATA_DEFER_LINK		= 1,
+	ATA_DEFER_PORT		= 2,
+
+	/* desc_len for ata_eh_info and context */
+	ATA_EH_DESC_LEN		= 80,
+
+	/* reset / recovery action types */
+	ATA_EH_REVALIDATE	= (1 << 0),
+	ATA_EH_SOFTRESET	= (1 << 1),
+	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_ENABLE_LINK	= (1 << 3),
+	ATA_EH_LPM		= (1 << 4),	/* link power management action */
+
+	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+	/* ata_eh_info->flags */
+	ATA_EHI_HOTPLUGGED	= (1 << 0),	/* could have been hotplugged */
+	ATA_EHI_RESUME_LINK	= (1 << 1),	/* resume link (reset modifier) */
+	ATA_EHI_NO_AUTOPSY	= (1 << 2),	/* no autopsy */
+	ATA_EHI_QUIET		= (1 << 3),	/* be quiet */
+
+	ATA_EHI_DID_SOFTRESET	= (1 << 16),	/* already soft-reset this port */
+	ATA_EHI_DID_HARDRESET	= (1 << 17),	/* already soft-reset this port */
+	ATA_EHI_PRINTINFO	= (1 << 18),	/* print configuration info */
+	ATA_EHI_SETMODE		= (1 << 19),	/* configure transfer mode */
+	ATA_EHI_POST_SETMODE	= (1 << 20),	/* revaildating after setmode */
+
+	ATA_EHI_DID_RESET       = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+	/* max tries if error condition is still set after ->error_handler */
+	ATA_EH_MAX_TRIES	= 5,
+
+	/* how hard are we gonna try to probe/recover devices */
+	ATA_PROBE_MAX_TRIES	= 3,
+	ATA_EH_DEV_TRIES	= 3,
+	ATA_EH_PMP_TRIES	= 5,
+	ATA_EH_PMP_LINK_TRIES	= 3,
+
+	SATA_PMP_SCR_TIMEOUT	= 250,
+
+	/* Horkage types. May be set by libata or controller on drives
+	(some horkage may be drive/controller pair dependant */
+
+	ATA_HORKAGE_DIAGNOSTIC	= (1 << 0),	/* Failed boot diag */
+	ATA_HORKAGE_NODMA	= (1 << 1),	/* DMA problems */
+	ATA_HORKAGE_NONCQ	= (1 << 2),	/* Don't use NCQ */
+	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),	/* Limit max sects to 128 */
+	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),	/* Broken HPA */
+	ATA_HORKAGE_SKIP_PM	= (1 << 5),	/* Skip PM operations */
+	ATA_HORKAGE_HPA_SIZE	= (1 << 6),	/* native size off by one */
+	ATA_HORKAGE_IPM		= (1 << 7),	/* Link PM problems */
+	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */
+	ATA_HORKAGE_STUCK_ERR	= (1 << 9),	/* stuck ERR on next PACKET */
+
+	/* DMA mask for user DMA control: User visible values; DO NOT renumber */
+	ATA_DMA_MASK_ATA	= (1 << 0),	/* DMA on ATA Disk */
+	ATA_DMA_MASK_ATAPI	= (1 << 1),	/* DMA on ATAPI */
+	ATA_DMA_MASK_CFA	= (1 << 2),	/* DMA on CF Card */
+
+	/* ATAPI command types */
+	ATAPI_READ		= 0,		/* READs */
+	ATAPI_WRITE		= 1,		/* WRITEs */
+	ATAPI_READ_CD		= 2,		/* READ CD [MSF] */
+	ATAPI_PASS_THRU		= 3,		/* SAT pass-thru */
+	ATAPI_MISC		= 4,		/* the rest */
+};
+
+enum ata_completion_errors {
+	AC_ERR_DEV		= (1 << 0),	/* device reported error */
+	AC_ERR_HSM		= (1 << 1),	/* host state machine violation */
+	AC_ERR_TIMEOUT		= (1 << 2),	/* timeout */
+	AC_ERR_MEDIA		= (1 << 3),	/* media error */
+	AC_ERR_ATA_BUS		= (1 << 4),	/* ATA bus error */
+	AC_ERR_HOST_BUS		= (1 << 5),	/* host bus error */
+	AC_ERR_SYSTEM		= (1 << 6),	/* system error */
+	AC_ERR_INVALID		= (1 << 7),	/* invalid argument */
+	AC_ERR_OTHER		= (1 << 8),	/* unknown */
+	AC_ERR_NODEV_HINT	= (1 << 9),	/* polling device detection hint */
+	AC_ERR_NCQ		= (1 << 10),	/* marker for offending NCQ qc */
+};
+
+enum ata_xfer_mask {
+	ATA_MASK_PIO	= ((1LU << ATA_NR_PIO_MODES) - 1) << ATA_SHIFT_PIO,
+	ATA_MASK_MWDMA	= ((1LU << ATA_NR_MWDMA_MODES) - 1) << ATA_SHIFT_MWDMA,
+	ATA_MASK_UDMA	= ((1LU << ATA_NR_UDMA_MODES) - 1) << ATA_SHIFT_UDMA,
+};
+
+struct ata_port_info {
+	struct scsi_host_template	*sht;
+	unsigned long			flags;
+	unsigned long			link_flags;
+	unsigned long			pio_mask;
+	unsigned long			mwdma_mask;
+	unsigned long			udma_mask;
+	const struct ata_port_operations *port_ops;
+	void				*private_data;
+};
+
+struct ata_ioports {
+	void __iomem		*cmd_addr;
+	void __iomem		*data_addr;
+	void __iomem		*error_addr;
+	void __iomem		*feature_addr;
+	void __iomem		*nsect_addr;
+	void __iomem		*lbal_addr;
+	void __iomem		*lbam_addr;
+	void __iomem		*lbah_addr;
+	void __iomem		*device_addr;
+	void __iomem		*status_addr;
+	void __iomem		*command_addr;
+	void __iomem		*altstatus_addr;
+	void __iomem		*ctl_addr;
+	void __iomem		*bmdma_addr;
+	void __iomem		*scr_addr;
+};
+
+struct ata_host {
+	void __iomem * const	*iomap;
+	unsigned int		n_ports;
+	void			*private_data;
+	const struct ata_port_operations *ops;
+	unsigned long		flags;
+	struct ata_port		*simplex_claimed;	/* channel owning the DMA */
+	struct ata_port		*ports[0];
+};
+
+struct ata_port_stats {
+	unsigned long		unhandled_irq;
+	unsigned long		idle_irq;
+	unsigned long		rw_reqbuf;
+};
+
+struct ata_device {
+	struct ata_link		*link;
+	unsigned int		devno;		/* 0 or 1 */
+	unsigned long		flags;		/* ATA_DFLAG_xxx */
+	unsigned int		horkage;	/* List of broken features */
+	struct scsi_device	*sdev;		/* attached SCSI device */
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	union acpi_object	*gtf_cache;
+#endif
+	/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
+	u64			n_sectors;	/* size of device, if ATA */
+	unsigned int		class;		/* ATA_DEV_xxx */
+
+	union {
+		u16		id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+		u32		gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+	};
+
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
+
+	unsigned int		multi_count;	/* sectors count for
+						 *READ/WRITE MULTIPLE */
+	unsigned int		max_sectors;    /* per-device max sectors */
+	unsigned int		cdb_len;
+
+	/* per-dev xfer mask */
+	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
+	unsigned long		udma_mask;
+
+	/* for CHS addressing */
+	u16			cylinders;	/* Number of cylinders */
+	u16			heads;		/* Number of heads */
+	u16			sectors;	/* Number of sectors per track */
+
+	/* error history */
+	int			spdn_cnt;
+};
+
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL = 0,
+	DMA_TO_DEVICE = 1,
+	DMA_FROM_DEVICE = 2,
+	DMA_NONE = 3,
+};
+
+struct ata_link {
+	struct ata_port		*ap;
+	int			pmp;		/* port multiplier port # */
+	unsigned int		active_tag;	/* active tag on this link */
+	u32			sactive;	/* active NCQ commands */
+
+	unsigned int		flags;		/* ATA_LFLAG_xxx */
+
+	unsigned int		hw_sata_spd_limit;
+	unsigned int		sata_spd_limit;
+	unsigned int		sata_spd;	/* current SATA PHY speed */
+
+	struct ata_device	device[2];
+};
+
+struct ata_port {
+	unsigned long		flags;		/* ATA_FLAG_xxx */
+	unsigned int		pflags;		/* ATA_PFLAG_xxx */
+	unsigned int		print_id;	/* user visible unique port ID */
+	unsigned int            port_no;	/* 0 based port no. inside the host */
+
+	struct ata_ioports	ioaddr;		/* ATA cmd/ctl/dma register blocks */
+
+	u8			ctl;		/* cache of ATA control register */
+	u8			last_ctl;	/* Cache last written value */
+	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
+	unsigned int		udma_mask;
+	unsigned int		cbl;		/* cable type; ATA_CBL_xxx */
+
+	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+	unsigned long		qc_allocated;
+	unsigned int		qc_active;
+	int			nr_active_links;	/* #links with active qcs */
+
+	struct ata_link		link;		/* host default link */
+
+	int			nr_pmp_links;	/* nr of available PMP links */
+	struct ata_link		*pmp_link;	/* array of PMP links */
+	struct ata_link		*excl_link;	/* for PMP qc exclusion */
+
+	struct ata_port_stats	stats;
+	struct ata_host		*host;
+
+	struct device		*dev;
+	void			*port_task_data;
+
+	unsigned int		hsm_task_state;
+
+	u32			msg_enable;
+	void			*private_data;
+	unsigned char		*pdata;
+};
+#endif	/* _SATA_DWC_H_ */
diff -purN u-boot-2009.03/include/configs/canyonlands.h u-boot-2009.03-sata/include/configs/canyonlands.h
--- u-boot-2009.03/include/configs/canyonlands.h	2009-03-22 06:04:41.000000000 +0900
+++ u-boot-2009.03-sata/include/configs/canyonlands.h	2009-03-26 18:15:30.000000000 +0900
@@ -454,6 +454,7 @@
  #define CONFIG_CMD_SDRAM
  #define CONFIG_CMD_SNTP
  #define CONFIG_CMD_USB
+#define CONFIG_CMD_SCSI
  #elif defined(CONFIG_GLACIER)
  #define CONFIG_CMD_DATE
  #define CONFIG_CMD_DTT
@@ -517,6 +518,22 @@
  #endif /* CONFIG_460GT */

  /*-----------------------------------------------------------------------
+ * S-ATA driver setup
+ *----------------------------------------------------------------------*/
+#define CONFIG_SATA_DWC
+
+#ifdef CONFIG_SATA_DWC
+#define CONFIG_LIBATA
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	1	/* SCSI ID */
+#define CONFIG_SYS_SCSI_MAX_LUN		1	/* SCSI LUN */
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+						CONFIG_SYS_SCSI_MAX_LUN)
+#define CONFIG_SYS_SCSI_MAXDEVICE	CONFIG_SYS_SCSI_MAX_DEVICE
+#define SATA_BASE_ADDR		0xe20d1000	/* PPC460EX SATA Base Address */
+#define SATA_DMA_REG_ADDR	0xe20d0800	/* PPC460EX SATA Base Address */
+#endif
+
+/*-----------------------------------------------------------------------
   * External Bus Controller (EBC) Setup
   *----------------------------------------------------------------------*/


Regards,
Kazuaki Ichinohe

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-26 10:56         ` Kazuaki Ichinohe
@ 2009-03-27 16:11           ` Stefan Roese
  2009-03-27 16:31           ` Wolfgang Denk
  1 sibling, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2009-03-27 16:11 UTC (permalink / raw)
  To: u-boot

On Thursday 26 March 2009, Kazuaki Ichinohe wrote:
> Thank you for the reply.
> My answer is described in the beginning.

OK, I just tried to apply your patch for basic testing. Didn't work though. 
Here the error log:

[stefan at kubuntu u-boot (master)]$ patch -p1 < patches_sata/\[U-Boot\]\ 
\[PATCH\]\ Canyonlands\ SATA\ harddisk\ driver.mbox
patching file common/cmd_scsi.c
Hunk #1 FAILED at 47.
Hunk #2 FAILED at 181.
Hunk #3 FAILED at 192.
Hunk #4 FAILED at 453.
4 out of 4 hunks FAILED -- saving rejects to file common/cmd_scsi.c.rej
patching file drivers/block/Makefile
Hunk #1 FAILED at 34.
1 out of 1 hunk FAILED -- saving rejects to file drivers/block/Makefile.rej
patching file drivers/block/sata_dwc.c
patching file drivers/block/sata_dwc.h
patching file include/configs/canyonlands.h
Hunk #1 FAILED at 454.
Hunk #2 FAILED at 518.
2 out of 2 hunks FAILED -- saving rejects to file 
include/configs/canyonlands.h.rej

Seems that you didn't base your patch on the latest git version of U-Boot. 
Please rebase your patch again that it applies cleanly. And again, please use 
the git tools to generate the patch. Or at least send the patch in a git 
compatible way, so that it can be applied using "git am".

Thanks.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-26 10:56         ` Kazuaki Ichinohe
  2009-03-27 16:11           ` Stefan Roese
@ 2009-03-27 16:31           ` Wolfgang Denk
  2009-03-30  8:27             ` Kazuaki Ichinohe
  1 sibling, 1 reply; 36+ messages in thread
From: Wolfgang Denk @ 2009-03-27 16:31 UTC (permalink / raw)
  To: u-boot

Dear Kazuaki Ichinohe,

In message <49CB5F77.1060304@fsi.co.jp> you wrote:
...
>  >Why do you add this 460EX SATA support to cmd_scsi.c? Wouldn't cmd_sata.c be a
>  >better place? Or did I miss something here?
> 
> The cmd_scsi.c which define CONFIG_CMD_SCSI are modified
> because I want to use scsiboot command of U-BOOT.

This makes no sense. It is a S-ATA driver, not a SCSI driver, and as
such it has to be supported in the context of the S-ATA support.

I explicitly NAK the changes to the SCSI related files.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A quarrel is quickly settled when deserted by one party; there is  no
battle unless there be two.                                  - Seneca

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-27 16:31           ` Wolfgang Denk
@ 2009-03-30  8:27             ` Kazuaki Ichinohe
  2009-04-17  7:31               ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-03-30  8:27 UTC (permalink / raw)
  To: u-boot

Hello Denk,

After confirming operation, I'll send sata_dwc.c with cmd_sata.c again.

Regards,
Kazuaki Ichinohe

Wolfgang Denk wrote:
> Dear Kazuaki Ichinohe,
> 
> In message <49CB5F77.1060304@fsi.co.jp> you wrote:
> ...
>>  >Why do you add this 460EX SATA support to cmd_scsi.c? Wouldn't cmd_sata.c be a
>>  >better place? Or did I miss something here?
>>
>> The cmd_scsi.c which define CONFIG_CMD_SCSI are modified
>> because I want to use scsiboot command of U-BOOT.
> 
> This makes no sense. It is a S-ATA driver, not a SCSI driver, and as
> such it has to be supported in the context of the S-ATA support.
> 
> I explicitly NAK the changes to the SCSI related files.
> 
> Best regards,
> 
> Wolfgang Denk
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-03-30  8:27             ` Kazuaki Ichinohe
@ 2009-04-17  7:31               ` Kazuaki Ichinohe
  2009-04-27  1:53                 ` Kazuaki Ichinohe
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-04-17  7:31 UTC (permalink / raw)
  To: u-boot

Hello Denk, Stefan,

This patch adds a SATA harddisk driver for the canyonlands.
This patch is kernel driver's porting.
This pach corresponded to not cmd_scsi but cmd_sata.


[environment variable, boot script]
setenv bootargs root=/dev/sda7 rw
setenv bootargs ${bootargs} console=ttyS0,115200
ext2load sata 0:2 0x400000 /canyonlands/uImage
ext2load sata 0:2 0x800000 /canyonlands/canyonlands.dtb
fdt addr 0x800000 0x4000
bootm 0x400000 - 0x800000

If you drive SATA-2 disk on Canyonlands, you must change parts from
PI2PCIE212 to PI2PCIE2212 on U25. We confirmed to boot by using following disk.

1.Vender: Fujitsu Type: MHW2040BS
2.Vender: Fujitsu Type: MHW2060BK
3.Vendor: HAGIWARA SYS-COM:HFD25S-032GT
4.Vender: WesternDigital Type: WD3200BJKT (CONFIG_LBA48 required)
5.Vender: WesternDigital Type: WD3200BEVT (CONFIG_LBA48 required)
6.Vender: hitachi Type: HTS543232L9A300 (CONFIG_LBA48 required)
7.Vender: Seagate Type: ST31000333AS (CONFIG_LBA48 required)
8.Vender: Transcend Type: TS32GSSD25S-M
9.Vender: MTRON Type: MSD-SATA1525-016

Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>
---

[patch]
---
  drivers/block/Makefile        |    1 +
  drivers/block/sata_dwc.c      | 2110 +++++++++++++++++++++++++++++++++++++++++
  drivers/block/sata_dwc.h      |  463 +++++++++
  include/configs/canyonlands.h |   16 +
  4 files changed, 2590 insertions(+), 0 deletions(-)
  create mode 100644 drivers/block/sata_dwc.c
  create mode 100644 drivers/block/sata_dwc.h

diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index eccefc1..e0af40e 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -35,6 +35,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
  COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
  COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
  COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

  COBJS	:= $(COBJS-y)
  SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/block/sata_dwc.c b/drivers/block/sata_dwc.c
new file mode 100644
index 0000000..91211bb
--- /dev/null
+++ b/drivers/block/sata_dwc.c
@@ -0,0 +1,2110 @@
+/*
+ * sata_dwc.c
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU
+ * General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 04-17-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <ata.h>
+#include <linux/ctype.h>
+
+#include "sata_dwc.h"
+
+#define DMA_NUM_CHANS			1
+#define DMA_NUM_CHAN_REGS		8
+
+#define AHB_DMA_BRST_DFLT		16
+
+struct dmareg {
+	u32 low;
+	u32 high;
+};
+
+struct dma_chan_regs {
+	struct dmareg sar;
+	struct dmareg dar;
+	struct dmareg llp;
+	struct dmareg ctl;
+	struct dmareg sstat;
+	struct dmareg dstat;
+	struct dmareg sstatar;
+	struct dmareg dstatar;
+	struct dmareg cfg;
+	struct dmareg sgr;
+	struct dmareg dsr;
+};
+
+struct dma_interrupt_regs {
+	struct dmareg tfr;
+	struct dmareg block;
+	struct dmareg srctran;
+	struct dmareg dsttran;
+	struct dmareg error;
+};
+
+struct ahb_dma_regs {
+	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];
+	struct dma_interrupt_regs	interrupt_raw;
+	struct dma_interrupt_regs	interrupt_status;
+	struct dma_interrupt_regs	interrupt_mask;
+	struct dma_interrupt_regs	interrupt_clear;
+	struct dmareg			statusInt;
+	struct dmareg			rq_srcreg;
+	struct dmareg			rq_dstreg;
+	struct dmareg			rq_sgl_srcreg;
+	struct dmareg			rq_sgl_dstreg;
+	struct dmareg			rq_lst_srcreg;
+	struct dmareg			rq_lst_dstreg;
+	struct dmareg			dma_cfg;
+	struct dmareg			dma_chan_en;
+	struct dmareg			dma_id;
+	struct dmareg			dma_test;
+	struct dmareg			res1;
+	struct dmareg			res2;
+	/* DMA Comp Params
+	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
+	 * Param 4 = dma_param[2] ...
+	 */
+	struct dmareg			dma_params[6];
+};
+
+#define DMA_EN			0x00000001
+#define DMA_DI			0x00000000
+#define DMA_CHANNEL(ch)		(0x00000001 << (ch))
+#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |	\
+				((0x000000001 << (ch)) << 8))
+#define DMA_DISABLE_CHAN(ch)	(0x00000000 | 	\
+				((0x000000001 << (ch)) << 8))
+
+#define SATA_DWC_MAX_PORTS	1
+#define SATA_DWC_SCR_OFFSET	0x24
+#define SATA_DWC_REG_OFFSET	0x64
+
+struct sata_dwc_regs {
+	u32 fptagr;
+	u32 fpbor;
+	u32 fptcr;
+	u32 dmacr;
+	u32 dbtsr;
+	u32 intpr;
+	u32 intmr;
+	u32 errmr;
+	u32 llcr;
+	u32 phycr;
+	u32 physr;
+	u32 rxbistpd;
+	u32 rxbistpd1;
+	u32 rxbistpd2;
+	u32 txbistpd;
+	u32 txbistpd1;
+	u32 txbistpd2;
+	u32 bistcr;
+	u32 bistfctr;
+	u32 bistsr;
+	u32 bistdecr;
+	u32 res[15];
+	u32 testr;
+	u32 versionr;
+	u32 idr;
+	u32 unimpl[192];
+	u32 dmadr[256];
+};
+
+#define SATA_DWC_TXFIFO_DEPTH		0x01FF
+#define SATA_DWC_RXFIFO_DEPTH		0x01FF
+
+#define SATA_DWC_DBTSR_MWR(size)	((size / 4) & SATA_DWC_TXFIFO_DEPTH)
+#define SATA_DWC_DBTSR_MRD(size)	(((size / 4) &	\
+					SATA_DWC_RXFIFO_DEPTH) << 16)
+#define SATA_DWC_INTPR_DMAT		0x00000001
+#define SATA_DWC_INTPR_NEWFP		0x00000002
+#define SATA_DWC_INTPR_PMABRT		0x00000004
+#define SATA_DWC_INTPR_ERR		0x00000008
+#define SATA_DWC_INTPR_NEWBIST		0x00000010
+#define SATA_DWC_INTPR_IPF		0x10000000
+#define SATA_DWC_INTMR_DMATM		0x00000001
+#define SATA_DWC_INTMR_NEWFPM		0x00000002
+#define SATA_DWC_INTMR_PMABRTM		0x00000004
+#define SATA_DWC_INTMR_ERRM		0x00000008
+#define SATA_DWC_INTMR_NEWBISTM		0x00000010
+
+#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
+#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
+
+#define SATA_DWC_QCMD_MAX	32
+
+#define SATA_DWC_SERROR_ERR_BITS	0x0FFF0F03
+
+#define HSDEVP_FROM_AP(ap)	(struct sata_dwc_device_port*)	\
+				(ap)->private_data
+
+struct sata_dwc_device {
+	struct device		*dev;
+	struct ata_probe_ent	*pe;
+	struct ata_host		*host;
+	u8			*reg_base;
+	struct sata_dwc_regs	*sata_dwc_regs;
+	int			irq_dma;
+};
+
+struct sata_dwc_device_port {
+	struct sata_dwc_device	*hsdev;
+	int			cmd_issued[SATA_DWC_QCMD_MAX];
+	u32			dma_chan[SATA_DWC_QCMD_MAX];
+	int			dma_pending[SATA_DWC_QCMD_MAX];
+};
+
+enum {
+	SATA_DWC_CMD_ISSUED_NOT		= 0,
+	SATA_DWC_CMD_ISSUED_PEND	= 1,
+	SATA_DWC_CMD_ISSUED_EXEC	= 2,
+	SATA_DWC_CMD_ISSUED_NODATA	= 3,
+
+	SATA_DWC_DMA_PENDING_NONE	= 0,
+	SATA_DWC_DMA_PENDING_TX		= 1,
+	SATA_DWC_DMA_PENDING_RX		= 2,
+};
+
+#define msleep(a)	udelay(a * 1000)
+#define ssleep(a)	msleep(a * 1000)
+
+static int ata_probe_timeout = (ATA_TMOUT_INTERNAL / 100);
+
+enum sata_dev_state {
+	SATA_INIT = 0,
+	SATA_READY = 1,
+	SATA_NODEVICE = 2,
+	SATA_ERROR = 3,
+};
+enum sata_dev_state dev_state = SATA_INIT;
+
+static struct ahb_dma_regs		*sata_dma_regs = 0;
+static struct ata_host			*phost;
+static struct ata_port			ap;
+static struct ata_port			*pap = &ap;
+static struct ata_device		ata_device;
+static struct sata_dwc_device_port	dwc_devp;
+
+static void	*scr_addr_sstatus;
+static u32	temp_n_block = 0;
+
+static unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout);
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+			u8 enable,u8 feature);
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+			u16 heads, u16 sectors);
+static u8 ata_irq_on(struct ata_port *ap);
+static struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+			unsigned int tag);
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq);
+static void ata_tf_to_host(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static void ata_exec_command(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+static u8 ata_check_altstatus(struct ata_port *ap);
+static u8 ata_check_status(struct ata_port *ap);
+static void ata_dev_select(struct ata_port *ap, unsigned int device,
+			unsigned int wait, unsigned int can_sleep);
+static void ata_qc_issue(struct ata_queued_cmd *qc);
+static void ata_tf_load(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static int ata_dev_read_sectors(unsigned char* pdata,
+			unsigned long datalen, u32 block, u32 n_block);
+static int ata_dev_write_sectors(unsigned char* pdata,
+			unsigned long datalen , u32 block, u32 n_block);
+static void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+static void ata_qc_complete(struct ata_queued_cmd *qc);
+static void __ata_qc_complete(struct ata_queued_cmd *qc);
+static void fill_result_tf(struct ata_queued_cmd *qc);
+static void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void ata_mmio_data_xfer(struct ata_device *dev,
+			unsigned char *buf,
+			unsigned int buflen,int do_write);
+static void ata_pio_task(struct ata_port *arg_ap);
+static void __ata_port_freeze(struct ata_port *ap);
+static int ata_port_freeze(struct ata_port *ap);
+static void ata_qc_free(struct ata_queued_cmd *qc);
+static void ata_pio_sectors(struct ata_queued_cmd *qc);
+static void ata_pio_sector(struct ata_queued_cmd *qc);
+static void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay);
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq);
+static int sata_dwc_softreset(struct ata_port *ap);
+static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id);
+static int check_sata_dev_state(void);
+
+extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
+
+static const struct ata_port_info sata_dwc_port_info[] = {
+	{
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
+				ATA_FLAG_SRST | ATA_FLAG_NCQ,
+		.pio_mask	= 0x1f,
+		.mwdma_mask	= 0x07,
+		.udma_mask	= 0x7f,
+	},
+};
+
+int init_sata (int dev)
+{
+	struct sata_dwc_device hsdev;
+	struct ata_host host;
+	struct ata_port_info pi = sata_dwc_port_info[0];
+	struct ata_link *link;
+	struct sata_dwc_device_port hsdevp = dwc_devp;
+	u8 *base = 0;
+	u8 *sata_dma_regs_addr = 0;
+	u8 status;
+	unsigned long base_addr = 0;
+	int chan = 0;
+	int rc;
+	int i;
+
+	phost = &host;
+
+	base = (u8*)SATA_BASE_ADDR;
+
+	hsdev.sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+
+	host.n_ports = SATA_DWC_MAX_PORTS;
+
+	for (i = 0; i < SATA_DWC_MAX_PORTS; i++) {
+		ap.pflags |= ATA_PFLAG_INITIALIZING;
+		ap.flags = ATA_FLAG_DISABLED;
+		ap.print_id = -1;
+		ap.ctl = ATA_DEVCTL_OBS;
+		ap.host = &host;
+		ap.last_ctl = 0xFF;
+
+		link = &ap.link;
+		link->ap = &ap;
+		link->pmp = 0;
+		link->active_tag = ATA_TAG_POISON;
+		link->hw_sata_spd_limit = 0;
+
+		ap.port_no = i;
+		host.ports[i] = &ap;
+	}
+
+	ap.pio_mask = pi.pio_mask;
+	ap.mwdma_mask = pi.mwdma_mask;
+	ap.udma_mask = pi.udma_mask;
+	ap.flags |= pi.flags;
+	ap.link.flags |= pi.link_flags;
+
+	host.ports[0]->ioaddr.cmd_addr = base;
+	host.ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
+	scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
+
+	base_addr = (unsigned long)base;
+
+	host.ports[0]->ioaddr.cmd_addr = (void *)base_addr + 0x00;
+	host.ports[0]->ioaddr.data_addr = (void *)base_addr + 0x00;
+
+	host.ports[0]->ioaddr.error_addr = (void *)base_addr + 0x04;
+	host.ports[0]->ioaddr.feature_addr = (void *)base_addr + 0x04;
+
+	host.ports[0]->ioaddr.nsect_addr = (void *)base_addr + 0x08;
+
+	host.ports[0]->ioaddr.lbal_addr = (void *)base_addr + 0x0c;
+	host.ports[0]->ioaddr.lbam_addr = (void *)base_addr + 0x10;
+	host.ports[0]->ioaddr.lbah_addr = (void *)base_addr + 0x14;
+
+	host.ports[0]->ioaddr.device_addr = (void *)base_addr + 0x18;
+	host.ports[0]->ioaddr.command_addr = (void *)base_addr + 0x1c;
+	host.ports[0]->ioaddr.status_addr = (void *)base_addr + 0x1c;
+
+	host.ports[0]->ioaddr.altstatus_addr = (void *)base_addr + 0x20;
+	host.ports[0]->ioaddr.ctl_addr = (void *)base_addr + 0x20;
+
+	sata_dma_regs_addr = (u8*)SATA_DMA_REG_ADDR;
+	sata_dma_regs = (void *__iomem)sata_dma_regs_addr;
+
+	status = ata_check_altstatus(&ap);
+
+	if (status == 0x7f) {
+		printf("Hard Disk not found.\n");
+		dev_state = SATA_NODEVICE;
+		rc = FALSE;
+		return rc;
+	}
+
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);
+
+		status = ata_check_altstatus(&ap);
+
+		if ((status & ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			dev_state = SATA_NODEVICE;
+			rc = FALSE;
+			return rc;
+		}
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	rc = sata_dwc_softreset(&ap);
+
+	if (rc) {
+		printf("sata_dwc : error. soft reset failed\n");
+		return rc;
+	}
+
+	for (chan = 0; chan < DMA_NUM_CHANS; chan++) {
+		out_le32(&(sata_dma_regs->interrupt_mask.error.low),
+				DMA_DISABLE_CHAN(chan));
+
+		out_le32(&(sata_dma_regs->interrupt_mask.tfr.low),
+				DMA_DISABLE_CHAN(chan));
+	}
+
+	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_DI);
+
+	out_le32(&hsdev.sata_dwc_regs->intmr,
+		SATA_DWC_INTMR_ERRM |
+		SATA_DWC_INTMR_PMABRTM);
+
+	/* Unmask the error bits that should trigger
+	 * an error interrupt by setting the error mask register.
+	 */
+	out_le32(&hsdev.sata_dwc_regs->errmr,SATA_DWC_SERROR_ERR_BITS);
+
+	hsdev.host = ap.host;
+	memset(&hsdevp, 0, sizeof(hsdevp));
+	hsdevp.hsdev = &hsdev;
+
+	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
+		hsdevp.cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
+
+	out_le32((void __iomem *)scr_addr_sstatus + 4,
+		in_le32((void __iomem *)scr_addr_sstatus + 4));
+
+	rc = 0;
+	return rc;
+}
+
+static u8 ata_check_altstatus(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.altstatus_addr);
+	return val;
+}
+
+static int sata_dwc_softreset(struct ata_port *ap)
+{
+	u8 nsect,lbal = 0;
+	u8 tmp = 0;
+	u32 serror = 0;
+	u8 status = 0;
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	serror = in_le32((void *)ap->ioaddr.scr_addr + (SCR_ERROR * 4));
+
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+	writeb(0xaa, ioaddr->nsect_addr);
+	writeb(0x55, ioaddr->lbal_addr);
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa)) {
+		printf("we found a device\n");
+	} else {
+		printf("Not found a device.\n");
+		dev_state = SATA_NODEVICE;
+		return FALSE;
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	udelay(200);
+
+	writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+
+	udelay(200);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	msleep(150);
+	status = ata_check_status(ap);
+
+	msleep(50);
+	ata_check_status(ap);
+
+	while (1) {
+		u8 status = ata_check_status(ap);
+
+		if (!(status & ATA_BUSY))
+			break;
+
+		printf("Hard Disk status is BUSY.\n");
+		msleep(50);
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	return 0;
+}
+
+static u8 ata_check_status(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.status_addr);
+	return val;
+}
+
+static int ata_id_has_hipm(const u16 *id)
+{
+	u16 val = id[76];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 9);
+}
+
+static int ata_id_has_dipm(const u16 *id)
+{
+	u16 val = id[78];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 3);
+}
+
+int scan_sata (int dev)
+{
+	int i;
+	int rc;
+	u8 status;
+	const u16 *id;
+	struct ata_device *ata_dev = &ata_device;
+	unsigned long pio_mask, mwdma_mask, udma_mask;
+	unsigned long xfer_mask;
+	char revbuf[7];
+	u16 iobuf[ATA_SECTOR_WORDS];
+
+	memset ( iobuf, 0, sizeof(iobuf));
+
+	if (dev_state == SATA_NODEVICE)
+		return 1;
+
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);
+
+		status = ata_check_altstatus(&ap);
+
+		if ((status & ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			dev_state = SATA_NODEVICE;
+			return 1;
+		}
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	udelay (1000);
+
+	rc = ata_dev_read_id(ata_dev, &ata_dev->class,
+			ATA_READID_POSTRESET,ata_dev->id);
+	if (rc) {
+		printf("sata_dwc : error. failed sata scan\n");
+		return 1;
+	}
+
+	/* SATA drives indicate we have a bridge. We don't know which
+	 * end of the link the bridge is which is a problem
+	 */
+	if (ata_id_is_sata(ata_dev->id))
+		ap.cbl = ATA_CBL_SATA;
+
+	id = ata_dev->id;
+
+	ata_dev->flags &= ~ATA_DFLAG_CFG_MASK;
+	ata_dev->max_sectors = 0;
+	ata_dev->cdb_len = 0;
+	ata_dev->n_sectors = 0;
+	ata_dev->cylinders = 0;
+	ata_dev->heads = 0;
+	ata_dev->sectors = 0;
+
+	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+		pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+		pio_mask <<= 3;
+		pio_mask |= 0x7;
+	} else {
+		/* If word 64 isn't valid then Word 51 high byte holds
+		 * the PIO timing number for the maximum. Turn it into
+		 * a mask.
+		 */
+		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
+		if (mode < 5) {
+			pio_mask = (2 << mode) - 1;
+		} else {
+			pio_mask = 1;
+		}
+	}
+
+	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+	if (ata_id_is_cfa(id)) {
+		int pio = id[163] & 0x7;
+		int dma = (id[163] >> 3) & 7;
+
+		if (pio)
+			pio_mask |= (1 << 5);
+		if (pio > 1)
+			pio_mask |= (1 << 6);
+		if (dma)
+			mwdma_mask |= (1 << 3);
+		if (dma > 1)
+			mwdma_mask |= (1 << 4);
+	}
+
+	udma_mask = 0;
+	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+	xfer_mask = ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
+		((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
+		((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
+
+	if (ata_dev->class == ATA_DEV_ATA) {
+		if (ata_id_is_cfa(id)) {
+			if (id[162] & 1)
+				printf("supports DRM functions and may "
+					"not be fully accessable.\n");
+			sprintf(revbuf, "%s", "CFA");
+		} else {
+			if (ata_id_has_tpm(id))
+				printf("supports DRM functions and may "
+						"not be fully accessable.\n");
+		}
+
+		ata_dev->n_sectors = ata_id_n_sectors((u16*)id);
+
+		if (ata_dev->id[59] & 0x100)
+			ata_dev->multi_count = ata_dev->id[59] & 0xff;
+
+		if (ata_id_has_lba(id)) {
+			const char *lba_desc;
+			char ncq_desc[20];
+
+			lba_desc = "LBA";
+			ata_dev->flags |= ATA_DFLAG_LBA;
+			if (ata_id_has_lba48(id)) {
+				ata_dev->flags |= ATA_DFLAG_LBA48;
+				lba_desc = "LBA48";
+
+				if (ata_dev->n_sectors >= (1UL << 28) &&
+					ata_id_has_flush_ext(id))
+					ata_dev->flags |= ATA_DFLAG_FLUSH_EXT;
+			}
+			if (!ata_id_has_ncq(ata_dev->id))
+				ncq_desc[0] = '\0';
+
+			if (ata_dev->horkage & ATA_HORKAGE_NONCQ)
+				sprintf(ncq_desc, "%s", "NCQ (not used)");
+
+			if (ap.flags & ATA_FLAG_NCQ)
+				ata_dev->flags |= ATA_DFLAG_NCQ;
+		}
+		ata_dev->cdb_len = 16;
+	}
+	ata_dev->max_sectors = ATA_MAX_SECTORS;
+	if (ata_dev->flags & ATA_DFLAG_LBA48)
+		ata_dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
+	if (!(ata_dev->horkage & ATA_HORKAGE_IPM)) {
+		if (ata_id_has_hipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_HIPM;
+		if (ata_id_has_dipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_DIPM;
+	}
+
+	if ((ap.cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ata_dev->id))) {
+		ata_dev->udma_mask &= ATA_UDMA5;
+		ata_dev->max_sectors = ATA_MAX_SECTORS;
+	}
+
+	if (ata_dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+		printf("Drive reports diagnostics failure."
+				"This may indicate a drive\n");
+		printf("fault or invalid emulation."
+				"Contact drive vendor for information.\n");
+	}
+
+	rc = check_sata_dev_state();
+
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].revision,
+			 ATA_ID_FW_REV, sizeof(sata_dev_desc[dev].revision));
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].vendor,
+			 ATA_ID_PROD, sizeof(sata_dev_desc[dev].vendor));
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].product,
+			 ATA_ID_SERNO, sizeof(sata_dev_desc[dev].product));
+
+	sata_dev_desc[dev].lba = (u32) ata_dev->n_sectors;
+
+#ifdef CONFIG_LBA48
+	if (ata_dev->id[83] & (1 << 10)) {
+		sata_dev_desc[dev].lba48 = 1;
+	} else {
+		sata_dev_desc[dev].lba48 = 0;
+	}
+#endif
+
+	return 0;
+}
+
+static u8 ata_busy_wait(struct ata_port *ap,
+		unsigned int bits,unsigned int max)
+{
+	u8 status;
+
+	do {
+		udelay(10);
+		status = ata_check_status(ap);
+		max--;
+	} while (status != 0xff && (status & bits) && (max > 0));
+
+	return status;
+}
+
+static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id)
+{
+	struct ata_port *ap = pap;
+	unsigned int class = *p_class;
+	struct ata_taskfile tf;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1, tried_spinup = 0;
+	u8 status;
+	int rc;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_ID_ATA;
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+	/* Device presence detection is unreliable on some
+	 * controllers.  Always poll IDENTIFY if available.
+	 */
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	temp_n_block = 1;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+					sizeof(id[0]) * ATA_ID_WORDS, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	unsigned int id_cnt;
+
+	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
+		id[id_cnt] = le16_to_cpu(id[id_cnt]);
+
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	if (class == ATA_DEV_ATA) {
+		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
+			goto err_out;
+	} else {
+		if (ata_id_is_ata(id))
+			goto err_out;
+	}
+	if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+		tried_spinup = 1;
+		/*
+		 * Drive powered-up in standby mode, and requires a specific
+		 * SET_FEATURES spin-up subcommand before it will accept
+		 * anything other than the original IDENTIFY command.
+		 */
+		err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+		if (err_mask && id[2] != 0x738c) {
+			rc = -EIO;
+			reason = "SPINUP failed";
+			goto err_out;
+		}
+		/*
+		 * If the drive initially returned incomplete IDENTIFY info,
+		 * we now must reissue the IDENTIFY command.
+		 */
+		if (id[2] == 0x37c8)
+			goto retry;
+	}
+
+	if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
+		/*
+		 * The exact sequence expected by certain pre-ATA4 drives is:
+		 * SRST RESET
+		 * IDENTIFY (optional in early ATA)
+		 * INITIALIZE DEVICE PARAMETERS (later IDE and ATA)
+		 * anything else..
+		 * Some drives were very specific about that exact sequence.
+		 *
+		 * Note that ATA4 says lba is mandatory so the second check
+		 * shoud never trigger.
+		 */
+		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+			err_mask = ata_dev_init_params(dev, id[3], id[6]);
+			if (err_mask) {
+				rc = -EIO;
+				reason = "INIT_DEV_PARAMS failed";
+				goto err_out;
+			}
+
+			/* current CHS translation info (id[53-58]) might be
+			 * changed. reread the identify device info.
+			 */
+			flags &= ~ATA_READID_POSTRESET;
+			goto retry;
+		}
+	}
+
+	*p_class = class;
+	return 0;
+
+err_out:
+	return rc;
+}
+
+static u8 ata_wait_idle(struct ata_port *ap)
+{
+	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	return status;
+}
+
+static void ata_dev_select(struct ata_port *ap, unsigned int device,
+		unsigned int wait, unsigned int can_sleep)
+{
+	if (wait)
+		ata_wait_idle(ap);
+
+	ata_std_dev_select(ap, device);
+
+	if (wait)
+		ata_wait_idle(ap);
+}
+
+static void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+{
+	u8 tmp;
+
+	if (device == 0) {
+		tmp = ATA_DEVICE_OBS;
+	} else {
+		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+	}
+
+	writeb(tmp, ap->ioaddr.device_addr);
+
+	readb(ap->ioaddr.altstatus_addr);
+
+	udelay(1);
+}
+
+static int waiting_for_reg_state(volatile u8 *offset,
+				int timeout_msec,
+				u32 sign)
+{
+	int i;
+	u32 status;
+
+	for (i = 0; i < timeout_msec; i++) {
+		status = readl(offset);
+		if ((status & sign) != 0)
+			break;
+		msleep(1);
+	}
+
+	return (i < timeout_msec) ? 0 : -1;
+}
+
+static void ata_qc_reinit(struct ata_queued_cmd *qc)
+{
+	qc->dma_dir = DMA_NONE;
+	qc->flags = 0;
+	qc->nbytes = qc->extrabytes = qc->curbytes = 0;
+	qc->n_elem = 0;
+	qc->err_mask = 0;
+	qc->sect_size = ATA_SECT_SIZE;
+	qc->nbytes = ATA_SECT_SIZE * temp_n_block;
+
+	memset(&qc->tf, 0, sizeof(qc->tf));
+	qc->tf.ctl = 0;
+	qc->tf.device = ATA_DEVICE_OBS;
+
+	qc->result_tf.command = ATA_DRDY;
+	qc->result_tf.feature = 0;
+}
+
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+					unsigned int tag)
+{
+	if (tag < ATA_MAX_QUEUE)
+		return &ap->qcmd[tag];
+	return NULL;
+}
+
+static void __ata_port_freeze(struct ata_port *ap)
+{
+	printf("set port freeze.\n");
+	ap->pflags |= ATA_PFLAG_FROZEN;
+}
+
+static int ata_port_freeze(struct ata_port *ap)
+{
+	__ata_port_freeze(ap);
+	return 0;
+}
+
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout)
+{
+	struct ata_link *link = dev->link;
+	struct ata_port *ap = pap;
+	struct ata_queued_cmd *qc;
+	unsigned int tag, preempted_tag;
+	u32 preempted_sactive, preempted_qc_active;
+	int preempted_nr_active_links;
+	unsigned int err_mask;
+	int rc = 0;
+	u8 status;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 300000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	if (ap->pflags & ATA_PFLAG_FROZEN)
+		return AC_ERR_SYSTEM;
+
+	tag = ATA_TAG_INTERNAL;
+
+	if (test_and_set_bit(tag, &ap->qc_allocated)) {
+		rc = FALSE;
+		return rc;
+	}
+
+	qc = __ata_qc_from_tag(ap, tag);
+	qc->tag = tag;
+	qc->ap = ap;
+	qc->dev = dev;
+
+	ata_qc_reinit(qc);
+
+	preempted_tag = link->active_tag;
+	preempted_sactive = link->sactive;
+	preempted_qc_active = ap->qc_active;
+	preempted_nr_active_links = ap->nr_active_links;
+	link->active_tag = ATA_TAG_POISON;
+	link->sactive = 0;
+	ap->qc_active = 0;
+	ap->nr_active_links = 0;
+
+	qc->tf = *tf;
+	if (cdb)
+		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+	qc->dma_dir = dma_dir;
+	qc->private_data = 0;
+
+	ata_qc_issue(qc);
+
+	if (!timeout)
+		timeout = ata_probe_timeout * 1000 / HZ;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		printf("altstatus = 0x%x.\n",status);
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	if (waiting_for_reg_state(ap->ioaddr.altstatus_addr,1000,0x8)) {
+		u8 status = 0;
+		u8 errorStatus = 0;
+
+		status = readb( ap->ioaddr.altstatus_addr);
+		if ((status & 0x01) != 0) {
+			errorStatus = readb( ap->ioaddr.feature_addr);
+			if (errorStatus == 0x04 &&
+				qc->tf.command == ATA_CMD_PIO_READ_EXT){
+				printf("Hard Disk doesn't support LBA48\n");
+				dev_state = SATA_ERROR;
+				qc->err_mask |= AC_ERR_OTHER;
+				return qc->err_mask;
+			}
+		}
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	status = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	ata_pio_task(ap);
+
+	if (!rc) {
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			qc->err_mask |= AC_ERR_TIMEOUT;
+			ata_port_freeze(ap);
+		}
+	}
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (qc->result_tf.command & (ATA_ERR | ATA_DF))
+			qc->err_mask |= AC_ERR_DEV;
+
+		if (!qc->err_mask)
+			qc->err_mask |= AC_ERR_OTHER;
+
+		if (qc->err_mask & ~AC_ERR_OTHER)
+			qc->err_mask &= ~AC_ERR_OTHER;
+	}
+
+	*tf = qc->result_tf;
+	err_mask = qc->err_mask;
+	ata_qc_free(qc);
+	link->active_tag = preempted_tag;
+	link->sactive = preempted_sactive;
+	ap->qc_active = preempted_qc_active;
+	ap->nr_active_links = preempted_nr_active_links;
+
+	if (ap->flags & ATA_FLAG_DISABLED) {
+		err_mask |= AC_ERR_SYSTEM;
+		ap->flags &= ~ATA_FLAG_DISABLED;
+	}
+
+	return err_mask;
+}
+
+static void ata_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+	u8 prot = qc->tf.protocol;
+
+	if (ata_is_ncq(prot)) {
+		if (!link->sactive)
+			ap->nr_active_links++;
+		link->sactive |= 1 << qc->tag;
+	} else {
+		ap->nr_active_links++;
+		link->active_tag = qc->tag;
+	}
+
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+	ap->qc_active |= 1 << qc->tag;
+
+	if (qc->dev->flags & ATA_DFLAG_SLEEPING) {
+		msleep(1);
+		return;
+	}
+
+	qc->err_mask |= ata_qc_issue_prot(qc);
+	if (qc->err_mask)
+		goto err;
+
+	return;
+err:
+	ata_qc_complete(qc);
+}
+
+static unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+		switch (qc->tf.protocol) {
+		case ATA_PROT_PIO:
+		case ATA_PROT_NODATA:
+		case ATAPI_PROT_PIO:
+		case ATAPI_PROT_NODATA:
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			qc->tf.ctl |= ATA_NIEN;
+
+		ata_tf_to_host(ap, &qc->tf);
+
+		ap->hsm_task_state = HSM_ST;
+
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_pio_queue_task(ap, qc, 0);
+
+		break;
+
+	default:
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+static void ata_tf_to_host(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	ata_tf_load(ap, tf);
+	ata_exec_command(ap, tf);
+}
+
+static void ata_tf_load(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		if (ioaddr->ctl_addr)
+			writeb(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writeb(tf->hob_feature, ioaddr->feature_addr);
+		writeb(tf->hob_nsect, ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, ioaddr->lbah_addr);
+	}
+
+	if (is_addr) {
+		writeb(tf->feature, ioaddr->feature_addr);
+		writeb(tf->nsect, ioaddr->nsect_addr);
+		writeb(tf->lbal, ioaddr->lbal_addr);
+		writeb(tf->lbam, ioaddr->lbam_addr);
+		writeb(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE)
+		writeb(tf->device, ioaddr->device_addr);
+
+	ata_wait_idle(ap);
+}
+
+static void ata_exec_command(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	writeb(tf->command, ap->ioaddr.command_addr);
+
+	readb(ap->ioaddr.altstatus_addr);
+
+	udelay(1);
+}
+
+static void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay)
+{
+	ap->port_task_data = data;
+}
+
+static unsigned int ac_err_mask(u8 status)
+{
+	if (status & (ATA_BUSY | ATA_DRQ))
+		return AC_ERR_HSM;
+	if (status & (ATA_ERR | ATA_DF))
+		return AC_ERR_DEV;
+	return 0;
+}
+
+static unsigned int __ac_err_mask(u8 status)
+{
+	unsigned int mask = ac_err_mask(status);
+	if (mask == 0)
+		return AC_ERR_OTHER;
+	return mask;
+}
+
+static void ata_pio_task(struct ata_port *arg_ap)
+{
+	struct ata_port *ap = arg_ap;
+	struct ata_queued_cmd *qc = ap->port_task_data;
+	u8 status;
+	int poll_next;
+
+fsm_start:
+	/*
+	 * This is purely heuristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, queue delayed work.
+	 */
+	status = ata_busy_wait(ap, ATA_BUSY, 5);
+	if (status & ATA_BUSY) {
+		msleep(2);
+		status = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (status & ATA_BUSY) {
+			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+			return;
+		}
+	}
+
+	poll_next = ata_hsm_move(ap, qc, status, 1);
+
+	/* another command or interrupt handler
+	 * may be running at this point.
+	 */
+	if (poll_next)
+		goto fsm_start;
+}
+
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq)
+{
+	int poll_next;
+
+fsm_start:
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+		if ((status & ATA_DRQ) == 0) {
+			if (status & (ATA_ERR | ATA_DF)) {
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				qc->err_mask |= AC_ERR_HSM;
+			}
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Device should not ask for data transfer (DRQ=1)
+		 * when it finds something wrong.
+		 * We ignore DRQ here and stop the HSM by
+		 * changing hsm_task_state to HSM_ST_ERR and
+		 * let the EH abort the command or reset the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+				printf("DRQ=1 with device error, "
+					"dev_stat 0x%X\n", status);
+				qc->err_mask |= AC_ERR_HSM;
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+		}
+
+		if (qc->tf.protocol == ATA_PROT_PIO) {
+			/* PIO data out protocol.
+			 * send first data block.
+			 */
+			/* ata_pio_sectors() might change the state
+			 * to HSM_ST_LAST. so, the state is changed here
+			 * before ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST;
+			ata_pio_sectors(qc);
+		} else {
+			printf("protocol is not ATA_PROT_PIO \n");
+		}
+		break;
+
+	case HSM_ST:
+		if ((status & ATA_DRQ) == 0) {
+			if (status & (ATA_ERR | ATA_DF)) {
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this.
+				 * Phantom devices also trigger this
+				 * condition.  Mark hint.
+				 */
+				qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT;
+			}
+
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+		/* For PIO reads, some devices may ask for
+		 * data transfer (DRQ=1) alone with ERR=1.
+		 * We respect DRQ here and transfer one
+		 * block of junk data before changing the
+		 * hsm_task_state to HSM_ST_ERR.
+		 *
+		 * For PIO writes, ERR=1 DRQ=1 doesn't make
+		 * sense since the data block has been
+		 * transferred to the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			qc->err_mask |= AC_ERR_DEV;
+
+			if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+				ata_pio_sectors(qc);
+				status = ata_wait_idle(ap);
+			}
+
+			if (status & (ATA_BUSY | ATA_DRQ))
+				qc->err_mask |= AC_ERR_HSM;
+
+			/* ata_pio_sectors() might change the
+			 * state to HSM_ST_LAST. so, the state
+			 * is changed after ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ata_pio_sectors(qc);
+		if (ap->hsm_task_state == HSM_ST_LAST &&
+			(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+			status = ata_wait_idle(ap);
+			goto fsm_start;
+		}
+
+		poll_next = 1;
+		break;
+
+	case HSM_ST_LAST:
+		if (!ata_ok(status)) {
+			qc->err_mask |= __ac_err_mask(status);
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+
+	case HSM_ST_ERR:
+		/* make sure qc->err_mask is available to
+		 * know what's wrong and recover
+		 */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+	default:
+		poll_next = 0;
+	}
+
+	return poll_next;
+}
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap;
+	ap = pap;
+	qc->pdata = ap->pdata;
+
+	ata_pio_sector(qc);
+
+	readb(qc->ap->ioaddr.altstatus_addr);
+	udelay(1);
+}
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	struct ata_port *ap = qc->ap;
+	unsigned int offset;
+	unsigned char *buf;
+	char temp_data_buf[512];
+
+	if (qc->curbytes == qc->nbytes - qc->sect_size)
+		ap->hsm_task_state = HSM_ST_LAST;
+
+	offset = qc->curbytes;
+
+	switch (qc->tf.command) {
+	case ATA_CMD_ID_ATA:
+		buf = (unsigned char *)&ata_device.id[0];
+		break;
+	case ATA_CMD_PIO_READ_EXT:
+	case ATA_CMD_PIO_READ:
+	case ATA_CMD_PIO_WRITE_EXT:
+	case ATA_CMD_PIO_WRITE:
+		buf = qc->pdata + offset;
+		break;
+	default:
+		buf = (unsigned char *)&temp_data_buf[0];
+	}
+
+	ata_mmio_data_xfer(qc->dev, buf, qc->sect_size, do_write);
+
+	qc->curbytes += qc->sect_size;
+
+}
+
+static void ata_mmio_data_xfer(struct ata_device *dev, unsigned char *buf,
+				unsigned int buflen, int do_write)
+{
+	struct ata_port *ap = pap;
+	void __iomem *data_addr = ap->ioaddr.data_addr;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *)buf;
+	unsigned int i = 0;
+
+	udelay(100);
+	if (do_write) {
+		for (i = 0; i < words; i++)
+			writew(le16_to_cpu(buf16[i]), data_addr);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(readw(data_addr));
+	}
+
+	if (buflen & 0x01) {
+		__le16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (do_write) {
+			memcpy(align_buf, trailing_buf, 1);
+			writew(le16_to_cpu(align_buf[0]), data_addr);
+		} else {
+			align_buf[0] = cpu_to_le16(readw(data_addr));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
+}
+
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (in_wq) {
+		/* EH might have kicked in while host lock is
+		 * released.
+		 */
+		qc = &ap->qcmd[qc->tag];
+		if (qc) {
+			if (!(qc->err_mask & AC_ERR_HSM)) {
+				ata_irq_on(ap);
+				ata_qc_complete(qc);
+			} else {
+				ata_port_freeze(ap);
+			}
+		}
+	} else {
+		if (!(qc->err_mask & AC_ERR_HSM)) {
+			ata_qc_complete(qc);
+		} else {
+			ata_port_freeze(ap);
+		}
+	}
+}
+
+static u8 ata_irq_on(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 tmp;
+
+	ap->ctl &= ~ATA_NIEN;
+	ap->last_ctl = ap->ctl;
+
+	if (ioaddr->ctl_addr)
+		writeb(ap->ctl, ioaddr->ctl_addr);
+
+	tmp = ata_wait_idle(ap);
+
+	return tmp;
+}
+
+static unsigned int ata_tag_internal(unsigned int tag)
+{
+	return tag == ATA_MAX_QUEUE - 1;
+}
+
+static void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_device *dev = qc->dev;
+	if (qc->err_mask)
+		qc->flags |= ATA_QCFLAG_FAILED;
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (!ata_tag_internal(qc->tag)) {
+			fill_result_tf(qc);
+			return;
+		}
+	}
+	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+		fill_result_tf(qc);
+
+	/* Some commands need post-processing after successful
+	 * completion.
+	 */
+	switch (qc->tf.command) {
+	case ATA_CMD_SET_FEATURES:
+		if (qc->tf.feature != SETFEATURES_WC_ON &&
+				qc->tf.feature != SETFEATURES_WC_OFF)
+			break;
+	case ATA_CMD_INIT_DEV_PARAMS:
+	case ATA_CMD_SET_MULTI:
+		break;
+
+	case ATA_CMD_SLEEP:
+		dev->flags |= ATA_DFLAG_SLEEPING;
+		break;
+	}
+
+	__ata_qc_complete(qc);
+}
+
+static void fill_result_tf(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	qc->result_tf.flags = qc->tf.flags;
+	ata_tf_read(ap, &qc->result_tf);
+}
+
+static void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->command = ata_check_status(ap);
+	tf->feature = readb(ioaddr->error_addr);
+	tf->nsect = readb(ioaddr->nsect_addr);
+	tf->lbal = readb(ioaddr->lbal_addr);
+	tf->lbam = readb(ioaddr->lbam_addr);
+	tf->lbah = readb(ioaddr->lbah_addr);
+	tf->device = readb(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		if (ioaddr->ctl_addr) {
+			writeb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+
+			tf->hob_feature = readb(ioaddr->error_addr);
+			tf->hob_nsect = readb(ioaddr->nsect_addr);
+			tf->hob_lbal = readb(ioaddr->lbal_addr);
+			tf->hob_lbam = readb(ioaddr->lbam_addr);
+			tf->hob_lbah = readb(ioaddr->lbah_addr);
+
+			writeb(tf->ctl, ioaddr->ctl_addr);
+			ap->last_ctl = tf->ctl;
+		} else {
+			printf("sata_dwc warnning register read.\n");
+		}
+	}
+}
+
+static void __ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+
+	link->active_tag = ATA_TAG_POISON;
+	ap->nr_active_links--;
+
+	if (qc->flags & ATA_QCFLAG_CLEAR_EXCL && ap->excl_link == link)
+		ap->excl_link = NULL;
+
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	ap->qc_active &= ~(1 << qc->tag);
+}
+
+static void ata_qc_free(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int tag;
+	qc->flags = 0;
+	tag = qc->tag;
+	if (tag < ATA_MAX_QUEUE) {
+		qc->tag = ATA_TAG_POISON;
+		clear_bit(tag, &ap->qc_allocated);
+	}
+}
+
+static int check_sata_dev_state(void)
+{
+	unsigned long datalen;
+	unsigned char *pdata;
+	int ret = 0;
+	int i = 0;
+	char temp_data_buf[512];
+
+	while (1) {
+		udelay (10000);
+
+		pdata = (unsigned char*)&temp_data_buf[0];
+		datalen = 512;
+
+		ret = ata_dev_read_sectors(pdata, datalen, 0, 1);
+
+		if (ret == TRUE)
+			break;
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+			dev_state = SATA_NODEVICE;
+			return FALSE;
+		}
+
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	dev_state = SATA_READY;
+
+	return TRUE;
+}
+
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+				u8 enable, u8 feature)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = enable;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = feature;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	return err_mask;
+}
+
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+				u16 heads, u16 sectors)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+		return AC_ERR_INVALID;
+
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
+		err_mask = 0;
+
+	return err_mask;
+}
+
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SATA_MAX_READ_BLK 0xFF
+#else
+#define SATA_MAX_READ_BLK 0xFFFF
+#endif
+
+ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	ulong start,blks, buf_addr;
+	unsigned short smallblks;
+	unsigned long datalen;
+	unsigned char *pdata;
+	device &= 0xff;
+
+	u32 block = 0;
+	u32 n_block = 0;
+
+	if (dev_state != SATA_READY)
+		return 0;
+
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	do {
+		pdata = (unsigned char *)buf_addr;
+		if (blks > SATA_MAX_READ_BLK) {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_READ_BLK;
+			smallblks = SATA_MAX_READ_BLK;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += SATA_MAX_READ_BLK;
+			blks -= SATA_MAX_READ_BLK;
+		} else {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_READ_BLK;
+			datalen = sata_dev_desc[device].blksz * blks;
+			smallblks = (unsigned short)blks;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += blks;
+			blks = 0;
+		}
+
+		if (ata_dev_read_sectors(pdata, datalen, block, n_block) != TRUE) {
+			printf("sata_dwc : Hard disk read error.\n");
+			blkcnt -= blks;
+			break;
+		}
+		buf_addr += datalen;
+	} while (blks != 0);
+
+	return (blkcnt);
+}
+
+static int ata_dev_read_sectors(unsigned char *pdata, unsigned long datalen,
+						u32 block, u32 n_block)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	if (dev_state == SATA_ERROR)
+		return FALSE;
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	ap->pdata = pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	temp_n_block = n_block;
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_READ_EXT;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else
+	tf.command = ATA_CMD_PIO_READ;
+	tf.flags |= ATA_TFLAG_LBA ;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully@least once.
+	 */
+	may_fallback = 0;
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return TRUE;
+
+err_out:
+	printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return FALSE;
+}
+
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SATA_MAX_WRITE_BLK 0xFF
+#else
+#define SATA_MAX_WRITE_BLK 0xFFFF
+#endif
+
+ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	ulong start,blks, buf_addr;
+	unsigned short smallblks;
+	unsigned long datalen;
+	unsigned char *pdata;
+	device &= 0xff;
+
+
+	u32 block = 0;
+	u32 n_block = 0;
+
+	if (dev_state != SATA_READY)
+		return 0;
+
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	do {
+		pdata = (unsigned char *)buf_addr;
+		if (blks > SATA_MAX_WRITE_BLK) {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_WRITE_BLK;
+			smallblks = SATA_MAX_WRITE_BLK;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += SATA_MAX_WRITE_BLK;
+			blks -= SATA_MAX_WRITE_BLK;
+		} else {
+			datalen = sata_dev_desc[device].blksz * blks;
+			smallblks = (unsigned short)blks;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += blks;
+			blks = 0;
+		}
+
+		if (ata_dev_write_sectors(pdata, datalen, block, n_block) != TRUE) {
+			printf("sata_dwc : Hard disk read error.\n");
+			blkcnt -= blks;
+			break;
+		}
+		buf_addr += datalen;
+	} while (blks != 0);
+
+	return (blkcnt);
+}
+
+static int ata_dev_write_sectors(unsigned char* pdata, unsigned long datalen,
+						u32 block, u32 n_block)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	if (dev_state == SATA_ERROR)
+		return FALSE;
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	ap->pdata = pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	temp_n_block = n_block;
+
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_WRITE_EXT;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48 | ATA_TFLAG_WRITE;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else
+	tf.command = ATA_CMD_PIO_WRITE;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_WRITE;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return TRUE;
+
+err_out:
+	printf("failed to WRITE SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return FALSE;
+}
diff --git a/drivers/block/sata_dwc.h b/drivers/block/sata_dwc.h
new file mode 100644
index 0000000..6259804
--- /dev/null
+++ b/drivers/block/sata_dwc.h
@@ -0,0 +1,463 @@
+/*
+ * sata_dwc.h
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under  the terms of  the GNU
+ * General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 04-17-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+
+#ifndef _SATA_DWC_H_
+#define _SATA_DWC_H_
+
+#define HZ 100
+
+#define READ 0
+#define WRITE 1
+
+enum {
+	ATA_READID_POSTRESET	= (1 << 0),
+
+	ATA_DNXFER_PIO		= 0,
+	ATA_DNXFER_DMA		= 1,
+	ATA_DNXFER_40C		= 2,
+	ATA_DNXFER_FORCE_PIO	= 3,
+	ATA_DNXFER_FORCE_PIO0	= 4,
+
+	ATA_DNXFER_QUIET	= (1 << 31),
+};
+
+enum hsm_task_states {
+	HSM_ST_IDLE,
+	HSM_ST_FIRST,
+	HSM_ST,
+	HSM_ST_LAST,
+	HSM_ST_ERR,
+};
+
+#define	ATA_SHORT_PAUSE		((HZ >> 6) + 1)
+
+struct ata_queued_cmd {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
+
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
+	unsigned long		flags;
+	unsigned int		tag;
+	unsigned int		n_elem;
+
+	int			dma_dir;
+
+	unsigned int		sect_size;
+
+	unsigned int		nbytes;
+	unsigned int		extrabytes;
+	unsigned int		curbytes;
+
+	unsigned int		err_mask;
+	struct ata_taskfile	result_tf;
+
+	void			*private_data;
+	void			*lldd_task;
+	unsigned char		*pdata;
+};
+
+typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+
+#define ATA_TAG_POISON	0xfafbfcfdU
+
+enum {
+	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,
+	ATA_MAX_PORTS		= 8,
+	ATA_DEF_QUEUE		= 1,
+	ATA_MAX_QUEUE		= 32,
+	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
+	ATA_MAX_BUS		= 2,
+	ATA_DEF_BUSY_WAIT	= 10000,
+
+	ATAPI_MAX_DRAIN		= 16 << 10,
+
+	ATA_SHT_EMULATED	= 1,
+	ATA_SHT_CMD_PER_LUN	= 1,
+	ATA_SHT_THIS_ID		= -1,
+	ATA_SHT_USE_CLUSTERING	= 1,
+
+	ATA_DFLAG_LBA		= (1 << 0),
+	ATA_DFLAG_LBA48		= (1 << 1),
+	ATA_DFLAG_CDB_INTR	= (1 << 2),
+	ATA_DFLAG_NCQ		= (1 << 3),
+	ATA_DFLAG_FLUSH_EXT	= (1 << 4),
+	ATA_DFLAG_ACPI_PENDING 	= (1 << 5),
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6),
+	ATA_DFLAG_AN		= (1 << 7),
+	ATA_DFLAG_HIPM		= (1 << 8),
+	ATA_DFLAG_DIPM		= (1 << 9),
+	ATA_DFLAG_DMADIR	= (1 << 10),
+	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
+
+	ATA_DFLAG_PIO		= (1 << 12),
+	ATA_DFLAG_NCQ_OFF	= (1 << 13),
+	ATA_DFLAG_SPUNDOWN	= (1 << 14),
+	ATA_DFLAG_SLEEPING	= (1 << 15),
+	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16),
+	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
+
+	ATA_DFLAG_DETACH	= (1 << 24),
+	ATA_DFLAG_DETACHED	= (1 << 25),
+
+	ATA_LFLAG_HRST_TO_RESUME	= (1 << 0),
+	ATA_LFLAG_SKIP_D2H_BSY		= (1 << 1),
+	ATA_LFLAG_NO_SRST		= (1 << 2),
+	ATA_LFLAG_ASSUME_ATA		= (1 << 3),
+	ATA_LFLAG_ASSUME_SEMB		= (1 << 4),
+	ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
+	ATA_LFLAG_NO_RETRY		= (1 << 5),
+	ATA_LFLAG_DISABLED		= (1 << 6),
+
+	ATA_FLAG_SLAVE_POSS	= (1 << 0),
+	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LEGACY	= (1 << 2),
+	ATA_FLAG_MMIO		= (1 << 3),
+	ATA_FLAG_SRST		= (1 << 4),
+	ATA_FLAG_SATA_RESET	= (1 << 5),
+	ATA_FLAG_NO_ATAPI	= (1 << 6),
+	ATA_FLAG_PIO_DMA	= (1 << 7),
+	ATA_FLAG_PIO_LBA48	= (1 << 8),
+	ATA_FLAG_PIO_POLLING	= (1 << 9),
+	ATA_FLAG_NCQ		= (1 << 10),
+	ATA_FLAG_DEBUGMSG	= (1 << 13),
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15),
+	ATA_FLAG_NO_IORDY	= (1 << 16),
+	ATA_FLAG_ACPI_SATA	= (1 << 17),
+	ATA_FLAG_AN		= (1 << 18),
+	ATA_FLAG_PMP		= (1 << 19),
+	ATA_FLAG_IPM		= (1 << 20),
+
+	ATA_FLAG_DISABLED	= (1 << 23),
+
+	ATA_PFLAG_EH_PENDING		= (1 << 0),
+	ATA_PFLAG_EH_IN_PROGRESS	= (1 << 1),
+	ATA_PFLAG_FROZEN		= (1 << 2),
+	ATA_PFLAG_RECOVERED		= (1 << 3),
+	ATA_PFLAG_LOADING		= (1 << 4),
+	ATA_PFLAG_UNLOADING		= (1 << 5),
+	ATA_PFLAG_SCSI_HOTPLUG		= (1 << 6),
+	ATA_PFLAG_INITIALIZING		= (1 << 7),
+	ATA_PFLAG_RESETTING		= (1 << 8),
+	ATA_PFLAG_SUSPENDED		= (1 << 17),
+	ATA_PFLAG_PM_PENDING		= (1 << 18),
+
+	ATA_QCFLAG_ACTIVE	= (1 << 0),
+	ATA_QCFLAG_DMAMAP	= (1 << 1),
+	ATA_QCFLAG_IO		= (1 << 3),
+	ATA_QCFLAG_RESULT_TF	= (1 << 4),
+	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5),
+	ATA_QCFLAG_QUIET	= (1 << 6),
+
+	ATA_QCFLAG_FAILED	= (1 << 16),
+	ATA_QCFLAG_SENSE_VALID	= (1 << 17),
+	ATA_QCFLAG_EH_SCHEDULED	= (1 << 18),
+
+	ATA_HOST_SIMPLEX	= (1 << 0),
+	ATA_HOST_STARTED	= (1 << 1),
+
+	ATA_TMOUT_BOOT			= 30 * 100,
+	ATA_TMOUT_BOOT_QUICK		= 7 * 100,
+	ATA_TMOUT_INTERNAL		= 30 * 100,
+	ATA_TMOUT_INTERNAL_QUICK	= 5 * 100,
+
+	/* FIXME: GoVault needs 2s but we can't afford that without
+	 * parallel probing.  800ms is enough for iVDR disk
+	 * HHD424020F7SV00.  Increase to 2secs when parallel probing
+	 * is in place.
+	 */
+	ATA_TMOUT_FF_WAIT	= 4 * 100 / 5,
+
+	BUS_UNKNOWN		= 0,
+	BUS_DMA			= 1,
+	BUS_IDLE		= 2,
+	BUS_NOINTR		= 3,
+	BUS_NODATA		= 4,
+	BUS_TIMER		= 5,
+	BUS_PIO			= 6,
+	BUS_EDD			= 7,
+	BUS_IDENTIFY		= 8,
+	BUS_PACKET		= 9,
+
+	PORT_UNKNOWN		= 0,
+	PORT_ENABLED		= 1,
+	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_NR_PIO_MODES	= 7,
+	ATA_NR_MWDMA_MODES	= 5,
+	ATA_NR_UDMA_MODES	= 8,
+
+	ATA_SHIFT_PIO		= 0,
+	ATA_SHIFT_MWDMA		= ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
+	ATA_SHIFT_UDMA		= ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
+
+	ATA_DMA_PAD_SZ		= 4,
+
+	ATA_ERING_SIZE		= 32,
+
+	ATA_DEFER_LINK		= 1,
+	ATA_DEFER_PORT		= 2,
+
+	ATA_EH_DESC_LEN		= 80,
+
+	ATA_EH_REVALIDATE	= (1 << 0),
+	ATA_EH_SOFTRESET	= (1 << 1),
+	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_ENABLE_LINK	= (1 << 3),
+	ATA_EH_LPM		= (1 << 4),
+
+	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+	ATA_EHI_HOTPLUGGED	= (1 << 0),
+	ATA_EHI_RESUME_LINK	= (1 << 1),
+	ATA_EHI_NO_AUTOPSY	= (1 << 2),
+	ATA_EHI_QUIET		= (1 << 3),
+
+	ATA_EHI_DID_SOFTRESET	= (1 << 16),
+	ATA_EHI_DID_HARDRESET	= (1 << 17),
+	ATA_EHI_PRINTINFO	= (1 << 18),
+	ATA_EHI_SETMODE		= (1 << 19),
+	ATA_EHI_POST_SETMODE	= (1 << 20),
+
+	ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+	ATA_EH_MAX_TRIES	= 5,
+
+	ATA_PROBE_MAX_TRIES	= 3,
+	ATA_EH_DEV_TRIES	= 3,
+	ATA_EH_PMP_TRIES	= 5,
+	ATA_EH_PMP_LINK_TRIES	= 3,
+
+	SATA_PMP_SCR_TIMEOUT	= 250,
+
+	/* Horkage types. May be set by libata or controller on drives
+	(some horkage may be drive/controller pair dependant */
+
+	ATA_HORKAGE_DIAGNOSTIC	= (1 << 0),
+	ATA_HORKAGE_NODMA	= (1 << 1),
+	ATA_HORKAGE_NONCQ	= (1 << 2),
+	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),
+	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),
+	ATA_HORKAGE_SKIP_PM	= (1 << 5),
+	ATA_HORKAGE_HPA_SIZE	= (1 << 6),
+	ATA_HORKAGE_IPM		= (1 << 7),
+	ATA_HORKAGE_IVB		= (1 << 8),
+	ATA_HORKAGE_STUCK_ERR	= (1 << 9),
+
+	ATA_DMA_MASK_ATA	= (1 << 0),
+	ATA_DMA_MASK_ATAPI	= (1 << 1),
+	ATA_DMA_MASK_CFA	= (1 << 2),
+
+	ATAPI_READ		= 0,
+	ATAPI_WRITE		= 1,
+	ATAPI_READ_CD		= 2,
+	ATAPI_PASS_THRU		= 3,
+	ATAPI_MISC		= 4,
+};
+
+enum ata_completion_errors {
+	AC_ERR_DEV		= (1 << 0),
+	AC_ERR_HSM		= (1 << 1),
+	AC_ERR_TIMEOUT		= (1 << 2),
+	AC_ERR_MEDIA		= (1 << 3),
+	AC_ERR_ATA_BUS		= (1 << 4),
+	AC_ERR_HOST_BUS		= (1 << 5),
+	AC_ERR_SYSTEM		= (1 << 6),
+	AC_ERR_INVALID		= (1 << 7),
+	AC_ERR_OTHER		= (1 << 8),
+	AC_ERR_NODEV_HINT	= (1 << 9),
+	AC_ERR_NCQ		= (1 << 10),
+};
+
+enum ata_xfer_mask {
+	ATA_MASK_PIO	= ((1LU << ATA_NR_PIO_MODES) - 1) << ATA_SHIFT_PIO,
+	ATA_MASK_MWDMA	= ((1LU << ATA_NR_MWDMA_MODES) - 1) << ATA_SHIFT_MWDMA,
+	ATA_MASK_UDMA	= ((1LU << ATA_NR_UDMA_MODES) - 1) << ATA_SHIFT_UDMA,
+};
+
+struct ata_port_info {
+	struct scsi_host_template	*sht;
+	unsigned long			flags;
+	unsigned long			link_flags;
+	unsigned long			pio_mask;
+	unsigned long			mwdma_mask;
+	unsigned long			udma_mask;
+	const struct ata_port_operations *port_ops;
+	void				*private_data;
+};
+
+struct ata_ioports {
+	void __iomem		*cmd_addr;
+	void __iomem		*data_addr;
+	void __iomem		*error_addr;
+	void __iomem		*feature_addr;
+	void __iomem		*nsect_addr;
+	void __iomem		*lbal_addr;
+	void __iomem		*lbam_addr;
+	void __iomem		*lbah_addr;
+	void __iomem		*device_addr;
+	void __iomem		*status_addr;
+	void __iomem		*command_addr;
+	void __iomem		*altstatus_addr;
+	void __iomem		*ctl_addr;
+	void __iomem		*bmdma_addr;
+	void __iomem		*scr_addr;
+};
+
+struct ata_host {
+	void __iomem * const	*iomap;
+	unsigned int		n_ports;
+	void			*private_data;
+	const struct ata_port_operations *ops;
+	unsigned long		flags;
+	struct ata_port		*simplex_claimed;
+	struct ata_port		*ports[0];
+};
+
+struct ata_port_stats {
+	unsigned long		unhandled_irq;
+	unsigned long		idle_irq;
+	unsigned long		rw_reqbuf;
+};
+
+struct ata_device {
+	struct ata_link		*link;
+	unsigned int		devno;
+	unsigned long		flags;
+	unsigned int		horkage;
+	struct scsi_device	*sdev;
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	union acpi_object	*gtf_cache;
+#endif
+	u64			n_sectors;
+	unsigned int		class;
+
+	union {
+		u16		id[ATA_ID_WORDS];
+		u32		gscr[SATA_PMP_GSCR_DWORDS];
+	};
+
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;
+
+	unsigned int		multi_count;
+	unsigned int		max_sectors;
+	unsigned int		cdb_len;
+
+	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
+	unsigned long		udma_mask;
+
+	u16			cylinders;
+	u16			heads;
+	u16			sectors;
+
+	int			spdn_cnt;
+};
+
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL = 0,
+	DMA_TO_DEVICE = 1,
+	DMA_FROM_DEVICE = 2,
+	DMA_NONE = 3,
+};
+
+struct ata_link {
+	struct ata_port		*ap;
+	int			pmp;
+	unsigned int		active_tag;
+	u32			sactive;
+
+	unsigned int		flags;
+
+	unsigned int		hw_sata_spd_limit;
+	unsigned int		sata_spd_limit;
+	unsigned int		sata_spd;
+
+	struct ata_device	device[2];
+};
+
+struct ata_port {
+	unsigned long		flags;
+	unsigned int		pflags;
+	unsigned int		print_id;
+	unsigned int		port_no;
+
+	struct ata_ioports	ioaddr;
+
+	u8			ctl;
+	u8			last_ctl;
+	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
+	unsigned int		udma_mask;
+	unsigned int		cbl;
+
+	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+	unsigned long		qc_allocated;
+	unsigned int		qc_active;
+	int			nr_active_links;
+
+	struct ata_link		link;
+
+	int			nr_pmp_links;
+	struct ata_link		*pmp_link;
+	struct ata_link		*excl_link;
+
+	struct ata_port_stats	stats;
+	struct ata_host		*host;
+
+	struct device		*dev;
+	void			*port_task_data;
+
+	unsigned int		hsm_task_state;
+
+	u32			msg_enable;
+	void			*private_data;
+	unsigned char		*pdata;
+};
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif
diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h
index d814012..d9b73dc 100644
--- a/include/configs/canyonlands.h
+++ b/include/configs/canyonlands.h
@@ -454,6 +454,7 @@
  #define CONFIG_CMD_SDRAM
  #define CONFIG_CMD_SNTP
  #define CONFIG_CMD_USB
+#define CONFIG_CMD_SATA
  #elif defined(CONFIG_GLACIER)
  #define CONFIG_CMD_DATE
  #define CONFIG_CMD_DTT
@@ -517,6 +518,21 @@
  #endif /* CONFIG_460GT */

  /*-----------------------------------------------------------------------
+ * S-ATA driver setup
+ *----------------------------------------------------------------------*/
+#define CONFIG_SATA_DWC
+
+#ifdef CONFIG_SATA_DWC
+#define CONFIG_LIBATA
+
+#define SATA_BASE_ADDR		0xe20d1000	/* PPC460EX SATA Base Address */
+#define SATA_DMA_REG_ADDR	0xe20d0800	/* PPC460EX SATA Base Address */
+#define CONFIG_SYS_SATA_MAX_DEVICE	1	/* SATA MAX DEVICE */
+/* Convert sectorsize to wordsize */
+#define ATA_SECTOR_WORDS (ATA_SECT_SIZE/2)
+#endif
+
+/*-----------------------------------------------------------------------
   * External Bus Controller (EBC) Setup
   *----------------------------------------------------------------------*/

-- 
1.6.2.1


Regards,
Kazuaki Ichinohe.


Kazuaki Ichinohe wrote:
> Hello Denk,
> 
> After confirming operation, I'll send sata_dwc.c with cmd_sata.c again.
> 
> Regards,
> Kazuaki Ichinohe
> 

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-04-17  7:31               ` Kazuaki Ichinohe
@ 2009-04-27  1:53                 ` Kazuaki Ichinohe
  2009-04-27  7:42                   ` Stefan Roese
  2009-04-29  6:58                   ` Stefan Roese
  0 siblings, 2 replies; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-04-27  1:53 UTC (permalink / raw)
  To: u-boot

Hello Denk, Stefan,

I sent the SATA patch mail on April 17.
However, the following content is not confirmed, and there is not a reply either.
Could you confirm it?
I re-send the SATA driver patch.
---

This patch adds a SATA harddisk driver for the canyonlands.
This patch is kernel driver's porting.
This pach corresponded to not cmd_scsi but cmd_sata.


[environment variable, boot script]
setenv bootargs root=/dev/sda7 rw
setenv bootargs ${bootargs} console=ttyS0,115200
ext2load sata 0:2 0x400000 /canyonlands/uImage
ext2load sata 0:2 0x800000 /canyonlands/canyonlands.dtb
fdt addr 0x800000 0x4000
bootm 0x400000 - 0x800000

If you drive SATA-2 disk on Canyonlands, you must change parts from
PI2PCIE212 to PI2PCIE2212 on U25. We confirmed to boot by using following disk.

1.Vender: Fujitsu Type: MHW2040BS
2.Vender: Fujitsu Type: MHW2060BK
3.Vendor: HAGIWARA SYS-COM:HFD25S-032GT
4.Vender: WesternDigital Type: WD3200BJKT (CONFIG_LBA48 required)
5.Vender: WesternDigital Type: WD3200BEVT (CONFIG_LBA48 required)
6.Vender: hitachi Type: HTS543232L9A300 (CONFIG_LBA48 required)
7.Vender: Seagate Type: ST31000333AS (CONFIG_LBA48 required)
8.Vender: Transcend Type: TS32GSSD25S-M
9.Vender: MTRON Type: MSD-SATA1525-016

Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>
---

[patch]
---

   drivers/block/Makefile        |    1 +
   drivers/block/sata_dwc.c      | 2110 +++++++++++++++++++++++++++++++++++++++++
   drivers/block/sata_dwc.h      |  463 +++++++++
   include/configs/canyonlands.h |   16 +
   4 files changed, 2590 insertions(+), 0 deletions(-)
   create mode 100644 drivers/block/sata_dwc.c
   create mode 100644 drivers/block/sata_dwc.h

diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index eccefc1..e0af40e 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -35,6 +35,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
   COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
   COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
   COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

   COBJS	:= $(COBJS-y)
   SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/block/sata_dwc.c b/drivers/block/sata_dwc.c
new file mode 100644
index 0000000..91211bb
--- /dev/null
+++ b/drivers/block/sata_dwc.c
@@ -0,0 +1,2110 @@
+/*
+ * sata_dwc.c
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU
+ * General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 04-17-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <ata.h>
+#include <linux/ctype.h>
+
+#include "sata_dwc.h"
+
+#define DMA_NUM_CHANS			1
+#define DMA_NUM_CHAN_REGS		8
+
+#define AHB_DMA_BRST_DFLT		16
+
+struct dmareg {
+	u32 low;
+	u32 high;
+};
+
+struct dma_chan_regs {
+	struct dmareg sar;
+	struct dmareg dar;
+	struct dmareg llp;
+	struct dmareg ctl;
+	struct dmareg sstat;
+	struct dmareg dstat;
+	struct dmareg sstatar;
+	struct dmareg dstatar;
+	struct dmareg cfg;
+	struct dmareg sgr;
+	struct dmareg dsr;
+};
+
+struct dma_interrupt_regs {
+	struct dmareg tfr;
+	struct dmareg block;
+	struct dmareg srctran;
+	struct dmareg dsttran;
+	struct dmareg error;
+};
+
+struct ahb_dma_regs {
+	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];
+	struct dma_interrupt_regs	interrupt_raw;
+	struct dma_interrupt_regs	interrupt_status;
+	struct dma_interrupt_regs	interrupt_mask;
+	struct dma_interrupt_regs	interrupt_clear;
+	struct dmareg			statusInt;
+	struct dmareg			rq_srcreg;
+	struct dmareg			rq_dstreg;
+	struct dmareg			rq_sgl_srcreg;
+	struct dmareg			rq_sgl_dstreg;
+	struct dmareg			rq_lst_srcreg;
+	struct dmareg			rq_lst_dstreg;
+	struct dmareg			dma_cfg;
+	struct dmareg			dma_chan_en;
+	struct dmareg			dma_id;
+	struct dmareg			dma_test;
+	struct dmareg			res1;
+	struct dmareg			res2;
+	/* DMA Comp Params
+	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
+	 * Param 4 = dma_param[2] ...
+	 */
+	struct dmareg			dma_params[6];
+};
+
+#define DMA_EN			0x00000001
+#define DMA_DI			0x00000000
+#define DMA_CHANNEL(ch)		(0x00000001 << (ch))
+#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |	\
+				((0x000000001 << (ch)) << 8))
+#define DMA_DISABLE_CHAN(ch)	(0x00000000 | 	\
+				((0x000000001 << (ch)) << 8))
+
+#define SATA_DWC_MAX_PORTS	1
+#define SATA_DWC_SCR_OFFSET	0x24
+#define SATA_DWC_REG_OFFSET	0x64
+
+struct sata_dwc_regs {
+	u32 fptagr;
+	u32 fpbor;
+	u32 fptcr;
+	u32 dmacr;
+	u32 dbtsr;
+	u32 intpr;
+	u32 intmr;
+	u32 errmr;
+	u32 llcr;
+	u32 phycr;
+	u32 physr;
+	u32 rxbistpd;
+	u32 rxbistpd1;
+	u32 rxbistpd2;
+	u32 txbistpd;
+	u32 txbistpd1;
+	u32 txbistpd2;
+	u32 bistcr;
+	u32 bistfctr;
+	u32 bistsr;
+	u32 bistdecr;
+	u32 res[15];
+	u32 testr;
+	u32 versionr;
+	u32 idr;
+	u32 unimpl[192];
+	u32 dmadr[256];
+};
+
+#define SATA_DWC_TXFIFO_DEPTH		0x01FF
+#define SATA_DWC_RXFIFO_DEPTH		0x01FF
+
+#define SATA_DWC_DBTSR_MWR(size)	((size / 4) & SATA_DWC_TXFIFO_DEPTH)
+#define SATA_DWC_DBTSR_MRD(size)	(((size / 4) &	\
+					SATA_DWC_RXFIFO_DEPTH) << 16)
+#define SATA_DWC_INTPR_DMAT		0x00000001
+#define SATA_DWC_INTPR_NEWFP		0x00000002
+#define SATA_DWC_INTPR_PMABRT		0x00000004
+#define SATA_DWC_INTPR_ERR		0x00000008
+#define SATA_DWC_INTPR_NEWBIST		0x00000010
+#define SATA_DWC_INTPR_IPF		0x10000000
+#define SATA_DWC_INTMR_DMATM		0x00000001
+#define SATA_DWC_INTMR_NEWFPM		0x00000002
+#define SATA_DWC_INTMR_PMABRTM		0x00000004
+#define SATA_DWC_INTMR_ERRM		0x00000008
+#define SATA_DWC_INTMR_NEWBISTM		0x00000010
+
+#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
+#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
+
+#define SATA_DWC_QCMD_MAX	32
+
+#define SATA_DWC_SERROR_ERR_BITS	0x0FFF0F03
+
+#define HSDEVP_FROM_AP(ap)	(struct sata_dwc_device_port*)	\
+				(ap)->private_data
+
+struct sata_dwc_device {
+	struct device		*dev;
+	struct ata_probe_ent	*pe;
+	struct ata_host		*host;
+	u8			*reg_base;
+	struct sata_dwc_regs	*sata_dwc_regs;
+	int			irq_dma;
+};
+
+struct sata_dwc_device_port {
+	struct sata_dwc_device	*hsdev;
+	int			cmd_issued[SATA_DWC_QCMD_MAX];
+	u32			dma_chan[SATA_DWC_QCMD_MAX];
+	int			dma_pending[SATA_DWC_QCMD_MAX];
+};
+
+enum {
+	SATA_DWC_CMD_ISSUED_NOT		= 0,
+	SATA_DWC_CMD_ISSUED_PEND	= 1,
+	SATA_DWC_CMD_ISSUED_EXEC	= 2,
+	SATA_DWC_CMD_ISSUED_NODATA	= 3,
+
+	SATA_DWC_DMA_PENDING_NONE	= 0,
+	SATA_DWC_DMA_PENDING_TX		= 1,
+	SATA_DWC_DMA_PENDING_RX		= 2,
+};
+
+#define msleep(a)	udelay(a * 1000)
+#define ssleep(a)	msleep(a * 1000)
+
+static int ata_probe_timeout = (ATA_TMOUT_INTERNAL / 100);
+
+enum sata_dev_state {
+	SATA_INIT = 0,
+	SATA_READY = 1,
+	SATA_NODEVICE = 2,
+	SATA_ERROR = 3,
+};
+enum sata_dev_state dev_state = SATA_INIT;
+
+static struct ahb_dma_regs		*sata_dma_regs = 0;
+static struct ata_host			*phost;
+static struct ata_port			ap;
+static struct ata_port			*pap = &ap;
+static struct ata_device		ata_device;
+static struct sata_dwc_device_port	dwc_devp;
+
+static void	*scr_addr_sstatus;
+static u32	temp_n_block = 0;
+
+static unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout);
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+			u8 enable,u8 feature);
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+			u16 heads, u16 sectors);
+static u8 ata_irq_on(struct ata_port *ap);
+static struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+			unsigned int tag);
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq);
+static void ata_tf_to_host(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static void ata_exec_command(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+static u8 ata_check_altstatus(struct ata_port *ap);
+static u8 ata_check_status(struct ata_port *ap);
+static void ata_dev_select(struct ata_port *ap, unsigned int device,
+			unsigned int wait, unsigned int can_sleep);
+static void ata_qc_issue(struct ata_queued_cmd *qc);
+static void ata_tf_load(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static int ata_dev_read_sectors(unsigned char* pdata,
+			unsigned long datalen, u32 block, u32 n_block);
+static int ata_dev_write_sectors(unsigned char* pdata,
+			unsigned long datalen , u32 block, u32 n_block);
+static void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+static void ata_qc_complete(struct ata_queued_cmd *qc);
+static void __ata_qc_complete(struct ata_queued_cmd *qc);
+static void fill_result_tf(struct ata_queued_cmd *qc);
+static void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void ata_mmio_data_xfer(struct ata_device *dev,
+			unsigned char *buf,
+			unsigned int buflen,int do_write);
+static void ata_pio_task(struct ata_port *arg_ap);
+static void __ata_port_freeze(struct ata_port *ap);
+static int ata_port_freeze(struct ata_port *ap);
+static void ata_qc_free(struct ata_queued_cmd *qc);
+static void ata_pio_sectors(struct ata_queued_cmd *qc);
+static void ata_pio_sector(struct ata_queued_cmd *qc);
+static void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay);
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq);
+static int sata_dwc_softreset(struct ata_port *ap);
+static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id);
+static int check_sata_dev_state(void);
+
+extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
+
+static const struct ata_port_info sata_dwc_port_info[] = {
+	{
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
+				ATA_FLAG_SRST | ATA_FLAG_NCQ,
+		.pio_mask	= 0x1f,
+		.mwdma_mask	= 0x07,
+		.udma_mask	= 0x7f,
+	},
+};
+
+int init_sata (int dev)
+{
+	struct sata_dwc_device hsdev;
+	struct ata_host host;
+	struct ata_port_info pi = sata_dwc_port_info[0];
+	struct ata_link *link;
+	struct sata_dwc_device_port hsdevp = dwc_devp;
+	u8 *base = 0;
+	u8 *sata_dma_regs_addr = 0;
+	u8 status;
+	unsigned long base_addr = 0;
+	int chan = 0;
+	int rc;
+	int i;
+
+	phost = &host;
+
+	base = (u8*)SATA_BASE_ADDR;
+
+	hsdev.sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+
+	host.n_ports = SATA_DWC_MAX_PORTS;
+
+	for (i = 0; i < SATA_DWC_MAX_PORTS; i++) {
+		ap.pflags |= ATA_PFLAG_INITIALIZING;
+		ap.flags = ATA_FLAG_DISABLED;
+		ap.print_id = -1;
+		ap.ctl = ATA_DEVCTL_OBS;
+		ap.host = &host;
+		ap.last_ctl = 0xFF;
+
+		link = &ap.link;
+		link->ap = &ap;
+		link->pmp = 0;
+		link->active_tag = ATA_TAG_POISON;
+		link->hw_sata_spd_limit = 0;
+
+		ap.port_no = i;
+		host.ports[i] = &ap;
+	}
+
+	ap.pio_mask = pi.pio_mask;
+	ap.mwdma_mask = pi.mwdma_mask;
+	ap.udma_mask = pi.udma_mask;
+	ap.flags |= pi.flags;
+	ap.link.flags |= pi.link_flags;
+
+	host.ports[0]->ioaddr.cmd_addr = base;
+	host.ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
+	scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
+
+	base_addr = (unsigned long)base;
+
+	host.ports[0]->ioaddr.cmd_addr = (void *)base_addr + 0x00;
+	host.ports[0]->ioaddr.data_addr = (void *)base_addr + 0x00;
+
+	host.ports[0]->ioaddr.error_addr = (void *)base_addr + 0x04;
+	host.ports[0]->ioaddr.feature_addr = (void *)base_addr + 0x04;
+
+	host.ports[0]->ioaddr.nsect_addr = (void *)base_addr + 0x08;
+
+	host.ports[0]->ioaddr.lbal_addr = (void *)base_addr + 0x0c;
+	host.ports[0]->ioaddr.lbam_addr = (void *)base_addr + 0x10;
+	host.ports[0]->ioaddr.lbah_addr = (void *)base_addr + 0x14;
+
+	host.ports[0]->ioaddr.device_addr = (void *)base_addr + 0x18;
+	host.ports[0]->ioaddr.command_addr = (void *)base_addr + 0x1c;
+	host.ports[0]->ioaddr.status_addr = (void *)base_addr + 0x1c;
+
+	host.ports[0]->ioaddr.altstatus_addr = (void *)base_addr + 0x20;
+	host.ports[0]->ioaddr.ctl_addr = (void *)base_addr + 0x20;
+
+	sata_dma_regs_addr = (u8*)SATA_DMA_REG_ADDR;
+	sata_dma_regs = (void *__iomem)sata_dma_regs_addr;
+
+	status = ata_check_altstatus(&ap);
+
+	if (status == 0x7f) {
+		printf("Hard Disk not found.\n");
+		dev_state = SATA_NODEVICE;
+		rc = FALSE;
+		return rc;
+	}
+
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);
+
+		status = ata_check_altstatus(&ap);
+
+		if ((status & ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			dev_state = SATA_NODEVICE;
+			rc = FALSE;
+			return rc;
+		}
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	rc = sata_dwc_softreset(&ap);
+
+	if (rc) {
+		printf("sata_dwc : error. soft reset failed\n");
+		return rc;
+	}
+
+	for (chan = 0; chan < DMA_NUM_CHANS; chan++) {
+		out_le32(&(sata_dma_regs->interrupt_mask.error.low),
+				DMA_DISABLE_CHAN(chan));
+
+		out_le32(&(sata_dma_regs->interrupt_mask.tfr.low),
+				DMA_DISABLE_CHAN(chan));
+	}
+
+	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_DI);
+
+	out_le32(&hsdev.sata_dwc_regs->intmr,
+		SATA_DWC_INTMR_ERRM |
+		SATA_DWC_INTMR_PMABRTM);
+
+	/* Unmask the error bits that should trigger
+	 * an error interrupt by setting the error mask register.
+	 */
+	out_le32(&hsdev.sata_dwc_regs->errmr,SATA_DWC_SERROR_ERR_BITS);
+
+	hsdev.host = ap.host;
+	memset(&hsdevp, 0, sizeof(hsdevp));
+	hsdevp.hsdev = &hsdev;
+
+	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
+		hsdevp.cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
+
+	out_le32((void __iomem *)scr_addr_sstatus + 4,
+		in_le32((void __iomem *)scr_addr_sstatus + 4));
+
+	rc = 0;
+	return rc;
+}
+
+static u8 ata_check_altstatus(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.altstatus_addr);
+	return val;
+}
+
+static int sata_dwc_softreset(struct ata_port *ap)
+{
+	u8 nsect,lbal = 0;
+	u8 tmp = 0;
+	u32 serror = 0;
+	u8 status = 0;
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	serror = in_le32((void *)ap->ioaddr.scr_addr + (SCR_ERROR * 4));
+
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+	writeb(0xaa, ioaddr->nsect_addr);
+	writeb(0x55, ioaddr->lbal_addr);
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa)) {
+		printf("we found a device\n");
+	} else {
+		printf("Not found a device.\n");
+		dev_state = SATA_NODEVICE;
+		return FALSE;
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	udelay(200);
+
+	writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+
+	udelay(200);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	msleep(150);
+	status = ata_check_status(ap);
+
+	msleep(50);
+	ata_check_status(ap);
+
+	while (1) {
+		u8 status = ata_check_status(ap);
+
+		if (!(status & ATA_BUSY))
+			break;
+
+		printf("Hard Disk status is BUSY.\n");
+		msleep(50);
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	return 0;
+}
+
+static u8 ata_check_status(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.status_addr);
+	return val;
+}
+
+static int ata_id_has_hipm(const u16 *id)
+{
+	u16 val = id[76];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 9);
+}
+
+static int ata_id_has_dipm(const u16 *id)
+{
+	u16 val = id[78];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 3);
+}
+
+int scan_sata (int dev)
+{
+	int i;
+	int rc;
+	u8 status;
+	const u16 *id;
+	struct ata_device *ata_dev = &ata_device;
+	unsigned long pio_mask, mwdma_mask, udma_mask;
+	unsigned long xfer_mask;
+	char revbuf[7];
+	u16 iobuf[ATA_SECTOR_WORDS];
+
+	memset ( iobuf, 0, sizeof(iobuf));
+
+	if (dev_state == SATA_NODEVICE)
+		return 1;
+
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);
+
+		status = ata_check_altstatus(&ap);
+
+		if ((status & ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			dev_state = SATA_NODEVICE;
+			return 1;
+		}
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	udelay (1000);
+
+	rc = ata_dev_read_id(ata_dev, &ata_dev->class,
+			ATA_READID_POSTRESET,ata_dev->id);
+	if (rc) {
+		printf("sata_dwc : error. failed sata scan\n");
+		return 1;
+	}
+
+	/* SATA drives indicate we have a bridge. We don't know which
+	 * end of the link the bridge is which is a problem
+	 */
+	if (ata_id_is_sata(ata_dev->id))
+		ap.cbl = ATA_CBL_SATA;
+
+	id = ata_dev->id;
+
+	ata_dev->flags &= ~ATA_DFLAG_CFG_MASK;
+	ata_dev->max_sectors = 0;
+	ata_dev->cdb_len = 0;
+	ata_dev->n_sectors = 0;
+	ata_dev->cylinders = 0;
+	ata_dev->heads = 0;
+	ata_dev->sectors = 0;
+
+	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+		pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+		pio_mask <<= 3;
+		pio_mask |= 0x7;
+	} else {
+		/* If word 64 isn't valid then Word 51 high byte holds
+		 * the PIO timing number for the maximum. Turn it into
+		 * a mask.
+		 */
+		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
+		if (mode < 5) {
+			pio_mask = (2 << mode) - 1;
+		} else {
+			pio_mask = 1;
+		}
+	}
+
+	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+	if (ata_id_is_cfa(id)) {
+		int pio = id[163] & 0x7;
+		int dma = (id[163] >> 3) & 7;
+
+		if (pio)
+			pio_mask |= (1 << 5);
+		if (pio > 1)
+			pio_mask |= (1 << 6);
+		if (dma)
+			mwdma_mask |= (1 << 3);
+		if (dma > 1)
+			mwdma_mask |= (1 << 4);
+	}
+
+	udma_mask = 0;
+	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+	xfer_mask = ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
+		((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
+		((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
+
+	if (ata_dev->class == ATA_DEV_ATA) {
+		if (ata_id_is_cfa(id)) {
+			if (id[162] & 1)
+				printf("supports DRM functions and may "
+					"not be fully accessable.\n");
+			sprintf(revbuf, "%s", "CFA");
+		} else {
+			if (ata_id_has_tpm(id))
+				printf("supports DRM functions and may "
+						"not be fully accessable.\n");
+		}
+
+		ata_dev->n_sectors = ata_id_n_sectors((u16*)id);
+
+		if (ata_dev->id[59] & 0x100)
+			ata_dev->multi_count = ata_dev->id[59] & 0xff;
+
+		if (ata_id_has_lba(id)) {
+			const char *lba_desc;
+			char ncq_desc[20];
+
+			lba_desc = "LBA";
+			ata_dev->flags |= ATA_DFLAG_LBA;
+			if (ata_id_has_lba48(id)) {
+				ata_dev->flags |= ATA_DFLAG_LBA48;
+				lba_desc = "LBA48";
+
+				if (ata_dev->n_sectors >= (1UL << 28) &&
+					ata_id_has_flush_ext(id))
+					ata_dev->flags |= ATA_DFLAG_FLUSH_EXT;
+			}
+			if (!ata_id_has_ncq(ata_dev->id))
+				ncq_desc[0] = '\0';
+
+			if (ata_dev->horkage & ATA_HORKAGE_NONCQ)
+				sprintf(ncq_desc, "%s", "NCQ (not used)");
+
+			if (ap.flags & ATA_FLAG_NCQ)
+				ata_dev->flags |= ATA_DFLAG_NCQ;
+		}
+		ata_dev->cdb_len = 16;
+	}
+	ata_dev->max_sectors = ATA_MAX_SECTORS;
+	if (ata_dev->flags & ATA_DFLAG_LBA48)
+		ata_dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
+	if (!(ata_dev->horkage & ATA_HORKAGE_IPM)) {
+		if (ata_id_has_hipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_HIPM;
+		if (ata_id_has_dipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_DIPM;
+	}
+
+	if ((ap.cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ata_dev->id))) {
+		ata_dev->udma_mask &= ATA_UDMA5;
+		ata_dev->max_sectors = ATA_MAX_SECTORS;
+	}
+
+	if (ata_dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+		printf("Drive reports diagnostics failure."
+				"This may indicate a drive\n");
+		printf("fault or invalid emulation."
+				"Contact drive vendor for information.\n");
+	}
+
+	rc = check_sata_dev_state();
+
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].revision,
+			 ATA_ID_FW_REV, sizeof(sata_dev_desc[dev].revision));
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].vendor,
+			 ATA_ID_PROD, sizeof(sata_dev_desc[dev].vendor));
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].product,
+			 ATA_ID_SERNO, sizeof(sata_dev_desc[dev].product));
+
+	sata_dev_desc[dev].lba = (u32) ata_dev->n_sectors;
+
+#ifdef CONFIG_LBA48
+	if (ata_dev->id[83] & (1 << 10)) {
+		sata_dev_desc[dev].lba48 = 1;
+	} else {
+		sata_dev_desc[dev].lba48 = 0;
+	}
+#endif
+
+	return 0;
+}
+
+static u8 ata_busy_wait(struct ata_port *ap,
+		unsigned int bits,unsigned int max)
+{
+	u8 status;
+
+	do {
+		udelay(10);
+		status = ata_check_status(ap);
+		max--;
+	} while (status != 0xff && (status & bits) && (max > 0));
+
+	return status;
+}
+
+static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id)
+{
+	struct ata_port *ap = pap;
+	unsigned int class = *p_class;
+	struct ata_taskfile tf;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1, tried_spinup = 0;
+	u8 status;
+	int rc;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_ID_ATA;
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+	/* Device presence detection is unreliable on some
+	 * controllers.  Always poll IDENTIFY if available.
+	 */
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	temp_n_block = 1;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+					sizeof(id[0]) * ATA_ID_WORDS, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	unsigned int id_cnt;
+
+	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
+		id[id_cnt] = le16_to_cpu(id[id_cnt]);
+
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	if (class == ATA_DEV_ATA) {
+		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
+			goto err_out;
+	} else {
+		if (ata_id_is_ata(id))
+			goto err_out;
+	}
+	if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+		tried_spinup = 1;
+		/*
+		 * Drive powered-up in standby mode, and requires a specific
+		 * SET_FEATURES spin-up subcommand before it will accept
+		 * anything other than the original IDENTIFY command.
+		 */
+		err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+		if (err_mask && id[2] != 0x738c) {
+			rc = -EIO;
+			reason = "SPINUP failed";
+			goto err_out;
+		}
+		/*
+		 * If the drive initially returned incomplete IDENTIFY info,
+		 * we now must reissue the IDENTIFY command.
+		 */
+		if (id[2] == 0x37c8)
+			goto retry;
+	}
+
+	if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
+		/*
+		 * The exact sequence expected by certain pre-ATA4 drives is:
+		 * SRST RESET
+		 * IDENTIFY (optional in early ATA)
+		 * INITIALIZE DEVICE PARAMETERS (later IDE and ATA)
+		 * anything else..
+		 * Some drives were very specific about that exact sequence.
+		 *
+		 * Note that ATA4 says lba is mandatory so the second check
+		 * shoud never trigger.
+		 */
+		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+			err_mask = ata_dev_init_params(dev, id[3], id[6]);
+			if (err_mask) {
+				rc = -EIO;
+				reason = "INIT_DEV_PARAMS failed";
+				goto err_out;
+			}
+
+			/* current CHS translation info (id[53-58]) might be
+			 * changed. reread the identify device info.
+			 */
+			flags &= ~ATA_READID_POSTRESET;
+			goto retry;
+		}
+	}
+
+	*p_class = class;
+	return 0;
+
+err_out:
+	return rc;
+}
+
+static u8 ata_wait_idle(struct ata_port *ap)
+{
+	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	return status;
+}
+
+static void ata_dev_select(struct ata_port *ap, unsigned int device,
+		unsigned int wait, unsigned int can_sleep)
+{
+	if (wait)
+		ata_wait_idle(ap);
+
+	ata_std_dev_select(ap, device);
+
+	if (wait)
+		ata_wait_idle(ap);
+}
+
+static void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+{
+	u8 tmp;
+
+	if (device == 0) {
+		tmp = ATA_DEVICE_OBS;
+	} else {
+		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+	}
+
+	writeb(tmp, ap->ioaddr.device_addr);
+
+	readb(ap->ioaddr.altstatus_addr);
+
+	udelay(1);
+}
+
+static int waiting_for_reg_state(volatile u8 *offset,
+				int timeout_msec,
+				u32 sign)
+{
+	int i;
+	u32 status;
+
+	for (i = 0; i < timeout_msec; i++) {
+		status = readl(offset);
+		if ((status & sign) != 0)
+			break;
+		msleep(1);
+	}
+
+	return (i < timeout_msec) ? 0 : -1;
+}
+
+static void ata_qc_reinit(struct ata_queued_cmd *qc)
+{
+	qc->dma_dir = DMA_NONE;
+	qc->flags = 0;
+	qc->nbytes = qc->extrabytes = qc->curbytes = 0;
+	qc->n_elem = 0;
+	qc->err_mask = 0;
+	qc->sect_size = ATA_SECT_SIZE;
+	qc->nbytes = ATA_SECT_SIZE * temp_n_block;
+
+	memset(&qc->tf, 0, sizeof(qc->tf));
+	qc->tf.ctl = 0;
+	qc->tf.device = ATA_DEVICE_OBS;
+
+	qc->result_tf.command = ATA_DRDY;
+	qc->result_tf.feature = 0;
+}
+
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+					unsigned int tag)
+{
+	if (tag < ATA_MAX_QUEUE)
+		return &ap->qcmd[tag];
+	return NULL;
+}
+
+static void __ata_port_freeze(struct ata_port *ap)
+{
+	printf("set port freeze.\n");
+	ap->pflags |= ATA_PFLAG_FROZEN;
+}
+
+static int ata_port_freeze(struct ata_port *ap)
+{
+	__ata_port_freeze(ap);
+	return 0;
+}
+
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout)
+{
+	struct ata_link *link = dev->link;
+	struct ata_port *ap = pap;
+	struct ata_queued_cmd *qc;
+	unsigned int tag, preempted_tag;
+	u32 preempted_sactive, preempted_qc_active;
+	int preempted_nr_active_links;
+	unsigned int err_mask;
+	int rc = 0;
+	u8 status;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 300000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	if (ap->pflags & ATA_PFLAG_FROZEN)
+		return AC_ERR_SYSTEM;
+
+	tag = ATA_TAG_INTERNAL;
+
+	if (test_and_set_bit(tag, &ap->qc_allocated)) {
+		rc = FALSE;
+		return rc;
+	}
+
+	qc = __ata_qc_from_tag(ap, tag);
+	qc->tag = tag;
+	qc->ap = ap;
+	qc->dev = dev;
+
+	ata_qc_reinit(qc);
+
+	preempted_tag = link->active_tag;
+	preempted_sactive = link->sactive;
+	preempted_qc_active = ap->qc_active;
+	preempted_nr_active_links = ap->nr_active_links;
+	link->active_tag = ATA_TAG_POISON;
+	link->sactive = 0;
+	ap->qc_active = 0;
+	ap->nr_active_links = 0;
+
+	qc->tf = *tf;
+	if (cdb)
+		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+	qc->dma_dir = dma_dir;
+	qc->private_data = 0;
+
+	ata_qc_issue(qc);
+
+	if (!timeout)
+		timeout = ata_probe_timeout * 1000 / HZ;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		printf("altstatus = 0x%x.\n",status);
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	if (waiting_for_reg_state(ap->ioaddr.altstatus_addr,1000,0x8)) {
+		u8 status = 0;
+		u8 errorStatus = 0;
+
+		status = readb( ap->ioaddr.altstatus_addr);
+		if ((status & 0x01) != 0) {
+			errorStatus = readb( ap->ioaddr.feature_addr);
+			if (errorStatus == 0x04 &&
+				qc->tf.command == ATA_CMD_PIO_READ_EXT){
+				printf("Hard Disk doesn't support LBA48\n");
+				dev_state = SATA_ERROR;
+				qc->err_mask |= AC_ERR_OTHER;
+				return qc->err_mask;
+			}
+		}
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	status = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	ata_pio_task(ap);
+
+	if (!rc) {
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			qc->err_mask |= AC_ERR_TIMEOUT;
+			ata_port_freeze(ap);
+		}
+	}
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (qc->result_tf.command & (ATA_ERR | ATA_DF))
+			qc->err_mask |= AC_ERR_DEV;
+
+		if (!qc->err_mask)
+			qc->err_mask |= AC_ERR_OTHER;
+
+		if (qc->err_mask & ~AC_ERR_OTHER)
+			qc->err_mask &= ~AC_ERR_OTHER;
+	}
+
+	*tf = qc->result_tf;
+	err_mask = qc->err_mask;
+	ata_qc_free(qc);
+	link->active_tag = preempted_tag;
+	link->sactive = preempted_sactive;
+	ap->qc_active = preempted_qc_active;
+	ap->nr_active_links = preempted_nr_active_links;
+
+	if (ap->flags & ATA_FLAG_DISABLED) {
+		err_mask |= AC_ERR_SYSTEM;
+		ap->flags &= ~ATA_FLAG_DISABLED;
+	}
+
+	return err_mask;
+}
+
+static void ata_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+	u8 prot = qc->tf.protocol;
+
+	if (ata_is_ncq(prot)) {
+		if (!link->sactive)
+			ap->nr_active_links++;
+		link->sactive |= 1 << qc->tag;
+	} else {
+		ap->nr_active_links++;
+		link->active_tag = qc->tag;
+	}
+
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+	ap->qc_active |= 1 << qc->tag;
+
+	if (qc->dev->flags & ATA_DFLAG_SLEEPING) {
+		msleep(1);
+		return;
+	}
+
+	qc->err_mask |= ata_qc_issue_prot(qc);
+	if (qc->err_mask)
+		goto err;
+
+	return;
+err:
+	ata_qc_complete(qc);
+}
+
+static unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+		switch (qc->tf.protocol) {
+		case ATA_PROT_PIO:
+		case ATA_PROT_NODATA:
+		case ATAPI_PROT_PIO:
+		case ATAPI_PROT_NODATA:
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			qc->tf.ctl |= ATA_NIEN;
+
+		ata_tf_to_host(ap, &qc->tf);
+
+		ap->hsm_task_state = HSM_ST;
+
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_pio_queue_task(ap, qc, 0);
+
+		break;
+
+	default:
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+static void ata_tf_to_host(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	ata_tf_load(ap, tf);
+	ata_exec_command(ap, tf);
+}
+
+static void ata_tf_load(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		if (ioaddr->ctl_addr)
+			writeb(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writeb(tf->hob_feature, ioaddr->feature_addr);
+		writeb(tf->hob_nsect, ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, ioaddr->lbah_addr);
+	}
+
+	if (is_addr) {
+		writeb(tf->feature, ioaddr->feature_addr);
+		writeb(tf->nsect, ioaddr->nsect_addr);
+		writeb(tf->lbal, ioaddr->lbal_addr);
+		writeb(tf->lbam, ioaddr->lbam_addr);
+		writeb(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE)
+		writeb(tf->device, ioaddr->device_addr);
+
+	ata_wait_idle(ap);
+}
+
+static void ata_exec_command(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	writeb(tf->command, ap->ioaddr.command_addr);
+
+	readb(ap->ioaddr.altstatus_addr);
+
+	udelay(1);
+}
+
+static void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay)
+{
+	ap->port_task_data = data;
+}
+
+static unsigned int ac_err_mask(u8 status)
+{
+	if (status & (ATA_BUSY | ATA_DRQ))
+		return AC_ERR_HSM;
+	if (status & (ATA_ERR | ATA_DF))
+		return AC_ERR_DEV;
+	return 0;
+}
+
+static unsigned int __ac_err_mask(u8 status)
+{
+	unsigned int mask = ac_err_mask(status);
+	if (mask == 0)
+		return AC_ERR_OTHER;
+	return mask;
+}
+
+static void ata_pio_task(struct ata_port *arg_ap)
+{
+	struct ata_port *ap = arg_ap;
+	struct ata_queued_cmd *qc = ap->port_task_data;
+	u8 status;
+	int poll_next;
+
+fsm_start:
+	/*
+	 * This is purely heuristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, queue delayed work.
+	 */
+	status = ata_busy_wait(ap, ATA_BUSY, 5);
+	if (status & ATA_BUSY) {
+		msleep(2);
+		status = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (status & ATA_BUSY) {
+			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+			return;
+		}
+	}
+
+	poll_next = ata_hsm_move(ap, qc, status, 1);
+
+	/* another command or interrupt handler
+	 * may be running at this point.
+	 */
+	if (poll_next)
+		goto fsm_start;
+}
+
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq)
+{
+	int poll_next;
+
+fsm_start:
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+		if ((status & ATA_DRQ) == 0) {
+			if (status & (ATA_ERR | ATA_DF)) {
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				qc->err_mask |= AC_ERR_HSM;
+			}
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Device should not ask for data transfer (DRQ=1)
+		 * when it finds something wrong.
+		 * We ignore DRQ here and stop the HSM by
+		 * changing hsm_task_state to HSM_ST_ERR and
+		 * let the EH abort the command or reset the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+				printf("DRQ=1 with device error, "
+					"dev_stat 0x%X\n", status);
+				qc->err_mask |= AC_ERR_HSM;
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+		}
+
+		if (qc->tf.protocol == ATA_PROT_PIO) {
+			/* PIO data out protocol.
+			 * send first data block.
+			 */
+			/* ata_pio_sectors() might change the state
+			 * to HSM_ST_LAST. so, the state is changed here
+			 * before ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST;
+			ata_pio_sectors(qc);
+		} else {
+			printf("protocol is not ATA_PROT_PIO \n");
+		}
+		break;
+
+	case HSM_ST:
+		if ((status & ATA_DRQ) == 0) {
+			if (status & (ATA_ERR | ATA_DF)) {
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this.
+				 * Phantom devices also trigger this
+				 * condition.  Mark hint.
+				 */
+				qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT;
+			}
+
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+		/* For PIO reads, some devices may ask for
+		 * data transfer (DRQ=1) alone with ERR=1.
+		 * We respect DRQ here and transfer one
+		 * block of junk data before changing the
+		 * hsm_task_state to HSM_ST_ERR.
+		 *
+		 * For PIO writes, ERR=1 DRQ=1 doesn't make
+		 * sense since the data block has been
+		 * transferred to the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			qc->err_mask |= AC_ERR_DEV;
+
+			if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+				ata_pio_sectors(qc);
+				status = ata_wait_idle(ap);
+			}
+
+			if (status & (ATA_BUSY | ATA_DRQ))
+				qc->err_mask |= AC_ERR_HSM;
+
+			/* ata_pio_sectors() might change the
+			 * state to HSM_ST_LAST. so, the state
+			 * is changed after ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ata_pio_sectors(qc);
+		if (ap->hsm_task_state == HSM_ST_LAST &&
+			(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+			status = ata_wait_idle(ap);
+			goto fsm_start;
+		}
+
+		poll_next = 1;
+		break;
+
+	case HSM_ST_LAST:
+		if (!ata_ok(status)) {
+			qc->err_mask |= __ac_err_mask(status);
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+
+	case HSM_ST_ERR:
+		/* make sure qc->err_mask is available to
+		 * know what's wrong and recover
+		 */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+	default:
+		poll_next = 0;
+	}
+
+	return poll_next;
+}
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap;
+	ap = pap;
+	qc->pdata = ap->pdata;
+
+	ata_pio_sector(qc);
+
+	readb(qc->ap->ioaddr.altstatus_addr);
+	udelay(1);
+}
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	struct ata_port *ap = qc->ap;
+	unsigned int offset;
+	unsigned char *buf;
+	char temp_data_buf[512];
+
+	if (qc->curbytes == qc->nbytes - qc->sect_size)
+		ap->hsm_task_state = HSM_ST_LAST;
+
+	offset = qc->curbytes;
+
+	switch (qc->tf.command) {
+	case ATA_CMD_ID_ATA:
+		buf = (unsigned char *)&ata_device.id[0];
+		break;
+	case ATA_CMD_PIO_READ_EXT:
+	case ATA_CMD_PIO_READ:
+	case ATA_CMD_PIO_WRITE_EXT:
+	case ATA_CMD_PIO_WRITE:
+		buf = qc->pdata + offset;
+		break;
+	default:
+		buf = (unsigned char *)&temp_data_buf[0];
+	}
+
+	ata_mmio_data_xfer(qc->dev, buf, qc->sect_size, do_write);
+
+	qc->curbytes += qc->sect_size;
+
+}
+
+static void ata_mmio_data_xfer(struct ata_device *dev, unsigned char *buf,
+				unsigned int buflen, int do_write)
+{
+	struct ata_port *ap = pap;
+	void __iomem *data_addr = ap->ioaddr.data_addr;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *)buf;
+	unsigned int i = 0;
+
+	udelay(100);
+	if (do_write) {
+		for (i = 0; i < words; i++)
+			writew(le16_to_cpu(buf16[i]), data_addr);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(readw(data_addr));
+	}
+
+	if (buflen & 0x01) {
+		__le16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (do_write) {
+			memcpy(align_buf, trailing_buf, 1);
+			writew(le16_to_cpu(align_buf[0]), data_addr);
+		} else {
+			align_buf[0] = cpu_to_le16(readw(data_addr));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
+}
+
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (in_wq) {
+		/* EH might have kicked in while host lock is
+		 * released.
+		 */
+		qc = &ap->qcmd[qc->tag];
+		if (qc) {
+			if (!(qc->err_mask & AC_ERR_HSM)) {
+				ata_irq_on(ap);
+				ata_qc_complete(qc);
+			} else {
+				ata_port_freeze(ap);
+			}
+		}
+	} else {
+		if (!(qc->err_mask & AC_ERR_HSM)) {
+			ata_qc_complete(qc);
+		} else {
+			ata_port_freeze(ap);
+		}
+	}
+}
+
+static u8 ata_irq_on(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 tmp;
+
+	ap->ctl &= ~ATA_NIEN;
+	ap->last_ctl = ap->ctl;
+
+	if (ioaddr->ctl_addr)
+		writeb(ap->ctl, ioaddr->ctl_addr);
+
+	tmp = ata_wait_idle(ap);
+
+	return tmp;
+}
+
+static unsigned int ata_tag_internal(unsigned int tag)
+{
+	return tag == ATA_MAX_QUEUE - 1;
+}
+
+static void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_device *dev = qc->dev;
+	if (qc->err_mask)
+		qc->flags |= ATA_QCFLAG_FAILED;
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (!ata_tag_internal(qc->tag)) {
+			fill_result_tf(qc);
+			return;
+		}
+	}
+	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+		fill_result_tf(qc);
+
+	/* Some commands need post-processing after successful
+	 * completion.
+	 */
+	switch (qc->tf.command) {
+	case ATA_CMD_SET_FEATURES:
+		if (qc->tf.feature != SETFEATURES_WC_ON &&
+				qc->tf.feature != SETFEATURES_WC_OFF)
+			break;
+	case ATA_CMD_INIT_DEV_PARAMS:
+	case ATA_CMD_SET_MULTI:
+		break;
+
+	case ATA_CMD_SLEEP:
+		dev->flags |= ATA_DFLAG_SLEEPING;
+		break;
+	}
+
+	__ata_qc_complete(qc);
+}
+
+static void fill_result_tf(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	qc->result_tf.flags = qc->tf.flags;
+	ata_tf_read(ap, &qc->result_tf);
+}
+
+static void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->command = ata_check_status(ap);
+	tf->feature = readb(ioaddr->error_addr);
+	tf->nsect = readb(ioaddr->nsect_addr);
+	tf->lbal = readb(ioaddr->lbal_addr);
+	tf->lbam = readb(ioaddr->lbam_addr);
+	tf->lbah = readb(ioaddr->lbah_addr);
+	tf->device = readb(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		if (ioaddr->ctl_addr) {
+			writeb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+
+			tf->hob_feature = readb(ioaddr->error_addr);
+			tf->hob_nsect = readb(ioaddr->nsect_addr);
+			tf->hob_lbal = readb(ioaddr->lbal_addr);
+			tf->hob_lbam = readb(ioaddr->lbam_addr);
+			tf->hob_lbah = readb(ioaddr->lbah_addr);
+
+			writeb(tf->ctl, ioaddr->ctl_addr);
+			ap->last_ctl = tf->ctl;
+		} else {
+			printf("sata_dwc warnning register read.\n");
+		}
+	}
+}
+
+static void __ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+
+	link->active_tag = ATA_TAG_POISON;
+	ap->nr_active_links--;
+
+	if (qc->flags & ATA_QCFLAG_CLEAR_EXCL && ap->excl_link == link)
+		ap->excl_link = NULL;
+
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	ap->qc_active &= ~(1 << qc->tag);
+}
+
+static void ata_qc_free(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int tag;
+	qc->flags = 0;
+	tag = qc->tag;
+	if (tag < ATA_MAX_QUEUE) {
+		qc->tag = ATA_TAG_POISON;
+		clear_bit(tag, &ap->qc_allocated);
+	}
+}
+
+static int check_sata_dev_state(void)
+{
+	unsigned long datalen;
+	unsigned char *pdata;
+	int ret = 0;
+	int i = 0;
+	char temp_data_buf[512];
+
+	while (1) {
+		udelay (10000);
+
+		pdata = (unsigned char*)&temp_data_buf[0];
+		datalen = 512;
+
+		ret = ata_dev_read_sectors(pdata, datalen, 0, 1);
+
+		if (ret == TRUE)
+			break;
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+			dev_state = SATA_NODEVICE;
+			return FALSE;
+		}
+
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	dev_state = SATA_READY;
+
+	return TRUE;
+}
+
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+				u8 enable, u8 feature)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = enable;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = feature;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	return err_mask;
+}
+
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+				u16 heads, u16 sectors)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+		return AC_ERR_INVALID;
+
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
+		err_mask = 0;
+
+	return err_mask;
+}
+
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SATA_MAX_READ_BLK 0xFF
+#else
+#define SATA_MAX_READ_BLK 0xFFFF
+#endif
+
+ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	ulong start,blks, buf_addr;
+	unsigned short smallblks;
+	unsigned long datalen;
+	unsigned char *pdata;
+	device &= 0xff;
+
+	u32 block = 0;
+	u32 n_block = 0;
+
+	if (dev_state != SATA_READY)
+		return 0;
+
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	do {
+		pdata = (unsigned char *)buf_addr;
+		if (blks > SATA_MAX_READ_BLK) {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_READ_BLK;
+			smallblks = SATA_MAX_READ_BLK;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += SATA_MAX_READ_BLK;
+			blks -= SATA_MAX_READ_BLK;
+		} else {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_READ_BLK;
+			datalen = sata_dev_desc[device].blksz * blks;
+			smallblks = (unsigned short)blks;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += blks;
+			blks = 0;
+		}
+
+		if (ata_dev_read_sectors(pdata, datalen, block, n_block) != TRUE) {
+			printf("sata_dwc : Hard disk read error.\n");
+			blkcnt -= blks;
+			break;
+		}
+		buf_addr += datalen;
+	} while (blks != 0);
+
+	return (blkcnt);
+}
+
+static int ata_dev_read_sectors(unsigned char *pdata, unsigned long datalen,
+						u32 block, u32 n_block)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	if (dev_state == SATA_ERROR)
+		return FALSE;
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	ap->pdata = pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	temp_n_block = n_block;
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_READ_EXT;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else
+	tf.command = ATA_CMD_PIO_READ;
+	tf.flags |= ATA_TFLAG_LBA ;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully@least once.
+	 */
+	may_fallback = 0;
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return TRUE;
+
+err_out:
+	printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return FALSE;
+}
+
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SATA_MAX_WRITE_BLK 0xFF
+#else
+#define SATA_MAX_WRITE_BLK 0xFFFF
+#endif
+
+ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	ulong start,blks, buf_addr;
+	unsigned short smallblks;
+	unsigned long datalen;
+	unsigned char *pdata;
+	device &= 0xff;
+
+
+	u32 block = 0;
+	u32 n_block = 0;
+
+	if (dev_state != SATA_READY)
+		return 0;
+
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	do {
+		pdata = (unsigned char *)buf_addr;
+		if (blks > SATA_MAX_WRITE_BLK) {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_WRITE_BLK;
+			smallblks = SATA_MAX_WRITE_BLK;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += SATA_MAX_WRITE_BLK;
+			blks -= SATA_MAX_WRITE_BLK;
+		} else {
+			datalen = sata_dev_desc[device].blksz * blks;
+			smallblks = (unsigned short)blks;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += blks;
+			blks = 0;
+		}
+
+		if (ata_dev_write_sectors(pdata, datalen, block, n_block) != TRUE) {
+			printf("sata_dwc : Hard disk read error.\n");
+			blkcnt -= blks;
+			break;
+		}
+		buf_addr += datalen;
+	} while (blks != 0);
+
+	return (blkcnt);
+}
+
+static int ata_dev_write_sectors(unsigned char* pdata, unsigned long datalen,
+						u32 block, u32 n_block)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	if (dev_state == SATA_ERROR)
+		return FALSE;
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	ap->pdata = pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	temp_n_block = n_block;
+
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_WRITE_EXT;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48 | ATA_TFLAG_WRITE;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else
+	tf.command = ATA_CMD_PIO_WRITE;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_WRITE;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return TRUE;
+
+err_out:
+	printf("failed to WRITE SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return FALSE;
+}
diff --git a/drivers/block/sata_dwc.h b/drivers/block/sata_dwc.h
new file mode 100644
index 0000000..6259804
--- /dev/null
+++ b/drivers/block/sata_dwc.h
@@ -0,0 +1,463 @@
+/*
+ * sata_dwc.h
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under  the terms of  the GNU
+ * General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 04-17-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+
+#ifndef _SATA_DWC_H_
+#define _SATA_DWC_H_
+
+#define HZ 100
+
+#define READ 0
+#define WRITE 1
+
+enum {
+	ATA_READID_POSTRESET	= (1 << 0),
+
+	ATA_DNXFER_PIO		= 0,
+	ATA_DNXFER_DMA		= 1,
+	ATA_DNXFER_40C		= 2,
+	ATA_DNXFER_FORCE_PIO	= 3,
+	ATA_DNXFER_FORCE_PIO0	= 4,
+
+	ATA_DNXFER_QUIET	= (1 << 31),
+};
+
+enum hsm_task_states {
+	HSM_ST_IDLE,
+	HSM_ST_FIRST,
+	HSM_ST,
+	HSM_ST_LAST,
+	HSM_ST_ERR,
+};
+
+#define	ATA_SHORT_PAUSE		((HZ >> 6) + 1)
+
+struct ata_queued_cmd {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
+
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
+	unsigned long		flags;
+	unsigned int		tag;
+	unsigned int		n_elem;
+
+	int			dma_dir;
+
+	unsigned int		sect_size;
+
+	unsigned int		nbytes;
+	unsigned int		extrabytes;
+	unsigned int		curbytes;
+
+	unsigned int		err_mask;
+	struct ata_taskfile	result_tf;
+
+	void			*private_data;
+	void			*lldd_task;
+	unsigned char		*pdata;
+};
+
+typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+
+#define ATA_TAG_POISON	0xfafbfcfdU
+
+enum {
+	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,
+	ATA_MAX_PORTS		= 8,
+	ATA_DEF_QUEUE		= 1,
+	ATA_MAX_QUEUE		= 32,
+	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
+	ATA_MAX_BUS		= 2,
+	ATA_DEF_BUSY_WAIT	= 10000,
+
+	ATAPI_MAX_DRAIN		= 16 << 10,
+
+	ATA_SHT_EMULATED	= 1,
+	ATA_SHT_CMD_PER_LUN	= 1,
+	ATA_SHT_THIS_ID		= -1,
+	ATA_SHT_USE_CLUSTERING	= 1,
+
+	ATA_DFLAG_LBA		= (1 << 0),
+	ATA_DFLAG_LBA48		= (1 << 1),
+	ATA_DFLAG_CDB_INTR	= (1 << 2),
+	ATA_DFLAG_NCQ		= (1 << 3),
+	ATA_DFLAG_FLUSH_EXT	= (1 << 4),
+	ATA_DFLAG_ACPI_PENDING 	= (1 << 5),
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6),
+	ATA_DFLAG_AN		= (1 << 7),
+	ATA_DFLAG_HIPM		= (1 << 8),
+	ATA_DFLAG_DIPM		= (1 << 9),
+	ATA_DFLAG_DMADIR	= (1 << 10),
+	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
+
+	ATA_DFLAG_PIO		= (1 << 12),
+	ATA_DFLAG_NCQ_OFF	= (1 << 13),
+	ATA_DFLAG_SPUNDOWN	= (1 << 14),
+	ATA_DFLAG_SLEEPING	= (1 << 15),
+	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16),
+	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
+
+	ATA_DFLAG_DETACH	= (1 << 24),
+	ATA_DFLAG_DETACHED	= (1 << 25),
+
+	ATA_LFLAG_HRST_TO_RESUME	= (1 << 0),
+	ATA_LFLAG_SKIP_D2H_BSY		= (1 << 1),
+	ATA_LFLAG_NO_SRST		= (1 << 2),
+	ATA_LFLAG_ASSUME_ATA		= (1 << 3),
+	ATA_LFLAG_ASSUME_SEMB		= (1 << 4),
+	ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
+	ATA_LFLAG_NO_RETRY		= (1 << 5),
+	ATA_LFLAG_DISABLED		= (1 << 6),
+
+	ATA_FLAG_SLAVE_POSS	= (1 << 0),
+	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LEGACY	= (1 << 2),
+	ATA_FLAG_MMIO		= (1 << 3),
+	ATA_FLAG_SRST		= (1 << 4),
+	ATA_FLAG_SATA_RESET	= (1 << 5),
+	ATA_FLAG_NO_ATAPI	= (1 << 6),
+	ATA_FLAG_PIO_DMA	= (1 << 7),
+	ATA_FLAG_PIO_LBA48	= (1 << 8),
+	ATA_FLAG_PIO_POLLING	= (1 << 9),
+	ATA_FLAG_NCQ		= (1 << 10),
+	ATA_FLAG_DEBUGMSG	= (1 << 13),
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15),
+	ATA_FLAG_NO_IORDY	= (1 << 16),
+	ATA_FLAG_ACPI_SATA	= (1 << 17),
+	ATA_FLAG_AN		= (1 << 18),
+	ATA_FLAG_PMP		= (1 << 19),
+	ATA_FLAG_IPM		= (1 << 20),
+
+	ATA_FLAG_DISABLED	= (1 << 23),
+
+	ATA_PFLAG_EH_PENDING		= (1 << 0),
+	ATA_PFLAG_EH_IN_PROGRESS	= (1 << 1),
+	ATA_PFLAG_FROZEN		= (1 << 2),
+	ATA_PFLAG_RECOVERED		= (1 << 3),
+	ATA_PFLAG_LOADING		= (1 << 4),
+	ATA_PFLAG_UNLOADING		= (1 << 5),
+	ATA_PFLAG_SCSI_HOTPLUG		= (1 << 6),
+	ATA_PFLAG_INITIALIZING		= (1 << 7),
+	ATA_PFLAG_RESETTING		= (1 << 8),
+	ATA_PFLAG_SUSPENDED		= (1 << 17),
+	ATA_PFLAG_PM_PENDING		= (1 << 18),
+
+	ATA_QCFLAG_ACTIVE	= (1 << 0),
+	ATA_QCFLAG_DMAMAP	= (1 << 1),
+	ATA_QCFLAG_IO		= (1 << 3),
+	ATA_QCFLAG_RESULT_TF	= (1 << 4),
+	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5),
+	ATA_QCFLAG_QUIET	= (1 << 6),
+
+	ATA_QCFLAG_FAILED	= (1 << 16),
+	ATA_QCFLAG_SENSE_VALID	= (1 << 17),
+	ATA_QCFLAG_EH_SCHEDULED	= (1 << 18),
+
+	ATA_HOST_SIMPLEX	= (1 << 0),
+	ATA_HOST_STARTED	= (1 << 1),
+
+	ATA_TMOUT_BOOT			= 30 * 100,
+	ATA_TMOUT_BOOT_QUICK		= 7 * 100,
+	ATA_TMOUT_INTERNAL		= 30 * 100,
+	ATA_TMOUT_INTERNAL_QUICK	= 5 * 100,
+
+	/* FIXME: GoVault needs 2s but we can't afford that without
+	 * parallel probing.  800ms is enough for iVDR disk
+	 * HHD424020F7SV00.  Increase to 2secs when parallel probing
+	 * is in place.
+	 */
+	ATA_TMOUT_FF_WAIT	= 4 * 100 / 5,
+
+	BUS_UNKNOWN		= 0,
+	BUS_DMA			= 1,
+	BUS_IDLE		= 2,
+	BUS_NOINTR		= 3,
+	BUS_NODATA		= 4,
+	BUS_TIMER		= 5,
+	BUS_PIO			= 6,
+	BUS_EDD			= 7,
+	BUS_IDENTIFY		= 8,
+	BUS_PACKET		= 9,
+
+	PORT_UNKNOWN		= 0,
+	PORT_ENABLED		= 1,
+	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_NR_PIO_MODES	= 7,
+	ATA_NR_MWDMA_MODES	= 5,
+	ATA_NR_UDMA_MODES	= 8,
+
+	ATA_SHIFT_PIO		= 0,
+	ATA_SHIFT_MWDMA		= ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
+	ATA_SHIFT_UDMA		= ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
+
+	ATA_DMA_PAD_SZ		= 4,
+
+	ATA_ERING_SIZE		= 32,
+
+	ATA_DEFER_LINK		= 1,
+	ATA_DEFER_PORT		= 2,
+
+	ATA_EH_DESC_LEN		= 80,
+
+	ATA_EH_REVALIDATE	= (1 << 0),
+	ATA_EH_SOFTRESET	= (1 << 1),
+	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_ENABLE_LINK	= (1 << 3),
+	ATA_EH_LPM		= (1 << 4),
+
+	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+	ATA_EHI_HOTPLUGGED	= (1 << 0),
+	ATA_EHI_RESUME_LINK	= (1 << 1),
+	ATA_EHI_NO_AUTOPSY	= (1 << 2),
+	ATA_EHI_QUIET		= (1 << 3),
+
+	ATA_EHI_DID_SOFTRESET	= (1 << 16),
+	ATA_EHI_DID_HARDRESET	= (1 << 17),
+	ATA_EHI_PRINTINFO	= (1 << 18),
+	ATA_EHI_SETMODE		= (1 << 19),
+	ATA_EHI_POST_SETMODE	= (1 << 20),
+
+	ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+	ATA_EH_MAX_TRIES	= 5,
+
+	ATA_PROBE_MAX_TRIES	= 3,
+	ATA_EH_DEV_TRIES	= 3,
+	ATA_EH_PMP_TRIES	= 5,
+	ATA_EH_PMP_LINK_TRIES	= 3,
+
+	SATA_PMP_SCR_TIMEOUT	= 250,
+
+	/* Horkage types. May be set by libata or controller on drives
+	(some horkage may be drive/controller pair dependant */
+
+	ATA_HORKAGE_DIAGNOSTIC	= (1 << 0),
+	ATA_HORKAGE_NODMA	= (1 << 1),
+	ATA_HORKAGE_NONCQ	= (1 << 2),
+	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),
+	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),
+	ATA_HORKAGE_SKIP_PM	= (1 << 5),
+	ATA_HORKAGE_HPA_SIZE	= (1 << 6),
+	ATA_HORKAGE_IPM		= (1 << 7),
+	ATA_HORKAGE_IVB		= (1 << 8),
+	ATA_HORKAGE_STUCK_ERR	= (1 << 9),
+
+	ATA_DMA_MASK_ATA	= (1 << 0),
+	ATA_DMA_MASK_ATAPI	= (1 << 1),
+	ATA_DMA_MASK_CFA	= (1 << 2),
+
+	ATAPI_READ		= 0,
+	ATAPI_WRITE		= 1,
+	ATAPI_READ_CD		= 2,
+	ATAPI_PASS_THRU		= 3,
+	ATAPI_MISC		= 4,
+};
+
+enum ata_completion_errors {
+	AC_ERR_DEV		= (1 << 0),
+	AC_ERR_HSM		= (1 << 1),
+	AC_ERR_TIMEOUT		= (1 << 2),
+	AC_ERR_MEDIA		= (1 << 3),
+	AC_ERR_ATA_BUS		= (1 << 4),
+	AC_ERR_HOST_BUS		= (1 << 5),
+	AC_ERR_SYSTEM		= (1 << 6),
+	AC_ERR_INVALID		= (1 << 7),
+	AC_ERR_OTHER		= (1 << 8),
+	AC_ERR_NODEV_HINT	= (1 << 9),
+	AC_ERR_NCQ		= (1 << 10),
+};
+
+enum ata_xfer_mask {
+	ATA_MASK_PIO	= ((1LU << ATA_NR_PIO_MODES) - 1) << ATA_SHIFT_PIO,
+	ATA_MASK_MWDMA	= ((1LU << ATA_NR_MWDMA_MODES) - 1) << ATA_SHIFT_MWDMA,
+	ATA_MASK_UDMA	= ((1LU << ATA_NR_UDMA_MODES) - 1) << ATA_SHIFT_UDMA,
+};
+
+struct ata_port_info {
+	struct scsi_host_template	*sht;
+	unsigned long			flags;
+	unsigned long			link_flags;
+	unsigned long			pio_mask;
+	unsigned long			mwdma_mask;
+	unsigned long			udma_mask;
+	const struct ata_port_operations *port_ops;
+	void				*private_data;
+};
+
+struct ata_ioports {
+	void __iomem		*cmd_addr;
+	void __iomem		*data_addr;
+	void __iomem		*error_addr;
+	void __iomem		*feature_addr;
+	void __iomem		*nsect_addr;
+	void __iomem		*lbal_addr;
+	void __iomem		*lbam_addr;
+	void __iomem		*lbah_addr;
+	void __iomem		*device_addr;
+	void __iomem		*status_addr;
+	void __iomem		*command_addr;
+	void __iomem		*altstatus_addr;
+	void __iomem		*ctl_addr;
+	void __iomem		*bmdma_addr;
+	void __iomem		*scr_addr;
+};
+
+struct ata_host {
+	void __iomem * const	*iomap;
+	unsigned int		n_ports;
+	void			*private_data;
+	const struct ata_port_operations *ops;
+	unsigned long		flags;
+	struct ata_port		*simplex_claimed;
+	struct ata_port		*ports[0];
+};
+
+struct ata_port_stats {
+	unsigned long		unhandled_irq;
+	unsigned long		idle_irq;
+	unsigned long		rw_reqbuf;
+};
+
+struct ata_device {
+	struct ata_link		*link;
+	unsigned int		devno;
+	unsigned long		flags;
+	unsigned int		horkage;
+	struct scsi_device	*sdev;
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	union acpi_object	*gtf_cache;
+#endif
+	u64			n_sectors;
+	unsigned int		class;
+
+	union {
+		u16		id[ATA_ID_WORDS];
+		u32		gscr[SATA_PMP_GSCR_DWORDS];
+	};
+
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;
+
+	unsigned int		multi_count;
+	unsigned int		max_sectors;
+	unsigned int		cdb_len;
+
+	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
+	unsigned long		udma_mask;
+
+	u16			cylinders;
+	u16			heads;
+	u16			sectors;
+
+	int			spdn_cnt;
+};
+
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL = 0,
+	DMA_TO_DEVICE = 1,
+	DMA_FROM_DEVICE = 2,
+	DMA_NONE = 3,
+};
+
+struct ata_link {
+	struct ata_port		*ap;
+	int			pmp;
+	unsigned int		active_tag;
+	u32			sactive;
+
+	unsigned int		flags;
+
+	unsigned int		hw_sata_spd_limit;
+	unsigned int		sata_spd_limit;
+	unsigned int		sata_spd;
+
+	struct ata_device	device[2];
+};
+
+struct ata_port {
+	unsigned long		flags;
+	unsigned int		pflags;
+	unsigned int		print_id;
+	unsigned int		port_no;
+
+	struct ata_ioports	ioaddr;
+
+	u8			ctl;
+	u8			last_ctl;
+	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
+	unsigned int		udma_mask;
+	unsigned int		cbl;
+
+	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+	unsigned long		qc_allocated;
+	unsigned int		qc_active;
+	int			nr_active_links;
+
+	struct ata_link		link;
+
+	int			nr_pmp_links;
+	struct ata_link		*pmp_link;
+	struct ata_link		*excl_link;
+
+	struct ata_port_stats	stats;
+	struct ata_host		*host;
+
+	struct device		*dev;
+	void			*port_task_data;
+
+	unsigned int		hsm_task_state;
+
+	u32			msg_enable;
+	void			*private_data;
+	unsigned char		*pdata;
+};
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif
diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h
index d814012..d9b73dc 100644
--- a/include/configs/canyonlands.h
+++ b/include/configs/canyonlands.h
@@ -454,6 +454,7 @@
   #define CONFIG_CMD_SDRAM
   #define CONFIG_CMD_SNTP
   #define CONFIG_CMD_USB
+#define CONFIG_CMD_SATA
   #elif defined(CONFIG_GLACIER)
   #define CONFIG_CMD_DATE
   #define CONFIG_CMD_DTT
@@ -517,6 +518,21 @@
   #endif /* CONFIG_460GT */

   /*-----------------------------------------------------------------------
+ * S-ATA driver setup
+ *----------------------------------------------------------------------*/
+#define CONFIG_SATA_DWC
+
+#ifdef CONFIG_SATA_DWC
+#define CONFIG_LIBATA
+
+#define SATA_BASE_ADDR		0xe20d1000	/* PPC460EX SATA Base Address */
+#define SATA_DMA_REG_ADDR	0xe20d0800	/* PPC460EX SATA Base Address */
+#define CONFIG_SYS_SATA_MAX_DEVICE	1	/* SATA MAX DEVICE */
+/* Convert sectorsize to wordsize */
+#define ATA_SECTOR_WORDS (ATA_SECT_SIZE/2)
+#endif
+
+/*-----------------------------------------------------------------------
    * External Bus Controller (EBC) Setup
    *----------------------------------------------------------------------*/

-- 
1.6.2.1


Regards,
Kazuaki Ichinohe.

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-04-27  1:53                 ` Kazuaki Ichinohe
@ 2009-04-27  7:42                   ` Stefan Roese
  2009-04-29  6:58                   ` Stefan Roese
  1 sibling, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2009-04-27  7:42 UTC (permalink / raw)
  To: u-boot

Hi Kazuaki Ichinohe,

On Monday 27 April 2009, Kazuaki Ichinohe wrote:
> I sent the SATA patch mail on April 17.
> However, the following content is not confirmed, and there is not a reply
> either. Could you confirm it?
> I re-send the SATA driver patch.

Sorry, I forgot about reviewing it. I'll do this today or tomorrow.

Thanks.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-04-27  1:53                 ` Kazuaki Ichinohe
  2009-04-27  7:42                   ` Stefan Roese
@ 2009-04-29  6:58                   ` Stefan Roese
  2009-05-07  6:23                     ` Kazuaki Ichinohe
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2009-04-29  6:58 UTC (permalink / raw)
  To: u-boot

On Monday 27 April 2009, Kazuaki Ichinohe wrote:
> I sent the SATA patch mail on April 17.
> However, the following content is not confirmed, and there is not a reply
> either. Could you confirm it?
> I re-send the SATA driver patch.

I failed applying your patch:

Applying: Canyonlands SATA harddisk driver
error: patch failed: drivers/block/Makefile:35
error: drivers/block/Makefile: patch does not apply
error: patch failed: include/configs/canyonlands.h:454
error: include/configs/canyonlands.h: patch does not apply
Patch failed at 0001 Canyonlands SATA harddisk driver
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

Could you please rebase your patch against the current top-of-tree mainline 
repository and resumbmit?

Thanks.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-04-29  6:58                   ` Stefan Roese
@ 2009-05-07  6:23                     ` Kazuaki Ichinohe
  2009-05-07  7:38                       ` Wolfgang Denk
  0 siblings, 1 reply; 36+ messages in thread
From: Kazuaki Ichinohe @ 2009-05-07  6:23 UTC (permalink / raw)
  To: u-boot

Hello Denk, Stefan,

 > Could you please rebase your patch against the current top-of-tree mainline
 > repository and resumbmit?

Thank you for the reply.
I made the patch from the source obtained with git in 5/7.
The confirmed patch is sent again.
Please review this patch.
---

This patch adds a SATA harddisk driver for the canyonlands.
This patch is kernel driver's porting.
This pach corresponded to not cmd_scsi but cmd_sata.

[environment variable, boot script]
setenv bootargs root=/dev/sda7 rw
setenv bootargs ${bootargs} console=ttyS0,115200
ext2load sata 0:2 0x400000 /canyonlands/uImage
ext2load sata 0:2 0x800000 /canyonlands/canyonlands.dtb
fdt addr 0x800000 0x4000
bootm 0x400000 - 0x800000

If you drive SATA-2 disk on Canyonlands, you must change parts from
PI2PCIE212 to PI2PCIE2212 on U25. We confirmed to boot by using following disk.

1.Vender: Fujitsu Type: MHW2040BS
2.Vender: Fujitsu Type: MHW2060BK
3.Vendor: HAGIWARA SYS-COM:HFD25S-032GT
4.Vender: WesternDigital Type: WD3200BJKT (CONFIG_LBA48 required)
5.Vender: WesternDigital Type: WD3200BEVT (CONFIG_LBA48 required)
6.Vender: hitachi Type: HTS543232L9A300 (CONFIG_LBA48 required)
7.Vender: Seagate Type: ST31000333AS (CONFIG_LBA48 required)
8.Vender: Transcend Type: TS32GSSD25S-M
9.Vender: MTRON Type: MSD-SATA1525-016

Signed-off-by: Kazuaki Ichinohe <kazuichi@fsi.co.jp>
---

[patch]
diff -uprN u-boot-0507/drivers/block/Makefile u-boot-sata/drivers/block/Makefile
--- u-boot-0507/drivers/block/Makefile	2009-05-07 09:25:48.000000000 +0900
+++ u-boot-sata/drivers/block/Makefile	2009-05-07 09:43:56.000000000 +0900
@@ -35,6 +35,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil
  COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
  COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
  COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

  COBJS	:= $(COBJS-y)
  SRCS	:= $(COBJS:.o=.c)
diff -uprN u-boot-0507/drivers/block/sata_dwc.c u-boot-sata/drivers/block/sata_dwc.c
--- u-boot-0507/drivers/block/sata_dwc.c	1970-01-01 09:00:00.000000000 +0900
+++ u-boot-sata/drivers/block/sata_dwc.c	2009-05-07 09:42:37.000000000 +0900
@@ -0,0 +1,2110 @@
+/*
+ * sata_dwc.c
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU
+ * General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 04-17-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <ata.h>
+#include <linux/ctype.h>
+
+#include "sata_dwc.h"
+
+#define DMA_NUM_CHANS			1
+#define DMA_NUM_CHAN_REGS		8
+
+#define AHB_DMA_BRST_DFLT		16
+
+struct dmareg {
+	u32 low;
+	u32 high;
+};
+
+struct dma_chan_regs {
+	struct dmareg sar;
+	struct dmareg dar;
+	struct dmareg llp;
+	struct dmareg ctl;
+	struct dmareg sstat;
+	struct dmareg dstat;
+	struct dmareg sstatar;
+	struct dmareg dstatar;
+	struct dmareg cfg;
+	struct dmareg sgr;
+	struct dmareg dsr;
+};
+
+struct dma_interrupt_regs {
+	struct dmareg tfr;
+	struct dmareg block;
+	struct dmareg srctran;
+	struct dmareg dsttran;
+	struct dmareg error;
+};
+
+struct ahb_dma_regs {
+	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];
+	struct dma_interrupt_regs	interrupt_raw;
+	struct dma_interrupt_regs	interrupt_status;
+	struct dma_interrupt_regs	interrupt_mask;
+	struct dma_interrupt_regs	interrupt_clear;
+	struct dmareg			statusInt;
+	struct dmareg			rq_srcreg;
+	struct dmareg			rq_dstreg;
+	struct dmareg			rq_sgl_srcreg;
+	struct dmareg			rq_sgl_dstreg;
+	struct dmareg			rq_lst_srcreg;
+	struct dmareg			rq_lst_dstreg;
+	struct dmareg			dma_cfg;
+	struct dmareg			dma_chan_en;
+	struct dmareg			dma_id;
+	struct dmareg			dma_test;
+	struct dmareg			res1;
+	struct dmareg			res2;
+	/* DMA Comp Params
+	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
+	 * Param 4 = dma_param[2] ...
+	 */
+	struct dmareg			dma_params[6];
+};
+
+#define DMA_EN			0x00000001
+#define DMA_DI			0x00000000
+#define DMA_CHANNEL(ch)		(0x00000001 << (ch))
+#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |	\
+				((0x000000001 << (ch)) << 8))
+#define DMA_DISABLE_CHAN(ch)	(0x00000000 | 	\
+				((0x000000001 << (ch)) << 8))
+
+#define SATA_DWC_MAX_PORTS	1
+#define SATA_DWC_SCR_OFFSET	0x24
+#define SATA_DWC_REG_OFFSET	0x64
+
+struct sata_dwc_regs {
+	u32 fptagr;
+	u32 fpbor;
+	u32 fptcr;
+	u32 dmacr;
+	u32 dbtsr;
+	u32 intpr;
+	u32 intmr;
+	u32 errmr;
+	u32 llcr;
+	u32 phycr;
+	u32 physr;
+	u32 rxbistpd;
+	u32 rxbistpd1;
+	u32 rxbistpd2;
+	u32 txbistpd;
+	u32 txbistpd1;
+	u32 txbistpd2;
+	u32 bistcr;
+	u32 bistfctr;
+	u32 bistsr;
+	u32 bistdecr;
+	u32 res[15];
+	u32 testr;
+	u32 versionr;
+	u32 idr;
+	u32 unimpl[192];
+	u32 dmadr[256];
+};
+
+#define SATA_DWC_TXFIFO_DEPTH		0x01FF
+#define SATA_DWC_RXFIFO_DEPTH		0x01FF
+
+#define SATA_DWC_DBTSR_MWR(size)	((size / 4) & SATA_DWC_TXFIFO_DEPTH)
+#define SATA_DWC_DBTSR_MRD(size)	(((size / 4) &	\
+					SATA_DWC_RXFIFO_DEPTH) << 16)
+#define SATA_DWC_INTPR_DMAT		0x00000001
+#define SATA_DWC_INTPR_NEWFP		0x00000002
+#define SATA_DWC_INTPR_PMABRT		0x00000004
+#define SATA_DWC_INTPR_ERR		0x00000008
+#define SATA_DWC_INTPR_NEWBIST		0x00000010
+#define SATA_DWC_INTPR_IPF		0x10000000
+#define SATA_DWC_INTMR_DMATM		0x00000001
+#define SATA_DWC_INTMR_NEWFPM		0x00000002
+#define SATA_DWC_INTMR_PMABRTM		0x00000004
+#define SATA_DWC_INTMR_ERRM		0x00000008
+#define SATA_DWC_INTMR_NEWBISTM		0x00000010
+
+#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
+#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
+
+#define SATA_DWC_QCMD_MAX	32
+
+#define SATA_DWC_SERROR_ERR_BITS	0x0FFF0F03
+
+#define HSDEVP_FROM_AP(ap)	(struct sata_dwc_device_port*)	\
+				(ap)->private_data
+
+struct sata_dwc_device {
+	struct device		*dev;
+	struct ata_probe_ent	*pe;
+	struct ata_host		*host;
+	u8			*reg_base;
+	struct sata_dwc_regs	*sata_dwc_regs;
+	int			irq_dma;
+};
+
+struct sata_dwc_device_port {
+	struct sata_dwc_device	*hsdev;
+	int			cmd_issued[SATA_DWC_QCMD_MAX];
+	u32			dma_chan[SATA_DWC_QCMD_MAX];
+	int			dma_pending[SATA_DWC_QCMD_MAX];
+};
+
+enum {
+	SATA_DWC_CMD_ISSUED_NOT		= 0,
+	SATA_DWC_CMD_ISSUED_PEND	= 1,
+	SATA_DWC_CMD_ISSUED_EXEC	= 2,
+	SATA_DWC_CMD_ISSUED_NODATA	= 3,
+
+	SATA_DWC_DMA_PENDING_NONE	= 0,
+	SATA_DWC_DMA_PENDING_TX		= 1,
+	SATA_DWC_DMA_PENDING_RX		= 2,
+};
+
+#define msleep(a)	udelay(a * 1000)
+#define ssleep(a)	msleep(a * 1000)
+
+static int ata_probe_timeout = (ATA_TMOUT_INTERNAL / 100);
+
+enum sata_dev_state {
+	SATA_INIT = 0,
+	SATA_READY = 1,
+	SATA_NODEVICE = 2,
+	SATA_ERROR = 3,
+};
+enum sata_dev_state dev_state = SATA_INIT;
+
+static struct ahb_dma_regs		*sata_dma_regs = 0;
+static struct ata_host			*phost;
+static struct ata_port			ap;
+static struct ata_port			*pap = &ap;
+static struct ata_device		ata_device;
+static struct sata_dwc_device_port	dwc_devp;
+
+static void	*scr_addr_sstatus;
+static u32	temp_n_block = 0;
+
+static unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout);
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+			u8 enable,u8 feature);
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+			u16 heads, u16 sectors);
+static u8 ata_irq_on(struct ata_port *ap);
+static struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+			unsigned int tag);
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq);
+static void ata_tf_to_host(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static void ata_exec_command(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+static u8 ata_check_altstatus(struct ata_port *ap);
+static u8 ata_check_status(struct ata_port *ap);
+static void ata_dev_select(struct ata_port *ap, unsigned int device,
+			unsigned int wait, unsigned int can_sleep);
+static void ata_qc_issue(struct ata_queued_cmd *qc);
+static void ata_tf_load(struct ata_port *ap,
+			const struct ata_taskfile *tf);
+static int ata_dev_read_sectors(unsigned char* pdata,
+			unsigned long datalen, u32 block, u32 n_block);
+static int ata_dev_write_sectors(unsigned char* pdata,
+			unsigned long datalen , u32 block, u32 n_block);
+static void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+static void ata_qc_complete(struct ata_queued_cmd *qc);
+static void __ata_qc_complete(struct ata_queued_cmd *qc);
+static void fill_result_tf(struct ata_queued_cmd *qc);
+static void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void ata_mmio_data_xfer(struct ata_device *dev,
+			unsigned char *buf,
+			unsigned int buflen,int do_write);
+static void ata_pio_task(struct ata_port *arg_ap);
+static void __ata_port_freeze(struct ata_port *ap);
+static int ata_port_freeze(struct ata_port *ap);
+static void ata_qc_free(struct ata_queued_cmd *qc);
+static void ata_pio_sectors(struct ata_queued_cmd *qc);
+static void ata_pio_sector(struct ata_queued_cmd *qc);
+static void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay);
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq);
+static int sata_dwc_softreset(struct ata_port *ap);
+static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id);
+static int check_sata_dev_state(void);
+
+extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
+
+static const struct ata_port_info sata_dwc_port_info[] = {
+	{
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING |
+				ATA_FLAG_SRST | ATA_FLAG_NCQ,
+		.pio_mask	= 0x1f,
+		.mwdma_mask	= 0x07,
+		.udma_mask	= 0x7f,
+	},
+};
+
+int init_sata (int dev)
+{
+	struct sata_dwc_device hsdev;
+	struct ata_host host;
+	struct ata_port_info pi = sata_dwc_port_info[0];
+	struct ata_link *link;
+	struct sata_dwc_device_port hsdevp = dwc_devp;
+	u8 *base = 0;
+	u8 *sata_dma_regs_addr = 0;
+	u8 status;
+	unsigned long base_addr = 0;
+	int chan = 0;
+	int rc;
+	int i;
+
+	phost = &host;
+
+	base = (u8*)SATA_BASE_ADDR;
+
+	hsdev.sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+
+	host.n_ports = SATA_DWC_MAX_PORTS;
+
+	for (i = 0; i < SATA_DWC_MAX_PORTS; i++) {
+		ap.pflags |= ATA_PFLAG_INITIALIZING;
+		ap.flags = ATA_FLAG_DISABLED;
+		ap.print_id = -1;
+		ap.ctl = ATA_DEVCTL_OBS;
+		ap.host = &host;
+		ap.last_ctl = 0xFF;
+
+		link = &ap.link;
+		link->ap = &ap;
+		link->pmp = 0;
+		link->active_tag = ATA_TAG_POISON;
+		link->hw_sata_spd_limit = 0;
+
+		ap.port_no = i;
+		host.ports[i] = &ap;
+	}
+
+	ap.pio_mask = pi.pio_mask;
+	ap.mwdma_mask = pi.mwdma_mask;
+	ap.udma_mask = pi.udma_mask;
+	ap.flags |= pi.flags;
+	ap.link.flags |= pi.link_flags;
+
+	host.ports[0]->ioaddr.cmd_addr = base;
+	host.ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
+	scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
+
+	base_addr = (unsigned long)base;
+
+	host.ports[0]->ioaddr.cmd_addr = (void *)base_addr + 0x00;
+	host.ports[0]->ioaddr.data_addr = (void *)base_addr + 0x00;
+
+	host.ports[0]->ioaddr.error_addr = (void *)base_addr + 0x04;
+	host.ports[0]->ioaddr.feature_addr = (void *)base_addr + 0x04;
+
+	host.ports[0]->ioaddr.nsect_addr = (void *)base_addr + 0x08;
+
+	host.ports[0]->ioaddr.lbal_addr = (void *)base_addr + 0x0c;
+	host.ports[0]->ioaddr.lbam_addr = (void *)base_addr + 0x10;
+	host.ports[0]->ioaddr.lbah_addr = (void *)base_addr + 0x14;
+
+	host.ports[0]->ioaddr.device_addr = (void *)base_addr + 0x18;
+	host.ports[0]->ioaddr.command_addr = (void *)base_addr + 0x1c;
+	host.ports[0]->ioaddr.status_addr = (void *)base_addr + 0x1c;
+
+	host.ports[0]->ioaddr.altstatus_addr = (void *)base_addr + 0x20;
+	host.ports[0]->ioaddr.ctl_addr = (void *)base_addr + 0x20;
+
+	sata_dma_regs_addr = (u8*)SATA_DMA_REG_ADDR;
+	sata_dma_regs = (void *__iomem)sata_dma_regs_addr;
+
+	status = ata_check_altstatus(&ap);
+
+	if (status == 0x7f) {
+		printf("Hard Disk not found.\n");
+		dev_state = SATA_NODEVICE;
+		rc = FALSE;
+		return rc;
+	}
+
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);
+
+		status = ata_check_altstatus(&ap);
+
+		if ((status & ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			dev_state = SATA_NODEVICE;
+			rc = FALSE;
+			return rc;
+		}
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	rc = sata_dwc_softreset(&ap);
+
+	if (rc) {
+		printf("sata_dwc : error. soft reset failed\n");
+		return rc;
+	}
+
+	for (chan = 0; chan < DMA_NUM_CHANS; chan++) {
+		out_le32(&(sata_dma_regs->interrupt_mask.error.low),
+				DMA_DISABLE_CHAN(chan));
+
+		out_le32(&(sata_dma_regs->interrupt_mask.tfr.low),
+				DMA_DISABLE_CHAN(chan));
+	}
+
+	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_DI);
+
+	out_le32(&hsdev.sata_dwc_regs->intmr,
+		SATA_DWC_INTMR_ERRM |
+		SATA_DWC_INTMR_PMABRTM);
+
+	/* Unmask the error bits that should trigger
+	 * an error interrupt by setting the error mask register.
+	 */
+	out_le32(&hsdev.sata_dwc_regs->errmr,SATA_DWC_SERROR_ERR_BITS);
+
+	hsdev.host = ap.host;
+	memset(&hsdevp, 0, sizeof(hsdevp));
+	hsdevp.hsdev = &hsdev;
+
+	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
+		hsdevp.cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
+
+	out_le32((void __iomem *)scr_addr_sstatus + 4,
+		in_le32((void __iomem *)scr_addr_sstatus + 4));
+
+	rc = 0;
+	return rc;
+}
+
+static u8 ata_check_altstatus(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.altstatus_addr);
+	return val;
+}
+
+static int sata_dwc_softreset(struct ata_port *ap)
+{
+	u8 nsect,lbal = 0;
+	u8 tmp = 0;
+	u32 serror = 0;
+	u8 status = 0;
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	serror = in_le32((void *)ap->ioaddr.scr_addr + (SCR_ERROR * 4));
+
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+	writeb(0xaa, ioaddr->nsect_addr);
+	writeb(0x55, ioaddr->lbal_addr);
+	writeb(0x55, ioaddr->nsect_addr);
+	writeb(0xaa, ioaddr->lbal_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa)) {
+		printf("we found a device\n");
+	} else {
+		printf("Not found a device.\n");
+		dev_state = SATA_NODEVICE;
+		return FALSE;
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	udelay(200);
+
+	writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+
+	udelay(200);
+	writeb(ap->ctl,ioaddr->ctl_addr);
+
+	msleep(150);
+	status = ata_check_status(ap);
+
+	msleep(50);
+	ata_check_status(ap);
+
+	while (1) {
+		u8 status = ata_check_status(ap);
+
+		if (!(status & ATA_BUSY))
+			break;
+
+		printf("Hard Disk status is BUSY.\n");
+		msleep(50);
+	}
+
+	tmp = ATA_DEVICE_OBS;
+	writeb(tmp,ioaddr->device_addr);
+
+	nsect = readb(ioaddr->nsect_addr);
+	lbal = readb(ioaddr->lbal_addr);
+
+	return 0;
+}
+
+static u8 ata_check_status(struct ata_port *ap)
+{
+	u8 val = 0;
+	val = readb(ap->ioaddr.status_addr);
+	return val;
+}
+
+static int ata_id_has_hipm(const u16 *id)
+{
+	u16 val = id[76];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 9);
+}
+
+static int ata_id_has_dipm(const u16 *id)
+{
+	u16 val = id[78];
+
+	if (val == 0 || val == 0xffff)
+		return -1;
+
+	return val & (1 << 3);
+}
+
+int scan_sata (int dev)
+{
+	int i;
+	int rc;
+	u8 status;
+	const u16 *id;
+	struct ata_device *ata_dev = &ata_device;
+	unsigned long pio_mask, mwdma_mask, udma_mask;
+	unsigned long xfer_mask;
+	char revbuf[7];
+	u16 iobuf[ATA_SECTOR_WORDS];
+
+	memset ( iobuf, 0, sizeof(iobuf));
+
+	if (dev_state == SATA_NODEVICE)
+		return 1;
+
+	printf("waitng for device ready.");
+	i = 0;
+	while (1) {
+		udelay (10000);
+
+		status = ata_check_altstatus(&ap);
+
+		if ((status & ATA_BUSY) == 0) {
+			printf("\n");
+			break;
+		}
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+
+			dev_state = SATA_NODEVICE;
+			return 1;
+		}
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	udelay (1000);
+
+	rc = ata_dev_read_id(ata_dev, &ata_dev->class,
+			ATA_READID_POSTRESET,ata_dev->id);
+	if (rc) {
+		printf("sata_dwc : error. failed sata scan\n");
+		return 1;
+	}
+
+	/* SATA drives indicate we have a bridge. We don't know which
+	 * end of the link the bridge is which is a problem
+	 */
+	if (ata_id_is_sata(ata_dev->id))
+		ap.cbl = ATA_CBL_SATA;
+
+	id = ata_dev->id;
+
+	ata_dev->flags &= ~ATA_DFLAG_CFG_MASK;
+	ata_dev->max_sectors = 0;
+	ata_dev->cdb_len = 0;
+	ata_dev->n_sectors = 0;
+	ata_dev->cylinders = 0;
+	ata_dev->heads = 0;
+	ata_dev->sectors = 0;
+
+	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+		pio_mask = id[ATA_ID_PIO_MODES] & 0x03;
+		pio_mask <<= 3;
+		pio_mask |= 0x7;
+	} else {
+		/* If word 64 isn't valid then Word 51 high byte holds
+		 * the PIO timing number for the maximum. Turn it into
+		 * a mask.
+		 */
+		u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
+		if (mode < 5) {
+			pio_mask = (2 << mode) - 1;
+		} else {
+			pio_mask = 1;
+		}
+	}
+
+	mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07;
+
+	if (ata_id_is_cfa(id)) {
+		int pio = id[163] & 0x7;
+		int dma = (id[163] >> 3) & 7;
+
+		if (pio)
+			pio_mask |= (1 << 5);
+		if (pio > 1)
+			pio_mask |= (1 << 6);
+		if (dma)
+			mwdma_mask |= (1 << 3);
+		if (dma > 1)
+			mwdma_mask |= (1 << 4);
+	}
+
+	udma_mask = 0;
+	if (id[ATA_ID_FIELD_VALID] & (1 << 2))
+		udma_mask = id[ATA_ID_UDMA_MODES] & 0xff;
+
+	xfer_mask = ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
+		((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
+		((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
+
+	if (ata_dev->class == ATA_DEV_ATA) {
+		if (ata_id_is_cfa(id)) {
+			if (id[162] & 1)
+				printf("supports DRM functions and may "
+					"not be fully accessable.\n");
+			sprintf(revbuf, "%s", "CFA");
+		} else {
+			if (ata_id_has_tpm(id))
+				printf("supports DRM functions and may "
+						"not be fully accessable.\n");
+		}
+
+		ata_dev->n_sectors = ata_id_n_sectors((u16*)id);
+
+		if (ata_dev->id[59] & 0x100)
+			ata_dev->multi_count = ata_dev->id[59] & 0xff;
+
+		if (ata_id_has_lba(id)) {
+			const char *lba_desc;
+			char ncq_desc[20];
+
+			lba_desc = "LBA";
+			ata_dev->flags |= ATA_DFLAG_LBA;
+			if (ata_id_has_lba48(id)) {
+				ata_dev->flags |= ATA_DFLAG_LBA48;
+				lba_desc = "LBA48";
+
+				if (ata_dev->n_sectors >= (1UL << 28) &&
+					ata_id_has_flush_ext(id))
+					ata_dev->flags |= ATA_DFLAG_FLUSH_EXT;
+			}
+			if (!ata_id_has_ncq(ata_dev->id))
+				ncq_desc[0] = '\0';
+
+			if (ata_dev->horkage & ATA_HORKAGE_NONCQ)
+				sprintf(ncq_desc, "%s", "NCQ (not used)");
+
+			if (ap.flags & ATA_FLAG_NCQ)
+				ata_dev->flags |= ATA_DFLAG_NCQ;
+		}
+		ata_dev->cdb_len = 16;
+	}
+	ata_dev->max_sectors = ATA_MAX_SECTORS;
+	if (ata_dev->flags & ATA_DFLAG_LBA48)
+		ata_dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
+	if (!(ata_dev->horkage & ATA_HORKAGE_IPM)) {
+		if (ata_id_has_hipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_HIPM;
+		if (ata_id_has_dipm(ata_dev->id))
+			ata_dev->flags |= ATA_DFLAG_DIPM;
+	}
+
+	if ((ap.cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ata_dev->id))) {
+		ata_dev->udma_mask &= ATA_UDMA5;
+		ata_dev->max_sectors = ATA_MAX_SECTORS;
+	}
+
+	if (ata_dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+		printf("Drive reports diagnostics failure."
+				"This may indicate a drive\n");
+		printf("fault or invalid emulation."
+				"Contact drive vendor for information.\n");
+	}
+
+	rc = check_sata_dev_state();
+
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].revision,
+			 ATA_ID_FW_REV, sizeof(sata_dev_desc[dev].revision));
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].vendor,
+			 ATA_ID_PROD, sizeof(sata_dev_desc[dev].vendor));
+	ata_id_c_string (ata_dev->id,
+			(unsigned char *)sata_dev_desc[dev].product,
+			 ATA_ID_SERNO, sizeof(sata_dev_desc[dev].product));
+
+	sata_dev_desc[dev].lba = (u32) ata_dev->n_sectors;
+
+#ifdef CONFIG_LBA48
+	if (ata_dev->id[83] & (1 << 10)) {
+		sata_dev_desc[dev].lba48 = 1;
+	} else {
+		sata_dev_desc[dev].lba48 = 0;
+	}
+#endif
+
+	return 0;
+}
+
+static u8 ata_busy_wait(struct ata_port *ap,
+		unsigned int bits,unsigned int max)
+{
+	u8 status;
+
+	do {
+		udelay(10);
+		status = ata_check_status(ap);
+		max--;
+	} while (status != 0xff && (status & bits) && (max > 0));
+
+	return status;
+}
+
+static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		unsigned int flags, u16 *id)
+{
+	struct ata_port *ap = pap;
+	unsigned int class = *p_class;
+	struct ata_taskfile tf;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1, tried_spinup = 0;
+	u8 status;
+	int rc;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_ID_ATA;
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+
+	/* Device presence detection is unreliable on some
+	 * controllers.  Always poll IDENTIFY if available.
+	 */
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	temp_n_block = 1;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+					sizeof(id[0]) * ATA_ID_WORDS, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	unsigned int id_cnt;
+
+	for (id_cnt = 0; id_cnt < ATA_ID_WORDS; id_cnt++)
+		id[id_cnt] = le16_to_cpu(id[id_cnt]);
+
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	if (class == ATA_DEV_ATA) {
+		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
+			goto err_out;
+	} else {
+		if (ata_id_is_ata(id))
+			goto err_out;
+	}
+	if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+		tried_spinup = 1;
+		/*
+		 * Drive powered-up in standby mode, and requires a specific
+		 * SET_FEATURES spin-up subcommand before it will accept
+		 * anything other than the original IDENTIFY command.
+		 */
+		err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+		if (err_mask && id[2] != 0x738c) {
+			rc = -EIO;
+			reason = "SPINUP failed";
+			goto err_out;
+		}
+		/*
+		 * If the drive initially returned incomplete IDENTIFY info,
+		 * we now must reissue the IDENTIFY command.
+		 */
+		if (id[2] == 0x37c8)
+			goto retry;
+	}
+
+	if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) {
+		/*
+		 * The exact sequence expected by certain pre-ATA4 drives is:
+		 * SRST RESET
+		 * IDENTIFY (optional in early ATA)
+		 * INITIALIZE DEVICE PARAMETERS (later IDE and ATA)
+		 * anything else..
+		 * Some drives were very specific about that exact sequence.
+		 *
+		 * Note that ATA4 says lba is mandatory so the second check
+		 * shoud never trigger.
+		 */
+		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+			err_mask = ata_dev_init_params(dev, id[3], id[6]);
+			if (err_mask) {
+				rc = -EIO;
+				reason = "INIT_DEV_PARAMS failed";
+				goto err_out;
+			}
+
+			/* current CHS translation info (id[53-58]) might be
+			 * changed. reread the identify device info.
+			 */
+			flags &= ~ATA_READID_POSTRESET;
+			goto retry;
+		}
+	}
+
+	*p_class = class;
+	return 0;
+
+err_out:
+	return rc;
+}
+
+static u8 ata_wait_idle(struct ata_port *ap)
+{
+	u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	return status;
+}
+
+static void ata_dev_select(struct ata_port *ap, unsigned int device,
+		unsigned int wait, unsigned int can_sleep)
+{
+	if (wait)
+		ata_wait_idle(ap);
+
+	ata_std_dev_select(ap, device);
+
+	if (wait)
+		ata_wait_idle(ap);
+}
+
+static void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+{
+	u8 tmp;
+
+	if (device == 0) {
+		tmp = ATA_DEVICE_OBS;
+	} else {
+		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+	}
+
+	writeb(tmp, ap->ioaddr.device_addr);
+
+	readb(ap->ioaddr.altstatus_addr);
+
+	udelay(1);
+}
+
+static int waiting_for_reg_state(volatile u8 *offset,
+				int timeout_msec,
+				u32 sign)
+{
+	int i;
+	u32 status;
+
+	for (i = 0; i < timeout_msec; i++) {
+		status = readl(offset);
+		if ((status & sign) != 0)
+			break;
+		msleep(1);
+	}
+
+	return (i < timeout_msec) ? 0 : -1;
+}
+
+static void ata_qc_reinit(struct ata_queued_cmd *qc)
+{
+	qc->dma_dir = DMA_NONE;
+	qc->flags = 0;
+	qc->nbytes = qc->extrabytes = qc->curbytes = 0;
+	qc->n_elem = 0;
+	qc->err_mask = 0;
+	qc->sect_size = ATA_SECT_SIZE;
+	qc->nbytes = ATA_SECT_SIZE * temp_n_block;
+
+	memset(&qc->tf, 0, sizeof(qc->tf));
+	qc->tf.ctl = 0;
+	qc->tf.device = ATA_DEVICE_OBS;
+
+	qc->result_tf.command = ATA_DRDY;
+	qc->result_tf.feature = 0;
+}
+
+struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+					unsigned int tag)
+{
+	if (tag < ATA_MAX_QUEUE)
+		return &ap->qcmd[tag];
+	return NULL;
+}
+
+static void __ata_port_freeze(struct ata_port *ap)
+{
+	printf("set port freeze.\n");
+	ap->pflags |= ATA_PFLAG_FROZEN;
+}
+
+static int ata_port_freeze(struct ata_port *ap)
+{
+	__ata_port_freeze(ap);
+	return 0;
+}
+
+unsigned ata_exec_internal(struct ata_device *dev,
+			struct ata_taskfile *tf, const u8 *cdb,
+			int dma_dir, unsigned int buflen,
+			unsigned long timeout)
+{
+	struct ata_link *link = dev->link;
+	struct ata_port *ap = pap;
+	struct ata_queued_cmd *qc;
+	unsigned int tag, preempted_tag;
+	u32 preempted_sactive, preempted_qc_active;
+	int preempted_nr_active_links;
+	unsigned int err_mask;
+	int rc = 0;
+	u8 status;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 300000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		rc = FALSE;
+		return rc;
+	}
+
+	if (ap->pflags & ATA_PFLAG_FROZEN)
+		return AC_ERR_SYSTEM;
+
+	tag = ATA_TAG_INTERNAL;
+
+	if (test_and_set_bit(tag, &ap->qc_allocated)) {
+		rc = FALSE;
+		return rc;
+	}
+
+	qc = __ata_qc_from_tag(ap, tag);
+	qc->tag = tag;
+	qc->ap = ap;
+	qc->dev = dev;
+
+	ata_qc_reinit(qc);
+
+	preempted_tag = link->active_tag;
+	preempted_sactive = link->sactive;
+	preempted_qc_active = ap->qc_active;
+	preempted_nr_active_links = ap->nr_active_links;
+	link->active_tag = ATA_TAG_POISON;
+	link->sactive = 0;
+	ap->qc_active = 0;
+	ap->nr_active_links = 0;
+
+	qc->tf = *tf;
+	if (cdb)
+		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+	qc->dma_dir = dma_dir;
+	qc->private_data = 0;
+
+	ata_qc_issue(qc);
+
+	if (!timeout)
+		timeout = ata_probe_timeout * 1000 / HZ;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 30000);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		printf("altstatus = 0x%x.\n",status);
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	if (waiting_for_reg_state(ap->ioaddr.altstatus_addr,1000,0x8)) {
+		u8 status = 0;
+		u8 errorStatus = 0;
+
+		status = readb( ap->ioaddr.altstatus_addr);
+		if ((status & 0x01) != 0) {
+			errorStatus = readb( ap->ioaddr.feature_addr);
+			if (errorStatus == 0x04 &&
+				qc->tf.command == ATA_CMD_PIO_READ_EXT){
+				printf("Hard Disk doesn't support LBA48\n");
+				dev_state = SATA_ERROR;
+				qc->err_mask |= AC_ERR_OTHER;
+				return qc->err_mask;
+			}
+		}
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	status = ata_busy_wait(ap, ATA_BUSY, 10);
+	if (status & ATA_BUSY) {
+		printf("BSY = 0 check. timeout.\n");
+		qc->err_mask |= AC_ERR_OTHER;
+		return qc->err_mask;
+	}
+
+	ata_pio_task(ap);
+
+	if (!rc) {
+		if (qc->flags & ATA_QCFLAG_ACTIVE) {
+			qc->err_mask |= AC_ERR_TIMEOUT;
+			ata_port_freeze(ap);
+		}
+	}
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (qc->result_tf.command & (ATA_ERR | ATA_DF))
+			qc->err_mask |= AC_ERR_DEV;
+
+		if (!qc->err_mask)
+			qc->err_mask |= AC_ERR_OTHER;
+
+		if (qc->err_mask & ~AC_ERR_OTHER)
+			qc->err_mask &= ~AC_ERR_OTHER;
+	}
+
+	*tf = qc->result_tf;
+	err_mask = qc->err_mask;
+	ata_qc_free(qc);
+	link->active_tag = preempted_tag;
+	link->sactive = preempted_sactive;
+	ap->qc_active = preempted_qc_active;
+	ap->nr_active_links = preempted_nr_active_links;
+
+	if (ap->flags & ATA_FLAG_DISABLED) {
+		err_mask |= AC_ERR_SYSTEM;
+		ap->flags &= ~ATA_FLAG_DISABLED;
+	}
+
+	return err_mask;
+}
+
+static void ata_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+	u8 prot = qc->tf.protocol;
+
+	if (ata_is_ncq(prot)) {
+		if (!link->sactive)
+			ap->nr_active_links++;
+		link->sactive |= 1 << qc->tag;
+	} else {
+		ap->nr_active_links++;
+		link->active_tag = qc->tag;
+	}
+
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+	ap->qc_active |= 1 << qc->tag;
+
+	if (qc->dev->flags & ATA_DFLAG_SLEEPING) {
+		msleep(1);
+		return;
+	}
+
+	qc->err_mask |= ata_qc_issue_prot(qc);
+	if (qc->err_mask)
+		goto err;
+
+	return;
+err:
+	ata_qc_complete(qc);
+}
+
+static unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+		switch (qc->tf.protocol) {
+		case ATA_PROT_PIO:
+		case ATA_PROT_NODATA:
+		case ATAPI_PROT_PIO:
+		case ATAPI_PROT_NODATA:
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			qc->tf.ctl |= ATA_NIEN;
+
+		ata_tf_to_host(ap, &qc->tf);
+
+		ap->hsm_task_state = HSM_ST;
+
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_pio_queue_task(ap, qc, 0);
+
+		break;
+
+	default:
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+static void ata_tf_to_host(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	ata_tf_load(ap, tf);
+	ata_exec_command(ap, tf);
+}
+
+static void ata_tf_load(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		if (ioaddr->ctl_addr)
+			writeb(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writeb(tf->hob_feature, ioaddr->feature_addr);
+		writeb(tf->hob_nsect, ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, ioaddr->lbah_addr);
+	}
+
+	if (is_addr) {
+		writeb(tf->feature, ioaddr->feature_addr);
+		writeb(tf->nsect, ioaddr->nsect_addr);
+		writeb(tf->lbal, ioaddr->lbal_addr);
+		writeb(tf->lbam, ioaddr->lbam_addr);
+		writeb(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE)
+		writeb(tf->device, ioaddr->device_addr);
+
+	ata_wait_idle(ap);
+}
+
+static void ata_exec_command(struct ata_port *ap,
+			const struct ata_taskfile *tf)
+{
+	writeb(tf->command, ap->ioaddr.command_addr);
+
+	readb(ap->ioaddr.altstatus_addr);
+
+	udelay(1);
+}
+
+static void ata_pio_queue_task(struct ata_port *ap,
+			void *data,unsigned long delay)
+{
+	ap->port_task_data = data;
+}
+
+static unsigned int ac_err_mask(u8 status)
+{
+	if (status & (ATA_BUSY | ATA_DRQ))
+		return AC_ERR_HSM;
+	if (status & (ATA_ERR | ATA_DF))
+		return AC_ERR_DEV;
+	return 0;
+}
+
+static unsigned int __ac_err_mask(u8 status)
+{
+	unsigned int mask = ac_err_mask(status);
+	if (mask == 0)
+		return AC_ERR_OTHER;
+	return mask;
+}
+
+static void ata_pio_task(struct ata_port *arg_ap)
+{
+	struct ata_port *ap = arg_ap;
+	struct ata_queued_cmd *qc = ap->port_task_data;
+	u8 status;
+	int poll_next;
+
+fsm_start:
+	/*
+	 * This is purely heuristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, queue delayed work.
+	 */
+	status = ata_busy_wait(ap, ATA_BUSY, 5);
+	if (status & ATA_BUSY) {
+		msleep(2);
+		status = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (status & ATA_BUSY) {
+			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+			return;
+		}
+	}
+
+	poll_next = ata_hsm_move(ap, qc, status, 1);
+
+	/* another command or interrupt handler
+	 * may be running at this point.
+	 */
+	if (poll_next)
+		goto fsm_start;
+}
+
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq)
+{
+	int poll_next;
+
+fsm_start:
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+		if ((status & ATA_DRQ) == 0) {
+			if (status & (ATA_ERR | ATA_DF)) {
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				qc->err_mask |= AC_ERR_HSM;
+			}
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Device should not ask for data transfer (DRQ=1)
+		 * when it finds something wrong.
+		 * We ignore DRQ here and stop the HSM by
+		 * changing hsm_task_state to HSM_ST_ERR and
+		 * let the EH abort the command or reset the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+				printf("DRQ=1 with device error, "
+					"dev_stat 0x%X\n", status);
+				qc->err_mask |= AC_ERR_HSM;
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+		}
+
+		if (qc->tf.protocol == ATA_PROT_PIO) {
+			/* PIO data out protocol.
+			 * send first data block.
+			 */
+			/* ata_pio_sectors() might change the state
+			 * to HSM_ST_LAST. so, the state is changed here
+			 * before ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST;
+			ata_pio_sectors(qc);
+		} else {
+			printf("protocol is not ATA_PROT_PIO \n");
+		}
+		break;
+
+	case HSM_ST:
+		if ((status & ATA_DRQ) == 0) {
+			if (status & (ATA_ERR | ATA_DF)) {
+				qc->err_mask |= AC_ERR_DEV;
+			} else {
+				/* HSM violation. Let EH handle this.
+				 * Phantom devices also trigger this
+				 * condition.  Mark hint.
+				 */
+				qc->err_mask |= AC_ERR_HSM | AC_ERR_NODEV_HINT;
+			}
+
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+		/* For PIO reads, some devices may ask for
+		 * data transfer (DRQ=1) alone with ERR=1.
+		 * We respect DRQ here and transfer one
+		 * block of junk data before changing the
+		 * hsm_task_state to HSM_ST_ERR.
+		 *
+		 * For PIO writes, ERR=1 DRQ=1 doesn't make
+		 * sense since the data block has been
+		 * transferred to the device.
+		 */
+		if (status & (ATA_ERR | ATA_DF)) {
+			qc->err_mask |= AC_ERR_DEV;
+
+			if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+				ata_pio_sectors(qc);
+				status = ata_wait_idle(ap);
+			}
+
+			if (status & (ATA_BUSY | ATA_DRQ))
+				qc->err_mask |= AC_ERR_HSM;
+
+			/* ata_pio_sectors() might change the
+			 * state to HSM_ST_LAST. so, the state
+			 * is changed after ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ata_pio_sectors(qc);
+		if (ap->hsm_task_state == HSM_ST_LAST &&
+			(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+			status = ata_wait_idle(ap);
+			goto fsm_start;
+		}
+
+		poll_next = 1;
+		break;
+
+	case HSM_ST_LAST:
+		if (!ata_ok(status)) {
+			qc->err_mask |= __ac_err_mask(status);
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+
+	case HSM_ST_ERR:
+		/* make sure qc->err_mask is available to
+		 * know what's wrong and recover
+		 */
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+	default:
+		poll_next = 0;
+	}
+
+	return poll_next;
+}
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap;
+	ap = pap;
+	qc->pdata = ap->pdata;
+
+	ata_pio_sector(qc);
+
+	readb(qc->ap->ioaddr.altstatus_addr);
+	udelay(1);
+}
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	struct ata_port *ap = qc->ap;
+	unsigned int offset;
+	unsigned char *buf;
+	char temp_data_buf[512];
+
+	if (qc->curbytes == qc->nbytes - qc->sect_size)
+		ap->hsm_task_state = HSM_ST_LAST;
+
+	offset = qc->curbytes;
+
+	switch (qc->tf.command) {
+	case ATA_CMD_ID_ATA:
+		buf = (unsigned char *)&ata_device.id[0];
+		break;
+	case ATA_CMD_PIO_READ_EXT:
+	case ATA_CMD_PIO_READ:
+	case ATA_CMD_PIO_WRITE_EXT:
+	case ATA_CMD_PIO_WRITE:
+		buf = qc->pdata + offset;
+		break;
+	default:
+		buf = (unsigned char *)&temp_data_buf[0];
+	}
+
+	ata_mmio_data_xfer(qc->dev, buf, qc->sect_size, do_write);
+
+	qc->curbytes += qc->sect_size;
+
+}
+
+static void ata_mmio_data_xfer(struct ata_device *dev, unsigned char *buf,
+				unsigned int buflen, int do_write)
+{
+	struct ata_port *ap = pap;
+	void __iomem *data_addr = ap->ioaddr.data_addr;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *)buf;
+	unsigned int i = 0;
+
+	udelay(100);
+	if (do_write) {
+		for (i = 0; i < words; i++)
+			writew(le16_to_cpu(buf16[i]), data_addr);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(readw(data_addr));
+	}
+
+	if (buflen & 0x01) {
+		__le16 align_buf[1] = { 0 };
+		unsigned char *trailing_buf = buf + buflen - 1;
+
+		if (do_write) {
+			memcpy(align_buf, trailing_buf, 1);
+			writew(le16_to_cpu(align_buf[0]), data_addr);
+		} else {
+			align_buf[0] = cpu_to_le16(readw(data_addr));
+			memcpy(trailing_buf, align_buf, 1);
+		}
+	}
+}
+
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (in_wq) {
+		/* EH might have kicked in while host lock is
+		 * released.
+		 */
+		qc = &ap->qcmd[qc->tag];
+		if (qc) {
+			if (!(qc->err_mask & AC_ERR_HSM)) {
+				ata_irq_on(ap);
+				ata_qc_complete(qc);
+			} else {
+				ata_port_freeze(ap);
+			}
+		}
+	} else {
+		if (!(qc->err_mask & AC_ERR_HSM)) {
+			ata_qc_complete(qc);
+		} else {
+			ata_port_freeze(ap);
+		}
+	}
+}
+
+static u8 ata_irq_on(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 tmp;
+
+	ap->ctl &= ~ATA_NIEN;
+	ap->last_ctl = ap->ctl;
+
+	if (ioaddr->ctl_addr)
+		writeb(ap->ctl, ioaddr->ctl_addr);
+
+	tmp = ata_wait_idle(ap);
+
+	return tmp;
+}
+
+static unsigned int ata_tag_internal(unsigned int tag)
+{
+	return tag == ATA_MAX_QUEUE - 1;
+}
+
+static void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_device *dev = qc->dev;
+	if (qc->err_mask)
+		qc->flags |= ATA_QCFLAG_FAILED;
+
+	if (qc->flags & ATA_QCFLAG_FAILED) {
+		if (!ata_tag_internal(qc->tag)) {
+			fill_result_tf(qc);
+			return;
+		}
+	}
+	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+		fill_result_tf(qc);
+
+	/* Some commands need post-processing after successful
+	 * completion.
+	 */
+	switch (qc->tf.command) {
+	case ATA_CMD_SET_FEATURES:
+		if (qc->tf.feature != SETFEATURES_WC_ON &&
+				qc->tf.feature != SETFEATURES_WC_OFF)
+			break;
+	case ATA_CMD_INIT_DEV_PARAMS:
+	case ATA_CMD_SET_MULTI:
+		break;
+
+	case ATA_CMD_SLEEP:
+		dev->flags |= ATA_DFLAG_SLEEPING;
+		break;
+	}
+
+	__ata_qc_complete(qc);
+}
+
+static void fill_result_tf(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	qc->result_tf.flags = qc->tf.flags;
+	ata_tf_read(ap, &qc->result_tf);
+}
+
+static void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->command = ata_check_status(ap);
+	tf->feature = readb(ioaddr->error_addr);
+	tf->nsect = readb(ioaddr->nsect_addr);
+	tf->lbal = readb(ioaddr->lbal_addr);
+	tf->lbam = readb(ioaddr->lbam_addr);
+	tf->lbah = readb(ioaddr->lbah_addr);
+	tf->device = readb(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		if (ioaddr->ctl_addr) {
+			writeb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+
+			tf->hob_feature = readb(ioaddr->error_addr);
+			tf->hob_nsect = readb(ioaddr->nsect_addr);
+			tf->hob_lbal = readb(ioaddr->lbal_addr);
+			tf->hob_lbam = readb(ioaddr->lbam_addr);
+			tf->hob_lbah = readb(ioaddr->lbah_addr);
+
+			writeb(tf->ctl, ioaddr->ctl_addr);
+			ap->last_ctl = tf->ctl;
+		} else {
+			printf("sata_dwc warnning register read.\n");
+		}
+	}
+}
+
+static void __ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_link *link = qc->dev->link;
+
+	link->active_tag = ATA_TAG_POISON;
+	ap->nr_active_links--;
+
+	if (qc->flags & ATA_QCFLAG_CLEAR_EXCL && ap->excl_link == link)
+		ap->excl_link = NULL;
+
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	ap->qc_active &= ~(1 << qc->tag);
+}
+
+static void ata_qc_free(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int tag;
+	qc->flags = 0;
+	tag = qc->tag;
+	if (tag < ATA_MAX_QUEUE) {
+		qc->tag = ATA_TAG_POISON;
+		clear_bit(tag, &ap->qc_allocated);
+	}
+}
+
+static int check_sata_dev_state(void)
+{
+	unsigned long datalen;
+	unsigned char *pdata;
+	int ret = 0;
+	int i = 0;
+	char temp_data_buf[512];
+
+	while (1) {
+		udelay (10000);
+
+		pdata = (unsigned char*)&temp_data_buf[0];
+		datalen = 512;
+
+		ret = ata_dev_read_sectors(pdata, datalen, 0, 1);
+
+		if (ret == TRUE)
+			break;
+
+		i++;
+		if (i > (ATA_RESET_TIME * 100)) {
+			printf("** TimeOUT **\n");
+			dev_state = SATA_NODEVICE;
+			return FALSE;
+		}
+
+		if ((i >= 100) && ((i % 100) == 0))
+			printf(".");
+	}
+
+	dev_state = SATA_READY;
+
+	return TRUE;
+}
+
+static unsigned int ata_dev_set_feature(struct ata_device *dev,
+				u8 enable, u8 feature)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = enable;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = feature;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	return err_mask;
+}
+
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+				u16 heads, u16 sectors)
+{
+	struct ata_taskfile tf;
+	struct ata_port *ap;
+	ap = pap;
+	unsigned int err_mask;
+
+	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+		return AC_ERR_INVALID;
+
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	tf.device = ATA_DEVICE_OBS;
+	tf.command = ATA_CMD_INIT_DEV_PARAMS;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = sectors;
+	tf.device |= (heads - 1) & 0x0f;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, 0, 0);
+
+	if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
+		err_mask = 0;
+
+	return err_mask;
+}
+
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SATA_MAX_READ_BLK 0xFF
+#else
+#define SATA_MAX_READ_BLK 0xFFFF
+#endif
+
+ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	ulong start,blks, buf_addr;
+	unsigned short smallblks;
+	unsigned long datalen;
+	unsigned char *pdata;
+	device &= 0xff;
+
+	u32 block = 0;
+	u32 n_block = 0;
+
+	if (dev_state != SATA_READY)
+		return 0;
+
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	do {
+		pdata = (unsigned char *)buf_addr;
+		if (blks > SATA_MAX_READ_BLK) {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_READ_BLK;
+			smallblks = SATA_MAX_READ_BLK;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += SATA_MAX_READ_BLK;
+			blks -= SATA_MAX_READ_BLK;
+		} else {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_READ_BLK;
+			datalen = sata_dev_desc[device].blksz * blks;
+			smallblks = (unsigned short)blks;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += blks;
+			blks = 0;
+		}
+
+		if (ata_dev_read_sectors(pdata, datalen, block, n_block) != TRUE) {
+			printf("sata_dwc : Hard disk read error.\n");
+			blkcnt -= blks;
+			break;
+		}
+		buf_addr += datalen;
+	} while (blks != 0);
+
+	return (blkcnt);
+}
+
+static int ata_dev_read_sectors(unsigned char *pdata, unsigned long datalen,
+						u32 block, u32 n_block)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	if (dev_state == SATA_ERROR)
+		return FALSE;
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	ap->pdata = pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	temp_n_block = n_block;
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_READ_EXT;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else
+	tf.command = ATA_CMD_PIO_READ;
+	tf.flags |= ATA_TFLAG_LBA ;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully@least once.
+	 */
+	may_fallback = 0;
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return TRUE;
+
+err_out:
+	printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return FALSE;
+}
+
+#if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48)
+#define SATA_MAX_WRITE_BLK 0xFF
+#else
+#define SATA_MAX_WRITE_BLK 0xFFFF
+#endif
+
+ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	ulong start,blks, buf_addr;
+	unsigned short smallblks;
+	unsigned long datalen;
+	unsigned char *pdata;
+	device &= 0xff;
+
+
+	u32 block = 0;
+	u32 n_block = 0;
+
+	if (dev_state != SATA_READY)
+		return 0;
+
+	buf_addr = (unsigned long)buffer;
+	start = blknr;
+	blks = blkcnt;
+	do {
+		pdata = (unsigned char *)buf_addr;
+		if (blks > SATA_MAX_WRITE_BLK) {
+			datalen = sata_dev_desc[device].blksz * SATA_MAX_WRITE_BLK;
+			smallblks = SATA_MAX_WRITE_BLK;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += SATA_MAX_WRITE_BLK;
+			blks -= SATA_MAX_WRITE_BLK;
+		} else {
+			datalen = sata_dev_desc[device].blksz * blks;
+			smallblks = (unsigned short)blks;
+
+			block = (u32)start;
+			n_block = (u32)smallblks;
+
+			start += blks;
+			blks = 0;
+		}
+
+		if (ata_dev_write_sectors(pdata, datalen, block, n_block) != TRUE) {
+			printf("sata_dwc : Hard disk read error.\n");
+			blkcnt -= blks;
+			break;
+		}
+		buf_addr += datalen;
+	} while (blks != 0);
+
+	return (blkcnt);
+}
+
+static int ata_dev_write_sectors(unsigned char* pdata, unsigned long datalen,
+						u32 block, u32 n_block)
+{
+	struct ata_port *ap = pap;
+	struct ata_device *dev = &ata_device;
+	struct ata_taskfile tf;
+	unsigned int class = ATA_DEV_ATA;
+	unsigned int err_mask = 0;
+	const char *reason;
+	int may_fallback = 1;
+	int rc;
+
+	if (dev_state == SATA_ERROR)
+		return FALSE;
+
+	ata_dev_select(ap, dev->devno, 1, 1);
+
+retry:
+	memset(&tf, 0, sizeof(tf));
+	tf.ctl = ap->ctl;
+	ap->print_id = 1;
+	ap->flags &= ~ATA_FLAG_DISABLED;
+
+	ap->pdata = pdata;
+
+	tf.device = ATA_DEVICE_OBS;
+
+	temp_n_block = n_block;
+
+
+#ifdef CONFIG_LBA48
+	tf.command = ATA_CMD_PIO_WRITE_EXT;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48 | ATA_TFLAG_WRITE;
+
+	tf.hob_feature = 31;
+	tf.feature = 31;
+	tf.hob_nsect = (n_block >> 8) & 0xff;
+	tf.nsect = n_block & 0xff;
+
+	tf.hob_lbah = 0x0;
+	tf.hob_lbam = 0x0;
+	tf.hob_lbal = (block >> 24) & 0xff;
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+#else
+	tf.command = ATA_CMD_PIO_WRITE;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_WRITE;
+
+	tf.feature = 31;
+	tf.nsect = n_block & 0xff;
+
+	tf.lbah = (block >> 16) & 0xff;
+	tf.lbam = (block >> 8) & 0xff;
+	tf.lbal = block & 0xff;
+
+	tf.device = (block >> 24) & 0xf;
+
+	tf.device |= 1 << 6;
+	if (tf.flags & ATA_TFLAG_FUA)
+		tf.device |= 1 << 7;
+
+#endif
+
+	tf.protocol = ATA_PROT_PIO;
+
+	/* Some devices choke if TF registers contain garbage.  Make
+	 * sure those are properly initialized.
+	 */
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_POLLING;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,0, 0);
+
+	if (err_mask) {
+		if (err_mask & AC_ERR_NODEV_HINT) {
+			printf("READ_SECTORS NODEV after polling detection\n");
+			return -ENOENT;
+		}
+
+		if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+			/* Device or controller might have reported
+			 * the wrong device class.  Give a shot at the
+			 * other IDENTIFY if the current one is
+			 * aborted by the device.
+			 */
+			if (may_fallback) {
+				may_fallback = 0;
+
+				if (class == ATA_DEV_ATA) {
+					class = ATA_DEV_ATAPI;
+				} else {
+					class = ATA_DEV_ATA;
+				}
+				goto retry;
+			}
+			/* Control reaches here iff the device aborted
+			 * both flavors of IDENTIFYs which happens
+			 * sometimes with phantom devices.
+			 */
+			printf("both IDENTIFYs aborted, assuming NODEV\n");
+			return -ENOENT;
+		}
+
+		rc = -EIO;
+		reason = "I/O error";
+		goto err_out;
+	}
+
+	/* Falling back doesn't make sense if ID data was read
+	 * successfully at least once.
+	 */
+	may_fallback = 0;
+
+	rc = -EINVAL;
+	reason = "device reports invalid type";
+
+	return TRUE;
+
+err_out:
+	printf("failed to WRITE SECTORS (%s, err_mask=0x%x)\n", reason, err_mask);
+	return FALSE;
+}
diff -uprN u-boot-0507/drivers/block/sata_dwc.h u-boot-sata/drivers/block/sata_dwc.h
--- u-boot-0507/drivers/block/sata_dwc.h	1970-01-01 09:00:00.000000000 +0900
+++ u-boot-sata/drivers/block/sata_dwc.h	2009-05-07 09:42:37.000000000 +0900
@@ -0,0 +1,463 @@
+/*
+ * sata_dwc.h
+ *
+ * Synopsys DesignWare Cores (DWC) SATA host driver
+ *
+ * Author: Mark Miesfeld <mmiesfeld@amcc.com>
+ *
+ * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
+ * Copyright 2008 DENX Software Engineering
+ *
+ * Based on versions provided by AMCC and Synopsys which are:
+ *          Copyright 2006 Applied Micro Circuits Corporation
+ *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under  the terms of  the GNU
+ * General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License,
+ * or (at your option) any later version.
+ *
+ */
+/*
+ * SATA support based on the chip canyonlands.
+ *
+ * 04-17-2009
+ *		The local version of this driver for the canyonlands board
+ *		does not use interrupts but polls the chip instead.
+ */
+
+
+#ifndef _SATA_DWC_H_
+#define _SATA_DWC_H_
+
+#define HZ 100
+
+#define READ 0
+#define WRITE 1
+
+enum {
+	ATA_READID_POSTRESET	= (1 << 0),
+
+	ATA_DNXFER_PIO		= 0,
+	ATA_DNXFER_DMA		= 1,
+	ATA_DNXFER_40C		= 2,
+	ATA_DNXFER_FORCE_PIO	= 3,
+	ATA_DNXFER_FORCE_PIO0	= 4,
+
+	ATA_DNXFER_QUIET	= (1 << 31),
+};
+
+enum hsm_task_states {
+	HSM_ST_IDLE,
+	HSM_ST_FIRST,
+	HSM_ST,
+	HSM_ST_LAST,
+	HSM_ST_ERR,
+};
+
+#define	ATA_SHORT_PAUSE		((HZ >> 6) + 1)
+
+struct ata_queued_cmd {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
+
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
+	unsigned long		flags;
+	unsigned int		tag;
+	unsigned int		n_elem;
+
+	int			dma_dir;
+
+	unsigned int		sect_size;
+
+	unsigned int		nbytes;
+	unsigned int		extrabytes;
+	unsigned int		curbytes;
+
+	unsigned int		err_mask;
+	struct ata_taskfile	result_tf;
+
+	void			*private_data;
+	void			*lldd_task;
+	unsigned char		*pdata;
+};
+
+typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
+
+#define ATA_TAG_POISON	0xfafbfcfdU
+
+enum {
+	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,
+	ATA_MAX_PORTS		= 8,
+	ATA_DEF_QUEUE		= 1,
+	ATA_MAX_QUEUE		= 32,
+	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
+	ATA_MAX_BUS		= 2,
+	ATA_DEF_BUSY_WAIT	= 10000,
+
+	ATAPI_MAX_DRAIN		= 16 << 10,
+
+	ATA_SHT_EMULATED	= 1,
+	ATA_SHT_CMD_PER_LUN	= 1,
+	ATA_SHT_THIS_ID		= -1,
+	ATA_SHT_USE_CLUSTERING	= 1,
+
+	ATA_DFLAG_LBA		= (1 << 0),
+	ATA_DFLAG_LBA48		= (1 << 1),
+	ATA_DFLAG_CDB_INTR	= (1 << 2),
+	ATA_DFLAG_NCQ		= (1 << 3),
+	ATA_DFLAG_FLUSH_EXT	= (1 << 4),
+	ATA_DFLAG_ACPI_PENDING 	= (1 << 5),
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6),
+	ATA_DFLAG_AN		= (1 << 7),
+	ATA_DFLAG_HIPM		= (1 << 8),
+	ATA_DFLAG_DIPM		= (1 << 9),
+	ATA_DFLAG_DMADIR	= (1 << 10),
+	ATA_DFLAG_CFG_MASK	= (1 << 12) - 1,
+
+	ATA_DFLAG_PIO		= (1 << 12),
+	ATA_DFLAG_NCQ_OFF	= (1 << 13),
+	ATA_DFLAG_SPUNDOWN	= (1 << 14),
+	ATA_DFLAG_SLEEPING	= (1 << 15),
+	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16),
+	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
+
+	ATA_DFLAG_DETACH	= (1 << 24),
+	ATA_DFLAG_DETACHED	= (1 << 25),
+
+	ATA_LFLAG_HRST_TO_RESUME	= (1 << 0),
+	ATA_LFLAG_SKIP_D2H_BSY		= (1 << 1),
+	ATA_LFLAG_NO_SRST		= (1 << 2),
+	ATA_LFLAG_ASSUME_ATA		= (1 << 3),
+	ATA_LFLAG_ASSUME_SEMB		= (1 << 4),
+	ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
+	ATA_LFLAG_NO_RETRY		= (1 << 5),
+	ATA_LFLAG_DISABLED		= (1 << 6),
+
+	ATA_FLAG_SLAVE_POSS	= (1 << 0),
+	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LEGACY	= (1 << 2),
+	ATA_FLAG_MMIO		= (1 << 3),
+	ATA_FLAG_SRST		= (1 << 4),
+	ATA_FLAG_SATA_RESET	= (1 << 5),
+	ATA_FLAG_NO_ATAPI	= (1 << 6),
+	ATA_FLAG_PIO_DMA	= (1 << 7),
+	ATA_FLAG_PIO_LBA48	= (1 << 8),
+	ATA_FLAG_PIO_POLLING	= (1 << 9),
+	ATA_FLAG_NCQ		= (1 << 10),
+	ATA_FLAG_DEBUGMSG	= (1 << 13),
+	ATA_FLAG_IGN_SIMPLEX	= (1 << 15),
+	ATA_FLAG_NO_IORDY	= (1 << 16),
+	ATA_FLAG_ACPI_SATA	= (1 << 17),
+	ATA_FLAG_AN		= (1 << 18),
+	ATA_FLAG_PMP		= (1 << 19),
+	ATA_FLAG_IPM		= (1 << 20),
+
+	ATA_FLAG_DISABLED	= (1 << 23),
+
+	ATA_PFLAG_EH_PENDING		= (1 << 0),
+	ATA_PFLAG_EH_IN_PROGRESS	= (1 << 1),
+	ATA_PFLAG_FROZEN		= (1 << 2),
+	ATA_PFLAG_RECOVERED		= (1 << 3),
+	ATA_PFLAG_LOADING		= (1 << 4),
+	ATA_PFLAG_UNLOADING		= (1 << 5),
+	ATA_PFLAG_SCSI_HOTPLUG		= (1 << 6),
+	ATA_PFLAG_INITIALIZING		= (1 << 7),
+	ATA_PFLAG_RESETTING		= (1 << 8),
+	ATA_PFLAG_SUSPENDED		= (1 << 17),
+	ATA_PFLAG_PM_PENDING		= (1 << 18),
+
+	ATA_QCFLAG_ACTIVE	= (1 << 0),
+	ATA_QCFLAG_DMAMAP	= (1 << 1),
+	ATA_QCFLAG_IO		= (1 << 3),
+	ATA_QCFLAG_RESULT_TF	= (1 << 4),
+	ATA_QCFLAG_CLEAR_EXCL	= (1 << 5),
+	ATA_QCFLAG_QUIET	= (1 << 6),
+
+	ATA_QCFLAG_FAILED	= (1 << 16),
+	ATA_QCFLAG_SENSE_VALID	= (1 << 17),
+	ATA_QCFLAG_EH_SCHEDULED	= (1 << 18),
+
+	ATA_HOST_SIMPLEX	= (1 << 0),
+	ATA_HOST_STARTED	= (1 << 1),
+
+	ATA_TMOUT_BOOT			= 30 * 100,
+	ATA_TMOUT_BOOT_QUICK		= 7 * 100,
+	ATA_TMOUT_INTERNAL		= 30 * 100,
+	ATA_TMOUT_INTERNAL_QUICK	= 5 * 100,
+
+	/* FIXME: GoVault needs 2s but we can't afford that without
+	 * parallel probing.  800ms is enough for iVDR disk
+	 * HHD424020F7SV00.  Increase to 2secs when parallel probing
+	 * is in place.
+	 */
+	ATA_TMOUT_FF_WAIT	= 4 * 100 / 5,
+
+	BUS_UNKNOWN		= 0,
+	BUS_DMA			= 1,
+	BUS_IDLE		= 2,
+	BUS_NOINTR		= 3,
+	BUS_NODATA		= 4,
+	BUS_TIMER		= 5,
+	BUS_PIO			= 6,
+	BUS_EDD			= 7,
+	BUS_IDENTIFY		= 8,
+	BUS_PACKET		= 9,
+
+	PORT_UNKNOWN		= 0,
+	PORT_ENABLED		= 1,
+	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_NR_PIO_MODES	= 7,
+	ATA_NR_MWDMA_MODES	= 5,
+	ATA_NR_UDMA_MODES	= 8,
+
+	ATA_SHIFT_PIO		= 0,
+	ATA_SHIFT_MWDMA		= ATA_SHIFT_PIO + ATA_NR_PIO_MODES,
+	ATA_SHIFT_UDMA		= ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES,
+
+	ATA_DMA_PAD_SZ		= 4,
+
+	ATA_ERING_SIZE		= 32,
+
+	ATA_DEFER_LINK		= 1,
+	ATA_DEFER_PORT		= 2,
+
+	ATA_EH_DESC_LEN		= 80,
+
+	ATA_EH_REVALIDATE	= (1 << 0),
+	ATA_EH_SOFTRESET	= (1 << 1),
+	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_ENABLE_LINK	= (1 << 3),
+	ATA_EH_LPM		= (1 << 4),
+
+	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+	ATA_EHI_HOTPLUGGED	= (1 << 0),
+	ATA_EHI_RESUME_LINK	= (1 << 1),
+	ATA_EHI_NO_AUTOPSY	= (1 << 2),
+	ATA_EHI_QUIET		= (1 << 3),
+
+	ATA_EHI_DID_SOFTRESET	= (1 << 16),
+	ATA_EHI_DID_HARDRESET	= (1 << 17),
+	ATA_EHI_PRINTINFO	= (1 << 18),
+	ATA_EHI_SETMODE		= (1 << 19),
+	ATA_EHI_POST_SETMODE	= (1 << 20),
+
+	ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+	ATA_EH_MAX_TRIES	= 5,
+
+	ATA_PROBE_MAX_TRIES	= 3,
+	ATA_EH_DEV_TRIES	= 3,
+	ATA_EH_PMP_TRIES	= 5,
+	ATA_EH_PMP_LINK_TRIES	= 3,
+
+	SATA_PMP_SCR_TIMEOUT	= 250,
+
+	/* Horkage types. May be set by libata or controller on drives
+	(some horkage may be drive/controller pair dependant */
+
+	ATA_HORKAGE_DIAGNOSTIC	= (1 << 0),
+	ATA_HORKAGE_NODMA	= (1 << 1),
+	ATA_HORKAGE_NONCQ	= (1 << 2),
+	ATA_HORKAGE_MAX_SEC_128	= (1 << 3),
+	ATA_HORKAGE_BROKEN_HPA	= (1 << 4),
+	ATA_HORKAGE_SKIP_PM	= (1 << 5),
+	ATA_HORKAGE_HPA_SIZE	= (1 << 6),
+	ATA_HORKAGE_IPM		= (1 << 7),
+	ATA_HORKAGE_IVB		= (1 << 8),
+	ATA_HORKAGE_STUCK_ERR	= (1 << 9),
+
+	ATA_DMA_MASK_ATA	= (1 << 0),
+	ATA_DMA_MASK_ATAPI	= (1 << 1),
+	ATA_DMA_MASK_CFA	= (1 << 2),
+
+	ATAPI_READ		= 0,
+	ATAPI_WRITE		= 1,
+	ATAPI_READ_CD		= 2,
+	ATAPI_PASS_THRU		= 3,
+	ATAPI_MISC		= 4,
+};
+
+enum ata_completion_errors {
+	AC_ERR_DEV		= (1 << 0),
+	AC_ERR_HSM		= (1 << 1),
+	AC_ERR_TIMEOUT		= (1 << 2),
+	AC_ERR_MEDIA		= (1 << 3),
+	AC_ERR_ATA_BUS		= (1 << 4),
+	AC_ERR_HOST_BUS		= (1 << 5),
+	AC_ERR_SYSTEM		= (1 << 6),
+	AC_ERR_INVALID		= (1 << 7),
+	AC_ERR_OTHER		= (1 << 8),
+	AC_ERR_NODEV_HINT	= (1 << 9),
+	AC_ERR_NCQ		= (1 << 10),
+};
+
+enum ata_xfer_mask {
+	ATA_MASK_PIO	= ((1LU << ATA_NR_PIO_MODES) - 1) << ATA_SHIFT_PIO,
+	ATA_MASK_MWDMA	= ((1LU << ATA_NR_MWDMA_MODES) - 1) << ATA_SHIFT_MWDMA,
+	ATA_MASK_UDMA	= ((1LU << ATA_NR_UDMA_MODES) - 1) << ATA_SHIFT_UDMA,
+};
+
+struct ata_port_info {
+	struct scsi_host_template	*sht;
+	unsigned long			flags;
+	unsigned long			link_flags;
+	unsigned long			pio_mask;
+	unsigned long			mwdma_mask;
+	unsigned long			udma_mask;
+	const struct ata_port_operations *port_ops;
+	void				*private_data;
+};
+
+struct ata_ioports {
+	void __iomem		*cmd_addr;
+	void __iomem		*data_addr;
+	void __iomem		*error_addr;
+	void __iomem		*feature_addr;
+	void __iomem		*nsect_addr;
+	void __iomem		*lbal_addr;
+	void __iomem		*lbam_addr;
+	void __iomem		*lbah_addr;
+	void __iomem		*device_addr;
+	void __iomem		*status_addr;
+	void __iomem		*command_addr;
+	void __iomem		*altstatus_addr;
+	void __iomem		*ctl_addr;
+	void __iomem		*bmdma_addr;
+	void __iomem		*scr_addr;
+};
+
+struct ata_host {
+	void __iomem * const	*iomap;
+	unsigned int		n_ports;
+	void			*private_data;
+	const struct ata_port_operations *ops;
+	unsigned long		flags;
+	struct ata_port		*simplex_claimed;
+	struct ata_port		*ports[0];
+};
+
+struct ata_port_stats {
+	unsigned long		unhandled_irq;
+	unsigned long		idle_irq;
+	unsigned long		rw_reqbuf;
+};
+
+struct ata_device {
+	struct ata_link		*link;
+	unsigned int		devno;
+	unsigned long		flags;
+	unsigned int		horkage;
+	struct scsi_device	*sdev;
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	union acpi_object	*gtf_cache;
+#endif
+	u64			n_sectors;
+	unsigned int		class;
+
+	union {
+		u16		id[ATA_ID_WORDS];
+		u32		gscr[SATA_PMP_GSCR_DWORDS];
+	};
+
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;
+
+	unsigned int		multi_count;
+	unsigned int		max_sectors;
+	unsigned int		cdb_len;
+
+	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
+	unsigned long		udma_mask;
+
+	u16			cylinders;
+	u16			heads;
+	u16			sectors;
+
+	int			spdn_cnt;
+};
+
+enum dma_data_direction {
+	DMA_BIDIRECTIONAL = 0,
+	DMA_TO_DEVICE = 1,
+	DMA_FROM_DEVICE = 2,
+	DMA_NONE = 3,
+};
+
+struct ata_link {
+	struct ata_port		*ap;
+	int			pmp;
+	unsigned int		active_tag;
+	u32			sactive;
+
+	unsigned int		flags;
+
+	unsigned int		hw_sata_spd_limit;
+	unsigned int		sata_spd_limit;
+	unsigned int		sata_spd;
+
+	struct ata_device	device[2];
+};
+
+struct ata_port {
+	unsigned long		flags;
+	unsigned int		pflags;
+	unsigned int		print_id;
+	unsigned int		port_no;
+
+	struct ata_ioports	ioaddr;
+
+	u8			ctl;
+	u8			last_ctl;
+	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
+	unsigned int		udma_mask;
+	unsigned int		cbl;
+
+	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+	unsigned long		qc_allocated;
+	unsigned int		qc_active;
+	int			nr_active_links;
+
+	struct ata_link		link;
+
+	int			nr_pmp_links;
+	struct ata_link		*pmp_link;
+	struct ata_link		*excl_link;
+
+	struct ata_port_stats	stats;
+	struct ata_host		*host;
+
+	struct device		*dev;
+	void			*port_task_data;
+
+	unsigned int		hsm_task_state;
+
+	u32			msg_enable;
+	void			*private_data;
+	unsigned char		*pdata;
+};
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif
diff -uprN u-boot-0507/include/configs/canyonlands.h u-boot-sata/include/configs/canyonlands.h
--- u-boot-0507/include/configs/canyonlands.h	2009-05-07 09:25:50.000000000 +0900
+++ u-boot-sata/include/configs/canyonlands.h	2009-05-07 09:49:10.000000000 +0900
@@ -454,6 +454,7 @@
  #define CONFIG_CMD_SDRAM
  #define CONFIG_CMD_SNTP
  #define CONFIG_CMD_USB
+#define CONFIG_CMD_SATA
  #elif defined(CONFIG_GLACIER)
  #define CONFIG_CMD_DATE
  #define CONFIG_CMD_DTT
@@ -517,6 +518,21 @@
  #endif /* CONFIG_460GT */

  /*-----------------------------------------------------------------------
+ * S-ATA driver setup
+ *----------------------------------------------------------------------*/
+#define CONFIG_SATA_DWC
+
+#ifdef CONFIG_SATA_DWC
+#define CONFIG_LIBATA
+
+#define SATA_BASE_ADDR		0xe20d1000	/* PPC460EX SATA Base Address */
+#define SATA_DMA_REG_ADDR	0xe20d0800	/* PPC460EX SATA Base Address */
+#define CONFIG_SYS_SATA_MAX_DEVICE	1	/* SATA MAX DEVICE */
+/* Convert sectorsize to wordsize */
+#define ATA_SECTOR_WORDS (ATA_SECT_SIZE/2)
+#endif
+
+/*-----------------------------------------------------------------------
   * External Bus Controller (EBC) Setup
   *----------------------------------------------------------------------*/
---
Thanks.

Regards,
Kazuaki Ichinohe.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH] Canyonlands SATA harddisk driver
  2009-05-07  6:23                     ` Kazuaki Ichinohe
@ 2009-05-07  7:38                       ` Wolfgang Denk
  0 siblings, 0 replies; 36+ messages in thread
From: Wolfgang Denk @ 2009-05-07  7:38 UTC (permalink / raw)
  To: u-boot

Dear Kazuaki Ichinohe,

In message <4A027E44.5080100@fsi.co.jp> you wrote:
> Hello Denk, Stefan,
> 
>  > Could you please rebase your patch against the current top-of-tree mainline
>  > repository and resumbmit?
> 
> Thank you for the reply.
> I made the patch from the source obtained with git in 5/7.
> The confirmed patch is sent again.
> Please review this patch.
> ---

Please put comments BELOW the "---" line, not above. Only put the
commit message ABOVE the "---" line. And note that there is only ONE
"---" line in a patch.

> [patch]
> diff -uprN u-boot-0507/drivers/block/Makefile u-boot-sata/drivers/block/Makefile
> --- u-boot-0507/drivers/block/Makefile	2009-05-07 09:25:48.000000000 +0900
> +++ u-boot-sata/drivers/block/Makefile	2009-05-07 09:43:56.000000000 +0900
> @@ -35,6 +35,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil
>   COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
>   COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
>   COBJS-$(CONFIG_SYSTEMACE) += systemace.o
> +COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o

Sorry, your patch is white-space corrupted:

patching file drivers/block/Makefile
Hunk #1 FAILED at 35.
1 out of 1 hunk FAILED -- saving rejects to file
drivers/block/Makefile.rej
patching file drivers/block/sata_dwc.c
patching file drivers/block/sata_dwc.h
patching file include/configs/canyonlands.h
Hunk #1 FAILED at 454.
patch: **** malformed patch at line 2718: Thanks.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Nearly everyone is in favor of going  to  heaven  but  too  many  are
hoping  they'll  live  long  enough  to see an easing of the entrance
requirements. Never appeal to a man's "better nature." he  might  not
have one.

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2009-05-07  7:38 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-17 13:08 [U-Boot] About PCI of U-BOOT of CANYONLANDS Kazuaki Ichinohe
2009-03-17 13:13 ` Stefan Roese
2009-03-18  1:28   ` Kazuaki Ichinohe
2009-03-18  9:07     ` Stefan Roese
2009-03-18  9:13       ` Felix Radensky
2009-03-18  9:23         ` Stefan Roese
2009-03-18  9:34           ` Felix Radensky
2009-03-18  9:39             ` Stefan Roese
2009-03-18 12:03       ` Anatolij Gustschin
2009-03-18 12:07         ` Kazuaki Ichinohe
2009-03-18 12:29           ` Kazuaki Ichinohe
2009-03-18 13:00             ` Kazuaki Ichinohe
     [not found]             ` <49C0EFB2.9020800@fsi.co.jp>
2009-03-18 14:48               ` Anatolij Gustschin
2009-03-19  4:43                 ` Kazuaki Ichinohe
2009-03-19  9:16                   ` Anatolij Gustschin
2009-03-19 11:28                     ` Kazuaki Ichinohe
2009-03-19 11:44                       ` Anatolij Gustschin
2009-03-19 12:09                         ` Kazuaki Ichinohe
2009-03-19 12:27                           ` Anatolij Gustschin
2009-03-19 12:52                             ` Kazuaki Ichinohe
2009-03-19 13:17                               ` Anatolij Gustschin
2009-03-20 10:50                                 ` Kazuaki Ichinohe
2009-03-24  5:22 ` [U-Boot] [PATCH] Canyonlands SATA harddisk driver Kazuaki Ichinohe
2009-03-24 16:22   ` Stefan Roese
2009-03-25 11:32     ` Kazuaki Ichinohe
2009-03-25 16:04       ` Stefan Roese
2009-03-26 10:56         ` Kazuaki Ichinohe
2009-03-27 16:11           ` Stefan Roese
2009-03-27 16:31           ` Wolfgang Denk
2009-03-30  8:27             ` Kazuaki Ichinohe
2009-04-17  7:31               ` Kazuaki Ichinohe
2009-04-27  1:53                 ` Kazuaki Ichinohe
2009-04-27  7:42                   ` Stefan Roese
2009-04-29  6:58                   ` Stefan Roese
2009-05-07  6:23                     ` Kazuaki Ichinohe
2009-05-07  7:38                       ` Wolfgang Denk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.