px4plus: further updates mostly to the cartridge RAM logic
authorAlan Cox <alan@linux.intel.com>
Fri, 27 Mar 2015 23:27:01 +0000 (23:27 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 27 Mar 2015 23:27:01 +0000 (23:27 +0000)
Kernel/platform-px4plus/config.h
Kernel/platform-px4plus/devfd.c
Kernel/platform-px4plus/main.c
Kernel/platform-px4plus/sio.c
Kernel/platform-px4plus/sio.h
Kernel/platform-px4plus/swapdev.s

index b08190c..d74610d 100644 (file)
@@ -16,7 +16,7 @@
 #undef CONFIG_CPM_EMU
 /* Fixed banking (although we must do magic in tricks.s to fake banking */
 #define CONFIG_BANK_FIXED
-#define MAX_MAPS       7
+#define MAX_MAPS       7               /* also appears in kernel.def */
 #define MAP_SIZE       0x8000
 /* Swap only */
 #undef CONFIG_SWAP_ONLY
@@ -48,7 +48,7 @@
 #define NUM_DEV_TTY 2
 
 #define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
-#define SWAPDEV  (256 + 0)  /* Device for swapping. (ram drive) */
+#define SWAPDEV  (1)     /* Device for swapping. (second floppy) */
 #define NBUFS    6        /* Number of block buffers */
 #define NMOUNTS         2        /* Number of mounts at a time */
 
@@ -57,5 +57,3 @@
 #define VT_RIGHT       29
 #define VT_BOTTOM      7
 
-
-#define PFTABSIZE      5       /* All we have room for right now */
index f7bd4cc..871a745 100644 (file)
@@ -109,7 +109,15 @@ int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
                 /* We need a special I/O helper for swapping out as we may
                    be swapping memory from an I/O mapped ram device to
                    the floppy disc */
-                read_from_bank(page, dptr, buf + 0x09, 128);
+                if (rawflag == 0)
+                    memcpy(buf + 0x09, (uint8_t *)dptr, 128);
+                else {
+                    romd_off = dptr;
+                    romd_addr = (uint16_t)buf + 0x09;
+                    romd_size = 128;
+                    romd_mode = page;
+                    read_from_bank();
+                }
                 sio_write(buf, 0x89);
                 err = sio_read(buf, 0x06);
                 if (!err)
index 87ed387..39bdbce 100644 (file)
@@ -28,6 +28,7 @@ void platform_interrupt(void)
 }
 
 extern uint8_t map_translate[MAX_MAPS];
+extern uint8_t *map_live;
 
 /* Add map numbers. These are logical mappings one of which is the current
    memory image and the others indexes into the sidecar or cartridge memory.
@@ -58,6 +59,7 @@ void pagemap_init(void)
                *p++ = ct--;
                pagemap_add(i);
        }
+       map_live = p - 1;       /* We add RAM last */
 }
 
 void map_init(void)
index 53e44a1..6505683 100644 (file)
@@ -24,6 +24,13 @@ void deselect_sio(int old)
 __sfr __at 0x14 artwr;
 __sfr __at 0x15 artsr;
 
