ubee: Next stages to get from prototype to usable
authorAlan Cox <alan@linux.intel.com>
Thu, 19 Apr 2018 22:50:37 +0000 (23:50 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 19 Apr 2018 22:50:37 +0000 (23:50 +0100)
- Draft code for lpen keyboard
- Fix various platform detection bugs
- Rework video to bank it out when not used (in progress)
- Support attributes and colour
- Memory map re-arrange and buffer recovery
- Turn on networking and other stuff that is useful

Not yet working (still debugging the video changes)

Kernel/platform-ubee/Makefile
Kernel/platform-ubee/README
Kernel/platform-ubee/config.h
Kernel/platform-ubee/crt0.s
Kernel/platform-ubee/devtty.h
Kernel/platform-ubee/discard.c [new file with mode: 0644]
Kernel/platform-ubee/fuzix.lnk
Kernel/platform-ubee/kernel.def
Kernel/platform-ubee/main.c
Kernel/platform-ubee/ubee.s
Kernel/platform-ubee/vt.c [new file with mode: 0644]

index c7a96db..8dda780 100644 (file)
@@ -1,6 +1,8 @@
 
 CSRCS = devlpr.c devtty.c devfd.c devhd.c
-CSRCS += devices.c main.c
+CSRCS += devices.c main.c vt.c
+
+DISCSRCS = discard.c
 
 ASRCS = ubee.s crt0.s
 ASRCS += tricks.s commonmem.s floppy.s
@@ -10,7 +12,9 @@ NSRCS = ../dev/net/net_native.c
 COBJS = $(CSRCS:.c=.rel)
 AOBJS = $(ASRCS:.s=.rel)
 NOBJS = $(patsubst ../dev/net/%.c,%.rel, $(NSRCS))
-OBJS  = $(COBJS) $(AOBJS) $(NOBJS)
+DISCOBJS = $(DISCSRCS:.c=.rel)
+
+OBJS  = $(COBJS) $(AOBJS) $(NOBJS) $(DISCOBJS)
 
 JUNK = $(CSRCS:.c=.lst) $(CSRCS:.c=.asm) $(CSRCS:.c=.sym) $(ASRCS:.s=.lst) $(ASRCS:.s=.sym) $(CSRCS:.c=.rst) $(ASRCS:.s=.rst)
 
@@ -19,6 +23,9 @@ all:  $(OBJS)
 $(COBJS): %.rel: %.c
        $(CROSS_CC) $(CROSS_CCOPTS) -c $<
 
+$(DISCOBJS): %.rel: %.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
 $(NOBJS): %.rel: ../dev/net/%.c
        $(CROSS_CC) $(CROSS_CCOPTS) -c $<
 
@@ -38,4 +45,3 @@ image:
        dd if=/dev/zero of=fuzix.ss80 bs=512 count=800
        dd if=bootstrap.bin of=fuzix.ss80 conv=notrunc
        dd if=../fuzix.bin of=fuzix.ss80 bs=512 seek=1 conv=notrunc
-#      dd if=hellotest.bin of=fuzix.ss80 bs=512 seek=1 conv=notrunc
index 741b4f5..e8480f9 100644 (file)
@@ -25,6 +25,12 @@ The other memory is then overlaid on 0000-7FFF for user space
        0100-7CFF               Application
        7D00-7FFF               Udata/stack cache (may be able to move
                                oto 7DFF/7E00)
+       (User space sees video mapped at 0x8000-8FFF)
+
+
+Testing with uBee512
+
+ubee512
 
 Done so far:
 
@@ -118,7 +124,8 @@ There are three kinds of video
 
 Standard:
        A 6545 with 2K of display memory and 128 8x16 ROM characters plus
-       128 in programmable character memory. No colour
+       128 in programmable character memory.
+       Colour option (includes flicker workaround)
 
 Premium:
        The 6545 has
@@ -137,5 +144,25 @@ Premium:
 
 High resolution video is sort of MSX like but cruder. The character memory is
 filled with unique character codes and the character ram is loaded with the
-bit patterns.
+bit patterns. Also it's banked and banked so will be horrible to program and
+we'll need graphics mode support for other modes
+
+
+
+Currently in progress
+
+- Video support (colour, attributes)                   DEBUGGING
+- Map video at 0x8000                                  DONE
+- Clear attribute ram if present                       DONE
+- Move common up                                       DONE
+- Do buffer over discard change                                UNTESTED
+- Check we have video latches/map right everywhere     DEBUGGING
+- Init vtattr_cap and the video variables correctly    PARTLY DONE
+- Check if scrolling in hw is doable or not in 80x25   NO
+- Support 'map video into my process at 0x8000 hack'   PARTLY DONE
+- Non premium video
+- Non premium video setup
+- Copy ROM font to RAM, support RAM font setting
+- Figure out how I broke the 6545 cursor
 
+Currently debugging scrolling and multichar writes
index 62b6e34..a6983fe 100644 (file)
@@ -12,8 +12,6 @@
 #undef CONFIG_SINGLETASK
 /* Video terminal, not a serial tty */
 #define CONFIG_VT
-/* Simple character addressed device (for now) */
-#define CONFIG_VT_SIMPLE
 /* Banked memory set up */
 #define CONFIG_BANK_FIXED
 #define MAX_MAPS       16              /* 512 KByte... */
 #define CONFIG_NET
 #define CONFIG_NET_NATIVE
 
+#define CONFIG_DYNAMIC_BUFPOOL
+
 #define CONFIG_BANKS   2       /* 2 x 32K */
 
-/* Vt definitions. Eventually we need to sort this out and do mapping of
-   video, correct video attributes, mode setting etc */
-#define VT_BASE                ((uint8_t *)0xF000)
+/* For now we don't support resizing */
 #define VT_WIDTH       80
 #define VT_HEIGHT      24
 #define VT_RIGHT       79
@@ -59,5 +57,3 @@
 #define NBUFS    7        /* Number of block buffers */
 #define NMOUNTS         4        /* Number of mounts at a time */
 
-
-#define platform_discard()
index 032de36..3677378 100644 (file)
@@ -4,6 +4,7 @@
                ; when they are first seen.     
                .area _CODE
                .area _CODE2
+               ; Load video later on so it ends up above 0x8800
                .area _VIDEO
                .area _CONST
                .area _INITIALIZED
@@ -13,8 +14,9 @@
                .area _HEAP
                .area _GSINIT
                .area _GSFINAL
-               .area _COMMONMEM
+               .area _BUFFERS
                .area _DISCARD
+               .area _COMMONMEM
                ; note that areas below here may be overwritten by the heap at runtime, so
                ; put initialisation stuff in here
                .area _INITIALIZER
@@ -48,7 +50,9 @@
                .word 0xC0DE
 start:
                di
-               ld sp, #kstack_top
+               ; We can't use the kstack yet - we've still got video mapped
+               ; all over it
+               ld sp, #0x0200
                ;
                ; Figure out our hardware type. We need to work this out
                ; before we can shuffle the memory map and set up video
@@ -68,33 +72,41 @@ start:
                ld a,#2
                ld (_ubee_model),a
                ; Do we need to touch ROM etc - not clear we need do
-               ; anything as we are already in RAM mode. Turn on video
-               ; mapping at Fxxx just while we boot up so we can poke it
-               ; for debug. Some day we can map the video just for
-               ; the video writes.
-               ld a,#0x04
+               ; anything as we are already in RAM mode. Turn off video
+               ; mapping
+               ld a,#0x0C
                out (0x50),a
                jr relocate
 
-not256tc:      ; The uBee might have colour support
-               ld hl, (0xF7FF)
-               ld (hl),#0x90           ; zero the last byte
-               ld a, #0x10
-               out (0x1C),a            ; attribute latch
-               ld (hl),#0xFF           ; set to 0xFF
-               ld a,#0x00              ; back to video
-               out (0x1c),a
-               ld a,(hl)
-               ld (_ubee_model),a      ; 1 - premium
-               or a
-               jr z, unsupported_model ; 128K required and premium
-               ld a,#0x04              ; ROMs off video at Fxxx
+not256tc:      ; Are we a premium model
+               ld a,#0x10              ; Attribute latch
+               out (0x1c),a            ; Set
+               in a,(0x1c)             ; Read
+               cp #0x10                ; If reads back we are premium
+               jr nz, premium_model
+               ld a,#0x40              ; Colour control register
+               out (0x08),a            ; Set
+               in a,(0x08)             ; Read
+               cp #0x40
+               jr nz, unsupported_model; not colour
+               xor a
+               jr colour_standard
+;
+;              uBee Premium Board
+;
+premium_model:
+               ld a,#1
+colour_standard:
+               ld (_ubee_model),a      ; model - 1 premium 0 colour standard
+               ld a,#0x0C              ; ROMs off video off
                out (0x50),a
 
                ; FIXME: support SBC (128K non premium 5.25 or 3.5
-               ; drives, flicker on video writes)
+               ; drives, without colour flicker on video writes)
+               ; may also have a 1793 not 2793 fdc
 
 relocate:
