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 */ 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 /*****************************************************************************/ 25 static __inline unsigned char get8(volatile unsigned char *addr) 26 { 27 return *addr; 28 } 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); 40 } 41 /*****************************************************************************/ 42 /* 43 * bpp must be bytes per pixel, not bits! 44 */ 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 */ 59 void et6000aclWaitIdle(void) { 60 while ((get8(mmRegs+0x36) & 0x02) == 0x02); 61 } 62 /*****************************************************************************/ 63 /* 64 * Wait until ACL queue becomes not full. 65 */ 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 */ 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 */ 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