+/*
+ *     FIXME:
+ *     For these functions we need to switch to a different very fast IRQ
+ *     handler which simply counts timer ticks, then when we finish the
+ *     sio transfers we can run all the missed timer handling.
+ */
+
 void sio_write(uint8_t *buf, int len)
 {
   while(len--) {
index 260f3b3..ea67ec1 100644 (file)
@@ -8,6 +8,6 @@ extern void sio_write(uint8_t *buf, int len);
 extern int sio_read(uint8_t *buf, int len);
 
 /* These don't truely belong here but it will do for now */
-extern void read_from_bank(uint16_t bank, uint16_t dptr, uint8_t *buf, uint16_t len);
+extern void read_from_bank(void);
 
 #endif
\ No newline at end of file
index de6397e..9eb1fb2 100644 (file)
@@ -1,5 +1,22 @@
 ;
-;      Support code for swap device activity
+;      Support code for mmio RAM based swap devices used as if they were
+;      banked memory. We could have made them swap but its faster to treat
+;      them as memory and do switching and exchanges. It also allows us to
+;      avoid the cost of having an empty space as needed for swap out and
+;      then swap in. On a PX4 with a single 32K cartridge that is critical.
+;
+;      The key element here is the map translation table. Each of the
+;      logical banks has a 1 byte entry that gives its current location
+;      as either
+;              1 - RAM
+;              2 - Cartridge, low 32K
+;              3 - Cartridge, high 32K (if present)
+;              0x80-0x83 - Sidecar in 32K chunks
+;
+;      When we "switch" to a bank we actually swap the RAM contents with
+;      the I/O memory that held the bank we switched to, and then we fix
+;      up the table. That makes all the magic going on conveniently
+;      invisible to the core code.
 ;
 
                .globl _cartridge_copy
                .globl _map_translate
                .globl _map_live
 
+               .globl _read_from_bank
+
+               .globl _romd_addr
+               .globl _romd_off
+               .globl _romd_size
+               .globl _romd_mode       ; byte size
+
+               .globl map_process_save
+               .globl map_kernel_restore
+
+               .module swapdev
+
+               .include "kernel.def"
 
                .area _COMMONMEM
 
+;
+;      Copy the RAM into the given bank in the cartridge. This is used when
+;      we do a fork.
 ;
 ;      A holds the bank to use (1 = RAM 2/3 for cartridge 128+ sidecar
 ;
@@ -48,7 +81,8 @@ cart_copy256:
                ret
 
 ;
-;      Exchange the process in bank a with the process in RAM
+;      Exchange the process in bank a with the process in RAM. This is
+;      used when we do a task switch between two processes.
 ;
 _cartridge_exchange:
                push bc
@@ -86,7 +120,10 @@ cart_x256:
 
 
                .area _CODE
-
+;
+;      Compute the size of a cartridge. We can only use 32K sized chunks,
+;      so the 16K cartridge while detected is useless.
+;
 _cartridge_size:
                ld c, #0xA512
                xor a
@@ -114,6 +151,11 @@ size32:
 
                .area _COMMONMEM
 
+;
+;      A holds the sidecar bank to use with bit 7 set. We call this
+;      function when we are forking a process so that we can write a copy
+;      of RAM into the other bank (where it will become the parent)
+;
 _sidecar_copy:
                push bc
                push de
@@ -140,6 +182,11 @@ sidecar_cnext:
                pop bc
                ret
 
+;
+;      Exchange RAM and the process in sidecar bank A (with bit 7 set).
+;      Used when we are task switching. This is rather ugly as the
+;      sidecar memory helpfully auto-increments the low byte!
+;
 _sidecar_exchange:
                push bc
                push de
@@ -179,9 +226,11 @@ sidecar_xnl:
                ret
 
 ;
-;      Make the requested process the current one in memory. We use this
-;      on task switching but also on the floppy I/O when swapping in or
-;      out. Preserves DE.
+;      Make the requested bank the current one in memory. We use this
+;      when task switching. It's the PX4 logical equivalent of the out
+;      instructions on saner ports that switch context. It must be called
+;      on a private stack as it will exchange the kernel/irq stacks of the
+;      old and new task as it runs.
 ;
 _make_mapped:
                ld c, a
@@ -212,3 +261,85 @@ in_sidecar:
 in_memory2:
                pop de                  ; recover task pointer
                ret
+
+;
+;      We have to deal with the awkward case of I/O wanting to access other
+;      banks for swapping. On a normal setup this is fairly trivial, in our
+;      case the memory they want to copy may in fact be stuffed into an I/O
+;      mapped device so we need to do some gymnastics.
+;
+_read_from_bank:       ; (page, dptr, buf) always 128 bytes
+               ld de, (_romd_mode)
+               ld d, #0
+               ld hl, #_map_translate
+               add hl, de
+               ld a, (hl)              ; Translation entry
+               cp #1
+               jr z, memory_read       ; It is in RAM
+               ;
+               ; Turn virtual address into offset in swap in HL as both
+               ; other methods need this
+               ;
+               ld hl, (_romd_off)      ; in bytes, userspace ptr
+               ld de, #SWAP_VTOP
+               or a
+               sbc hl, de              ; convert to zero based
+               bit 7, a                ; cartridge is 2/3
+               jr z, cartridge_read
+               ;
+               ; Pull it from the sidecar (0x80-0x83)
+               ;
+               ld b, #0
+               rra                     ; effectively multiply by 32768
+               rr b                    ; 0x0 or 0x80
+               and #0x3f               ; 32K per process
+               out (0x92), a           ; select right 64K bank
+               ;
+               ; Now work out which 256 byte page is needed
+               ;
+               ld a, h
+               add b                   ; 32K low bit of bank number
+               out (0x91), a           ; middle byte of I/O offset
+               ld a, l
+               out (0x90), a           ; low byte of I/O offset
+               ld bc, #0x8093          ; 128 count, port 92)
+               ld hl, (_romd_addr)
+               inir                    ; 128 bytes into hl
+               ret
+;
+;              2 is the low 32K, 3 the high
+;
+cartridge_read:
+               cp #2
+               jr z, cart_read_1
+               set 7,h                 ; offset by another 32K
+cart_read_1:
+               ld a, h
+               out (0x10), a           ; set high byte
+               ld de, (_romd_addr)
+               ld b, #0x80             ; 128 bytes
+cart_read_l:
+               ld a, l                 ; sufficient as this won't
+               out (0x11), a           ; cross a page
+               in a, (0x12)
+               ld (de), a
+               inc de
+               inc l
+               djnz cart_read_l
+               ret
+;
+;              Pull 128 bytes from user space. We pull a trick here.
+;              We are copying between user space and kernel writable data.
+;              Only R/O space is banked on the PX4 systems so we don't need
+;              to play bank pogo.
+;
+memory_read:
+               ld bc, #0x80
+               ld de, (_romd_addr)
+               call map_process_save
+               ldir
+               call map_kernel_restore
+               ret
+
+_map_translate:        .ds MAX_MAPS
+_map_live:     .dw 0