void ns16550_init(int minor) { uintptr_t pNS16550; uint8_t ucDataByte; uint32_t ulBaudDivisor; NS16550Context *pns16550Context; setRegister_f setReg; getRegister_f getReg; console_tbl *c = Console_Port_Tbl [minor]; pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context)); if (pns16550Context == NULL) { printk( "%s: Error: Not enough memory\n", __func__); rtems_fatal_error_occurred( 0xdeadbeef); } Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context; pns16550Context->ucModemCtrl=SP_MODEM_IRQ; pNS16550 = c->ulCtrlPort1; setReg = c->setRegister; getReg = c->getRegister; /* Clear the divisor latch, clear all interrupt enables, * and reset and * disable the FIFO's. */ (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0); ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR ); /* Set the divisor latch and set the baud rate. */ ulBaudDivisor = NS16550_GetBaudDivisor(c, (uintptr_t) c->pDeviceParams); ucDataByte = SP_LINE_DLAB; (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); /* XXX */ (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU)); (*setReg)( pNS16550,NS16550_INTERRUPT_ENABLE, (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU ) ); /* Clear the divisor latch and set the character size to eight bits */ /* with one stop bit and no parity checking. */ ucDataByte = EIGHT_BITS; (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); /* Enable and reset transmit and receive FIFOs. TJA */ ucDataByte = SP_FIFO_ENABLE; (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR); /* Set data terminal ready. */ /* And open interrupt tristate line */ (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl); (*getReg)(pNS16550, NS16550_LINE_STATUS ); (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER ); }
int ns16550_set_attributes( int minor, const struct termios *t ) { uint32_t pNS16550; uint32_t ulBaudDivisor; uint8_t ucLineControl; uint32_t baud_requested; setRegister_f setReg; rtems_interrupt_lock_context lock_context; const console_tbl *c = Console_Port_Tbl [minor]; pNS16550 = c->ulCtrlPort1; setReg = c->setRegister; /* * Calculate the baud rate divisor * * Assert ensures there is no division by 0. */ baud_requested = rtems_termios_baud_to_number(t->c_cflag); _Assert( baud_requested != 0 ); ulBaudDivisor = NS16550_GetBaudDivisor(c, baud_requested); ucLineControl = 0; /* * Parity */ if (t->c_cflag & PARENB) { ucLineControl |= SP_LINE_PAR; if (!(t->c_cflag & PARODD)) ucLineControl |= SP_LINE_ODD; } /* * Character Size */ if (t->c_cflag & CSIZE) { switch (t->c_cflag & CSIZE) { case CS5: ucLineControl |= FIVE_BITS; break; case CS6: ucLineControl |= SIX_BITS; break; case CS7: ucLineControl |= SEVEN_BITS; break; case CS8: ucLineControl |= EIGHT_BITS; break; } } else { ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */ } /* * Stop Bits */ if (t->c_cflag & CSTOPB) { ucLineControl |= SP_LINE_STOP; /* 2 stop bits */ } else { ; /* 1 stop bit */ } /* * Now actually set the chip */ rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); /* * Set the baud rate * * NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1, * the transmit buffer and interrupt enable registers * turn into the LSB and MSB divisor latch registers. */ (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB); (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff); (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff); /* * Now write the line control */ (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl ); rtems_interrupt_lock_release(&ns16550_lock, &lock_context); return 0; }
int ns16550_set_attributes( int minor, const struct termios *t ) { uint32_t pNS16550; uint32_t ulBaudDivisor; uint8_t ucLineControl; uint32_t baud_requested; setRegister_f setReg; uint32_t Irql; const console_tbl *c = Console_Port_Tbl [minor]; pNS16550 = c->ulCtrlPort1; setReg = c->setRegister; /* * Calculate the baud rate divisor */ baud_requested = rtems_termios_baud_to_number(t->c_cflag); ulBaudDivisor = NS16550_GetBaudDivisor(c, baud_requested); ucLineControl = 0; /* * Parity */ if (t->c_cflag & PARENB) { ucLineControl |= SP_LINE_PAR; if (!(t->c_cflag & PARODD)) ucLineControl |= SP_LINE_ODD; } /* * Character Size */ if (t->c_cflag & CSIZE) { switch (t->c_cflag & CSIZE) { case CS5: ucLineControl |= FIVE_BITS; break; case CS6: ucLineControl |= SIX_BITS; break; case CS7: ucLineControl |= SEVEN_BITS; break; case CS8: ucLineControl |= EIGHT_BITS; break; } } else { ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */ } /* * Stop Bits */ if (t->c_cflag & CSTOPB) { ucLineControl |= SP_LINE_STOP; /* 2 stop bits */ } else { ; /* 1 stop bit */ } /* * Now actually set the chip */ rtems_interrupt_disable(Irql); /* * Set the baud rate */ (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB); /* XXX are these registers right? */ (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff); (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff); /* * Now write the line control */ (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl ); rtems_interrupt_enable(Irql); return 0; }