Annotation of lucent/sys/src/boot/pc/8250.c, revision 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.