vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / accelerants / et6x00 / Acceleration.c
blobf0ee55c7906eee7ecb5ce45cc16fd113b37fb3d2
1 /*****************************************************************************\
2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
4 \*****************************************************************************/
6 #include "GlobalData.h"
7 #include "generic.h"
10 /*****************************************************************************/
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.
16 static __inline void set8(volatile unsigned char *addr, unsigned char mask,
17 unsigned char val)
19 if (mask == 0)
20 *addr = val;
21 else
22 *addr = (*addr & mask) | (val & ~mask);
24 /*****************************************************************************/
25 static __inline unsigned char get8(volatile unsigned char *addr)
27 return *addr;
29 /*****************************************************************************/
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);
41 /*****************************************************************************/
43 * bpp must be bytes per pixel, not bits!
45 void et6000aclInit(uint8 bpp) {
47 et6000aclTerminate();
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 */
55 /*****************************************************************************/
57 * Wait until ACL becomes idle.
59 void et6000aclWaitIdle(void) {
60 while ((get8(mmRegs+0x36) & 0x02) == 0x02);
62 /*****************************************************************************/
64 * Wait until ACL queue becomes not full.
66 static __inline void et6000aclWaitQueueNotFull(void) {
67 while ((get8(mmRegs+0x36) & 0x01) == 0x01);
69 /*****************************************************************************/
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.
75 void SCREEN_TO_SCREEN_BLIT(engine_token *et,
76 blit_params *list,
77 uint32 count)
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;
85 et6000aclWaitQueueNotFull();
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 */
91 /* Set the source Y offset */
92 *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1;
94 /* Set the destination Y offset */
95 *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1;
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;
105 et6000aclWaitQueueNotFull();
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);
113 /* Set the X count register */
114 *((vuint16 *)(mmRegs+0x98)) = (width + 1) * bpp - 1;
116 /* Set the Y count register */
117 *((vuint16 *)(mmRegs+0x9a)) = height;
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;
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;
130 case 0x02:
131 srcAddr = ((src_top + height)*screenWidth + src_left) * bpp;
132 destAddr = ((dest_top + height)*screenWidth + dest_left) * bpp;
133 break;
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;
141 /* Set the source address */
142 *((vuint32 *)(mmRegs+0x84)) = srcAddr;
145 * Set the destination address -
146 * this action starts the BitBLT operation.
148 *((vuint32 *)(mmRegs+0xa0)) = destAddr;
150 list++;
153 si->engine.count++;
155 /*****************************************************************************/
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.
164 void FILL_RECTANGLE(engine_token *et,
165 uint32 color,
166 fill_rect_params *list,
167 uint32 count)
169 uint16 screenWidth = si->dm.virtual_width;
170 uint8 bpp = si->bytesPerPixel;
171 uint16 left, top, right, bottom;
172 uint32 srcAddr;
173 uint8 i;
176 * Normally WaitQueueNotFull should be required & enough, but in reality
177 * this is somewhy sometimes not enough for pixel depth of 3 bytes.
179 if (bpp == 2)
180 et6000aclWaitQueueNotFull();
181 else
182 et6000aclWaitIdle();
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.
189 srcAddr = (uint32)si->framebuffer - (uint32)si->memory +
190 si->dm.virtual_width * si->dm.virtual_height * bpp;
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];
203 break;
206 set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */
207 set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */
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;
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);
219 /* Set the primary delta minor register */
220 *((vuint16 *)(mmRegs+0xac)) = 0;
221 /* Set the secondary delta minor register */
222 *((vuint16 *)(mmRegs+0xb4)) = 0;
224 while(count--) {
225 left = list->left;
226 top = list->top;
227 right = list->right;
228 bottom = list->bottom;
230 et6000aclWaitQueueNotFull();
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;
237 /* Set the primary delta major register */
238 *((vuint16 *)(mmRegs+0xae)) = bottom-top;
240 /* Set the secondary delta major register */
241 *((vuint16 *)(mmRegs+0xb6)) = bottom-top;
243 /* Set the source address */
244 *((vuint32 *)(mmRegs+0x84)) = srcAddr;
247 * Set the destination address -
248 * this action starts the trapezoid operation.
250 *((vuint32 *)(mmRegs+0xa0)) = (top * screenWidth + left) * bpp;
252 list++;
255 si->engine.count++;
257 /*****************************************************************************/