msx2 megasd: handle page crossings
authorgeijoenr <enric.geijo@gmail.com>
Tue, 30 May 2017 18:37:38 +0000 (20:37 +0200)
committergeijoenr <geijoenr@gmail.com>
Mon, 5 Jun 2017 18:23:50 +0000 (20:23 +0200)
Due to PROGLOAD being 0x0100, last block read
in a page overflows to the next one.

Kernel/platform-msx2/devmegasd.c

index 90690f6..868b8f7 100644 (file)
@@ -128,117 +128,58 @@ uint8_t sd_spi_receive_byte(void)
  * Target page is always mapped to slot_page2, and the target address offset accordingly.
  *
  */
-bool sd_spi_receive_sector(void) __naked
+void sd_spi_txrx_sector(bool is_read)
 {
-    __asm
-
-    ; map sd interface
-    ;
-    ld a,(_slotmfr)
-    call _mapslot_bank1
-    ld a, #MSD_PAGE
-    ld (MFR_BANKSEL0),a
-
-    ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET)
-    ld de, (_blk_op+BLKPARAM_ADDR_OFFSET)
-    push af
-    or a
-    jr z, starttx
-
-    ; map process target page in slot_page2 if needed
-    ;
-    ld a,d
-    and #0xC0
-    rlca
-    rlca    ;  a contains the page to map
-    ld b,#0
-    ld c,a
-    ld hl,#U_DATA__U_PAGE
-    add hl,bc
-    ld a,(hl)
-    out(_RAM_PAGE2),a
-
-starttx:
-    ; calculate offset address in target page
-    ld a,d
-    and #0x3F
-    or #0x80
-    ld d,a
-    ld hl,#MSD_RDWR
-    ld bc,#512
-    jp looptxrx
-    __endasm;
+    uint16_t addr, len, len2;
+    uint8_t *page;
+    uint8_t page_offset;
+
+    addr = ((uint16_t) blk_op.addr) % 0x4000 + 0x8000;
+    page_offset = (((uint16_t)blk_op.addr) / 0x4000);
+    page = &udata.u_page;
+
+    len = 0xC000 - addr;
+    sd_spi_map_interface();
+
+    if (blk_op.is_user) {
+        RAM_PAGE2 = *(page + page_offset);
+        if (is_read)
+                memcpy((uint8_t *)addr, (uint8_t *)MSD_RDWR,
+                        len < BLKSIZE ? len : BLKSIZE);
+        else
+                memcpy((uint8_t *)MSD_RDWR, (uint8_t *)addr,
+                        len < BLKSIZE ? len : BLKSIZE);
+        if (len < BLKSIZE) {
+                /* handle page crossing */
+                len2 = BLKSIZE - len;
+                RAM_PAGE2 = *(page + page_offset + 1);
+                if (is_read)
+                        memcpy((uint8_t *)0x8000, (uint8_t *)MSD_RDWR, len2);
+                else
+                        memcpy((uint8_t *)MSD_RDWR, (uint8_t *)0x8000, len2);
+        }
+        RAM_PAGE2 = 1;
+    } else {
+        /* kernel only */
+        if (is_read)
+                memcpy((uint8_t *)addr, (uint8_t *)MSD_RDWR, BLKSIZE);
+        else
+                memcpy((uint8_t *)MSD_RDWR, (uint8_t *)addr, BLKSIZE);
+    }
+    sd_spi_unmap_interface();
+}
+
+
+bool sd_spi_receive_sector(void)
+{
+    sd_spi_txrx_sector(true);
+    return true;
 }
 
-bool sd_spi_transmit_sector(void) __naked
+bool sd_spi_transmit_sector(void)
 {
-    __asm
-
-    ; map sd interface
-    ;
-    ld a,(_slotmfr)
-    call _mapslot_bank1
-    ld a, #MSD_PAGE
-    ld (MFR_BANKSEL0),a
-
-    ; map process target page in slot_page2
-    ;
-    ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET)
-    ld de, (_blk_op+BLKPARAM_ADDR_OFFSET);
-    push af
-    or a
-    jr z, startrx
-
-    ; map process target page in slot_page2 if needed
-    ;
-    ld a,d
-    and #0xC0
-    rlca
-    rlca    ;  a contains the page to map
-    ld b,#0
-    ld c,a
-    ld hl,#U_DATA__U_PAGE
-    add hl,bc
-    ld a,(hl)
-    out(_RAM_PAGE2),a
-
-startrx:
-    ; calculate offset address in target page
-    ld a,d
-    and #0x3F
-    or #0x80
-    ld d,a
-    ld hl,#MSD_RDWR
-    ex de,hl
-    ld bc,#512
-looptxrx:
-    ldi        ; 16x ldi: 19% faster
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    ldi
-    jp pe, looptxrx
-
-    ; unmap interface
-    ;
-    ld a,(_slotram)
-    call _mapslot_bank1
-    pop af
-    or a
-    ret z
-    jp _map_kernel
-    __endasm;
+    sd_spi_txrx_sector(false);
+    return true;
 }
 
 #endif