]> git.saurik.com Git - apple/xnu.git/blobdiff - pexpert/i386/pe_serial.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / pexpert / i386 / pe_serial.c
index ff104bba5d64fddbe97f4fa4031bc50f6054a1a2..f056487a044ce0a798318ad729fd744266a7c829 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
 #include <pexpert/protos.h>
 #include <pexpert/pexpert.h>
 
-void   serial_putc(char);
-int    serial_getc(void);
-int    serial_init(void);
-
 /* standard port addresses */
 enum {
     COM1_PORT_ADDR = 0x3f8,
@@ -56,7 +52,8 @@ enum {
     UART_LCR = 3,  /* line control register         */
     UART_MCR = 4,  /* modem control register        */
     UART_LSR = 5,  /* line status register          */
-    UART_MSR = 6   /* modem status register         */
+    UART_MSR = 6,  /* modem status register         */
+    UART_SCR = 7   /* scratch register              */
 };
 
 enum {
@@ -73,12 +70,18 @@ enum {
 };
 
 enum {
+    UART_LSR_DR    = 0x01,
+    UART_LSR_OE    = 0x02,
+    UART_LSR_PE    = 0x04,
+    UART_LSR_FE    = 0x08,
     UART_LSR_THRE  = 0x20
 };
 
-#define UART_BAUD_RATE  115200
+static unsigned uart_baud_rate = 115200;
 #define UART_PORT_ADDR  COM1_PORT_ADDR
 
+#define UART_CLOCK  1843200   /* 1.8432 MHz clock */
+
 #define WRITE(r, v)  outb(UART_PORT_ADDR + UART_##r, v)
 #define READ(r)      inb(UART_PORT_ADDR + UART_##r)
 #define DELAY(x)     { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; }
@@ -88,22 +91,18 @@ static int uart_initted = 0;   /* 1 if init'ed */
 static int
 uart_probe( void )
 {
-    /* Verify that the Divisor Register is accessible */
-
-    WRITE( LCR, UART_LCR_DLAB );
-    WRITE( DLL, 0x5a );
-    if (READ(DLL) != 0x5a) return 0;
-    WRITE( DLL, 0xa5 );
-    if (READ(DLL) != 0xa5) return 0;
-    WRITE( LCR, 0x00 );
+    /* Verify that the Scratch Register is accessible */
+
+    WRITE( SCR, 0x5a );
+    if (READ(SCR) != 0x5a) return 0;
+    WRITE( SCR, 0xa5 );
+    if (READ(SCR) != 0xa5) return 0;
     return 1;
 }
 
 static void
 uart_set_baud_rate( unsigned long baud_rate )
 {
-    #define UART_CLOCK  1843200   /* 1.8432 MHz clock */
-
     const unsigned char lcr = READ( LCR );
     unsigned long       div;
 
@@ -126,9 +125,41 @@ uart_putc( char c )
     WRITE( THR, c );
 }
 
+static int
+uart_getc( void )
+{
+    /*
+     * This function returns:
+     * -1 : no data
+     * -2 : receiver error
+     * >0 : character received
+     */
+
+    unsigned char lsr;
+
+    if (!uart_initted) return -1;
+
+    lsr = READ( LSR );
+
+    if ( lsr & (UART_LSR_FE | UART_LSR_PE | UART_LSR_OE) )
+    {
+        READ( RBR ); /* discard */
+        return -2;
+    }
+
+    if ( lsr & UART_LSR_DR )
+    {
+        return READ( RBR );
+    }
+
+    return -1;
+}
+
 int serial_init( void )
 {
-    if ( /*uart_initted ||*/ uart_probe() == 0 ) return 0;
+    unsigned serial_baud_rate = 0;
+       
+    if ( uart_probe() == 0 ) return 0;
 
     /* Disable hardware interrupts */
 
@@ -143,9 +174,16 @@ int serial_init( void )
 
     WRITE( LCR, UART_LCR_8BITS );
 
-    /* Set baud rate */
+    /* Set baud rate - use the supplied boot-arg if available */
 
-    uart_set_baud_rate( UART_BAUD_RATE );
+    if (PE_parse_boot_argn("serialbaud", &serial_baud_rate, sizeof (serial_baud_rate)))
+    {
+           /* Valid divisor? */
+           if (!((UART_CLOCK / 16) % serial_baud_rate)) {
+                   uart_baud_rate = serial_baud_rate;
+           }
+    }
+    uart_set_baud_rate( uart_baud_rate );
 
     /* Assert DTR# and RTS# lines (OUT2?) */
 
@@ -163,10 +201,9 @@ int serial_init( void )
 void serial_putc( char c )
 {
     uart_putc(c);
-    if (c == '\n') uart_putc('\r');
 }
 
 int serial_getc( void )
 {
-    return 0;  /* not supported */
+    return uart_getc();
 }