Browse Source

hl: Convert I/O port inline assembly to .S files

This change removes the ioport.c file that contained non-portable inline
assembly, and replaces with with ioport.S assembly functions. This cleanup
keeps our C files more portable.
Olexandr Kolomiiets 5 years ago
parent
commit
0c8bef3a7a
6 changed files with 541 additions and 311 deletions
  1. 2 1
      kernel/hl/Makefile
  2. 7 4
      kernel/hl/boot/Makefile
  3. 12 3
      kernel/hl/build.ck
  4. 257 0
      kernel/hl/x64/ioport.S
  5. 263 0
      kernel/hl/x86/ioport.S
  6. 0 303
      kernel/hl/x86/ioport.c

+ 2 - 1
kernel/hl/Makefile

@@ -105,18 +105,19 @@ X86_COMMON_OBJS = ns16550.o      \
                   x86/archintr.o \
                   x86/archrst.o  \
                   x86/archtimr.o \
-                  x86/ioport.o   \
                   x86/pmtimer.o  \
                   x86/regacces.o \
                   x86/rtc.o      \
                   x86/tsc.o      \
 
 X86_OBJS = $(X86_COMMON_OBJS)  \
+           x86/ioport.o   \
            x86/apinit.o        \
            x86/apstart.o       \
            x86/archsup.o       \
 
 X64_OBJS = $(X86_COMMON_OBJS)  \
+           x64/ioport.o   \
            x64/apinit.o        \
            x64/apstart.o       \
            x64/archsup.o       \

+ 7 - 4
kernel/hl/boot/Makefile

@@ -45,12 +45,15 @@ ARMV6_OBJS = ../armv6/archdbg.o  \
              ../armv7/regacces.o \
              ../armv7/uartpl11.o \
 
-X86_OBJS = ../x86/archdbg.o  \
+X86_COMMON_OBJS = ../x86/archdbg.o  \
+                  ../x86/regacces.o \
+                  ../ns16550.o      \
+
+X86_OBJS = $(X86_COMMON_OBJS) \
            ../x86/ioport.o   \
-           ../x86/regacces.o \
-           ../ns16550.o      \
 
-X64_OBJS = $(X86_OBJS)
+X64_OBJS = $(X86_COMMON_OBJS) \
+           ../x64/ioport.o   \
 
 ifeq ($(ARCH),x64)
 DIRS += x6432

+ 12 - 3
kernel/hl/build.ck

@@ -143,7 +143,6 @@ function build() {
             "x86/archintr.c",
             "x86/archrst.c",
             "x86/archtimr.c",
-            "x86/ioport.c",
             "x86/pmtimer.c",
             "x86/regacces.c",
             "x86/rtc.c",
@@ -152,7 +151,6 @@ function build() {
 
         archBootSources = [
             ":x86/archdbg.o",
-            ":x86/ioport.o",
             ":x86/regacces.o"
         ];
 
@@ -162,14 +160,19 @@ function build() {
                 "dbgdev.c",
                 "ns16550.c",
                 "x86/archdbg.c",
-                "x86/ioport.c",
                 "x86/regacces.c"
+                "x86/ioport.S",
             ];
 
             archSources += [
                 "x64/apinit.c",
                 "x64/apstart.S",
                 "x64/archsup.S",
+                "x64/ioport.S",
+            ];
+
+            archBootSources += [
+                ":x64/ioport.o",
             ];
 
         } else {
@@ -177,7 +180,13 @@ function build() {
                 "x86/apinit.c",
                 "x86/apstart.S",
                 "x86/archsup.S",
+                ":x86/ioport.o",
             ];
+
+            archBootSources += [
+                "x86/ioport.S",
+            ];
+
         }
     }
 

+ 257 - 0
kernel/hl/x64/ioport.S

