|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.