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