/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * Description:
 *
 *---------------------------------------------------------------------------*/

#ifndef X_HAL_IO_H
#define X_HAL_IO_H

#include "x_typedef.h"
#include "x_hal_reg.h"

#if defined(__KERNEL__)
#include <linux/string.h>
#ifndef CC_UBOOT
#include <linux/irqflags.h>
#include <linux/kernel.h>
#endif
#endif
//===========================================================================

// Type of IO register, for recording the address of an IO register
typedef volatile UINT32             HAL_IO_REGISTER;

#if defined(CONFIG_64BIT) || defined (__USERDRV__)
#if 0
#define OFFSET_64BIT 0xFFFFFF8000000000UL
#else
extern UPTR pdwnc_reg_base;
extern UPTR pdwnc_sram_reg_base;
extern UPTR tv_reg_base;
extern UPTR tv_sre_reg_base;
extern UPTR SW_DRAM_BASE;
/* keep this not 0 for ncstool */
#define SW_REG_64_BASE  0x1000
#endif

#ifndef IO_VIRT
#error "IO_VIRT must be defined!!"
#endif

#ifndef IO_VIRT_SRE
#define IO_VIRT_SRE ULLONG_MAX
#endif

#ifndef IO_VIRT_PDWNC
#define IO_VIRT_PDWNC ULLONG_MAX
#endif

#ifndef IO_VIRT_PDWNC_SRAM
#define IO_VIRT_PDWNC_SRAM ULLONG_MAX
#endif

#ifndef IO_VIRT_MAX
#define IO_VIRT_MAX ULLONG_MAX
#endif
/*
 * Assume the 4 chunks has at least 0x10000000 gap to avoid overlaping
 */
#if IO_VIRT < SW_REG_64_BASE
#error "IO_VIRT should >= SW_REG_64_BASE"
#endif
#if IO_VIRT_SRE < IO_VIRT
#error "IO_VIRT_SRE should >= IO_VIRT"
#endif
#if IO_VIRT_PDWNC_SRAM < IO_VIRT_SRE
#error "IO_VIRT_PDWNC_SRAM should >= IO_VIRT_SRE"
#endif
#if IO_VIRT_PDWNC < IO_VIRT_PDWNC_SRAM
#error "IO_VIRT_PDWNC should >= IO_VIRT_PDWNC_SRAM"
#endif

#define OFFSET_64BIT            (tv_reg_base - IO_VIRT)
#define OFFSET_64BIT_SRE        (tv_sre_reg_base - IO_VIRT_SRE)
#define OFFSET_64BIT_PDWNC      (pdwnc_reg_base - IO_VIRT_PDWNC)
#define OFFSET_64BIT_PDWNC_SRAM (pdwnc_sram_reg_base - IO_VIRT_PDWNC_SRAM)
#ifdef USERDRV_KERNEL_MOD
//kernel builit-in shouldn't have this case.
#define OFFSET_SWREG_64BIT 0
#else
#define OFFSET_SWREG_64BIT (SW_DRAM_BASE - SW_REG_64_BASE)
#endif

#ifdef CC_CHECK_IO_VIRT
static inline UINT64 check_io_virt(UINT64 _reg_)
{
	WARN(_reg_ > (UINT64)IO_VIRT_MAX, "Invalid IO virt address 0x%lx !!!!!\n", _reg_);
	return 0;
}
#else
static inline UINT64 check_io_virt(UINT64 _reg_) { return 0; }
#endif

/*
 * This is a simplified version of
 * (if _reg_ < IO_VIRT),
 *     than (OFFSET_SWREG_64BIT)
 * (else if _reg_ >= IO_VIRT and < IO_VIRT + IO_VIRT_SIZE),
 *     than (OFFSET_64BIT)
 * (else if _reg_ >= IO_VIRT_SRE and < IO_VIRT_SRE + IO_VIRT_SRE_SIZE),
 *     than (OFFSET_64BIT_SRE)
 * (else if _reg_ >= IO_VIRT_PDWNC_SRAM and < IO_VIRT_PDWNC_SRAM + IO_VIRT_PDWNC_SRAM_SIZE),
 *     than (OFFSET_64BIT_PDWNC_SRAM)
 * (else if _reg_ >= IO_VIRT_PDWNC and < IO_VIRT_PDWNC + IO_VIRT_PDWNC_SIZE),
 *     than (OFFSET_64BIT_PDWNC)
 * (else)
 *     error
 * Assume user knows they would send reasonable _reg_ to this function.
 */
