third_party/virtualbox/src/VBox/Devices/Network/DevE1000.cpp
/**
 * Handle unaligned register read operation.
 *
 * Looks up and calls appropriate handler.
 *
 * @returns VBox status code.
 *
 * @param   pThis       The device state structure.
 * @param   offReg      Register offset in memory-mapped frame.
 * @param   pv          Where to store the result.
 * @param   cb          Number of bytes to read.
 * @thread  EMT
 * @remarks IOM takes care of unaligned and small reads via MMIO.  For I/O port
 *          accesses we have to take care of that ourselves.
 */
Handle unaligned register read operation.
Looks up and calls appropriate handler.

@returns VBox status code.

@param   pThis       The device state structure.
@param   offReg      Register offset in memory-mapped frame.
@param   pv          Where to store the result.
@param   cb          Number of bytes to read.
@thread  EMT
@remarks IOM takes care of unaligned and small reads via MMIO.  For I/O port
accesses we have to take care of that ourselves.
Handle unaligned register read operation . Looks up and calls appropriate handler . @returns VBox status code . @param pThis The device state structure . @param offReg Register offset in memory - mapped frame . @param pv Where to store the result . @param cb Number of bytes to read . @thread EMT @remarks IOM takes care of unaligned and small reads via MMIO . For I / O port accesses we have to take care of that ourselves .
static int e1kRegReadUnaligned(PE1KSTATE pThis, uint32_t offReg, void *pv, uint32_t cb)
{
    uint32_t    u32    = 0;
    uint32_t    shift;
    int         rc     = VINF_SUCCESS;
    int         index  = e1kRegLookup(offReg);
#ifdef LOG_ENABLED
    char        buf[9];
#endif
    uint32_t mask;
    switch (cb)
    {
        case 4: mask = 0xFFFFFFFF; break;
        case 2: mask = 0x0000FFFF; break;
        case 1: mask = 0x000000FF; break;
        default:
            return PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS,
                                     "unsupported op size: offset=%#10x cb=%#10x\n", offReg, cb);
    }
    if (index != -1)
    {
        RT_UNTRUSTED_VALIDATED_FENCE(); 
        if (g_aE1kRegMap[index].readable)
        {
            shift = (offReg - g_aE1kRegMap[index].offset) % sizeof(uint32_t) * 8;
            mask <<= shift;
            if (!mask)
                return PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS, "Zero mask: offset=%#10x cb=%#10x\n", offReg, cb);
            if (RT_UNLIKELY(rc != VINF_SUCCESS))
                return rc;
            rc = g_aE1kRegMap[index].pfnRead(pThis, offReg & 0xFFFFFFFC, index, &u32);
            u32 &= mask;
            E1kLog2(("%s At %08X read  %s          from %s (%s)\n",
                    pThis->szPrf, offReg, e1kU32toHex(u32, mask, buf), g_aE1kRegMap[index].abbrev, g_aE1kRegMap[index].name));
            Log6(("%s At %08X read  %s          from %s (%s) [UNALIGNED]\n",
                  pThis->szPrf, offReg, e1kU32toHex(u32, mask, buf), g_aE1kRegMap[index].abbrev, g_aE1kRegMap[index].name));
            u32 >>= shift;
        }
        else
            E1kLog(("%s At %08X read (%s) attempt from write-only register %s (%s)\n",
                    pThis->szPrf, offReg, e1kU32toHex(u32, mask, buf), g_aE1kRegMap[index].abbrev, g_aE1kRegMap[index].name));
        if (IOM_SUCCESS(rc))
            STAM_COUNTER_INC(&pThis->aStatRegReads[index]);
    }
    else
        E1kLog(("%s At %08X read (%s) attempt from non-existing register\n",
                pThis->szPrf, offReg, e1kU32toHex(u32, mask, buf)));
    memcpy(pv, &u32, cb);
    return rc;
}
static int e1kRegReadUnaligned ( PE1KSTATE pThis , uint32_t offReg , void * pv , uint32_t cb ) { uint32_t u32 = 0 ; uint32_t shift ; int rc = VINF_SUCCESS ; int index = e1kRegLookup ( offReg ) ; #ifdef LOG_ENABLED char buf [ 9 ] ; #endif uint32_t mask ; switch ( cb ) { case 4 : mask = 0xFFFFFFFF ; break ; case 2 : mask = 0x0000FFFF ; break ; case 1 : mask = 0x000000FF ; break ; default : return PDMDevHlpDBGFStop ( pThis -> CTX_SUFF ( pDevIns ) , RT_SRC_POS , " \n " , offReg , cb ) ; } if ( index != -1 ) { RT_UNTRUSTED_VALIDATED_FENCE ( ) ; if ( g_aE1kRegMap [ index ] . readable ) { shift = ( offReg - g_aE1kRegMap [ index ] . offset ) % sizeof ( uint32_t ) * 8 ; mask <<= shift ; if ( ! mask ) return PDMDevHlpDBGFStop ( pThis -> CTX_SUFF ( pDevIns ) , RT_SRC_POS , " \n " , offReg , cb ) ; if ( RT_UNLIKELY ( rc != VINF_SUCCESS ) ) return rc ; rc = g_aE1kRegMap [ index ] . pfnRead ( pThis , offReg & 0xFFFFFFFC , index , & u32 ) ; u32 &= mask ; E1kLog2 ( ( " \n " , pThis -> szPrf , offReg , e1kU32toHex ( u32 , mask , buf ) , g_aE1kRegMap [ index ] . abbrev , g_aE1kRegMap [ index ] . name ) ) ; Log6 ( ( " \n " , pThis -> szPrf , offReg , e1kU32toHex ( u32 , mask , buf ) , g_aE1kRegMap [ index ] . abbrev , g_aE1kRegMap [ index ] . name ) ) ; u32 >>= shift ; } else E1kLog ( ( " \n " , pThis -> szPrf , offReg , e1kU32toHex ( u32 , mask , buf ) , g_aE1kRegMap [ index ] . abbrev , g_aE1kRegMap [ index ] . name ) ) ; if ( IOM_SUCCESS ( rc ) ) STAM_COUNTER_INC ( & pThis -> aStatRegReads [ index ] ) ; } else E1kLog ( ( " \n " , pThis -> szPrf , offReg , e1kU32toHex ( u32 , mask , buf ) ) ) ; memcpy ( pv , & u32 , cb ) ; return rc ; }
Handle unaligned register read operation.
Handle unaligned register read operation .
/*
     * From the spec:
     * For registers that should be accessed as 32-bit double words, partial writes (less than a 32-bit
     * double word) is ignored. Partial reads return all 32 bits of data regardless of the byte enables.
     */ /*
     * To be able to read bytes and short word we convert them to properly
     * shifted 32-bit words and masks.  The idea is to keep register-specific
     * handlers simple. Most accesses will be 32-bit anyway.
     */ /* paranoia because of port I/O. */ /* Make the mask correspond to the bits we are about to read. */ /*
             * Read it. Pass the mask so the handler knows what has to be read.
             * Mask out irrelevant bits.
             */ //rc = e1kCsEnter(pThis, VERR_SEM_BUSY, RT_SRC_POS); //pThis->fDelayInts = false; //pThis->iStatIntLost += pThis->iStatIntLostOne; //pThis->iStatIntLostOne = 0; //e1kCsLeave(pThis); /* Shift back the result. */