#define pia1b ((volatile uint8_t *)0xFF22)
#define sam_v ((volatile uint8_t *)0xFFC0)
+static int gfx_draw_op(uarg_t arg, char *ptr, uint8_t *buf)
+{
+ int l;
+ int c = 8; /* 4 x uint16_t */
+ uint16_t *p = (uint16_t *)buf;
+ l = ugetw(ptr);
+ if (l < 6 || l > 512)
+ return EINVAL;
+ if (arg != GFXIOC_READ)
+ c = l;
+ if (uget(buf, ptr + 2, c))
+ return EFAULT;
+ switch(arg) {
+ case GFXIOC_DRAW:
+ /* TODO
+ if (draw_validate(ptr, l, 256, 192)) - or 128!
+ return EINVAL */
+ video_cmd(buf);
+ break;
+ case GFXIOC_WRITE:
+ case GFXIOC_READ:
+ if (l < 8)
+ return EINVAL;
+ l -= 8;
+ if (p[0] > 31 || p[1] > 191 || p[2] > 31 || p[3] > 191 ||
+ p[0] + p[2] > 32 || p[1] + p[3] > 192 ||
+ (p[2] * p[3]) > l)
+ return -EFAULT;
+ if (arg == GFXIOC_READ) {
+ video_read(buf);
+ if (uput(buf + 8, ptr, l))
+ return EFAULT;
+ return 0;
+ }
+ video_write(buf);
+ }
+ return 0;
+}
+
/*
* Start by just reporting the 256x192 mode which is memory mapped
* (it's effectively always in our address space). Should really
{
if (arg >> 8 != 0x03)
return vt_ioctl(minor, arg, ptr);
- if (arg == GFXIOC_GETINFO)
+ switch(arg) {
+ case GFXIOC_GETINFO:
return uput(&display[vmode], ptr, sizeof(struct display));
- if (arg == GFXIOC_MAP)
+ case GFXIOC_MAP:
return uput(&displaymap, ptr, sizeof(displaymap));
- if (arg == GFXIOC_GETMODE || arg == GFXIOC_SETMODE) {
+ case GFXIOC_UNMAP:
+ return 0;
+ case GFXIOC_GETMODE:
+ case GFXIOC_SETMODE:
+ {
uint8_t m = ugetc(ptr);
// uint8_t b;
if (m > 3) {
// sam_v[(b & 4)?5:4] = 0;
return 0;
}
- udata.u_error = ENOTTY;
+ case GFXIOC_DRAW:
+ case GFXIOC_READ:
+ case GFXIOC_WRITE:
+ {
+ uint8_t *tmp;
+ int err;
+
+ tmp = (uint8_t *)tmpbuf();
+ err = gfx_draw_op(arg, ptr, tmp);
+ brelse((bufptr) tmp);
+ if (err) {
+ udata.u_error = err;
+ err = -1;
+ }
+ return err;
+ }
+ }
return -1;
}
extern int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr);
+extern void video_cmd(uint8_t *ptr);
+extern void video_read(uint8_t *ptr);
+extern void video_write(uint8_t *ptr);
+
#endif
.globl _clear_lines
.globl _cursor_on
.globl _cursor_off
+
+ .globl _video_read
+ .globl _video_write
+ .globl _video_cmd
+
;
; Imports
;
com 224,x
nocursor:
rts
+;
+; These routines wortk in both 256x192x2 and 128x192x4 modes
+; because everything in the X plane is bytewide.
+;
+_video_write:
+ pshs u
+ bsr vidptr
+ tfr x,y ; So we can use y to get at the w/h
+ leax 4,x ; Move on to data space
+vwnext:
+ lda 2,y
+ pshs u
+vwline:
+ ldb ,x+
+ stb ,u+
+ deca
+ bne vwline
+ puls u
+ leau 32,u
+ dec ,y
+ bne vwnext
+ puls u,pc
+;
+; Find the address we need on a pixel row basis
+;
+vidptr:
+ ldu #VIDEO_BASE
+ ldd ,x++ ; Y into B
+ lda #32
+ mul
+ leau d,u
+ ldd ,x++ ; X
+ leau d,u
+ rts
+;
+; FIXME - fold read/write into one self modifier
+;
+_video_read:
+ pshs u
+ bsr vidptr
+ tfr x,y ; So we can use y to get at the w/h
+ leax 4,x ; Move on to data space
+vrnext:
+ lda 2,y ; a counts our copy along the scan line
+ pshs u
+vrline:
+ ldb ,u+ ; b does our data
+ stb ,x+
+ deca
+ bne vrline
+ puls u ; step down a line
+ leau 32,u
+ dec ,y ; use the buffer directly for line count
+ bne vrnext
+ puls u,pc ; and done
+
+_video_cmd:
+ pshs u
+ bsr vidptr ; u now points to the screen
+nextline:
+ pshs u ; save it for the next line
+nextop:
+ ldb ,x+ ; op code, 0 = end of line
+ beq endline
+oploop:
+ lda ,u ; do one screen byte
+ anda ,x
+ eora 1,x
+ sta ,u+
+ decb
+ bne oploop ; keep going for run
+ leax 2,x
+ bra nextop ; next triplet
+endline:
+ puls u ; get position back
+ leau 32,u ; down one scan line
+ ldb ,x+ ; get next op - 0,0 means end and done
+ bne oploop
+ puls u,pc
.area .data
cursor_save:
.dw 0
_vtrow:
- .db 0
\ No newline at end of file
+ .db 0