+               ld sp,#kstack_top
                ;
                ; move the common memory where it belongs    
                ld hl, #s__DATA
index a010a72..aaa66bb 100644 (file)
@@ -7,4 +7,13 @@ extern void lpen_kbd_poll(void);
 
 extern uint8_t kbscan(void);
 extern uint8_t kbtest(uint16_t code);
+
+extern uint16_t vtattrib;
+extern uint16_t vtaddr;
+extern uint16_t vtbase;
+extern uint16_t vtcount;
+extern uint8_t vtchar;
+
+extern void vwrite(void);
+
 #endif
diff --git a/Kernel/platform-ubee/discard.c b/Kernel/platform-ubee/discard.c
new file mode 100644 (file)
index 0000000..3cfe15f
--- /dev/null
@@ -0,0 +1,120 @@
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <ubee.h>
+
+__sfr __at 0x04 cmos_reg;
+__sfr __at 0x07 cmos_read;
+
+void has_cmos_rtc(void)
+{
+       /* See if the week looks valid - probably want a stronger check */
+       cmos_reg = 0x06;
+       if (cmos_read == 0 || cmos_read > 7)
+               panic("RTC required");
+}
+
+void map_init(void)
+{
+
+}
+
+__sfr __at 0x58 portswitch;
+__sfr __at 0x45 probe_reg;
+__sfr __at 0x41 fdc_cyl;
+__sfr __at 0x48 fdc_stat;
+
+void do_diskprobe(uint8_t *p)
+{
+       probe_reg = 0x5A;
+       /* probe_reg is read/write same value for both controllers so if it
+          doesn't work we have no disk */
+       if (probe_reg != 0x5A)
+               return;
+       /* If it mirrored check if a second value mirrors */
+       if (fdc_cyl == 0x5A) {
+               probe_reg = 0x22;
+               if (fdc_cyl == 0x22) {
+                       /* It's a floppy */
+                       if (fdc_stat & 0x0F)
+                               *p = DISK_TYPE_FDC_D;   /* Dream disc */
+                       else
+                               *p = DISK_TYPE_FDC;
+                       return;
+               }
+       }
+       /* Double check */
+       probe_reg = 0x22;
+       if (probe_reg != 0x22)
+               return;
+       *p = DISK_TYPE_HDC;
+}
+
+static const char dcstr[] = "Disk controller %d: %s\n";
+static const char *diskname[4] = { NULL, "2793", "DreamDisc", "WD1010" };
+
+void diskprobe(void)
+{
+       portswitch = 0;
+       do_diskprobe(disk_type);
+       portswitch = 1;
+       do_diskprobe(disk_type + 1);
+       /* Hard case: two of the same */
+       if (disk_type[0] == disk_type[1]) {
+               /* No disk at all - we don't care if port 58 works */
+               if (!disk_type[0])
+                       return;
+               /* We might have internal and external the same ? */
+               probe_reg = 0x5C;
+               portswitch = 0;
+               probe_reg = 0x00;
+               portswitch = 1;
+               if (probe_reg != 0x5C)
+                       disk_type[1] = 0;
+       }
+       kprintf(dcstr, 0, diskname[disk_type[0]]);
+       if (disk_type[1])
+               kprintf(dcstr, 1, diskname[disk_type[1]]);
+}
+
+/* The bank bits are not laid out nicely for historical reasons
+
+   A classic uBee has the bank selection in bits 0/1
+   The 256TC needed an extra bit so reused bit 5 (rom selector)
+   The 3rd party 512K/1MB add ons used bits 7/6 for the high bank bits
+
+   Bank 0/0 holds the kernel and common Bank 0/1 holds the kernel low 32k */
+static uint8_t map_mod(uint8_t banknum)
+{
+       uint8_t r = banknum & 0x03;
+       r |= 0x14;              /* ROM off, Video on at 0x8000 */
+       if (ubee_model == UBEE_256TC)
+               r |= (banknum & 4) ? 0x20 : 0;
+       else
+               r |= (banknum & 0x0C) << 4;
+       return r;
+}
+
+/* Kernel in bank 0 low/high,user apps in bank 1 low/high (and if present
+   other banks too). Memorywise it's a lot like the TRS80 layout */
+
+void pagemap_init(void)
+{
+       uint8_t i;
+       uint8_t nbank = procmem / 32;
+
+       /* Just a handy spot to run it early */
+       has_cmos_rtc();
+
+       for (i = 1; i < nbank; i++)
+               pagemap_add(map_mod(i));
+
+}
+
+uint8_t platform_param(char *p)
+{
+       used(p);
+       return 0;
+}
index c83b9d5..b508268 100644 (file)
@@ -1,9 +1,8 @@
 -mwxuy
 -i fuzix.ihx
 -b _CODE=0x0200
