diff --git a/src/devices/uart_16550.rs b/src/devices/uart_16550.rs
index c888c8a33151d9ea8f5b5772a0d3d63e3c176de6..d482504b054c2affbc114df2d5f9d6bcf4d26dad 100644
--- a/src/devices/uart_16550.rs
+++ b/src/devices/uart_16550.rs
@@ -1,3 +1,5 @@
+use core::convert::TryInto;
+
 use crate::syscall::io::{Io, Pio, Mmio, ReadOnly};
 
 bitflags! {
@@ -22,7 +24,8 @@ bitflags! {
 }
 
 #[allow(dead_code)]
-pub struct SerialPort<T: Io<Value = u8>> {
+#[repr(packed)]
+pub struct SerialPort<T: Io> {
     /// Data register, read to receive, write to send
     data: T,
     /// Interrupt enable
@@ -53,40 +56,38 @@ impl SerialPort<Pio<u8>> {
     }
 }
 
-impl SerialPort<Mmio<u8>> {
-    pub fn new(_base: usize) -> SerialPort<Mmio<u8>> {
-        SerialPort {
-            data: Mmio::new(),
-            int_en: Mmio::new(),
-            fifo_ctrl: Mmio::new(),
-            line_ctrl: Mmio::new(),
-            modem_ctrl: Mmio::new(),
-            line_sts: ReadOnly::new(Mmio::new()),
-            modem_sts: ReadOnly::new(Mmio::new())
-        }
+impl SerialPort<Mmio<u32>> {
+    pub unsafe fn new(base: usize) -> &'static mut SerialPort<Mmio<u32>> {
+        &mut *(base as *mut Self)
     }
 }
 
-impl<T: Io<Value = u8>> SerialPort<T> {
+impl<T: Io> SerialPort<T>
+    where T::Value: From<u8> + TryInto<u8>
+{
     pub fn init(&mut self) {
         //TODO: Cleanup
-        self.int_en.write(0x00);
-        self.line_ctrl.write(0x80);
-        self.data.write(0x01);
-        self.int_en.write(0x00);
-        self.line_ctrl.write(0x03);
-        self.fifo_ctrl.write(0xC7);
-        self.modem_ctrl.write(0x0B);
-        self.int_en.write(0x01);
+        self.int_en.write(0x00.into());
+        self.line_ctrl.write(0x80.into());
+        self.data.write(0x01.into());
+        self.int_en.write(0x00.into());
+        self.line_ctrl.write(0x03.into());
+        self.fifo_ctrl.write(0xC7.into());
+        self.modem_ctrl.write(0x0B.into());
+        self.int_en.write(0x01.into());
     }
 
     fn line_sts(&self) -> LineStsFlags {
-        LineStsFlags::from_bits_truncate(self.line_sts.read())
+        LineStsFlags::from_bits_truncate(
+            (self.line_sts.read() & 0xFF.into()).try_into().unwrap_or(0)
+        )
     }
 
     pub fn receive(&mut self) -> Option<u8> {
         if self.line_sts().contains(LineStsFlags::INPUT_FULL) {
-            Some(self.data.read())
+            Some(
+                (self.data.read() & 0xFF.into()).try_into().unwrap_or(0)
+            )
         } else {
             None
         }
@@ -94,7 +95,7 @@ impl<T: Io<Value = u8>> SerialPort<T> {
 
     pub fn send(&mut self, data: u8) {
         while ! self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) {}
-        self.data.write(data);
+        self.data.write(data.into());
     }
 
     pub fn write(&mut self, buf: &[u8]) {
@@ -105,6 +106,10 @@ impl<T: Io<Value = u8>> SerialPort<T> {
                     self.send(b' ');
                     self.send(8);
                 },
+                b'\n' => {
+                    self.send(b'\r');
+                    self.send(b'\n');
+                },
                 _ => {
                     self.send(b);
                 }