Optimize insb/outsb/insw/etc. functions.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 9 Mar 2008 05:59:58 +0000 (00:59 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 9 Mar 2008 05:59:58 +0000 (00:59 -0500)
Use "string ops" to simplify port accesses.
Always run "cld" on entry to C code.

src/ata.c
src/farptr.h
src/ioport.h
src/romlayout.S
src/system.c

index d26eca9..25327fc 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
@@ -125,46 +125,6 @@ ata_reset(u16 device)
     outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
 }
 
-static void
-insw(u16 port, u16 segment, u16 offset, u16 count)
-{
-    u16 i;
-    for (i=0; i<count; i++) {
-        u16 d = inw(port);
-        SET_FARVAR(segment, *(u16*)(offset + 2*i), d);
-    }
-}
-
-static void
-insl(u16 port, u16 segment, u16 offset, u16 count)
-{
-    u16 i;
-    for (i=0; i<count; i++) {
-        u32 d = inl(port);
-        SET_FARVAR(segment, *(u32*)(offset + 4*i), d);
-    }
-}
-
-static void
-outsw(u16 port, u16 segment, u16 offset, u16 count)
-{
-    u16 i;
-    for (i=0; i<count; i++) {
-        u16 d = GET_FARVAR(segment, *(u16*)(offset + 2*i));
-        outw(d, port);
-    }
-}
-
-static void
-outsl(u16 port, u16 segment, u16 offset, u16 count)
-{
-    u16 i;
-    for (i=0; i<count; i++) {
-        u32 d = GET_FARVAR(segment, *(u32*)(offset + 4*i));
-        outl(d, port);
-    }
-}
-
 
 // ---------------------------------------------------------------------------
 // ATA/ATAPI driver : execute a data-in command
@@ -255,9 +215,9 @@ ata_cmd_data_in(u16 device, u16 command, u16 count, u16 cylinder
         }
 
         if (mode == ATA_MODE_PIO32)
-            insl(iobase1, segment, offset, 512 / 4);
+            insl_seg(iobase1, segment, offset, 512 / 4);
         else
-            insw(iobase1, segment, offset, 512 / 2);
+            insw_seg(iobase1, segment, offset, 512 / 2);
         offset += 512;
 
         current++;
@@ -380,9 +340,9 @@ ata_cmd_data_out(u16 device, u16 command, u16 count, u16 cylinder
         }
 
         if (mode == ATA_MODE_PIO32)
-            outsl(iobase1, segment, offset, 512 / 4);
+            outsl_seg(iobase1, segment, offset, 512 / 4);
         else
-            outsw(iobase1, segment, offset, 512 / 2);
+            outsw_seg(iobase1, segment, offset, 512 / 2);
         offset += 512;
 
         current++;
@@ -492,7 +452,7 @@ ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen, u16 header
     // Send command to device
     irq_enable();
 
-    outsw(iobase1, GET_SEG(SS), (u32)cmdbuf, cmdlen);
+    outsw_seg(iobase1, GET_SEG(SS), (u32)cmdbuf, cmdlen);
 
     if (inout == ATA_DATA_NO) {
         await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
@@ -584,9 +544,9 @@ ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen, u16 header
                     inw(iobase1);
 
             if (lmode == ATA_MODE_PIO32)
-                insl(iobase1, bufseg, bufoff, lcount);
+                insl_seg(iobase1, bufseg, bufoff, lcount);
             else
-                insw(iobase1, bufseg, bufoff, lcount);
+                insw_seg(iobase1, bufseg, bufoff, lcount);
 
             for (i=0; i<lafter; i++)
                 if (lmode == ATA_MODE_PIO32)
index 7216f23..e142843 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __FARPTR_H
 #define __FARPTR_H
 
+#include "ioport.h" // insb
+
 #define READ8_SEG(SEG, var) ({                                          \
     u8 __value;                                                         \
     __asm__ __volatile__("movb %%" #SEG ":%1, %b0"                      \
@@ -100,4 +102,29 @@ extern void __force_link_error__unknown_type();
 #define SET_FARPTR(ptr, val) do { (var) = (val); } while (0)
 #endif
 
+static inline void insb_seg(u16 port, u16 segment, u16 offset, u16 count) {
+    SET_SEG(ES, segment);
+    insb(port, (u8*)(offset+0), count);
+}
+static inline void insw_seg(u16 port, u16 segment, u16 offset, u16 count) {
+    SET_SEG(ES, segment);
+    insw(port, (u16*)(offset+0), count);
+}
+static inline void insl_seg(u16 port, u16 segment, u16 offset, u16 count) {
+    SET_SEG(ES, segment);
+    insl(port, (u32*)(offset+0), count);
+}
+static inline void outsb_seg(u16 port, u16 segment, u16 offset, u16 count) {
+    SET_SEG(ES, segment);
+    outsb(port, (u8*)(offset+0), count);
+}
+static inline void outsw_seg(u16 port, u16 segment, u16 offset, u16 count) {
+    SET_SEG(ES, segment);
+    outsw(port, (u16*)(offset+0), count);
+}
+static inline void outsl_seg(u16 port, u16 segment, u16 offset, u16 count) {
+    SET_SEG(ES, segment);
+    outsl(port, (u32*)(offset+0), count);
+}
+
 #endif // farptr.h
index d756e34..ba9117b 100644 (file)
@@ -73,4 +73,30 @@ static inline u32 inl(u16 port) {
     return value;
 }
 
+static inline void insb(u16 port, u8 *data, u32 count) {
+    asm volatile("rep insb (%%dx), %%es:(%%di)"
+                 : "+c"(count), "+D"(data) : "d"(port) : "memory");
+}
+static inline void insw(u16 port, u16 *data, u32 count) {
+    asm volatile("rep insw (%%dx), %%es:(%%di)"
+                 : "+c"(count), "+D"(data) : "d"(port) : "memory");
+}
+static inline void insl(u16 port, u32 *data, u32 count) {
+    asm volatile("rep insl (%%dx), %%es:(%%di)"
+                 : "+c"(count), "+D"(data) : "d"(port) : "memory");
+}
+// XXX - outs not limited to es segment
+static inline void outsb(u16 port, u8 *data, u32 count) {
+    asm volatile("rep outsb %%es:(%%si), (%%dx)"
+                 : "+c"(count), "+S"(data) : "d"(port) : "memory");
+}
+static inline void outsw(u16 port, u16 *data, u32 count) {
+    asm volatile("rep outsw %%es:(%%si), (%%dx)"
+                 : "+c"(count), "+S"(data) : "d"(port) : "memory");
+}
+static inline void outsl(u16 port, u32 *data, u32 count) {
+    asm volatile("rep outsl %%es:(%%si), (%%dx)"
+                 : "+c"(count), "+S"(data) : "d"(port) : "memory");
+}
+
 #endif // ioport.h
index 1aa0bbf..96e2e8b 100644 (file)
@@ -245,6 +245,7 @@ rombios32_gdt:
  ****************************************************************/
 
         .macro ENTRY cfunc
+        cld
         pushal
         pushw %es
         pushw %ds
index b1e4fe8..1f34c97 100644 (file)
@@ -174,7 +174,6 @@ handle_1587(struct bregs *regs)
         // move CX words from DS:SI to ES:DI
         "xorw %%si, %%si\n"
         "xorw %%di, %%di\n"
-        "cld\n"
         "rep movsw\n"
 
         // reset PG bit in CR0 ???