#if !(IO_VIRT_SRE == ULLONG_MAX)
#define __HAL_READ_OFFSET(_reg_)    ((UINT64) (_reg_) < (UINT64) IO_VIRT ? \
                                        (OFFSET_SWREG_64BIT) : \
                                    ((UINT64) (_reg_) < (UINT64) IO_VIRT_SRE ? \
                                        (OFFSET_64BIT) : \
                                    ((UINT64) (_reg_) < (UINT64) IO_VIRT_PDWNC_SRAM ? \
                                        (OFFSET_64BIT_SRE) : \
                                    ((UINT64) (_reg_) < (UINT64) IO_VIRT_PDWNC ? \
                                        (OFFSET_64BIT_PDWNC_SRAM) : \
                                        (OFFSET_64BIT_PDWNC)))))
#else
/*
 * Actually we don't need if/else macro, GCC with -O2 would optimize for us.
 * But Coverity test thinks it's always true and goes crazy.
 */
#define __HAL_READ_OFFSET(_reg_)    ((UINT64) (_reg_) < (UINT64) IO_VIRT ? \
                                        (OFFSET_SWREG_64BIT) : \
                                        (OFFSET_64BIT))
#endif
#define __HAL_READ(_reg_)           (check_io_virt((UINT64)(_reg_)) + (UINT64) (_reg_) + (UINT64) __HAL_READ_OFFSET(_reg_))
#define HAL_READ8(_reg_)            (*((volatile UINT8*)__HAL_READ(_reg_)))
#define HAL_READ16(_reg_)           (*((volatile UINT16*)__HAL_READ(_reg_)))
#define HAL_READ32(_reg_)           (*((volatile UINT32*)__HAL_READ(_reg_)))
// Macros of register write
#define HAL_WRITE8(_reg_, _val_)    (*((volatile UINT8*)__HAL_READ(_reg_)) = (_val_))
#define HAL_WRITE16(_reg_, _val_)   (*((volatile UINT16*)__HAL_READ(_reg_)) = (_val_))
#define HAL_WRITE32(_reg_, _val_)   (*((volatile UINT32*)__HAL_READ(_reg_)) = (_val_))
#else
#define OFFSET_64BIT (0)
#define OFFSET_64BIT_SRE (0)
#define SW_REG_64_BASE  0
#define __HAL_READ_OFFSET(_reg_)    0
#define __HAL_READ(_reg_)           (_reg_)
// Macros of register read
#define HAL_READ8(_reg_)            (*((volatile UINT8*)(_reg_)))
#define HAL_READ16(_reg_)           (*((volatile UINT16*)(_reg_)))
#define HAL_READ32(_reg_)           (*((volatile UINT32*)(_reg_)))

// Macros of register write
#define HAL_WRITE8(_reg_, _val_)    (*((volatile UINT8*)(_reg_)) = (_val_))
#define HAL_WRITE16(_reg_, _val_)   (*((volatile UINT16*)(_reg_)) = (_val_))
#define HAL_WRITE32(_reg_, _val_)   (*((volatile UINT32*)(_reg_)) = (_val_))

#endif
// Macros for read/write access
#define HAL_REG8(_reg_)         HAL_READ8((_reg_))
#define HAL_REG16(_reg_)        HAL_READ16((_reg_))
#define HAL_REG32(_reg_)        HAL_READ32((_reg_))

//===========================================================================

// Bit field definitions
#define BIT0                        0x00000001
#define BIT1                        0x00000002
#define BIT2                        0x00000004
#define BIT3                        0x00000008
#define BIT4                        0x00000010
#define BIT5                        0x00000020
#define BIT6                        0x00000040
#define BIT7                        0x00000080
#define BIT8                        0x00000100
#define BIT9                        0x00000200
#define BIT10                       0x00000400
#define BIT11                       0x00000800
#define BIT12                       0x00001000
#define BIT13                       0x00002000
#define BIT14                       0x00004000
#define BIT15                       0x00008000
#define BIT16                       0x00010000
#define BIT17                       0x00020000
#define BIT18                       0x00040000
#define BIT19                       0x00080000
#define BIT20                       0x00100000
#define BIT21                       0x00200000
#define BIT22                       0x00400000
#define BIT23                       0x00800000
#define BIT24                       0x01000000
#define BIT25                       0x02000000
#define BIT26                       0x04000000
#define BIT27                       0x08000000
#define BIT28                       0x10000000
#define BIT29                       0x20000000
#define BIT30                       0x40000000
#define BIT31                       0x80000000