@@ -0,0 +1,257 @@
+/*++
+
+Copyright (c) 2017 Minoca Corp.
+
+    This file is licensed under the terms of the GNU General Public License
+    version 3. Alternative licensing terms are available. Contact
+    info@minocacorp.com for details. See the LICENSE file at the root of this
+    project for complete licensing information.
+
+Module Name:
+
+    ioport.S
+
+Abstract:
+
+    This module implements assembly-based I/O port access routines for the
+    AMD64 platform.
+
+Author:
+
+    Evan Green 11-Aug-2017
+
+Environment:
+
+    Boot
+
+--*/
+
+//
+// ------------------------------------------------------------------- Includes
+//
+
+#include <minoca/kernel/x64.inc>
+
+//
+// -------------------------------------------------------------------- Macros
+//
+
+//
+// ---------------------------------------------------------------- Definitions
+//
+
+//
+// -------------------------------------------------------------------- Globals
+//
+
+//
+// ----------------------------------------------------------------------- Code
+//
+
+ASSEMBLY_FILE_HEADER
+
+//
+// UINT8
+// HlIoPortInByte (
+//     UINT16 Address
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs an 8-bit read from the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to read from.
+
+Return Value:
+
+    Returns the value at that address.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortInByte)
+    movl    %edi, %edx              # Get port number in the right register.
+    xorl    %eax, %eax              # Clear the high bits.
+    inb     %dx, %al                # Perform the I/O port read.
+    nop                             # Rest a touch.
+    retq                            # Return.
+
+END_FUNCTION(HlIoPortInByte)
+
+//
+// UINT16
+// HlIoPortInShort (
+//     UINT16 Address
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 16-bit read from the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to read from.
+
+Return Value:
+
+    Returns the value at that address.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortInShort)
+    movl    %edi, %edx              # Get port number in the right register.
+    xorl    %eax, %eax              # Clear the high bits.
+    inw     %dx, %ax                # Perform the I/O port read.
+    nop                             # Rest a touch.
+    retq                            # Return.
+
+END_FUNCTION(HlIoPortInShort)
+
+//
+// UINT32
+// HlIoPortInLong (
+//     UINT16 Address
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 32-bit read from the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to read from.
+
+Return Value:
+
+    Returns the value at that address.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortInLong)
+    movl    %edi, %edx              # Get port number in the right register.
+    xorl    %eax, %eax              # Clear the upper word.
+    inl     %dx, %eax               # Perform the I/O port read.
+    nop                             # Rest a touch.
+    retq                            # Return.
+
+END_FUNCTION(HlIoPortInLong)
+
+//
+// VOID
+// HlIoPortOutByte (
+//     UINT16 Address,
+//     UINT8 Value
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs an 8-bit write to the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to write to.
+
+    Value - Supplies the value to write.
+
+Return Value:
+
+    None.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortOutByte)
+    movl    %edi, %edx              # Get port number in the right register.
+    movl    %esi, %eax              # Get the value in the right register.
+    outb    %al, %dx                # Perform the I/O port write.
+    nop                             # Rest a touch.
+    retq                            # Return.
+
+END_FUNCTION(HlIoPortOutByte)
+
+//
+// VOID
+// HlIoPortOutShort (
+//     UINT16 Address,
+//     UINT16 Value
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 16-bit write to the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to write to.
+
+    Value - Supplies the value to write.
+
+Return Value:
+
+    None.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortOutShort)
+    movl    %edi, %edx              # Get port number in the right register.
+    movl    %esi, %eax              # Get the value in the right register.
+    outw    %ax, %dx                # Perform the I/O port write.
+    nop                             # Rest a touch.
+    retq                            # Return.
+
+END_FUNCTION(HlIoPortOutShort)
+
+//
+// VOID
+// HlIoPortOutLong (
+//     UINT16 Address,
+//     UINT32 Value
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 32-bit write to the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to write to.
+
+    Value - Supplies the value to write.
+
+Return Value:
+
+    None.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortOutLong)
+    movl    %edi, %edx              # Get port number in the right register.
+    movl    %esi, %eax              # Get the value in the right register.
+    outl    %eax, %dx               # Perform the I/O port write.
+    nop                             # Rest a touch.
+    retq                            # Return.
+
+END_FUNCTION(HlIoPortOutLong)
+
+//
+// --------------------------------------------------------- Internal Functions
+//
+

+ 263 - 0
kernel/hl/x86/ioport.S

