?? mbus.c
字號:
// Wait for MBUS interface if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_R1_CMD))) goto exit_mbus_read_dram; gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_ADD, addr); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_CNT, mbus_size); if (xfer_dma_size == mbus_size) gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_CMD, MBUS_LINEAR_VOID); else gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_CMD, MBUS_LINEAR); addr += mbus_size; xfer_dma_size -= mbus_size; } offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2 dmacpy_read_data(pdmacpy, offset, data, old_read_size); data += old_read_size; // 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; } offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2 dmacpy_read_data(pdmacpy, offset, data, read_size); exit_mbus_read_dram: dmacpy_close(pdmacpy); gbus_close(pgbus); return status;} RMint32 mbus_write_picture(struct llad *pllad, RMuint32 addr, RMuint8 *data, RMuint16 x, RMuint16 y, RMuint32 buffer_width, RMuint8 xfer_mode, RMuint32 max_pci_size){ RMuint32 pci_size, xfer_size = 0; RMuint32 dma_size, dma_bus_address, half_dma_size, offset; RMuint32 skip; 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; // Wait for MBUS interface if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD))) goto exit_mbus_write_picture; // 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_picture; // 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); if (xfer_mode) skip = ((buffer_width / 128) - 1) | 0x10000; else skip = buffer_width; gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_ADD, addr); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CNT, x + (y << 16)); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_SKIP, skip); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CMD, MBUS_RECTANGLE_VOID | xfer_mode); pci_size = x * y; while (pci_size > 0) { if (xfer_size == 0) { xfer_size = RMmin(max_pci_size, RMmin(half_dma_size, pci_size)); dmacpy_write_data(pdmacpy, offset, data, xfer_size); } // PCI Master side status = get_pci_status(pgbus, REG_BASE_host_interface+READ_COUNTER); if (status == 0) { 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_size); gbus_write_uint32(pgbus, REG_BASE_host_interface+READ_ENABLE, 1); data += xfer_size; pci_size -= xfer_size; offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2 xfer_size = 0; } else if (status < 0) goto exit_mbus_write_picture; } // Wait for the void command to be executed to ensure // all the data has been written to DRAM. if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_W1_CMD))) goto exit_mbus_write_picture; gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_W1_CMD, 0); // reset tiled mode // 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_picture; exit_mbus_write_picture: dmacpy_close(pdmacpy); gbus_close(pgbus); return status;}RMint32 mbus_read_picture (struct llad *pllad, RMuint32 addr, RMuint8 *data, RMuint16 x, RMuint16 y, RMuint32 buffer_width, RMuint8 tiled_xfer, RMuint32 max_pci_size){ RMuint32 pci_size = 0; RMuint32 line_read = 0; RMuint32 dma_size, dma_bus_address, half_dma_size, offset; RMuint32 skip; RMuint16 x_xfer; RMuint32 i, j; RMint32 status = 0; RMuint32 cur_address; RMuint32 cur_y; RMuint32 max_line_count; struct gbus *pgbus; struct dmacpy *pdmacpy; RMuint32 base_addr; 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; } if ((x == 0) || (y == 0)) return 1; 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;#if (EM86XX_CHIP < EM86XX_CHIPID_TANGO15) // read size must be a multiple of 4 on mambo/tango x_xfer = (x + 3) & ~3;#else x_xfer = x;#endif max_pci_size = RMmin(max_pci_size,half_dma_size); if (max_pci_size < x_xfer) { RMDBGLOG((MBUSDBG, "max_pci_size [%lu] must be large enough to transfer one line of [%lu] bytes each\n", max_pci_size,x)); status = max_pci_size; goto exit_mbus_read_picture; } max_line_count = max_pci_size / x_xfer; // Wait for MBUS interface if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_R1_CMD))) goto exit_mbus_read_picture; // 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_picture; // 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); if (tiled_xfer) skip = ((buffer_width / 128) - 1) | 0x10000; else skip = buffer_width; j = y; if (tiled_xfer) { /* get the curt line in the tile and compute base_addr */ cur_y = (addr/128) % 32; base_addr = addr - (cur_y*128); } else { cur_y = 0; base_addr = addr; } while (j>0) { RMuint32 line_count = RMmin(max_line_count, j); if (tiled_xfer) { cur_address = base_addr + (cur_y % 32) * 128 + (cur_y/32) * buffer_width * 32; } else { cur_address = base_addr + cur_y * buffer_width; } gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_ADD, cur_address); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_CNT, x_xfer + (line_count << 16)); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_SKIP, skip); gbus_write_uint32(pgbus, REG_BASE_host_interface+MIF_R1_CMD, MBUS_RECTANGLE_VOID | (tiled_xfer ? 0x8 : 0x0)); pci_size = x_xfer * line_count; 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, pci_size); gbus_write_uint32(pgbus, REG_BASE_host_interface+WRITE_ENABLE, 1); RMDBGLOG((MBUSDBG, "MBUS 0x%08lx %ld %ld %ld %ld\n", cur_address, x_xfer, line_count, skip&~0x10000, pci_size)); offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2 for (i = 0; i < line_read; i++) { dmacpy_read_data(pdmacpy, offset + i * x_xfer, data, x); data += x; } line_read = line_count; // Wait for MBUS interface if ((status = wait_for_mbus(pgbus, REG_BASE_host_interface+MIF_R1_CMD))) goto exit_mbus_read_picture; // 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_picture; j -= line_count; cur_y += line_count; } offset = (offset + half_dma_size) & (dma_size - 1); // dma_size is a power of 2 for (i = 0; i < line_read; i ++) { dmacpy_read_data(pdmacpy, offset + i * x_xfer, data + i * x, x); } exit_mbus_read_picture: dmacpy_close(pdmacpy); gbus_close(pgbus); return status;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -