sbcv2: comment extensively and move driver stuff that should be shared out
authorAlan Cox <alan@linux.intel.com>
Tue, 28 Aug 2018 12:47:24 +0000 (13:47 +0100)
committerAlan Cox <alan@linux.intel.com>
Tue, 28 Aug 2018 12:47:24 +0000 (13:47 +0100)
We now have something approaching a clean reference port, and a long list of
cleanups to do the other trees !

Kernel/platform-sbcv2/Makefile
Kernel/platform-sbcv2/commonmem.s
Kernel/platform-sbcv2/discard.c
Kernel/platform-sbcv2/ds1302-n8vem.s [deleted file]
Kernel/platform-sbcv2/ppide.c [deleted file]
Kernel/platform-sbcv2/sbcv2.s
Kernel/platform-sbcv2/tricks.s

index 623ff2e..b807b31 100644 (file)
@@ -1,7 +1,7 @@
 CROSS_CCOPTS += -I../dev/
 
 
-CSRCS = devtty.c ppide.c
+CSRCS = devtty.c
 CSRCS += devices.c main.c
 
 DISCSRCS = discard.c
@@ -12,9 +12,9 @@ ASRCS += tricks.s commonmem.s
 DISCARD_DSRCS = ../dev/devide_discard.c
 DSRCS = ../dev/blkdev.c ../dev/devide.c ../dev/mbr.c
 DSRCS += ../dev/propio2.c ../dev/ds1302.c
-DSRCS += ../dev/devfd.c
+DSRCS += ../dev/devfd.c ../dev/ppide_rbc.c
 
-DASRCS = ../dev/rbcfd9266_hw.s
+DASRCS = ../dev/rbcfd9266_hw.s ../dev/ds1302_rbc.s
 
 NSRCS = 
 
index bafd590..ed19918 100644 (file)
@@ -1,6 +1,7 @@
 ;
-;      We have no real common on the TRS80so just tuck it up at the top of
-;      memory leaving room for the keyboard and video (3K)
+;      The common memory area traditionally starts with the udata and the
+;      interrupt stacks. As this is standard in almost all cases you can
+;      just include the standard implementation.
 ;
         .module commonmem
 
index 3703edc..b9e6bb3 100644 (file)
@@ -9,20 +9,50 @@
 
 extern int strcmp(const char *, const char *);
 
-/* Could move to discard */
+/*
+ *     Everything in this file ends up in discard which means the moment
+ *     we try and execute init it gets blown away. That includes any
+ *     variables declared here so beware!
+ */
+
+/*
+ *     We get passed each kernel command line argument. if we return 1 then
+ *     we claim it, if not it gets passed to init. It's perfectly acceptable
+ *     to act on a match and return to also pass it to init if you need to.
+ */
 uint8_t platform_param(unsigned char *p)
 {
        used(p);
-       if (strcmp(p, "msr") == 0)
+       if (strcmp(p, "msr") == 0) {
                timermsr = 1;
+               return 1;
+        }
        return 0;
 }
 
+/*
+ *     Set up our memory mappings. This is not needed for simple banked memory
+ *     only more complex setups such as 16K paging.
+ */
 void map_init(void)
 {
 }
 
-/* Kernel in bank 0, user in banks 1-14, high 32K is bank 15 */
+/*
+ *     Add all the available pages to the list of pages we an use. If this
+ *     is runtime dynamic check to make sure you don't add more than MAX_MAPS
+ *     of them. On some machines with a lot of RAM the implementation turns
+ *     the excess into a RAM disc
+ *
+ *     The mapping can be logical numbers 1-n, or can be physical values to
+ *     write into registers. Whatever works best. The 0 value is however
+ *     reserved throughout to indicate kernel mode in calls, and also
+ *     to mean swapped out for processes. If your bank 0 is user space you
+ *     might need to just dec/inc before using it in an I/O port or similar
+ *     to avoid confusion.
+ *
+ *     Kernel in bank 0, user in banks 1-14, high 32K is bank 15
+ */
 void pagemap_init(void)
 {
        uint8_t i;
@@ -30,6 +60,11 @@ void pagemap_init(void)
                pagemap_add(i);
 }
 