--b _DISCARD=0xDC00
--b _COMMONMEM=0xE400
--b _INITIALIZER=0xF000
+-b _COMMONMEM=0xF000
+-b _INITIALIZER=0x0001
 -l z80
 platform-ubee/crt0.rel
 platform-ubee/commonmem.rel
@@ -15,6 +14,7 @@ usermem.rel
 usermem_std-z80.rel
 platform-ubee/tricks.rel
 platform-ubee/main.rel
+platform-ubee/discard.rel
 timer.rel
 kdata.rel
 platform-ubee/devfd.rel
@@ -41,4 +41,5 @@ vt.rel
 devsys.rel
 platform-ubee/devlpr.rel
 platform-ubee/devtty.rel
+platform-ubee/vt.rel
 -e
index 86bb8db..607f6aa 100644 (file)
@@ -1,6 +1,6 @@
 ; UZI mnemonics for memory addresses etc
 
-U_DATA                      .equ 0xE400       ; (this is struct u_data from kernel.h)
+U_DATA                      .equ 0xF000       ; (this is struct u_data from kernel.h)
 U_DATA__TOTALSIZE           .equ 0x300        ; 256+256+256 bytes.
 
 U_DATA_STASH               .equ 0x7D00       ; BD00-BFFF
@@ -13,3 +13,5 @@ Z80_TYPE                  .equ 0
 Z80_MMU_HOOKS              .equ 0
 
 CONFIG_SWAP                .equ 1
