IDE woos in BE mode 2.6 kernel
Hello !
In response to Jun Suns mail sent on 06/24/2004
Anybody has tried IDE disks in big endian mode with 2.6 kernel? I seem to have troubles with Malta board.
Current malta board has CONFIG_SWAP_IO_SPACE defined and therefore all inw, inl and their friends are byte-swapped in BE mode. As a results all IDE IO ops (such as ide_inw, etc) do swapping too.
A quick experiement shows those IDE IO ops should not do swapping. Anybody knows why?
Apparently fixing the above is not enough. I either encountered failure to read partition table or having DMA error. Any clues here?
I suppose this problem really should exist for other arches with BE support. Anybody knows how other arches deal with this?
Thanks.
Jun
---
The following patch gets the Malta to work well. However, this patch introduces board specific changes in the IDE subsystem. This is not a final patch but maybe there can be a better approach to this issue
Thanks
Manish
ide/ide-iops.c renamed from ide/ide-iops.c.orig +10 -0
@@ -95,13 +95,23 @@ hwif->OUTBSYNC = ide_outbsync; hwif->OUTW = ide_outw; hwif->OUTL = ide_outl; +#if defined(CONFIG_MIPS_MALTA ) && !defined(CONFIG_CPU_LITTLE_ENDIAN ) + hwif->OUTSW = malta_ide_outsw; + hwif->OUTSL = malta_ide_outsl; +#else hwif->OUTSW = ide_outsw; hwif->OUTSL = ide_outsl; +#endif hwif->INB = ide_inb; hwif->INW = ide_inw; hwif->INL = ide_inl; +#if defined(CONFIG_MIPS_MALTA ) && !defined(CONFIG_CPU_LITTLE_ENDIAN ) + hwif->INSW = malta_ide_insw; + hwif->INSL = malta_ide_insl; +#else hwif->INSW = ide_insw; hwif->INSL = ide_insl; +#endif }EXPORT_SYMBOL (default_hwif_iops);
asm-mips/ide.h renamed from asm-mips/ide.h.orig +36 -0
@@ -20,6 +20,42 @@#define __ide_mm_outsw ide_outsw#define __ide_mm_outsl ide_outsl +#if defined(CONFIG_MIPS_MALTA ) && !defined(CONFIG_CPU_LITTLE_ENDIAN ) +extern const unsigned long mips_io_port_base; + +static inline void malta_ide_insw (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(u16 *)addr = *(volatile u16 *)(mips_io_port_base + port); + addr +=2 ; + } +} + +static inline void malta_ide_outsw (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(volatile u16 *)(mips_io_port_base + (port)) = *(u16 *)addr; + addr +=2 ; + } +} + +static inline void malta_ide_insl (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(u32 *)addr = *(volatile u32 *)(mips_io_port_base + port); + addr +=4 ; + } +} + +static inline void malta_ide_outsl (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(volatile u32 *)(mips_io_port_base + (port)) = *(u32 *)addr; + addr +=4 ; + } +} +#endif +#endif /* __KERNEL__ */ #endif /* __ASM_IDE_H */
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Manish Lachwani
mlachwani> In response to Jun Suns mail sent on 06/24/2004
jsun> Anybody has tried IDE disks in big endian mode with 2.6 jsun> kernel? I seem to have troubles with Malta board.
...
mlachwani> The following patch gets the Malta to work well. However, mlachwani> this patch introduces board specific changes in the IDE mlachwani> subsystem. This is not a final patch but maybe there can mlachwani> be a better approach to this issue
FYI, here is my approach. Not so beautiful but less intrusive...
1. copy include/asm-mips/mach-generic/ide.h to my mach-xxx directory.
2. add following lines to include/asm-mips/mach-xxx/ide.h
--- begin ---
/* get rid of defs from io.h - ide has its private and conflicting versions */ #ifdef insb
#undef insb
#endif
#ifdef outsb
#undef outsb
#endif
#ifdef insw
#undef insw
#endif
#ifdef outsw
#undef outsw
#endif
#ifdef insl
#undef insl
#endif
#ifdef outsl
#undef outsl
#endif
#define insb(port, addr, count) ___ide_insb(port, addr, count) #define insw(port, addr, count) ___ide_insw(port, addr, count) #define insl(port, addr, count) ___ide_insl(port, addr, count) #define outsb(port, addr, count) ___ide_outsb(port, addr, count) #define outsw(port, addr, count) ___ide_outsw(port, addr, count) #define outsl(port, addr, count) ___ide_outsl(port, addr, count)
static inline void ___ide_insb(unsigned long port, void *addr, unsigned int count)
{
unsigned long start = (unsigned long)addr;
unsigned long size = (unsigned long)count;
while (count--) {
*(u16 *)addr = *(volatile u8 *)(mips_io_port_base + port);
addr++;
}
if (cpu_has_dc_aliases)
dma_cache_wback((unsigned long)start, size);
}static inline void ___ide_outsb(unsigned long port, void *addr, unsigned int count)
{
while (count--) {
*(volatile u8 *)(mips_io_port_base + port) = *(u8 *)addr;
addr++;
}
}static inline void ___ide_insw(unsigned long port, void *addr, unsigned int count)
{
unsigned long start = (unsigned long)addr;
unsigned long size = (unsigned long)count * 2;
while (count--) {
*(u16 *)addr = *(volatile u16 *)(mips_io_port_base + port);
addr += 2;
}
if (cpu_has_dc_aliases)
dma_cache_wback((unsigned long)start, size);
}static inline void ___ide_outsw(unsigned long port, void *addr, unsigned int count)
{
while (count--) {
*(volatile u16 *)(mips_io_port_base + port) = *(u16 *)addr;
addr += 2;
}
}static inline void ___ide_insl(unsigned long port, void *addr, unsigned int count)
{
unsigned long start = (unsigned long)addr;
unsigned long size = (unsigned long)count * 4;
while (count--) {
*(u32 *)addr = *(volatile u32 *)(mips_io_port_base + port);
addr += 4;
}
if (cpu_has_dc_aliases)
dma_cache_wback((unsigned long)start, size);
}static inline void ___ide_outsl(unsigned long port, void *addr, unsigned int count)
{
while (count--) {
*(volatile u32 *)(mips_io_port_base + port) = *(u32 *)addr;
addr += 4;
}
}--- end ---
Note that above codes include workarounds for PIO IDE cache problem (dma_cache_wback) though I'm not sure this workaround still needed. Please refer this ML thread for the workaround.
<http://www.linux-mips.org/archives/linux-mips/2004-03/msg00185.html>
And as I wrote before, I think this IDE endian problem still exists in current 2.4 tree too. Please refer my 02/26 mail for this topic.
<http://www.linux-mips.org/archives/linux-mips/2004-02/msg00219.html>
Thank you.
---
Atsushi Nemoto
Hello !
These changes below work and attached is the patch based on your suggestion. However, I have made changes to include/asm-mips/ide.h since I think there may be problems with other MIPS boards to in BE mode. And, I have not included the (dma_cache_wback) in the patch.
Thanks
Manish
Quoted 113 lines · Atsushi Nemoto
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines · Manish Lachwani
mlachwani> In response to Jun Suns mail sent on 06/24/2004
jsun> Anybody has tried IDE disks in big endian mode with 2.6 jsun> kernel? I seem to have troubles with Malta board.
...
mlachwani> The following patch gets the Malta to work well. However, mlachwani> this patch introduces board specific changes in the IDE mlachwani> subsystem. This is not a final patch but maybe there can mlachwani> be a better approach to this issueFYI, here is my approach. Not so beautiful but less intrusive...
1. copy
include/asm-mips/mach-generic/ide.hto my mach-xxx directory.
2. add following lines toinclude/asm-mips/mach-xxx/ide.h
--- begin ---
/* get rid of defs fromio.h- ide has its private and conflicting versions */ #ifdef insb
#undef insb
#endif
#ifdef outsb
#undef outsb
#endif
#ifdef insw
#undef insw
#endif
#ifdef outsw
#undef outsw
#endif
#ifdef insl
#undef insl
#endif
#ifdef outsl
#undef outsl
#endif#define
insb(port, addr, count)___ide_insb(port, addr, count)#defineinsw(port, addr, count)___ide_insw(port, addr, count)#defineinsl(port, addr, count)___ide_insl(port, addr, count)#defineoutsb(port, addr, count)___ide_outsb(port, addr, count)#defineoutsw(port, addr, count)___ide_outsw(port, addr, count)#defineoutsl(port, addr, count)___ide_outsl(port, addr, count)static inline void
___ide_insb(unsigned long port, void *addr, unsigned int count){ unsigned long start = (unsigned long)addr; unsigned long size = (unsigned long)count; while (count--) { *(u16 *)addr = *(volatile u8 *)(mips_io_port_base + port); addr++; } if (cpu_has_dc_aliases) dma_cache_wback((unsigned long)start, size); }static inline void
___ide_outsb(unsigned long port, void *addr, unsigned int count){ while (count--) { *(volatile u8 *)(mips_io_port_base + port) = *(u8 *)addr; addr++; } }static inline void
___ide_insw(unsigned long port, void *addr, unsigned int count){ unsigned long start = (unsigned long)addr; unsigned long size = (unsigned long)count * 2; while (count--) { *(u16 *)addr = *(volatile u16 *)(mips_io_port_base + port); addr += 2; } if (cpu_has_dc_aliases) dma_cache_wback((unsigned long)start, size); }static inline void
___ide_outsw(unsigned long port, void *addr, unsigned int count){ while (count--) { *(volatile u16 *)(mips_io_port_base + port) = *(u16 *)addr; addr += 2; } }static inline void
___ide_insl(unsigned long port, void *addr, unsigned int count){ unsigned long start = (unsigned long)addr; unsigned long size = (unsigned long)count * 4; while (count--) { *(u32 *)addr = *(volatile u32 *)(mips_io_port_base + port); addr += 4; } if (cpu_has_dc_aliases) dma_cache_wback((unsigned long)start, size); }static inline void
___ide_outsl(unsigned long port, void *addr, unsigned int count){ while (count--) { *(volatile u32 *)(mips_io_port_base + port) = *(u32 *)addr; addr += 4; } }--- end ---
Note that above codes include workarounds for PIO IDE cache problem (
dma_cache_wback) though I'm not sure this workaround still needed. Please refer this ML thread for the workaround.
<http://www.linux-mips.org/archives/linux-mips/2004-03/msg00185.html>
Quoted 10 lines
And as I wrote before, I think this IDE endian problem still exists in current 2.4 tree too. Please refer my 02/26 mail for this topic.
<http://www.linux-mips.org/archives/linux-mips/2004-02/msg00219.html>Thank you.
---
Atsushi Nemoto
asm-mips/ide.h renamed from asm-mips/ide.h.orig +85 -0
@@ -20,6 +20,91 @@#define __ide_mm_outsw ide_outsw#define __ide_mm_outsl ide_outsl +#ifndef CONFIG_CPU_LITTLE_ENDIAN +/* +* Only for the Big Endian systems, do not do the swapping. +* We cannot turn off the CONFIG_SWAP_IO_SPACE since the +* other subsystems need it. Hence we need this approach for +* IDE only - Manish Lachwani ([email protected]) +*/ +extern const unsigned long mips_io_port_base; + +#ifdef insb +#undef insb +#endif +#ifdef outsb +#undef outsb +#endif +#ifdef insw +#undef insw +#endif +#ifdef outsw +#undef outsw +#endif +#ifdef insl +#undef insl +#endif +#ifdef outsl +#undef outsl +#endif + +#define insb (port, addr, count) ___ide_insb(port, addr, count) +#define insw (port, addr, count) ___ide_insw(port, addr, count) +#define insl (port, addr, count) ___ide_insl(port, addr, count) +#define outsb (port, addr, count) ___ide_outsb(port, addr, count) +#define outsw (port, addr, count) ___ide_outsw(port, addr, count) +#define outsl (port, addr, count) ___ide_outsl(port, addr, count) + +static inline void ___ide_insb (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(u16 *)addr = *(volatile u8 *)(mips_io_port_base + port); + addr++; + } +} + +static inline void ___ide_outsb (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(volatile u8 *)(mips_io_port_base + port) = *(u8 *)addr; + addr++; + } +} + +static inline void ___ide_insw (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(u16 *)addr = *(volatile u16 *)(mips_io_port_base + port); + addr +=2 ; + } +} + +static inline void ___ide_outsw (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(volatile u16 *)(mips_io_port_base + port) = *(u16 *)addr; + addr +=2 ; + } +} + +static inline void ___ide_insl (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(u32 *)addr = *(volatile u32 *)(mips_io_port_base + port); + addr +=4 ; + } +} + +static inline void ___ide_outsl (unsigned long port,void *addr,unsigned int count) +{ +while (count--) { + *(volatile u32 *)(mips_io_port_base + port) = *(u32 *)addr; + addr +=4 ; + } +} + +#endif /* CONFIG_LITTLE_ENDIAN */ +#endif /* __KERNEL__ */ #endif /* __ASM_IDE_H */
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Manish Lachwani
mlachwani> These changes below work and attached is the patch based on mlachwani> your suggestion. However, I have made changes to mlachwani> include/asm-mips/ide.h since I think there may be problems mlachwani> with other MIPS boards to in BE mode. And, I have not mlachwani> included the (dma_cache_wback) in the patch.
Hmm, I think declaration of mips_io_port_base is not needed since asm/io.h must be included before asm/ide.h. If asm/io.h was not included first, ide.h can not override these functions anyway.
Also, moving the fixup block before "#include <ide.h>" will give a chance to override these functions again in mach-dependent ide.h. (for more weired hardware)
---
Atsushi Nemoto