1 /*****************************************************************************\
2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
4 \*****************************************************************************/
5
6 #include "GlobalData.h"
7 #include "generic.h"
8
9
10 /*****************************************************************************/
11 /*
12 * Set bits in a byte pointed by addr; mask must contain 0s at the bits
13 * positions to be set and must contain 1s at all other bits; val must
14 * contain the values of bits to be set.
15 */
set8(volatile unsigned char * addr,unsigned char mask,unsigned char val)16 static __inline void set8(volatile unsigned char *addr, unsigned char mask,
17 unsigned char val)
18 {
19 if (mask == 0)
20 *addr = val;
21 else
22 *addr = (*addr & mask) | (val & ~mask);
23 }
24 /*****************************************************************************/
get8(volatile unsigned char * addr)25 static __inline unsigned char get8(volatile unsigned char *addr)
26 {
27 return *addr;
28 }
29 /*****************************************************************************/
et6000aclTerminate(void)30 static __inline void et6000aclTerminate(void) {
31 set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */
32 et6000aclWaitIdle();
33 set8(mmRegs+0x30, 0, 0x00);
34 set8(mmRegs+0x30, 0, 0x01);
35 et6000aclWaitIdle();
36 set8(mmRegs+0x30, 0, 0x00);
37 set8(mmRegs+0x30, 0, 0x10);
38 et6000aclWaitIdle();
39 set8(mmRegs+0x30, 0, 0x00);
40 }
41 /*****************************************************************************/
42 /*
43 * bpp must be bytes per pixel, not bits!
44 */
et6000aclInit(uint8 bpp)45 void et6000aclInit(uint8 bpp) {
46
47 et6000aclTerminate();
48
49 set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */
50 set8(mmRegs+0x32, 0x99, 0x00); /* maximize the performance */
51 set8(mmRegs+0x8e, 0xcf, (bpp - 1) << 4); /* set pixel color depth */
52 set8(mmRegs+0x91, 0x80, 0x00); /* maximize the performance */
53 set8(mmRegs+0x9d, 0x00, 0x00); /* maximize the performance */
54 }
55 /*****************************************************************************/
56 /*
57 * Wait until ACL becomes idle.
58 */
et6000aclWaitIdle(void)59 void et6000aclWaitIdle(void) {
60 while ((get8(mmRegs+0x36) & 0x02) == 0x02);
61 }
62 /*****************************************************************************/
63 /*
64 * Wait until ACL queue becomes not full.
65 */
et6000aclWaitQueueNotFull(void)66 static __inline void et6000aclWaitQueueNotFull(void) {
67 while ((get8(mmRegs+0x36) & 0x01) == 0x01);
68 }
69 /*****************************************************************************/
70 /*
71 * Move the specified list of rectangular regions from one location in
72 * the frame buffer to another in the order they are specified in the
73 * blit_params *list. The list is uint32 count elements in length.
74 */
SCREEN_TO_SCREEN_BLIT(engine_token * et,blit_params * list,uint32 count)75 void SCREEN_TO_SCREEN_BLIT(engine_token *et,
76 blit_params *list,
77 uint32 count)
78 {
79 uint16 screenWidth = si->dm.virtual_width;
80 uint8 bpp = si->bytesPerPixel;
81 uint8 bltDir;
82 uint16 src_left, src_top, dest_left, dest_top, width, height;
83 uint32 srcAddr = 0, destAddr = 0;
84
85 et6000aclWaitQueueNotFull();
86
87 set8(mmRegs+0x92, 0x80, 0x77); /* no source wrap */
88 set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
89 set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
90
91 /* Set the source Y offset */
92 *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
93
94 /* Set the destination Y offset */
95 *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
96
97 while(count--) {
98 src_left = list->src_left;
99 src_top = list->src_top;
100 dest_left = list->dest_left;
101 dest_top = list->dest_top;
102 width = list->width;
103 height = list->height;
104
105 et6000aclWaitQueueNotFull();
106
107 /* Set the direction and opcode(BitBLT) register */
108 bltDir = 0x00;
109 if (src_left < dest_left) bltDir |= 0x01;
110 if (src_top < dest_top) bltDir |= 0x02;
111 set8(mmRegs+0x8f, 0x3c, bltDir);
112
113 /* Set the X count register */
114 *((vuint16 *)(mmRegs+0x98)) = (width + 1) * bpp - 1;
115
116 /* Set the Y count register */
117 *((vuint16 *)(mmRegs+0x9a)) = height;
118
119 switch (bltDir & 0x03) {
120 case 0x00:
121 srcAddr = (src_top * screenWidth + src_left) * bpp;
122 destAddr = (dest_top * screenWidth + dest_left) * bpp;
123 break;
124
125 case 0x01:
126 srcAddr = (src_top * screenWidth + src_left + width) * bpp + bpp-1;
127 destAddr = (dest_top * screenWidth + dest_left + width) * bpp + bpp-1;
128 break;
129
130 case 0x02:
131 srcAddr = ((src_top + height)*screenWidth + src_left) * bpp;
132 destAddr = ((dest_top + height)*screenWidth + dest_left) * bpp;
133 break;
134
135 case 0x03:
136 srcAddr = ((src_top + height)*screenWidth + src_left + width) * bpp + bpp-1;
137 destAddr = ((dest_top + height)*screenWidth + dest_left + width) * bpp + bpp-1;
138 break;
139 }
140
141 /* Set the source address */
142 *((vuint32 *)(mmRegs+0x84)) = srcAddr;
143
144 /*
145 * Set the destination address -
146 * this action starts the BitBLT operation.
147 */
148 *((vuint32 *)(mmRegs+0xa0)) = destAddr;
149
150 list++;
151 }
152
153 si->engine.count++;
154 }
155 /*****************************************************************************/
156 /*
157 * Fill the specified list of rectangular regions with the specified color.
158 * The list is uint32 count elements in length. The rectangular regions are
159 * inclusive. The uint32 color is specified in the same configuration and
160 * byte order as the current display_mode. All coordinates in the list of
161 * rectangles is guaranteed to have been clipped to the virtual limits of
162 * the display_mode.
163 */
FILL_RECTANGLE(engine_token * et,uint32 color,fill_rect_params * list,uint32 count)164 void FILL_RECTANGLE(engine_token *et,
165 uint32 color,
166 fill_rect_params *list,
167 uint32 count)
168 {
169 uint16 screenWidth = si->dm.virtual_width;
170 uint8 bpp = si->bytesPerPixel;
171 uint16 left, top, right, bottom;
172 uint32 srcAddr;
173 uint8 i;
174
175 /*
176 * Normally WaitQueueNotFull should be required & enough, but in reality
177 * this is somewhy sometimes not enough for pixel depth of 3 bytes.
178 */
179 if (bpp == 2)
180 et6000aclWaitQueueNotFull();
181 else
182 et6000aclWaitIdle();
183
184 /*
185 * We'll put the color at 4 bytes just after the framebuffer.
186 * The srcAddr must be 4 bytes aligned and is always for standard
187 * resolutions.
188 */
189 srcAddr = (uint32)si->framebuffer - (uint32)si->memory +
190 si->dm.virtual_width * si->dm.virtual_height * bpp;
191
192 switch(bpp) {
193 case 2:
194 set8(mmRegs+0x92, 0x80, 0x02); /* 4x1 source wrap */
195 for (i = 0; i < 2; i++) /* copy the color to source address */
196 ((vuint16 *)((uint32)si->memory + srcAddr))[i] = (uint16)color;
197 break;
198 case 3:
199 set8(mmRegs+0x92, 0x80, 0x0a); /* 3x1 source wrap */
200 for (i = 0; i < 3; i++) /* copy the color to source address */
201 ((vuint8 *)((uint32)si->memory + srcAddr))[i] = ((uint8 *)&color)[i];
202
203 break;
204 }
205
206 set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
207 set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
208
209 /* Set the source Y offset */
210 *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
211 /* Set the destination Y offset */
212 *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
213
214 /* Set the direction and opcode(trapezoid) register (primary edge) */
215 set8(mmRegs+0x8f, 0x18, 0x40);
216 /* Set the secondary edge register */
217 set8(mmRegs+0x93, 0x1a, 0x00);
218
219 /* Set the primary delta minor register */
220 *((vuint16 *)(mmRegs+0xac)) = 0;
221 /* Set the secondary delta minor register */
222 *((vuint16 *)(mmRegs+0xb4)) = 0;
223
224 while(count--) {
225 left = list->left;
226 top = list->top;
227 right = list->right;
228 bottom = list->bottom;
229
230 et6000aclWaitQueueNotFull();
231
232 /* Set the X count register */
233 *((vuint16 *)(mmRegs+0x98)) = (right-left+1)*bpp - 1;
234 /* Set the Y count register */
235 *((vuint16 *)(mmRegs+0x9a)) = bottom-top;
236
237 /* Set the primary delta major register */
238 *((vuint16 *)(mmRegs+0xae)) = bottom-top;
239
240 /* Set the secondary delta major register */
241 *((vuint16 *)(mmRegs+0xb6)) = bottom-top;
242
243 /* Set the source address */
244 *((vuint32 *)(mmRegs+0x84)) = srcAddr;
245
246 /*
247 * Set the destination address -
248 * this action starts the trapezoid operation.
249 */
250 *((vuint32 *)(mmRegs+0xa0)) = (top * screenWidth + left) * bpp;
251
252 list++;
253 }
254
255 si->engine.count++;
256 }
257 /*****************************************************************************/
258