trs80: update to support direct to user space I/O
authorAlan Cox <alan@linux.intel.com>
Sun, 25 Jan 2015 17:37:36 +0000 (17:37 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 25 Jan 2015 17:37:36 +0000 (17:37 +0000)
Kernel/platform-trs80/devfd.c
Kernel/platform-trs80/devfd.h
Kernel/platform-trs80/devhd.c
Kernel/platform-trs80/floppy.s

index 9b08ebc..057c78f 100644 (file)
 #define FD_WRITE       0xA0    /* Likewise A8 v A0 */
 
 static uint8_t motorct;
-static uint8_t fd_selected = 0xFF;
-static uint8_t fd_tab[MAX_FD] = { 0xFF, 0xFF, 0xFF, 0xFF };
+
+/* Extern as they live in common */
+extern uint8_t fd_map, fd_tab[MAX_FD];
+extern uint8_t fd_selected;
+extern uint8_t fd_cmd[6];
 
 /*
  *     We only support normal block I/O for the moment. We do need to
  *     add swapping!
  */
-
 static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x08 };
 
 static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
@@ -31,9 +33,9 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
     int tries;
     uint8_t err = 0;
     uint8_t *driveptr = fd_tab + minor;
-    uint8_t cmd[6];
+    uint8_t nblock;
 
-    if(rawflag)
+    if(rawflag == 2)
         goto bad2;
 
     if (fd_selected != minor) {
@@ -47,19 +49,29 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
     if (*driveptr == 0xFF)
         fd_reset(driveptr);
 
-    dptr = (uint16_t)udata.u_buf->bf_data;
-    block = udata.u_buf->bf_blk;
+    fd_map = rawflag;
+    if (rawflag == 0) {
+        dptr = (uint16_t)udata.u_buf->bf_data;
+        block = udata.u_buf->bf_blk;
+        nblock = 2;
+    } else {
+        if ((udata.u_offset|udata.u_count) & 0x1FF)
+            goto bad2;
+        dptr = (uint16_t)udata.u_base;
+        block = udata.u_offset >> 9;
+        nblock = udata.u_count >> 8;
+    }
 
-    cmd[0] = is_read ? FD_READ : FD_WRITE;
-    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 & 0xFF;
-    cmd[5] = dptr >> 8;
+    fd_cmd[0] = is_read ? FD_READ : FD_WRITE;
+    fd_cmd[1] = block / 9;             /* 2 sectors per block */
+    fd_cmd[2] = ((block % 9) << 1) + 1;        /*eww.. */
+    fd_cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE;
+    fd_cmd[4] = dptr & 0xFF;
+    fd_cmd[5] = dptr >> 8;
 
-    while (ct < 2) {
+    while (ct < nblock) {
         for (tries = 0; tries < 4 ; tries++) {
-            err = fd_operation(cmd, driveptr);
+            err = fd_operation(driveptr);
             if (err == 0)
                 break;
             if (tries > 1)
@@ -68,8 +80,8 @@ 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 == 4)
             goto bad;
-        cmd[5]++;      /* Move on 256 bytes in the buffer */
-        cmd[2]++;      /* Next sector for 2nd block */
+        fd_cmd[5]++;   /* Move on 256 bytes in the buffer */
+        fd_cmd[2]++;   /* Next sector for 2nd block */
         ct++;
     }
     return 1;
index 5f94507..672cf90 100644 (file)
@@ -8,7 +8,7 @@ int fd_open(uint8_t minor, uint16_t flag);
 
 /* low level interface */
 uint16_t fd_reset(uint8_t *driveptr);
-uint16_t fd_operation(uint8_t *cmd, uint8_t *driveptr);
+uint16_t fd_operation(uint8_t *driveptr);
 uint16_t fd_motor_on(uint16_t drivesel);
 uint16_t fd_motor_off(uint16_t driveptr);
 
index c0812fd..4652435 100644 (file)
@@ -105,6 +105,13 @@ int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
                block = udata.u_buf->bf_blk;
                nblock = 2;
                hd_page = 0;            /* Kernel */
+       } else if (rawflag == 1) {
+               if ((udata.u_offset|udata.u_count) & 0x1FF)
+                       goto bad2;
+               dptr = (uint16_t)udata.u_base;
+               nblock = udata.u_count >> 9;
+               block = udata.u_offset >> 9;
+               hd_page = udata.u_page;
        } else if (rawflag == 2) {
                nblock = swapcnt >> 8;  /* in 256 byte chunks */
                dptr = (uint16_t)swapbase;
index 9c61c03..2456b2d 100644 (file)
        .globl _fd_motor_on
        .globl _fd_motor_off
        .globl fd_nmi_handler
+       .globl _fd_map
+       .globl _fd_selected
+       .globl _fd_tab
+       .globl _fd_cmd
+       .globl map_kernel, map_process_always
 
 FDCREG .equ    0xF0
 FDCTRK .equ    0xF1
@@ -300,22 +305,25 @@ _fdr_wait:
 ;      running.
 ;
 _fd_operation:
+       ld      a, (_fd_map)
+       or      a
+       call    nz, map_process_always
        pop     bc              ; return address
-       pop     hl              ; command
        pop     de              ; drive track ptr
        push    de
-       push    hl
        push    bc
        push    ix
-       push    hl
-       pop     ix
+       ld      ix, #_fd_cmd
        ld      l, DATA(ix)
        ld      h, DATA+1(ix)
        call    fdsetup         ; Set up for a command
        ld      l, a
        ld      h, #0
        pop     ix
-       ret
+       ld      a, (_fd_map)
+       or      a
+       ret     z
+       jp      map_kernel
 ;
 ;      C interface fd_motor_on(uint16_t drivesel)
 ;
@@ -388,3 +396,11 @@ fdcctrl:
        .db     0
 fdc_active:
        .db     0
+_fd_map:
+       .db     0
+_fd_selected:
+       .db     0xFF
+_fd_tab:
+       .db     0xFF, 0xFF, 0xFF, 0xFF
+_fd_cmd:
+       .ds     6