static VOID DumpPortWrite( IN ULONG64 Offset, IN PVOID Buffer, IN ULONG Length ) { PHYSICAL_ADDRESS Address; ASSERT(Offset == (ULONG64)-1); ASSERT(IS_PAGE_ALIGNED(Buffer)); ASSERT(IS_PAGE_ALIGNED(Length)); // // Sometimes Windows passes us virtual addresses, sometimes it passes // physical addresses. It doesn't tell us which it's handing us, and // how this plays with PAE is anybody's guess. // Address = MmGetPhysicalAddress(Buffer); if (Address.QuadPart == 0) Address.QuadPart = (ULONG_PTR)Buffer; Address.QuadPart >>= PAGE_SHIFT; ASSERT3U(Address.HighPart, ==, 0); for (Length >>= PAGE_SHIFT; Length != 0; Length--) WRITE_PORT_ULONG(PortEC, Address.LowPart++); }
VOID ScsiPortWritePortUlong( IN PULONG Port, IN ULONG Value ) /*++ Routine Description: Write to the specificed port address. Arguments: Port - Supplies a pointer to the port address. Value - Supplies the value to be written. Return Value: None --*/ { WRITE_PORT_ULONG(Port, Value); }
ACPI_STATUS AcpiOsWritePort ( ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width) { DPRINT("AcpiOsWritePort %p, width %d\n",Address,Width); switch (Width) { case 8: WRITE_PORT_UCHAR((PUCHAR)Address, Value); break; case 16: WRITE_PORT_USHORT((PUSHORT)Address, Value); break; case 32: WRITE_PORT_ULONG((PULONG)Address, Value); break; default: DPRINT1("AcpiOsWritePort got bad width: %d\n",Width); return (AE_BAD_PARAMETER); break; } return (AE_OK); }
static FORCEINLINE NTSTATUS __UnplugPreamble( IN PXENFILT_UNPLUG_CONTEXT Context, IN BOOLEAN Locked ) { KIRQL Irql = PASSIVE_LEVEL; USHORT Magic; UCHAR Version; NTSTATUS status; if (!Locked) AcquireHighLock(&Context->Lock, &Irql); // See docs/misc/hvm-emulated-unplug.markdown for details of the // protocol in use here Magic = READ_PORT_USHORT((PUSHORT)0x10); if (Magic == 0xd249) { Context->BlackListed = TRUE; goto done; } status = STATUS_NOT_SUPPORTED; if (Magic != 0x49d2) goto fail1; Version = READ_PORT_UCHAR((PUCHAR)0x12); if (Version != 0) { WRITE_PORT_USHORT((PUSHORT)0x12, 0xFFFF); // FIXME WRITE_PORT_ULONG((PULONG)0x10, (MAJOR_VERSION << 16) | (MINOR_VERSION << 8) | MICRO_VERSION); Magic = READ_PORT_USHORT((PUSHORT)0x10); if (Magic == 0xd249) Context->BlackListed = TRUE; } done: LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: PRE-AMBLE (DRIVERS %s)\n", (Context->BlackListed) ? "BLACKLISTED" : "NOT BLACKLISTED"); if (!Locked) ReleaseHighLock(&Context->Lock, Irql); return STATUS_SUCCESS; fail1: Error("fail1 (%08x)\n", status); if (!Locked) ReleaseHighLock(&Context->Lock, Irql); return status; }
VOID NTAPI VideoPortWritePortUlong( PULONG Port, ULONG Value) { WRITE_PORT_ULONG(Port, Value); }
VOID NTAPI ScsiPortWritePortUlong( IN PULONG Port, IN ULONG Value) { WRITE_PORT_ULONG(Port, Value); }
void io_write(struct fscc_card *card, unsigned bar, PULONG Address, ULONG Value) { if (card->bar[bar].memory_mapped) WRITE_REGISTER_ULONG(Address, Value); else WRITE_PORT_ULONG(Address, Value); }
VOID XboxMemInit(VOID) { UCHAR ControlRegion[TEST_SIZE]; PVOID MembaseTop = (PVOID)(64 * 1024 * 1024); PVOID MembaseLow = (PVOID)0; (*(PULONG)(0xfd000000 + 0x100200)) = 0x03070103 ; (*(PULONG)(0xfd000000 + 0x100204)) = 0x11448000 ; WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); WRITE_PORT_ULONG((ULONG*) 0xcfc, 0x7ffffff); /* Prep hardware for 128 Mb */ InstalledMemoryMb = 64; memset(ControlRegion, TEST_PATTERN1, TEST_SIZE); memset(MembaseTop, TEST_PATTERN1, TEST_SIZE); __wbinvd(); if (0 == memcmp(MembaseTop, ControlRegion, TEST_SIZE)) { /* Looks like there is memory .. maybe a 128MB box */ memset(ControlRegion, TEST_PATTERN2, TEST_SIZE); memset(MembaseTop, TEST_PATTERN2, TEST_SIZE); __wbinvd(); if (0 == memcmp(MembaseTop, ControlRegion, TEST_SIZE)) { /* Definitely looks like there is memory */ if (0 == memcmp(MembaseLow, ControlRegion, TEST_SIZE)) { /* Hell, we find the Test-string at 0x0 too ! */ InstalledMemoryMb = 64; } else { InstalledMemoryMb = 128; } } } /* Set hardware for amount of memory detected */ WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); WRITE_PORT_ULONG((ULONG*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1); AvailableMemoryMb = InstalledMemoryMb; }
/* * @implemented */ VOID EXPORT NdisImmediateWritePortUlong( IN NDIS_HANDLE WrapperConfigurationContext, IN ULONG Port, IN ULONG Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); WRITE_PORT_ULONG(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? }
XEN_API NTSTATUS XencrshEntryPoint( IN PDRIVER_OBJECT _DriverObject ) { NTSTATUS Status; HW_INITIALIZATION_DATA InitData; LogTrace("===> (Irql=%d)\n", KeGetCurrentIrql()); LogVerbose("%s (%s)\n", MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, DAY_STR "/" MONTH_STR "/" YEAR_STR); LogVerbose("Loading PV Disk in %s mode\n", __OperatingModeName()); if (DriverGetOperatingMode() == DUMP_MODE) { WRITE_PORT_ULONG(CRASH_PORT, 'PLEH'); } AustereInitialize(); BufferInitialize(); RtlZeroMemory(&InitData, sizeof(InitData)); InitData.HwInitializationDataSize = sizeof(InitData); InitData.AdapterInterfaceType = Internal; InitData.HwInitialize = HwInitialize; InitData.HwStartIo = HwStartIo; InitData.HwInterrupt = HwInterrupt; #pragma warning(suppress : 4152) InitData.HwFindAdapter = HwFindAdapter; InitData.HwResetBus = HwResetBus; InitData.HwDmaStarted = NULL; InitData.HwAdapterState = NULL; InitData.DeviceExtensionSize = FdoSizeofXenvbdFdo(); InitData.SpecificLuExtensionSize = 0; InitData.SrbExtensionSize = sizeof(XENVBD_SRBEXT); InitData.NumberOfAccessRanges = 2; InitData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; InitData.NeedPhysicalAddresses = TRUE; InitData.TaggedQueuing = TRUE; InitData.AutoRequestSense = TRUE; InitData.MultipleRequestPerLu = TRUE; InitData.HwAdapterControl = HwAdapterControl; InitData.HwBuildIo = HwBuildIo; #pragma prefast(suppress: 6387, "Crash Driver has no registry path") Status = StorPortInitialize(_DriverObject, NULL, &InitData, NULL); LogVerbose("(%08x)\n", Status); LogTrace("<=== (%08x) (Irql=%d)\n", Status, KeGetCurrentIrql()); return Status; }
void CES1371::WriteCodecRegister(UCHAR Reg, USHORT Val) { ULONG i; // ULONG dtemp, dinit; // Don't write if the value is the same as // what is in the register but always let writes // to the reset register go through. if ( (m_usCRegs[Reg/2] == Val) && (AC97_RESET != Reg) ) return; #ifdef DBG _DbgPrintF( DEBUGLVL_VERBOSE, ("[CodecWrite] Reg %x Val %x", Reg, Val)); #endif /* wait for WIP to go away */ for( i = 0; i < 0x1000UL; ++i ) if( !(READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF)) & (1UL << 30)) ) break; // /* save the current state for later */ // dinit = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF)); // // /* enable SRC state data in SRC mux */ // for( i = 0; i < 0x1000UL; ++i ) // if( !((dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF))) & SRC_BUSY) ) // break; // WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), (dtemp & SRC_CTLMASK) | 0x00010000UL); // // /* wait for a SAFE time to write addr/data and then do it */ //// _disable(); // for( i = 0; i < 0x1000UL; ++i ) // if( (READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF)) & 0x00870000UL) == // 0x00010000UL ) // break; WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF), ((ULONG) Reg << 16) | Val); //// _enable(); // // /* restore SRC reg */ // for( i = 0; i < 0x1000UL; ++i ) // if( !(READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF)) & SRC_BUSY) ) // break; // WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), dinit & SRC_CTLMASK ); /* store the written value in our local storage */ m_usCRegs[Reg/2] = Val; return; }
void ReadPci32Reg(uint bus, uint device, uint func, uint reg, uint& data) { uint32 address = HelpEncodeExtendedConfigSpaceAddress(bus, device, func, reg); // Set new address WRITE_PORT_ULONG(PciAddr, static_cast<ULONG>(address)); // Read current data ULONG currentData = READ_PORT_ULONG(PciData); data = static_cast<uint>(currentData); }
// HelpAccessPciAddress: Read/Write PCI address space bool HelpAccessPciAddress(PACCESS_PCI pData) { bool ret = true; if (NULL == pData) { ret = false; } if (true == ret) { // Enable Access to the PCI Extended Configuration Space // It is not done by default for Pci write // TODO: need to check if we are really usingEnableExtendedPCIConfigSpace(); if (pData->isReadAccess) { // Set new address WRITE_PORT_ULONG(PciAddr, static_cast<ULONG>(pData->address)); // Read current data ULONG currentData = READ_PORT_ULONG(PciData); pData->data = static_cast<uint>(currentData); } else { // Get the address to write to // Set new address WRITE_PORT_ULONG(PciAddr, static_cast<ULONG>(pData->address)); // Write data WRITE_PORT_ULONG(PciData, static_cast<ULONG>(pData->data)); } ret = true; } return ret; }
USHORT CES1371::ReadCodecRegister( UCHAR Reg ) { ULONG i, dtemp; // ULONG dinit; /* wait for WIP to go away saving the current state for later */ for( i = 0; i < 0x1000UL; ++i ) if( !(READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF)) & (1UL << 30)) ) break; /* write addr w/data=0 and assert read request ... */ // /* save the current state for later */ // dinit = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF)); // // /* enable SRC state data in SRC mux */ // for( i = 0; i < 0x1000UL; ++i ) // if( !((dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF))) & SRC_BUSY) ) // break; // WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), (dtemp & SRC_CTLMASK) | 0x00010000UL); // // /* wait for a SAFE time to write a read request and then do it */ //// _disable(); // for( i = 0; i < 0x1000UL; ++i ) // if( (READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF)) & 0x00870000UL) == // 0x00010000UL ) // break; // WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF), ((ULONG) Reg << 16) | (1UL << 23)); // _enable(); // /* restore SRC reg */ // for( i = 0; i < 0x1000UL; ++i ) // if( !(READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF)) & SRC_BUSY) ) // break; // WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), dinit & SRC_CTLMASK ); // /* now wait for the data (RDY) */ for( i = 0; i < 0x1000UL; ++i ) if( READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF)) & (1UL << 31) ) break; dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF)); /* store the read value in our local storage */ m_usCRegs[Reg/2] = (USHORT) dtemp; return (USHORT) dtemp; }
VOID EISAWritePortULONG ( IN ULONG BusNumber, IN ULONG Offset, IN ULONG Datum ) /*++ Routine Description: This writes EISA I/O space using a longword write. On Alpha, this is identical to writing EISA memory space. Arguments: BusNumber EISA bus number, starting with 0. Offset Byte offset from the beginning of EISA space for this bus. This must be based off the .IoStart value in the EISA adapter's ConfigurationData, which is held in the Component Data Structure node. Therefore, this will already have the EISA QVA bits set up. Datum The long to be written. Return Value: None. Errors will cause either a no-op or a bugcheck. --*/ { // // Check for illegal values for Jensen. // if ((BusNumber != 0) || ((Offset & 0x3) != 0)) { return; } // // Call HAL library function with QVA bit or'd in. // WRITE_PORT_ULONG((PULONG)Offset, Datum); return; }
VOID NTAPI HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler, IN KIRQL Irql) { PCI_TYPE1_CFG_BITS PciCfg1; /* Clear the PCI Configuration Register */ PciCfg1.u.AsULONG = 0; WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address, PciCfg1.u.AsULONG); /* Release the lock */ KiReleaseSpinLock(&HalpPCIConfigLock); KeLowerIrql(Irql); }
void __stdcall __FAKE_WRITE_PORT_ULONG(PULONG Port, ULONG Value) { ULONG caller; _asm { mov eax,dword ptr [ebp+4] mov dword ptr [caller],eax } if ((caller >= fltCallerEntry) && (caller < (fltCallerEntry + fltCallerSize))) DbgPrint("__FAKE_WRITE_PORT_ULONG: port %#x value %u", (ULONG)Port, (ULONG)Value); splice_uninstall(&b_wplong); WRITE_PORT_ULONG(Port, Value); splice_install(&b_wplong, WRITE_PORT_ULONG, __FAKE_WRITE_PORT_ULONG); }
STDMETHODIMP_(void) CCMIAdapter::writeUInt32(UInt8 cmd, UInt32 value) { WRITE_PORT_ULONG((PULONG)(reinterpret_cast<PUCHAR>(cm.IOBase) + cmd), value); }
BOOLEAN AmccPciEvtInterruptIsr( __in WDFINTERRUPT Interrupt, __in ULONG MessageID ) /*++ Routine Description: This routine assumes that only a single I/O can be completed at a time on the hardware (i.e. at most one I/O completed per interrupt). Arguments: Interupt - Address of the framework interrupt object MessageID - Return Value: TRUE - Interrupt belongs to this device. --*/ { PAMCC_DEVICE_EXTENSION devExt = NULL; WDFDEVICE hDevice; union { ULONG ulong; INTCSR_REG bits; } intcsr; union { ULONG ulong; MCSR_REG bits; } mcsr; UNREFERENCED_PARAMETER( MessageID ); hDevice = WdfInterruptGetDevice(Interrupt); devExt = AmccPciGetDevExt(hDevice); // // Read interrupt control/status register and see if an interrupt is pending. // If not, return FALSE immediately. // intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR); if (!intcsr.bits.InterruptAsserted) { return FALSE; } // // Disable bus-mastering // mcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->MCSR); mcsr.bits.WriteTransferEnable = FALSE; mcsr.bits.ReadTransferEnable = FALSE; WRITE_PORT_ULONG((PULONG) &devExt->Regs->MCSR, mcsr.ulong ); // // This will take effect when INTCSR is rewritten later. // intcsr.bits.IntOnWriteTransferComplete = FALSE; intcsr.bits.IntOnReadTransferComplete = FALSE; // // Process pending interrupts. We're expecting an interrupt due // to a transfer count going to zero, but we might be getting a // master or target abort instead. // while (intcsr.bits.InterruptAsserted) { // // Merge new interrupts with old // _InterlockedOr((PLONG) &devExt->Intcsr, (LONG) intcsr.ulong ); // // Interrupt flags on the S5933 are cleared by writing a "1" bit // to them, so clear all the interrupts just examined. // WRITE_PORT_ULONG((PULONG) &devExt->Regs->INTCSR, intcsr.ulong); // // Check for additional interrupts // intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR); } // // Check if there is a current Request. If not, then this interrupt cannot // do anything. This driver design requires an I/O to be pending in order // to queue the DPC. If there is no I/O current, then there is no need // to have a DPC queued. This driver also assumes one I/O per interrupt. // // IMPORTANT: Before returning TRUE, the interrupt must have been cleared // on the device or the system will hang trying to service this level // sensitive interrupt. // if (!devExt->CurrentRequest) { TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO, "Hardware generated interrupt with no request pending"); return TRUE; } // // Request the DPC to complete the transfer. // WdfInterruptQueueDpcForIsr( Interrupt ); // // Indicate that this adapter was interrupting. // return TRUE; }
BOOLEAN AmccPciProgramDma( __in WDFDMATRANSACTION Transaction, __in WDFDEVICE Device, __in PVOID Context, __in WDF_DMA_DIRECTION Direction, __in PSCATTER_GATHER_LIST SgList ) /*++ Routine Description: Arguments: Return Value: --*/ { AMCC_DEVICE_EXTENSION * devExt; ULONG address; ULONG length; union { ULONG ulong; MCSR_REG bits; } mcsr; union { ULONG ulong; INTCSR_REG bits; } intcsr; UNREFERENCED_PARAMETER( Transaction ); UNREFERENCED_PARAMETER( Context ); // // Reestablish working parameters. // devExt = AmccPciGetDevExt(Device); // // The S5933 used only 32-bit packet mode DMA operations. // ASSERT(SgList->NumberOfElements == 1); ASSERT(SgList->Elements[0].Address.HighPart == 0); // // Only the first Scatter/Gather element is relevant for packet mode. // S5933 only does 32-bit DMA transfer operations: only low part of // physical address is usable. // address = SgList->Elements[0].Address.LowPart; length = SgList->Elements[0].Length; TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO, "Address 0x%08X, Length %d", address, length); // // Read the Master Control/Status Register (MCSR) and // the Interrupt Control/Status Register (INTCSR). // mcsr.ulong = READ_PORT_ULONG((PULONG) &(devExt->Regs->MCSR)); intcsr.ulong = READ_PORT_ULONG((PULONG) &devExt->Regs->INTCSR); // // Setup read or write transfer registers. // // NOTE: The S5933 calls a transfer from memory to the device a "read". // if (Direction == WdfDmaDirectionWriteToDevice) { mcsr.bits.ReadFifoMgmtScheme = TRUE; mcsr.bits.ReadTransferEnable = TRUE; intcsr.bits.IntOnReadTransferComplete = TRUE; WRITE_PORT_ULONG((PULONG) &devExt->Regs->MRTC, length); WRITE_PORT_ULONG((PULONG) &devExt->Regs->MRAR, address); } else { mcsr.bits.WriteFifoMgmtScheme = TRUE; mcsr.bits.WriteTransferEnable = TRUE; intcsr.bits.IntOnWriteTransferComplete = TRUE; WRITE_PORT_ULONG((PULONG) &devExt->Regs->MWTC, length); WRITE_PORT_ULONG((PULONG) &devExt->Regs->MWAR, address); } // // Write modified INTCSR to enable the appropriate interrupt and // the MCSR to actually start the transfer. // WRITE_PORT_ULONG((PULONG) &devExt->Regs->INTCSR, intcsr.ulong); WRITE_PORT_ULONG((PULONG) &devExt->Regs->MCSR, mcsr.ulong); return TRUE; }
BOOLEAN IOWriteCommand( IN PCHAR Argv[], IN PFW_EXCEPTION_FRAME Frame ) /*++ Routine Description: This implements the IOWrite command given the arguments in the argc,Argv form. This writes I/O space. Arguments: Argv - array of zero terminated argument strings. Frame - the saved register & exception state. Return Value: Returns TRUE if the command is valid, FALSE otherwise. --*/ { ULONG Start; ULONG Value; UCHAR Message[32]; PCHAR Terminator; if (Argc!=3) { FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG); return FALSE; } if (GetAddress(Argv[1],Frame,&Start) == FALSE) { return FALSE; } // // Check for proper alignment in I/O space. // if (// combo space check ((Start & 0xf0000000) == 0xa0000000) && (DataSize != BYTE) ) { FwPrint(MON_UNALIGNED_ADDRESS_MSG); return FALSE; } // // Convert deposit value to integer // Value = strtoul(Argv[2],&Terminator,16); if (*Terminator != '\0') { // // Not the whole string was converted. // FwPrint(Terminator); FwPrint(MON_INVALID_VALUE_MSG); return FALSE; } else { // // Do the I/O space write // switch (DataSize) { // Byte case BYTE: WRITE_PORT_UCHAR((PUCHAR)Start, Value); break; // Word case HALF: WRITE_PORT_USHORT((PUSHORT)Start, Value); break; // Longword case MON_LONGWORD: WRITE_PORT_ULONG((PULONG)Start, Value); break; // bad data size default: FwPrint(MON_BAD_IO_OPERATION_MSG); return FALSE; } } // // Set new default addresses // DefaultAddress = Start+DataSize; return TRUE; }
void WriteVirtIODeviceRegister(ULONG_PTR ulRegister, u32 ulValue) { WRITE_PORT_ULONG((PULONG)(ulRegister), (ULONG)(ulValue)); }
/////////////////////////////////////////////////////////////////////////////// // // OsrStartReadOnDevice // // This function performs all the actual hardware manipulation to initiate // a new read request on the AMCC device. When called, all resources // (mapping registers) have been allocated for the operation, and we have // a base address and length of a buffer fragment to be DMA'ed. // // INPUTS: // // DeviceObject - Address of the DEVICE_OBJECT for our device. // // BaseAddress - Logical base address of the requestor's buffer fragment // to be used as the base address of the transfer // // Length - Length in bytes of this fragment to be transfered. // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL_DISPATCH_LEVEL. // // NOTES: // // When this routine is called, no other Read operations are in progress on // the device. // /////////////////////////////////////////////////////////////////////////////// BOOLEAN OsrStartReadOnDevice(IN PVOID SynchronizeContext) { ULONG temp; PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)SynchronizeContext; PHYSICAL_ADDRESS baseAddress; ULONG length; POSR_DEVICE_EXT devExt = deviceObject->DeviceExtension; baseAddress = devExt->ReadPaToDevice; length = devExt->ReadLength; #if DBG DbgPrint("StartReadOnDev: Reading BA = 0x%0x, Length = %d.\n", baseAddress.LowPart, length); #endif // // Pass the device the Physical Base Address of the buffer // ASSERT(!baseAddress.HighPart); WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MWAR_OFF, baseAddress.LowPart); // // ...and the length of the read // WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MWTC_OFF, length); // // Tell the device to interrupt when the read is complete. // // NOTE: In this particular device, "read" operations from the // device are called "WRITE" operations... since they write to // MEMORY. Thus, we set the INT_ON_WRITE bit in the Interrupt // CSR. // temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF); #if DBG DbgPrint("StartDmaRead: Current INTCSR State:\n"); OsrPrintIntcsr(temp); #endif temp &= ~AMCC_INT_ACK_BITS; temp |= AMCC_INT_INT_ON_WRITE; WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF, temp); // // Yeeeeha! Start the request by settting the "Write Enable" // bit in the master CSR // temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF); temp &= (AMCC_MCSR_READ_ENABLE | AMCC_MCSR_READ_FIFO_MGMT | AMCC_MCSR_READ_PRIORITY | AMCC_MCSR_WRITE_ENABLE | AMCC_MCSR_WRITE_FIFO_MGMT | AMCC_MCSR_WRITE_PRIORITY); temp |= AMCC_MCSR_WRITE_ENABLE; WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF, temp); return(TRUE); }
/////////////////////////////////////////////////////////////////////////////// // // OsrStartWriteOnDevice // // This function performs all the actual hardware manipulation to initiate // a new read request on the AMCC device. When called, all resources // (mapping registers) have been allocated for the operation, and we have // a base address and length of a buffer fragment to be DMA'ed. // // INPUTS: // // DeviceObject - Address of the DEVICE_OBJECT for our device. // // BaseAddress - Logical base address of the requestor's buffer fragment // to be used as the base address of the transfer // // Length - Length in bytes of this fragment to be transfered. // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL_DISPATCH_LEVEL. // // NOTES: // // When this routine is called, no other Write operations are in progress on // the device. // /////////////////////////////////////////////////////////////////////////////// BOOLEAN OsrStartWriteOnDevice(IN PVOID SynchronizeContext) { ULONG temp; PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)SynchronizeContext; PHYSICAL_ADDRESS baseAddress; ULONG length; POSR_DEVICE_EXT devExt = deviceObject->DeviceExtension; baseAddress = devExt->WritePaToDevice; length = devExt->WriteLength; #if DBG DbgPrint("StartWriteOnDev: Writing BA = 0x%0x, Length = %d.\n", baseAddress.LowPart, length); #endif // // Pass the device the Physical Base Address of the buffer... // ASSERT(!baseAddress.HighPart); WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MRAR_OFF, baseAddress.LowPart); // // ...and the length of the write operation // WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MRTC_OFF, length); // // Request the device interrupt when the write operation is complete // temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF); #if DBG DbgPrint("StartWriteOnDev: Current INTCSR State:\n"); OsrPrintIntcsr(temp); #endif temp &= ~AMCC_INT_ACK_BITS; temp |= AMCC_INT_INT_ON_READ; WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF, temp); // // Yeeeeha! Start the request by setting the appropriate enable bit. // temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF); temp &= (AMCC_MCSR_READ_ENABLE| AMCC_MCSR_READ_FIFO_MGMT| AMCC_MCSR_READ_PRIORITY| AMCC_MCSR_WRITE_ENABLE| AMCC_MCSR_WRITE_FIFO_MGMT| AMCC_MCSR_WRITE_PRIORITY); temp |= AMCC_MCSR_READ_ENABLE; WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF, temp); return(TRUE); }
NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { NTSTATUS status = STATUS_SUCCESS; KdPrint(("Enter HelloDDKDeviceIOControl\n")); //得到当前堆栈 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); //得到输入缓冲区大小 ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength; //得到输出缓冲区大小 ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength; //得到IOCTL码 ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; ULONG info = 0; switch (code) { // process request case READ_PORT: { KdPrint(("READ_PORT\n")); //缓冲区方式IOCTL //显示输入缓冲区数据 PULONG InputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; ULONG port = (ULONG)(*InputBuffer); InputBuffer++; UCHAR method = (UCHAR)(*InputBuffer); KdPrint(("port:%x\n",port)); KdPrint(("method:%x\n",method)); //操作输出缓冲区 PULONG OutputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; if (method==1)//8位操作 { *OutputBuffer = READ_PORT_UCHAR((PUCHAR)port); }else if(method==2)//16位操作 { *OutputBuffer = READ_PORT_USHORT((PUSHORT)port); }else if(method==4)//32位操作 { *OutputBuffer = READ_PORT_ULONG((PULONG)port); } //设置实际操作输出缓冲区长度 info = 4; break; } case WRITE_PORT: { KdPrint(("WRITE_PORT\n")); //缓冲区方式IOCTL //显示输入缓冲区数据 PULONG InputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; ULONG port = (ULONG)(*InputBuffer); InputBuffer++; UCHAR method = (UCHAR)(*InputBuffer); InputBuffer++; ULONG value = (ULONG)(*InputBuffer); KdPrint(("port:%x\n",port)); KdPrint(("method:%x\n",method)); KdPrint(("value:%x\n",value)); //操作输出缓冲区 PULONG OutputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; if (method==1)//8位操作 { WRITE_PORT_UCHAR((PUCHAR)port,(UCHAR)value); }else if(method==2)//16位操作 { WRITE_PORT_USHORT((PUSHORT)port,(USHORT)value); }else if(method==4)//32位操作 { WRITE_PORT_ULONG((PULONG)port,(ULONG)value); } //设置实际操作输出缓冲区长度 info = 0; break; } default: status = STATUS_INVALID_VARIANT; } // 完成IRP pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = info; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKDeviceIOControl\n")); return status; }
NTSTATUS hwinterfaceDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp) { PIO_STACK_LOCATION stkloc; NTSTATUS ntStatus = STATUS_SUCCESS; struct tagPhys32Struct Phys32Struct; PUCHAR cData; PUSHORT sData; PULONG lData; PUSHORT address; ULONG inBuffersize; ULONG outBuffersize; ULONG inBuf; PVOID CtrlBuff; stkloc = IoGetCurrentIrpStackLocation( pIrp ); inBuffersize = stkloc->Parameters.DeviceIoControl.InputBufferLength; outBuffersize = stkloc->Parameters.DeviceIoControl.OutputBufferLength; CtrlBuff = pIrp->AssociatedIrp.SystemBuffer; cData = (PUCHAR) CtrlBuff; sData = (PUSHORT) CtrlBuff; lData = (PULONG) CtrlBuff; address = (PUSHORT) CtrlBuff; switch ( stkloc->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_READ_PORT_UCHAR: if ((inBuffersize >= 2) && (outBuffersize >= 1)) { UCHAR value; value = READ_PORT_UCHAR((PUCHAR)address[0]); cData[0] = value; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } pIrp->IoStatus.Information = sizeof(UCHAR); ntStatus = STATUS_SUCCESS; break; case IOCTL_WRITE_PORT_UCHAR: if (inBuffersize >= 3) { WRITE_PORT_UCHAR((PUCHAR)address[0], cData[2]); //Byte 0,1=Address Byte 2=Value pIrp->IoStatus.Information = 10; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Information = 0; ntStatus = STATUS_SUCCESS; } break; case IOCTL_READ_PORT_USHORT: if ((inBuffersize >= 2) && (outBuffersize >= 2)) { USHORT value; value = READ_PORT_USHORT((PUSHORT)address[0]); sData[0] = value; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } pIrp->IoStatus.Information = sizeof(USHORT); ntStatus = STATUS_SUCCESS; break; case IOCTL_WRITE_PORT_USHORT: if (inBuffersize >= 4) { WRITE_PORT_USHORT((PUSHORT)address[0], sData[1]); //Short 0=Address Short 1=Value pIrp->IoStatus.Information = 10; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Information = 0; ntStatus = STATUS_SUCCESS; } break; case IOCTL_READ_PORT_ULONG: if ((inBuffersize >= 4) && (outBuffersize >= 4)) { ULONG value; value = READ_PORT_ULONG((PULONG)address[0]); lData[0] = value; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } pIrp->IoStatus.Information = sizeof(ULONG); ntStatus = STATUS_SUCCESS; break; case IOCTL_WRITE_PORT_ULONG: if (inBuffersize >= 8) { WRITE_PORT_ULONG(&(lData[0]), lData[1]); //Short 0=Address long 1=Value pIrp->IoStatus.Information = 10; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Information = 0; ntStatus = STATUS_SUCCESS; } break; case IOCTL_WINIO_MAPPHYSTOLIN: if (inBuffersize) { memcpy (&Phys32Struct, CtrlBuff, inBuffersize); ntStatus = MapPhysicalMemoryToLinearSpace(Phys32Struct.pvPhysAddress, Phys32Struct.dwPhysMemSizeInBytes, &Phys32Struct.pvPhysMemLin, &Phys32Struct.PhysicalMemoryHandle); if (NT_SUCCESS(ntStatus)) { memcpy (CtrlBuff, &Phys32Struct, inBuffersize); pIrp->IoStatus.Information = inBuffersize; } pIrp->IoStatus.Status = ntStatus; } else pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; case IOCTL_WINIO_UNMAPPHYSADDR: if (inBuffersize) { memcpy (&Phys32Struct, CtrlBuff, inBuffersize); ntStatus = UnmapPhysicalMemory(Phys32Struct.PhysicalMemoryHandle, Phys32Struct.pvPhysMemLin); pIrp->IoStatus.Status = ntStatus; } else pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; default: ntStatus = STATUS_UNSUCCESSFUL; pIrp->IoStatus.Information = 0; break; } pIrp->IoStatus.Status = ntStatus; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return ntStatus; }
VOID KdpWriteIoSpaceExtended ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ) /*++ Routine Description: This function is called in response of a read io space extended state manipulation message. Its function is to read system io locations. Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context. Return Value: None. --*/ { PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m->u.ReadWriteIoExtended; ULONG Length; STRING MessageHeader; PUCHAR b; PUSHORT s; PULONG l; ULONG BusNumber; ULONG AddressSpace; ULONG SavedAddressSpace; PHYSICAL_ADDRESS IoAddress; ULONG DataSize; PHYSICAL_ADDRESS TranslatedAddress; INTERFACE_TYPE InterfaceType; ULONG Value; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; ASSERT(AdditionalData->Length == 0); m->ReturnStatus = STATUS_SUCCESS; InterfaceType = a->InterfaceType; BusNumber = a->BusNumber; AddressSpace = SavedAddressSpace = a->AddressSpace; IoAddress.QuadPart = (ULONG_PTR)a->IoAddress; DataSize = a->DataSize; Value = a->DataValue; // // Translate the bus address to the physical system address // or QVA. // if( !HalTranslateBusAddress( InterfaceType, BusNumber, IoAddress, &AddressSpace, &TranslatedAddress ) ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendWriteIoSpaceExtendedResponse; } // // N.B. - for the moment we will only support QVAs ie. when AddressSpace // is one. It may be in later systems that we will have to // check the address space, map it, perform the virtual read // unmap, and then return the data - only we will have to be // careful about what Irql we are to make sure the memory mgmt // stuff will all work // if( !AddressSpace ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendWriteIoSpaceExtendedResponse; } // // Do the IO space read using the appropriate HAL routines based upon // the original address space and the data size requested. // if( !SavedAddressSpace ){ // // Memory (buffer) space on the bus // switch( DataSize ){ case 1: WRITE_REGISTER_UCHAR( (PUCHAR)TranslatedAddress.QuadPart, (UCHAR)Value ); break; case 2: WRITE_REGISTER_USHORT( (PUSHORT)TranslatedAddress.QuadPart, (USHORT)Value ); break; case 4: WRITE_REGISTER_ULONG( (PULONG)TranslatedAddress.QuadPart, Value ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } else { // // I/O space on the bus // switch( DataSize ){ case 1: WRITE_PORT_UCHAR( (PUCHAR)TranslatedAddress.QuadPart, (UCHAR)Value ); break; case 2: WRITE_PORT_USHORT( (PUSHORT)TranslatedAddress.QuadPart, (USHORT)Value); break; case 4: WRITE_PORT_ULONG( (PULONG)TranslatedAddress.QuadPart, Value ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } SendWriteIoSpaceExtendedResponse: KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }