sam: more work on the ATA disk interface
authorAlan Cox <alan@linux.intel.com>
Sun, 19 Aug 2018 14:19:26 +0000 (15:19 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 19 Aug 2018 14:19:26 +0000 (15:19 +0100)
We can now detect Atom and Atom Lite, as well as select the right 8 or 16bit
handling for them. The 16bit handlers are hairy because we can be doing an
I/O that crosses a page boundary. This needs a bit of thought to keep it
efficient. Atom Lite on the other hand appears to be trivial.

Kernel/platform-sam/atom.s
Kernel/platform-sam/devatom.c
Kernel/platform-sam/discard.c
Kernel/platform-sam/platform_ide.h

index dff0897..e343ac5 100644 (file)
@@ -38,6 +38,9 @@ BLKPARAM_SWAP_PAGE            .equ    3
 IDE_DATA_R     .equ 0x00F6
 IDE_DATA_W     .equ 0x00F7
 
+;
+;      TODO: Use atom_ methods once written and we have them workable
+;
 _devide_read_data:
        ld a, (_blk_op + BLKPARAM_IS_USER_OFFSET)
        ld hl, (_blk_op + BLKPARAM_ADDR_OFFSET)
@@ -91,48 +94,66 @@ ide_w2:
        call atomlite_writer
        pop ix
        jp map_kernel_low
+
 ;
-;      This needs optimizing to use as we know C = 0 - but think about
-;      the hard case with atom and split transfers. Probably need to
-;      unroll the loop into two halves, check termination on each and also
-;      somehow indicate partial transfers. We do know the transfer will be
-;      a total of 512 bytes so the rule I think is
-;      if bit 0,c on 1st transfer - it's split word 
+;      Routines for the Atom IDE 16bit interface
+;
+;      Not yet finished
 ;
-atomlite_reader:
-       ld a,#0x30
-       out (0xF5),a    ; Select data port
-       ld d,b
-       ld e,c
-       ld bc,#0xF6
-ide_r_loop:
-       ini
-       dec de
-       ld a,d
-       or e
-       jr nz,ide_r_loop
-       ret
 ;
 ;      The non split case 512 bytes as fast as we can given the interface
 ;      design
 ;
-atomlite_reader_fast:
+atom_reader_fast:
        ; Select data port
        ld a,#0x30
        out (0xF5),a
-       ld bc,#0xF7
-       xor a           ; 256 words
-atomlite_rf_loop:
-       dec c
+       ld bc,#0xF7     ; 256 words, port F7
+atom_rf_loop:
+       ld a,(0xF6)
        ini             ; Read from F6 for the data high
-       inc c
-       inc b           ; so it's one loop of 256 counts
-       ini
-       jr nz, atomlite_rf_loop
+       ld (hl),a
+       inc hl
+       jr nz,atom_rf_loop
+       ret
+;
+;      The non split case 512 bytes as fast as we can given the interface
+;      design. For Atomlite we could just inir
+;
+atom_writer_fast:
+       ld a,#0x30
+       out (0xF5),a    ; Select data port
+       ld bc,#0xF7     ; 256 words port F7
+atomlite_wf_loop:
+       ld a,(hl)
+       inc hl
+       outi
+       out (0xF6),a
+       jr nz, atomlite_wf_loop
        ret
+
+;
+;      The Atomlite is simpler
+;
+
 ;
-;      This needs optimizing to use as we know C = 0
+;      The Atomlite reader is simple
 ;
+atomlite_reader_fast:
+       ld a,#0x30
+       out (0xF5),a
+       ld bc,#0xF7
+       inir
+       inir
+       ret
+atomlite_writer_fast:
+       ld a,#0x30
+       out (0xF5),a
+       ld bc,#0xF7     ; 256 bytes port F7
+       otir
+       otir
+       ret
+
 atomlite_writer:
        ld a,#0x30
        out (0xF5),a    ; Select data port
@@ -147,18 +168,23 @@ ide_w_loop:
        jr nz,ide_w_loop
        ret
 ;
-;      The non split case 512 bytes as fast as we can given the interface
-;      design. For Atomlite we could just inir
+;      This needs optimizing to use as we know C = 0 - but think about
+;      the hard case with atom and split transfers. Probably need to
+;      unroll the loop into two halves, check termination on each and also
+;      somehow indicate partial transfers. We do know the transfer will be
+;      a total of 512 bytes so the rule I think is
+;      if bit 0,c on 1st transfer - it's split word 
 ;
-atomlite_writer_fast:
+atomlite_reader:
        ld a,#0x30
        out (0xF5),a    ; Select data port
+       ld d,b
+       ld e,c
        ld bc,#0xF6
-atomlite_wf_loop:
-       inc c
-       outi            ; Write F6
-       dec c
-       inc b           ; So it's 256 times count
-       outi            ; Then F7
-       jr nz, atomlite_wf_loop
+ide_r_loop:
+       ini
+       dec de
+       ld a,d
+       or e
+       jr nz,ide_r_loop
        ret
index ce45111..ccb4c84 100644 (file)
@@ -1,11 +1,14 @@
 #include <kernel.h>
 #include <kdata.h>
 #include <devide.h>
+#include <printf.h>
 
 __sfr __at 0xF5 ide_addr;
 __sfr __at 0xF6 ide_high;
 __sfr __at 0xF7 ide_low;
 
+uint8_t atom_type;
+
 uint8_t devide_readb(uint8_t reg)
 {
     volatile uint8_t dummy;
@@ -20,3 +23,25 @@ void devide_writeb(uint8_t reg, uint8_t value)
     ide_high = 0;
     ide_low = value;
 }
+
+uint8_t atom_probe(void)
+{
+    ide_addr = ide_reg_lba_0;
+    ide_high = 0xAA;
+    ide_low = 0x55;
+    /* This triggers the read back. On an AtomLite it reads the lba register
+       and returns it. On the Atom it reads the lba register and latches it
+       and returns the high 8bits - ie 0 */
+    if (ide_high == 0x55) {
+        kputs("AtomLite IDE detected.\n");
+        atom_type = ATOM_LITE;
+        return 1;
+    }
+    /* Did we latch 0x55. If so we have a real Atom IDE */
+    if (ide_low == 0x55) {
+        kputs("Atom IDE detected.\n");
+        atom_type = ATOM_16BIT;
+        return 1;
+    }
+    return 0;
+}
index b65e674..6254053 100644 (file)
@@ -4,6 +4,7 @@
 #include <printf.h>
 #include <devtty.h>
 #include <devide.h>
+#include <devatom.h>
 
 void map_init(void)
 {
@@ -30,5 +31,6 @@ void device_init(void)
        /* Time of day clock */
        inittod();
 #endif
-       devide_init();
+       if (atom_probe())
+               devide_init();
 }
index dc55ee3..fcf35bf 100644 (file)
@@ -45,3 +45,8 @@
 
 #define ide_reg_altstatus      (IDE_CS3 | 6)
 #define ide_reg_control                (IDE_CS3 | 7)
+
+#include <devatom.h>
+
+#define IDE_8BIT_ONLY          /* For the Atomlite */
+#define IDE_IS_8BIT(drive)     (atom_type != ATOM_16BIT)