// field access macro-----------------------------------------------------------

/* field macros */
#define Fld(wid,shft,ac)    (((UINT32)wid<<16)|(shft<<8)|ac)
#define Fld_wid(fld)    (UINT8)((fld)>>16)
#define Fld_shft(fld)   (UINT8)((fld)>>8)
#define Fld_ac(fld)     (UINT8)(fld)

/* access method*/
#define AC_FULLB0       1
#define AC_FULLB1       2
#define AC_FULLB2       3
#define AC_FULLB3       4
#define AC_FULLW10      5
#define AC_FULLW21      6
#define AC_FULLW32      7
#define AC_FULLDW       8
#define AC_MSKB0        11
#define AC_MSKB1        12
#define AC_MSKB2        13
#define AC_MSKB3        14
#define AC_MSKW10       15
#define AC_MSKW21       16
#define AC_MSKW32       17
#define AC_MSKDW        18

/* Reg32 to Reg8*/
#define REGB0(reg)  (reg)
#define REGB1(reg)  ((reg)+1)
#define REGB2(reg)  ((reg)+2)
#define REGB3(reg)  ((reg)+3)
/* Reg32 to Reg16*/
#define REGW0(reg)  (reg)
#define REGW1(reg)  ((reg)+1)
#define REGW2(reg)  ((reg)+2)

/* --------FLD help macros, mask32 to mask8,mask16,maskalign ----------*/
/* mask32 -> mask8 */
#define MSKB0(msk)  (UINT8)(msk)
#define MSKB1(msk)  (UINT8)((msk)>>8)
#define MSKB2(msk)  (UINT8)((msk)>>16)
#define MSKB3(msk)  (UINT8)((msk)>>24)
/* mask32 -> mask16 */
#define MSKW0(msk)  (UINT16)(msk)
#define MSKW1(msk)  (UINT16)((msk)>>8)
#define MSKW2(msk)  (UINT16)((msk)>>16)
                        /* mask32 -> maskalign */
#define MSKAlignB(msk)  (((msk)&0xff)?(msk):(\
            ((msk)&0xff00)?((msk)>>8):(\
            ((msk)&0xff0000)?((msk)>>16):((msk)>>24)\
        )\
    ))

/* --------FLD help macros, mask32 to mask8,mask16,maskalign ----------*/
#define Fld2Msk32(fld)  /*lint -save -e504 */ (((UINT32)0xffffffff>>(32-Fld_wid(fld)))<<Fld_shft(fld)) /*lint -restore */
#define Fld2MskB0(fld)  MSKB0(Fld2Msk32(fld))
#define Fld2MskB1(fld)  MSKB1(Fld2Msk32(fld))
#define Fld2MskB2(fld)  MSKB2(Fld2Msk32(fld))
#define Fld2MskB3(fld)  MSKB3(Fld2Msk32(fld))
#define Fld2MskBX(fld,byte) ((UINT8)(Fld2Msk32(fld)>>((byte&3)*8)))

#define Fld2MskW0(fld)  MSKW0(Fld2Msk32(fld))
#define Fld2MskW1(fld)  MSKW1(Fld2Msk32(fld))
#define Fld2MskW2(fld)  MSKW2(Fld2Msk32(fld))
#define Fld2MskWX(fld,byte) ((UINT16)(Fld2Msk32(fld)>>((byte&3)*8)))

#define Fld2MskAlignB(fld)  MSKAlignB(Fld2Msk32(fld))
#define FldshftAlign(fld)   ((Fld_shft(fld)<8)?Fld_shft(fld):(\
            (Fld_shft(fld)<16)?(Fld_shft(fld)-8):(\
            (Fld_shft(fld)<24)?(Fld_shft(fld)-16):(Fld_shft(fld)-24)\
        )\
    ))
