dragon: initial fdc work
authorAlan Cox <alan@linux.intel.com>
Sat, 6 Dec 2014 02:49:39 +0000 (02:49 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 6 Dec 2014 02:49:39 +0000 (02:49 +0000)
Now correctly loads the superblock off disk. Something is astray once we
try and seek off track 0 however

Kernel/platform-dragon/devfd.c
Kernel/platform-dragon/devfd.h
Kernel/platform-dragon/floppy.s
Kernel/platform-dragon/p6809.s

index 1d3443a..f9acb73 100644 (file)
@@ -5,8 +5,8 @@
 
 #define MAX_FD 4
 
-#define OPDIR_READ     0
-#define OPDIR_NONE     1
+#define OPDIR_NONE     0
+#define OPDIR_READ     1
 #define OPDIR_WRITE    2
 
 #define FD_READ                0x88    /* 2797 needs 0x88, 1797 needs 0x80 */
@@ -42,6 +42,9 @@ static void fd_motor_timeout(void)
  *     for our usage but would break for single density media.
  */
 
+/* static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x40 }; - COCO */
+static uint8_t selmap[4] = {0x00, 0x01, 0x02, 0x03 };
+
 static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
 {
     blkno_t block;
@@ -50,9 +53,7 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
     int tries;
     uint8_t err;
     uint8_t *driveptr = fd_tab + minor;
-    uint16_t cmd[5];
-
-    /* FIXME: raw is broken unless nicely aligned */
+    uint8_t cmd[6];
 
     if(rawflag)
         goto bad2;
@@ -60,7 +61,7 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
     fd_motor_busy();           /* Touch the motor timer first so we don't
                                    go and turn it off as we are doing this */
     if (fd_selected != minor) {
-        uint8_t err = fd_motor_on(driveptr);
+        uint8_t err = fd_motor_on(selmap[minor]);
         if (err)
             goto bad;
     }
@@ -68,17 +69,19 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
     dptr = (uint16_t)udata.u_buf->bf_data;
     block = udata.u_buf->bf_blk;
 
+//    kprintf("Issue command: drive %d\n", minor);
     cmd[0] = is_read ? FD_READ : FD_WRITE;
-    cmd[1] = block / 18;
-    cmd[2] = (block % 18) + 1; /*eww.. */
-    cmd[3] = minor;    /* FIXME: other bits ? */
-    cmd[4] = is_read ? OPDIR_READ: OPDIR_WRITE;
-    cmd[5] = block << 8;
-    cmd[6] = block & 0xFF;
+    cmd[1] = block / 9;                /* 2 sectors per block */
+    cmd[2] = ((block % 9) << 1) + 1;   /*eww.. */
+    cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE;
+    cmd[4] = dptr >> 8;
+    cmd[5] = dptr & 0xFF;
         
     while (ct < 2) {
-        for (tries = 0; tries < 3 ; tries++) {
+        for (tries = 0; tries < 4 ; tries++) {
+//            kprintf("Issue command: %d drive %d sec %d\n", cmd[0], minor, cmd[2]);
             err = fd_operation(cmd, driveptr);
+//            kprintf("Issue command: return %d\n", err);
             if (err == 0)
                 break;
             if (tries > 1)
@@ -87,7 +90,7 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
         /* FIXME: should we try the other half and then bale out ? */
         if (tries == 3)
             goto bad;
-        cmd[5]++;      /* Move on 256 bytes in the buffer */
+        cmd[4]++;      /* Move on 256 bytes in the buffer */
         cmd[2]++;      /* Next sector for 2nd block */
         ct++;
     }
index 2354e36..69ecb5e 100644 (file)
@@ -9,7 +9,7 @@ int fd_open(uint8_t minor, uint16_t flag);
 /* low level interface */
 uint8_t fd_reset(uint8_t *drive);
 uint8_t fd_operation(uint16_t *cmd, uint8_t *drive);
-uint8_t fd_motor_on(uint8_t *drive);
+uint8_t fd_motor_on(uint8_t drive);
 uint8_t fd_motor_off(void);
 
 #endif /* __DEVFD_DOT_H__ */
index 789ea06..34c34bc 100644 (file)
 ;
 ;      MMIO for the floppy controller
 ;
+;      For a Dragon cartridge
 ;
-;      These four are a normal WD2797 under DragonDOS
+FDCCTRL        EQU     0xFF48
+;
+;      0-1: drive select
+;      2: motor on
+;      3: density
+;      4: precomp
+;      5: nmi mode
 ;
 FDCREG EQU     0xFF40
 FDCTRK EQU     0xFF41
 FDCSEC EQU     0xFF42
 FDCDATA        EQU     0xFF43
-;
-;      This is the control logic
-;
-FDCCTRL        EQU     0xFF48          ; drive select and motors
-;      bit5: NMI enable, 4: Precomp ?, 3: Density, 2: Motor, 
-;      bits 0-1 are drive nymber 0-3
-
 
 ;
 ;      Structures we use
@@ -41,9 +41,8 @@ TRKCOPY       EQU     0
 CMD    EQU     0
 TRACK  EQU     1
 SECTOR EQU     2
-DRIVESEL EQU   3
-DIRECT EQU     4               ; 0 = read 2 = write 1 = status
-DATA   EQU     5
+DIRECT EQU     3               ; 0 = read 2 = write 1 = status
+DATA   EQU     4
 
        .area   .text
 ;
@@ -75,36 +74,42 @@ waitdisk:
 waitdisk_l:
        leax    -1,x
        beq     forceint        ; try forcing an interrupt
-       lda     FDCREG
+       lda     <FDCREG
        bita    #0x01
        bne     waitdisk_l
        rts                     ; done, idle EQ true
 forceint:                      ; no response, bigger stick
        lda     #0xD0           ; reset
-       sta     FDCREG
+       sta     <FDCREG
        nop
        exg     a,a
        exg     a,a
-       lda     FDCREG          ; read to reset int status
+       lda     <FDCREG         ; read to reset int status
        ; ?? what to do next ??
        lda     #0xff           ; force NEQ
        rts
 
-;
 ;      Set up the disk. On entry y points to our per drive data and
 ;      x points to the command block
 ;
 fdsetup:
        lda     TRKCOPY,y
-       sta     FDCTRK          ; reset track register
+       sta     <FDCTRK         ; reset track register
        pshs    x,y
        cmpa    TRACK,x         ; target track
        beq     fdiosetup
+
+       sta     <FDCTRK         ; target
+       ;
+       ;       So we can verify
+       ;
+       lda     SECTOR,x
+       sta     <FDCSEC
        ;
        ;       Need to seek the disk
        ;
        lda     #0x14
-       sta     FDCREG          ; seek
+       sta     <FDCREG         ; seek
        nop
        exg     a,a
        exg     a,a
@@ -116,8 +121,8 @@ fdsetup:
        ; seek failed, not good
 setuptimeout:                  ; NE = bad
        puls    x,y
-       lda     FDCTRK          ; we have no idea where we are
-       sta     TRKCOPY,y       ; so remember what the drive reported
+       ldb     <FDCTRK         ; we have no idea where we are
+       stb     TRKCOPY,y       ; so remember what the drive reported
        rts
 ;
 ;      Head in the right place
@@ -126,22 +131,23 @@ fdiosetup:
        puls    x,y
        lda     TRACK,x
        sta     TRKCOPY,y       ; remember we arrived
-       ldb     FDCCTRL
-       andb    #0xEF
+       ldb     fdcctrl
+       andb    #0xEF           ; precomp
        cmpa    #22
        blo     noprecomp
        orb     #0x10
 noprecomp:
-       stb     FDCCTRL         ; precomp configured
+       orb     #0x20           ; NMI/halt on
+       stb     <FDCCTRL                ; precomp configured
        lda     SECTOR,x
-       sta     FDCSEC
-       lda     FDCREG          ; clear any pending int
+       sta     <FDCSEC
+       lda     <FDCREG         ; clear any pending int
        lda     CMD,x           ; command to issue
        ldy     #fdxferdone
        sty     nmivector       ; so our NMI handler will clean up
        ldy     #0              ; timeout handling
-       orcc    #0x10           ; irqs off or we'll miss bytes
-       sta     FDCREG          ; issue the command
+       orcc    #0x50           ; irqs off or we'll miss bytes
+       sta     <FDCREG         ; issue the command
        nop                     ; give the FDC a moment to think
        exg     a,a
        exg     a,a
@@ -154,22 +160,22 @@ noprecomp:
 ;      Status registers
 ;
 fdxferdone:
-       andcc   #0xef
-       lda     FDCREG
+       ldb     fdcctrl
+       stb     <FDCCTRL
+       lda     <FDCREG
        anda    #0x7C           ; Returns with A holding the status bits
        rts
 ;
 ;      Relies on B being 2...
 ;
 wait_drq:
-       bitb    FDCREG
+       bitb    <FDCREG
        bne     drq_on
        leay    -1,y
        bne     wait_drq
        ;
        ;       Timed out - reset etc to clean up ??
        ;
-       andcc   #0xef
        lda     #0xff           ; our error code
        rts
 
@@ -177,27 +183,86 @@ wait_drq:
 ;      Once the controller decides it is finished it will flag an NMI
 ;      and the NMI will switch the PC on the return to fdxferdone.
 ;
-;      Begin the actual copy
+;      Begin the actual copy to disk
 ;
 drq_on:
-       ldy     DATA,x
+       ldx     DATA,x
+       lda     ,x+
+       bra     drq_go
 drq_loop:
-       ldb     ,y+
-       stb     FDCDATA         ; hardware will stall this for us
-       sta     FDCREG
+       sync
+drq_go:
+       sta     <FDCDATA
+       lda     ,x+
        bra     drq_loop
 
 ;
-;      Write to the disk
+;      Read from the disk
 ;
 fdio_in:
-       ldy     DATA,x
+       ldx     DATA,x
+fdio_dwait:
+       ldb     <FDCREG
+       bitb    #0x02
+       bne     fdio_go
+       leay    -1,y
+       bne     fdio_dwait
+       ldb     fdcctrl
+       stb     <FDCCTRL
+       lda     #0xff
+       rts
+;
+;      Now do the data
+;
 fdio_loop:
-       ldb     FDCDATA         ; Sync is done by hardware
-       stb     ,y+
-       bra     fdio_loop       ; exit is via NMI to fdxferdone
+       sync
+fdio_go:
+       ldb     <0xFF22         ; clear the FIR (PIA1DB)
+       lda     <FDCDATA
+       sta     ,x+
+       bra     fdio_loop
 
+;
+;      PIA management
+;
+piasave:
+       pshs    x,y
+       ldx     #0xFF01         ; PIA0CRA
+       ldy     #pia_stash
+       lda     ,x
+       sta     ,y+
+       anda    #0xFC
+       sta     ,x++            ; move on to 0CRB
+       lda     ,x
+       sta     ,y+
+       anda    #0xFC
+       sta     ,x
+       leax    0x1e,x          ; PIA1CRA
+       lda     ,x
+       sta     ,y+
+       anda    #0xFC
+       sta     ,x++            ; on to PIA1CRB
+       lda     ,x
+       sta     ,y
+       ora     #0x37
+       sta     ,x              ; floppy FIR enabled
+       puls    x,y,pc
 
+piaload:
+       ; Must leave B untouched
+       pshs    x,y
+       ldx     #0xFF01
+       ldy     #pia_stash
+       lda     ,y+
+       sta     ,x++
+       lda     ,y+
+       sta     ,x
+       leax    0x1e,x
+       lda     ,y+
+       sta     ,x++
+       lda     ,y+
+       sta     ,x
+       puls    x,y,pc
 ;
 ;      C glue interface.
 ;
@@ -212,9 +277,16 @@ fdio_loop:
 ;      fd_reset(uint16_t *drive)
 ;
 _fd_reset:
-       pshs    x,y
+       pshs    x,y,dp
+       lda     #0xFF
+       tfr     a,dp
+       ldb     fdcctrl
+       stb     <FDCCTRL
+       lda     #0x01
+       sta     <FDCSEC
        lda     #0x00           ; seek
-       sta     FDCREG
+       sta     <FDCTRK
+       sta     <FDCREG
        nop
        exg     a,a
        exg     a,a
@@ -225,8 +297,8 @@ _fd_reset:
        beq     rstff           ; Total fail
        anda    #0x10           ; Error bit from the reset
 rstff:
-       tfr a,b
-       puls    x, y, pc
+       tfr     a,b
+       puls    x,y,dp,pc
 ;
 ;      fd_operation(uint16_t *cmd, uint16_t *drive)
 ;
@@ -234,19 +306,26 @@ rstff:
 ;      running.
 ;
 _fd_operation:
-       pshs y
-       ldy 4,s         ; Drive struct
-       jsr fdsetup     ; Set up for a command
-       puls y
-       tfr a,b         ; Status code or 0xFF for total failure
-       rts
-;
-;      C interface fd_motor_on(uint8 drive)
+       pshs y,cc,dp
+       lda     #0xFF
+       tfr     a,dp
+       orcc    #0x40           ; Make sure FIR is off
+       jsr     piasave
+       ldy     6,s             ; Drive struct
+       jsr     fdsetup         ; Set up for a command
+       tfr     a,b             ; Status code or 0xFF for total failure
+       bsr     piaload
+       puls    y,cc,dp,pc      ; Restore IRQ state etc
+;
+;      C interface fd_motor_on(uint8 drivesel)
 ;
 ;      Selects this drive and turns on the motors
 ;
 _fd_motor_on:
-       pshs y
+       pshs    y,dp
+       lda     #0xFF
+       tfr     a,dp
+
        ;
        ;       Select drive B, turn on motor if needed
        ;
@@ -259,21 +338,21 @@ _fd_motor_on:
 ;
 motor_was_on:
        ldb     #0
-       puls    y,pc
+       puls    y,dp,pc
 ;
 ;      Select our drive
 ;
 notsel:
-       orb     #0xA8           ; NMI, motor on, density + our drive id
-       lda     FDCCTRL
-       stb     FDCCTRL
-       bita    #0x08
+       orb     #0x04           ; motor on, single density + our drive id
+       stb     <FDCCTRL
+       stb     fdcctrl
+       bita    #0x4
        bne     motor_was_on
        jsr     disknap
        ; FIXME: longer motor spin up delay goes here
        jsr     waitdisk
-       tfr a,b         ; return in the right place
-       puls y,pc
+       tfr     a,b             ; return in the right place
+       puls    y,dp,pc
 
 ;
 ;      C interface fd_motor_off(void)
@@ -281,19 +360,22 @@ notsel:
 ;      Turns off the drive motors, deselects all drives
 ;
 _fd_motor_off:
-       pshs y
+       pshs    y,dp
+       lda     #0xFF
+       tfr     a,dp
+
 ;
 ;      Deselect drives and turn off motor
 ;
        ldb     motor_running
        beq     no_work_motor
        ; Should we seek to track 0 ?
-       ldb     FDCCTRL
+       ldb     <FDCCTRL
        andb    #0xF0
-       stb     FDCCTRL
+       stb     <FDCCTRL
        clr     motor_running
 no_work_motor:
-       puls y,pc
+       puls y,dp,pc
 
        .area .data
 
@@ -305,3 +387,10 @@ curdrive:
        .area .bss
 motor_running:
        .byte   0
+fdcctrl:
+       .byte   0
+pia_stash:
+       .byte   0
+       .byte   0
+       .byte   0
+       .byte   0
\ No newline at end of file
index 5f285fa..3fe993a 100644 (file)
@@ -40,14 +40,11 @@ trapmsg2:   .ascii ", PC="
             .db 0
 tm_user_sp: .dw 0
 
+_trap_reboot:
 _trap_monitor:
-           orcc #0x10
+           cwai #0
            bra _trap_monitor
 
-_trap_reboot:
-           lda 0xff90
-           anda #0xfc          ; map in the ROM
-           jmp 0
 
 _di:
            tfr cc,b            ; return the old irq state
@@ -164,14 +161,21 @@ map_save:
 ; outchar: Wait for UART TX idle, then print the char in a
 
 outchar:
-           pshs b
-outcharw:
-           ldb 0xff05
-           bitb #0x04
-           beq outcharw
-           sta 0xff04
-           puls b,pc
+;          pshs b
+;outcharw:
+           pshs x
+           ldx traceptr
+           sta ,x+
+           stx traceptr
+           puls x, pc
+;          ldb 0xff05
+;          bitb #0x04
+;          beq outcharw
+;          sta 0xff04
+;          puls b,pc
 
            .area .data
 
 _kernel_flag: .db 1
+traceptr:
+          .dw 0x6000