gonzui


Format: Advanced Search

tkernel_2/monitor/driver/sio/src/ns16550.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2013/02/28.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:  *      ns16550.c
   18:  *
   19:  *       serial port I/O
   20:  */
   21: 
   22: #include <tmonitor.h>
   23: 
   24: /*
   25:  * serial port hardware configuration definition
   26:  */
   27: typedef struct {
   28:         UW     iob;                /* I/O base address */
   29: } DEFSIO;
   30: 
   31: #if 0
   32: #  define IOSTEP                /* I/O address separation */
   33: #  define CLOCK                 /* input clock (Hz) */
   34: 
   35: /* ----------------------------------------------------------------------- */
   36: #elif _TEF_EM1D_
   37: #  include <arm/em1d512.h>
   38:    LOCAL const DEFSIO   DefSIO[3] = {
   39:                         { UARTnBase(UART0) },
   40:                         { UARTnBase(UART1) },
   41:                         { UARTnBase(UART2) },
   42:    };
   43: #  define IOSTEP        4
   44: #  define CLOCK         229376000
   45: 
   46: // Unlike ordinary 16550, all registers exist and are independently accessed.
   47: // (No overlaid meaning/behavior per read or write, or switching of register sets is necessary.
   48: // also, 16-bits read/write to data register while FIFO is enabled causes two character input/output.)
   49: //
   50: #define UART(n)         ( IOB + (n) * IOSTEP )
   51: #define regDATA         UART(0)                /* data register          (RW) */
   52: #define regINTE         UART(1)                /* interrupt enable register   (RW) */
   53: #define regINTS         UART(2)                /* interrupt selection register(R ) */
   54: #define regFCTL         UART(3)                /* FIFO control register  (RW) */
   55: #define regLCTL         UART(4)                /* line control register  (RW) */
   56: #define regMCTL         UART(5)                /* model control register (RW) */
   57: #define regLSTS         UART(6)                /* line status register   (R ) */
   58: #define regMSTS         UART(7)                /* modem status register  (R ) */
   59: #define regSCRA         UART(8)                /* scratch data register  (RW) */
   60: #define regDIVL         UART(9)                /* divisor lower bits     (RW) */
   61: #define regDIVH         UART(10)       /* divisor upper bits     (RW) */
   62: /* ----------------------------------------------------------------------- */
   63: #endif
   64: 
   65: #define N_DEFSIO        ( sizeof(DefSIO) / sizeof(DEFSIO) )
   66: 
   67: /* ------------------------------------------------------------------------ */
   68: 
   69: #define IOB     ( scb->info )               /* I/O base address */
   70: 
   71: #if !defined(IN)
   72: #define IN(x)           in_b(x)
   73: #define OUT(x, y)       out_b((x), (y))
   74: #endif
   75: 
   76: /*
   77:  * definition of 16550
   78:  *       Every access is byte access.
   79:  */
   80: #if !defined(UART)
   81: #define UART(n)         ( IOB + (n) * IOSTEP )
   82: #define regDATA         UART(0)                /* data register          (RW) */
   83: #define regINTE         UART(1)                /* interrupt enable register   (RW) */
   84: #define regINTS         UART(2)                /* interrupt selection register(R ) */
   85: #define regFCTL         UART(2)                /* FIFO control register  ( W) */
   86: #define regLCTL         UART(3)                /* line control register  (RW) */
   87: #define regMCTL         UART(4)                /* modem control register (RW) */
   88: #define regLSTS         UART(5)                /* line status register   (R ) */
   89: #define regMSTS         UART(6)                /* modem status register  (R ) */
   90: #define regSCRA         UART(7)                /* scratch data register  (RW) */
   91: #define regDIVL         UART(0)                /* divisor lower bits     (RW) */
   92: #define regDIVH         UART(1)                /* divisor upper bits     (RW) */
   93: #endif
   94: 
   95: /* transmission speed -> divided counter value. */
   96: #define LC_LINE_SPEED(bps)      (CLOCK / 16 / (bps))
   97: 
   98: /* line control register */
   99: #define LC_DLAB         0x80           /* (divided) counter access */
  100: #define LC_SBRK         0x40           /* send BREAK */
  101: #define LC_SNDP         0x20           /* with parity */
  102: #define LC_EVNP         0x10           /* even parity */
  103: #define LC_ENAP         0x08           /* enable parity */
  104: #define LC_STOP         0x04           /* stop bit */
  105: #define LC_BLEN         0x03           /* number of bits in data */
  106: 
  107: /* default : 8 bits data, one bit stop, and no parity. */
  108: #define dtLC            (0x03)
  109: 
  110: /* line status register */
  111: #define LS_TSRE         0x40           /* transmission shift register empty */
  112: #define LS_THRE         0x20           /* transmission hold register empty */
  113: #define LS_BINT         0x10           /* BREAK received */
  114: #define LS_FERR         0x08           /* framing error */
  115: #define LS_PERR         0x04           /* parity error */
  116: #define LS_OERR         0x02           /* overrun error */
  117: #define LS_DRDY         0x01           /* received data ready */
  118: 
  119: #define LS_RxERR        (LS_BINT|LS_FERR|LS_PERR|LS_OERR)
  120: 
  121: /* modem control register */
  122: #define MC_OUT2         0x08           /* auxiliary output #2 (enable interrupt) */
  123: #define MC_OUT1         0x04           /* auxiliary output #1 */
  124: #define MC_RTS          0x02            /* Request To Send */
  125: #define MC_DTR          0x01            /* Data Terminal Ready */
  126: 
  127: /* default : disable interrupt */
  128: #define dtMC            (MC_RTS | MC_DTR)
  129: 
  130: /* modem status register */
  131: #define MS_CD           0x80             /* Data Carrier Detect */
  132: #define MS_RI           0x40             /* Ring Indicate */
  133: #define MS_DR           0x20             /* Data Set Ready */
  134: #define MS_CS           0x10             /* Clear To Send */
  135: #define MS_D_CD         0x08           /* change of CD detected */
  136: #define MS_D_RI         0x04           /* change of RI detected */
  137: #define MS_D_DR         0x02           /* change of DR detected */
  138: #define MS_D_CS         0x01           /* change of CS detected */
  139: 
  140: /* interrupt enable register */
  141: #define IM_MSTS         0x08           /* modem state interrupt */
  142: #define IM_LSTS         0x04           /* receive line state interrupt */
  143: #define IM_SND          0x02            /* send ready interrupt  */
  144: #define IM_RCV          0x01            /* input data ready interrupt */
  145: 
  146: /* default : all interrupts are disabled */
  147: #define dtIM            (0x00)
  148: 
  149: /* interrupt selection register */
  150: #define IS_PEND         0x01           /* interrupt is pending */
  151: #define IS_ID           0x0e             /* interrupt ID */
  152: #define IS_CTMO         0x0c           /* ID=6 timeout interrupt */
  153: #define IS_LSTS         0x06           /* ID=3 receive line state interrupt. */
  154: #define IS_RCV          0x04            /* ID=2 input data ready interupt */
  155: #define IS_SND          0x02            /* ID=1 send ready interrupt */
  156: #define IS_MSTS         0x00           /* ID=0 modem state interrupt */
  157: #define IS_FIFO         0xc0           /* FIFO is in use */
  158: 
  159: /* FIFO control register */
  160: #define FC_TL01         0x00           /* receive interrupt threshold ( 1 byte ) */
  161: #define FC_TL04         0x40           /* receive threshold 4 byte */
  162: #define FC_TL08         0x80           /* receive interrupt thereshold 8 byte */
  163: #define FC_TL14         0xc0           /* receive interrupt threshold 14 byte */
  164: #define FC_TXCLR        0x04           /* clear trasnmission FIFO */
  165: #define FC_RXCLR        0x02           /* receive FIFO clear. */
  166: #if _TEF_EM1D_
  167: #define FC_FIFO         0x21           /* enable 64 bytes FIFO */
  168: #define FIFO_SIZE       64                    /* FIFO size */
  169: #define dtFC            (FC_FIFO | FC_TL14)       /* default */
  170: #else
  171: #define FC_FIFO         0x01           /* enable FIFO */
  172: #define FIFO_SIZE       16                    /* FIFO size */
  173: #define dtFC            (FC_FIFO | FC_TL08)       /* default */
  174: #endif
  175: 
  176: /* default : enable FIFO, 8 byte threshold */
  177: #define dtFC_CLR        (FC_FIFO | FC_TXCLR | FC_RXCLR)        /* clear */
  178: 
  179: /* ------------------------------------------------------------------------ */
  180: 
  181: /*
  182:  * Power on RS-232C driver IC
  183:  */
  184: #define RSDRV_PWON(siocb)               /* no operation */
  185: 
  186: /*
  187:  * serial port I/O
  188:  */
  189: LOCAL void putSIO_16550( SIOCB *scb, UB c )
  190: {
  191:         RSDRV_PWON(scb);
  192: 
  193:         /* wait until transmission is ready. */
  194:         while ((IN(regLSTS) & LS_THRE) == 0);
  195: 
  196:         /* write transmission data */
  197:         OUT(regDATA, c);
  198: 
  199:         /* wait until the completion of transmission */
  200:         while ((IN(regLSTS) & LS_THRE) == 0);
  201: }
  202: 
  203: /*
  204:  * serial port input
  205:  *       tmo     timeout (milliseconds)
  206:  *              You can not wait forever.
  207:  *       return value       >= 0 : character code
  208:  *                 -1 : timeout
  209:  *       input data using buffer.
  210:  *       receive error is ignored.
  211:  */
  212: LOCAL W getSIO_16550(SIOCB *scb, W tmo )
  213: {
  214:         W      sts, c = 0;
  215: 
  216:         RSDRV_PWON();
  217: 
  218:         tmo *= 1000/20;                /* convert tmo to 20 usec units */
  219: 
  220:         /* receive as much data as possible in the receive buffer */
  221:         while (scb->iptr - scb->optr < SIO_RCVBUFSZ) {
  222: 
  223:                 /* is there data in FIFO? */
  224:                 if ( !((sts = IN(regLSTS)) & (LS_DRDY | LS_RxERR))) {
  225:                         if (scb->iptr != scb->optr) break;  /* already received */
  226:                         if (tmo-- <= 0) break;                   /* timeout */
  227:                         waitUsec(20);
  228:                         continue;
  229:                 }
  230: 
  231:                 /* receive data input */
  232:                 if (sts & LS_DRDY) c = IN(regDATA);
  233: 
  234:                 /* error check */
  235:                 if (sts & LS_RxERR) continue;
  236: 
  237:                 /* set data to rcvbuf */
  238:                 scb->rcvbuf[scb->iptr++ & SIO_PTRMSK] = c;
  239:         }
  240: 
  241:         /* return the data in rcvbuf */
  242:         return (scb->iptr == scb->optr)?
  243:                         -1 : scb->rcvbuf[scb->optr++ & SIO_PTRMSK];
  244: }
  245: 
  246: /* ------------------------------------------------------------------------ */
  247: 
  248: /*
  249:  * initialize serial port
  250:  *       serial port that is supported by the initialization of CFGSIO
  251:  *       speed   communication speed (bps)
  252:  *       initialize the serial port according to the specified parameters and set SIOCB
  253:  *       SIOCB is given in 0-cleared state initially.
  254:  *       Subsequent I/O operations uses the SIOCB.
  255:  *
  256:  *       Only for PC/AT version
  257:  *      if speed = 0, we use the value in biosp->siomode.
  258:  *       But we use only the transmission speed and other settings are ignored.
  259:  *       Efforts were made to be compatible B-right/V, but because of the ignorance of no-speed settings such as data length and stop bit length,
  260:  *       we have reduced functionality.
  261:  */
  262: EXPORT ER initSIO_ns16550(SIOCB *scb, const CFGSIO *csio, W speed)
  263: {
  264:         UH     div;
  265: 
  266:         if ( (UW)csio->info >= N_DEFSIO ) return E_PAR;
  267: 
  268:         /* select the target port */
  269:         scb->info = DefSIO[csio->info].iob;
  270: 
  271:         /* communicatin speed default value */
  272:         div = LC_LINE_SPEED(speed);
  273: 
  274:         /* initialize serial controller */
  275:         IN(regLSTS);                   /* clear IS_LSTS */
  276:         IN(regINTS);                   /* clear IS_SND  */
  277:         IN(regMSTS);                   /* clear IS_MSTS */
  278: 
  279:         OUT(regLCTL, LC_DLAB);
  280:         OUT(regDIVL, 0xff);            /* to keep the following from happening, Div = 0 */
  281:         OUT(regDIVH, div >> 8);                /* communication speed */
  282:         OUT(regDIVL, div & 0xff);
  283:         OUT(regLCTL, dtLC);            /* line mode */
  284:         OUT(regFCTL, dtFC_CLR);                /* clear FIFO */
  285:         OUT(regFCTL, dtFC);            /* FIFO mode */
  286:         OUT(regMCTL, dtMC);            /* modem mode */
  287:         OUT(regINTE, dtIM);            /* interrupt mask */
  288: 
  289:         /* I/O function default */
  290:         scb->put = putSIO_16550;
  291:         scb->get = getSIO_16550;
  292: 
  293:         return E_OK;
  294: }