/* NV Acceleration functions */ /* Author: Rudolf Cornelissen 8/2003-1/2005. This code was possible thanks to: - the Linux XFree86 NV driver, - the Linux UtahGLX 3D driver. */ /* note: attempting DMA on NV40 and higher because without it I can't get it going ATM. Later on this can become a nv.settings switch, and maybe later we can even forget about non-DMA completely (depends on 3D acceleration attempts). */ #define MODULE_BIT 0x00080000 #include "nv_std.h" /*acceleration notes*/ /*functions Be's app_server uses: fill span (horizontal only) fill rectangle (these 2 are very similar) invert rectangle blit */ static void nv_start_dma(void); static status_t nv_acc_fifofree_dma(uint16 cmd_size); static void nv_acc_cmd_dma(uint32 cmd, uint16 offset, uint16 size); status_t nv_acc_wait_idle_dma() { /* wait until engine completely idle */ /* wait until all upcoming commands are in execution at least */ while (NV_REG32(NVACC_FIFO + NV_GENERAL_DMAGET + si->engine.fifo.handle[(si->engine.fifo.ch_ptr[NV_ROP5_SOLID])]) != (si->engine.dma.put << 2)) { /* snooze a bit so I do not hammer the bus */ snooze (100); } /* wait until execution completed */ while (ACCR(STATUS)) { /* snooze a bit so I do not hammer the bus */ snooze (100); } return B_OK; } /* AFAIK this must be done for every new screenmode. * Engine required init. */ 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; snooze(1000); NV_REG32(NV32_PWRUPCTRL) = 0x13111111; /* setup PTIMER: */ //fixme? how about NV28 setup as just after coldstarting? (see nv_info.c) /* set timer numerator to 8 (in b0-15) */ ACCW(PT_NUMERATOR, 0x00000008); /* set timer denominator to 3 (in b0-15) */ ACCW(PT_DENOMINATR, 0x00000003); /* disable timer-alarm INT requests (b0) */ ACCW(PT_INTEN, 0x00000000); /* reset timer-alarm INT status bit (b0) */ ACCW(PT_INTSTAT, 0xffffffff); /* enable PRAMIN write access on pre NV10 before programming it! */ if (si->ps.card_arch == NV04A) { /* set framebuffer config: type = notiling, PRAMIN write access enabled */ NV_REG32(NV32_PFB_CONFIG_0) = 0x00001114; } else { /* setup acc engine 'source' tile adressranges */ ACCW(NV10_FBTIL0AD, 0); ACCW(NV10_FBTIL1AD, 0); ACCW(NV10_FBTIL2AD, 0); ACCW(NV10_FBTIL3AD, 0); ACCW(NV10_FBTIL4AD, 0); ACCW(NV10_FBTIL5AD, 0); ACCW(NV10_FBTIL6AD, 0); ACCW(NV10_FBTIL7AD, 0); ACCW(NV10_FBTIL0ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL1ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL2ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL3ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL4ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL5ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL6ED, (si->ps.memory_size - 1)); ACCW(NV10_FBTIL7ED, (si->ps.memory_size - 1)); } /*** PRAMIN ***/ /* RAMHT (hash-table) space SETUP FIFO HANDLES */ /* note: * 'instance' tells you where the engine command is stored in 'PR_CTXx_x' sets * below: instance being b4-19 with baseadress NV_PRAMIN_CTX_0 (0x00700000). * That command is linked to the handle noted here. This handle is then used to * tell the FIFO to which engine command it is connected! * (CTX registers are actually a sort of RAM space.) */ if (si->ps.card_arch >= NV40A) { /* (first set) */ ACCW(HT_HANDL_00, (0x80000000 | NV10_CONTEXT_SURFACES_2D)); /* 32bit handle (not used) */ ACCW(HT_VALUE_00, 0x0010114c); /* instance $114c, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_01, (0x80000000 | NV_IMAGE_BLIT)); /* 32bit handle */ ACCW(HT_VALUE_01, 0x00101148); /* instance $1146, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_02, (0x80000000 | NV3_GDI_RECTANGLE_TEXT)); /* 32bit handle */ ACCW(HT_VALUE_02, 0x0010114a); /* instance $1147, engine = acc engine, CHID = $00 */ /* (second set) */ ACCW(HT_HANDL_10, (0x80000000 | NV_ROP5_SOLID)); /* 32bit handle */ ACCW(HT_VALUE_10, 0x00101142); /* instance $1142, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_11, (0x80000000 | NV_IMAGE_BLACK_RECTANGLE)); /* 32bit handle */ ACCW(HT_VALUE_11, 0x00101144); /* instance $1143, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_12, (0x80000000 | NV_IMAGE_PATTERN)); /* 32bit handle */ ACCW(HT_VALUE_12, 0x00101146); /* instance $1144, engine = acc engine, CHID = $00 */ } else { /* (first set) */ ACCW(HT_HANDL_00, (0x80000000 | NV4_SURFACE)); /* 32bit handle */ ACCW(HT_VALUE_00, 0x8001114c); /* instance $114c, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_01, (0x80000000 | NV_IMAGE_BLIT)); /* 32bit handle */ ACCW(HT_VALUE_01, 0x80011148); /* instance $1146, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_02, (0x80000000 | NV3_GDI_RECTANGLE_TEXT)); /* 32bit handle */ ACCW(HT_VALUE_02, 0x8001114a); /* instance $1147, engine = acc engine, CHID = $00 */ /* (second set) */ ACCW(HT_HANDL_10, (0x80000000 | NV_ROP5_SOLID)); /* 32bit handle */ ACCW(HT_VALUE_10, 0x80011142); /* instance $1142, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_11, (0x80000000 | NV_IMAGE_BLACK_RECTANGLE)); /* 32bit handle */ ACCW(HT_VALUE_11, 0x80011144); /* instance $1143, engine = acc engine, CHID = $00 */ ACCW(HT_HANDL_12, (0x80000000 | NV_IMAGE_PATTERN)); /* 32bit handle */ ACCW(HT_VALUE_12, 0x80011146); /* instance $1144, engine = acc engine, CHID = $00 */ } /* program CTX registers: CTX1 is mostly done later (colorspace dependant) */ /* note: * CTX determines which HT handles point to what engine commands. * (CTX registers are actually a sort of RAM space.) */ if (si->ps.card_arch >= NV40A) { /* setup a DMA define for use by command defines below. */ ACCW(PR_CTX0_R, 0x00003000); /* DMA page table present and of linear type; * DMA target node is NVM (non-volatile memory?) * (instead of doing PCI or AGP transfers) */ ACCW(PR_CTX1_R, (si->ps.memory_size - 1)); /* DMA limit */ ACCW(PR_CTX2_R, 0x00000002); /* DMA access type is READ_AND_WRITE */ ACCW(PR_CTX3_R, 0x00000002); /* unknown (looks like this is rubbish/not needed?) */ /* setup set '0' for cmd NV_ROP5_SOLID */ ACCW(PR_CTX0_0, 0x02080043); /* NVclass $043, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_0, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_0, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_0, 0x00000000); /* method traps disabled */ ACCW(PR_CTX0_1, 0x00000000); /* extra */ ACCW(PR_CTX1_1, 0x00000000); /* extra */ /* setup set '1' for cmd NV_IMAGE_BLACK_RECTANGLE */ ACCW(PR_CTX0_2, 0x02080019); /* NVclass $019, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_2, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_2, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_2, 0x00000000); /* method traps disabled */ ACCW(PR_CTX0_3, 0x00000000); /* extra */ ACCW(PR_CTX1_3, 0x00000000); /* extra */ /* setup set '2' for cmd NV_IMAGE_PATTERN */ ACCW(PR_CTX0_4, 0x02080018); /* NVclass $018, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_4, 0x02000000); /* colorspace not set, notify instance is $0200 (b16-31) */ ACCW(PR_CTX2_4, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_4, 0x00000000); /* method traps disabled */ ACCW(PR_CTX0_5, 0x00000000); /* extra */ ACCW(PR_CTX1_5, 0x00000000); /* extra */ /* setup set '4' for cmd NV_IMAGE_BLIT */ ACCW(PR_CTX0_6, 0x0208005f); /* NVclass $05f, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_6, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_6, 0x00001140); /* DMA0 instance is $1140, DMA1 instance invalid */ ACCW(PR_CTX3_6, 0x00001140); /* method trap 0 is $1140, trap 1 disabled */ ACCW(PR_CTX0_7, 0x00000000); /* extra */ ACCW(PR_CTX1_7, 0x00000000); /* extra */ /* setup set '5' for cmd NV3_GDI_RECTANGLE_TEXT */ ACCW(PR_CTX0_8, 0x0208004b); /* NVclass $04b, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_8, 0x02000000); /* colorspace not set, notify instance is $0200 (b16-31) */ ACCW(PR_CTX2_8, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_8, 0x00000000); /* method traps disabled */ ACCW(PR_CTX0_9, 0x00000000); /* extra */ ACCW(PR_CTX1_9, 0x00000000); /* extra */ /* setup set '6' for cmd NV10_CONTEXT_SURFACES_2D */ ACCW(PR_CTX0_A, 0x02080062); /* NVclass $062, nv10+: little endian */ ACCW(PR_CTX1_A, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_A, 0x00001140); /* DMA0 instance is $1140, DMA1 instance invalid */ ACCW(PR_CTX3_A, 0x00001140); /* method trap 0 is $1140, trap 1 disabled */ ACCW(PR_CTX0_B, 0x00000000); /* extra */ ACCW(PR_CTX1_B, 0x00000000); /* extra */ /* setup DMA set pointed at by PF_CACH1_DMAI */ ACCW(PR_CTX0_C, 0x00003002); /* DMA page table present and of linear type; * DMA class is $002 (b0-11); * DMA target node is NVM (non-volatile memory?) * (instead of doing PCI or AGP transfers) */ ACCW(PR_CTX1_C, 0x00007fff); /* DMA limit: tablesize is 32k bytes */ ACCW(PR_CTX2_C, (((si->ps.memory_size - 1) & 0xffff8000) | 0x00000002)); /* DMA access type is READ_AND_WRITE; * table is located at end of cardRAM (b12-31): * It's adress needs to be at a 4kb boundary! */ } else { /* setup a DMA define for use by command defines below. */ ACCW(PR_CTX0_R, 0x00003000); /* DMA page table present and of linear type; * DMA target node is NVM (non-volatile memory?) * (instead of doing PCI or AGP transfers) */ ACCW(PR_CTX1_R, (si->ps.memory_size - 1)); /* DMA limit */ ACCW(PR_CTX2_R, 0x00000002); /* DMA access type is READ_AND_WRITE */ ACCW(PR_CTX3_R, 0x00000002); /* unknown (looks like this is rubbish/not needed?) */ /* setup set '0' for cmd NV_ROP5_SOLID */ ACCW(PR_CTX0_0, 0x01008043); /* NVclass $043, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_0, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_0, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_0, 0x00000000); /* method traps disabled */ /* setup set '1' for cmd NV_IMAGE_BLACK_RECTANGLE */ ACCW(PR_CTX0_2, 0x01008019); /* NVclass $019, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_2, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_2, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_2, 0x00000000); /* method traps disabled */ /* setup set '2' for cmd NV_IMAGE_PATTERN */ ACCW(PR_CTX0_4, 0x01008018); /* NVclass $018, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_4, 0x00000002); /* colorspace not set, notify instance is $0200 (b16-31) */ ACCW(PR_CTX2_4, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_4, 0x00000000); /* method traps disabled */ /* setup set '4' for cmd NV_IMAGE_BLIT */ ACCW(PR_CTX0_6, 0x0100805f); /* NVclass $05f, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_6, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_6, 0x11401140); /* DMA0 instance is $1140, DMA1 instance invalid */ ACCW(PR_CTX3_6, 0x00000000); /* method trap 0 is $1140, trap 1 disabled */ /* setup set '5' for cmd NV3_GDI_RECTANGLE_TEXT */ ACCW(PR_CTX0_8, 0x0100804b); /* NVclass $04b, patchcfg ROP_AND, nv10+: little endian */ ACCW(PR_CTX1_8, 0x00000002); /* colorspace not set, notify instance is $0200 (b16-31) */ ACCW(PR_CTX2_8, 0x00000000); /* DMA0 and DMA1 instance invalid */ ACCW(PR_CTX3_8, 0x00000000); /* method traps disabled */ /* setup set '6' for ... */ if(si->ps.card_arch >= NV10A) { /* ... cmd NV10_CONTEXT_SURFACES_2D */ ACCW(PR_CTX0_A, 0x01008062); /* NVclass $062, nv10+: little endian */ } else { /* ... cmd NV4_SURFACE */ ACCW(PR_CTX0_A, 0x01008042); /* NVclass $042, nv10+: little endian */ } ACCW(PR_CTX1_A, 0x00000000); /* colorspace not set, notify instance invalid (b16-31) */ ACCW(PR_CTX2_A, 0x11401140); /* DMA0 instance is $1140, DMA1 instance invalid */ ACCW(PR_CTX3_A, 0x00000000); /* method trap 0 is $1140, trap 1 disabled */ /* setup DMA set pointed at by PF_CACH1_DMAI */ ACCW(PR_CTX0_C, 0x00003002); /* DMA page table present and of linear type; * DMA class is $002 (b0-11); * DMA target node is NVM (non-volatile memory?) * (instead of doing PCI or AGP transfers) */ ACCW(PR_CTX1_C, 0x00007fff); /* DMA limit: tablesize is 32k bytes */ ACCW(PR_CTX2_C, (((si->ps.memory_size - 1) & 0xffff8000) | 0x00000002)); /* DMA access type is READ_AND_WRITE; * table is located at end of cardRAM (b12-31): * It's adress needs to be at a 4kb boundary! */ } if (si->ps.card_arch == NV04A) { /* if((pNv->Chipset & 0x0fff) == 0x0020) { pNv->PRAMIN[0x0824] |= 0x00020000; pNv->PRAMIN[0x0826] += pNv->FbAddress; } pNv->PGRAPH[0x0080/4] = 0x000001FF;//acc DEBUG0 pNv->PGRAPH[0x0080/4] = 0x1230C000; pNv->PGRAPH[0x0084/4] = 0x72111101; pNv->PGRAPH[0x0088/4] = 0x11D5F071; pNv->PGRAPH[0x008C/4] = 0x0004FF31; pNv->PGRAPH[0x008C/4] = 0x4004FF31; pNv->PGRAPH[0x0140/4] = 0x00000000; pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF; pNv->PGRAPH[0x0170/4] = 0x10010100; pNv->PGRAPH[0x0710/4] = 0xFFFFFFFF; pNv->PGRAPH[0x0720/4] = 0x00000001; pNv->PGRAPH[0x0810/4] = 0x00000000; pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF; */ } else { /* do a explicit engine reset */ ACCW(DEBUG0, 0xffffffff); ACCW(DEBUG0, 0x00000000); /* disable all acceleration engine INT reguests */ ACCW(ACC_INTE, 0x00000000); /* reset all acceration engine INT status bits */ ACCW(ACC_INTS, 0xffffffff); /* context control enabled */ ACCW(NV10_CTX_CTRL, 0x10010100); /* all acceleration buffers, pitches and colors are valid */ ACCW(NV10_ACC_STAT, 0xffffffff); /* enable acceleration engine command FIFO */ ACCW(FIFO_EN, 0x00000001); /* setup surface type */ ACCW(NV10_SURF_TYP, ((ACCR(NV10_SURF_TYP)) & 0x0007ff00)); ACCW(NV10_SURF_TYP, ((ACCR(NV10_SURF_TYP)) | 0x00020100)); } if (si->ps.card_arch == NV10A) { /* init some function blocks */ ACCW(DEBUG1, 0x00118700); ACCW(DEBUG2, 0x24e00810); ACCW(DEBUG3, 0x55de0030); /* copy tile setup stuff from 'source' to acc engine */ for (cnt = 0; cnt < 32; cnt++) { NV_REG32(NVACC_NV10_TIL0AD + (cnt << 2)) = NV_REG32(NVACC_NV10_FBTIL0AD + (cnt << 2)); } /* setup accesible card memory range for acc engine */ //fixme: should these two be zero after all??!! ACCW(OFFSET0, ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer)); ACCW(OFFSET1, ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer)); //end fixme. ACCW(BLIMIT0, (si->ps.memory_size - 1)); ACCW(BLIMIT1, (si->ps.memory_size - 1)); /* pattern shape value = 8x8, 2 color */ ACCW(PAT_SHP, 0x00000000); /* Pgraph Beta AND value (fraction) b23-30 */ ACCW(BETA_AND_VAL, 0xffffffff); } if (si->ps.card_arch >= NV20A) { switch (si->ps.card_arch) { case NV40A: /* init some function blocks */ ACCW(DEBUG1, 0x401287c0); ACCW(DEBUG3, 0x60de8051); /* disable specific functions, but enable SETUP_SPARE2 register */ ACCW(NV10_DEBUG4, 0x00008000); /* set limit_viol_pix_adress(?): more likely something unknown.. */ ACCW(NV25_WHAT0, 0x00be3c5f); /* unknown.. */ switch (si->ps.card_type) { case NV40: ACCW(NV40_WHAT0, 0x83280fff); ACCW(NV40_WHAT1, 0x000000a0); ACCW(NV40_WHAT2, 0x0078e366); ACCW(NV40_WHAT3, 0x0000014c); // pNv->PFB[0x033C/4] &= 0xffff7fff;//0x00100000 :<<<< NV_PFB_CLOSE_PAGE2, bits unknown break; case NV41: ACCW(NV40P_WHAT0, 0x83280eff); ACCW(NV40P_WHAT1, 0x000000a0); ACCW(NV40P_WHAT2, 0x007596ff); ACCW(NV40P_WHAT3, 0x00000108); break; case NV43: ACCW(NV40P_WHAT0, 0x83280eff); ACCW(NV40P_WHAT1, 0x000000a0); ACCW(NV40P_WHAT2, 0x0072cb77); ACCW(NV40P_WHAT3, 0x00000108); break; case NV45: //fixme, checkout: this is cardID 0x016x at least! ACCW(NV40P_WHAT0, 0x83280eff); ACCW(NV40P_WHAT1, 0x000000a0); NV_REG32(NV32_NV45_WHAT10) = NV_REG32(NV32_NV10STRAPINFO); NV_REG32(NV32_NV45_WHAT11) = 0x00000000; NV_REG32(NV32_NV45_WHAT12) = 0x00000000; NV_REG32(NV32_NV45_WHAT13) = NV_REG32(NV32_NV10STRAPINFO); ACCW(NV45_WHAT2, 0x00000000); ACCW(NV45_WHAT3, 0x00000000); //schakelt screrm signaal uit op NV43, maar timing blijft werken<<<<<<<< // pNv->PRAMDAC[0x0608/4] |= 0x00100000;//0x00680608==NVDAC_TSTCTRL haiku //b20=1=DACTM_TEST ON (termination?) //how about: NVDAC2_TSTCTRL???? break; default: ACCW(NV40P_WHAT0, 0x83280eff); ACCW(NV40P_WHAT1, 0x000000a0); break; } ACCW(NV10_TIL3PT, 0x2ffff800); ACCW(NV10_TIL3ST, 0x00006000); ACCW(NV4X_WHAT1, 0x01000000); ACCW(NV4X_WHAT0, 0x00001200);//1200 DMA instance????(test shutoff in PIO mod) //test if trouble: // ACCW(NV4X_WHAT0, 0x00001140); break; case NV30A: /* pNv->PGRAPH[0x0084/4] = 0x40108700;//acc DEBUG1 pNv->PGRAPH[0x0890/4] = 0x00140000;//0x00400890 nieuw: unknown!!<<<<<<<<(NV25) pNv->PGRAPH[0x008C/4] = 0xf00e0431;//acc DEBUG3 pNv->PGRAPH[0x0090/4] = 0x00008000;//acc NV10_DEBUG4 pNv->PGRAPH[0x0610/4] = 0xf04b1f36;//NVACC_NV4X_WHAT2 nw, dus ook op NV30!<<< pNv->PGRAPH[0x0B80/4] = 0x1002d888;//0x00400b80 nieuw: unknown!!<<<<<<< pNv->PGRAPH[0x0B88/4] = 0x62ff007f;//0x00400b88 nieuw: unknown!!<<<<<<< */ break; case NV20A: /* pNv->PGRAPH[0x0084/4] = 0x00118700;//acc DEBUG1 pNv->PGRAPH[0x008C/4] = 0xF20E0431;//acc DEBUG3 pNv->PGRAPH[0x0090/4] = 0x00000000;//acc NV10_DEBUG4 pNv->PGRAPH[0x009C/4] = 0x00000040;//0x0040009c nieuw: unknown!!<<<<<<<< if((pNv->Chipset & 0x0ff0) >= 0x0250) { pNv->PGRAPH[0x0890/4] = 0x00080000;//0x00400890 nieuw: unknown!!<<<<<<<< pNv->PGRAPH[0x0610/4] = 0x304B1FB6;//NVACC_NV4X_WHAT2 nw,ook op NV25 en+!<<< pNv->PGRAPH[0x0B80/4] = 0x18B82880;//0x00400b80 nieuw: unknown!!<<<<<<< pNv->PGRAPH[0x0B84/4] = 0x44000000;//0x00400b84 nieuw: unknown!!<<<<<<< pNv->PGRAPH[0x0098/4] = 0x40000080;//0x00400098 nieuw: unknown!!<<<<<<< pNv->PGRAPH[0x0B88/4] = 0x000000ff;//0x00400b88 nieuw: unknown!!<<<<<<< } else { pNv->PGRAPH[0x0880/4] = 0x00080000; pNv->PGRAPH[0x0094/4] = 0x00000005; pNv->PGRAPH[0x0B80/4] = 0x45CAA208; pNv->PGRAPH[0x0B84/4] = 0x24000000; pNv->PGRAPH[0x0098/4] = 0x00000040; pNv->PGRAPH[0x0750/4] = 0x00E00038; pNv->PGRAPH[0x0754/4] = 0x00000030; pNv->PGRAPH[0x0750/4] = 0x00E10038; pNv->PGRAPH[0x0754/4] = 0x00000030; } */ break; } /* NV20A, NV30A and NV40A: */ /* copy tile setup stuff from 'source' to acc engine (pattern colorRAM?) */ for (cnt = 0; cnt < 32; cnt++) { NV_REG32(NVACC_NV20_WHAT0 + (cnt << 2)) = NV_REG32(NVACC_NV10_FBTIL0AD + (cnt << 2)); } if (si->ps.card_arch >= NV40A) { if (si->ps.card_type == NV40) { /* copy unknown tile setup stuff from 'source' to acc engine(?) */ ACCW(NV20_WHAT_T0, ACCR(NV20_FBWHAT0)); ACCW(NV20_WHAT_T1, ACCR(NV20_FBWHAT1)); ACCW(NV40_WHAT_T2, ACCR(NV20_FBWHAT0)); ACCW(NV40_WHAT_T3, ACCR(NV20_FBWHAT1)); /* setup accesible card memory range for acc engine */ //fixme: should these two be zero after all??!! ACCW(NV20_OFFSET0, ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer)); ACCW(NV20_OFFSET1, ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer)); //end fixme. ACCW(NV20_BLIMIT6, (si->ps.memory_size - 1)); ACCW(NV20_BLIMIT7, (si->ps.memory_size - 1)); } else { /* copy unknown tile setup stuff from 'source' to acc engine(?) */ ACCW(NV40P_WHAT_T0, ACCR(NV20_FBWHAT0)); ACCW(NV40P_WHAT_T1, ACCR(NV20_FBWHAT1)); ACCW(NV40P_WHAT_T2, ACCR(NV20_FBWHAT0)); ACCW(NV40P_WHAT_T3, ACCR(NV20_FBWHAT1)); /* setup accesible card memory range for acc engine */ //fixme: should these two be zero after all??!! ACCW(NV40P_OFFSET0, ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer)); ACCW(NV40P_OFFSET1, ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer)); //end fixme. ACCW(NV40P_BLIMIT6, (si->ps.memory_size - 1)); ACCW(NV40P_BLIMIT7, (si->ps.memory_size - 1)); } } else /* NV20A and NV30A: */ { /* //NVACC_NV20_WHAT0 from NV20_FBWHAT0 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4]; //NVACC_NV20_WHAT1 from NV20_FBWHAT1 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4]; pNv->PGRAPH[0x0750/4] = 0x00EA0000; pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0200/4]; pNv->PGRAPH[0x0750/4] = 0x00EA0004; pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0204/4]; pNv->PGRAPH[0x0820/4] = 0;//NV20_OFFSET0 pNv->PGRAPH[0x0824/4] = 0;//NV20_OFFSET1 pNv->PGRAPH[0x0864/4] = pNv->FbMapSize - 1;//NV20_BLIMIT6 pNv->PGRAPH[0x0868/4] = pNv->FbMapSize - 1;//NV20_BLIMIT7 */ } /* NV20A, NV30A and NV40A: */ /* setup some acc engine tile stuff */ ACCW(NV10_TIL2AD, 0x00000000); ACCW(NV10_TIL0ED, 0xffffffff); } /* all cards: */ /* setup some 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); ACCW(ABS_UCLP_YMAX, 0x00007fff); /*** PFIFO ***/ /* (setup caches) */ /* disable caches reassign */ ACCW(PF_CACHES, 0x00000000); /* PFIFO mode: channel 0 is in DMA mode, channels 1 - 32 are in PIO mode */ ACCW(PF_MODE, 0x00000001); /* cache1 push0 access disabled */ ACCW(PF_CACH1_PSH0, 0x00000000); /* cache1 pull0 access disabled */ ACCW(PF_CACH1_PUL0, 0x00000000); /* cache1 push1 mode = DMA */ if (si->ps.card_arch >= NV40A) ACCW(PF_CACH1_PSH1, 0x00010000); else ACCW(PF_CACH1_PSH1, 0x00000100); /* cache1 DMA Put offset = 0 (b2-28) */ ACCW(PF_CACH1_DMAP, 0x00000000); /* cache1 DMA Get offset = 0 (b2-28) */ ACCW(PF_CACH1_DMAG, 0x00000000); /* cache1 DMA instance adress = $114e (b0-15); * 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: if needed... ACCW(PF_CACH1_DMAI, 0x0000114e); /* cache0 push0 access disabled */ ACCW(PF_CACH0_PSH0, 0x00000000); /* cache0 pull0 access disabled */ ACCW(PF_CACH0_PUL0, 0x00000000); /* RAM HT (hash table) baseadress = $10000 (b4-8), size = 4k, * search = 128 (is byte offset between hash 'sets') */ /* note: * so HT base is $00710000, last is $00710fff. * In this space you define the engine command handles (HT_HANDL_XX), which * in turn points to the defines in CTX register space (which is sort of RAM) */ ACCW(PF_RAMHT, 0x03000100); /* RAM FC baseadress = $11000 (b3-8) (size is fixed to 0.5k(?)) */ /* note: * so FC base is $00711000, last is $007111ff. (not used?) */ ACCW(PF_RAMFC, 0x00000110); /* RAM RO baseadress = $11200 (b1-8), size = 0.5k */ /* note: * so RO base is $00711200, last is $007113ff. (not used?) */ /* note also: * This means(?) the PRAMIN CTX registers are accessible from base $00711400. */ ACCW(PF_RAMRO, 0x00000112); /* PFIFO size: ch0-15 = 512 bytes, ch16-31 = 124 bytes */ ACCW(PF_SIZE, 0x0000ffff); /* cache1 hash instance = $ffff (b0-15) */ ACCW(PF_CACH1_HASH, 0x0000ffff); /* disable all PFIFO INTs */ ACCW(PF_INTEN, 0x00000000); /* reset all PFIFO INT status bits */ ACCW(PF_INTSTAT, 0xffffffff); /* cache0 pull0 engine = acceleration engine (graphics) */ ACCW(PF_CACH0_PUL1, 0x00000001); /* cache1 DMA control: disable some stuff */ ACCW(PF_CACH1_DMAC, 0x00000000); /* cache1 engine 0 upto/including 7 is software (could also be graphics or DVD) */ ACCW(PF_CACH1_ENG, 0x00000000); /* cache1 DMA fetch: trigger at 128 bytes, size is 32 bytes, max requests is 15, * use little endian */ ACCW(PF_CACH1_DMAF, 0x000f0078); /* cache1 DMA push: b0 = 1: access is enabled */ ACCW(PF_CACH1_DMAS, 0x00000001); /* cache1 push0 access enabled */ ACCW(PF_CACH1_PSH0, 0x00000001); /* cache1 pull0 access enabled */ ACCW(PF_CACH1_PUL0, 0x00000001); /* cache1 pull1 engine = acceleration engine (graphics) */ ACCW(PF_CACH1_PUL1, 0x00000001); /* enable PFIFO caches reassign */ ACCW(PF_CACHES, 0x00000001); /*** init acceleration engine command info ***/ /* set object handles */ /* note: * probably depending on some other setup, there are 8 or 32 FIFO channels * available. Assuming the current setup only has 8 channels because the 'rest' * isn't setup here... */ si->engine.fifo.handle[0] = NV_ROP5_SOLID; si->engine.fifo.handle[1] = NV_IMAGE_BLACK_RECTANGLE; si->engine.fifo.handle[2] = NV_IMAGE_PATTERN; si->engine.fifo.handle[3] = NV4_SURFACE; /* NV10_CONTEXT_SURFACES_2D is identical */ si->engine.fifo.handle[4] = NV_IMAGE_BLIT; si->engine.fifo.handle[5] = NV3_GDI_RECTANGLE_TEXT; si->engine.fifo.handle[6] = NV1_RENDER_SOLID_LIN; si->engine.fifo.handle[7] = NV4_DX5_TEXTURE_TRIANGLE; /* preset no FIFO channels assigned to cmd's */ for (cnt = 0; cnt < 0x20; cnt++) { si->engine.fifo.ch_ptr[cnt] = 0; } /* set handle's pointers to their assigned FIFO channels */ /* note: * b0-1 aren't used as adressbits. Using b0 to indicate a valid pointer. */ for (cnt = 0; cnt < 0x08; cnt++) { si->engine.fifo.ch_ptr[(si->engine.fifo.handle[cnt])] = (0x00000001 + (cnt * 0x00002000)); } /*** init DMA command buffer info ***/ si->engine.dma.cmdbuffer = (uint32 *)((char *)si->framebuffer + ((si->ps.memory_size - 1) & 0xffff8000)); LOG(4,("ACC_DMA: command buffer is at adress $%08x\n", ((uint32)(si->engine.dma.cmdbuffer)))); /* we have issued no DMA cmd's to the engine yet */ si->engine.dma.put = 0; /* the current first free adress in the DMA buffer is at offset 0 */ si->engine.dma.current = 0; /* the DMA buffer can hold 8k 32-bit words (it's 32kb in size) */ /* note: * 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; /* note the current free space we have left in the DMA buffer */ si->engine.dma.free = /*si->dma.*/max - si->engine.dma.current /*+ 1*/; /*** init FIFO via DMA command buffer. ***/ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH0 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[0]); /* Raster OPeration */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH1 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[1]); /* Clip */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH2 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[2]); /* Pattern */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH3 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[3]); /* 2D Surface */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH4 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[4]); /* Blit */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH5 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[5]); /* Bitmap */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH6 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = //fixme: temporary so there's something valid here.. (maybe needed, don't yet know) // (0x80000000 | si->engine.fifo.handle[6]); /* Line (not used or 3D only?) */ (0x80000000 | si->engine.fifo.handle[0]); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH7 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = //fixme: temporary so there's something valid here.. (maybe needed, don't yet know) // (0x80000000 | si->engine.fifo.handle[7]); /* Textured Triangle (3D only) */ (0x80000000 | si->engine.fifo.handle[0]); //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 ***/ switch(si->dm.space) { case B_CMAP8: surf_depth = 0x00000001; patt_depth = 0x00000003; break; case B_RGB15_LITTLE: surf_depth = 0x00000004; patt_depth = 0x00000001; break; case B_RGB16_LITTLE: surf_depth = 0x00000004; patt_depth = 0x00000001; break; case B_RGB32_LITTLE: case B_RGBA32_LITTLE: surf_depth = 0x00000006; patt_depth = 0x00000003; break; default: LOG(8,("ACC: init, invalid bit depth\n")); return B_ERROR; } /* now setup 2D surface (writing 5 32bit words) */ nv_acc_cmd_dma(NV4_SURFACE, NV4_SURFACE_FORMAT, 4); si->engine.dma.cmdbuffer[si->engine.dma.current++] = surf_depth; /* Format */ /* setup screen pitch */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = ((si->fbc.bytes_per_row & 0x0000ffff) | (si->fbc.bytes_per_row << 16)); /* Pitch */ /* setup screen location */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer); /* OffsetSource */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = ((uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer); /* OffsetDest */ /* set pattern colordepth (writing 2 32bit words) */ //fixme: switch to NV4_IMAGE_PATTERN from NV_IMAGE_PATTERN??? nv_acc_cmd_dma(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETCOLORFORMAT, 1); si->engine.dma.cmdbuffer[si->engine.dma.current++] = patt_depth; /* SetColorFormat */ /* tell the engine to fetch and execute all (new) commands in the DMA buffer */ nv_start_dma(); return B_OK; } static void nv_start_dma(void) { uint8 dummy; if (si->engine.dma.current != si->engine.dma.put) { si->engine.dma.put = si->engine.dma.current; /* fixme: is this actually needed? (force some flush somewhere) */ ISAWB(0x03d0, 0x00); /* dummy read the first adress of the framebuffer: flushes MTRR-WC buffers so * we know for sure the DMA command buffer received all data. */ dummy = *((char *)(si->framebuffer)); /* actually start DMA to execute all commands now in buffer */ /* note: * the actual FIFO channel that gets activated does not really matter: * all FIFO fill-level info actually points at the same registers. */ /* note also: * NV_GENERAL_DMAPUT is a write-only register on some cards (confirmed NV11). */ NV_REG32(NVACC_FIFO + NV_GENERAL_DMAPUT + si->engine.fifo.handle[(si->engine.fifo.ch_ptr[NV_ROP5_SOLID])]) = (si->engine.dma.put << 2); } //test: for (dummy = 0; dummy < 2; dummy++) { LOG(4,("ACC_DMA: 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: put $%08x\n", (si->engine.dma.put << 2))); } } 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; return B_ERROR; } static void nv_acc_cmd_dma(uint32 cmd, uint16 offset, uint16 size) { /* NV_FIFO_DMA_OPCODE: set number of cmd words (b18 - 28); set FIFO offset for * first cmd word (b2 - 15); set DMA opcode = method (b29 - 31). * a 'NOP' is the opcode word $00000000. */ /* note: * possible DMA opcodes: * b'000' is 'method' (execute cmd); * b'001' is 'jump'; * b'002' is 'noninc method' (execute buffer wrap-around); * b'003' is 'call': return is executed by opcode word $00020000 (b17 = 1). */ /* note also: * this system uses auto-increments for the FIFO offset adresses. Make sure * 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)); } /* fixme? (check this out..) * Looks like this stuff can be very much simplified and speed-up, as it seems it's not * nessesary to wait for the engine to become idle before re-assigning channels. * Because the cmd handles are actually programmed _inside_ the fifo channels, it might * well be that the assignment is buffered along with the commands that still have to * be executed! * (sounds very plausible to me :) */ void nv_acc_assert_fifo_dma(void) { /* does every engine cmd this accelerant needs have a FIFO channel? */ //fixme: can probably be optimized for both speed and channel selection... if (!si->engine.fifo.ch_ptr[NV_ROP5_SOLID] || !si->engine.fifo.ch_ptr[NV_IMAGE_BLACK_RECTANGLE] || !si->engine.fifo.ch_ptr[NV_IMAGE_PATTERN] || !si->engine.fifo.ch_ptr[NV4_SURFACE] || !si->engine.fifo.ch_ptr[NV_IMAGE_BLIT] || !si->engine.fifo.ch_ptr[NV3_GDI_RECTANGLE_TEXT]) { uint16 cnt; /* no, wait until the engine is idle before re-assigning the FIFO */ nv_acc_wait_idle_dma(); /* free the FIFO channels we want from the currently assigned cmd's */ si->engine.fifo.ch_ptr[si->engine.fifo.handle[0]] = 0; si->engine.fifo.ch_ptr[si->engine.fifo.handle[1]] = 0; si->engine.fifo.ch_ptr[si->engine.fifo.handle[2]] = 0; si->engine.fifo.ch_ptr[si->engine.fifo.handle[3]] = 0; si->engine.fifo.ch_ptr[si->engine.fifo.handle[4]] = 0; si->engine.fifo.ch_ptr[si->engine.fifo.handle[5]] = 0; /* set new object handles */ si->engine.fifo.handle[0] = NV_ROP5_SOLID; si->engine.fifo.handle[1] = NV_IMAGE_BLACK_RECTANGLE; si->engine.fifo.handle[2] = NV_IMAGE_PATTERN; si->engine.fifo.handle[3] = NV4_SURFACE; si->engine.fifo.handle[4] = NV_IMAGE_BLIT; si->engine.fifo.handle[5] = NV3_GDI_RECTANGLE_TEXT; /* set handle's pointers to their assigned FIFO channels */ /* note: * b0-1 aren't used as adressbits. Using b0 to indicate a valid pointer. */ for (cnt = 0; cnt < 0x08; cnt++) { si->engine.fifo.ch_ptr[(si->engine.fifo.handle[cnt])] = (0x00000001 + (cnt * 0x00002000)); } /* program new FIFO assignments */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH0 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[0]); /* Raster OPeration */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH1 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[1]); /* Clip */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH2 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[2]); /* Pattern */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH3 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[3]); /* 2D Surface */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH4 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[4]); /* Blit */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (NV_GENERAL_FIFO_CH5 | (1 << 18)); si->engine.dma.cmdbuffer[si->engine.dma.current++] = (0x80000000 | si->engine.fifo.handle[5]); /* Bitmap */ /* tell the engine to fetch and execute all (new) commands in the DMA buffer */ nv_start_dma(); } } /* screen to screen blit - i.e. move windows around and scroll within them. */ 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; /* now setup pattern (writing 7 32bit words) */ nv_acc_cmd_dma(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETSHAPE, 1); si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0x00000000; /* SetShape: 0 = 8x8, 1 = 64x1, 2 = 1x64 */ nv_acc_cmd_dma(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETCOLOR0, 4); si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0xffffffff; /* SetColor0 */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0xffffffff; /* SetColor1 */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0xffffffff; /* SetPattern[0] */ 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; /* now setup ROP (writing 2 32bit words) */ nv_acc_cmd_dma(NV_ROP5_SOLID, NV_ROP5_SOLID_SETROP5, 1); si->engine.dma.cmdbuffer[si->engine.dma.current++] = 0xcc; /* SetRop5 */ return B_OK; } status_t nv_acc_blit_dma(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h) { /* Note: blit-copy direction is determined inside riva hardware: no setup needed */ /* 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; /* now setup blit (writing 4 32bit words) */ nv_acc_cmd_dma(NV_IMAGE_BLIT, NV_IMAGE_BLIT_SOURCEORG, 3); si->engine.dma.cmdbuffer[si->engine.dma.current++] = ((ys << 16) | xs); /* SourceOrg */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = ((yd << 16) | xd); /* DestOrg */ si->engine.dma.cmdbuffer[si->engine.dma.current++] = (((h + 1) << 16) | (w + 1)); /* HeightWidth */ /* tell the engine to fetch the commands in the DMA buffer that where not * executed before. At this time the setup done by nv_acc_setup_blit_dma() is * also executed on the first call of nv_acc_blit_dma(). */ nv_start_dma(); return B_OK; } /* rectangle fill - i.e. workspace and window background color */ /* span fill - i.e. (selected) menuitem background color (Dano) */ status_t nv_acc_setup_rectangle_dma(uint32 color) { //fixme: implement. return B_ERROR; } status_t nv_acc_rectangle_dma(uint32 xs,uint32 xe,uint32 ys,uint32 yl) { //fixme: implement. return B_ERROR; } /* rectangle invert - i.e. text cursor and text selection */ status_t nv_acc_setup_rect_invert_dma() { //fixme: implement. return B_ERROR; } status_t nv_acc_rectangle_invert_dma(uint32 xs,uint32 xe,uint32 ys,uint32 yl) { //fixme: implement. return B_ERROR; }