Be very careful about using ioread32be() and iowrite32()

They appeared:
- in generic code and PARISC - in 2.6.12
- in PPC64 - in 2.6.14
- in merged PowerPC - in 2.6.15 (when the merge occurred)
- in MIPS - in 2.6.21

Improve comments and indentation, as the logic is getting more complex.


git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3712 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
proski 2008-06-08 01:28:58 +00:00
parent 785ca93999
commit c47c360b48
1 changed files with 47 additions and 40 deletions

View File

@ -151,19 +151,27 @@ extern void *__ahdecl ath_hal_memcpy(void *, const void *, size_t);
#endif /* AH_BYTE_ORDER */
/*
* Some big-endian architectures don't set CONFIG_GENERIC_IOMAP, but fail to
* implement iowrite32be and ioread32be. Provide compatibility macros when
* it's needed.
* The HAL programs big-endian platforms to use byte-swapped hardware registers.
* This is done to avoid the byte swapping needed to access PCI devices.
*
* As of Linux 2.6.24, only MIPS, PARISC and PowerPC implement iowrite32be and
* ioread32be as functions.
* Many big-endian architectures provide I/O functions that avoid byte swapping.
* We use them when possible. Otherwise, we provide replacements. The downside
* or the replacements is that we may be byte-swapping data twice, so we try to
* avoid it.
*
* The downside or the replacement macros it that we may be byte-swapping data
* for the second time, so the native implementations should be preferred.
* We use raw access for Linux prior to 2.6.12. For newer version, we need to
* use ioread32() and iowrite32(), which would take care of indirect access to
* the registers.
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) && \
!defined(CONFIG_GENERIC_IOMAP) && (AH_BYTE_ORDER == AH_BIG_ENDIAN) && \
!defined(__mips__) && !defined(__hppa__) && !defined(__powerpc__)
(AH_BYTE_ORDER == AH_BIG_ENDIAN) && \
!defined(CONFIG_GENERIC_IOMAP) && \
!defined(CONFIG_PARICS) && \
!(defined(CONFIG_PPC64) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))) && \
!defined(CONFIG_PPC_MERGE) && \
!(defined(CONFIG_MIPS) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)))
# ifndef iowrite32be
# define iowrite32be(_val, _addr) iowrite32(swab32((_val)), (_addr))
# endif
@ -177,54 +185,53 @@ extern void *__ahdecl ath_hal_memcpy(void *, const void *, size_t);
* debugging is enabled (AH_DEBUG) or it's explicitly requested for the target.
*
* The hardware registers use little-endian byte order natively. Big-endian
* systems are configured by HAL to enable hardware byte-swap of register reads
* and writes at reset. This avoid the need to byte-swap the data in software.
* However, the registers in a certain area from 0x4000 to 0x4fff (PCI clock
* domain registers) are not byte swapped!
* systems are configured by HAL to byte-swap of register reads and writes.
* However, the registers in the areas 0x4000-0x4fff and 0x7000-0x7fff are not
* byte swapped!
*
* Since Linux I/O primitives default to little-endian operations, we only
* need to suppress byte-swapping on big-endian systems outside the area used
* by the PCI clock domain registers.
*/
#if (AH_BYTE_ORDER == AH_BIG_ENDIAN)
#define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000) || \
(0x7000 <= (__reg) && (__reg) < 0x8000))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
#define _OS_REG_WRITE(_ah, _reg, _val) do { \
# define is_reg_le(__reg) ((0x4000 <= (__reg) && (__reg) < 0x5000) || \
(0x7000 <= (__reg) && (__reg) < 0x8000))
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
# define _OS_REG_WRITE(_ah, _reg, _val) do { \
is_reg_le(_reg) ? \
iowrite32((_val), (_ah)->ah_sh + (_reg)) : \
iowrite32be((_val), (_ah)->ah_sh + (_reg)); \
iowrite32((_val), (_ah)->ah_sh + (_reg)) : \
iowrite32be((_val), (_ah)->ah_sh + (_reg)); \
} while (0)
#define _OS_REG_READ(_ah, _reg) \
# define _OS_REG_READ(_ah, _reg) \
(is_reg_le(_reg) ? \
ioread32((_ah)->ah_sh + (_reg)) : \
ioread32be((_ah)->ah_sh + (_reg)))
#else
#define _OS_REG_WRITE(_ah, _reg, _val) do { \
writel(is_reg_le(_reg) ? \
(_val) : cpu_to_le32(_val), \
(_ah)->ah_sh + (_reg)); \
ioread32((_ah)->ah_sh + (_reg)) : \
ioread32be((_ah)->ah_sh + (_reg)))
# else /* Linux < 2.6.12 */
# define _OS_REG_WRITE(_ah, _reg, _val) do { \
writel(is_reg_le(_reg) ? \
(_val) : cpu_to_le32(_val), \
(_ah)->ah_sh + (_reg)); \
} while (0)
#define _OS_REG_READ(_ah, _reg) \
# define _OS_REG_READ(_ah, _reg) \
(is_reg_le(_reg) ? \
readl((_ah)->ah_sh + (_reg)) : \
cpu_to_le32(readl((_ah)->ah_sh + (_reg))))
#endif /* KERNEL_VERSION(2,6,12) */
#else /* AH_BYTE_ORDER != AH_BIG_ENDIAN */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
#define _OS_REG_WRITE(_ah, _reg, _val) do { \
readl((_ah)->ah_sh + (_reg)) : \
cpu_to_le32(readl((_ah)->ah_sh + (_reg))))
# endif /* Linux < 2.6.12 */
#else /* Little endian */
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
# define _OS_REG_WRITE(_ah, _reg, _val) do { \
iowrite32((_val), (_ah)->ah_sh + (_reg)); \
} while (0)
#define _OS_REG_READ(_ah, _reg) \
# define _OS_REG_READ(_ah, _reg) \
ioread32((_ah)->ah_sh + (_reg))
#else
#define _OS_REG_WRITE(_ah, _reg, _val) do { \
# else /* Linux < 2.6.12 */
# define _OS_REG_WRITE(_ah, _reg, _val) do { \
writel((_val), (_ah)->ah_sh + (_reg)); \
} while (0)
#define _OS_REG_READ(_ah, _reg) \
# define _OS_REG_READ(_ah, _reg) \
readl((_ah)->ah_sh + (_reg))
#endif /* KERNEL_VERSION(2,6,12) */
#endif /* AH_BYTE_ORDER != AH_BIG_ENDIAN */
# endif /* Linux < 2.6.12 */
#endif /* Little endian */
#define HAL_DEBUG_OFF 0
/* Show register accesses */