trs80: update devgfx test code
authorAlan Cox <alan@linux.intel.com>
Sat, 3 Oct 2015 10:03:03 +0000 (11:03 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 3 Oct 2015 10:03:03 +0000 (11:03 +0100)
Correct for 16bit co-ordinates
Add GFX_READ/WRITE test implementation

Kernel/platform-trs80/devgfx.c
Kernel/platform-trs80/trs80.s

index 603a4d5..07b9f90 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *     Graphics logic for the TRS80 graphics add on board
  *
- *     FIXME: GETPIXEL, direct raw I/O access, scrolling, rects and
- *     aligned blit are probably the basic set we should go for
+ *     FIXME: - turn the gfx on/off when we switch tty
+ *            - tie gfx to one tty and report EBUSY for the other on enable
  */
 
 #include <kernel.h>
@@ -12,6 +12,7 @@
 #include <devgfx.h>
 
 static const struct display trsdisplay = {
+  0,
   640, 240,
   1024, 256,
   1, 1,                /* Need adding to ioctls */
@@ -19,7 +20,7 @@ static const struct display trsdisplay = {
   HW_TRS80GFX,
   GFX_ENABLE|GFX_MAPPABLE|GFX_OFFSCREEN,       /* Can in theory do pans */
   32,
-  GFX_DRAW     /* FIXME: do GFX_READ */
+  GFX_DRAW|GFX_READ|GFX_WRITE
 };
 
 /* Assumes a Tandy board */
@@ -34,10 +35,49 @@ static const struct videomap trsmap = {
 
 __sfr __at 0x83 gfx_ctrl;
 
+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, 1024, 256))
+      return EINVAL */
+    video_cmd(buf);
+    break;
+  case GFXIOC_WRITE:
+  case GFXIOC_READ:
+    if (l < 8)
+      return EINVAL;
+    l -= 8;
+    if (p[0] > 128 || p[1] > 255 || p[2] > 128 || p[3] > 255 ||
+      p[0] + p[2] > 128 || p[1] + p[3] > 255 ||
+      (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;
+}
+
 int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
 {
   uint8_t *tmp;
-  uint16_t l;
+  int err;
 
   if (arg >> 8 != 0x03)
     return vt_ioctl(minor, arg, ptr);
@@ -57,25 +97,18 @@ int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
   case GFXIOC_MAP:
     return uput(&trsmap, ptr, sizeof(trsmap));
   case GFXIOC_DRAW:
+  case GFXIOC_READ:
+  case GFXIOC_WRITE:
     tmp = (uint8_t *)tmpbuf();
-    l = ugetw(ptr);
-    if (l < 2 || l > 512)
-      goto bad;
-    if (uget(tmp, ptr + 2, l))
-      goto bad2;
-    /* TODO
-    if (draw_validate(ptr, l, 1024, 256))
-      goto bad; */
-    video_cmd(tmp);
+    err = gfx_draw_op(arg, ptr, tmp);
     brelse((bufptr) tmp);
-    return 0;
+    if (err) {
+      udata.u_error = err;
+      err = -1;
+    }
+    return err;
   default:
     udata.u_error = EINVAL;
     return -1;
   }
-bad:
-  udata.u_error = EINVAL;
-bad2:
-  brelse((bufptr) tmp);
-  return -1;
 }
index 114ff6c..1719f1b 100644 (file)
@@ -19,6 +19,8 @@
 
            ; video
            .globl _video_cmd
+           .globl _video_read
+           .globl _video_write
 
             ; exported debugging tools
             .globl _trap_monitor
@@ -188,7 +190,10 @@ _video_cmd:
            push de
            ld e,(hl)                   ; X byte, Y line
            inc hl                      ; The hardware does the conversion
+           inc hl
            ld d,(hl)                   ; for us
+           inc hl                      ; skip high bytes
+           inc hl
            ld a, #0x43                 ; auto incremeent X on write only
            out (0x83), a               ; set the register up
 nextline:
@@ -214,9 +219,45 @@ oploop:
            inc hl
            jr nextop
 endline:    pop de
-           inc d               ; down a scan line (easy peasy)
+           inc d                       ; down a scan line (easy peasy)
            inc hl
            xor a
            cp (hl)             ; 0 0 = end (for blank lines just do 01 ff 00)
            jr nz, nextline
            ret
+
+_video_write:
+           ld a, #0xB3
+           ld (patch_io + 1), a        ; OTIR
+           ld a, #0x43
+video_do:
+           out (0x83), a               ; autoincrement on write
+           pop de
+           pop iy
+           push iy
+           push de
+           push iy
+           pop hl
+           ld de, #8
+           add hl, de                  ; Data start into HL
+           ld e, (iy)                  ; x
+           ld d, 2(iy)                 ; y
+next_rw:
+           ld c, #0x80
+           out (c), e                  ; x
+           inc c
+           out (c), d                  ; y
+           inc c                       ; to data
+           ld b, 4(iy)                 ; count of bytes per line
+patch_io:
+           otir                        ; wheee...
+           inc d                       ; next line
+           dec 6(iy)                   ; height
+           jr nz, next_rw
+           ret
+
+_video_read:
+           ld a, #0xB2                 ; inir
+           ld (patch_io + 1), a
+           ld a, #0x13                 ; autoincrement on read
+           jr video_do