+/*
+ *     This function is called for partitioned devices if a partition is found
+ *     and marked as swap type. The first one found will be used as swap. We
+ *     only support one swap device.
+ */
 void platform_swap_found(uint8_t letter, uint8_t m)
 {
   blkdev_t *blk = blk_op.blkdev;
@@ -46,6 +81,10 @@ void platform_swap_found(uint8_t letter, uint8_t m)
     swapmap_add(n--);
 }
 
+/*
+ *     Called after interrupts are enabled in order to enumerate and set up
+ *     any devices. In our case we simply need to probe the IDE and SD card.
+ */
 void device_init(void)
 {
        devide_init();
diff --git a/Kernel/platform-sbcv2/ds1302-n8vem.s b/Kernel/platform-sbcv2/ds1302-n8vem.s
deleted file mode 100644 (file)
index 87a95bc..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-; 2015-02-19 Sergey Kiselev
-; 2014-12-31 William R Sowerbutts
-; N8VEM SBC / Zeta SBC DS1302 real time clock interface code
-;
-;      FIXME: belongs in dev/
-;
-
-        .module ds1302-n8vem
-
-        ; exported symbols
-        .globl _ds1302_set_pin_ce
-        .globl _ds1302_set_pin_clk
-        .globl _ds1302_set_pin_data
-        .globl _ds1302_set_pin_data_driven
-        .globl _ds1302_get_pin_data
-
-        .include "kernel.def"
-        .include "../kernel.def"
-
-; -----------------------------------------------------------------------------
-; DS1302 interface
-; -----------------------------------------------------------------------------
-
-N8VEM_RTC       = 0x70
-PIN_CE          = 0x10
-PIN_DATA_HIZ    = 0x20
-PIN_CLK         = 0x40
-PIN_DATA_OUT    = 0x80
-PIN_DATA_IN     = 0x01
-
-.area _DATA
-
-rtc_shadow:     .db 0           ; we can't read back the latch contents, so we must keep a copy
-
-.area _CODE
-
-_ds1302_get_pin_data:
-        in a, (N8VEM_RTC)       ; read input register
-        and #PIN_DATA_IN        ; mask off data pin
-        ld l, a                 ; return result in L
-        ret
-
-_ds1302_set_pin_data_driven:
-        ld hl, #2               ; get address of function argument
-        add hl, sp
-        ld b, (hl)              ; load argument from stack
-        ld a, (rtc_shadow)
-        and #~PIN_DATA_HIZ      ; 0 - output pin
-        bit 0, b                ; test bit
-        jr nz, writereg
-        or #PIN_DATA_HIZ
-        jr writereg
-
-_ds1302_set_pin_data:
-        ld bc, #(((~PIN_DATA_OUT) << 8) | PIN_DATA_OUT)
-        jr setpin
-
-_ds1302_set_pin_ce:
-        ld bc, #(((~PIN_CE) << 8) | PIN_CE)
-        jr setpin
-
-_ds1302_set_pin_clk:
-        ld bc, #(((~PIN_CLK) << 8) | PIN_CLK)
-        jr setpin
-
-setpin:
-        ld a, (rtc_shadow)      ; load current register contents
-        and b                   ; unset the pin
-        ld hl, #2               ; get address of function argument
-        add hl, sp
-        ld b, (hl)              ; load argument from stack
-        bit 0, b                ; test bit
-        jr z, writereg          ; arg is false
-        or c                    ; arg is true
-writereg:
-        out (N8VEM_RTC), a      ; write out new register contents
-        ld (rtc_shadow), a      ; update our shadow copy
-        ret
-
diff --git a/Kernel/platform-sbcv2/ppide.c b/Kernel/platform-sbcv2/ppide.c
deleted file mode 100644 (file)
index 1d89cb7..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* 2015-04-24 WRS: devide glue functions for PPIDE */
-/* FIXME: move to dev */
-
-#include <kernel.h>
-#include <kdata.h>
-#include <printf.h>
-#include <stdbool.h>
-#include <timer.h>
-#include <devide.h>
-#include <blkdev.h>
-
-__sfr __at (PPIDE_BASE + 0x00) ppi_port_a;   /* IDE bus LSB */
-__sfr __at (PPIDE_BASE + 0x01) ppi_port_b;   /* IDE bus MSB */
-__sfr __at (PPIDE_BASE + 0x02) ppi_port_c;   /* IDE bus control signals */
-__sfr __at (PPIDE_BASE + 0x03) ppi_control;  /* 8255 command register */
-
-void ppide_init(void)
-{
-    ppi_control = PPIDE_PPI_BUS_READ;
-    ppi_port_c = ide_reg_status;
-}
-
-uint8_t devide_readb(uint8_t regaddr)
-{
-    uint8_t r;
-
-    /* note: ppi_control should contain PPIDE_PPI_BUS_READ already */
-    ppi_port_c = regaddr;
-    ppi_port_c = regaddr | PPIDE_RD_LINE; /* begin /RD pulse */
-    r = ppi_port_a;
-    ppi_port_c = regaddr;       /* end /RD pulse */
-    return r;
-}
-
-void devide_writeb(uint8_t regaddr, uint8_t value)
-{
-    ppi_control = PPIDE_PPI_BUS_WRITE;
-    ppi_port_c = regaddr;
-    ppi_port_a = value;
-    ppi_port_b = 0;
-    ppi_port_c = regaddr | PPIDE_WR_LINE;
-    /* FIXME: check timing */
-    ppi_port_c = regaddr;
-    ppi_control = PPIDE_PPI_BUS_READ;
-}
-
-/****************************************************************************/
-/* The innermost part of the transfer routines has to live in common memory */
-/* since it must be able to bank switch to the user memory bank.            */
-/****************************************************************************/
-COMMON_MEMORY
-
-void devide_read_data(void) __naked
-{
-    __asm
-            ld a, #ide_reg_data
-            ld c, #PPIDE_BASE+2                     ; select control lines
-            out (c), a                              ; select IDE data register
-            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
-            ld d, #ide_reg_data                     ; register address
-            ld e, #ide_reg_data | PPIDE_RD_LINE     ; register address with /RD asserted
-            ld b, #0                                ; setup count
-            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
-            or a                                    ; test is_user
-            push af                                 ; save flags
-            ld a, #PPIDE_BASE+0                     ; I will be needing this later
-            call nz, map_process_always             ; map user memory first if required
-goread:     ; now we do the transfer
-            out (c), e                              ; assert /RD
-            ld c, a                                 ; PPIDE_BASE
-            ini                                     ; read byte from LSB
-            inc c                                   ; up to MSB
-            ini                                     ; read byte from MSB
-            inc c                                   ; control lines
-            out (c), d                              ; de-assert /RD
-            inc b                                   ; (delay) counteract second ini instruction
-            jr nz, goread                           ; (delay) next word
-            ; read completed
-            pop af                                  ; recover is_user test result
-            ret z                                   ; done if kernel memory transfer
-            jp map_kernel                           ; else map kernel then return
-    __endasm;
-}
-
-void devide_write_data(void) __naked
-{
-    __asm
-            ld c, #PPIDE_BASE+2                     ; select control lines
-            ld a, #ide_reg_data
-            out (c), a                              ; select data register
-            ld a, #PPIDE_PPI_BUS_WRITE
-            inc c                                   ; up to 8255A command register
-            out (c), a                              ; 8255A ports A, B to output mode
-            dec c                                   ; back down to the control lines
-            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
-            ld d, #ide_reg_data                     ; register address
-            ld e, #ide_reg_data | PPIDE_WR_LINE     ; register address with /WR asserted
-            ld b, #0                                ; setup count
-            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
-            or a                                    ; test is_user
-            push af                                 ; save flags
-            ld a, #PPIDE_BASE+0                     ; I will be needing this later
-            call nz, map_process_always             ; map user memory first if required
-gowrite:    ; now we do the transfer
-            out (c), d                              ; de-assert /WR
-            ld c, a                                 ; PPIDE_BASE
-            outi                                    ; write byte to LSB
-            inc c                                   ; up to MSB
-            outi                                    ; write byte to MSB
-            inc c                                   ; up to control lines
-            out (c), e                              ; assert /WR
-            inc b                                   ; (delay) offset to counteract second outi instruction
-            jr nz, gowrite                          ; (delay) next word
-            ; write completed
-            out (c), d                              ; de-assert /WR
-            ld a, #PPIDE_PPI_BUS_READ
-            inc c                                   ; up to 8255A command register
-            out (c), a                              ; 8255A ports A, B to read mode
-            pop af                                  ; recover is_user test result
-            ret z                                   ; done if kernel memory transfer
-            jp map_kernel                           ; else map kernel then return
-    __endasm;
-}
index a061855..9bdcea9 100644 (file)
@@ -1,5 +1,8 @@
 ;
 ;          SBC v2 support
+;
+;      This first chunk is mostly boilerplate to adjust for each
+;      system.
 ;
 
             .module sbcv2
 
 _bufpool:
            .ds BUFSIZE * NBUFS
-;
+
+; -----------------------------------------------------------------------------
 ; COMMON MEMORY BANK (kept even when we task switch)
-;
+; -----------------------------------------------------------------------------
             .area _COMMONMEM
 
+;
+;      This method is invoked early in interrupt handling before any
+;      complex handling is done. It's useful on a few platforms but
+;      generally a ret is all that is needed
+;
 platform_interrupt_all:
            ret
 
-; FIXME: map ROM and jump into it
+;
+;      If you have a ROM monitor you can get back to then do so, if not
+;      fall into reboot.
+;
 _platform_monitor:
+;
+;      Reboot the system if possible, halt if not. On a system where the
+;      ROM promptly wipes the display you may want to delay or wait for
+;      a keypress here (just remember you may be interrupts off, no kernel
+;      mapped so hit the hardware).
+;
 _platform_reboot:
            di
            xor a
@@ -72,10 +90,12 @@ _platform_reboot:
 ; -----------------------------------------------------------------------------
            .area _CODE
 
+           .globl _ttymap
 ;
-;      We will address this one better when we do some ROMWBW integration
+;      This routine is called very early, before the boot code shuffles
+;      things into place. We do the ttymap here mostly as an example but
+;      even that really ought to be in init_hardware.
 ;
-           .globl _ttymap
 init_early:
            ; FIXME: code goes here to check for PropIO v2 nicely
            ; Passes the minimal checking
@@ -92,8 +112,20 @@ init_early:
            ld (_ttymap+1), hl          ; set tty map to 0,2,1 for prop
            ret
 
+; -----------------------------------------------------------------------------
+; DISCARD is memory that will be recycled when we exec init
+; -----------------------------------------------------------------------------
            .area _DISCARD
-
+;
+;      After the kernel has shuffled things into place this code is run.
+;      It's the best place to breakpoint or trace if you are not sure your
+;      kernel is loading and putting itself into place properly.
+;
+;      It's required jobs are to set up the vectors, ramsize (total RAM),
+;      and procmem (total memory free to processs), as well as setting the
+;      interrupt mode but *not* enabling interrupts. Many platforms also
+;      program up support hardware like PIO and CTC devices here.
+;
 init_hardware:
            ld hl,#512
             ld (_ramsize), hl
@@ -110,17 +142,23 @@ init_hardware:
 
             ret
 
-;------------------------------------------------------------------------------
-; COMMON MEMORY PROCEDURES FOLLOW
-
+;
+;      Bank switching unsurprisingly must be in common memory space so it's
+;      always available.
+;
             .area _COMMONMEM
 
-mapreg:    .db 0
-mapsave:   .db 0
+mapreg:    .db 0       ; Our map register is write only so keep a copy
+mapsave:   .db 0       ; Saved copy of the previous map (see map_save)
 
 _kernel_flag:
            .db 1       ; We start in kernel mode
 
+;
+;      This is invoked with a NULL argument at boot to set the kernel
+;      vectors and then elsewhere in the kernel when the kernel knows
+;      a bank may need vectors writing to it.
+;
 _program_vectors:
             ; we are called, with interrupts disabled, by both newproc() and crt0
            ; will exit with interrupts off
@@ -164,12 +202,20 @@ map_kernel:
            out (0x78), a
            pop af
            ret
+           ; map_process is called with HL either NULL or pointing to the
+           ; page mapping. Unlike the other calls it's allowed to trash AF
 map_process:
            ld a, h
            or l
            jr z, map_kernel
 map_process_hl:
-           ld a, (hl)
+           ld a, (hl)                  ; and fall through
+           ;
+           ; With a simple bank switching system you need to provide a
+           ; method to switch to the bank in A without corrupting any
+           ; other registers. The stack is safe in common memory.
+           ; For swap you need to provide what for simple banking is an
+           ; identical routine.
 map_for_swap:
 map_process_a:                 ; used by bankfork
            dec a               ; We bias by 1 because 0 is a valid user
@@ -178,6 +224,10 @@ map_process_a:                     ; used by bankfork
            inc a               ; cheaper than push/pop
             ret
 
+           ;
+           ; Map the current process into memory. We do this by extracting
+           ; the bank value from u_page.
+           ;
 map_process_always:
            push af
            push hl
@@ -187,12 +237,20 @@ map_process_always:
            pop af
            ret
 
+           ;
+           ; Save the existing mapping. The place you save it to needs to
+           ; be in common memory as you have no idea what bank is live
+            ;
 map_save:   push af
            ld a, (mapreg)
            ld (mapsave), a
            pop af
            ret
-
+           ;
+           ; Restore the saved bank. Note that you don't need to deal with
+           ; stacking of banks (we never recursively use save/restore), and
+           ; that we may well call save and decide not to call restore.
+           ;
 map_restore:
            push af
            ld a, (mapsave)
@@ -201,6 +259,11 @@ map_restore:
            pop af
            ret
            
+           ;
+           ; Used for low level debug. Output the character in A without
+           ; corrupting other registers. May block. Interrupts and memory
+           ; state are undefined
+           ;
 outchar:
            push af
 twait:     in a,(0x6D)
@@ -213,6 +276,10 @@ twait:         in a,(0x6D)
 ;
 ;      PropIO v2 block transfers
 ;
+;      This is glue specific to the PropIO driver to customise it for a
+;      given platform. Basically it's the code in common space to do the
+;      data transfer into any bank.
+;
 
 ; FIXME: Move these somewhere better
 BLKPARAM_ADDR_OFFSET           .equ    0
@@ -234,7 +301,7 @@ _platform_prop_sd_read:
            jr nz, do_read_a
            ld a, (U_DATA__U_PAGE)
 do_read_a:  call map_process_a
-do_read:   ld bc,#0xAB
+do_read:    ld bc,#0xAB
            inir
            inir
            jp map_kernel
index ee50c07..1eaafca 100644 (file)
@@ -1,4 +1,12 @@
-
+;
+;      For simple banked systems there is a standard implementation. The
+;      only reason to do otherwise is for speed. A custom bank logic aware
+;      bank to bank copier will give vastly better fork() performance.
+;
+;      As this is meant to be a simple reference port we use the standard
+;      approach. The morbidly curious can read the TRS80 model 1 bank to
+;      bank copier.
+;
        .include "../kernel.def"
        .include "kernel.def"