ubee: some further initial work
authorAlan Cox <alan@linux.intel.com>
Sun, 28 Jan 2018 00:48:07 +0000 (00:48 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 28 Jan 2018 00:48:07 +0000 (00:48 +0000)
Thi is enough to get us loaded into memory and run through the early
assembly entry code. We don't get far yet though.

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

index 7f90738..c7a96db 100644 (file)
@@ -5,9 +5,12 @@ CSRCS += devices.c main.c
 ASRCS = ubee.s crt0.s
 ASRCS += tricks.s commonmem.s floppy.s
 
+NSRCS = ../dev/net/net_native.c
+
 COBJS = $(CSRCS:.c=.rel)
 AOBJS = $(ASRCS:.s=.rel)
-OBJS  = $(COBJS) $(AOBJS)
+NOBJS = $(patsubst ../dev/net/%.c,%.rel, $(NSRCS))
+OBJS  = $(COBJS) $(AOBJS) $(NOBJS)
 
 JUNK = $(CSRCS:.c=.lst) $(CSRCS:.c=.asm) $(CSRCS:.c=.sym) $(ASRCS:.s=.lst) $(ASRCS:.s=.sym) $(CSRCS:.c=.rst) $(ASRCS:.s=.rst)
 
@@ -16,10 +19,23 @@ all:        $(OBJS)
 $(COBJS): %.rel: %.c
        $(CROSS_CC) $(CROSS_CCOPTS) -c $<
 
+$(NOBJS): %.rel: ../dev/net/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
 $(AOBJS): %.rel: %.s
        $(CROSS_AS) $(ASOPTS) $<
 
 clean:
-       rm -f $(OBJS) $(JUNK)  core *~ 
+       rm -f $(OBJS) $(JUNK)  core *~  fuzix.ss80 bootstrap.bin
 
 image:
+       sdasz80 -o bootstrap.s
+       sdldz80 -m -i bootstrap.rel
+       sdasz80 -o hellotest.s
+       sdldz80 -m -i hellotest.rel
+       makebin -s 640 bootstrap.ihx | dd of=bootstrap.bin bs=128 skip=1
+       makebin -s 640 hellotest.ihx | dd of=hellotest.bin bs=512 skip=1
+       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
diff --git a/Kernel/platform-ubee/bootstrap.s b/Kernel/platform-ubee/bootstrap.s
new file mode 100644 (file)
index 0000000..7eacf8b
--- /dev/null
@@ -0,0 +1,42 @@
+;
+;      The bootstrap loads a chunk of sectors from disk. In the ubee
+;      case it's easier than many as we have a bootrom image at 0xE000
+;      until we blow it away
+;
+;      FIXME: do any platforms need us to force RAM banks (eg so top and
+;      lower RAM are not both the same bank), or unmap other ROM here
+;
+;      Preserve EFFx for the loaded image (so it can spot a 256TC)
+;
+
+       .area ASEG(ABS)
+       .org 0x80
+
+boot:  jr bootme
+       .word 0xAA55            ; signature
+bootme:
+       ld hl,#0x200
+       ld de,#0x0002           ; track 0 sector 2
+       ld bc,#0xDC00           ; D800 takes us up to DEFF, and DFxx is
+                               ; ROM owned. We'll use DFxx+ for BSS etc
+       call 0xE039             ; ROM request
+       jr z, allgood           ; Loaded
+       ld hl,#loadfail
+fail:
+       call 0xE033             ; Flash up error
+       jp 0xE003               ; Monitor
+loadfail:
+       .ascii 'Load failed'
+       .byte 0x80
+notbootable:
+       .ascii 'Not bootable'
+       .byte 0x80
+allgood:
+       ld hl,(0x200)           ; but is it crap ?
+       ld de,#0xC0DE
+       or a
+       sbc hl,de
+       ld hl,#notbootable
+       jr nz,fail
+       jp 0x0202
+       
\ No newline at end of file
index b15aa29..544ddd0 100644 (file)
@@ -1,27 +1,31 @@
-/* We have an RTC */
+/* We have an RTC - well maybe (its optional) */
 #define CONFIG_RTC
 /* Enable to make ^Z dump the inode table for debug */
 #undef CONFIG_IDUMP
 /* Enable to make ^A drop back into the monitor */
 #undef CONFIG_MONITOR
 /* Profil syscall support (not yet complete) */
-#define CONFIG_PROFIL
+#undef CONFIG_PROFIL
 /* Multiple processes in memory at once */
 #define CONFIG_MULTI
 /* Single tasking */
 #undef CONFIG_SINGLETASK
 /* Video terminal, not a serial tty */
 #define CONFIG_VT
-/* Simple character addressed device */
+/* Simple character addressed device (for now) */
 #define CONFIG_VT_SIMPLE
 /* Banked memory set up */
 #define CONFIG_BANK_FIXED
-#define MAX_MAPS       32              /* 1MByte... */
+#define MAX_MAPS       16              /* 512 KByte... */
 #define MAP_SIZE       0x8000
 
+#define CONFIG_NET
+#define CONFIG_NET_NATIVE
+
 #define CONFIG_BANKS   2       /* 2 x 32K */
 
-/* Vt definitions */
+/* 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)
 #define VT_WIDTH       80
 #define VT_HEIGHT      24
@@ -49,7 +53,7 @@
 #define CMDLINE        NULL      /* Location of root dev name */
 
 /* Device parameters */
-#define NUM_DEV_TTY 2
+#define NUM_DEV_TTY 1
 #define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
 #define SWAPDEV  (256)   /* Device for swapping (1st hd). */
 #define NBUFS    10       /* Number of block buffers */
index 78fe134..7c43676 100644 (file)
                .globl s__INITIALIZER
                .globl kstack_top
 
+               .globl _ubee_model
+
                ; startup code
                .area _CODE
 
 ;
-;      Once the loader completes it jumps here
+;      Once the loader completes it jumps here. We are loaded between
+;      low memory and DFFF. Above us at this moment is ROM and VRAM is
+;      at F800 overlapping the top of RAM
+;
+;      There are lots of uBee's we might have been loaded on but we
+;      only have to care about those that have enough memory (128K+_
 ;
+               .word 0xC0DE
 start:
+               di
                ld sp, #kstack_top
+               ;
+               ; Figure out our hardware type. We need to work this out
+               ; before we can shuffle the memory map and set up video
+               ;
+               ; Start with the easy case (we expect our loader to preserve
+               ; these - we might need to move the model detection and
+               ; support check into the loader
+               ld a, (0xEFFD)
+               cp #'2'
+               jr nz, not256tc
+               ld a, (0xEFFE)
+               cp #'5'
+               jr nz, not256tc
+               ld a, (0xEFFF)
+               cp #'6'
+               jr nz, not256tc
+               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
+               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
+               out (0x50),a
+
+               ; FIXME: support SBC (128K non premium 5.25 or 3.5
+               ; drives, flicker on video writes)
+
+relocate:
+               ;
                ; move the common memory where it belongs    
                ld hl, #s__DATA
                ld de, #s__COMMONMEM
@@ -56,13 +112,22 @@ start:
                ld (hl), #0
                ldir
 
-;      TODO: Move the common into the other bank, pain as we may well have
-;      code in low bank and __COMMON packed in high. Needs to be in
-;      .COMMONMEM and map the other page low
-;
                call init_early
                call init_hardware
                call _fuzix_main
                di
 stop:          halt
                jr stop
+
+;
+;      We still have ROM at this point
+;
+unsupported_model:
+               ld hl,#unsupported_txt
+               call 0xE033
+               jp 0xE000
+unsupported_txt:
+               .ascii "Unsupported platform"
+               .byte 0x80
+
+_ubee_model:   .byte 0
index fed72db..d5bb8c9 100644 (file)
@@ -1,3 +1,20 @@
+/*
+ *     The MicroBee has a console interface which we map as tty1. It's a
+ *     rather normal 6845 setup but with options to do character based high
+ *     res with 8x16 patterns, two colours per pattern.
+ *
+ *     The input side on the other hand is a bit different. The TC has a
+ *     rather normal sane interface but the older machines wire the keyboard
+ *     through some of the address scanning of the 6845 and the light pen
+ *     input so that the raster scan does a (slow) keyboard scan. Sucky but
+ *     cheap.
+ *
+ *     The serial ports are wired to a pair of PIO controllers not to an
+ *     actual UART although there are interrupting on the edges. We don't
+ *     support those for now. Some machines had add in Z8530 based
+ *     interfaces at 0x68/0x69:  we need to look at those some day.
+ */
+
 #include <kernel.h>
 #include <kdata.h>
 #include <printf.h>
 #include <devtty.h>
 #include <stdarg.h>
 
-char tbuf1[TTYSIZ];
-char tbuf2[TTYSIZ];
+static char tbuf1[TTYSIZ];
 
 uint8_t vtattr_cap;
 
-__sfr __at 0xE8 tr1865_ctrl;
-__sfr __at 0xE9 tr1865_baud;
-__sfr __at 0xEA tr1865_status;
-__sfr __at 0xEB tr1865_rxtx;
-
 struct s_queue ttyinq[NUM_DEV_TTY + 1] = {     /* ttyinq[0] is never used */
        {NULL, NULL, NULL, 0, 0, 0},
        {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2},
-       {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}
 };
 
 /* Write to system console */
@@ -60,11 +70,6 @@ int tty_carrier(uint8_t minor)
 }
 
 #if 0
-static uint8_t keymap[8];
-static uint8_t keyin[8];
-static uint8_t keybyte, keybit;
-static uint8_t newkey;
-static int keysdown = 0;
 static uint8_t shiftmask[8] = {
        0, 0, 0, 0, 0, 0, 0, 7
 };
@@ -103,76 +108,87 @@ static void keyproc(void)
        }
 }
 
-static uint8_t keyboard[8][8] = {
-       {'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g'},
-       {'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'},
-       {'p', 'q', 'r', 's', 't', 'u', 'v', 'w'},
-       {'x', 'y', 'z', '[', '\\', ']', '^', '_'},
-       {'0', '1', '2', '3', '4', '5', '6', '7'},
-       {'8', '9', ':', ';', ',', '-', '.', '/'},
-       {13, 12, 3, 0 /*up */ , 0 /*down */ , 8 /* left */ , 0 /*right */ ,
-        ' '},
-       {0, 0, 0, 0, 0xF1, 0xF2, 0xF3, 0}
+#endif
+
+static uint8_t keymap[15];
+static uint8_t keyin[15];
+static uint8_t keybyte, keybit;
+static uint8_t newkey;
+static int keysdown = 0;
+
+/* These are not completely correct for the TC yet */
+static uint8_t keyboard_tc[15][8] = {
+       /* 0x */
+       { KEY_F1, KEY_ESC, KEY_TAB, KEY_STOP, 0, '0','.',' ' },
+       { KEY_F2, '1', 'q', 'a', 0, 0/*Capslock*/, CTRL('M'), KEY_INSERT },
+       /* 1x */
+       { KEY_F3, '2', 'w', 's', '+', '2', '3', 'z' },
+       { KEY_F4, '3', 'e', 'd', '-', '5', '6', 'x' },
+       /* 2x */
+       { KEY_F5, '4', 'r', 'f', '*', '8', '9', 'c' },
+       { KEY_F6, '5', 't', 'g', '7', '1', '4', 'v' },
+       /* 3x */
+       { KEY_F7, '6', 'y', 'h', '/', KEY_DOWN, KEY_RIGHT, 'b' },
+       { KEY_F8, '7', 'u', 'j',  0 , KEY_LEFT,  0 , 'n' },
+       /* 4x */
+       { KEY_F9, '8', 'i', 'k',  0 ,  0 , KEY_UP, 'm' },
+       { KEY_F10, '9', 'o', 'l', 0, KEY_BS, KEY_ENTER, ',' },
+       /* 5x */
+       { KEY_F11, '0', 'p', ';', KEY_DEL, '`', '\\', '.' },
+       { KEY_F12, '-', '[', '\'', 0, '=', ']', '/' },
+       /* 60 shift 67 ctrl 70 alt */
 };
 
-static uint8_t shiftkeyboard[8][10] = {
-       {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G'},
-       {'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'},
-       {'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'},
-       {'X', 'Y', 'Z', '{', '|', '}', '^', '_'},
-       {'0', '!', '"', '#', '$', '%', '&', '\''},
-       {'(', ')', '*', '+', '<', '=', '>', '?'},
-       {13, 12, 3, 0 /*up */ , 0 /*down */ , 8 /* left */ , 0 /*right */ ,
-        ' '},
-       {0, 0, 0, 0, 0xF1, 0xF2, 0xF3, 0}
+static uint8_t shift_keyboard_tc[15][8] = {
+       /* 0x */
+       { KEY_F1, KEY_ESC, KEY_TAB, KEY_STOP, 0, '0','.',' ' },
+       { KEY_F2, '!', 'Q', 'A', 0, 0/*Capslock*/, CTRL('M'), KEY_INSERT },
+       /* 1x */
+       { KEY_F3, '@', 'W', 'S', '+', '2', '3', 'z' },
+       { KEY_F4, '#', 'E', 'D', '-', '5', '6', 'x' },
+       /* 2x */
+       { KEY_F5, '$', 'R', 'F', '*', '8', '9', 'c' },
+       { KEY_F6, '%', 'T', 'G', '7', '1', '4', 'v' },
+       /* 3x */
+       { KEY_F7, '^', 'Y', 'H', '/', KEY_DOWN, KEY_RIGHT, 'b' },
+       { KEY_F8, '&', 'U', 'J',  0 , KEY_LEFT,  0 , 'n' },
+       /* 4x */
+       { KEY_F9, '*', 'I', 'K',  0 ,  0 , KEY_UP, 'm' },
+       { KEY_F10, '(', 'O', 'L', 0, KEY_BS, KEY_ENTER, '<' },
+       /* 5x */
+       { KEY_F11, ')', 'P', ':', KEY_DEL, '"', '|', '>' },
+       { KEY_F12, '_', '{', '\'', 0, '+', '}', '?' },
+       /* 60 shift 67 ctrl 70 alt */
 };
 
+
 static uint8_t capslock = 0;
 
-static void keydecode(void)
+static void keydecode_tc(void)
 {
        uint8_t c;
 
-       if (keybyte == 7 && keybit == 3) {
+       if (keybyte == 1 && keybit == 5) {
                capslock = 1 - capslock;
                return;
        }
 
-       if (keymap[7] & 3)      /* shift */
-               c = shiftkeyboard[keybyte][keybit];
+       /* TODO: ALT */
+       if (keymap[6] & 0x80)   /* shift */
+               c = shift_keyboard_tc[keybyte][keybit];
        else
-               c = keyboard[keybyte][keybit];
+               c = keyboard_tc[keybyte][keybit];
 
-       /* The keyboard lacks some rather important symbols so remap them
-          with control */
-       if (keymap[7] & 4) {    /* control */
+       if (keymap[7] & 0x80) { /* control */
                if (c > 31 && c < 127)
                        c &= 31;
-               if (keymap[7] & 3) {
-                       if (c == '(')
-                               c = '{';
-                       if (c == ')')
-                               c = '}';
-                       if (c == '-')
-                               c = '_';
-                       if (c == '/')
-                               c = '``';
-                       if (c == '<')
-                               c = '^';
-               } else {
-                       if (c == '(')
-                               c = '[';
-                       if (c == ')')
-                               c = ']';
-                       if (c == '-')
-                               c = '|';
-               }
        }
        if (capslock && c >= 'a' && c <= 'z')
                c -= 'a' - 'A';
        tty_inproc(1, c);
 }
 
+#if 0
 void kbd_interrupt(void)
 {
        newkey = 0;
@@ -182,3 +198,42 @@ void kbd_interrupt(void)
 }
 
 #endif
+
+__sfr __at 0x02        tc256_kstat;
+__sfr __at 0x18 tc256_kcode;
+
+/* In order to make most of the code follow the same logic as the scan
+   keyboad we basically fake a scan keyboard using the keycodes we get */
+static void keymap_down(uint8_t c)
+{
+       keybyte = c >> 3;
+       keybit = c & 7; 
+       if (keybyte < 15) {
+               keymap[keybyte] |= keybit;
+               keysdown++;
+               newkey = 1;
+       }
+}
+
+static void keymap_up(uint8_t c)
+{
+       if (keybyte < 15) {
+               keymap[c >> 3] &= ~(c & 7);
+               keysdown--;
+       }
+}
+
+/* 256TC */
+void kbd_interrupt(void)
+{
+       uint8_t x = tc256_kstat;
+       if (x & 1) {
+               x = tc256_kcode;
+               if (x & 0x80)
+                       keymap_down(x & 0x7F);
+               else
+                       keymap_up(x & 0x7F);
+               if (keysdown < 3)
+                       keydecode_tc();
+       }
+}
index 746fb24..ab23ad1 100644 (file)
@@ -1,8 +1,8 @@
 -mwxuy
 -i fuzix.ihx
--b _CODE=0x0100
--b _DISCARD=0xD000
--b _COMMONMEM=0xE800
+-b _CODE=0x0200
+-b _DISCARD=0xDA00
+-b _COMMONMEM=0xE400
 -l z80
 platform-ubee/crt0.rel
 platform-ubee/commonmem.rel
@@ -28,11 +28,13 @@ syscall_exec16.rel
 syscall_fs.rel
 syscall_fs2.rel
 syscall_fs3.rel
+syscall_net.rel
 syscall_proc.rel
 syscall_other.rel
 tty.rel
 mm.rel
 swap.rel
+platform-ubee/net_native.rel
 bankfixed.rel
 vt.rel
 devsys.rel
index ebadc45..1211ad4 100644 (file)
@@ -1,6 +1,6 @@
 ; UZI mnemonics for memory addresses etc
 
-U_DATA                      .equ 0xE000       ; (this is struct u_data from kernel.h)
+U_DATA                      .equ 0xE400       ; (this is struct u_data from kernel.h)
 U_DATA__TOTALSIZE           .equ 0x300        ; 256+256+256 bytes.
 
 U_DATA_STASH               .equ 0x7D00       ; BD00-BFFF
@@ -8,6 +8,6 @@ U_DATA_STASH                .equ 0x7D00       ; BD00-BFFF
 PROGBASE                   .equ 0x0000
 PROGLOAD                   .equ 0x0100
 
-Z80_TYPE                   .equ 1
+Z80_TYPE                   .equ 0
 
 Z80_MMU_HOOKS              .equ 0
index 7c4cd71..e4d68e5 100644 (file)
@@ -3,6 +3,7 @@
 #include <kdata.h>
 #include <printf.h>
 #include <devtty.h>
+#include <ubee.h>
 
 uint16_t ramtop = PROGTOP;
 
@@ -19,45 +20,46 @@ void do_beep(void)
 
 void platform_interrupt(void)
 {
+       kbd_interrupt();
        timer_interrupt();
 }
 
 void map_init(void)
 {
+
 }
 
-/* Toggle bit 1, set the no ROM bits */
-#define PAGE_MAP(page) (((page) | 0x04)^0x02)
+/* 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 |= 0xC;               /* ROM off, Video off */
+       if (ubee_model == UBEE_256TC)
+               r |= (banknum & 4) ? 0x20 : 0;
+       else
+               r |= (banknum & 0x0C) << 4;
+       return r;
+}
 
-/* Kernel in 0/1. We don't pull video tricks with 0xF000 yet to save memory
-   but we should eventually */
+/* 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)
 {
-       /* This is model dependent */
-       pagemap_add(PAGE_MAP(2));
-       pagemap_add(PAGE_MAP(3));
-#if defined(CONFIG_UB256) || defined(CONFIG_UB512)
-       pagemap_add(PAGE_MAP(0) | 0x40);
-       pagemap_add(PAGE_MAP(1) | 0x40);
-       pagemap_add(PAGE_MAP(2) | 0x40);
-       pagemap_add(PAGE_MAP(3) | 0x40);
-#endif
-#if defined(CONFIG_UB256TC) || defined(CONFIG_UB512)
-       pagemap_add(PAGE_MAP(0) | 0x80);
-       pagemap_add(PAGE_MAP(1) | 0x80);
-       pagemap_add(PAGE_MAP(2) | 0x80);
-       pagemap_add(PAGE_MAP(3) | 0x80);
-#endif
-#if defined(CONFIG_UB512)
-       pagemap_add(PAGE_MAP(0) | 0xC0);
-       pagemap_add(PAGE_MAP(1) | 0xC0);
-       pagemap_add(PAGE_MAP(2) | 0xC0);
-       pagemap_add(PAGE_MAP(3) | 0xC0);
-#endif
-/* and if we ever poke at the 1024 stuff its bit 7-5/1-0 */
+       uint8_t i;
+       uint8_t nbank = procmem / 32;
+       for (i = 1; i < nbank; i++)
+               pagemap_add(map_mod(i));
+
 }
 
+/* FIXME: check RTC is not an option on supported devices, if so probe it */
 __sfr __at 0x04 rtc_c;
 __sfr __at 0x06 rtc_d;
 
index 1d39787..90f6b84 100644 (file)
@@ -40,6 +40,8 @@
            .globl fd_nmi_handler
            .globl null_handler
 
+           .globl _ubee_model
+
            .globl s__COMMONMEM
            .globl l__COMMONMEM
 
@@ -65,12 +67,56 @@ _trap_reboot:
            call map_kernel
            jp to_reboot
 
+;
+;      Sit in common and play with th banks to see what we have
+;
+size_ram:
+           ; We could have < 128, 128 or various extensions up to 512K or
+           ; so.
+           ld ix,#0x80                 ; safe scribble
+           ld c,#0x01
+           ld de,#page_codes
+           ld (ix),#0                  ; clear in bank 0 low
+           ld hl,#32
+scan_ram:
+           add hl,hl
+           ld a,(de)                   ; try entry in table
+           or a
+           jr z,scan_done              ; finished
+           inc de
+           out (0x50),a                ; select proposed bank
+           ld (ix),c                   ; write to it
+           ld a,#4
+           out (0x50),a                ; back to bank 0
+           ld a,(ix)                   ; read it back
+           cp c                        ; did it mess with bank 0L ?
+           jr nz, scan_ram
+
+;      We found our first mismatch HL is our memory size
+;      info if at least 128K is present (or 64 if not)
+scan_done:
+           ret
+
+page_codes:
+           ; Detect a standard or premium 128K system
+           .byte 0x06  ;       write 1 to bank 1L 0x80
+           ; Detect a system with a 256K expansion mod
+           .byte 0x44  ;       write 1 to bank 2L 0x80
+           ; Detect a system with a 512K expansion mod
+           .byte 0x84  ;       write 1 to bank 4L 0x80
+           ; We don't handle the modern ubee premium plus emulated thing
+           .byte 0x00  ;       and done
+
 ; -----------------------------------------------------------------------------
 ; KERNEL MEMORY BANK (below 0xE800, only accessible when the kernel is mapped)
 ; -----------------------------------------------------------------------------
             .area _CODE
 
-; These two must be below 32K and not use the stack until they hit ROM space
+; These two must be below 32K and not use the stack until they hit ROM
+; space.
+;
+; Not sure we can do this for most cases because not everyone has all that
+; ROM
 ;
 to_monitor:
            xor a                       ; 0 or 1 to keep low 32K right ? */
@@ -91,16 +137,15 @@ _ctc6845:                          ; registers in reverse order
            .db 0x1a, 0x19, 0x05, 0x1B, 0x37, 0x58, 0x50, 0x6B
 
 init_early:
-
             ; load the 6845 parameters
            ld hl, #_ctc6845
-           ld bc, #0x100C
+           ld bc, #0x0F0C
 ctcloop:    out (c), b                 ; register
            ld a, (hl)
            out (0x0D), a               ; data
            inc hl
            dec b
-           jp po, ctcloop              ; check V not C
+           jp p, ctcloop
            ; ensure the CTC clock is right
            ld a, #0
            in a, (9)                   ; manual says in but double check
@@ -118,10 +163,15 @@ ctcloop:    out (c), b                    ; register
             ret
 
 init_hardware:
-            ; set system RAM size
-            ld hl, #128                        ; FIXME according to platform
+           ld a,(_ubee_model)
+           cp #2                       ; 256TC
+           ld hl,#256                  ; 256TC has 256K
+           call nz, size_ram
+is_tc:
             ld (_ramsize), hl
-            ld hl, #(128-64)           ; 64K for kernel
+           ld de,#64                   ; 64K for kernel
+           or a
+           sbc hl,de
             ld (_procmem), hl
 
             ; set up interrupt vectors for the kernel (also sets up common memory in page 0x000F which is unused)
@@ -134,6 +184,8 @@ init_hardware:
            ; set up the RTC driven periodic timer. The PIA should already
            ; have been configured for us
            ;
+           ; FIXME: RTC is an option - use vblank instead  (pio bit 7)
+           ;
            ld a, #0x0A                 ; PIR timer
            out (0x04), a
            ld a, #0x1001               ; 64 ints/second
@@ -205,7 +257,6 @@ map_kernel:
            out (0x50), a
            pop af
            ret
-
 map_process:
            ld a, h
            or l