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