static void
i8250fifo(Uart* uart, int level)
{
Ctlr *ctlr;
ctlr = uart->regs;
if(ctlr->hasfifo == 0)
return;
/*
* 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.
*/
ilock(ctlr);
while(!(csr8r(ctlr, Lsr) & Temt))
;
/*
* Set the trigger level, default is the max.
* value.
* Some UARTs require FIFOena to be set before
* other bits can take effect, so set it twice.
*/
ctlr->fena = level;
switch(level){
case 0:
break;
case 1:
level = FIFO1|FIFOena;
break;
case 4:
level = FIFO4|FIFOena;
break;
case 8:
level = FIFO8|FIFOena;
break;
default:
level = FIFO14|FIFOena;
break;
}
csr8w(ctlr, Fcr, level);
csr8w(ctlr, Fcr, level);
iunlock(ctlr);
}
static void
i8250dtr(Uart* uart, int on)
{
Ctlr *ctlr;
switch(bits){
case 5:
lcr |= Wls5;
break;
case 6:
lcr |= Wls6;
break;
case 7:
lcr |= Wls7;
break;
case 8:
lcr |= Wls8;
break;
default:
return -1;
}
ctlr->sticky[Lcr] = lcr;
csr8w(ctlr, Lcr, 0);
uart->bits = bits;
return 0;
}
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);
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
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);
/*
* 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);
}
/*
* If PhysUart has a non-nil .poll member, this
* routine will be called from the uartclock timer.
* If the Ctlr .poll member is non-zero, when the
* Uart is enabled interrupts will not be enabled
* and the result is polled input and output.
* Not very useful here, but ports to new hardware
* or simulators can use this to get serial I/O
* without setting up the interrupt mechanism.
*/
ctlr = uart->regs;
if(ctlr->iena || !ctlr->poll)
return;
i8250interrupt(nil, uart);
}
#endif