#define ValAlign2Fld(val,fld)   ((val)<<FldshftAlign(fld))
#if defined(CONFIG_64BIT) || defined (__USERDRV__)
#define u1IO32Read1B(reg32) (*(volatile UINT8 *)(__HAL_READ(reg32)))
extern UINT16 u2IO32Read2B(UPTR reg32);
#define u4IO32Read4B(reg32) (*(volatile UINT32 *)(__HAL_READ(reg32)))

#define vIO32Write1B(reg32, val8) vIO32Write1BMsk(reg32,val8,0xff)
#define vIO32Write2B(reg32, val16) vIO32Write2BMsk(reg32,val16,0xffff)
#define vIO32Write4B(reg32,val32) (*(volatile UINT32 *)(__HAL_READ(reg32))=(val32))
#else
#define u1IO32Read1B(reg32) (*(volatile UINT8 *)(reg32))
extern UINT16 u2IO32Read2B(UPTR reg32);
#define u4IO32Read4B(reg32) (*(volatile UINT32 *)(reg32))

#define vIO32Write1B(reg32, val8) vIO32Write1BMsk(reg32,val8,0xff)
#define vIO32Write2B(reg32, val16) vIO32Write2BMsk(reg32,val16,0xffff)
#define vIO32Write4B(reg32,val32) (*(volatile UINT32 *)(reg32)=(val32))

#endif
//always set FORCE_IO32_1BMSK_FUNCTION for linux ko code size reduction
#define FORCE_IO32_1BMSK_FUNCTION
#if defined(FORCE_IO32_1BMSK_FUNCTION) || defined(CC_MTK_LOADER) || defined(CC_UBOOT) || !defined(__KERNEL__)
extern void vIO32Write1BMsk(UPTR reg32, UINT32 val8,UINT8 msk8);
#else
static inline void vIO32Write1BMsk(UPTR reg32, UINT32 val8, UINT8 msk8)
{
    unsigned long flags;
    UINT32 u4Val, u4Msk;
    UINT8 bByte;
#if defined(CONFIG_64BIT) || defined (__USERDRV__)
    UPTR uptrOffset = __HAL_READ_OFFSET(reg32);
#else
    UPTR uptrOffset = 0;
#endif


    bByte = reg32&3;
    reg32 &= ~3;
    val8 &= msk8;
    u4Msk = ~(UINT32)(msk8<<((UINT32)bByte<<3));

    local_irq_save(flags);
    u4Val = (*(volatile UINT32 *)(reg32 + uptrOffset));
    u4Val = ((u4Val & u4Msk) | ((UINT32)val8 << (bByte<<3)));

    (*(volatile UINT32 *)(reg32 + uptrOffset)=(u4Val));
    local_irq_restore(flags);

}
#endif
extern void vIO32Write2BMsk(UPTR reg32, UINT32 val16, UINT16 msk16);
extern void vIO32Write4BMsk(UPTR reg32, UINT32 val32, UINT32 msk32);


#define IO32ReadFld(reg32,fld)  /*lint -save -e506 -e504 -e514 -e62 -e737 -e572 -e961 -e648 -e701 -e732 -e571 */ \
    (((Fld_ac(fld)>=AC_FULLB0)&&(Fld_ac(fld)<=AC_FULLB3))?u1IO32Read1B((reg32)+(Fld_ac(fld)-AC_FULLB0)):( \
    ((Fld_ac(fld)>=AC_FULLW10)&&(Fld_ac(fld)<=AC_FULLW32))?u2IO32Read2B((reg32)+(Fld_ac(fld)-AC_FULLW10)):( \
    (Fld_ac(fld)==AC_FULLDW)? u4IO32Read4B(reg32):( \
    ((Fld_ac(fld)>=AC_MSKB0)&&(Fld_ac(fld)<=AC_MSKB3))?(u1IO32Read1B((reg32)+(Fld_ac(fld)-AC_MSKB0))&Fld2MskBX(fld,(Fld_ac(fld)-AC_MSKB0))):( \
    ((Fld_ac(fld)>=AC_MSKW10)&&(Fld_ac(fld)<=AC_MSKW32))?(u2IO32Read2B((reg32)+(Fld_ac(fld)-AC_MSKW10))&Fld2MskWX(fld,(Fld_ac(fld)-AC_MSKW10))):( \
    (Fld_ac(fld)==AC_MSKDW)?(u4IO32Read4B(reg32)&Fld2Msk32(fld)):0 \
  ))))))  /*lint -restore */


