sunrise: assorted fixes
authorAlan Cox <alan@linux.intel.com>
Sat, 6 Apr 2019 21:33:57 +0000 (22:33 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 6 Apr 2019 21:33:57 +0000 (22:33 +0100)
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
Kernel/platform-msx1/sunrise.s

index 57db3c3..4f7548f 100644 (file)
@@ -6,8 +6,8 @@
 #include <devide_sunrise.h>
 #include <msx.h>
 
-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();
index 4d60b48..4066f6c 100644 (file)
        .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