#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <luna88k/dev/omrasops.h>
#include <machine/board.h>
#define OMFB_PLANEMASK BMAP_BMSEL
#define OMFB_ROPFUNC BMAP_FN
int om_copycols(void *, int, int, int, int);
int om_copyrows(void *, int, int, int num);
int om_erasecols(void *, int, int, int, uint32_t);
int om_eraserows(void *, int, int, uint32_t);
int om1_cursor(void *, int, int, int);
int om1_putchar(void *, int, int, u_int, uint32_t);
int om4_cursor(void *, int, int, int);
int om4_putchar(void *, int, int, u_int, uint32_t);
void setup_omrasops1(struct rasops_info *);
void setup_omrasops4(struct rasops_info *);
int om1_windowmove(struct rasops_info *, u_int16_t, u_int16_t, u_int16_t,
u_int16_t, u_int16_t, u_int16_t, int16_t, int16_t);
int om4_windowmove(struct rasops_info *, u_int16_t, u_int16_t, u_int16_t,
u_int16_t, u_int16_t, u_int16_t, int16_t, int16_t);
int rasops_pack_cattr(void *, int, int, int, uint32_t *);
int rasops_pack_mattr(void *, int, int, int, uint32_t *);
static int (*om_windowmove)(struct rasops_info *, u_int16_t, u_int16_t,
u_int16_t, u_int16_t, u_int16_t, u_int16_t, int16_t, int16_t);
extern struct wsscreen_descr omfb_stdscreen;
#define ALL1BITS (~0U)
#define ALL0BITS (0U)
#define BLITWIDTH (32)
#define ALIGNMASK (0x1f)
#define BYTESDONE (4)
int
om1_putchar(void *cookie, int row, int startcol, u_int uc, uint32_t attr)
{
struct rasops_info *ri = cookie;
u_int8_t *p;
int scanspan, startx, height, width, align, y;
u_int32_t lmask, rmask, glyph, inverse;
int i, fg, bg;
u_int8_t *fb;
scanspan = ri->ri_stride;
y = ri->ri_font->fontheight * row;
startx = ri->ri_font->fontwidth * startcol;
height = ri->ri_font->fontheight;
fb = (u_int8_t *)ri->ri_font->data +
(uc - ri->ri_font->firstchar) * ri->ri_fontscale;
ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
inverse = (bg != 0) ? ALL1BITS : ALL0BITS;
p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
align = startx & ALIGNMASK;
width = ri->ri_font->fontwidth + align;
lmask = ALL1BITS >> align;
rmask = ALL1BITS << (-width & ALIGNMASK);
if (width <= BLITWIDTH) {
lmask &= rmask;
while (height > 0) {
glyph = 0;
for (i = ri->ri_font->stride; i != 0; i--)
glyph = (glyph << 8) | *fb++;
glyph <<= (4 - ri->ri_font->stride) * NBBY;
glyph = (glyph >> align) ^ inverse;
*P0(p) = (*P0(p) & ~lmask) | (glyph & lmask);
p += scanspan;
height--;
}
} else {
u_int8_t *q = p;
u_int32_t lhalf, rhalf;
while (height > 0) {
glyph = 0;
for (i = ri->ri_font->stride; i != 0; i--)
glyph = (glyph << 8) | *fb++;
glyph <<= (4 - ri->ri_font->stride) * NBBY;
lhalf = (glyph >> align) ^ inverse;
*P0(p) = (*P0(p) & ~lmask) | (lhalf & lmask);
p += BYTESDONE;
rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
*P0(p) = (rhalf & rmask) | (*P0(p) & ~rmask);
p = (q += scanspan);
height--;
}
}
return 0;
}
int
om4_putchar(void *cookie, int row, int startcol, u_int uc, uint32_t attr)
{
struct rasops_info *ri = cookie;
u_int8_t *p;
int scanspan, startx, height, width, align, y;
u_int32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat;
u_int32_t fgmask0, fgmask1, fgmask2, fgmask3;
u_int32_t bgmask0, bgmask1, bgmask2, bgmask3;
int i, fg, bg;
u_int8_t *fb;
scanspan = ri->ri_stride;
y = ri->ri_font->fontheight * row;
startx = ri->ri_font->fontwidth * startcol;
height = ri->ri_font->fontheight;
fb = (u_int8_t *)ri->ri_font->data +
(uc - ri->ri_font->firstchar) * ri->ri_fontscale;
ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
fgmask0 = (fg & 0x01) ? ALL1BITS : ALL0BITS;
fgmask1 = (fg & 0x02) ? ALL1BITS : ALL0BITS;
fgmask2 = (fg & 0x04) ? ALL1BITS : ALL0BITS;
fgmask3 = (fg & 0x08) ? ALL1BITS : ALL0BITS;
bgmask0 = (bg & 0x01) ? ALL1BITS : ALL0BITS;
bgmask1 = (bg & 0x02) ? ALL1BITS : ALL0BITS;
bgmask2 = (bg & 0x04) ? ALL1BITS : ALL0BITS;
bgmask3 = (bg & 0x08) ? ALL1BITS : ALL0BITS;
p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
align = startx & ALIGNMASK;
width = ri->ri_font->fontwidth + align;
lmask = ALL1BITS >> align;
rmask = ALL1BITS << (-width & ALIGNMASK);
*(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;
if (width <= BLITWIDTH) {
lmask &= rmask;
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask;
while (height > 0) {
glyph = 0;
for (i = ri->ri_font->stride; i != 0; i--)
glyph = (glyph << 8) | *fb++;
glyph <<= (4 - ri->ri_font->stride) * NBBY;
glyph = (glyph >> align);
glyphbg = glyph ^ ALL1BITS;
fgpat = glyph & fgmask0;
bgpat = glyphbg & bgmask0;
*P0(p) = (fgpat | bgpat);
fgpat = glyph & fgmask1;
bgpat = glyphbg & bgmask1;
*P1(p) = (fgpat | bgpat);
fgpat = glyph & fgmask2;
bgpat = glyphbg & bgmask2;
*P2(p) = (fgpat | bgpat);
fgpat = glyph & fgmask3;
bgpat = glyphbg & bgmask3;
*P3(p) = (fgpat | bgpat);
p += scanspan;
height--;
}
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
} else {
u_int8_t *q = p;
u_int32_t lhalf, rhalf;
u_int32_t lhalfbg, rhalfbg;
while (height > 0) {
glyph = 0;
for (i = ri->ri_font->stride; i != 0; i--)
glyph = (glyph << 8) | *fb++;
glyph <<= (4 - ri->ri_font->stride) * NBBY;
lhalf = (glyph >> align);
lhalfbg = lhalf ^ ALL1BITS;
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH]
= lmask;
fgpat = lhalf & fgmask0;
bgpat = lhalfbg & bgmask0;
*P0(p) = (fgpat | bgpat);
fgpat = lhalf & fgmask1;
bgpat = lhalfbg & bgmask1;
*P1(p) = (fgpat | bgpat);
fgpat = lhalf & fgmask2;
bgpat = lhalfbg & bgmask2;
*P2(p) = (fgpat | bgpat);
fgpat = lhalf & fgmask3;
bgpat = lhalfbg & bgmask3;
*P3(p) = (fgpat | bgpat);
p += BYTESDONE;
rhalf = (glyph << (BLITWIDTH - align));
rhalfbg = rhalf ^ ALL1BITS;
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH]
= rmask;
fgpat = rhalf & fgmask0;
bgpat = rhalfbg & bgmask0;
*P0(p) = (fgpat | bgpat);
fgpat = rhalf & fgmask1;
bgpat = rhalfbg & bgmask1;
*P1(p) = (fgpat | bgpat);
fgpat = rhalf & fgmask2;
bgpat = rhalfbg & bgmask2;
*P2(p) = (fgpat | bgpat);
fgpat = rhalf & fgmask3;
bgpat = rhalfbg & bgmask3;
*P3(p) = (fgpat | bgpat);
p = (q += scanspan);
height--;
}
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
}
*(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;
return 0;
}
int
om_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
{
struct rasops_info *ri = cookie;
int fg, bg;
int snum, scol, srow;
ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
snum = num * ri->ri_font->fontwidth;
scol = col * ri->ri_font->fontwidth + ri->ri_xorigin;
srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
if ((*om_windowmove)(ri, scol, srow, scol, srow, snum,
ri->ri_font->fontheight, RR_CLEAR, 0xff ^ bg) != 0)
rasops_erasecols(cookie, row, col, num, attr);
return 0;
}
int
om_eraserows(void *cookie, int row, int num, uint32_t attr)
{
struct rasops_info *ri = cookie;
int fg, bg;
int srow, snum;
int rc;
ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
bg ^= 0xff;
if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
rc = (*om_windowmove)(ri, 0, 0, 0, 0, ri->ri_width,
ri->ri_height, RR_CLEAR, bg);
} else {
srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
snum = num * ri->ri_font->fontheight;
rc = (*om_windowmove)(ri, ri->ri_xorigin, srow, ri->ri_xorigin,
srow, ri->ri_emuwidth, snum, RR_CLEAR, bg);
}
if (rc != 0)
rasops_eraserows(cookie, row, num, attr);
return 0;
}
int
om_copyrows(void *cookie, int src, int dst, int n)
{
struct rasops_info *ri = cookie;
n *= ri->ri_font->fontheight;
src *= ri->ri_font->fontheight;
dst *= ri->ri_font->fontheight;
(*om_windowmove)(ri, ri->ri_xorigin, ri->ri_yorigin + src,
ri->ri_xorigin, ri->ri_yorigin + dst,
ri->ri_emuwidth, n, RR_COPY, 0xff);
return 0;
}
int
om_copycols(void *cookie, int row, int src, int dst, int n)
{
struct rasops_info *ri = cookie;
n *= ri->ri_font->fontwidth;
src *= ri->ri_font->fontwidth;
dst *= ri->ri_font->fontwidth;
row *= ri->ri_font->fontheight;
(*om_windowmove)(ri, ri->ri_xorigin + src, ri->ri_yorigin + row,
ri->ri_xorigin + dst, ri->ri_yorigin + row,
n, ri->ri_font->fontheight, RR_COPY, 0xff);
return 0;
}
int
om1_cursor(void *cookie, int on, int row, int col)
{
struct rasops_info *ri = cookie;
u_int8_t *p;
int scanspan, startx, height, width, align, y;
u_int32_t lmask, rmask, image;
if (!on) {
if ((ri->ri_flg & RI_CURSOR) == 0)
return 0;
row = ri->ri_crow;
col = ri->ri_ccol;
} else {
ri->ri_crow = row;
ri->ri_ccol = col;
}
scanspan = ri->ri_stride;
y = ri->ri_font->fontheight * row;
startx = ri->ri_font->fontwidth * col;
height = ri->ri_font->fontheight;
p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
align = startx & ALIGNMASK;
width = ri->ri_font->fontwidth + align;
lmask = ALL1BITS >> align;
rmask = ALL1BITS << (-width & ALIGNMASK);
if (width <= BLITWIDTH) {
lmask &= rmask;
while (height > 0) {
image = *P0(p);
*P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
p += scanspan;
height--;
}
} else {
u_int8_t *q = p;
while (height > 0) {
image = *P0(p);
*P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
p += BYTESDONE;
image = *P0(p);
*P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
p = (q += scanspan);
height--;
}
}
ri->ri_flg ^= RI_CURSOR;
return 0;
}
int
om4_cursor(void *cookie, int on, int row, int col)
{
struct rasops_info *ri = cookie;
u_int8_t *p;
int scanspan, startx, height, width, align, y;
u_int32_t lmask, rmask;
if (!on) {
if ((ri->ri_flg & RI_CURSOR) == 0)
return 0;
row = ri->ri_crow;
col = ri->ri_ccol;
} else {
ri->ri_crow = row;
ri->ri_ccol = col;
}
scanspan = ri->ri_stride;
y = ri->ri_font->fontheight * row;
startx = ri->ri_font->fontwidth * col;
height = ri->ri_font->fontheight;
p = (u_int8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
align = startx & ALIGNMASK;
width = ri->ri_font->fontwidth + align;
lmask = ALL1BITS >> align;
rmask = ALL1BITS << (-width & ALIGNMASK);
*(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;
if (width <= BLITWIDTH) {
lmask &= rmask;
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
while (height > 0) {
*W(p) = ALL1BITS;
p += scanspan;
height--;
}
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
} else {
u_int8_t *q = p;
while (height > 0) {
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask;
*W(p) = ALL1BITS;
p += BYTESDONE;
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask;
*W(p) = ALL1BITS;
p = (q += scanspan);
height--;
}
((volatile u_int32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS;
}
*(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;
ri->ri_flg ^= RI_CURSOR;
return 0;
}
void
setup_omrasops1(struct rasops_info *ri)
{
om_windowmove = om1_windowmove;
ri->ri_ops.cursor = om1_cursor;
ri->ri_ops.putchar = om1_putchar;
omfb_stdscreen.capabilities
= ri->ri_caps & ~WSSCREEN_UNDERLINE;
ri->ri_ops.pack_attr = rasops_pack_mattr;
}
void
setup_omrasops4(struct rasops_info *ri)
{
om_windowmove = om4_windowmove;
ri->ri_ops.cursor = om4_cursor;
ri->ri_ops.putchar = om4_putchar;
omfb_stdscreen.capabilities
= WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
ri->ri_ops.pack_attr = rasops_pack_cattr;
}