trs80: add initial prototype graphics card support
authorAlan Cox <alan@linux.intel.com>
Tue, 31 Mar 2015 21:53:48 +0000 (22:53 +0100)
committerAlan Cox <alan@linux.intel.com>
Tue, 31 Mar 2015 21:53:48 +0000 (22:53 +0100)
Kernel/platform-trs80/Makefile
Kernel/platform-trs80/devgfx.c [new file with mode: 0644]
Kernel/platform-trs80/devices.c
Kernel/platform-trs80/fuzix.lnk
Kernel/platform-trs80/trs80.s

index d28ab0d..82c1e02 100644 (file)
@@ -1,5 +1,5 @@
 
-CSRCS = devlpr.c devtty.c devfd.c devhd.c
+CSRCS = devlpr.c devtty.c devfd.c devhd.c devgfx.c
 CSRCS += devices.c main.c
 DISCARD_CSRCS = discard.c devhd_discard.c
 
diff --git a/Kernel/platform-trs80/devgfx.c b/Kernel/platform-trs80/devgfx.c
new file mode 100644 (file)
index 0000000..b8ba5be
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *     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
+ */
+
+#include <kernel.h>
+#include <kdata.h>
+#include <vt.h>
+#include <graphics.h>
+#include <devgfx.h>
+
+static struct display trsdisplay = {
+  640, 240,
+  1024, 256,
+  1, 1,                /* Need adding to ioctls */
+  FMT_MONO_BW,
+  HW_UNACCEL,
+  GFX_ENABLE,
+  32,
+  GFX_SETPIXEL,
+  0
+};
+
+uint16_t video_op[GFX_BUFLEN];
+
+__sfr __at 0x83 gfx_ctrl;
+
+struct attribute video_attr;   /* Shared with asm code */
+int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
+{
+  if (arg >> 8 != 0x03)
+    return vt_ioctl(minor, arg, ptr);
+  switch(arg) {
+  case GFXIOC_GETINFO:
+    return uput(&trsdisplay, ptr, sizeof(trsdisplay));
+  case GFXIOC_ENABLE:
+    gfx_ctrl = 3;      /* we might want 1 for special cases */
+    return 0;
+  case GFXIOC_DISABLE:
+    gfx_ctrl = 0;      /* we might want 1 for special cases */
+    return 0;
+  case GFXIOC_SETATTR:
+    return uget(&video_attr, ptr, sizeof(video_attr));
+  case GFXIOC_SETPIXEL:
+    if (uget(&video_op, ptr, sizeof(video_op)))
+      return -1;
+    video_setpixel();
+    return 0;
+  default:
+    udata.u_error = EINVAL;
+    return -1;
+  }
+}
index 6a9792d..f633f8f 100644 (file)
@@ -8,6 +8,7 @@
 #include <devlpr.h>
 #include <vt.h>
 #include <devtty.h>
+#include <devgfx.h>
 
 struct devsw dev_tab[] =  /* The device driver switch table */
 {
@@ -16,7 +17,7 @@ struct devsw dev_tab[] =  /* The device driver switch table */
   /* 1: /dev/hd                Hard disc block devices */
   {  hd_open,     no_close,     hd_read,   hd_write,   no_ioctl  },
   /* 2: /dev/tty       TTY devices */
-  {  tty_open,    trstty_close, tty_read,  tty_write,  vt_ioctl },
+  {  tty_open,    trstty_close, tty_read,  tty_write,  gfx_ioctl },
   /* 3: /dev/lpr       Printer devices */
   {  lpr_open,    lpr_close,    no_rdwr,   lpr_write,  no_ioctl  },
   /* 4: /dev/mem etc   System devices (one offs) */
index bca84f3..210e691 100644 (file)
@@ -20,6 +20,7 @@ platform-trs80/devfd.rel
 platform-trs80/floppy.rel
 platform-trs80/devhd.rel
 platform-trs80/devhd_discard.rel
+platform-trs80/devgfx.rel
 platform-trs80/devices.rel
 devio.rel
 filesys.rel
index fc22d6d..ae5ca7a 100644 (file)
            ; and the page from the C code
            .globl _hd_page
 
+           ; video
+           .globl _video_setpixel
+           .globl _video_op
+           .globl _video_attr
+
             ; exported debugging tools
             .globl _trap_monitor
             .globl outchar
@@ -275,3 +280,76 @@ _hd_xfer_out:
           otir
           call map_kernel
           ret
+
+;
+;      Graphics card
+;
+setpixel_optab:
+           nop                         ;
+           or b                        ; COPY
+           nop
+           or b                        ; SET
+           cpl                         ; complement pixel mask
+           and b                       ; CLEAR by anding with mask
+           nop
+           xor b                       ; INVERT
+setpixel_bittab:
+           .db 128,64,32,16,8,4,2,1
+
+_video_setpixel:
+           ld a, (_video_attr + 2)     ; mode
+           or a                        ; copy ?
+           jr nz, setpixel_notdraw
+           ld a, (_video_attr)         ; ink
+           or a                        ; white ?
+           jr nz, setpixel_notdraw     ; a = 1 = set so good
+           ld a, #2                    ; clear
+setpixel_notdraw:
+           ld e, a
+           ld d, #0
+           ld hl, #setpixel_optab
+           add hl, de
+           ld a, (hl)
+           ld (setpixel_opcode), a     ; Self modifying
+           inc hl
+           ld a, (hl)
+           ld (setpixel_opcode), a     ; Self modifying
+           ld bc, (_video_op)  ; B is the count
+           ld a, b
+           and #0x1f           ; max 31 pixels per op
+           ret z
+           push bc
+setpixel_loop:
+           ld hl, #_video_op + 2       ; co-ordinate pairs
+           ld a, (hl)          ; low bits of X
+           and #7
+           ld c, a
+           ld a, (hl)
+           inc hl
+           ld b, (hl)          ; high bits of X
+           srl b
+           rra
+           srl b
+           rra
+           srl b
+           rra
+           and #0x7F
+           out (0x80), a
+           ld a, (hl)          ; y low (no y high needed)
+           inc hl
+           inc hl              ; next point pair
+           push hl
+           out (0x81), a
+           ld hl, #setpixel_bittab
+           ld b, #0
+           add hl, bc
+           ld b, (hl)          ; our pixel mask
+           in a, (0x82)        ; pixel from screen
+setpixel_opcode:
+           nop                 ; nop or cpl
+           or b
+           out (0x82), a
+           pop hl
+           pop bc
+           djnz setpixel_loop
+           ret