From fc61675c5a3f99cfac3695afcf512781ea63c93d Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Sat, 22 Jan 2005 19:22:45 +0000 Subject: [PATCH] completed DMA buffer wraparounds. DMA acceleration is now stable on NV11 and NV43. Enjoy.. (still missing acc hooks will be setup asap.) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10959 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../accelerants/nvidia/engine/nv_acc.c | 14 +-- .../accelerants/nvidia/engine/nv_acc_dma.c | 93 ++++++++++++++----- 2 files changed, 76 insertions(+), 31 deletions(-) diff --git a/src/add-ons/accelerants/nvidia/engine/nv_acc.c b/src/add-ons/accelerants/nvidia/engine/nv_acc.c index b4b9a06292..ed4a56d821 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_acc.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_acc.c @@ -26,9 +26,8 @@ blit nVidia hardware info: We should be able to do FIFO assignment setup changes on-the-fly now, using all the engine-command-handles that are pre-defined on any FIFO channel. - - We should be able to even setup new additional handles to previously unused engine - commands now, and DMA use should also be possible. + Also we should be able to setup new additional handles to previously unused + engine commands now. */ /* FIFO channel pointers */ @@ -82,14 +81,12 @@ status_t nv_acc_init() /* (setup caches) */ /* disable caches reassign */ ACCW(PF_CACHES, 0x00000000); - //fixme: set this up for DMA use one day.. /* PFIFO mode for all 32 channels is PIO (instead of DMA) */ ACCW(PF_MODE, 0x00000000); /* cache1 push0 access disabled */ ACCW(PF_CACH1_PSH0, 0x00000000); /* cache1 pull0 access disabled */ ACCW(PF_CACH1_PUL0, 0x00000000); - //fixme: set this up for DMA use one day.. /* cache1 push1 mode = pio (disable DMA use) */ ACCW(PF_CACH1_PSH1, 0x00000000); /* cache1 DMA Put offset = 0 (b2-28) */ @@ -100,10 +97,8 @@ status_t nv_acc_init() * instance being b4-19 with baseadress NV_PRAMIN_CTX_0 (0x00700000). */ /* note: * should point to a DMA definition in CTX register space (which is sort of RAM). - * This define tells the engine where the DMA cmd buffer is and what it's size is; - * inside that cmd buffer you'll find the engine handles for the FIFO channels, - * followed by actual issued engine commands. */ - //fixme: set this up for DMA use one day.. + * This define tells the engine where the DMA cmd buffer is and what it's size is. + * Inside that cmd buffer you'll find the actual issued engine commands. */ ACCW(PF_CACH1_DMAI, 0x00000000); /* cache0 push0 access disabled */ ACCW(PF_CACH0_PSH0, 0x00000000); @@ -144,7 +139,6 @@ status_t nv_acc_init() * use little endian */ ACCW(PF_CACH1_DMAF, 0x000f0078); /* cache1 DMA push: b0=0 is access disabled */ - //fixme: set this up for DMA use one day.. ACCW(PF_CACH1_DMAS, 0x00000000); /* cache1 push0 access enabled */ ACCW(PF_CACH1_PSH0, 0x00000001); diff --git a/src/add-ons/accelerants/nvidia/engine/nv_acc_dma.c b/src/add-ons/accelerants/nvidia/engine/nv_acc_dma.c index 412f7b03bb..8e317d33a5 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_acc_dma.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_acc_dma.c @@ -61,8 +61,6 @@ status_t nv_acc_init_dma() { uint16 cnt; uint32 surf_depth, patt_depth; - //fixme: move to shared info: - uint32 max; /* a hanging engine only recovers from a complete power-down/power-up cycle */ NV_REG32(NV32_PWRUPCTRL) = 0x13110011; @@ -555,7 +553,7 @@ status_t nv_acc_init_dma() } /* all cards: */ - /* setup some clipping: rect size is 32768 x 32768, probably max. setting */ + /* setup clipping: rect size is 32768 x 32768, probably max. setting */ ACCW(ABS_UCLP_XMIN, 0x00000000); ACCW(ABS_UCLP_YMIN, 0x00000000); ACCW(ABS_UCLP_XMAX, 0x00007fff); @@ -584,9 +582,8 @@ status_t nv_acc_init_dma() * instance being b4-19 with baseadress NV_PRAMIN_CTX_0 (0x00700000). */ /* note: * should point to a DMA definition in CTX register space (which is sort of RAM). - * This define tells the engine where the DMA cmd buffer is and what it's size is; - * inside that cmd buffer you'll find the engine handles for the FIFO channels, - * followed by actual issued engine commands. */ + * This define tells the engine where the DMA cmd buffer is and what it's size is. + * Inside that cmd buffer you'll find the actual issued engine commands. */ ACCW(PF_CACH1_DMAI, 0x0000114e); /* cache0 push0 access disabled */ ACCW(PF_CACH0_PSH0, 0x00000000); @@ -679,11 +676,15 @@ status_t nv_acc_init_dma() * one word is reserved at the end of the DMA buffer to be able to instruct the * engine to do a buffer wrap-around! * (DMA opcode 'noninc method': issue word $20000000.) */ - /*si->dma.*/max = 8191; + //testing: + si->engine.dma.max = 2048 - 1;//8192 - 1; /* note the current free space we have left in the DMA buffer */ - si->engine.dma.free = /*si->dma.*/max - si->engine.dma.current /*+ 1*/; + si->engine.dma.free = si->engine.dma.max - si->engine.dma.current; /*** init FIFO via DMA command buffer. ***/ + /* note: + * we know there's space enough in the command buffer to issue these commands, + * so no need to wait for room in there. */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH0 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = @@ -728,6 +729,9 @@ status_t nv_acc_init_dma() // (0x80000000 | si->engine.fifo.handle[7]); /* Textured Triangle (3D only) */ (0x80000000 | si->engine.fifo.handle[0]); + /* update the current free space we have left in the DMA buffer */ + si->engine.dma.free = si->engine.dma.max - si->engine.dma.current; + //fixme: overlay should stay outside the DMA buffer, also add a failsafe // space in between both functions as errors might hang the engine! /*** Set pixel width ***/ @@ -810,14 +814,55 @@ for (dummy = 0; dummy < 2; dummy++) static status_t nv_acc_fifofree_dma(uint16 cmd_size) { - //fixme: implement buffer wraparounds.. (buffer resets when full) - //for now only executing the first commands issued and drop exec after; - //this offers testing options already (depending on how much windows are visible, - //exec remains going say 30 seconds to a few minutes if only blits are enabled. -// if (si->dma.free >= cmd_size) return B_OK; - if ((si->engine.dma.current + cmd_size) < 8191) return B_OK; + //test: + uint32 dummy; - return B_ERROR; + if (si->engine.dma.free < cmd_size) + { + //test: + LOG(4,("ACC_FIFOFREE: level 1; free $%08x, max $%08x, current $%08x\n", + si->engine.dma.free, si->engine.dma.max, si->engine.dma.current )); + + /* update to actual current situation (free is 'cached') */ +// si->engine.dma.free = si->engine.dma.max - si->engine.dma.current; + /* check again if we have enough space */ +// if (si->engine.dma.free < cmd_size) + { + //test: + LOG(4,("ACC_FIFOFREE: level 2\n")); + + /* nope, so instruct DMA engine to reset the buffer when it's done */ + si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0x20000000; + + /* reset our buffer pointer, so new commands will be placed at the + * beginning of the buffer. */ + si->engine.dma.current = 0; + /* tell the engine to fetch the remaining command(s) in the DMA buffer + * that where not executed before. */ + nv_start_dma(); + /* fixme if needed: + * we are assuming here that a large part in the beginning of the DMA + * cmd buffer is already processed. If this is not true, we need to wait + * here until the engine becomes idle or so... */ +//test: +//nv_acc_wait_idle_dma(); +// { + /* snooze a bit so I do not hammer the bus */ +// snooze (100); +// } +for (dummy = 0; dummy < 2; dummy++) +{ + LOG(4,("ACC_DMA_WRAP: get $%08x\n", NV_REG32(NVACC_FIFO + NV_GENERAL_DMAGET + + si->engine.fifo.handle[(si->engine.fifo.ch_ptr[NV_ROP5_SOLID])]))); + LOG(4,("ACC_DMA_WRAP: put $%08x\n", (si->engine.dma.put << 2))); +} + + /* update the current free space we have left in the DMA buffer */ + si->engine.dma.free = si->engine.dma.max - si->engine.dma.current; + } + } + + return B_OK; } static void nv_acc_cmd_dma(uint32 cmd, uint16 offset, uint16 size) @@ -836,6 +881,9 @@ static void nv_acc_cmd_dma(uint32 cmd, uint16 offset, uint16 size) * to set a new adress if a gap exists between the previous one and the new one. */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = ((size << 18) | ((si->engine.fifo.ch_ptr[cmd] + offset) & 0x0000fffc)); + + /* space left after issuing the current command is the cmd AND it's data */ + si->engine.dma.free -= (size + 1); } /* fixme? (check this out..) @@ -886,6 +934,9 @@ void nv_acc_assert_fifo_dma(void) (0x00000001 + (cnt * 0x00002000)); } + /* wait for room in fifo for new FIFO assigment cmds if needed. */ + nv_acc_fifofree_dma(12); + /* program new FIFO assignments */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH0 | (1 << 18)); @@ -917,6 +968,9 @@ void nv_acc_assert_fifo_dma(void) si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[5]); /* Bitmap */ + /* update the current free space we have left in the DMA buffer */ + si->engine.dma.free = si->engine.dma.max - si->engine.dma.current; + /* tell the engine to fetch and execute all (new) commands in the DMA buffer */ nv_start_dma(); } @@ -927,8 +981,7 @@ status_t nv_acc_setup_blit_dma() { /* setup solid pattern: * wait for room in fifo for pattern cmd if needed. */ - //fixme: testing.. - if (nv_acc_fifofree_dma(7) != B_OK) return B_ERROR; + nv_acc_fifofree_dma(7); /* now setup pattern (writing 7 32bit words) */ nv_acc_cmd_dma(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETSHAPE, 1); @@ -940,8 +993,7 @@ status_t nv_acc_setup_blit_dma() si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0xffffffff; /* SetPattern[1] */ /* ROP registers (Raster OPeration): * wait for room in fifo for ROP cmd if needed. */ - //fixme: testing.. - if (nv_acc_fifofree_dma(2) != B_OK) return B_ERROR; + nv_acc_fifofree_dma(2); /* now setup ROP (writing 2 32bit words) */ nv_acc_cmd_dma(NV_ROP5_SOLID, NV_ROP5_SOLID_SETROP5, 1); @@ -956,8 +1008,7 @@ status_t nv_acc_blit_dma(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 /* instruct engine what to blit: * wait for room in fifo for blit cmd if needed. */ - //fixme: testing.. - if (nv_acc_fifofree_dma(4) != B_OK) return B_ERROR; + nv_acc_fifofree_dma(4); /* now setup blit (writing 4 32bit words) */ nv_acc_cmd_dma(NV_IMAGE_BLIT, NV_IMAGE_BLIT_SOURCEORG, 3);