📄 z85c30.c
字号:
* Calculate the baud rate divisor */ baud_requested = t->c_cflag & CBAUD; if (!baud_requested) baud_requested = B9600; /* default to 9600 baud */ ulBaudDivisor = Z85C30_Baud( (unsigned32) Console_Port_Tbl[minor].ulClock, (unsigned32) termios_baud_to_number( baud_requested ) ); wr3 = SCC_WR3_RX_EN; wr4 = SCC_WR4_16_CLOCK; wr5 = SCC_WR5_TX_EN; /* * Parity */ if (t->c_cflag & PARENB) { wr4 |= SCC_WR4_PAR_EN; if (!(t->c_cflag & PARODD)) wr4 |= SCC_WR4_PAR_EVEN; } /* * Character Size */ if (t->c_cflag & CSIZE) { switch (t->c_cflag & CSIZE) { case CS5: break; case CS6: wr3 |= SCC_WR3_RX_6_BITS; wr5 |= SCC_WR5_TX_6_BITS; break; case CS7: wr3 |= SCC_WR3_RX_7_BITS; wr5 |= SCC_WR5_TX_7_BITS; break; case CS8: wr3 |= SCC_WR3_RX_8_BITS; wr5 |= SCC_WR5_TX_8_BITS; break; } } else { wr3 |= SCC_WR3_RX_8_BITS; /* default to 9600,8,N,1 */ wr5 |= SCC_WR5_TX_8_BITS; /* default to 9600,8,N,1 */ } /* * Stop Bits */ if (t->c_cflag & CSTOPB) { wr4 |= SCC_WR4_2_STOP; /* 2 stop bits */ } else { wr4 |= SCC_WR4_1_STOP; /* 1 stop bits */ } /* * Now actually set the chip */ rtems_interrupt_disable(Irql); (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 ); (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 ); (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 ); /* * Setup the lower 8 bits time constants=1E. * If the time constans=1E, then the desire * baud rate will be equilvalent to 9600, via register 12. */ (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff ); /* * using register 13 * Setup the upper 8 bits time constant */ (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff ); rtems_interrupt_enable(Irql); return 0;}/* * z85c30_process * * This is the per port ISR handler. */Z85C30_STATIC void z85c30_process( int minor, unsigned8 ucIntPend){ unsigned32 ulCtrlPort; volatile unsigned8 z85c30_status; unsigned char cChar; setRegister_f setReg; getRegister_f getReg; ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1; setReg = Console_Port_Tbl[minor].setRegister; getReg = Console_Port_Tbl[minor].getRegister; /* * Deal with any received characters */ while (ucIntPend&SCC_RR3_B_RX_IP) { z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) { break; } /* * Return the character read. */ cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8); rtems_termios_enqueue_raw_characters( Console_Port_Data[minor].termios_data, &cChar, 1 ); } /* * There could be a race condition here if there is not yet a TX * interrupt pending but the buffer is empty. This condition has * been seen before on other z8530 drivers but has not been seen * with this one. The typical solution is to use "vector includes * status" or to only look at the interrupts actually pending * in RR3. */ while (TRUE) { z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) { /* * We'll get another interrupt when * the transmitter holding reg. becomes * free again and we are clear to send */ break; } #if 0 if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) { /* * We can't transmit yet */ (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT); /* * The next state change of CTS will wake us up */ break; }#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 != &z85c30_flow_RTSCTS) { z85c30_negate_RTS(minor); } Console_Port_Data[minor].bActive = FALSE; z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX); (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT); break; } } if (ucIntPend & SCC_RR3_B_EXT_IP) { /* * Clear the external status interrupt */ (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT); z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); } /* * Reset interrupts */ (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);}/* * z85c30_isr * * This is the ISR handler for each Z8530. */Z85C30_STATIC rtems_isr z85c30_isr( rtems_vector_number vector){ int minor; unsigned32 ulCtrlPort; volatile unsigned8 ucIntPend; volatile unsigned8 ucIntPendPort; getRegister_f getReg; for (minor=0;minor<Console_Port_Count;minor++) { if(Console_Port_Tbl[minor].ulIntVector == vector && Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) { ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2; getReg = Console_Port_Tbl[minor].getRegister; do { ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3); /* * If this is channel A select channel A status */ if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) { ucIntPendPort = ucIntPend >> 3; ucIntPendPort &= 7; } else { ucIntPendPort = ucIntPend &= 7; } if (ucIntPendPort) { z85c30_process(minor, ucIntPendPort); } } while (ucIntPendPort); } }}/* * z85c30_enable_interrupts * * This routine enables the specified interrupts for this minor. */Z85C30_STATIC void z85c30_enable_interrupts( int minor, int interrupt_mask){ unsigned32 ulCtrlPort; setRegister_f setReg; ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1; setReg = Console_Port_Tbl[minor].setRegister; (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);}/* * z85c30_initialize_interrupts * * This routine initializes the port to use interrupts. */Z85C30_STATIC void z85c30_initialize_interrupts( int minor){ unsigned32 ulCtrlPort1; unsigned32 ulCtrlPort2; setRegister_f setReg; ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1; ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2; setReg = Console_Port_Tbl[minor].setRegister; z85c30_init(minor); Console_Port_Data[minor].bActive=FALSE; z85c30_initialize_port( minor ); if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) { z85c30_negate_RTS(minor); } set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1); z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX); (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0); /* XXX vector */ (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE); /* * Reset interrupts */ (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);}/* * z85c30_write_support_int * * Console Termios output entry point. * */Z85C30_STATIC int z85c30_write_support_int( int minor, const char *buf, int len){ unsigned32 Irql; unsigned32 ulCtrlPort; setRegister_f setReg; ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1; setReg = Console_Port_Tbl[minor].setRegister; /* * We are using interrupt driven output and termios only sends us * one character at a time. */ if ( !len ) return 0; /* * Put the character out and enable interrupts if necessary. */ if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) { z85c30_assert_RTS(minor); } rtems_interrupt_disable(Irql); if ( Console_Port_Data[minor].bActive == FALSE) { Console_Port_Data[minor].bActive = TRUE; z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR); } (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf); rtems_interrupt_enable(Irql); return 1;}/* * z85c30_inbyte_nonblocking_polled * * This routine polls for a character. */Z85C30_STATIC int z85c30_inbyte_nonblocking_polled( int minor){ volatile unsigned8 z85c30_status; unsigned32 ulCtrlPort; getRegister_f getReg; ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1; getReg = Console_Port_Tbl[minor].getRegister; /* * return -1 if a character is not available. */ z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) { return -1; } /* * Return the character read. */ return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);}/* * z85c30_write_support_polled * * Console Termios output entry point. * */Z85C30_STATIC int z85c30_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) { z85c30_write_polled(minor, *buf++); nwrite++; } /* * return the number of bytes written. */ return nwrite;}/* * z85c30_write_polled * * This routine transmits a character using polling. */Z85C30_STATIC void z85c30_write_polled( int minor, char cChar){ volatile unsigned8 z85c30_status; unsigned32 ulCtrlPort; getRegister_f getReg; setRegister_f setReg; ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1; getReg = Console_Port_Tbl[minor].getRegister; setReg = Console_Port_Tbl[minor].setRegister; /* * Wait for the Transmit buffer to indicate that it is empty. */ z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 ); while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) { /* * Yield while we wait */#if 0 if (_System_state_Is_up(_System_state_Get())) { rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); }#endif z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0); } /* * Write the character. */ (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -