1/*
2	Copyright 2008 Haiku, Inc.  All rights reserved.
3	Distributed under the terms of the MIT license.
4
5	Authors:
6	Gerald Zajac 2008
7*/
8
9#include "accel.h"
10
11#include <unistd.h>
12
13
14// Macros for memory mapped I/O.
15//==============================
16
17#define INREG8(addr)		*((vuint8*)(gInfo.regs + addr))
18#define INREG16(addr)		*((vuint16*)(gInfo.regs + addr))
19#define INREG32(addr)		*((vuint32*)(gInfo.regs + addr))
20
21#define OUTREG8(addr, val)	*((vuint8*)(gInfo.regs + addr)) = val
22#define OUTREG16(addr, val)	*((vuint16*)(gInfo.regs + addr)) = val
23#define OUTREG32(addr, val)	*((vuint32*)(gInfo.regs + addr)) = val
24
25
26// Functions for PIO.
27//===================
28
29uint32 ReadPIO(uint32 addr, uint8 numBytes)
30{
31	S3GetSetPIO gsp;
32	gsp.magic = S3_PRIVATE_DATA_MAGIC;
33	gsp.offset = addr;
34	gsp.size = numBytes;
35	gsp.value = 0;
36
37	status_t result = ioctl(gInfo.deviceFileDesc, S3_GET_PIO, &gsp, sizeof(gsp));
38	if (result != B_OK)
39		TRACE("ReadPIO() failed, result = 0x%x\n", result);
40
41	return gsp.value;
42}
43
44
45void WritePIO(uint32 addr, uint8 numBytes, uint32 value)
46{
47	S3GetSetPIO gsp;
48	gsp.magic = S3_PRIVATE_DATA_MAGIC;
49	gsp.offset = addr;
50	gsp.size = numBytes;
51	gsp.value = value;
52
53	status_t result = ioctl(gInfo.deviceFileDesc, S3_SET_PIO, &gsp, sizeof(gsp));
54	if (result != B_OK)
55		TRACE("WritePIO() failed, result = 0x%x\n", result);
56}
57
58
59// Functions to read 8/16/32 bit registers.
60//=========================================
61
62uint8 ReadReg8(uint32 addr)
63{
64	if (gInfo.sharedInfo->chipType == S3_TRIO64)
65		return ReadPIO(addr, 1);
66
67	return INREG8(addr);
68}
69
70
71uint16 ReadReg16(uint32 addr)
72{
73	if (gInfo.sharedInfo->chipType == S3_TRIO64)
74		return ReadPIO(addr, 2);
75
76	return INREG16(addr);
77}
78
79
80uint32 ReadReg32(uint32 addr)
81{
82	if (gInfo.sharedInfo->chipType == S3_TRIO64)
83		return ReadPIO(addr, 4);
84
85	return INREG32(addr);
86}
87
88
89// Functions to write 8/16/32 bit registers.
90//=========================================
91
92void WriteReg8(uint32 addr, uint8 value)
93{
94	if (gInfo.sharedInfo->chipType == S3_TRIO64)
95		WritePIO(addr, 1, value);
96	else
97		OUTREG8(addr, value);
98}
99
100
101void WriteReg16(uint32 addr, uint16 value)
102{
103	if (gInfo.sharedInfo->chipType == S3_TRIO64)
104		WritePIO(addr, 2, value);
105	else
106		OUTREG16(addr, value);
107}
108
109
110void WriteReg32(uint32 addr, uint32 value)
111{
112	if (gInfo.sharedInfo->chipType == S3_TRIO64)
113		WritePIO(addr, 4, value);
114	else
115		OUTREG32(addr, value);
116}
117
118
119// Functions to read/write CRTC registers.
120//========================================
121
122uint8 ReadCrtcReg(uint8 index)
123{
124	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
125		WritePIO_8(0x3d4, index);
126		return ReadPIO_8(0x3d5);
127	}
128
129	OUTREG8(0x83d4, index);
130	return INREG8(0x83d5);
131}
132
133
134void WriteCrtcReg(uint8 index, uint8 value)
135{
136	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
137		WritePIO_8(0x3d4, index);
138		WritePIO_8(0x3d5, value);
139	} else {
140		OUTREG8(0x83d4, index);
141		OUTREG8(0x83d5, value);
142	}
143}
144
145
146void WriteCrtcReg(uint8 index, uint8 value, uint8 mask)
147{
148	// Write a value to a CRTC reg using a mask.  The mask selects the
149	// bits to be modified.
150
151	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
152		WritePIO_8(0x3d4, index);
153		WritePIO_8(0x3d5, (ReadPIO_8(0x3d5) & ~mask) | (value & mask));
154	} else {
155		OUTREG8(0x83d4, index);
156		OUTREG8(0x83d5, (INREG8(0x83d5) & ~mask) | (value & mask));
157	}
158}
159
160
161// Functions to read/write Sequence registers.
162//============================================
163
164uint8 ReadSeqReg(uint8 index)
165{
166	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
167		WritePIO_8(0x3c4, index);
168		return ReadPIO_8(0x3c5);
169	}
170
171	OUTREG8(0x83c4, index);
172	return INREG8(0x83c5);
173}
174
175
176void WriteSeqReg(uint8 index, uint8 value)
177{
178	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
179		WritePIO_8(0x3c4, index);
180		WritePIO_8(0x3c5, value);
181	} else {
182		OUTREG8(0x83c4, index);
183		OUTREG8(0x83c5, value);
184	}
185}
186
187
188void WriteSeqReg(uint8 index, uint8 value, uint8 mask)
189{
190	// Write a value to a Sequencer reg using a mask.  The mask selects the
191	// bits to be modified.
192
193	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
194		WritePIO_8(0x3c4, index);
195		WritePIO_8(0x3c5, (ReadPIO_8(0x3c5) & ~mask) | (value & mask));
196	} else {
197		OUTREG8(0x83c4, index);
198		OUTREG8(0x83c5, (INREG8(0x83c5) & ~mask) | (value & mask));
199	}
200}
201
202
203// Functions to read/write the misc output register.
204//==================================================
205
206uint8 ReadMiscOutReg()
207{
208	if (gInfo.sharedInfo->chipType == S3_TRIO64)
209		return ReadPIO_8(0x3cc);
210
211	return INREG8(0x83cc);
212}
213
214
215void WriteMiscOutReg(uint8 value)
216{
217	if (gInfo.sharedInfo->chipType == S3_TRIO64)
218		WritePIO_8(0x3c2, value);
219	else
220		OUTREG8(0x83c2, value);
221}
222
223
224void WriteIndexedColor(uint8 index, uint8 red, uint8 green, uint8 blue)
225{
226	// Write an indexed color.  Argument index is the index (0-255) of the
227	// color, and arguments red, green, & blue are the components of the color.
228
229	// Note that although the Trio64V+ chip supports MMIO in nearly all areas,
230	// it does not support MMIO for setting indexed colors;  thus, use PIO to
231	// set the indexed color.
232
233	if (gInfo.sharedInfo->chipType == S3_TRIO64
234			|| gInfo.sharedInfo->chipType == S3_TRIO64_VP) {
235		WritePIO_8(0x3c8, index);	// color index
236		WritePIO_8(0x3c9, red);
237		WritePIO_8(0x3c9, green);
238		WritePIO_8(0x3c9, blue);
239	} else {
240		OUTREG8(0x83c8, index);		// color index
241		OUTREG8(0x83c9, red);
242		OUTREG8(0x83c9, green);
243		OUTREG8(0x83c9, blue);
244	}
245}
246