#define IO32ReadFldAlign(reg32,fld) /*lint -save -e506 -e504 -e514 -e62 -e737 -e572 -e961 -e648 -e701 -e732 -e571 */ \
    (((Fld_ac(fld)>=AC_FULLB0)&&(Fld_ac(fld)<=AC_FULLB3))?u1IO32Read1B((reg32)+(Fld_ac(fld)-AC_FULLB0)):( \
    ((Fld_ac(fld)>=AC_FULLW10)&&(Fld_ac(fld)<=AC_FULLW32))?u2IO32Read2B((reg32)+(Fld_ac(fld)-AC_FULLW10)):( \
    (Fld_ac(fld)==AC_FULLDW)? u4IO32Read4B(reg32):( \
    ((Fld_ac(fld)>=AC_MSKB0)&&(Fld_ac(fld)<=AC_MSKB3))?((UINT32)(u1IO32Read1B((reg32)+(Fld_ac(fld)-AC_MSKB0))&Fld2MskBX(fld,(Fld_ac(fld)-AC_MSKB0)))>>((Fld_shft(fld)-8*(Fld_ac(fld)-AC_MSKB0))&7)):( \
    ((Fld_ac(fld)>=AC_MSKW10)&&(Fld_ac(fld)<=AC_MSKW32))?((u2IO32Read2B((reg32)+(Fld_ac(fld)-AC_MSKW10))&Fld2MskWX(fld,(Fld_ac(fld)-AC_MSKW10)))>>((Fld_shft(fld)-8*(Fld_ac(fld)-AC_MSKW10))&15)):( \
    (Fld_ac(fld)==AC_MSKDW)?((u4IO32Read4B(reg32)&Fld2Msk32(fld))>>Fld_shft(fld)):0 \
  ))))))  /*lint -restore */

#define vIO32WriteFld(reg32,val,fld) /*lint -save -e506 -e504 -e514 -e62 -e737 -e572 -e961 -e648 -e701 -e732 -e571 */ \
    (((Fld_ac(fld)>=AC_FULLB0)&&(Fld_ac(fld)<=AC_FULLB3))? vIO32Write1B((reg32)+(Fld_ac(fld)-AC_FULLB0),(val)):( \
    ((Fld_ac(fld)>=AC_FULLW10)&&(Fld_ac(fld)<=AC_FULLW32))?vIO32Write2B((reg32)+(Fld_ac(fld)-AC_FULLW10),(val)):( \
    (Fld_ac(fld)==AC_FULLDW)?vIO32Write4B((reg32),(val)):( \
    ((Fld_ac(fld)>=AC_MSKB0)&&(Fld_ac(fld)<=AC_MSKB3))?vIO32Write1BMsk((reg32)+(Fld_ac(fld)-AC_MSKB0),(val),Fld2MskBX(fld,(Fld_ac(fld)-AC_MSKB0))):( \
    ((Fld_ac(fld)>=AC_MSKW10)&&(Fld_ac(fld)<=AC_MSKW32))?vIO32Write2BMsk((reg32)+(Fld_ac(fld)-AC_MSKW10),(val),Fld2MskWX(fld,(Fld_ac(fld)-AC_MSKW10))):( \
    (Fld_ac(fld)==AC_MSKDW)?vIO32Write4BMsk((reg32),(val),Fld2Msk32(fld)):0\
    ))))))  /*lint -restore */

