Edit

openbios/openboot/obp/dev/serial/su16550

Branch :

  • Show log

    Commit

  • Author : Stefan Reinauer
    Date : 2010-08-25 09:23:17
    Hash : 1a08f436
    Message : change to well-formed svn directory structure. git-svn-id: svn://coreboot.org/openboot/trunk@2 4486e004-3823-0410-90c7-fb508cc143bb

  • io.fth
  • \ ========== Copyright Header Begin ==========================================
    \ 
    \ Hypervisor Software File: io.fth
    \ 
    \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
    \ 
    \  - Do no alter or remove copyright notices
    \ 
    \  - Redistribution and use of this software in source and binary forms, with 
    \    or without modification, are permitted provided that the following 
    \    conditions are met: 
    \ 
    \  - Redistribution of source code must retain the above copyright notice, 
    \    this list of conditions and the following disclaimer.
    \ 
    \  - Redistribution in binary form must reproduce the above copyright notice,
    \    this list of conditions and the following disclaimer in the
    \    documentation and/or other materials provided with the distribution. 
    \ 
    \    Neither the name of Sun Microsystems, Inc. or the names of contributors 
    \ may be used to endorse or promote products derived from this software 
    \ without specific prior written permission. 
    \ 
    \     This software is provided "AS IS," without a warranty of any kind. 
    \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 
    \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
    \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN 
    \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR 
    \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 
    \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN 
    \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR 
    \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE 
    \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, 
    \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF 
    \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
    \ 
    \ You acknowledge that this software is not designed, licensed or
    \ intended for use in the design, construction, operation or maintenance of
    \ any nuclear facility. 
    \ 
    \ ========== Copyright Header End ============================================
    id: @(#)io.fth 1.11 05/02/02
    purpose: 
    copyright: Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved
    copyright: Use is subject to license terms.
    
    headers
    d# 90   constant ubufsize
    ubufsize buffer: ubuf
    0 	value  getptr
    0 	value  putptr
    0 	value  endptr
    
    h# 10 constant msr-cts
    
    variable ttylock
    
    : initubuf  ( -- )
       ubuf  is  getptr
       ubuf  is  putptr
       ubuf ubufsize + is endptr
    ;
    
    \ put key into uart buffer, ignoring overun
    : bput	( key -- )	\ put key into buffer
       putptr endptr >= if  ubuf is putptr  then
       putptr c! putptr 1+ is putptr
    ;
    
    \ clear the uart buffer for put task
    : bputclr  ( -- )  getptr is putptr  ;
    
    
    \ Fetch a key from buffer
    : bget	( -- key )
       getptr endptr >= if  ubuf is getptr  then
       getptr c@ getptr 1+ is getptr
    ;
    
    \ return TRUE if uart buffer is empty.
    : ubuf-empty? 	( -- flag )  getptr putptr =  ;
    
    headerless
    : usea  ( -- )  uartbase to uart  ;
    : useb  ( -- )  uartbase to uart  ;
    
    create init-table
      h# 00 c, h# 01 c,	\ Interrupt Enable Register = disable all interrupts
      h# 00 c, h# 04 c,	\ Modem Control Register = disable all Modem fcns
      h# 00 c, h# 02 c,	\ FIFO Control Register = 0
      h# 01 c, h# 02 c,	\ FIFO Control Register = 1
      h# 83 c, h# 03 c,	\ Line Control Register = 83
      h# 60 c, h# 00 c,	\ Divisor Latch Register LSB
      h# 00 c, h# 01 c,	\ Divisor Latch Register MSB
      h# 03 c, h# 03 c,	\ Line Control Register = 03
    \  h# 00 c, h# 04 c,	\ Modem Control Register unchanged
    \  h# 10 c, h# 04 c,	\ Modem Control Register = enable Loopback Mode
      h# 08 c, h# 04 c,	\ Modem Control Register = IRQ enable
    here init-table - constant #table-size
    
    : uart!  ( c offset -- )  uart + c!  ;
    : uart@  ( offset -- c )  uart + c@  ;
    
    \ read SIO modem status register
    : msr@  ( -- byte )  h# 06 uart@  ;
    
    \ bsc is ready if CTS is asserted
    : hw-bsc-ready?  ( -- ready? )  msr@ msr-cts and  ;
    
    defer bsc-ready?  ( -- ready? )		\ depends on flow control
    ' true is bsc-ready?			\ default is no flow control
    
    \ Receive Buffer Register RO
    : rbr@  ( -- c )  0 uart@  ;
    
    \ Transmit Holding Register WO
    : thr!  ( c -- )  0 uart!  ;
    
    0 value IER-reg		\ IER contents at entry
    
    \ Interrupt Enable Register
    : ier!  ( c -- )  1 uart!  ;
    : ier@  ( -- c )  1 uart@  ;
    
    : disable_tx_int  ( -- )
       ier@ dup to IER-reg  h# fd and ier!
    ;
    
    : restore_tx_int  ( -- )
       IER-reg ier!
    ;
    
    variable LSR-reg	\ LSR shadow
    
    \ Line Status Register RO
    : lsr@  ( -- c )  5 uart@ dup  LSR-reg c@ or LSR-reg c!  ;
    
    : inituart  ( -- )
       initubuf
       \ One time init stuff goes here.
       init-table #table-size bounds  ?do
          i c@ i 1+ c@ uart!
       2 +loop
    ;
    
    \ Test for "break" character received.
    : ubreak?  ( -- flag )  lsr@ drop LSR-reg c@ h# 10 and  ;
    
    : uemit?  ( -- flag )
       bsc-ready? if
          lsr@ h# 20 and
       else
          1 ms
          0
       then
    ;
    
    : uemit  ( char -- )  begin  uemit?  until  thr!  ;
    
    : (ukey?)  ( -- flag )  lsr@ h# 01 and  ;
    : (ukey)   ( -- key )   begin  (ukey?)  until  rbr@  ;
    
    \ Wait for characters to finish transmitting
    : uwait  ( -- )  begin  lsr@ h# 40 and  until  ;
    
    \ This is called from Solaris under certain circumstances
    \ such as early boot and panics.
    \ In order to prevent MP systems registering spurious interrupts on
    \ the CPU(s) not in OBP, or to prevent corruption of console I/O by
    \ OBP and the console driver writing at the same time at the start of
    \ panic handling, disable the THRE (tx) interrupt during the write.
    \ Restore the state of the interrupt before waiting for the last
    \ character to finish transmitting, this will ensure that Solaris
    \ will see a tx interrupt in the case that it is waiting for one ie
    \ OBP was called with data in the FIFO.
    : uwrite  ( adr len -- #written )
       ttylock on
       disable_tx_int
       tuck  bounds  ?do	( len )
          i c@  uemit	( len )
       loop			( len )
       restore_tx_int	( len )
       uwait		( len )
       ttylock off		( len )
    ;
    
    : uread  ( -- )
       ttylock on
       begin  (ukey?)  while  (ukey) bput  repeat
       ttylock off
    ;
    
    : ukey?  ( -- flag )  uread  ubuf-empty? 0=  ;
    
    : ukey   ( -- char )  begin  ukey?  until  bget  ;
    
    : clear-break  ( -- )
       ukey? drop bputclr
       0 LSR-reg c!
    ;
    
    headerless
    d# 24.000.000	constant xtal-clk
    d# 13 d# 16 *	constant chip-div
    
    : fifo!  ( data -- )  h# 02 uart!  ;
    : lcr!   ( data -- )  h# 03 uart!  ;
    : mcr!   ( data -- )  h# 8 or  h# 04 uart!  ;
    : mcr@   ( -- data )  h# 04 uart@  ;
    
    struct
      1 field LCR-reg	\ Line Control
      1 field MCR-reg	\ Modem Control
    drop
    variable shadow-regs
    
    \ Set the s/w version of the Line Control Register
    : set-bits  ( data addr -- )  tuck  c@ or  swap c!  ;
    : set-lcr  ( data -- )  shadow-regs LCR-reg set-bits  ;
    : set-mcr  ( data -- )  shadow-regs MCR-reg set-bits  ;
    
    : hold-uart  ( -- )
      h# 00 fifo!	\ Disable and clear FIFOs
    ;
    
    : release-uart  ( -- )
      5 uart@ drop          \ clear error bits in LSR
      shadow-regs			( addr )
      dup LCR-reg c@ lcr!	\ Write LCR (and select bank 0)
      MCR-reg c@ mcr!	\ write MCR reg
      h# 01 fifo!		\ FIFOs enabled
      1 ms                  \ Allow device to stabilize.
    ;			\ This delay is necessary to prevent
    			\ garbage characters from being sent out on
    			\ the first transmit resulting in a framing
    			\ error. For some reason this device needs
    			\ a moment to stabilize.
    
    : set-baud  ( baud -- )
      chip-div *		( baud' )
      xtal-clk d# 8 <<	( baud' clk' )
      swap / d# 8 >>	( divisor )
      wbsplit		( lo hi )
      h# 83 lcr!            ( lo hi )       \ select Bank 1
      h# 01 uart!		( lo )		\ Write Hi Div
      h# 00 uart!		( -- )		\ Write Lo Div
      h# 03 lcr!            ( -- )          \ select Bank 0
    ;
    
    : set-dtr-rts  ( on? -- )
       mcr@ swap
       if  3 or
       else  3 invert and
       then
       set-mcr
    ;
    
    : set-databits  ( #bits -- )
      case
        5 of  h# 00  endof		\ 5 bits data
        6 of  h# 01  endof		\ 6 bits data
        7 of  h# 02  endof		\ 7 bits data
        8 of  h# 03  endof		\ 8 bits data
      endcase			( data )
      shadow-regs LCR-reg c!	( -- )
    ;
    
    : set-parity  ( parity -- )
      case
        p.mark  of  h# 28  endof	\ mark
        p.even  of  h# 18  endof	\ even
        p.odd   of  h# 08  endof	\ odd
        p.none  of  h#  0  endof	\ none
        p.space of  h# 38  endof	\ space
      endcase			( data )
      set-lcr			(  )
    ;
    
    : set-stopbits  ( #stp -- )
      1- if  h# 04 set-lcr  then
    ;
    
    : no-flow-ctrl  ( -- )
       ['] true is bsc-ready?
    ;
    
    : hard-flow-ctrl  ( -- )
       ['] hw-bsc-ready? is bsc-ready?
    ;
    
    \ XXX needs work looking at the input chars as they arrive:
    : soft-flow-ctrl  ( -- )
       ." XXXX unimp: su16550 handshake" cr
       ['] true is bsc-ready?
    ;
    
    : set-handshake  ( hs -- )
       case
          hs.none of  no-flow-ctrl    endof
          hs.hw   of  hard-flow-ctrl  endof
          hs.sw   of  soft-flow-ctrl  endof
       endcase
    ;
    
    headers
    
    \ mode parameter is switching between 232 and 433 (sp?)
    : config-serial  ( hs stp prty dbits baud dtr-rts-on? mode -- )
       hold-uart		( hs stp prty dbits baud dtr-rts-on? mode )
       rs-mode-select	( hs stp prty dbits baud dtr-rts-on? )
       set-dtr-rts		( hs stp prty dbits baud )
       set-baud		( hs stp prty dbits )
       set-databits		( hs stp prty )
       set-parity		( hs stp )
       set-stopbits		( hs )
       set-handshake	(  )
       release-uart		(  )
    ;
    
    headerless