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