+
+NBUFS                      .equ 7
index b9d0457..25466c4 100644 (file)
@@ -37,14 +37,6 @@ uint8_t platform_rtc_secs(void)
        return cmos_read;
 }
 
-void has_cmos_rtc(void)
-{
-       /* See if the week looks valid - probably want a stronger check */
-       cmos_reg = 0x06;
-       if (cmos_read == 0 || cmos_read > 7)
-               panic("RTC required");
-}
-
 void platform_interrupt(void)
 {
        static uint8_t icount;
@@ -68,109 +60,31 @@ void platform_interrupt(void)
        }
 }
 
-void map_init(void)
-{
-
-}
-
-uint8_t disk_type[2];
-
-/* More _DISCARD material */
-
-__sfr __at 0x58 portswitch;
-__sfr __at 0x45 probe_reg;
-__sfr __at 0x41 fdc_cyl;
-__sfr __at 0x48 fdc_stat;
-
-void do_diskprobe(uint8_t *p)
-{
-       probe_reg = 0x5A;
-       /* probe_reg is read/write same value for both controllers so if it
-          doesn't work we have no disk */
-       if (probe_reg != 0x5A)
-               return;
-       /* If it mirrored check if a second value mirrors */
-       if (fdc_cyl == 0x5A) {
-               probe_reg = 0x22;
-               if (fdc_cyl == 0x22) {
-                       /* It's a floppy */
-                       if (fdc_stat & 0x0F)
-                               *p = DISK_TYPE_FDC_D;   /* Dream disc */
-                       else
-                               *p = DISK_TYPE_FDC;
-                       return;
-               }
-       }
-       /* Double check */
-       probe_reg = 0x22;
-       if (probe_reg != 0x22)
-               return;
-       *p = DISK_TYPE_HDC;
-}
-
-static const char dcstr[] = "Disk controller %d: %s\n";
-static const char *diskname[4] = { NULL, "2793", "DreamDisc", "WD1010" };
+struct blkbuf *bufpool_end = bufpool + NBUFS;
 
