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