#define vIO32WriteFldAlign(reg32,val,fld) /*lint -save -e506 -e504 -e514 -e62 -e737 -e572 -e961 -e648 -e701 -e732 -e571 */ \
    (((Fld_ac(fld)>=AC_FULLB0)&&(Fld_ac(fld)<=AC_FULLB3))?vIO32Write1B((reg32)+(Fld_ac(fld)-AC_FULLB0),(val)):( \
    ((Fld_ac(fld)>=AC_FULLW10)&&(Fld_ac(fld)<=AC_FULLW32))?vIO32Write2B((reg32)+(Fld_ac(fld)-AC_FULLW10),(val)):( \
    (Fld_ac(fld)==AC_FULLDW)?vIO32Write4B((reg32),(val)):( \
    ((Fld_ac(fld)>=AC_MSKB0)&&(Fld_ac(fld)<=AC_MSKB3))?vIO32Write1BMsk((reg32)+(Fld_ac(fld)-AC_MSKB0),ValAlign2Fld((val),fld),Fld2MskBX(fld,(Fld_ac(fld)-AC_MSKB0))):( \
    ((Fld_ac(fld)>=AC_MSKW10)&&(Fld_ac(fld)<=AC_MSKW32))?vIO32Write2BMsk((reg32)+(Fld_ac(fld)-AC_MSKW10),ValAlign2Fld((val),fld),Fld2MskWX(fld,(Fld_ac(fld)-AC_MSKW10))):( \
    (Fld_ac(fld)==AC_MSKDW)?vIO32Write4BMsk((reg32),((UINT32)(val)<<Fld_shft(fld)),Fld2Msk32(fld)):0\
    )))))) /*lint -restore */

#define vIO32WriteFldMulti(reg32,list) /*lint -save -e506 -e504 -e514 -e62 -e737 -e572 -e961 -e648 -e701 -e732 -e571 */ \
{ \
	UINT16 upk;\
	INT32 msk=(INT32)(list); \
	{UINT8 upk;\
	((UINT32)msk==0xff)?vIO32Write1B(reg32,(list)):(\
	((UINT32)msk==0xff00)?vIO32Write1B(reg32+1,(list)>>8):(\
	((UINT32)msk==0xff0000)?vIO32Write1B(reg32+2,(list)>>16):(\
	((UINT32)msk==0xff000000)?vIO32Write1B(reg32+3,(list)>>24):(\
	((UINT32)msk==0xffff)?vIO32Write2B(reg32,(list)):(\
	((UINT32)msk==0xffff00)?vIO32Write2B(reg32+1,(list)>>8):(\
	((UINT32)msk==0xffff0000)?vIO32Write2B(reg32+2,(list)>>16):(\
	((UINT32)msk==0xffffffff)?vIO32Write4B(reg32,(list)):(\
	(((UINT32)msk&0xff)&&(!((UINT32)msk&0xffffff00)))?vIO32Write1BMsk(reg32,(list),(UINT8)(UINT32)msk):(\
	(((UINT32)msk&0xff00)&&(!((UINT32)msk&0xffff00ff)))?vIO32Write1BMsk(reg32+1,(list)>>8,(UINT8)((UINT32)msk>>8)):(\
	(((UINT32)msk&0xff0000)&&(!((UINT32)msk&0xff00ffff)))?vIO32Write1BMsk(reg32+2,(list)>>16,(UINT8)((UINT32)msk>>16)):(\
	(((UINT32)msk&0xff000000)&&(!((UINT32)msk&0x00ffffff)))?vIO32Write1BMsk(reg32+3,(list)>>24,(UINT8)((UINT32)msk>>24)):(\
	(((UINT32)msk&0xffff)&&(!((UINT32)msk&0xffff0000)))?vIO32Write2BMsk(reg32,(list),(UINT16)(UINT32)msk):(\
	(((UINT32)msk&0xffff00)&&(!((UINT32)msk&0xff0000ff)))?vIO32Write2BMsk(reg32+1,(list)>>8,(UINT16)((UINT32)msk>>8)):(\
	(((UINT32)msk&0xffff0000)&&(!((UINT32)msk&0x0000ffff)))?vIO32Write2BMsk(reg32+2,(list)>>16,(UINT16)((UINT32)msk>>16)):(\
	((UINT32)msk)?vIO32Write4BMsk(reg32,(list),((UINT32)msk)):0\
	)))))))))))))));\
	}\
}/*lint -restore */

#define vIO32WriteFldD4val(reg32,dval32,list) /*lint -save -e506 -e504 -e514 -e62 -e737 -e572 -e961 -e648 -e701 -e732 -e571 */ \
{ \
	UINT16 upk;\
	enum {msk=(INT32)(list)};\
	{UINT8 upk;\
	vIO32Write4B(reg32,((dval32)&~(UINT32)msk)|(list));\
	}\
}/*lint -restore */

#endif  // X_HAL_IO_H