-void diskprobe(void)
+/*
+ *     We pack discard into the memory image is if it were just normal
+ *     code but place it at the end after the buffers. When we finish up
+ *     booting we turn everything from the buffer pool to common into
+ *     buffers.
+ */
+void platform_discard(void)
 {
-       portswitch = 0;
-       do_diskprobe(disk_type);
-       portswitch = 1;
-       do_diskprobe(disk_type + 1);
-       /* Hard case: two of the same */
-       if (disk_type[0] == disk_type[1]) {
-               /* No disk at all - we don't care if port 58 works */
-               if (!disk_type[0])
-                       return;
-               /* We might have internal and external the same ? */
-               probe_reg = 0x5C;
-               portswitch = 0;
-               probe_reg = 0x00;
-               portswitch = 1;
-               if (probe_reg != 0x5C)
-                       disk_type[1] = 0;
-       }
-       kprintf(dcstr, 0, diskname[disk_type[0]]);
-       if (disk_type[1])
-               kprintf(dcstr, 1, diskname[disk_type[1]]);
-}
-
+       uint16_t discard_size = (uint16_t)udata - (uint16_t)bufpool_end;
+       bufptr bp = bufpool_end;
 
-/* The bank bits are not laid out nicely for historical reasons
+       discard_size /= sizeof(struct blkbuf);
 
-   A classic uBee has the bank selection in bits 0/1
-   The 256TC needed an extra bit so reused bit 5 (rom selector)
-   The 3rd party 512K/1MB add ons used bits 7/6 for the high bank bits
+       kprintf("%d buffers added\n", discard_size);
 
-   Bank 0/0 holds the kernel and common Bank 0/1 holds the kernel low 32k */
-static uint8_t map_mod(uint8_t banknum)
-{
-       uint8_t r = banknum & 0x03;
-       r |= 0xC;               /* ROM off, Video off */
-       if (ubee_model == UBEE_256TC)
-               r |= (banknum & 4) ? 0x20 : 0;
-       else
-               r |= (banknum & 0x0C) << 4;
-       return r;
-}
+       bufpool_end += discard_size;
 
