?? mbus.c
字號:
#include "../../llad/include/gbus.h"#include "../../llad/include/dmacpy.h"#include "../include/mbus.h"#include "../../emhwlib_hal/include/emhwlib_registers.h"#include "../../emhwlib/include/emhwlib_chipspecific.h"#if 0#define MBUSDBG ENABLE#else#define MBUSDBG DISABLE#endif#define PCI_TIMEOUT_COUNT (1024*2014)static inline RMint32 wait_for_mbus(struct gbus *pgbus, RMuint32 cmd_addr){ RMuint32 mbus_count = 0; while (gbus_read_uint32(pgbus, cmd_addr) & 7) { mbus_count ++; if (mbus_count>PCI_TIMEOUT_COUNT) { RMDBGLOG((ENABLE, "MBUS FROZEN\n")); return 1; } } return 0;}static inline RMint32 get_mbus_status(struct gbus *pgbus, RMuint32 cmd_addr){ static RMuint32 mbus_count = 0; if (gbus_read_uint32(pgbus, cmd_addr) & 7) { mbus_count ++; if (mbus_count>PCI_TIMEOUT_COUNT) { RMDBGLOG((ENABLE, "MBUS FROZEN\n")); return 1; } return -mbus_count; } mbus_count = 0; return 0;}static inline RMint32 wait_for_pci(struct gbus *pgbus, RMuint32 pci_en_addr, RMuint32 pci_cnt_addr){ RMuint32 pci_count = 0, old_pci_count = 0; RMuint32 i = 0; if (gbus_read_uint32(pgbus, pci_en_addr)) { while ((pci_count = gbus_read_uint32(pgbus, pci_cnt_addr))) { if (old_pci_count == pci_count) i++; else i = 0; old_pci_count = pci_count; if (i>PCI_TIMEOUT_COUNT) { RMDBGLOG((ENABLE, "PCI FROZEN\n")); return -pci_count; } } gbus_write_uint32(pgbus, pci_en_addr, 0); } return 0;}static inline RMint32 get_pci_status(struct gbus *pgbus, RMuint32 pci_cnt_addr){ static RMuint32 pci_count = 0; static RMuint32 old_pci_count = 0; static RMuint32 i = 0; if ((pci_count = gbus_read_uint32(pgbus, pci_cnt_addr))) { if (old_pci_count == pci_count) i++; else i = 0; old_pci_count = pci_count; if (i>PCI_TIMEOUT_COUNT) { RMDBGLOG((ENABLE, "PCI FROZEN\n")); return -pci_count; } return 1; } i = 0; return 0;}RMint32 mbus_write_dram(struct llad *pllad, RMuint32 addr, RMuint8 *data, RMuint32 size, RMuint32 max_pci_size){ RMuint32 pci_size = size; RMuint32 mbus_size = size; RMuint32 dma_size, dma_bus_address, half_dma_size, offset; RMuint32 xfer_dma_size = 0; RMint32 status = 0; struct gbus *pgbus; struct dmacpy *pdmacpy; if (max_pci_size > 65532) { RMDBGLOG((MBUSDBG, "bad value for max_pci_size %lu\n", max_pci_size)); return max_pci_size; } pgbus = gbus_open(pllad); pdmacpy = dmacpy_open(pllad); dmacpy_get_info(pdmacpy, &dma_size, &dma_bus_address); half_dma_size = dma_size / 2; offset = 0; RMDBGLOG((MBUSDBG, "dma size is %lu bytes at bus address 0x%08x\n", dma_size, dma_bus_address)); // Wait for MBUS interface if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD))) goto exit_mbus_write_dram; // Wait for PCI Master if ((status = wait_for_pci(pgbus, REG_BASE_host_interface+READ_ENABLE, REG_BASE_host_interface+READ_COUNTER))) goto exit_mbus_write_dram; // Program the switchbox hostsbox_pcimaster_channel1(pgbus); // Program endianness (0 on little-endian systems, 1 on big-endian systems) gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_REVERSE, 0x0); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_SKIP, 0); while (mbus_size || pci_size) { if ((xfer_dma_size == 0) && (pci_size > 0)) { xfer_dma_size = RMmin(max_pci_size, RMmin(half_dma_size, pci_size)); dmacpy_write_data(pdmacpy, offset, data, xfer_dma_size); } // MBUS side if (mbus_size > 0) { status = get_mbus_status(pgbus, REG_BASE_host_interface+MIF_W1_CMD); if (status == 0) { RMuint32 xfer_size = RMmin(8191, mbus_size); RMDBGLOG((MBUSDBG, "program a mbus xfer. addr=0x%08x, size=%lu\n", addr, xfer_size)); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_ADD, addr); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CNT, xfer_size); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CMD, MBUS_LINEAR); addr += xfer_size; mbus_size -= xfer_size; } else if (status > 0) goto exit_mbus_write_dram; } // PCI Master side if (xfer_dma_size > 0) { status = get_pci_status(pgbus, REG_BASE_host_interface+READ_COUNTER); if (status == 0) { RMDBGLOG((MBUSDBG, "program a pci xfer. addr=0x%08x, size=%lu\n", dma_bus_address + offset, xfer_dma_size)); gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ENABLE, 0); gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ADDRESS, dma_bus_address + offset); gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_COUNTER, xfer_dma_size); gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ENABLE, 1); data += xfer_dma_size; pci_size -= xfer_dma_size; offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2 xfer_dma_size = 0; } else if (status < 0) goto exit_mbus_write_dram; } } // Push a void command to the command FIFO and wait for its completion if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD))) goto exit_mbus_write_dram; gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CMD, MBUS_VOID); if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD))) goto exit_mbus_write_dram; // Wait for PCI to finish if ((status = wait_for_pci(pgbus, REG_BASE_host_interface+READ_ENABLE, REG_BASE_host_interface+READ_COUNTER))) goto exit_mbus_write_dram; exit_mbus_write_dram: dmacpy_close(pdmacpy); gbus_close(pgbus); return status;}RMint32 mbus_read_dram(struct llad *pllad, RMuint32 addr, RMuint8 *data, RMuint32 size, RMuint32 max_pci_size){ RMuint32 pci_size = size; RMuint32 read_size = 0, old_read_size = 0; RMuint32 dma_size, dma_bus_address, half_dma_size, offset; RMint32 status = 0; struct gbus *pgbus; struct dmacpy *pdmacpy; if (size % 4) { RMDBGLOG((MBUSDBG, "size not a multiple of 4 bytes %lu\n", size)); return size; } if ((max_pci_size % 4) || (max_pci_size > 65532)) { RMDBGLOG((MBUSDBG, "bad value for max_pci_size %lu\n", max_pci_size)); return max_pci_size; } pgbus = gbus_open(pllad); pdmacpy = dmacpy_open(pllad); dmacpy_get_info(pdmacpy, &dma_size, &dma_bus_address); half_dma_size = dma_size / 2; offset = 0; RMDBGLOG((MBUSDBG, "dma size is %lu bytes at bus address 0x%08x\n", dma_size, dma_bus_address)); // Wait for MBUS interface if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_R1_CMD))) goto exit_mbus_read_dram; // Wait for PCI Master if ((status = wait_for_pci(pgbus, REG_BASE_host_interface+WRITE_ENABLE, REG_BASE_host_interface+WRITE_COUNTER))) goto exit_mbus_read_dram; // Program the switchbox hostsbox_pcimaster_channel1(pgbus); // Program endianness (0 on little-endian systems, 1 on big-endian systems) gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_REVERSE, 0x0); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_SKIP, 0); while (pci_size) { RMuint32 xfer_dma_size; xfer_dma_size = RMmin(half_dma_size, RMmin(max_pci_size, pci_size)); old_read_size = read_size; read_size = xfer_dma_size; RMDBGLOG((MBUSDBG, "program a pci xfer. addr=0x%08x, size=%lu\n", dma_bus_address + offset, xfer_dma_size)); gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ENABLE, 0); gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ADDRESS, dma_bus_address + offset); gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_COUNTER, xfer_dma_size); gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ENABLE, 1); pci_size -= xfer_dma_size; while (xfer_dma_size > 0) { RMuint32 mbus_size = RMmin(8191, xfer_dma_size); RMDBGLOG((MBUSDBG, "program a mbus xfer. addr=0x%08x, size=%lu\n", addr, mbus_size));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -