public PCIE_Device(DWORD dwVendorId, DWORD dwDeviceId, WD_PCI_SLOT slot) { m_wdcDevice = new WDC_DEVICE(); m_wdcDevice.id.pciId.dwVendorId = dwVendorId; m_wdcDevice.id.pciId.dwDeviceId = dwDeviceId; m_wdcDevice.slot.pciSlot = slot; m_wdcDeviceMarshaler = new MarshalWdcDevice(); m_eventHandler = new EVENT_HANDLER_DOTNET(NEWAMD86_EventHandler); m_regs = new PCIE_Regs(); SetDescription(); m_dmaMarshaler = new MarshalWdDma(); }
public void ReadDMA(uint uLocalAddr, uint dwBytes, ref IntPtr data) { //开DMA Buffer IntPtr pDMA = IntPtr.Zero; wdc_lib_decl.WDC_DMAContigBufLock(this.Handle, ref data, (uint)WD_DMA_OPTIONS.DMA_FROM_DEVICE, dwBytes, ref pDMA); MarshalWdDma m_wdDmaMarshaler = new MarshalWdDma(); WD_DMA dma = (WD_DMA)m_wdDmaMarshaler.MarshalNativeToManaged(pDMA); //配置buffer的物理地址到DSP的outbound wdc_lib_decl.WDC_WriteAddr32(this.Handle, 0, 0x30, 0x0); // 1MB outbound translation size uint pageBase = (uint)(dma.Page[0].pPhysicalAddr & 0x100000); wdc_lib_decl.WDC_WriteAddr32(this.Handle, 0, 0x200, pageBase | 0x1); wdc_lib_decl.WDC_WriteAddr32(this.Handle, 0, 0x204, 0x0); //将EDMA配置空间(0x02700000)映射到DSP的IB_OFFSET(3),以便于PC控制DSP的EDMA wdc_lib_decl.WDC_WriteAddr32(this.Handle, 0, 0x33C, 0x02700000); /* EDMA registers */ //#define EDMA_TPCC0_BASE_ADDRESS 0x02700000 //#define DMAQNUM0 0x0240 //#define ESR 0x1010 //#define EESR 0x1030 //#define IESR 0x1060 //#define IPR 0x1068 //#define ICR 0x1070 //#define PARAM_0_OPT 0x4000 //#define PARAM_0_SRC 0x4004 //#define PARAM_0_A_B_CNT 0x4008 //#define PARAM_0_DST 0x400C //#define PARAM_0_SRC_DST_BIDX 0x4010 //#define PARAM_0_LINK_BCNTRLD 0x4014 //#define PARAM_0_SRC_DST_CIDX 0x4018 //#define PARAM_0_CCNT 0x401C //#define PCIE_DATA 0x60000000 //#define DMA_TRANSFER_SIZE 0x400000 /* 4MB */ /* Payload size in bytes over PCIE link. PCIe module supports * outbound payload size of 128 bytes and inbound payload size of 256 bytes */ //#define PCIE_TRANSFER_SIZE 0x80 ///* For 1MB outbound translation window size */ //#define PCIE_ADLEN_1MB 0x00100000 //#define PCIE_1MB_BITMASK 0xFFF00000 //启动DMA传输 while (true) { /* Use TC0 for DBS = 128 bytes */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x0240, 0x0); //* Set the interrupt enable for 1st Channel (IER). */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x1060, 0x1); //* Clear any pending interrupt (IPR). */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x1070, 0x1); //* Populate the Param entry. */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x4000, 0x00100004); /* Enable SYNCDIM and TCINTEN, TCC = 0 */ //* Calculate the DSP PCI address for the PC address */ uint tmp = (uint)(0x60000000 + (dma.Page[0].pPhysicalAddr & ~0xFFF00000)); wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x400C, tmp);//dst address目标地址 //PARAM_0_A_B_CNT wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x4008, 0x10000 | dwBytes); //PARAM_0_SRC wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x4004, (DWORD)uLocalAddr);//src address 源地址 wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x4010, ((0x80 << 16) | 0x80)); wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x4014, 0xFFFF); wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x4018, 0x0); //* C Count is set to 1 since mostly size will not be more than 1.75GB */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x401C, 0x1); //* Set the Event Enable Set Register. */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x1030, 0x1); //* Set the event set register. */ wdc_lib_decl.WDC_WriteAddr32(this.Handle, 3, 0x1010, 0x1); //等待dma结束 while (true) { wdc_lib_decl.WDC_ReadAddr32(this.Handle, 3, 0x1068, ref tmp); if ((tmp & 0x1) == 1) { break; } } break; } //恢复inbound配置 wdc_lib_decl.WDC_WriteAddr32(this.Handle, 0, 0x33C, 0x80000000); }