dragon-nx32: first cut at adding draw/read/write methods
authorAlan Cox <alan@linux.intel.com>
Sun, 4 Oct 2015 21:16:02 +0000 (22:16 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 4 Oct 2015 21:16:02 +0000 (22:16 +0100)
Strictly speaking we don't need them, but this probably won't be true on all
the 6809 variants (eg COCO3) so we should support them to make portable code
easier. It's not as if they are very much code space.

Kernel/platform-dragon-nx32/devtty.c
Kernel/platform-dragon-nx32/devtty.h
Kernel/platform-dragon-nx32/video.s

index ebbba43..b564319 100644 (file)
@@ -311,6 +311,45 @@ static uint8_t piabits[] = { 0xF0, 0xF8, 0xE0, 0xE8};
 #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
@@ -320,11 +359,16 @@ int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
 {
        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) {
@@ -341,6 +385,22 @@ int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
 //             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;
 }
index 2d6f873..89b1ac0 100644 (file)
@@ -9,4 +9,8 @@ extern uint8_t shiftkeyboard[8][7];
 
 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
index a4b8646..da68bdd 100644 (file)
@@ -9,6 +9,11 @@
        .globl _clear_lines
        .globl _cursor_on
        .globl _cursor_off
+
+       .globl _video_read
+       .globl _video_write
+       .globl _video_cmd
+
        ;
        ; Imports
        ;
@@ -329,9 +334,88 @@ _cursor_off:
        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