1/*
2	Haiku S3 Savage driver adapted from the X.org Savage driver.
3
4	Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
5	Copyright (c) 2003-2006, X.Org Foundation
6
7	Copyright 2007-2008 Haiku, Inc.  All rights reserved.
8	Distributed under the terms of the MIT license.
9
10	Authors:
11	Gerald Zajac 2006-2008
12*/
13
14
15#include "accel.h"
16#include "savage.h"
17
18
19
20// Certain HW cursor operations seem to require a delay to prevent lockups.
21
22static void
23WaitHSync(int n)
24{
25	while (n--) {
26		while (ReadReg8(SYSTEM_CONTROL_REG) & 0x01) {};
27		while ( ! ReadReg8(SYSTEM_CONTROL_REG) & 0x01) {};
28	}
29}
30
31
32void
33Savage_ShowCursor(bool bShow)
34{
35	// Turn cursor on/off.
36
37	if ( ! bShow && S3_SAVAGE4_SERIES(gInfo.sharedInfo->chipType))
38		WaitHSync(5);
39
40	WriteCrtcReg(0x45, bShow ? 0x01 : 0x00, 0x01);
41}
42
43
44void
45Savage_SetCursorPosition(int x, int y)
46{
47	SharedInfo& si = *gInfo.sharedInfo;
48
49	if (S3_SAVAGE4_SERIES(si.chipType))
50		WaitHSync(5);
51
52	// xOffset & yOffset are used for displaying partial cursors on screen edges.
53
54	uint8 xOffset = 0;
55	uint8 yOffset = 0;
56
57	if (x < 0) {
58		xOffset = (( -x) & 0xFE);
59		x = 0;
60	}
61
62	if (y < 0) {
63		yOffset = (( -y) & 0xFE);
64		y = 0;
65	}
66
67
68	// Note: when setting the cursor position, register 48 must be set last
69	// since setting register 48 activates the new cursor position.
70
71	WriteCrtcReg( 0x4e, xOffset );
72	WriteCrtcReg( 0x4f, yOffset );
73
74	WriteCrtcReg( 0x47, (x & 0xff) );
75	WriteCrtcReg( 0x46, (x & 0x0700) >> 8 );
76
77	WriteCrtcReg( 0x49, (y & 0xff) );
78	WriteCrtcReg( 0x48, (y & 0x0700) >> 8 );
79}
80
81
82bool
83Savage_LoadCursorImage(int width, int height, uint8* andMask, uint8* xorMask)
84{
85	SharedInfo& si = *gInfo.sharedInfo;
86
87	if (andMask == NULL || xorMask == NULL)
88		return false;
89
90	// Initialize the hardware cursor as completely transparent.
91
92	uint16* fbCursor16 = (uint16*)((addr_t)si.videoMemAddr + si.cursorOffset);
93
94	for (int i = 0; i < CURSOR_BYTES; i += 4) {
95		*fbCursor16++ = ~0;		// and bits
96		*fbCursor16++ = 0;		// xor bits
97	}
98
99	// Now load the AND & XOR masks for the cursor image into the cursor
100	// buffer.  Note that a particular bit in these masks will have the
101	// following effect upon the corresponding cursor pixel:
102	//	AND  XOR	Result
103	//	 0    0		 White pixel
104	//	 0    1		 Black pixel
105	//	 1    0		 Screen color (for transparency)
106	//	 1    1		 Reverse screen color to black or white
107
108	uint8* fbCursor = (uint8*)((addr_t)si.videoMemAddr + si.cursorOffset);
109
110	for (int row = 0; row < height; row++) {
111		for (int colByte = 0; colByte < width / 8; colByte++) {
112			fbCursor[row * 16 + colByte] = *andMask++;
113			fbCursor[row * 16 + colByte + 2] = *xorMask++;
114		}
115	}
116
117	if (S3_SAVAGE4_SERIES(si.chipType)) {
118
119		// Bug in Savage4 Rev B requires us to do an MMIO read after
120		// loading the cursor.
121
122		volatile unsigned int k = ALT_STATUS_WORD0;
123		(void)k++;	// Not to be optimised out
124	}
125
126	// Set cursor location in video memory.
127
128	WriteCrtcReg(0x4d, (0xff & si.cursorOffset / 1024));
129	WriteCrtcReg(0x4c, (0xff00 & si.cursorOffset / 1024) >> 8);
130
131	// Set the cursor colors which are black foreground and white background.
132
133	ReadCrtcReg(0x45);		// reset cursor color stack pointer
134	WriteCrtcReg(0x4a, 0);	// set foreground color stack low, mid, high bytes
135	WriteCrtcReg(0x4a, 0);
136	WriteCrtcReg(0x4a, 0);
137
138	ReadCrtcReg(0x45);		// reset cursor color stack pointer
139	WriteCrtcReg(0x4b, ~0);	// set background color stack low, mid, high bytes
140	WriteCrtcReg(0x4b, ~0);
141	WriteCrtcReg(0x4b, ~0);
142
143	return true;
144}
145