format MS COFF include 'proc32.inc' include 'imports.inc' DEBUG equ 1 VID_ATI equ 0x1002 LOAD_FROM_FILE equ 0 LOAD_FROM_MEM equ 1 LOAD_INDIRECT equ 2 LOAD_SYSTEM equ 3 VIDEO_FREE equ 2 struc BITMAPINFOHEADER { .biSize dd ? ; DWORD .biWidth dd ? ; LONG .biHeight dd ? ; LONG .biPlanes dw ? ; WORD .biBitCount dw ? ; WORD .biCompression dd ? ; DWORD .biSizeImage dd ? ; DWORD .biXPelsPerMeter dd ? ; LONG .biYPelsPerMeter dd ? ; LONG .biClrUsed dd ? ; DWORD .biClrImportant dd ? ; DWORD } virtual at 0 BI BITMAPINFOHEADER end virtual struc CURSOR {;common object header .magic dd ? ;'CURS' .destroy dd ? ;internal destructor .fd dd ? ;next object in list .bk dd ? ;prev object in list .pid dd ? ;owner id ;cursor data .base dd ? ;allocated memory .hot_x dd ? ;hotspot coords .hot_y dd ? } virtual at 0 CURSOR CURSOR end virtual CURSOR_SIZE equ 32 R8500 equ 0x514C ;R200 R9000 equ 0x4966 ;RV250 R9200 equ 0x5961 ;RV280 R9500 equ 0x4144 ;R300 R9500P equ 0x4E45 ;R300 R9550 equ 0x4153 ;RV350 R9600 equ 0x4150 ;RV350 R9600XT equ 0x4152 ;RV360 R9700P equ 0x4E44 ;R300 R9800 equ 0x4E49 ;R350 R9800P equ 0x4E48 ;R350 R9800XT equ 0x4E4A ;R360 OS_BASE equ 0 new_app_base equ 0x80000000 SLOT_BASE equ 0x0080000 PG_SW equ 0x003 PG_NOCACHE equ 0x018 struc IOCTL { .handle dd ? .io_code dd ? .input dd ? .inp_size dd ? .output dd ? .out_size dd ? } virtual at 0 IOCTL IOCTL end virtual ;MMIO equ 0F9000000h RD_RB3D_CNTL equ 1c3ch RD_MEM_CNTL equ 0140h RD_CRTC_GEN_CNTL equ 0050h RD_CRTC_CUR_EN equ 10000h RD_DISPLAY_BASE_ADDR equ 023ch RD_DEFAULT_OFFSET equ 16e0h CUR_HORZ_VERT_OFF equ 0268h CUR_HORZ_VERT_POSN equ 0264h CUR_OFFSET equ 0260h RD_RB3D_CNTL equ 1c3ch RD_RBBM_STATUS equ 0e40h RD_RBBM_FIFOCNT_MASK equ 007fh RD_RBBM_ACTIVE equ 80000000h RD_TIMEOUT equ 2000000 RD_DP_GUI_MASTER_CNTL equ 0146ch RD_DP_BRUSH_BKGD_CLR equ 01478h RD_DP_BRUSH_FRGD_CLR equ 0147ch RD_DP_SRC_BKGD_CLR equ 015dch RD_DP_SRC_FRGD_CLR equ 015d8h RD_DP_CNTL equ 016c0h RD_DP_DATATYPE equ 016c4h RD_DP_WRITE_MASK equ 016cch RD_DP_SRC_SOURCE_MEMORY equ (2 shl 24) RD_DP_SRC_SOURCE_HOST_DATA equ (3 shl 24) RD_DEFAULT_SC_BOTTOM_RIGHT equ 16e8h RD_GMC_BRUSH_SOLID_COLOR equ (13 shl 4) RD_DEFAULT_SC_RIGHT_MAX equ 1fffh RD_DEFAULT_SC_BOTTOM_MAX equ 1fff0000h RD_GMC_DST_DATATYPE_SHIFT equ 8 RD_ROP3_S equ 00cc0000h RD_ROP3_P equ 00f00000h RD_RB2D_DSTCACHE_MODE equ 03428h RD_RB2D_DSTCACHE_CTLSTAT equ 0342ch RD_RB2D_DC_FLUSH_ALL equ 000fh RD_RB2D_DC_BUSY equ 80000000h RD_GMC_BRUSH_SOLID_COLOR equ 000000D0h RD_GMC_SRC_DATATYPE_COLOR equ (3 shl 12) RD_GMC_CLR_CMP_CNTL_DIS equ (1 shl 28) RD_GMC_WR_MSK_DIS equ (1 shl 30) cmdSolidFill equ 73f036d0h RD_DST_PITCH_OFFSET equ 142ch RD_SRC_PITCH_OFFSET equ 1428h RD_DST_X_LEFT_TO_RIGHT equ 1 RD_DST_Y_TOP_TO_BOTTOM equ 2 RD_DST_Y_X equ 1438h RD_DST_WIDTH_HEIGHT equ 1598h RD_DST_LINE_START equ 1600h RD_DST_LINE_END equ 1604h R300_MEM_NUM_CHANNELS_MASK equ 0003h macro rdr op1, op2 { mov edi, [ati_io] mov op1, [edi+op2] } macro wrr dest, src { mov edi, [ati_io] mov dword [edi+dest], src } public START public service_proc public version CURSOR_IMAGE_OFFSET equ 0x00500000 DRV_ENTRY equ 1 DRV_EXIT equ -1 section '.flat' code readable align 16 proc START stdcall, state:dword cmp [state], 1 jne .exit if DEBUG mov esi, msgInit call SysMsgBoardStr end if call detect_ati test eax, eax jz .fail call init_ati test eax, eax jz .fail or eax, -1 mov [cursor_map], eax mov [cursor_map+4], eax mov edx, cursor_map mov [cursor_start], edx add edx, 8 mov [cursor_end], edx stdcall RegService, sz_ati_srv, service_proc test eax, eax jz .fail mov dword [SetHwCursor], drvCursorPos ;enable hardware cursor mov dword [HwCursorRestore], drv_restore mov dword [HwCursorCreate], ati_cursor ret .fail: if DEBUG mov esi, msgFail call SysMsgBoardStr end if .exit: xor eax, eax ; mov ebx, SetHwCursor ; mov dword [ebx], eax ;force disable hardware cursor ret endp handle equ IOCTL.handle io_code equ IOCTL.io_code input equ IOCTL.input inp_size equ IOCTL.inp_size output equ IOCTL.output out_size equ IOCTL.out_size align 4 proc service_proc stdcall, ioctl:dword mov edi, [ioctl] mov ebx, [edi+io_code] cmp ebx, VIDEO_FREE jne .fail mov eax, [edi+input] call video_free .fail: or eax, -1 ret endp restore handle restore io_code restore input restore inp_size restore output restore out_size align 4 proc detect_ati locals last_bus dd ? endl xor eax, eax mov [bus], eax inc eax call PciApi cmp eax, -1 je .err mov [last_bus], eax .next_bus: and [devfn], 0 .next_dev: stdcall PciRead32, [bus], [devfn], dword 0 test eax, eax jz .next cmp eax, -1 je .next mov edi, devices @@: mov ebx, [edi] test ebx, ebx jz .next cmp eax, ebx je .found add edi, 4 jmp @B .next: inc [devfn] cmp [devfn], 256 jb .next_dev mov eax, [bus] inc eax mov [bus], eax cmp eax, [last_bus] jna .next_bus xor eax, eax ret .found: xor eax, eax inc eax ret .err: xor eax, eax ret endp align 4 proc init_ati stdcall AllocKernelSpace, dword 0x10000 test eax, eax jz .fail mov [ati_io], eax stdcall PciRead32, [bus], [devfn], dword 0x18 and eax, 0xFFFF0000 mov esi, eax mov edi, [ati_io] mov edx, 16 @@: stdcall MapPage,edi,esi,PG_SW+PG_NOCACHE add edi, 0x1000 add esi, 0x1000 dec edx jnz @B mov edi, [ati_io] mov dword [edi+RD_RB3D_CNTL], 0 call engRestore mov edi, [ati_io] mov eax, [edi+0x50] mov ebx,3 shl ebx,20 not ebx and eax,ebx mov ebx, 2 shl ebx,20 or eax, ebx mov [edi+0x50], eax call drvShowCursor xor eax, eax inc eax .fail: ret endp align 4 drv_restore: ret 8 align 4 drvShowCursor: mov edi, [ati_io] mov eax, [edi+RD_CRTC_GEN_CNTL] bts eax,16 mov [edi+RD_CRTC_GEN_CNTL], eax ret align 4 proc drvCursorPos stdcall, hcursor:dword, x:dword, y:dword pushfd cli xor eax, eax xor edx, edx mov esi, [hcursor] mov ebx, [x] mov ecx, [y] sub ebx, [esi+CURSOR.hot_x] jnc @F neg ebx mov eax, ebx shl eax, 16 xor ebx, ebx @@: sub ecx, [esi+CURSOR.hot_y] jnc @F neg ecx mov ax, cx mov edx, ecx xor ecx, ecx @@: or eax, 0x80000000 wrr CUR_HORZ_VERT_OFF, eax shl ebx, 16 mov bx, cx or ebx, 0x80000000 wrr CUR_HORZ_VERT_POSN, ebx shl edx, 8 add edx, [esi+CURSOR.base] sub edx, LFBAddress wrr CUR_OFFSET, edx popfd ret endp align 4 proc video_alloc pushfd cli mov ebx, [cursor_start] mov ecx, [cursor_end] .l1: bsf eax,[ebx]; jnz .found add ebx,4 cmp ebx, ecx jb .l1 popfd xor eax,eax ret .found: btr [ebx], eax popfd mov [cursor_start],ebx sub ebx, cursor_map lea eax,[eax+ebx*8] shl eax,14 add eax, LFBAddress+CURSOR_IMAGE_OFFSET ret endp align 4 video_free: pushfd cli sub eax, LFBAddress+CURSOR_IMAGE_OFFSET shr eax, 14 mov ebx, cursor_map bts [ebx], eax shr eax, 3 and eax, not 3 add eax, ebx cmp [cursor_start], eax ja @f popfd ret @@: mov [cursor_start], eax popfd ret ; param ; eax= pid ; ebx= src ; ecx= flags align 4 ati_cursor: .src equ esp .flags equ esp+4 .hcursor equ esp+8 sub esp, 4 ;space for .hcursor push ecx push ebx mov ebx, eax mov eax, CURSOR_SIZE call CreateObject test eax, eax jz .fail mov [.hcursor],eax xor ebx, ebx mov [eax+CURSOR.magic], 'CURS' mov [eax+CURSOR.destroy], destroy_cursor mov [eax+CURSOR.hot_x], ebx mov [eax+CURSOR.hot_y], ebx call video_alloc mov edi, [.hcursor] mov [edi+CURSOR.base], eax mov esi, [.src] mov ebx, [.flags] cmp bx, LOAD_INDIRECT je .indirect movzx ecx, word [esi+10] movzx edx, word [esi+12] mov [edi+CURSOR.hot_x], ecx mov [edi+CURSOR.hot_y], edx stdcall ati_init_cursor, eax, esi mov eax, [.hcursor] .fail: add esp, 12 ret .indirect: shr ebx, 16 movzx ecx, bh movzx edx, bl mov [edi+CURSOR.hot_x], ecx mov [edi+CURSOR.hot_y], edx mov edi, eax mov ebx, eax mov ecx, 64*64 xor eax,eax cld rep stosd mov edi, ebx mov esi, [.src] mov ebx, 32 cld @@: mov ecx, 32 rep movsd add edi, 128 dec ebx jnz @B mov eax, [.hcursor] add esp, 12 ret align 4 destroy_cursor: push eax mov eax, [eax+CURSOR.base] call video_free pop eax call DestroyObject ret align 4 proc ati_init_cursor stdcall, dst:dword, src:dword locals rBase dd ? pQuad dd ? pBits dd ? pAnd dd ? width dd ? height dd ? counter dd ? endl mov esi, [src] add esi,[esi+18] mov eax,esi cmp [esi+BI.biBitCount], 24 je .img_24 cmp [esi+BI.biBitCount], 8 je .img_8 cmp [esi+BI.biBitCount], 4 je .img_4 .img_2: add eax, [esi] mov [pQuad],eax add eax,8 mov [pBits],eax add eax, 128 mov [pAnd],eax mov eax,[esi+4] mov [width],eax mov ebx,[esi+8] shr ebx,1 mov [height],ebx mov edi, pCursor add edi, 32*31*4 mov [rBase],edi mov esi,[pQuad] .l21: mov ebx, [pBits] mov ebx, [ebx] bswap ebx mov eax, [pAnd] mov eax, [eax] bswap eax mov [counter], 32 @@: xor edx, edx shl eax,1 setc dl dec edx xor ecx, ecx shl ebx,1 setc cl mov ecx, [esi+ecx*4] and ecx, edx and edx, 0xFF000000 or edx, ecx mov [edi], edx add edi, 4 dec [counter] jnz @B add [pBits], 4 add [pAnd], 4 mov edi,[rBase] sub edi,128 mov [rBase],edi sub [height],1 jnz .l21 jmp .copy .img_4: add eax, [esi] mov [pQuad],eax add eax,64 mov [pBits],eax add eax, 0x200 mov [pAnd],eax mov eax,[esi+4] mov [width],eax mov ebx,[esi+8] shr ebx,1 mov [height],ebx mov edi, pCursor add edi, 32*31*4 mov [rBase],edi mov esi,[pQuad] mov ebx, [pBits] .l4: mov eax, [pAnd] mov eax, [eax] bswap eax mov [counter], 16 @@: xor edx, edx shl eax,1 setc dl dec edx movzx ecx, byte [ebx] and cl, 0xF0 shr ecx, 2 mov ecx, [esi+ecx] and ecx, edx and edx, 0xFF000000 or edx, ecx mov [edi], edx xor edx, edx shl eax,1 setc dl dec edx movzx ecx, byte [ebx] and cl, 0x0F mov ecx, [esi+ecx*4] and ecx, edx and edx, 0xFF000000 or edx, ecx mov [edi+4], edx inc ebx add edi, 8 dec [counter] jnz @B add [pAnd], 4 mov edi,[rBase] sub edi,128 mov [rBase],edi sub [height],1 jnz .l4 jmp .copy .img_8: add eax, [esi] mov [pQuad],eax add eax,1024 mov [pBits],eax add eax, 1024 mov [pAnd],eax mov eax,[esi+4] mov [width],eax mov ebx,[esi+8] shr ebx,1 mov [height],ebx mov edi, pCursor add edi, 32*31*4 mov [rBase],edi mov esi,[pQuad] mov ebx, [pBits] .l81: mov eax, [pAnd] mov eax, [eax] bswap eax mov [counter], 32 @@: xor edx, edx shl eax,1 setc dl dec edx movzx ecx, byte [ebx] mov ecx, [esi+ecx*4] and ecx, edx and edx, 0xFF000000 or edx, ecx mov [edi], edx inc ebx add edi, 4 dec [counter] jnz @B add [pAnd], 4 mov edi,[rBase] sub edi,128 mov [rBase],edi sub [height],1 jnz .l81 jmp .copy .img_24: add eax, [esi] mov [pQuad],eax add eax, 0xC00 mov [pAnd],eax mov eax,[esi+BI.biWidth] mov [width],eax mov ebx,[esi+BI.biHeight] shr ebx,1 mov [height],ebx mov edi, pCursor add edi, 32*31*4 mov [rBase],edi mov esi,[pAnd] mov ebx, [pQuad] .row_24: mov eax, [esi] bswap eax mov [counter], 32 @@: xor edx, edx shl eax,1 setc dl dec edx mov ecx, [ebx] and ecx, 0x00FFFFFF and ecx, edx and edx, 0xFF000000 or edx, ecx mov [edi], edx add ebx, 3 add edi, 4 dec [counter] jnz @B add esi, 4 mov edi,[rBase] sub edi,128 mov [rBase],edi sub [height],1 jnz .row_24 .copy: mov edi, [dst] mov ecx, 64*64 xor eax,eax rep stosd mov esi, pCursor mov edi, [dst] mov ebx, 32 cld @@: mov ecx, 32 rep movsd add edi, 128 dec ebx jnz @B ret endp align 4 proc engFlush mov edi, [ati_io] mov eax, [edi+RD_RB2D_DSTCACHE_CTLSTAT] or eax,RD_RB2D_DC_FLUSH_ALL mov [edi+RD_RB2D_DSTCACHE_CTLSTAT],eax mov ecx, RD_TIMEOUT @@: mov eax,[edi+RD_RB2D_DSTCACHE_CTLSTAT] and eax, RD_RB2D_DC_BUSY jz .exit sub ecx,1 jnz @B .exit: ret endp align 4 engWaitForFifo: cnt equ bp+8 push ebp mov ebp, esp mov edi, [ati_io] mov ecx, RD_TIMEOUT @@: mov eax, [edi+RD_RBBM_STATUS] and eax, RD_RBBM_FIFOCNT_MASK cmp eax, [ebp+8] jae .exit sub ecx,1 jmp @B .exit: leave ret 4 align 4 proc engWaitForIdle push dword 64 call engWaitForFifo mov edi, [ati_io] mov ecx ,RD_TIMEOUT @@: mov eax, [edi+RD_RBBM_STATUS] and eax,RD_RBBM_ACTIVE jz .exit sub ecx,1 jnz @B .exit: call engFlush ret endp align 4 proc engRestore ; push dword 1 ; call engWaitForFifo ; mov dword [MMIO+RD_RB2D_DSTCACHE_MODE], 0 push dword 3 call engWaitForFifo mov edi, [ati_io] mov eax, [edi+RD_DISPLAY_BASE_ADDR] shr eax, 10d or eax,(64d shl 22d) mov [edi+RD_DEFAULT_OFFSET],eax mov [edi+RD_SRC_PITCH_OFFSET],eax mov [edi+RD_DST_PITCH_OFFSET],eax push dword 1 call engWaitForFifo mov edi, [ati_io] mov eax, [edi+RD_DP_DATATYPE] btr eax, 29d mov [edi+RD_DP_DATATYPE],eax push dword 1 call engWaitForFifo mov edi, [ati_io] mov dword [edi+RD_DEFAULT_SC_BOTTOM_RIGHT],\ (RD_DEFAULT_SC_RIGHT_MAX or RD_DEFAULT_SC_BOTTOM_MAX) push dword 1 call engWaitForFifo mov edi, [ati_io] mov dword [edi+RD_DP_GUI_MASTER_CNTL],\ (RD_GMC_BRUSH_SOLID_COLOR or \ RD_GMC_SRC_DATATYPE_COLOR or \ (6 shl RD_GMC_DST_DATATYPE_SHIFT) or \ RD_GMC_CLR_CMP_CNTL_DIS or \ RD_ROP3_P or \ RD_GMC_WR_MSK_DIS) push dword 7 call engWaitForFifo mov edi, [ati_io] mov dword [edi+RD_DST_LINE_START],0 mov dword [edi+RD_DST_LINE_END], 0 mov dword [edi+RD_DP_BRUSH_FRGD_CLR], 808000ffh mov dword [edi+RD_DP_BRUSH_BKGD_CLR], 002020ffh mov dword [edi+RD_DP_SRC_FRGD_CLR], 808000ffh mov dword [edi+RD_DP_SRC_BKGD_CLR], 004000ffh mov dword [edi+RD_DP_WRITE_MASK],0ffffffffh call engWaitForIdle ret endp align 4 engSetupSolidFill: push ebp mov ebp, esp push dword 3 call engWaitForFifo wrr RD_DP_GUI_MASTER_CNTL, cmdSolidFill mov eax, [ebp+8] wrr RD_DP_BRUSH_FRGD_CLR,eax mov edi, [ati_io] mov dword [edi+RD_DP_CNTL],(RD_DST_X_LEFT_TO_RIGHT or RD_DST_Y_TOP_TO_BOTTOM) leave ret 4 align 4 drvSolidFill: ;x:word,y:word,w:word,h:word,color:dword push ebp mov ebp, esp x equ ebp+8 y equ ebp+12 w equ ebp+16 h equ ebp+20 color equ ebp+24 push dword [ebp+24] call engSetupSolidFill push dword 2 call engWaitForFifo mov edi, [ati_io] mov eax, [y] mov ebx, [x] shl eax,16 or eax, ebx mov ecx, [w] mov edx, [h] shl ecx,16 or ecx, edx mov [edi+RD_DST_Y_X], eax mov [edi+RD_DST_WIDTH_HEIGHT], ecx call engFlush leave ret 20 align 4 devices dd (R8500 shl 16)+VID_ATI dd (R9000 shl 16)+VID_ATI dd (R9200 shl 16)+VID_ATI dd (R9500 shl 16)+VID_ATI dd (R9500P shl 16)+VID_ATI dd (R9550 shl 16)+VID_ATI dd (R9600 shl 16)+VID_ATI dd (R9600XT shl 16)+VID_ATI dd (R9700P shl 16)+VID_ATI dd (R9800 shl 16)+VID_ATI dd (R9800P shl 16)+VID_ATI dd (R9800XT shl 16)+VID_ATI dd 0 ;terminator version dd 0x00040004 sz_ati_srv db 'HWCURSOR',0 msgInit db 'detect hardware...',13,10,0 msgPCI db 'PCI accsess not supported',13,10,0 msgFail db 'device not found',13,10,0 msg_neg db 'neg ecx',13,10,0 buff db 8 dup(0) db 13,10, 0 section '.data' data readable writable align 16 pCursor db 4096 dup(?) cursor_map rd 2 cursor_start rd 1 cursor_end rd 1 bus dd ? devfn dd ? ati_io dd ?