📄 serial_ti16550.c
字号:
} /* TTY1 */ tty = PORT_TTY1; SYSCON_read( SYSCON_COM_TTY1_MAJOR, (void *)(&major), sizeof(UINT32) ); if (major == SYS_MAJOR_SERIAL_TI16550) { SYSCON_read(SYSCON_COM_TTY1_MINOR, (void *)(&minor), sizeof(UINT32)); IO_init( SYS_MAJOR_SERIAL_TI16550, minor, &tty ); } return OK;}/************************************************************************ * Implementation : Device driver services ************************************************************************//************************************************************************ * * SERIAL_TI16550_init * Description : * ------------- * This service initializes the serial driver and configures * the applicable channels according to the configuration data, read * from SYSCON * * Parameters : * ------------ * * 'major', IN, major device number * 'minor', IN, not used * 'port', IN, port mapping (PORT_TTY0/PORT_TTY1) * * Return values : * --------------- * * 'OK'(=0) * ************************************************************************/staticINT32 SERIAL_TI16550_init( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT32 *port ) /* IN: port mapping */{ INT32 rcode; UINT32 brkresval; UINT8 baudrate, databits, parity, stopbits, flowctrl; UINT8 dll, dlm; t_SERIAL_ctrl_descriptor ctrl; void *minor_data; bool ic_in_use; UINT32 int_line; bool adjust_break; /* Get settings */ SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_BAUDRATE_ID : SYSCON_COM_TTY1_BAUDRATE_ID, (void *)&baudrate, sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_DATABITS_ID : SYSCON_COM_TTY1_DATABITS_ID, (void *)&databits, sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_PARITY_ID : SYSCON_COM_TTY1_PARITY_ID, (void *)&parity, sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_STOPBITS_ID : SYSCON_COM_TTY1_STOPBITS_ID, (void *)&stopbits, sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_FLOWCTRL_ID : SYSCON_COM_TTY1_FLOWCTRL_ID, (void *)&flowctrl, sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_REG_SIZE_ID : SYSCON_COM_TTY1_REG_SIZE_ID, (void *)&size[minor], sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_REG_SPACING_ID : SYSCON_COM_TTY1_REG_SPACING_ID, (void *)&spacing, sizeof(UINT8) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_IC_IN_USE_ID : SYSCON_COM_TTY1_IC_IN_USE_ID, (void *)&ic_in_use, sizeof(bool) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_INTLINE_ID : SYSCON_COM_TTY1_INTLINE_ID, (void *)&int_line, sizeof(UINT32) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_ADJUST_BREAK_ID : SYSCON_COM_TTY1_ADJUST_BREAK_ID, (void *)&adjust_break, sizeof(bool) ); SYSCON_read( (*port == PORT_TTY0) ? SYSCON_COM_TTY0_BIGEND_ID : SYSCON_COM_TTY1_BIGEND_ID, (void *)&bigend, sizeof(bool) ); SYSCON_read( (minor == SERIAL_MINOR_TI16550_UART0) ? SYSCON_BOARD_TI16C550C_BASE0_ID : SYSCON_BOARD_TI16C550C_BASE1_ID, (void *)&ti16550base, sizeof(void *) ); SYSCON_read( (minor == SERIAL_MINOR_TI16550_UART0) ? SYSCON_COM_TTY0_BAUDRATE_DIV_ID : SYSCON_COM_TTY1_BAUDRATE_DIV_ID, (void *)&serial_baudrate, sizeof(t_SERIAL_baudrate_div *) ); ti16550base = (void *)KSEG1(ti16550base); /* Verify settings */ if (baudrate >= SERIAL_BAUDRATE_MAX || (*serial_baudrate)[baudrate] == SERIAL_ILLEGAL ) { return( ERROR_SERIAL_INVALID_BAUDRATE ) ; } if (databits >= SERIAL_DATABITS_MAX || serial_databits[databits] == SERIAL_ILLEGAL ) { return( ERROR_SERIAL_INVALID_DATABITS ) ; } if (parity >= SERIAL_PARITY_MAX || serial_parity[parity] == SERIAL_ILLEGAL ) { return( ERROR_SERIAL_INVALID_PARITY ) ; } if (stopbits >= SERIAL_STOPBITS_MAX || serial_stopbits[stopbits] == SERIAL_ILLEGAL ) { return( ERROR_SERIAL_INVALID_STOPBITS ) ; } if (flowctrl >= SERIAL_FLOWCTRL_MAX || flowctrl == SERIAL_FLOWCTRL_NOT_DEFINED ) { return( ERROR_SERIAL_INVALID_FLOWCTRL ) ; } /* convert */ dll = (*serial_baudrate)[baudrate] & 0xff; dlm = ((*serial_baudrate)[baudrate]>>8) & 0xff; databits = serial_databits[databits]; parity = serial_parity[parity]; stopbits = serial_stopbits[stopbits]; /* initialize physical register addresses based on size and spacing */ phy_rbr[minor] = SET_ADDR( SERIAL_TI16550_RBR_OFS ); phy_thr[minor] = SET_ADDR( SERIAL_TI16550_THR_OFS ); phy_ier[minor] = SET_ADDR( SERIAL_TI16550_IER_OFS ); phy_iir[minor] = SET_ADDR( SERIAL_TI16550_IIR_OFS ); phy_fcr[minor] = SET_ADDR( SERIAL_TI16550_FCR_OFS ); phy_lcr[minor] = SET_ADDR( SERIAL_TI16550_LCR_OFS ); phy_mcr[minor] = SET_ADDR( SERIAL_TI16550_MCR_OFS ); phy_lsr[minor] = SET_ADDR( SERIAL_TI16550_LSR_OFS ); phy_msr[minor] = SET_ADDR( SERIAL_TI16550_MSR_OFS ); phy_scr[minor] = SET_ADDR( SERIAL_TI16550_SCR_OFS ); phy_dll[minor] = SET_ADDR( SERIAL_TI16550_DLL_OFS ); phy_dlm[minor] = SET_ADDR( SERIAL_TI16550_DLM_OFS ); /* init IER: clear all interrupts */ PHY_IER_W(minor, 0); shadow_ier[minor] = 0; /* initalize poll buffer pointers */ recv_getptr[minor] = recv_putptr[minor] = &recv_buffer[minor][0]; /* clear statistical info */ uart_statistics[minor].ua_tx_bytes = 0; uart_statistics[minor].ua_rx_bytes = 0; uart_statistics[minor].ua_rx_overrun = 0; uart_statistics[minor].ua_rx_parity = 0; uart_statistics[minor].ua_rx_framing = 0; uart_statistics[minor].ua_rx_break = 0; uart_statistics[minor].ua_rx_irqs = 0; uart_statistics[minor].ua_no_of_init++; /* Init baudrate : * 1) enable DL-registers * 2) set DLL + DLM divisor registers * 3) disable DL-registers */ PHY_LCR_W(minor, SERIAL_LCR_DLAB); PHY_DLL_W(minor, dll); PHY_DLM_W(minor, dlm); PHY_LCR_W(minor, 0); /* Init LCR: * 1) 8-bit data * 2) 1 stop bit * 3) no parity */ PHY_LCR_W(minor, databits | stopbits | parity); /* Init FCR: * 1) enable FIFO * 2) reset receiver FIFO * 3) reset transmitter FIFO * 4) set receive FIFO threshold to 4 */ PHY_FCR_W(minor, SERIAL_FCR_ENABLE | SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET | SERIAL_FCR_RCVFIFO_4); /* Init MCR: * 1) set DTR * 2) set RTS * 3) enable auto-flow control (both RX and TX) * (Texas only; SuperIO and Philips: No OPeration) * 4) enable interrupt mask (OUT2) * (SuperIO and Philips only; Texas: NC on Atlas,SEAD,Malta) */ shadow_flow[minor] = flowctrl == SERIAL_FLOWCTRL_HARDWARE ? SERIAL_MCR_AFE : 0; shadow_mcr[minor] = shadow_flow[minor] | SERIAL_MCR_DTR | SERIAL_MCR_RTS | SERIAL_MCR_OUT2; PHY_MCR_W(minor, shadow_mcr[minor]); if( adjust_break ) { /* limit BRKRES register to prevent low baudrates from forcing reset */ rcode = SYSCON_read( SYSCON_BOARD_BRKRES_ID, &brkresval, sizeof(brkresval)); if(rcode == OK && brkresval && brkresval < (*serial_baudrate)[baudrate]>>4) { brkresval = (*serial_baudrate)[baudrate] >> 4; rcode = SYSCON_write( SYSCON_BOARD_BRKRES_ID, &brkresval, sizeof(brkresval)); } } /* If this is the first call of init, we need to install interrupt handler */ if( !registered[minor] ) { /* Determine parameter for interrupt service routine */ minor_data = (void *)&minor_numbers[minor]; /* Register interrupt handler */ if( ic_in_use ) { EXCEP_register_ic_isr( int_line, serial_int_handler, minor_data, NULL ); } else { EXCEP_register_cpu_isr( int_line, serial_int_handler, minor_data, NULL ); } registered[minor] = TRUE; } /* Configure driver to be interrupt driven */ ctrl.sc_command = SERIAL_CTRL_RCV_IRQ_ON; SERIAL_TI16550_ctrl( major, minor, &ctrl ); return( OK );}/************************************************************************ * serial_int_handler ************************************************************************/static voidserial_int_handler( void *data ) /* Holds the minor device number */{ t_SERIAL_ctrl_descriptor ctrl; ctrl.sc_command = SERIAL_CTRL_RCV_IRQ; SERIAL_TI16550_ctrl( 0, *(UINT32 *)data, &ctrl );}/************************************************************************ * * SERIAL_TI16550_read * Description : * ------------- * This service polls the specified channel for any present character. * If any character is present, it will be read into the user allocated * variable; if none present, completion = 'ERROR_SERIAL_NO_CHARACTER' * will be returned. * * Parameters : * ------------ * * 'major', IN, major device number * 'minor', IN, minor device number for multi device drivers * 'p_param', OUT, character read * * Return values : * --------------- * 'OK' = 0x00: character read into user variable * 'ERROR_SERIAL_NO_CHARACTER': no character present on channel * 'ERROR_SERIAL_COMM_ERROR': communication error detected * 'ERROR_SERIAL_COMM_BREAK': 'BREAK' detected * ************************************************************************/static INT32 SERIAL_TI16550_read( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT8 *p_param ) /* OUT: character been read */{ UINT32 rc; UINT32 lstat;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -