1 #include "ite.h" 2 #if NITE > 0 3 4 #include "param.h" 5 #include "conf.h" 6 #include "proc.h" 7 #include "ioctl.h" 8 #include "tty.h" 9 #include "systm.h" 10 11 #include "itevar.h" 12 13 #include "machine/cpu.h" 14 15 /* XXX */ 16 #include "grfioctl.h" 17 #include "grfvar.h" 18 #include "grf_rtreg.h" 19 20 void retina_init(struct ite_softc *ip) 21 { 22 struct MonDef *md; 23 24 if (ip->grf == 0) 25 ip->grf = &grf_softc[ip - ite_softc]; 26 27 ip->priv = ip->grf->g_data; 28 md = (struct MonDef *) ip->priv; 29 30 ip->cols = md->TX; 31 ip->rows = md->TY; 32 } 33 34 35 void retina_cursor(struct ite_softc *ip, int flag) 36 { 37 volatile u_char *ba = ip->grf->g_regkva; 38 39 if (flag == ERASE_CURSOR) 40 { 41 /* disable cursor */ 42 WCrt (ba, CRT_ID_CURSOR_START, RCrt (ba, CRT_ID_CURSOR_START) | 0x20); 43 } 44 else 45 { 46 int pos = ip->curx + ip->cury * ip->cols; 47 48 /* make sure to enable cursor */ 49 WCrt (ba, CRT_ID_CURSOR_START, RCrt (ba, CRT_ID_CURSOR_START) & ~0x20); 50 51 /* and position it */ 52 WCrt (ba, CRT_ID_CURSOR_LOC_HIGH, (u_char) (pos >> 8)); 53 WCrt (ba, CRT_ID_CURSOR_LOC_LOW, (u_char) pos); 54 55 ip->cursorx = ip->curx; 56 ip->cursory = ip->cury; 57 } 58 } 59 60 61 62 static void screen_up (struct ite_softc *ip, int top, int bottom, int lines) 63 { 64 volatile u_char * ba = ip->grf->g_regkva; 65 volatile u_char * fb = ip->grf->g_fbkva; 66 const struct MonDef * md = (struct MonDef *) ip->priv; 67 68 /* do some bounds-checking here.. */ 69 if (top >= bottom) 70 return; 71 72 if (top + lines >= bottom) 73 { 74 retina_clear (ip, top, 0, bottom - top, ip->cols); 75 return; 76 } 77 78 79 /* the trick here is to use a feature of the NCR chip. It can 80 optimize data access in various read/write modes. One of 81 the modes is able to read/write from/to different zones. 82 83 Thus, by setting the read-offset to lineN, and the write-offset 84 to line0, we just cause read/write cycles for all characters 85 up to the last line, and have the chip transfer the data. The 86 `addqb' are the cheapest way to cause read/write cycles (DONT 87 use `tas' on the Amiga!), their results are completely ignored 88 by the NCR chip, it just replicates what it just read. */ 89 90 /* write to primary, read from secondary */ 91 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 ); 92 /* clear extended chain4 mode */ 93 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02); 94 95 /* set write mode 1, "[...] data in the read latches is written 96 to memory during CPU memory write cycles. [...]" */ 97 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1); 98 99 { 100 /* write to line TOP */ 101 long toploc = top * (md->TX / 16); 102 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, ((unsigned char)toploc)); 103 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, ((unsigned char)(toploc >> 8))); 104 } 105 { 106 /* read from line TOP + LINES */ 107 long fromloc = (top+lines) * (md->TX / 16); 108 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, ((unsigned char)fromloc)) ; 109 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, ((unsigned char)(fromloc >> 8))) ; 110 } 111 { 112 unsigned char * p = (unsigned char *) fb; 113 /* transfer all characters but LINES lines, unroll by 16 */ 114 short x = (1 + bottom - (top + lines)) * (md->TX / 16) - 1; 115 do { 116 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 117 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 118 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 119 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 120 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 121 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 122 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 123 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 124 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 125 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 126 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 127 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 128 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 129 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 130 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 131 asm volatile("addqb #1,%0@+" : "=a" (p) : "0" (p)); 132 } while (x--); 133 } 134 135 /* reset to default values */ 136 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0); 137 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0); 138 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0); 139 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0); 140 /* write mode 0 */ 141 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0); 142 /* extended chain4 enable */ 143 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 144 /* read/write to primary on A0, secondary on B0 */ 145 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0x40 ); 146 147 148 /* fill the free lines with spaces */ 149 150 { /* feed latches with value */ 151 unsigned short * f = (unsigned short *) fb; 152 153 f += (1 + bottom - lines) * md->TX * 2; 154 *f = 0x2010; 155 { 156 volatile unsigned short dummy = *((volatile unsigned short *)f); 157 } 158 } 159 160 /* clear extended chain4 mode */ 161 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02); 162 /* set write mode 1, "[...] data in the read latches is written 163 to memory during CPU memory write cycles. [...]" */ 164 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1); 165 166 { 167 unsigned long * p = (unsigned long *) fb; 168 short x = (lines * (md->TX/16)) - 1; 169 const unsigned long dummyval = 0; 170 171 p += (1 + bottom - lines) * (md->TX/4); 172 173 do { 174 *p++ = dummyval; 175 *p++ = dummyval; 176 *p++ = dummyval; 177 *p++ = dummyval; 178 } while (x--); 179 } 180 181 /* write mode 0 */ 182 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0); 183 /* extended chain4 enable */ 184 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 185 186 }; 187 188 static void screen_down (struct ite_softc *ip, int top, int bottom, int lines) 189 { 190 volatile u_char * ba = ip->grf->g_regkva; 191 volatile u_char * fb = ip->grf->g_fbkva; 192 const struct MonDef * md = (struct MonDef *) ip->priv; 193 194 /* do some bounds-checking here.. */ 195 if (top >= bottom) 196 return; 197 198 if (top + lines >= bottom) 199 { 200 retina_clear (ip, top, 0, bottom - top, ip->cols); 201 return; 202 } 203 204 /* see screen_up() for explanation of chip-tricks */ 205 206 /* write to primary, read from secondary */ 207 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0 ); 208 /* clear extended chain4 mode */ 209 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02); 210 211 /* set write mode 1, "[...] data in the read latches is written 212 to memory during CPU memory write cycles. [...]" */ 213 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1); 214 215 { 216 /* write to line TOP + LINES */ 217 long toloc = (top + lines) * (md->TX / 16); 218 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, ((unsigned char)toloc)); 219 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, ((unsigned char)(toloc >> 8))); 220 } 221 { 222 /* read from line TOP */ 223 long fromloc = top * (md->TX / 16); 224 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, ((unsigned char)fromloc)); 225 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, ((unsigned char)(fromloc >> 8))) ; 226 } 227 228 { 229 unsigned char * p = (unsigned char *) fb; 230 short x = (1 + bottom - (top + lines)) * (md->TX / 16) - 1; 231 p += (1 + bottom - (top + lines)) * md->TX; 232 do { 233 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 234 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 235 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 236 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 237 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 238 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 239 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 240 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 241 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 242 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 243 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 244 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 245 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 246 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 247 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 248 asm volatile("addqb #1,%0@-" : "=a" (p) : "0" (p)); 249 } while (x--); 250 } 251 252 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_HI, 0); 253 WSeq (ba, SEQ_ID_PRIM_HOST_OFF_LO, 0); 254 WSeq (ba, SEQ_ID_SEC_HOST_OFF_HI, 0); 255 WSeq (ba, SEQ_ID_SEC_HOST_OFF_LO, 0); 256 257 /* write mode 0 */ 258 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0); 259 /* extended chain4 enable */ 260 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 261 /* read/write to primary on A0, secondary on B0 */ 262 WSeq (ba, SEQ_ID_EXTENDED_MEM_ENA, (RSeq(ba, SEQ_ID_EXTENDED_MEM_ENA) & 0x1f) | 0x40 ); 263 264 /* fill the free lines with spaces */ 265 266 { /* feed latches with value */ 267 unsigned short * f = (unsigned short *) fb; 268 269 f += top * md->TX * 2; 270 *f = 0x2010; 271 { 272 volatile unsigned short dummy = *((volatile unsigned short *)f); 273 } 274 } 275 276 /* clear extended chain4 mode */ 277 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR, RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) & ~0x02); 278 /* set write mode 1, "[...] data in the read latches is written 279 to memory during CPU memory write cycles. [...]" */ 280 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 1); 281 282 { 283 unsigned long * p = (unsigned long *) fb; 284 short x = (lines * (md->TX/16)) - 1; 285 const unsigned long dummyval = 0; 286 287 p += top * (md->TX/4); 288 289 do { 290 *p++ = dummyval; 291 *p++ = dummyval; 292 *p++ = dummyval; 293 *p++ = dummyval; 294 } while (x--); 295 } 296 297 /* write mode 0 */ 298 WGfx (ba, GCT_ID_GRAPHICS_MODE, (RGfx(ba, GCT_ID_GRAPHICS_MODE) & 0xfc) | 0); 299 /* extended chain4 enable */ 300 WSeq (ba, SEQ_ID_EXT_VIDEO_ADDR , RSeq(ba, SEQ_ID_EXT_VIDEO_ADDR) | 0x02); 301 302 }; 303 304 void retina_deinit(struct ite_softc *ip) 305 { 306 ip->flags &= ~ITE_INITED; 307 } 308 309 310 void retina_putc(struct ite_softc *ip, int c, int dy, int dx, int mode) 311 { 312 volatile u_char * ba = ip->grf->g_regkva; 313 volatile u_char * fb = ip->grf->g_fbkva; 314 register u_char attr; 315 316 attr = (mode & ATTR_INV) ? 0x21 : 0x10; 317 if (mode & ATTR_UL) attr = 0x01; /* ???????? */ 318 if (mode & ATTR_BOLD) attr |= 0x08; 319 if (mode & ATTR_BLINK) attr |= 0x80; 320 321 fb += 4 * (dy * ip->cols + dx); 322 *fb++ = c; *fb = attr; 323 } 324 325 void retina_clear(struct ite_softc *ip, int sy, int sx, int h, int w) 326 { 327 volatile u_char * ba = ip->grf->g_regkva; 328 u_short * fb = (u_short *) ip->grf->g_fbkva; 329 short x; 330 const u_short fillval = 0x2010; 331 /* could probably be optimized just like the scrolling functions !! */ 332 fb += 2 * (sy * ip->cols + sx); 333 while (h--) 334 { 335 for (x = 2 * (w - 1); x >= 0; x -= 2) 336 fb[x] = fillval; 337 fb += 2 * ip->cols; 338 } 339 } 340 341 void retina_scroll(struct ite_softc *ip, int sy, int sx, int count, int dir) 342 { 343 volatile u_char * ba = ip->grf->g_regkva; 344 u_long * fb = (u_short *) ip->grf->g_fbkva; 345 register int height, dy, i; 346 347 retina_cursor(ip, ERASE_CURSOR); 348 349 if (dir == SCROLL_UP) 350 { 351 screen_up (ip, sy - count, ip->bottom_margin, count); 352 /* bcopy (fb + sy * ip->cols, fb + (sy - count) * ip->cols, 4 * (ip->bottom_margin - sy + 1) * ip->cols); */ 353 /* retina_clear (ip, ip->bottom_margin + 1 - count, 0, count, ip->cols); */ 354 } 355 else if (dir == SCROLL_DOWN) 356 { 357 screen_down (ip, sy, ip->bottom_margin, count); 358 /* bcopy (fb + sy * ip->cols, fb + (sy + count) * ip->cols, 4 * (ip->bottom_margin - sy - count + 1) * ip->cols); */ 359 /* retina_clear (ip, sy, 0, count, ip->cols); */ 360 } 361 else if (dir == SCROLL_RIGHT) 362 { 363 bcopy (fb + sx + sy * ip->cols, fb + sx + sy * ip->cols + count, 4 * (ip->cols - (sx + count))); 364 retina_clear (ip, sy, sx, 1, count); 365 } 366 else 367 { 368 bcopy (fb + sx + sy * ip->cols, fb + sx - count + sy * ip->cols, 4 * (ip->cols - sx)); 369 retina_clear (ip, sy, ip->cols - count, 1, count); 370 } 371 } 372 373 #endif 374 375 376 377