From 4844f442d2492bb014d581c6f005aaffe9e00c7e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 6 Apr 2019 22:33:57 +0100 Subject: [PATCH] sunrise: assorted fixes With these fixed we can mount the root fs and load stuff from the Sunrise IDE controller. There are a ton of races with switching and interrupts to fix after this --- Kernel/platform-msx1/devide_sunrise.c | 41 ++++++++++++---- Kernel/platform-msx1/sunrise.s | 68 ++++++++++++++++++++------- 2 files changed, 85 insertions(+), 24 deletions(-) diff --git a/Kernel/platform-msx1/devide_sunrise.c b/Kernel/platform-msx1/devide_sunrise.c index 57db3c36..4f7548f6 100644 --- a/Kernel/platform-msx1/devide_sunrise.c +++ b/Kernel/platform-msx1/devide_sunrise.c @@ -6,8 +6,8 @@ #include #include -uint8_t ide_error; -uint16_t ide_base; +uint16_t ide_error; +uint16_t ide_base = 0x7E00; uint8_t *devide_buf; struct msx_map sunrise_u, sunrise_k; @@ -27,22 +27,42 @@ static uint8_t sunrise_transfer_sector(void) uint8_t drive = (blk_op.blkdev->driver_data & IDE_DRIVE_NR_MASK); uint8_t mask = drive ? 0xF0 : 0xE0; uint8_t *addr = blk_op.addr; + uint8_t old_user = blk_op.is_user; - if (blk_op.is_read) + if (!blk_op.is_read) blk_op.blkdev->driver_data |= FLAG_CACHE_DIRTY; /* Shortcut: this range can only occur for a user mode I/O */ if (addr >= (uint8_t *)0x3E00U && addr <= (uint8_t *)0x8000U) { blk_op.addr = tmpbuf(); blk_op.is_user = 0; - if (do_ide_xfer(mask) == 0) - goto fail; - uput(blk_op.addr, addr, 512); + kprintf("bounced do_ide_xfer %p %x\n", addr, mask); + if (blk_op.is_read) { + if (do_ide_xfer(mask)) + goto fail; + kputs("uput.\n"); + di();// FIXME + uput(blk_op.addr, addr, 512); + ei();// FIXME + kputs("uputdone.\n"); + } else { + uget(addr, blk_op.addr, 512); + if (do_ide_xfer(mask) == 0) + goto fail; + } tmpfree(blk_op.addr); + kprintf("bounced done.\n"); + blk_op.addr = addr; + blk_op.is_user = old_user; return 1; } - if (do_ide_xfer(mask)) + kprintf("do_ide_xfer %d %p %x\n", blk_op.is_user, addr, mask); + if (do_ide_xfer(mask) == 0) { + kputs("done.\n"); return 1; + } fail: + blk_op.addr = addr; + blk_op.is_user = old_user; if (ide_error == 0xFF) kprintf("ide%d: timeout.\n", drive); else @@ -104,6 +124,7 @@ static void sunrise_init_drive(uint8_t drive) blkdev_scan(blk, SWAPSCAN); return; failout: + kputs("\n"); tmpfree(devide_buf); } @@ -117,7 +138,11 @@ void sunrise_probe(uint8_t slot, uint8_t subslot) /* Generate and cache the needed mapping table */ memcpy(&sunrise_k, map_slot1_kernel(i), sizeof(sunrise_k)); memcpy(&sunrise_u, map_slot1_user(i), sizeof(sunrise_k)); - + + kprintf("sunrise_k: %x %x %x %x %x %x\n", + sunrise_k.private[0], sunrise_k.private[1], sunrise_k.private[2], + sunrise_k.private[3], sunrise_k.private[4], sunrise_k.private[5]); + do_ide_begin_reset(); delay(); do_ide_end_reset(); diff --git a/Kernel/platform-msx1/sunrise.s b/Kernel/platform-msx1/sunrise.s index 4d60b489..4066f6ca 100644 --- a/Kernel/platform-msx1/sunrise.s +++ b/Kernel/platform-msx1/sunrise.s @@ -21,6 +21,11 @@ .globl _sunrise_u .globl _sunrise_k + .globl outcharhex + .globl outhl + + .module sunrise + IDE_REG_ERROR .equ 1 IDE_REG_FEATURES .equ 1 IDE_REG_SEC_COUNT .equ 2 @@ -52,7 +57,12 @@ BLK_OP_ISUSER .equ 2 BLK_OP_LBA .equ 6 BLK_OP_ISREAD .equ 12 + + .area _COMMONMEM + devide_wait_ready: + xor a + ld (_ide_error),a ld a,#IDE_STATUS_READY devide_wait: push de @@ -70,23 +80,26 @@ wait_nbusy: jr nz, wait_nbusy ; Check for an error bit IDE_ERROR,a - jr nz, error + jr z, noerror + ld (_ide_error),a + ld a,IDE_REG_ERROR(ix) + ld (_ide_error + 1),a + jr waitout +noerror: ; Now see if it's a good status and c cp c jr nz, wait_nbusy ; We have !busy, !error and the value we wanted - done +waitout: pop hl pop de ret ; Z = good wait_timeout: ld a,#255 ; NZ is set already -error: ld (_ide_error),a ; save the value ; NZ set already - pop hl - pop de - ret + jr waitout ; ; Flip I/O maps @@ -94,13 +107,17 @@ error: map_sunrise_k: push hl ld hl,#_sunrise_k + di call _switch_map + ei pop hl ret map_sunrise_u: push hl ld hl,#_sunrise_u + di call _switch_map + ei pop hl ret ; @@ -109,18 +126,27 @@ map_sunrise_u: _do_ide_init_drive: push ix ld ix,(_ide_base) + ld a,#'i' + out (0x2f),a call map_sunrise_k + ld a,#'I' + out (0x2f),a ld IDE_REG_DEVHEAD(ix),l ld hl,#0 call devide_wait_ready jr nz, timeout + ld a,#'D' + out (0x2f),a ld IDE_REG_COMMAND(ix),#IDE_CMD_IDENTIFY ld a,#IDE_STATUS_DATAREQUEST call devide_wait + ld a,#'E' + out (0x2f),a jr nz, timeout call devide_rx_buf ; returns the tmpbuf to the caller to free timeout: + ld a,#'R' call map_kernel pop ix ret @@ -175,25 +201,34 @@ xfer_user: init_io: ld e,l ld hl, (_blk_op + BLK_OP_LBA + 2) - ld IDE_REG_LBA_0(ix),l - ld IDE_REG_LBA_1(ix),h - ld hl, (_blk_op + BLK_OP_LBA + 3) - ld IDE_REG_LBA_2(ix),l ld a,h and #0x0F ; Merge drive and bits 24-27 or e ld IDE_REG_LBA_3(ix),a + call outcharhex ld hl,#0 call devide_wait_ready - jr z, xfer_timeout + jr nz, xfer_timeout + ld IDE_REG_LBA_2(ix),l + ld a,l + call outcharhex + ld hl, (_blk_op + BLK_OP_LBA) + ld IDE_REG_LBA_1(ix),h + ld a,h + call outcharhex + ld IDE_REG_LBA_0(ix),l + ld a,l + call outcharhex ld IDE_REG_SEC_COUNT(ix),#1 ld a,(_blk_op + BLK_OP_ISREAD) or a jr z, send_cmd - ld b,#IDE_CMD_READ_SECTOR ld IDE_REG_COMMAND(ix),#IDE_CMD_READ_SECTOR + ld a,#IDE_STATUS_DATAREQUEST + call devide_wait + jr nz, xfer_timeout call devide_xfer_r - ld hl,#1 + ld hl,#0 call map_kernel pop ix ret @@ -201,16 +236,16 @@ send_cmd: ld IDE_REG_COMMAND(ix),#IDE_CMD_WRITE_SECTOR ld a,#IDE_STATUS_DATAREQUEST call devide_wait - jr z, xfer_timeout + jr nz, xfer_timeout call devide_xfer_w call devide_wait_ready - jr z, xfer_timeout - ld hl,#1 + jr nz, xfer_timeout + ld hl,#0 call map_kernel pop ix ret xfer_timeout: - ld hl,#0 + ld hl,#0xffff call map_kernel pop ix ret @@ -224,6 +259,7 @@ devide_xfer_r: ; We don't have to worry about swap being special for this port ; Our caller also is responsible for working out when to bounce xfer_do: + ; FIXME: for non Sunrise we may need to change this and the xfer_w ld hl,#0x7C00 ld bc,#0x0200 ldir -- 2.34.1