/* Initial device configuration. */ static BOOLEAN VBoxDrvInitialize(PVOID HwDeviceExtension) { PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; USHORT DispiId; PAGED_CODE(); LOGF_ENTER(); /* Initialize the request pointer. */ pExt->u.primary.pvReqFlush = NULL; /* Check if the chip restricts horizontal resolution or not. */ VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId == VBE_DISPI_ID_ANYX) pExt->fAnyX = TRUE; else pExt->fAnyX = FALSE; VBoxMPCmnInitCustomVideoModes(pExt); LOGF_LEAVE(); return TRUE; }
VP_STATUS VgaInterpretCmdStream( PHW_DEVICE_EXTENSION HwDeviceExtension, PUSHORT pusCmdStream ) /*++ Routine Description: Interprets the appropriate command array to set up VGA registers for the requested mode. Typically used to set the VGA into a particular mode by programming all of the registers Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. pusCmdStream - array of commands to be interpreted. Return Value: The status of the operation (can only fail on a bad command); TRUE for success, FALSE for failure. --*/ { ULONG ulCmd; ULONG ulPort; UCHAR jValue; USHORT usValue; ULONG culCount; ULONG ulIndex; ULONG ulBase; if (pusCmdStream == NULL) { VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n")); return TRUE; } ulBase = (ULONG)HwDeviceExtension->IOAddress; // // Now set the adapter to the desired mode. // while ((ulCmd = *pusCmdStream++) != EOD) { // // Determine major command type // switch (ulCmd & 0xF0) { // // Basic input/output command // case INOUT: // // Determine type of inout instruction // if (!(ulCmd & IO)) { // // Out instruction. Single or multiple outs? // if (!(ulCmd & MULTI)) { // // Single out. Byte or word out? // if (!(ulCmd & BW)) { // // Single byte out // ulPort = *pusCmdStream++; jValue = (UCHAR) *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)(ulBase+ulPort), jValue); } else { // // Single word out // ulPort = *pusCmdStream++; usValue = *pusCmdStream++; VideoPortWritePortUshort((PUSHORT)(ulBase+ulPort), usValue); } } else { // // Output a string of values // Byte or word outs? // if (!(ulCmd & BW)) { // // String byte outs. Do in a loop; can't use // VideoPortWritePortBufferUchar because the data // is in USHORT form // ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; while (culCount--) { jValue = (UCHAR) *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)ulPort, jValue); } } else { // // String word outs // ulPort = *pusCmdStream++; culCount = *pusCmdStream++; VideoPortWritePortBufferUshort((PUSHORT) (ulBase + ulPort), pusCmdStream, culCount); pusCmdStream += culCount; } } } else { // In instruction // // Currently, string in instructions aren't supported; all // in instructions are handled as single-byte ins // // Byte or word in? // if (!(ulCmd & BW)) { // // Single byte in // ulPort = *pusCmdStream++; jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort); } else { // // Single word in // ulPort = *pusCmdStream++; usValue = VideoPortReadPortUshort((PUSHORT) (ulBase+ulPort)); } } break; // // Higher-level input/output commands // case METAOUT: // // Determine type of metaout command, based on minor // command field // switch (ulCmd & 0x0F) { // // Indexed outs // case INDXOUT: ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; ulIndex = *pusCmdStream++; while (culCount--) { usValue = (USHORT) (ulIndex + (((ULONG)(*pusCmdStream++)) << 8)); VideoPortWritePortUshort((PUSHORT)ulPort, usValue); ulIndex++; } break; // // Masked out (read, AND, XOR, write) // case MASKOUT: ulPort = *pusCmdStream++; jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort); jValue &= *pusCmdStream++; jValue ^= *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)ulBase + ulPort, jValue); break; // // Attribute Controller out // case ATCOUT: ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; ulIndex = *pusCmdStream++; while (culCount--) { // Write Attribute Controller index VideoPortWritePortUchar((PUCHAR)ulPort, (UCHAR)ulIndex); // Write Attribute Controller data jValue = (UCHAR) *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)ulPort, jValue); ulIndex++; } break; // // None of the above; error // default: return FALSE; } break; // // NOP // case NCMD: break; // // Unknown command; error // default: return FALSE; } } return TRUE; } // end VgaInterpretCmdStream()
/* Checks if we have a device supported by our driver and initialize * our driver/card specific information. * In particular we obtain VM monitors configuration and configure related structures. */ static VP_STATUS VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { RT_NOREF(HwContext, ArgumentString, Again); PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; VP_STATUS rc; USHORT DispiId; ULONG cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; PHYSICAL_ADDRESS phVRAM = {0}; ULONG ulApertureSize = 0; PAGED_CODE(); LOGF_ENTER(); /* Init video port api */ VBoxSetupVideoPortAPI(pExt, ConfigInfo); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId != VBE_DISPI_ID2) { WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST")); return ERROR_DEV_NOT_EXIST; } LOG(("found the VBE card")); /* * Query the adapter's memory size. It's a bit of a hack, we just read * an ULONG from the data port without setting an index before. */ cbVRAM = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA); /* Write hw information to registry, so that it's visible in windows property dialog */ rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType", g_wszVBoxChipType, sizeof(g_wszVBoxChipType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType", g_wszVBoxDACType, sizeof(g_wszVBoxDACType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize", &cbVRAM, sizeof(ULONG)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString", g_wszVBoxAdapterString, sizeof(g_wszVBoxAdapterString)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString", g_wszVBoxBiosString, sizeof(g_wszVBoxBiosString)); VBOXMP_WARN_VPS(rc); /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up * and to get LFB aperture data. */ { VIDEO_ACCESS_RANGE tmpRanges[4]; ULONG slot = 0; VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges)); if (VBoxQueryWinVersion(NULL) == WINVERSION_NT4) { /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL, * and needs PCI ids for a successful VideoPortGetAccessRanges call. */ ULONG vendorId = 0x80EE; ULONG deviceId = 0xBEEF; rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, &vendorId, &deviceId, &slot); } else { rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot); } VBOXMP_WARN_VPS(rc); if (rc != NO_ERROR) { return rc; } /* The first non-IO range is the framebuffer. We require that information. */ for (int iRange = 0; iRange < RT_ELEMENTS(tmpRanges); ++iRange) { if (!tmpRanges[iRange].RangeInIoSpace) { phVRAM = tmpRanges[iRange].RangeStart; ulApertureSize = tmpRanges[iRange].RangeLength; break; } } } /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */ rc = VbglR0InitClient(); VBOXMP_WARN_VPS(rc); /* Preinitialize the primary extension. */ pExt->pNext = NULL; pExt->pPrimary = pExt; pExt->iDevice = 0; pExt->ulFrameBufferOffset = 0; pExt->ulFrameBufferSize = 0; pExt->u.primary.ulVbvaEnabled = 0; VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA)); /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old * code will be ifdef'ed and later removed. * The host will however support both old and new interface to keep compatibility * with old guest additions. */ VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, phVRAM, ulApertureSize, cbVRAM, 0); /* Check if the chip restricts horizontal resolution or not. * Must be done after VBoxSetupDisplaysHGSMI, because it initializes the common structure. */ VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId == VBE_DISPI_ID_ANYX) VBoxCommonFromDeviceExt(pExt)->fAnyX = TRUE; else VBoxCommonFromDeviceExt(pExt)->fAnyX = FALSE; if (pExt->u.primary.commonInfo.bHGSMI) { LOGREL(("using HGSMI")); VBoxCreateDisplays(pExt, ConfigInfo); } /** @todo pretend success to make the driver work. */ rc = NO_ERROR; LOGF_LEAVE(); VBOXMP_WARN_VPS(rc); return rc; }
VP_STATUS DGXFindAdapter( PVOID HwDeviceExtension, PVOID HwContext, PWSTR ArgumentString, PVIDEO_PORT_CONFIG_INFO ConfigInfo, PUCHAR Again ) /*++ Routine Description: This routine is called to determine if the adapter for this driver is present in the system. If it is present, the function fills out some information describing the adapter. Arguments: HwDeviceExtension - Supplies the miniport driver's adapter storage. This storage is initialized to zero before this call. HwContext - Supplies the context value which was passed to VideoPortInitialize(). ArgumentString - Suuplies a NULL terminated ASCII string. This string originates from the user. ConfigInfo - Returns the configuration information structure which is filled by the miniport driver. This structure is initialized with any knwon configuration information (such as SystemIoBusNumber) by the port driver. Where possible, drivers should have one set of defaults which do not require any supplied configuration information. Again - Indicates if the miniport driver wants the port driver to call its VIDEO_HW_FIND_ADAPTER function again with a new device extension and the same config info. This is used by the miniport drivers which can search for several adapters on a bus. Return Value: This routine must return: NO_ERROR - Indicates a host adapter was found and the configuration information was successfully determined. ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an error obtaining the configuration information. If possible an error should be logged. ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the supplied configuration information. --*/ { #define NUM_ACCESS_RANGES 5 PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; PVOID *pVirtAddr; ULONG i; USHORT temp; PUSHORT port; VP_STATUS status; PWSTR pwszChip= NULL; // chip name ULONG cbChip= 0; // length of chip name PWSTR pwszDac= NULL; // DAC name ULONG cbDac= 0; // length of DAC name ULONG cbMemSize; // size of video memory VIDEO_ACCESS_RANGE accessRange[NUM_ACCESS_RANGES] = { {0X00000061, 0x00000000, 0x00000001, 1, 1, 0}, // DGX I {0X00006CA8, 0x00000000, 0x00000001, 1, 1, 0}, // DGX I {0X00006C80, 0x00000000, 0x00000009, 1, 1, 0}, // DGX I & II {0X00000CAC, 0x00000000, 0x00000004, 1, 1, 0}, // front panel {0x20000000, 0x00000000, 0x00400000, 0, 1, 0} // Frame buf & dac }; // // Make sure the size of the structure is at least as large as what we // are expecting (check version of the config info structure). // if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) { return ERROR_INVALID_PARAMETER; } // // Check to see if there is a hardware resource conflict. // status = VideoPortVerifyAccessRanges(HwDeviceExtension, NUM_ACCESS_RANGES, accessRange); if (status != NO_ERROR) { return status; } // // Clear out the Emulator entries and the state size since this driver // does not support them. // ConfigInfo->NumEmulatorAccessEntries = 0; ConfigInfo->EmulatorAccessEntries = NULL; ConfigInfo->EmulatorAccessEntriesContext = 0; ConfigInfo->HardwareStateSize = 0; ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x00000000; ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000; ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00000000; // // Frame buffer information // hwDeviceExtension->FrameLength = DELL_DGX_LEN; hwDeviceExtension->PhysicalFrameAddress.HighPart = 0; hwDeviceExtension->PhysicalFrameAddress.LowPart = DELL_DGX_BASE; // // Map all of our ranges into system virtual address space. // IMPORTANT !!! // This is dependant on the order of the virtual addresses in the // HwDeviceExtensionto be the same as the order of the entries in the // access range structure. // pVirtAddr = &hwDeviceExtension->DGX1Misc; for (i=0 ; i <NUM_ACCESS_RANGES ; i++ ) { if ( (*pVirtAddr = VideoPortGetDeviceBase(hwDeviceExtension, accessRange[i].RangeStart, accessRange[i].RangeLength, accessRange[i].RangeInIoSpace)) == NULL) { return ERROR_INVALID_PARAMETER; } pVirtAddr++; } // // Are we really on a Dell DGX machine? If so which one? // hwDeviceExtension->ModelNumber = 0; port = (PUSHORT) hwDeviceExtension->DGXControlPorts; temp = VideoPortReadPortUshort(port++); if (temp == DELL_DGX_ID_LOW) { temp = VideoPortReadPortUshort(port); if (temp == DELL_DGX_1_ID_HIGH) { hwDeviceExtension->ModelNumber = 1; pwszChip= CHIPNAME1; cbChip= sizeof(CHIPNAME1); } if (temp == DELL_DGX_2_ID_HIGH) { hwDeviceExtension->ModelNumber = 2; pwszChip= CHIPNAME2; cbChip= sizeof(CHIPNAME2); } } if (hwDeviceExtension->ModelNumber == 0) { // // If we did not find the chip, free all the resources we allocated. // pVirtAddr = &hwDeviceExtension->DGX1Misc; for (i=0 ; i <NUM_ACCESS_RANGES ; i++) { VideoPortFreeDeviceBase(hwDeviceExtension, *pVirtAddr); pVirtAddr++; } return ERROR_DEV_NOT_EXIST; } // // Initialize the current mode number. // hwDeviceExtension->CurrentModeNumber = 0; // // Setup All the valid modes. // hwDeviceExtension->NumValidModes = 0; for (i=0; i < NumDGXModes; i++) { DGXModes[i].modeInformation.ModeIndex = i; DGXModes[i].bValid = TRUE; hwDeviceExtension->NumValidModes++; } // // Indicate we do not wish to be called over // *Again = 0; // // Init Front panel Display // DevSetPanel(HwDeviceExtension, PANEL_MESSAGE); // // Set hardware information strings in registry // VideoPortSetRegistryParameters(HwDeviceExtension, L"HardwareInformation.ChipType", pwszChip, cbChip ); pwszDac= DELL_DGX_DACNAME; cbDac= sizeof( DELL_DGX_DACNAME ); VideoPortSetRegistryParameters(HwDeviceExtension, L"HardwareInformation.DacType", pwszDac, cbDac ); cbMemSize= DELL_DGX_LEN; VideoPortSetRegistryParameters(HwDeviceExtension, L"HardwareInformation.MemorySize", &cbMemSize, sizeof(ULONG) ); // // Indicate a successful completion status. // return NO_ERROR; } // end DGXFindAdapter()
/* Checks if we have a device supported by our driver and initialize * our driver/card specific information. * In particular we obtain VM monitors configuration and configure related structures. */ static VP_STATUS VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; VP_STATUS rc; USHORT DispiId; ULONG AdapterMemorySize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; PAGED_CODE(); LOGF_ENTER(); /* Init video port api */ VBoxSetupVideoPortAPI(pExt, ConfigInfo); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId != VBE_DISPI_ID2) { WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST")); return ERROR_DEV_NOT_EXIST; } LOG(("found the VBE card")); /* * Query the adapter's memory size. It's a bit of a hack, we just read * an ULONG from the data port without setting an index before. */ AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA); /* Write hw information to registry, so that it's visible in windows property dialog */ rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType", VBoxChipType, sizeof(VBoxChipType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType", VBoxDACType, sizeof(VBoxDACType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize", &AdapterMemorySize, sizeof(ULONG)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString", VBoxAdapterString, sizeof(VBoxAdapterString)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString", VBoxBiosString, sizeof(VBoxBiosString)); VBOXMP_WARN_VPS(rc); /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up */ { VIDEO_ACCESS_RANGE tmpRanges[4]; ULONG slot = 0; VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges)); if (VBoxQueryWinVersion() == WINNT4) { /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL, * and needs PCI ids for a successful VideoPortGetAccessRanges call. */ ULONG vendorId = 0x80EE; ULONG deviceId = 0xBEEF; rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, &vendorId, &deviceId, &slot); } else { rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot); } VBOXMP_WARN_VPS(rc); } /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */ rc = VbglInit(); VBOXMP_WARN_VPS(rc); /* Preinitialize the primary extension. */ pExt->pNext = NULL; pExt->pPrimary = pExt; pExt->iDevice = 0; pExt->ulFrameBufferOffset = 0; pExt->ulFrameBufferSize = 0; pExt->u.primary.ulVbvaEnabled = 0; VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA)); /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old * code will be ifdef'ed and later removed. * The host will however support both old and new interface to keep compatibility * with old guest additions. */ VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, AdapterMemorySize, 0); if (pExt->u.primary.commonInfo.bHGSMI) { LOGREL(("using HGSMI")); VBoxCreateDisplays(pExt, ConfigInfo); } /** @todo pretend success to make the driver work. */ rc = NO_ERROR; LOGF_LEAVE(); VBOXMP_WARN_VPS(rc); return rc; }
static BOOLEAN ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, ULONG *Data_to_smbus) { int nRetriesToLive=50; while (0 != (VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800)) { ; /* Franz's spin while bus busy with any master traffic */ } while (0 != nRetriesToLive--) { UCHAR b; int temp; VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1); VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 8), bRegister); temp = VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 0)); VideoPortWritePortUshort((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */ switch (Size) { case 4: VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0d); /* DWORD modus ? */ break; case 2: VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0b); /* WORD modus */ break; default: VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0a); // BYTE break; } b = 0; while (0 == (b & 0x36)) { b = VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 0)); } if (0 != (b & 0x24)) { /* printf("I2CTransmitByteGetReturn error %x\n", b); */ } if(0 == (b & 0x10)) { /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */ } else { switch (Size) { case 4: VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 6)); VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); break; case 2: *Data_to_smbus = VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 6)); break; default: *Data_to_smbus = VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 6)); break; } return TRUE; } } return FALSE; }