@@ -0,0 +1,263 @@
+/*++
+
+Copyright (c) 2014 Minoca Corp.
+
+    This file is licensed under the terms of the GNU General Public License
+    version 3. Alternative licensing terms are available. Contact
+    info@minocacorp.com for details. See the LICENSE file at the root of this
+    project for complete licensing information.
+
+Module Name:
+
+    ioport.S
+
+Abstract:
+
+    This module implements assembly-based I/O port access routines for the
+    x86 platform.
+
+Author:
+
+    Evan Green 7-Aug-2013
+
+Environment:
+
+    Boot
+
+--*/
+
+//
+// ------------------------------------------------------------------- Includes
+//
+
+#include <minoca/kernel/x86.inc>
+
+//
+// -------------------------------------------------------------------- Macros
+//
+
+//
+// ---------------------------------------------------------------- Definitions
+//
+
+//
+// -------------------------------------------------------------------- Globals
+//
+
+//
+// ----------------------------------------------------------------------- Code
+//
+
+//
+// .text specifies that this code belongs in the executable section.
+//
+// .code32 specifies that this is 32-bit protected mode code.
+//
+
+.text
+.code32
+
+//
+// UINT8
+// HlIoPortInByte (
+//     UINT16 Address
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs an 8-bit read from the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to read from.
+
+Return Value:
+
+    Returns the value at that address.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortInByte)
+    movl    4(%esp), %edx           # Get the I/O port.
+    xorl    %eax, %eax              # Clear the high bits.
+    inb     %dx, %al                # Perform the I/O port read.
+    nop                             # Rest a touch.
+    ret                             # Return.
+
+END_FUNCTION(HlIoPortInByte)
+
+//
+// UINT16
+// HlIoPortInShort (
+//     UINT16 Address
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 16-bit read from the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to read from.
+
+Return Value:
+
+    Returns the value at that address.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortInShort)
+    movl    4(%esp), %edx           # Get the I/O port.
+    xorl    %eax, %eax              # Clear the high bits.
+    inw     %dx, %ax                # Perform the I/O port read.
+    nop                             # Rest a touch.
+    ret                             # Return.
+
+END_FUNCTION(HlIoPortInShort)
+
+//
+// UINT32
+// HlIoPortInLong (
+//     UINT16 Address
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 32-bit read from the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to read from.
+
+Return Value:
+
+    Returns the value at that address.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortInLong)
+    movl    4(%esp), %edx           # Get the I/O port.
+    inl     %dx, %eax               # Perform the I/O port read.
+    nop                             # Rest a touch.
+    ret                             # Return.
+
+END_FUNCTION(HlIoPortInLong)
+
+//
+// VOID
+// HlIoPortOutByte (
+//     UINT16 Address,
+//     UINT8 Value
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs an 8-bit write to the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to write to.
+
+    Value - Supplies the value to write.
+
+Return Value:
+
+    None.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortOutByte)
+    movl    4(%esp), %edx           # Get the I/O port.
+    movl    8(%esp), %eax           # Get the value.
+    outb    %al, %dx                # Perform the I/O port write.
+    nop                             # Rest a touch.
+    ret                             # Return.
+
+END_FUNCTION(HlIoPortOutByte)
+
+//
+// VOID
+// HlIoPortOutShort (
+//     UINT16 Address,
+//     UINT16 Value
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 16-bit write to the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to write to.
+
+    Value - Supplies the value to write.
+
+Return Value:
+
+    None.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortOutShort)
+    movl    4(%esp), %edx           # Get the I/O port.
+    movl    8(%esp), %eax           # Get the value.
+    outw    %ax, %dx                # Perform the I/O port write.
+    nop                             # Rest a touch.
+    ret                             # Return.
+
+END_FUNCTION(HlIoPortOutShort)
+
+//
+// VOID
+// HlIoPortOutLong (
+//     UINT16 Address,
+//     UINT32 Value
+//     )
+//
+
+/*++
+
+Routine Description:
+
+    This routine performs a 32-bit write to the given I/O port.
+
+Arguments:
+
+    Address - Supplies the address to write to.
+
+    Value - Supplies the value to write.
+
+Return Value:
+
+    None.
+
+--*/
+
+PROTECTED_FUNCTION(HlIoPortOutLong)
+    movl    4(%esp), %edx           # Get the I/O port.
+    movl    8(%esp), %eax           # Get the value.
+    outl    %eax, %dx               # Perform the I/O port write.
+    nop                             # Rest a touch.
+    ret                             # Return.
+
+END_FUNCTION(HlIoPortOutLong)
+
+//
+// --------------------------------------------------------- Internal Functions
+//
+

+ 0 - 303
kernel/hl/x86/ioport.c

@@ -1,303 +0,0 @@
-/*++
-
-Copyright (c) 2012 Minoca Corp.
-
-    This file is licensed under the terms of the GNU General Public License
-    version 3. Alternative licensing terms are available. Contact
-    info@minocacorp.com for details. See the LICENSE file at the root of this
-    project for complete licensing information.
-
-Module Name:
-
-    ioport.c
-
-Abstract:
-
-    This module implements legacy I/O port communication.
-
-Author:
-
-    Evan Green
-
-Environment:
-
-    Boot
-
---*/
-
-//
-// ------------------------------------------------------------------- Includes
-//
-
-#include <minoca/kernel/kernel.h>
-#include <minoca/kernel/ioport.h>
-
-//
-// ---------------------------------------------------------------- Definitions
-//
-
-//
-// ----------------------------------------------- Internal Function Prototypes
-//
-
-//
-// ------------------------------------------------------ Data Type Definitions
-//
-
-//
-// ------------------------------------------------------------------ Functions
-//
-
-KERNEL_API
-UCHAR
-HlIoPortInByte (
-    USHORT InputPort
-    )
-
-/*++
-
-Routine Description:
-
-    This routine gets one byte from the specified legacy I/O port.
-
-Arguments:
-
-    InputPort - Supplies the port to receive a byte from.
-
-Return Value:
-
-    Returns the data at that port.
-
---*/
-
-{
-
-    UCHAR ReturnValue;
-
-    //
-    // Clear eax and mark it as destroyed.
-    //
-
-    asm volatile ("xorl %%eax,%%eax":::"eax");
-
-    //
-    // Execute the inb instruction. Register al has the output which should go
-    // in ReturnValue, and dx has the input which should come from InputPort.
-    //
-
-    asm volatile ("inb %%dx,%%al":"=a" (ReturnValue):"d"(InputPort));
-    return ReturnValue;
-}
-
-KERNEL_API
-VOID
-HlIoPortOutByte (
-    USHORT OutputPort,
-    BYTE OutputData
-    )
-
-/*++
-
-Routine Description:
-
-    This routine sends one byte to the specified legacy I/O port.
-
-Arguments:
-
-    OutputPort - Supplies the port to send a byte to.
-
-    OutputData - Supplies the data to send.
-
-Return Value:
-
-    None.
-
---*/
-
-{
-
-    //
-    // execute the outb instruction. There are no outputs, but both variables
-    // are inputs to their respective registers.
-    //
-
-    asm volatile ("outb %%al,%%dx"::"a" (OutputData), "d"(OutputPort));
-
-    //
-    // Execute a no-op to give the bus time to settle.
-    //
-
-    asm volatile ("nop");
-    return;
-}
-
-KERNEL_API
-USHORT
-HlIoPortInShort (
-    USHORT InputPort
-    )
-
-/*++
-
-Routine Description:
-
-    This routine gets one 16 bit value from the specified legacy I/O port.
-
-Arguments:
-
-    InputPort - Supplies the port to receive a byte from.
-
-Return Value:
-
-    Returns the data at that port.
-
---*/
-
-{
-
-    USHORT ReturnValue;
-
-    //
-    // Clear eax and mark it as destroyed.
-    //
-
-    asm volatile ("xorl %%eax,%%eax":::"eax");
-
-    //
-    // Execute the inw instruction. Register ax has the output which should go
-    // in ReturnValue, and dx has the input which should come from InputPort.
-    //
-
-    asm volatile ("inw %%dx,%%ax":"=a" (ReturnValue):"d"(InputPort));
-    return ReturnValue;
-}
-
-KERNEL_API
-VOID
-HlIoPortOutShort (
-    USHORT OutputPort,
-    USHORT OutputData
-    )
-
-/*++
-
-Routine Description:
-
-    This routine sends one 16-bit value to the specified legacy I/O port.
-
-Arguments:
-
-    OutputPort - Supplies the port to send a byte to.
-
-    OutputData - Supplies the data to send.
-
-Return Value:
-
-    None.
-
---*/
-
-{
-
-    //
-    // execute the outb instruction. There are no outputs, but both variables
-    // are inputs to their respective registers.
-    //
-
-    asm volatile ("outw %%ax,%%dx"::"a" (OutputData), "d"(OutputPort));
-
-    //
-    // Execute a no-op to give the bus time to settle.
-    //
-
-    asm volatile ("nop");
-    return;
-}
-
-KERNEL_API
-ULONG
-HlIoPortInLong (
-    USHORT InputPort
-    )
-
-/*++
-
-Routine Description:
-
-    This routine gets a 32-bit value from the specified legacy I/O port.
-
-Arguments:
-
-    InputPort - Supplies the port to receive a long from.
-
-Return Value:
-
-    Returns the data at that port.
-
---*/
-
-{
-
-    ULONG ReturnValue;
-
-    //
-    // Clear eax and mark it as destroyed.
-    //
-
-    asm volatile ("xorl %%eax,%%eax":::"eax");
-
-    //
-    // Execute the inl instruction. Register eax has the output which should go
-    // in ReturnValue, and dx has the input which should come from InputPort.
-    //
-
-    asm volatile ("inl %%dx,%%eax":"=a" (ReturnValue):"d"(InputPort));
-    return ReturnValue;
-}
-
-KERNEL_API
-VOID
-HlIoPortOutLong (
-    USHORT OutputPort,
-    ULONG OutputData
-    )
-
-/*++
-
-Routine Description:
-
-    This routine sends one 32-bit to the specified legacy I/O port.
-
-Arguments:
-
-    OutputPort - Supplies the port to send a long to.
-
-    OutputData - Supplies the data to send.
-
-Return Value:
-
-    None.
-
---*/
-
-{
-
-    //
-    // execute the outl instruction. There are no outputs, but both variables
-    // are inputs to their respective registers.
-    //
-
-    asm volatile ("outl %%eax,%%dx"::"a" (OutputData), "d"(OutputPort));
-
-    //
-    // Execute a no-op to give the bus time to settle.
-    //
-
-    asm volatile ("nop");
-    return;
-}
-
-//
-// --------------------------------------------------------- Internal Functions
-//
-