-/* Kernel in bank 0 low/high,user apps in bank 1 low/high (and if present
-   other banks too). Memorywise it's a lot like the TRS80 layout */
-
-void pagemap_init(void)
-{
-       uint8_t i;
-       uint8_t nbank = procmem / 32;
-
-       /* Just a handy spot to run it early */
-       has_cmos_rtc();
-
-       for (i = 1; i < nbank; i++)
-               pagemap_add(map_mod(i));
+       memset( bp, 0, discard_size * sizeof(struct blkbuf) );
 
+       for( bp = bufpool + NBUFS; bp < bufpool_end; ++bp ){
+               bp->bf_dev = NO_DEVICE;
+               bp->bf_busy = BF_FREE;
+       }
 }
 
-uint8_t platform_param(char *p)
-{
-       return 0;
-}
+uint8_t disk_type[2];
index b605c39..5022a5d 100644 (file)
@@ -39,6 +39,7 @@
             .globl outcharhex
            .globl fd_nmi_handler
            .globl null_handler
+           .globl _vtinit
 
            .globl _ubee_model
 
             .include "kernel.def"
             .include "../kernel.def"
 
-; -----------------------------------------------------------------------------
+;
+; Buffers (we use asm to set this up as we need them in a special segment
+; so we can recover the discard memory into the buffer pool
+;
+
+           .globl _bufpool
+           .area _BUFFERS
+
+_bufpool:
+           .ds BUFSIZE * NBUFS
+
+;
 ; COMMON MEMORY BANK (kept even when we task switch)
-; -----------------------------------------------------------------------------
+;
             .area _COMMONMEM
 
 _platform_monitor:
@@ -59,7 +71,7 @@ _platform_monitor:
            jp to_monitor
 
 platform_interrupt_all:
-           in a,(0xef)
+           in a,(0xef)                 ; FIXME: remove this line once debugged
            ret
 
 _platform_reboot:
@@ -112,8 +124,6 @@ page_codes:
 ; -----------------------------------------------------------------------------
             .area _CODE
 
-; FIXME: most of this belongs in discard
-
 ; These two must be below 32K and not use the stack until they hit ROM
 ; space.
 ;
@@ -129,6 +139,8 @@ to_reboot:
            xor a
            out (0x50), a
            jp 0xE000
+
+           .area _DISCARD
        
 ;
 ;      This setting list comes from the Microbee 256TC documentation
@@ -138,6 +150,7 @@ _ctc6545:                           ; registers in reverse order
            .db 0x00, 0x00, 0x00, 0x20, 0x0A, 0x09, 0x0A, 0x48
            .db 0x1a, 0x19, 0x05, 0x1B, 0x37, 0x58, 0x50, 0x6B
 
+
 init_early:
             ; load the 6545 parameters
            ld hl, #_ctc6545
@@ -151,18 +164,45 @@ ctcloop:    out (c), b                    ; register
            ; ensure the CTC clock is right
            ld a, #0
            in a, (9)                   ; manual says in but double check
-           in a, (0x1C)
-           and #0x7F
-           out (0x1C), a               ; ensure we are in simple mode for now
+           xor a
+           out (0x0B),a                ; vanish the character rom
+           ld a,#0x40
+           out (0x08),a                ; colour, black background
+           ld a,#0x14                  ; map the video in at 0x8000
+           out (0x50),a
            ; clear screen
-           ld hl, #0xF000
+           ld hl, #0x8000
            ld (hl), #'*'               ; debugging aid in top left
            inc hl
-           ld de, #0xF002
+           ld de, #0x8002
            ld bc, #1998
            ld (hl), #' '
            ldir
-            ret
+           ld hl,#0x8800
+           ld de,#0x8801
+           ld (hl), #4                 ; green characters/black
+           ld bc,#1999
+           ldir
+           ld a,(_ubee_model)
+           or a
+           jr z, no_attribs
+           ;
+           ;   Map in and wipe attribute memory on the premium and tc
+           ;   models.
+           ;
+           ld a,#0x10                  ; Enable attribute memory and
+           out (0x1C),a                ; wipe it
+           ld hl,#0x8000
+           ld de,#0x8001
+           ld bc,#1999
+           ld (hl),#0
+           ldir
+           ld a,#0x80                  ; extended PCG on
+           out (0x1C),a
+no_attribs:
+           ld a,#0x0C                  ; video back off
+           out (0x50),a
+           jp _vtinit
 
 init_hardware:
            ld a,(_ubee_model)
@@ -296,6 +336,7 @@ _program_vectors:
 
            call map_process
 
+           out (0xfe), a
             ; write zeroes across all vectors
             ld hl, #0
             ld de, #1
@@ -330,7 +371,7 @@ _program_vectors:
 ;
 map_kernel:
            push af
-           ld a, #0x04         ; bank 0, 1 no ROM - FIXME: map video over kernel
+           ld a, #0x0C         ; bank 0, 1 no ROM or video
            ld (mapreg), a
            out (0x50), a
            pop af
@@ -418,8 +459,6 @@ _hd_xfer_out:
            .globl _lpen_kbd_last
 ;
 _kbscan:
-           ; FIXME set right register ??? or do we always put it right
-           ; irq handling versus video setup !
            in a,(0x0C)
            bit 6,a             ; No light pen signal - no key
            jr z, nokey         ; Fast path exit
@@ -525,3 +564,157 @@ scanner_done:
             xor a
             out (0x0b),a
            ret
+
+
+;
+;      Video support code. This has to live below F000 so it can use the
+;      video memory and not common. Note that this means we need to disable
+;      interrupts briefly when we do the flipping
+;
+;      TODO: it would make sense to map the ROM and RAM font space and
+;      copy the ROM font to RAM so we can support font setting ?
+;
+
+           .area _VIDEO
+
+           .globl _cursor_off
+           .globl _cursor_on
+           .globl _scroll_up
+           .globl _scroll_down
+           .globl _vwrite
+           .globl _patch_std
+           .globl _patch_std_end
+
+           .globl ___hard_di
+
+           .globl _vtwidth
+           .globl _vtaddr
+           .globl _vtcount
+           .globl _vtattrib
+           .globl _vtchar
+;
+;      6545 Hardware Cursor
+;
+_cursor_off:
+           ret
+_cursor_on:
+           pop hl
+           pop de
+           push de
+           push hl
+           ; ld a,i handling is buggy on NMOS Z80
+           call ___hard_di
+           push af
+           ld c,#0x0d
+           ld a,#0x0e
+           out (0x0c),a
+           out (c),d
+           inc a
+           out (0x0c),a
+           out (c),e
+popout:
+           pop af
+           ret c
+           ei
+           ret
+;
+;      Scroll the display (the memory wraps on a 2K boundary, the
+;      display wraps on 2000 bytes). Soft scroll - hard scroll only works
+;      in 64x16 mode
+;
+;      FIXME: on premium/tc we also need to scroll the attribute RAM!
+;
+_scroll_up:
+           call ___hard_di
+           push af
+           ld a, (mapreg)
+           push af
+           and #0xF7           ; enable video memory
+           or #0x10            ; and put it at 0x8000
+            ld (mapreg),a
+           out (0x50),a
+           ld hl,#0x8000
+           push hl
+           ld de, (_vtwidth)
+           add hl,de
+           pop de
+           ld bc,#4016         ; FIXME compute for variable width
+           ldir
+unmap_out:
+           ; now put the RAM back
+           pop af
+           ld (mapreg),a
+           out (0x50),a
+           ; We usually only do one char
+           jr popout
+
+_scroll_down:
+           call ___hard_di
+           push af
+           ld a, (mapreg)
+           push af
+           and #0xF7           ; enable video memory
+           or #0x10            ; and put it at 0x8000
+            ld (mapreg),a
+           out (0x50),a
+           ld hl,#0x8FCF       ; end of display
+           push hl
+           ld de, (_vtwidth)
+           or a
+           sbc hl,de
+           pop de
+           ex de,hl
+           ld bc,#4016         ; FIXME compute for widths
+           lddr
+           jr unmap_out
+;
+;      Write to the display
+;
+;      In theory we can avoid the di/ei but that needs some careful review
+;      of the banking paths on interrupt
+;
+_vwrite:
+           call ___hard_di
+           push af
+           ld a, (mapreg)
+           push af
+           and #0xF7           ; enable video memory
+           or #0x10            ; and put it at 0x8000
+            ld (mapreg),a
+           out (0x50),a
+           ld hl,(_vtaddr)
+           ld bc,(_vtcount)
+           ld a,h
+           and #0x07
+           or #0x80
+           ld h,a
+           ld de,(_vtattrib)
+           ld a,(_vtchar)
+vloop:
+           ld (hl),a           ; character
+           ld a,#0x90          ; attribute RAM / 0x90 if we enable PCG extended
+_patch_std:
+           out (0x1c),a        ; latch in attribute RAM
+           ld (hl),e           ; attribute
+           xor a               ; #0x80 if enable PCG extended
+           out (0x1c),a
+_patch_std_end:
+           set 3,h             ; colour is at F8-FF
+           ld (hl),d           ; colour
+           dec bc
+           ld a,b
+           or c
+           jr nz, nextchar
+           jr unmap_out
+nextchar:
+           res 3,h
+           inc hl
+           jr vloop
+;
+;      Ensure these are in the video mapping
+;
+_vtaddr:    .word 0
+_vtcount:   .word 0
+_vtattrib:  .word 0
+_vtwidth:   .word 80                   ; FIXME should be variable
+_vtchar:    .byte 0
diff --git a/Kernel/platform-ubee/vt.c b/Kernel/platform-ubee/vt.c
new file mode 100644 (file)
index 0000000..fa3746f
--- /dev/null
@@ -0,0 +1,59 @@
+#include <kernel.h>
+#include <devtty.h>
+#include <ubee.h>
+#include <vt.h>
+
+/*
+ *     We use a variant of the generic code for now but we need a different
+ *     helper as we bank the video memory. We should also start using hard
+ *     cursors as the 6545 has one
+ */
+
+static void char_addr(unsigned int y1, unsigned char x1)
+{
+       vtaddr = VT_WIDTH * y1 + x1;
+}
+
+void plot_char(int8_t y, int8_t x, uint16_t c)
+{
+        char_addr(y,x);
+        vtcount = 1;
+        vtchar = c;
+        vwrite();
+}
+
+void clear_lines(int8_t y, int8_t ct)
+{
+       char_addr(y, 0);
+       vtcount = ct * (uint16_t)VT_WIDTH;
+       vtchar = ' ';
+//     vwrite();
+}
+
+void clear_across(int8_t y, int8_t x, int16_t l)
+{
+       char_addr(y, x);
+       vtcount = l;
+       vtchar = ' ';
+       vwrite();
+}
+
+void vtattr_notify(void)
+{
+       if (ubee_model == UBEE_256TC) {
+               vtattrib = (((uint16_t)vtink) << 8) | (((uint16_t)vtpaper) << 12);
+               if (vtattr & VTA_FLASH)
+                       vtattrib |= 0x80;
+               if (vtattr & VTA_INVERSE)
+                       vtattrib |= 0x40;
+               /* 5 4 must be zero 3-0 are extended font select -> 0 for now */
+       } else if (ubee_model == UBEE_PREMIUM) {
+               if (vtattr & VTA_INVERSE)
+                       vtattrib = (((uint16_t)vtpaper) << 8) | (((uint16_t)vtink) << 12);
+               else
+                       vtattrib = (((uint16_t)vtink) << 8) | (((uint16_t)vtpaper) << 12);
+               /* 7-4 MBZ, 3-0 are extended font select */
+       } else
+               vtattrib = 0;
+}
+