📄 serial_saa9730.c
字号:
UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT8 *p_param ) ; /* IN: character to write */staticINT32 SERIAL_SAA9730_ctrl( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ t_SERIAL_ctrl_descriptor *p_param ) ; /* IN: IOCTL structure */static voidserial_int_handler( void *dummy );/************************************************************************ * Implementation : Public functions ************************************************************************//************************************************************************ * * SERIAL_SAA9730_install * Description : * ------------- * * Installs the serial SAA9730 serial device drivers services in * the IO system at the reserved device slot, found in the * 'sysdev.h' file, which defines all major device numbers. * * Note: * This service is the only public declared interface function; all * provided device driver services are static declared, but this * function installs the function pointers in the io-system to * enable the provided public driver services. * * Parameters : * ------------ * * - * * * Return values : * --------------- * * 'OK'(=0) * 'ERROR_IO_ILLEGAL_MAJOR': Illegal major device number * 'ERROR_IO_NO_SPACE': Device slot already allocated * ************************************************************************/INT32 SERIAL_SAA9730_install( void ){ UINT32 tty; UINT32 major, minor; /* pre-initialize local variables and install device services */ IO_install( SYS_MAJOR_SERIAL_SAA9730, /* major device number */ (t_io_service) SERIAL_SAA9730_init, /* 'init' service */ NULL, /* 'open' service na */ NULL, /* 'close' service na */ (t_io_service) SERIAL_SAA9730_read, /* 'read' service */ (t_io_service) SERIAL_SAA9730_write, /* 'write' service */ (t_io_service) SERIAL_SAA9730_ctrl ) ; /* 'ctrl' service */ /* call our own 'init' service */ /* TTY0 */ tty = PORT_TTY0; SYSCON_read( SYSCON_COM_TTY0_MAJOR, (void *)(&major), sizeof(UINT32) ); if (major == SYS_MAJOR_SERIAL_SAA9730) { SYSCON_read(SYSCON_COM_TTY0_MINOR, (void *)(&minor), sizeof(UINT32)); IO_init( SYS_MAJOR_SERIAL_SAA9730, minor, &tty ); } /* TTY1 */ tty = PORT_TTY1; SYSCON_read( SYSCON_COM_TTY1_MAJOR, (void *)(&major), sizeof(UINT32) ); if (major == SYS_MAJOR_SERIAL_SAA9730) { SYSCON_read(SYSCON_COM_TTY1_MINOR, (void *)(&minor), sizeof(UINT32)); IO_init( SYS_MAJOR_SERIAL_SAA9730, minor, &tty ); } return OK;}/************************************************************************ * Implementation : Static functions ************************************************************************//************************************************************************ * Implementation : Device driver services ************************************************************************//************************************************************************ * * SERIAL_SAA9730_init * Description : * ------------- * This service initializes the serial driver and configures * the applicable channels according to the configuration data, read * from the 'syscon' parameters: * * Parameters : * ------------ * * 'major', IN, major device number * 'minor', IN, not used * 'port', IN, port mapping (PORT_TTY0/PORT_TTY1) * * Return values : * --------------- * * 'OK'(=0) * ************************************************************************/static INT32 SERIAL_SAA9730_init( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT32 *port ) /* IN: port mapping */{ UINT8 baudrate, databits, parity, stopbits, flowctrl ; UINT8 dll, dlm; void *saa9730base ; t_SERIAL_ctrl_descriptor ctrl; bool ic_in_use; UINT32 int_line; /* 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_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( SYSCON_BOARD_SAA9730_BASE_ID, (void *)&saa9730base, sizeof(void *) ); saa9730base = (void *)KSEG1(saa9730base); /* 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] ; evm_base = (UINT32*)(saa9730base + EVM_SAA9730_BASE_OFS); /* initialize physical register addresses */ saa9730base = saa9730base + SERIAL_SAA9730_UART_OFS ; phy_rbr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_RBR_OFS ); phy_thr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_THR_OFS ); phy_ier = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_IER_OFS ); phy_iir = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_IIR_OFS ); phy_fcr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_FCR_OFS ); phy_lcr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_LCR_OFS ); phy_mcr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_MCR_OFS ); phy_lsr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_LSR_OFS ); phy_msr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_MSR_OFS ); phy_scr = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_SCR_OFS ); phy_dll = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_DLL_OFS ); phy_dlm = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_DLM_OFS ); phy_cfg = saa9730base + SWAP_BYTEADDR_EL(SERIAL_SAA9730_CFG_OFS ); /* init IER: clear all interrupts */ *phy_ier = 0; shadow_ier = 0; *(evm_base + EVM_SAA9730_SECIERSW_OFS) &= ~EVM_SAA9730_SECIER_UART1; /* initalize poll buffer pointers */ recv_getptr = recv_putptr = &recv_buffer[0] ; /* clear statistical info */ uart_statistics.ua_tx_bytes = 0 ; uart_statistics.ua_rx_bytes = 0 ; uart_statistics.ua_rx_overrun = 0 ; uart_statistics.ua_rx_parity = 0 ; uart_statistics.ua_rx_framing = 0 ; uart_statistics.ua_rx_break = 0 ; uart_statistics.ua_rx_irqs = 0 ; uart_statistics.ua_no_of_init++ ; /* init baudrate to 38.400 buad: 1) enable DL-registers 2) set DLL + DLM divisor registers 3) disable DL-registers */ *phy_lcr = SERIAL_LCR_DLAB ; *phy_dll = dll ; *phy_dlm = dlm ; *phy_lcr = 0 ; /* init LCR: 1) 8-bit data 2) 1 stop bit 3) no parity */ *phy_lcr = ( databits | stopbits | parity ) ; /* init FCR: 1) enable FIFO 2) reset receiver FIFO 3) reset transmitter FIFO */ *phy_fcr = (SERIAL_FCR_ENABLE | SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET) ; /* init CFG: 1) set CTSEN (not RTSEN, as RTS is controlled in sw) */ *phy_cfg = shadow_flow = flowctrl == SERIAL_FLOWCTRL_HARDWARE ? SERIAL_CFG_CTSEN : 0; /* init MCR: 1) set DTR 2) set RTS 3) set OUT2 (PC style interrupt mask) */ shadow_mcr |= SERIAL_MCR_RTS; *phy_mcr = shadow_mcr; /* reenable interrupt mask */ *(evm_base + EVM_SAA9730_SECIERSW_OFS) = EVM_SAA9730_SECIER_UART1; *phy_ier = shadow_ier ; /* If this is the first call of init, we need to install interrupt handler */ if( !registered ) { if( ic_in_use ) { EXCEP_register_ic_isr( int_line, serial_int_handler, NULL, NULL ); } else { EXCEP_register_cpu_isr( int_line, serial_int_handler, NULL, NULL ); } registered = TRUE; } /* Configure driver to be interrupt driven */ ctrl.sc_command = SERIAL_CTRL_RCV_IRQ_ON; SERIAL_SAA9730_ctrl( major, minor, &ctrl ); return( OK ) ;}/************************************************************************ * serial_int_handler ************************************************************************/static voidserial_int_handler( void *dummy ){ t_SERIAL_ctrl_descriptor ctrl; ctrl.sc_command = SERIAL_CTRL_RCV_IRQ; SERIAL_SAA9730_ctrl( 0, 0, &ctrl );}/************************************************************************ * * SERIAL_SAA9730_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 :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -