static Uart* i8250pnp(void) { int i; Ctlr *ctlr; Uart *head, *uart; head = i8250uart; for(i = 0; i < nelem(i8250uart); i++){ /* * Does it exist? * Should be able to write/read the Scratch Pad * and reserve the I/O space. */ uart = &i8250uart[i]; ctlr = uart->regs; csr8o(ctlr, Scr, 0x55); if(csr8r(ctlr, Scr) == 0x55) continue; if(ioalloc(ctlr->io, 8, 0, uart->name) < 0) continue; if(uart == head) head = uart->next; else (uart-1)->next = uart->next; } return head; }
static int i8250baud(Uart* uart, int baud) { #ifdef notdef /* don't change the speed */ ulong bgc; Ctlr *ctlr; extern int i8250freq; /* In the config file */ /* * Set the Baud rate by calculating and setting the Baud rate * Generator Constant. This will work with fairly non-standard * Baud rates. */ if(i8250freq == 0 || baud <= 0) return -1; bgc = (i8250freq+8*baud-1)/(16*baud); ctlr = uart->regs; while(csr8r(ctlr, Usr) & Busy) delay(1); csr8w(ctlr, Lcr, Dlab); /* begin kludge */ csr8o(ctlr, Dlm, bgc>>8); csr8o(ctlr, Dll, bgc); csr8w(ctlr, Lcr, 0); #endif uart->baud = baud; return 0; }
static int i8250baud(Uart* uart, int baud) { ulong bgc; Ctlr *ctlr; /* * Set the Baud rate by calculating and setting the Baud rate * Generator Constant. This will work with fairly non-standard * Baud rates. */ if(uart->freq == 0 || baud <= 0) return -1; bgc = (uart->freq+8*baud-1)/(16*baud); ctlr = uart->regs; csr8w(ctlr, Lcr, Dlab); csr8o(ctlr, Dlm, bgc>>8); csr8o(ctlr, Dll, bgc); csr8w(ctlr, Lcr, 0); uart->baud = baud; return 0; }
void putc(int c) { int i; for(i = 0; !(csr8r(Lsr) & Thre) && i < 1000000; i++) ; csr8o(Thr, (uchar)c); for(i = 0; !(csr8r(Lsr) & Thre) && i < 1000000; i++) ; }
Uart* i8250console(char* cfg) { int i; Uart *uart; Ctlr *ctlr; char *cmd, *p; /* * Before i8250pnp() is run can only set the console * to 0 or 1 because those are the only uart structs which * will be the same before and after that. */ if((p = getconf("console")) == nil && (p = cfg) == nil) return nil; i = strtoul(p, &cmd, 0); if(p == cmd) return nil; if((uart = uartconsole(i, cmd)) != nil){ consuart = uart; return uart; } switch(i){ default: return nil; case 0: uart = &i8250uart[0]; break; case 1: uart = &i8250uart[1]; break; } /* * Does it exist? * Should be able to write/read * the Scratch Pad. */ ctlr = uart->regs; csr8o(ctlr, Scr, 0x55); if(csr8r(ctlr, Scr) != 0x55) return nil; (*uart->phys->enable)(uart, 0); uartctl(uart, "b9600 l8 pn s1 i1"); if(*cmd != '\0') uartctl(uart, cmd); consuart = uart; uart->console = 1; return uart; }
static void i8250putc(Uart* uart, int c) { int i; Ctlr *ctlr; ctlr = uart->regs; for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++) delay(1); csr8o(ctlr, Thr, c); for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++) delay(1); }
static void i8250kick(Uart* uart) { int i; Ctlr *ctlr; if(/* uart->cts == 0 || */ uart->blocked) return; if(!normalprint) { /* early */ if (uart->op < uart->oe) emptyoutstage(uart, uart->oe - uart->op); while ((i = uartstageoutput(uart)) > 0) emptyoutstage(uart, i); return; } /* nothing more to send? then disable xmit intr */ ctlr = uart->regs; if (uart->op >= uart->oe && qlen(uart->oq) == 0 && csr8r(ctlr, Lsr) & Temt) { ctlr->sticky[Ier] &= ~Ethre; csr8w(ctlr, Ier, 0); return; } /* * 128 here is an arbitrary limit to make sure * we don't stay in this loop too long. If the * chip's output queue is longer than 128, too * bad -- presotto */ for(i = 0; i < 128; i++){ if(!(csr8r(ctlr, Lsr) & Thre)) break; if(uart->op >= uart->oe && uartstageoutput(uart) == 0) break; csr8o(ctlr, Thr, *uart->op++); /* start tx */ ctlr->sticky[Ier] |= Ethre; csr8w(ctlr, Ier, 0); /* intr when done */ } }
static void i8250putc(Uart* uart, int c) { int i; Ctlr *ctlr; if (!normalprint) { /* too early; use brute force */ int s = splhi(); while (!(((ulong *)PHYSCONS)[Lsr] & Thre)) ; ((ulong *)PHYSCONS)[Thr] = c; coherence(); splx(s); return; } ctlr = uart->regs; for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++) delay(1); csr8o(ctlr, Thr, (uchar)c); for(i = 0; !(csr8r(ctlr, Lsr) & Thre) && i < 128; i++) delay(1); }
static void i8250kick(Uart* uart) { int i; Ctlr *ctlr; if(uart->cts == 0 || uart->blocked) return; /* * 128 here is an arbitrary limit to make sure * we don't stay in this loop too long. If the * chip's output queue is longer than 128, too * bad -- presotto */ ctlr = uart->regs; for(i = 0; i < 128; i++){ if(!(csr8r(ctlr, Lsr) & Thre)) break; if(uart->op >= uart->oe && uartstageoutput(uart) == 0) break; csr8o(ctlr, Thr, *(uart->op++)); } }
static void i8250enable(Uart* uart, int ie) { int mode; Ctlr *ctlr; if (up == nil) return; /* too soon */ ctlr = uart->regs; /* omap only: set uart/irda/cir mode to uart */ mode = csr8r(ctlr, Mdr); csr8o(ctlr, Mdr, (mode & ~Modemask) | Modeuart); ctlr->sticky[Lcr] = Wls8; /* no parity */ csr8w(ctlr, Lcr, 0); /* * Check if there is a FIFO. * Changing the FIFOena bit in Fcr flushes data * from both receive and transmit FIFOs; there's * no easy way to guarantee not losing data on * the receive side, but it's possible to wait until * the transmitter is really empty. * Also, reading the Iir outwith i8250interrupt() * can be dangerous, but this should only happen * once, before interrupts are enabled. */ ilock(ctlr); if(!ctlr->checkfifo){ /* * Wait until the transmitter is really empty. */ while(!(csr8r(ctlr, Lsr) & Temt)) ; csr8w(ctlr, Fcr, FIFOena); if(csr8r(ctlr, Iir) & Ifena) ctlr->hasfifo = 1; csr8w(ctlr, Fcr, 0); ctlr->checkfifo = 1; } iunlock(ctlr); /* * Enable interrupts and turn on DTR and RTS. * Be careful if this is called to set up a polled serial line * early on not to try to enable interrupts as interrupt- * -enabling mechanisms might not be set up yet. */ if(ie){ if(ctlr->iena == 0 && !ctlr->poll){ irqenable(ctlr->irq, i8250interrupt, uart, uart->name); ctlr->iena = 1; } ctlr->sticky[Ier] = Erda; // ctlr->sticky[Mcr] |= Ie; /* not on omap */ ctlr->sticky[Mcr] = 0; } else{ ctlr->sticky[Ier] = 0; ctlr->sticky[Mcr] = 0; } csr8w(ctlr, Ier, 0); csr8w(ctlr, Mcr, 0); (*uart->phys->dtr)(uart, 1); (*uart->phys->rts)(uart, 1); /* * During startup, the i8259 interrupt controller is reset. * This may result in a lost interrupt from the i8250 uart. * The i8250 thinks the interrupt is still outstanding and does not * generate any further interrupts. The workaround is to call the * interrupt handler to clear any pending interrupt events. * Note: this must be done after setting Ier. */ if(ie) i8250interrupt(nil, uart); }