📄 ns16550.c
字号:
}/* * ns16550_set_attributes * * This function sets the channel to reflect the requested termios * port settings. */NS16550_STATIC int ns16550_set_attributes( int minor, const struct termios *t){ unsigned32 pNS16550; unsigned32 ulBaudDivisor; unsigned8 ucLineControl; unsigned32 baud_requested; setRegister_f setReg; getRegister_f getReg; unsigned32 Irql; pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1; setReg = Console_Port_Tbl[minor].setRegister; getReg = Console_Port_Tbl[minor].getRegister; /* * Calculate the baud rate divisor */ baud_requested = t->c_cflag & CBAUD; if (!baud_requested) baud_requested = B9600; /* default to 9600 baud */ ulBaudDivisor = NS16550_Baud( (unsigned32) Console_Port_Tbl[minor].ulClock, termios_baud_to_number(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;}/* * ns16550_process * * This routine is the console interrupt handler for A port. */NS16550_STATIC void ns16550_process( int minor){ unsigned32 pNS16550; volatile unsigned8 ucLineStatus; volatile unsigned8 ucInterruptId; unsigned char cChar; getRegister_f getReg; setRegister_f setReg; pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1; getReg = Console_Port_Tbl[minor].getRegister; setReg = Console_Port_Tbl[minor].setRegister; do { /* * Deal with any received characters */ while(TRUE) { ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); if(~ucLineStatus & SP_LSR_RDY) { break; } cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); rtems_termios_enqueue_raw_characters( Console_Port_Data[minor].termios_data, &cChar, 1 ); } /* * TX all the characters we can */ while(TRUE) { ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); if(~ucLineStatus & SP_LSR_THOLD) { /* * We'll get another interrupt when * the transmitter holding reg. becomes * free again */ break; }#if 0 /* XXX flow control not completely supported in libchip */ if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) { ns16550_negate_RTS(minor); }#endif rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1); if (rtems_termios_dequeue_characters( Console_Port_Data[minor].termios_data, 1)) { if (Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) { ns16550_negate_RTS(minor); } Console_Port_Data[minor].bActive = FALSE; ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); break; } ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID); } } while((ucInterruptId&0xf)!=0x1);}/* * ns16550_isr */NS16550_STATIC rtems_isr ns16550_isr( rtems_vector_number vector){ int minor; for(minor=0;minor<Console_Port_Count;minor++) { if(Console_Port_Tbl[minor].ulIntVector == vector && Console_Port_Tbl[minor].deviceType == SERIAL_NS16550 ) { ns16550_process(minor); } }}/* * ns16550_enable_interrupts * * This routine initializes the port to have the specified interrupts masked. */NS16550_STATIC void ns16550_enable_interrupts( int minor, int mask){ unsigned32 pNS16550; setRegister_f setReg; pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1; setReg = Console_Port_Tbl[minor].setRegister; (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);}/* * ns16550_initialize_interrupts * * This routine initializes the port to operate in interrupt driver mode. */ NS16550_STATIC void ns16550_initialize_interrupts(int minor){ ns16550_init(minor); Console_Port_Data[minor].bActive = FALSE; set_vector(ns16550_isr, Console_Port_Tbl[minor].ulIntVector, 1); ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);}/* * ns16550_write_support_int * * Console Termios output entry point. */NS16550_STATIC int ns16550_write_support_int( int minor, const char *buf, int len){ unsigned32 Irql; unsigned32 pNS16550; setRegister_f setReg; setReg = Console_Port_Tbl[minor].setRegister; pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1; /* * We are using interrupt driven output and termios only sends us * one character at a time. */ if ( !len ) return 0; if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) { ns16550_assert_RTS(minor); } rtems_interrupt_disable(Irql); if ( Console_Port_Data[minor].bActive == FALSE) { Console_Port_Data[minor].bActive = TRUE; ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR); } (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf); rtems_interrupt_enable(Irql); return 1;}/* * ns16550_write_support_polled * * Console Termios output entry point. * */NS16550_STATIC int ns16550_write_support_polled( int minor, const char *buf, int len){ int nwrite = 0; /* * poll each byte in the string out of the port. */ while (nwrite < len) { /* * transmit character */ ns16550_write_polled(minor, *buf++); nwrite++; } /* * return the number of bytes written. */ return nwrite;}/* * ns16550_inbyte_nonblocking_polled * * Console Termios polling input entry point. */NS16550_STATIC int ns16550_inbyte_nonblocking_polled( int minor ){ unsigned32 pNS16550; unsigned char ucLineStatus; char cChar; getRegister_f getReg; pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1; getReg = Console_Port_Tbl[minor].getRegister; ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); if(ucLineStatus & SP_LSR_RDY) { cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); return (int)cChar; } else { return -1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -