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; }
ACPI_STATUS AcpiOsReadPort ( ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width) { DPRINT("AcpiOsReadPort %p, width %d\n",Address,Width); switch (Width) { case 8: *Value = READ_PORT_UCHAR((PUCHAR)Address); break; case 16: *Value = READ_PORT_USHORT((PUSHORT)Address); break; case 32: *Value = READ_PORT_ULONG((PULONG)Address); break; default: DPRINT1("AcpiOsReadPort got bad width: %d\n",Width); return (AE_BAD_PARAMETER); break; } return (AE_OK); }
ULONG ScsiPortReadPortUlong( IN PULONG Port ) /*++ Routine Description: Read from the specified port address. Arguments: Port - Supplies a pointer to the port address. Return Value: Returns the value read from the specified port address. --*/ { return(READ_PORT_ULONG(Port)); }
UINT32 io_read(struct fscc_card *card, unsigned bar, PULONG Address) { if (card->bar[bar].memory_mapped) return READ_REGISTER_ULONG(Address); else return READ_PORT_ULONG(Address); }
ULONG NTAPI ScsiPortReadPortUlong( IN PULONG Port) { return READ_PORT_ULONG(Port); }
ULONG NTAPI VideoPortReadPortUlong( PULONG Port) { return READ_PORT_ULONG(Port); }
/* * @implemented */ VOID EXPORT NdisImmediateReadPortUlong( IN NDIS_HANDLE WrapperConfigurationContext, IN ULONG Port, OUT PULONG Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); *Data = READ_PORT_ULONG(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? }
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; }
//-------------------------------------------------------------------------- // // Codec_SetPowerState // Description: // The AC97 Codec has 4 power states (that are meaningful to us): // 0x0000 - normal operation // 0x1700 - fully powered down // AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR4 // 0x1300 - powered down with analog mixer active // AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4 // 0x0800 - turn off analog mixer section // AC97_PWR_PR3 // // This procedure will transition the Codec from its current // state to the specified one. // // Input: // ulNewState - the new AC97 power state // //-------------------------------------------------------------------------- ULONG CES1371::Codec_SetPowerState( ULONG ulNewState ) { USHORT usAC97_PowerReg; ULONG delay_count; // if the AC97 is asleep wake it up. since we only leave it asleep // or fully awake if it isn't awake it must be asleep if ( m_ulCodecPowerState ) { UCHAR ucMiscCtl; // wake up the AC97 using the warm reset method // from 5.2.1.2 AC97 spec a warm reset is signaled by // driving SYNC high for a minimum of one microsecond // in the absence of bit clock. Do this using the // SYNC_RES bit in byte 1 of the es1371 chip. if ( AC97_PWR_PR4 & m_ulCodecPowerState ) { ucMiscCtl = READ_PORT_UCHAR((PUCHAR)(m_pPciAddr + ES1371_bMISCCTL_OFF)); WRITE_PORT_UCHAR((PUCHAR)(m_pPciAddr + ES1371_bMISCCTL_OFF), ucMiscCtl | ES1371_MISCCTL_SYNC_RES ); // now wait around long enough to be sure 1.3 microseconds have gone by //<mod:ce> KeStallExecutionProcessor( 2 ); StallExecution(1000); // some older codecs require longer stall times WRITE_PORT_UCHAR((PUCHAR)(m_pPciAddr + ES1371_bMISCCTL_OFF), ucMiscCtl & ~ES1371_MISCCTL_SYNC_RES ); // now wait around long enough to be sure a microsecond has gone by //<mod:ce> KeStallExecutionProcessor( 1 ); StallExecution(1000); // some older codecs require longer stall times } // now the ACLink should be active. take the Codec through the steps // to bring it back up to fully awake. // read the power register to see what the current state is usAC97_PowerReg = ReadCodecRegister( AC97_POWER_CONTROL ); #ifdef DBG _DbgPrintF( DEBUGLVL_VERBOSE, ("AC97 power state 1: %x", usAC97_PowerReg)); #endif // is the analog section awake if ( !(AC97_PWR_ANL & usAC97_PowerReg ) ) WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg & ~(AC97_PWR_PR2|AC97_PWR_PR3) ); Codec_WaitForPowerState( AC97_PWR_ANL ); // read the power register to see what the current state is usAC97_PowerReg = ReadCodecRegister( AC97_POWER_CONTROL ); #ifdef DBG _DbgPrintF( DEBUGLVL_VERBOSE, ("AC97 power state 2: %x", usAC97_PowerReg)); #endif // is the DAC section awake if ( !(AC97_PWR_DAC & usAC97_PowerReg ) ) WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg & ~AC97_PWR_PR1 ); Codec_WaitForPowerState( AC97_PWR_DAC ); // read the power register to see what the current state is usAC97_PowerReg = ReadCodecRegister( AC97_POWER_CONTROL ); #ifdef DBG _DbgPrintF( DEBUGLVL_VERBOSE, ("AC97 power state 3: %x", usAC97_PowerReg)); #endif // is the ADC section awake if ( !(AC97_PWR_ADC & usAC97_PowerReg ) ) WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg & ~AC97_PWR_PR0 ); Codec_WaitForPowerState( AC97_PWR_ADC ); // read the power register to see what the current state is usAC97_PowerReg = ReadCodecRegister( AC97_POWER_CONTROL ); #ifdef DBG _DbgPrintF( DEBUGLVL_VERBOSE, ("AC97 power state 3: %x", usAC97_PowerReg)); #endif } // now the AC97 Codec if fully awake. if it should be in a power down // mode do that now. if ( ulNewState ) { // start the process of shutting down the Codec usAC97_PowerReg = 0; // shut down the ADC section if ( AC97_PWR_PR0 & ulNewState ) { usAC97_PowerReg |= AC97_PWR_PR0; WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg ); } // shut down the DAC section if ( AC97_PWR_PR1 & ulNewState ) { usAC97_PowerReg |= AC97_PWR_PR1; WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg ); } // if it is called for shut off the analog section if ( AC97_PWR_PR2 & ulNewState ) { usAC97_PowerReg |= AC97_PWR_PR2; WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg ); } // if it is called for shut off the analog section if ( AC97_PWR_PR3 & ulNewState ) { usAC97_PowerReg |= AC97_PWR_PR3; WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg ); } if ( AC97_PWR_PR4 & ulNewState ) { // shut down the digital interface section usAC97_PowerReg |= AC97_PWR_PR4; WriteCodecRegister( AC97_POWER_CONTROL, usAC97_PowerReg ); } // poll the WIP bit of the Codec control register to make sure // it is clear before we power anything else down. for( delay_count = 0; delay_count < 0x1000UL; ++delay_count ) if( !(READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dCODECCTL_OFF)) & (1UL << 30)) ) break; // the AC97 Codec is now powered down } // save the new AC97 Codec power state m_ulCodecPowerState = ulNewState; return ulNewState; }
BOOLEAN IOReadCommand( IN PCHAR Argv[], IN PFW_EXCEPTION_FRAME Frame ) /*++ Routine Description: This implements the IORead command given the arguments in the argc,Argv form. This reads 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; UCHAR Message[32]; if (Argc!=2) { 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 ((Start & 0xf0000000) == 0xa0000000) && (DataSize != BYTE) ) ) { FwPrint(MON_UNALIGNED_ADDRESS_MSG); return FALSE; } // // Do the I/O space read. // switch (DataSize) { // Byte case BYTE: sprintf(Message,"0x%08lx: 0x%02x\r\n", Start, READ_PORT_UCHAR((PUCHAR)Start)); FwPrint(Message); break; // Word case HALF: sprintf(Message,"0x%08lx: 0x%04x\r\n", Start, READ_PORT_USHORT((PUSHORT)Start)); FwPrint(Message); break; // Longword case MON_LONGWORD: sprintf(Message,"0x%08lx: 0x%08x\r\n", Start, READ_PORT_ULONG((PULONG)Start)); FwPrint(Message); break; // bad data size default: FwPrint(MON_BAD_IO_OPERATION_MSG); return FALSE; } // // Set new default addresses // DefaultAddress = Start+DataSize; return TRUE; }
VOID KdpReadIoSpaceExtended ( 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; 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; // // Zero the return data value. // a->DataValue = 0; // // Translate the bus address to the physical system address // or QVA. // if( !HalTranslateBusAddress( InterfaceType, BusNumber, IoAddress, &AddressSpace, &TranslatedAddress ) ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendReadIoSpaceExtendedResponse; } // // 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 SendReadIoSpaceExtendedResponse; } // // 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: a->DataValue = READ_REGISTER_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 2: a->DataValue = READ_REGISTER_USHORT((PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 4: a->DataValue = READ_REGISTER_ULONG((PULONG)(ULONG_PTR) TranslatedAddress.QuadPart ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } else { // // I/O space on the bus // switch( DataSize ){ case 1: a->DataValue = READ_PORT_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 2: a->DataValue = READ_PORT_USHORT( (PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 4: a->DataValue = READ_PORT_ULONG( (PULONG)(ULONG_PTR) TranslatedAddress.QuadPart ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } SendReadIoSpaceExtendedResponse: KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }
u32 ReadVirtIODeviceRegister(ULONG_PTR ulRegister) { return READ_PORT_ULONG((PULONG)(ulRegister)); }
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; }
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; }
/////////////////////////////////////////////////////////////////////////////// // // 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); }
/////////////////////////////////////////////////////////////////////////////// // // 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); }
STDMETHODIMP_(UInt32) CCMIAdapter::readUInt32(UInt8 reg) { return READ_PORT_ULONG((PULONG)(reinterpret_cast<PUCHAR>(cm.IOBase) + reg)); }
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; }
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; }
ULONG EISAReadPortULONG ( IN ULONG BusNumber, IN ULONG Offset ) /*++ Routine Description: This reads EISA I/O space using a longword read. On Alpha, this is identical to reading EISA memory space. On Alpha/Jensen we check for a read to 0C80--0C83, and manually return the EISA System Board ID bytes. 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. Return Value: This returns the longword read. On an error, 0 is returned. --*/ { // // Check for illegal values for Jensen. // if ((BusNumber != 0) || ((Offset & 0x3) != 0)) { return (0); } // // Trap reads to System Board ID bytes and return Jensen ID bytes. // which correspond to the EISA identifier "DEC2400". // if ((Offset & 0xffff) == 0x0c80) { return 0x0024a310; } // // Call HAL library function with QVA bit or'd in. // return (READ_PORT_ULONG((PULONG)Offset)); }