Annotation of lucent/sys/src/boot/pc/8250.c, revision 1.1.1.1

1.1       root        1: #include "u.h"
                      2: #include "lib.h"
                      3: #include "mem.h"
                      4: #include "dat.h"
                      5: #include "fns.h"
                      6: #include "io.h"
                      7: 
                      8: /*
                      9:  *  INS8250 uart
                     10:  */
                     11: enum
                     12: {
                     13:        /*
                     14:         *  register numbers
                     15:         */
                     16:        Data=   0,              /* xmit/rcv buffer */
                     17:        Iena=   1,              /* interrupt enable */
                     18:         Ircv=  (1<<0),         /*  for char rcv'd */
                     19:         Ixmt=  (1<<1),         /*  for xmit buffer empty */
                     20:         Irstat=(1<<2),         /*  for change in rcv'er status */
                     21:         Imstat=(1<<3),         /*  for change in modem status */
                     22:        Istat=  2,              /* interrupt flag (read) */
                     23:        Tctl=   2,              /* test control (write) */
                     24:        Format= 3,              /* byte format */
                     25:         Bits8= (3<<0),         /*  8 bits/byte */
                     26:         Stop2= (1<<2),         /*  2 stop bits */
                     27:         Pena=  (1<<3),         /*  generate parity */
                     28:         Peven= (1<<4),         /*  even parity */
                     29:         Pforce=(1<<5),         /*  force parity */
                     30:         Break= (1<<6),         /*  generate a break */
                     31:         Dra=   (1<<7),         /*  address the divisor */
                     32:        Mctl=   4,              /* modem control */
                     33:         Dtr=   (1<<0),         /*  data terminal ready */
                     34:         Rts=   (1<<1),         /*  request to send */
                     35:         Ri=    (1<<2),         /*  ring */
                     36:         Inton= (1<<3),         /*  turn on interrupts */
                     37:         Loop=  (1<<4),         /*  loop back */
                     38:        Lstat=  5,              /* line status */
                     39:         Inready=(1<<0),        /*  receive buffer full */
                     40:         Oerror=(1<<1),         /*  receiver overrun */
                     41:         Perror=(1<<2),         /*  receiver parity error */
                     42:         Ferror=(1<<3),         /*  rcv framing error */
                     43:         Outready=(1<<5),       /*  output buffer empty */
                     44:        Mstat=  6,              /* modem status */
                     45:         Ctsc=  (1<<0),         /*  clear to send changed */
                     46:         Dsrc=  (1<<1),         /*  data set ready changed */
                     47:         Rire=  (1<<2),         /*  rising edge of ring indicator */
                     48:         Dcdc=  (1<<3),         /*  data carrier detect changed */
                     49:         Cts=   (1<<4),         /*  complement of clear to send line */
                     50:         Dsr=   (1<<5),         /*  complement of data set ready line */
                     51:         Ring=  (1<<6),         /*  complement of ring indicator line */
                     52:         Dcd=   (1<<7),         /*  complement of data carrier detect line */
                     53:        Scratch=7,              /* scratchpad */
                     54:        Dlsb=   0,              /* divisor lsb */
                     55:        Dmsb=   1,              /* divisor msb */
                     56: 
                     57:        Serial= 0,
                     58:        Modem=  1,
                     59: };
                     60: 
                     61: typedef struct Uart    Uart;
                     62: struct Uart
                     63: {
                     64:        int     port;
                     65:        uchar   sticky[8];      /* sticky write register values */
                     66:        uchar   txbusy;
                     67: 
                     68:        void    (*rx)(int);     /* routine to take a received character */
                     69:        int     (*tx)(void);    /* routine to get a character to transmit */
                     70: 
                     71:        ulong   frame;
                     72:        ulong   overrun;
                     73: };
                     74: 
                     75: Uart   uart[1];
                     76: 
                     77: #define UartFREQ 1843200
                     78: 
                     79: #define uartwrreg(u,r,v)       outb((u)->port + r, (u)->sticky[r] | (v))
                     80: #define uartrdreg(u,r)         inb((u)->port + r)
                     81: 
                     82: /*
                     83:  *  set the baud rate by calculating and setting the baudrate
                     84:  *  generator constant.  This will work with fairly non-standard
                     85:  *  baud rates.
                     86:  */
                     87: static void
                     88: uartsetbaud(Uart *up, int rate)
                     89: {
                     90:        ulong brconst;
                     91: 
                     92:        brconst = (UartFREQ+8*rate-1)/(16*rate);
                     93: 
                     94:        uartwrreg(up, Format, Dra);
                     95:        outb(up->port+Dmsb, (brconst>>8) & 0xff);
                     96:        outb(up->port+Dlsb, brconst & 0xff);
                     97:        uartwrreg(up, Format, 0);
                     98: }
                     99: 
                    100: /*
                    101:  *  toggle DTR
                    102:  */
                    103: static void
                    104: uartdtr(Uart *up, int n)
                    105: {
                    106:        if(n)
                    107:                up->sticky[Mctl] |= Dtr;
                    108:        else
                    109:                up->sticky[Mctl] &= ~Dtr;
                    110:        uartwrreg(up, Mctl, 0);
                    111: }
                    112: 
                    113: /*
                    114:  *  toggle RTS
                    115:  */
                    116: static void
                    117: uartrts(Uart *up, int n)
                    118: {
                    119:        if(n)
                    120:                up->sticky[Mctl] |= Rts;
                    121:        else
                    122:                up->sticky[Mctl] &= ~Rts;
                    123:        uartwrreg(up, Mctl, 0);
                    124: }
                    125: 
                    126: static void
                    127: uartintr(Ureg*, void *arg)
                    128: {
                    129:        Uart *up;
                    130:        int ch;
                    131:        int s, l, loops;
                    132: 
                    133:        up = arg;
                    134:        for(loops = 0; loops < 1024; loops++){
                    135:                s = uartrdreg(up, Istat);
                    136:                switch(s){
                    137:                case 6: /* receiver line status */
                    138:                        l = uartrdreg(up, Lstat);
                    139:                        if(l & Ferror)
                    140:                                up->frame++;
                    141:                        if(l & Oerror)
                    142:                                up->overrun++;
                    143:                        break;
                    144:        
                    145:                case 4: /* received data available */
                    146:                case 12:
                    147:                        ch = inb(up->port+Data);
                    148:                        if(up->rx)
                    149:                                (*up->rx)(ch);
                    150:                        break;
                    151:        
                    152:                case 2: /* transmitter empty */
                    153:                        ch = -1;
                    154:                        if(up->tx)
                    155:                                ch = (*up->tx)();
                    156:                        if(ch != -1)
                    157:                                outb(up->port+Data, ch);
                    158:                        else
                    159:                                up->txbusy = 0;
                    160:                        break;
                    161:        
                    162:                case 0: /* modem status */
                    163:                        uartrdreg(up, Mstat);
                    164:                        break;
                    165:        
                    166:                default:
                    167:                        if(s&1)
                    168:                                return;
                    169:                        print("weird modem interrupt #%2.2ux\n", s);
                    170:                        break;
                    171:                }
                    172:        }
                    173:        panic("uartintr: 0x%2.2ux\n", uartrdreg(up, Istat));
                    174: }
                    175: 
                    176: /*
                    177:  *  turn on a port's interrupts.  set DTR and RTS
                    178:  */
                    179: static void
                    180: uartenable(Uart *up)
                    181: {
                    182:        /*
                    183:         *  turn on interrupts
                    184:         */
                    185:        up->sticky[Iena] = 0;
                    186:        if(up->tx)
                    187:                up->sticky[Iena] |= Ixmt;
                    188:        if(up->rx)
                    189:                up->sticky[Iena] |= Ircv|Irstat;
                    190:        uartwrreg(up, Iena, 0);
                    191: 
                    192:        /*
                    193:         *  turn on DTR and RTS
                    194:         */
                    195:        uartdtr(up, 1);
                    196:        uartrts(up, 1);
                    197: }
                    198: 
                    199: void
                    200: uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
                    201: {
                    202:        Uart *up = &uart[0];
                    203: 
                    204:        if(up->port)
                    205:                return;
                    206: 
                    207:        switch(port){
                    208: 
                    209:        case 0:
                    210:                up->port = 0x3F8;
                    211:                setvec(Uart0vec, uartintr, up);
                    212:                break;
                    213: 
                    214:        case 1:
                    215:                up->port = 0x2F8;
                    216:                setvec(Uart1vec, uartintr, up);
                    217:                break;
                    218: 
                    219:        default:
                    220:                return;
                    221:        }
                    222: 
                    223:        /*
                    224:         *  set rate to 9600 baud.
                    225:         *  8 bits/character.
                    226:         *  1 stop bit.
                    227:         *  interrupts enabled.
                    228:         */
                    229:        uartsetbaud(up, 9600);
                    230:        up->sticky[Format] = Bits8;
                    231:        uartwrreg(up, Format, 0);
                    232:        up->sticky[Mctl] |= Inton;
                    233:        uartwrreg(up, Mctl, 0x0);
                    234: 
                    235:        up->rx = rx;
                    236:        up->tx = tx;
                    237:        uartenable(up);
                    238:        if(baud)
                    239:                uartsetbaud(up, baud);
                    240: }
                    241: 
                    242: static void
                    243: uartputc(int c)
                    244: {
                    245:        Uart *up = &uart[0];
                    246:        int i;
                    247: 
                    248:        for(i = 0; i < 100; i++){
                    249:                if(uartrdreg(up, Lstat) & Outready)
                    250:                        break;
                    251:                delay(1);
                    252:        }
                    253:        outb(up->port+Data, c);
                    254: }
                    255: 
                    256: void
                    257: uartputs(IOQ *q, char *s, int n)
                    258: {
                    259:        Uart *up = &uart[0];
                    260:        int c, x;
                    261: 
                    262:        while(n--){
                    263:                if(*s == '\n')
                    264:                        q->putc(q, '\r');
                    265:                q->putc(q, *s++);
                    266:        }
                    267:        x = splhi();
                    268:        if(up->txbusy == 0 && (c = q->getc(q)) != -1){
                    269:                uartputc(c & 0xFF);
                    270:                up->txbusy = 1;
                    271:        }
                    272:        splx(x);
                    273: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.