📄 serial_saa9730.c
字号:
* --------------- * '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 * * ************************************************************************/staticINT32 SERIAL_SAA9730_read( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT8 *p_param ) /* OUT: character been read */{ UINT32 rc ; UINT32 lstat ; UINT16 *getptr ; /* check for device initialization */ if (phy_lsr == NULL) { return( ERROR_SERIAL_UNKNOWN_DEVICE ) ; } SERIAL_SAA9730_irqpoll(); /* service UART */ getptr= recv_getptr ; if (getptr == recv_putptr) return( ERROR_SERIAL_NO_CHARACTER ) ; if (poll_retcode != OK) { poll_retcode = OK ; /* flush receive buffer up to the last received ctrl/c or break */ getptr = recv_flushptr; /* always read CTRL/C in case of 'break' or ctrl/c */ lstat = (*getptr & 0xff00) | CTRL_C; rc = ERROR_SERIAL_COMM_BREAK; } else { lstat = *getptr; rc = OK; } *p_param = lstat ; uart_statistics.ua_rx_bytes++ ; /* check for errors */ if (lstat & ((SERIAL_LSR_OE<<8) | (SERIAL_LSR_PE<<8) | (SERIAL_LSR_FE<<8))) { if (rc == OK) rc = ERROR_SERIAL_COMM_ERROR ; if (lstat & (SERIAL_LSR_OE<<8)) uart_statistics.ua_rx_overrun++ ; if (lstat & (SERIAL_LSR_PE<<8)) uart_statistics.ua_rx_parity++ ; if (lstat & (SERIAL_LSR_FE<<8)) uart_statistics.ua_rx_framing++ ; } if (++getptr >= &recv_buffer[POLLSIZE]) getptr= &recv_buffer[0] ; recv_getptr = getptr ; /* compute room in buffer */ if ( (shadow_mcr & SERIAL_MCR_RTS) == 0 && (((UINT32)getptr - (UINT32)recv_putptr) & ((POLLSIZE - 1) * sizeof(*getptr))) >= HW_LIMIT_START * sizeof(*getptr) ) { shadow_mcr |= SERIAL_MCR_RTS; *phy_mcr = shadow_mcr; } return( rc ) ;}/************************************************************************ * * SERIAL_SAA9730_irqpoll * Description : * ------------- * Disabling of interrupts around call of SERIAL_SAA9730_irq() * ************************************************************************/staticUINT32 SERIAL_SAA9730_irqpoll( void ){ UINT32 lstat; if (sys_disable_int()) { lstat = SERIAL_SAA9730_irq( 0 ); sys_enable_int(); } else lstat = SERIAL_SAA9730_irq( 0 ); return lstat;}/************************************************************************ * * SERIAL_SAA9730_irq * Description : * ------------- * This service empties the UART's FIFO buffer and puts the chars into * the cyclic receive buffer. * * This routine is called in both polled and interrupt mode. * and requires interrupts to be disabled. * * static variables written: * poll_retcode BREAK or CTRL/C has been read * recv_putptr pointer to next free position in cyclic queue. * * * static variables read: * phy_lsr pointer to UART line status register * phy_rbr pointer to UART receive data register * recv_getptr pointer to first unread position in cyclic queue. * recv_flushptr pointer to position of last read break or ctrl/c * ************************************************************************/staticUINT32 SERIAL_SAA9730_irq( UINT32 in_intrpt ){ UINT32 lstat ; /* LSR_OE, LSR_PE, LSR_FE and LSR_BI are clear on read */ UINT8 rdata ; UINT16 *putptr ; UINT32 room ; putptr= recv_putptr ; /* empty FIFO*/ for (lstat = *phy_lsr; lstat & SERIAL_LSR_DR; lstat = *phy_lsr) { rdata = *phy_rbr & 0xff; uart_statistics.ua_rx_irqs += in_intrpt; if (lstat & SERIAL_LSR_BI) { rdata = CTRL_C; uart_statistics.ua_rx_break++; } /* compute room left in buffer, AFTER this byte has been put */ room = ((UINT32)recv_getptr - (UINT32)putptr - 1) & ((POLLSIZE - 1) * sizeof(*putptr)); if (room <= HW_LIMIT_STOP * sizeof(*putptr) && shadow_flow != 0) { shadow_mcr &= ~SERIAL_MCR_RTS; *phy_mcr = shadow_mcr; } if (room == 0) { lstat |= SERIAL_LSR_OE; /* overrun */ /* overwrite previous char (overflow anyway) */ if (--putptr < &recv_buffer[0]) putptr= &recv_buffer[POLLSIZE-1] ; } *putptr = (lstat << 8) | rdata; if (rdata == CTRL_C) { poll_retcode = ERROR_SERIAL_COMM_BREAK ; recv_flushptr = putptr; } /* increase putptr to its future position */ if (++putptr >= &recv_buffer[POLLSIZE]) putptr= &recv_buffer[0] ; } recv_putptr = putptr ; return lstat;}/************************************************************************ * * SERIAL_SAA9730_write * Description : * ------------- * This service writes a character on the specified channel * * * Parameters : * ------------ * * 'major', IN, major device number * 'minor', IN, minor device number for multi device drivers * 'p_param', IN, pointer to character to write * * * Return values : * --------------- * 'OK' = 0x00: character has been written on channel * * ************************************************************************/staticINT32 SERIAL_SAA9730_write( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ UINT8 *p_param ) /* IN: pointer to character to write */{ UINT32 lstat ; /* check for device initialization */ if (phy_lsr == NULL) { return( ERROR_SERIAL_UNKNOWN_DEVICE ) ; } /* check modem status: not necessary at auto-flow *//* { UINT8 mstat ; do { mstat = *phy_msr ; } while (!(mstat & SERIAL_MSR_CTS)); }*/ /* check line status */ do { /* OBS: LSR_OE, LSR_PE, LSR_FE and LSR_BI are cleared on read */ lstat = SERIAL_SAA9730_irqpoll() ; } while (!(lstat & SERIAL_LSR_THRE)) ; /* write character */ *phy_thr = *p_param ; uart_statistics.ua_tx_bytes++ ; return( OK ) ;}/************************************************************************ * * SERIAL_SAA9730_ctrl * Description : * ------------- * This service performs the actions defined by t_SERIAL_ctrl_command_ids * on the specified channel. * * * Parameters : * ------------ * * 'major', IN, major device number * 'minor', IN, minor device number for multi device drivers * 'p_param', INOUT, IOCTL structure * * * Return values : * --------------- * 'OK' = 0x00: normal return * ERROR_SERIAL_COMM_BREAK: break or ctrl/c received * ERROR_SERIAL_COMM_ERROR: receive error, characters lost * * ************************************************************************/staticINT32 SERIAL_SAA9730_ctrl( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ t_SERIAL_ctrl_descriptor *p_param ) /* INOUT: IOCTL structure */{ UINT32 rcode ; /* check for device initialization */ if (phy_lsr == NULL) { return( ERROR_SERIAL_UNKNOWN_DEVICE ) ; } if (p_param == NULL) { return( ERROR_SERIAL_INVALID_ARGUMENT ) ; } rcode = OK ; switch( p_param->sc_command ) { case SERIAL_CTRL_POLL_BREAK: SERIAL_SAA9730_irqpoll(); /* service UART */ if( (rcode = poll_retcode) != OK ) { /* flush read buffer */ rcode = SERIAL_SAA9730_read( major, minor, (UINT8 *)&rcode ); } break ; case SERIAL_CTRL_GET_STATISTICS: memcpy((UINT8*)&p_param->sc_arg.sc_statistics, (UINT8 *)&uart_statistics, sizeof(uart_statistics)) ; break ; case SERIAL_CTRL_GET_LSR: p_param->sc_arg.sc_linestat = SERIAL_SAA9730_irqpoll(); break ; case SERIAL_CTRL_RCV_IRQ: /* acknowledge to Philips Event Monitor */ *(evm_base + EVM_SAA9730_SECISR_OFS) = EVM_SAA9730_SECIER_UART1; SERIAL_SAA9730_irq( 1 ); break ; case SERIAL_CTRL_RCV_IRQ_ON: *(evm_base + EVM_SAA9730_IER_OFS) |= EVM_SAA9730_IER_MASTER; *(evm_base + EVM_SAA9730_IERSW_OFS) |= EVM_SAA9730_IER_MASTER; *(evm_base + EVM_SAA9730_SECIER_OFS) |= EVM_SAA9730_SECIER_UART1; *phy_ier = shadow_ier = SERIAL_IER_RCVEN; break ; case SERIAL_CTRL_RCV_IRQ_OFF: *(evm_base + EVM_SAA9730_SECIER_OFS) &= ~EVM_SAA9730_SECIER_UART1; shadow_ier = *phy_ier = 0; break ; case SERIAL_CTRL_FORCE_DTR: if (p_param->sc_arg.sc_dtr == 0) shadow_mcr &= ~SERIAL_MCR_DTR; else shadow_mcr |= SERIAL_MCR_DTR; *phy_mcr = shadow_mcr; break ; case SERIAL_CTRL_GET_MSR: p_param->sc_arg.sc_msr = *phy_msr & ~(SERIAL_MSR_DSR | SERIAL_MSR_RI); if ((*(evm_base + EVM_SAA9730_IMR_OFS) & EVM_SAA9730_GPIO0) == 0) p_param->sc_arg.sc_msr |= SERIAL_MSR_RI; if ((*(evm_base + EVM_SAA9730_IMR_OFS) & EVM_SAA9730_GPIO1) == 0) p_param->sc_arg.sc_msr |= SERIAL_MSR_DSR; break ; case SERIAL_CTRL_SEND_BREAK: /* the normal LCR_BREAK bit does not function porperly */ *phy_cfg |= SERIAL_CFG_BREAK; sys_wait_ms(250); *phy_cfg &= ~SERIAL_CFG_BREAK; break ; default: rcode = ERROR_SERIAL_INVALID_ARGUMENT ; } return( rcode ) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -