From edf3d6272c315759ed33a7a800c6952a71646a0a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 12 Apr 2015 17:45:44 +0100 Subject: [PATCH] zx128, microdrive: Microdrive write support Still somewhat fragile --- Kernel/platform-zx128/devmdv.c | 7 +++ Kernel/platform-zx128/microdrive.s | 84 ++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/Kernel/platform-zx128/devmdv.c b/Kernel/platform-zx128/devmdv.c index e772bbff..17e22cd2 100644 --- a/Kernel/platform-zx128/devmdv.c +++ b/Kernel/platform-zx128/devmdv.c @@ -19,6 +19,8 @@ static uint8_t mdv_valid; /* Used by the asm helpers */ uint8_t *mdv_buf; uint8_t mdv_hdr_buf[15]; +uint8_t mdv_w_hdr_buf[15+12]; + uint8_t mdv_sector; uint16_t mdv_len; uint8_t mdv_page; @@ -80,6 +82,11 @@ static int mdv_transfer(uint8_t minor, bool is_read, uint8_t rawflag) else err = mdv_bwrite(); irqrestore(irq); + if (err) { + kprintf("mdv%d: %c error %d\n", minor, "wr"[is_read], + err); + goto bad; + } mdv_buf += 512; } return 0; diff --git a/Kernel/platform-zx128/microdrive.s b/Kernel/platform-zx128/microdrive.s index 5bb5b102..ffd57732 100644 --- a/Kernel/platform-zx128/microdrive.s +++ b/Kernel/platform-zx128/microdrive.s @@ -19,6 +19,10 @@ ; there is an "erase" command. When running as a pseudo-floppy we ; don't have that. Instead we keep a blockmap table in physical 1 and ; 128. +; +; +; FIXME: currently if we find the block but get a bad csum we can +; loop effectively forever. ; .module microdrive @@ -31,6 +35,7 @@ .globl _mdv_sector .globl _mdv_buf .globl _mdv_hdr_buf + .globl _mdv_w_hdr_buf .globl _mdv_len .globl _mdv_page .globl _mdv_csum @@ -42,6 +47,7 @@ SECTORID .equ 0x01 CSUM .equ 0x0E +MAP_PREAMBLE .equ 0x0C nap_1ms: push de ld de, #87 @@ -57,18 +63,28 @@ napl: dec de ; Must preserve E ; mdv_csum_hdr: + ld hl, #_mdv_hdr_buf ; header buffer +mdv_csum_hdr_2: + ld bc, #0x0E01 ; 14 bytes + call mdv_csum_data + cp (hl) + ret +mdv_csum_w_hdr: + ld hl, #_mdv_w_hdr_buf + MAP_PREAMBLE + jr mdv_csum_hdr_2 + +mdv_csum_data: xor a - ld b, #14 - ld hl, #_mdv_hdr_buf -csum_hdr: ; check the header is valid +csum_data2: add (hl) adc #1 inc hl - jr z, csum_h0 + jr z, csum_d2 dec a -csum_h0: - djnz csum_hdr - cp (hl) +csum_d2: + djnz csum_data2 + dec c + jr nz, csum_data2 ret ; @@ -237,26 +253,14 @@ mdv_get_blk: ld hl, #0x0F02 ; 15 + 2 loops (data) + csum in e ; Sum the header block call mdv_csum_hdr jr nz, failblk - - ld hl, (_mdv_buf) ; now the data ld bc, #2 ; 2 x 256 byte runs - xor a -csum_data2: - add (hl) - adc #1 - inc hl - jr z, csum_d2 - dec a -csum_d2: - djnz csum_data2 - dec c - jr nz, csum_data2 - cp e ; expected csum - ret z ; good block + call mdv_csum_data ; checksum data into a + cp e ; expected csum + ret z ; good block ld a, #2 out (0xfe), a - ; try again + ; try again failblk: ret @@ -269,7 +273,7 @@ mdv_put_blk: ld a, #0xE6 call nap ; May need to be a shade ; longer. Compare timings ; with Sinclair ROM - ld hl, #_mdv_hdr_buf ; Header to write first + ld hl, #_mdv_w_hdr_buf ; Header to write first ld a, (_mdv_csum) ld e, a ld a, #0x03 ; Magneta border @@ -283,7 +287,7 @@ mdv_put_blk: ld a, #0xE6 nop nop ld c, #0xE7 ; Data port - ld b, #0x1E ; Header + ld b, #0x0F ; Header otir ; Header bytes out ld hl, (_mdv_buf) otir ; First 256 data @@ -299,11 +303,37 @@ mdv_put_blk: ld a, #0xE6 ret ; +; Template for writes +buftmplt: + .db 0, 0, 0, 0 + .db 0, 0, 0, 0 + .db 0, 0, 0xff, 0xff ; preamble + .db 0 ; block not header + .db 0 ; sector + .db 0 ; length low + .db 2 ; length high + .ascii "FUZIX " ; filler basically +; ; Write a sector from memory ; -mdv_store: in a, (0xef) +mdv_store: ld hl, (_mdv_buf) + ld bc, #2 ; 512 bytes + call mdv_csum_data ; checksum into A + ld (_mdv_csum), a ; save ready to write + ; + ; Now fill in the header on the data bloc + ; + ld hl, #buftmplt + ld de, #_mdv_w_hdr_buf + ld bc, #14+MAP_PREAMBLE + ldir + ld a, (_mdv_sector) ; fill in the sector + ld (_mdv_w_hdr_buf + MAP_PREAMBLE + 1), a + call mdv_csum_w_hdr ; checksum + ld (hl), a ; fill in the checksum + in a, (0xef) and #1 - jr nz, mdv_put_wp ; write protected + jr z, mdv_put_wp ; write protected call mdv_find_hdr ; find the header we want call z, mdv_put_blk ; write the block after it ret ; done -- 2.34.1