📄 mc68681.c
字号:
#endif ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); if(!--iTimeout) { break; } } /* * transmit character */ (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);}/* * mc68681_isr * * This is the single interrupt entry point which parcels interrupts * out to the various ports. */MC68681_STATIC rtems_isr mc68681_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_MC68681 ) { mc68681_process(minor); } }}/* * mc68681_initialize_interrupts * * This routine initializes the console's receive and transmit * ring buffers and loads the appropriate vectors to handle the interrupts. */MC68681_STATIC void mc68681_initialize_interrupts(int minor){ mc68681_init(minor); Console_Port_Data[minor].bActive = FALSE; set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1); mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);}/* * mc68681_write_support_int * * Console Termios output entry point when using interrupt driven output. */MC68681_STATIC int mc68681_write_support_int( int minor, const char *buf, int len){ unsigned32 Irql; unsigned32 pMC68681_port; setRegister_f setReg; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; 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. */ rtems_interrupt_disable(Irql); if ( Console_Port_Data[minor].bActive == FALSE ) { Console_Port_Data[minor].bActive = TRUE; mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL); } (*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf); rtems_interrupt_enable(Irql); return 1;}/* * mc68681_write_support_polled * * Console Termios output entry point when using polled output. * */MC68681_STATIC int mc68681_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 */ mc68681_write_polled(minor, *buf++); nwrite++; } /* * return the number of bytes written. */ return nwrite;}/* * mc68681_inbyte_nonblocking_polled * * Console Termios polling input entry point. */MC68681_STATIC int mc68681_inbyte_nonblocking_polled( int minor ){ unsigned32 pMC68681_port; unsigned char ucLineStatus; unsigned char cChar; getRegister_f getReg; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; getReg = Console_Port_Tbl[minor].getRegister; ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); if(ucLineStatus & MC68681_RX_READY) { cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER); return (int)cChar; } else { return -1; }}/* * mc68681_baud_rate */MC68681_STATIC int mc68681_baud_rate( int minor, int baud, unsigned int *baud_mask_p, unsigned int *acr_bit_p, unsigned int *command){ unsigned int baud_mask; unsigned int acr_bit; int status; int is_extended; int baud_requested; mc68681_baud_table_t *baud_tbl; baud_mask = 0; acr_bit = 0; status = 0; if (Console_Port_Tbl[minor].ulDataPort & MC68681_DATA_BAUD_RATE_SET_2) { acr_bit = 1; } is_extended = 0; switch (Console_Port_Tbl[minor].ulDataPort & MC68681_XBRG_MASK) { case MC68681_XBRG_IGNORED: *command = 0x00; break; case MC68681_XBRG_ENABLED: *command = 0x80; is_extended = 1; break; case MC68681_XBRG_DISABLED: *command = 0x90; break; } baud_requested = baud & CBAUD; if (!baud_requested) baud_requested = B9600; /* default to 9600 baud */ baud_requested = termios_baud_to_index( baud_requested ); baud_tbl = (mc68681_baud_table_t *) Console_Port_Tbl[minor].ulClock; if (!baud_tbl) rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); if ( is_extended ) baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ]; else baud_mask = baud_tbl[ acr_bit ][ baud_requested ]; if ( baud_mask == MC68681_BAUD_NOT_VALID ) status = -1; /* * upper nibble is receiver and lower nibble is transmitter */ *baud_mask_p = (baud_mask << 4) | baud_mask; *acr_bit_p = acr_bit; return status;}/* * mc68681_process * * This routine is the per port console interrupt handler. */MC68681_STATIC void mc68681_process( int minor){ unsigned32 pMC68681; unsigned32 pMC68681_port; volatile unsigned8 ucLineStatus; volatile unsigned8 ucISRStatus; unsigned char cChar; getRegister_f getReg; setRegister_f setReg; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; getReg = Console_Port_Tbl[minor].getRegister; setReg = Console_Port_Tbl[minor].setRegister; /* Get ISR at the beginning of the IT routine */ ucISRStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG); /* Get good ISR a or b channel */ if (pMC68681 != pMC68681_port){ ucISRStatus >>= 4; } /* See if is usefull to call rtems_termios_dequeue */ if(Console_Port_Data[minor].bActive == FALSE) { ucISRStatus = ucISRStatus & ~MC68681_IR_TX_READY; } /* * Deal with any received characters */ while(TRUE) { ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); if(!(ucLineStatus & MC68681_RX_READY)) { break; } /* * If there is a RX error, then dump all the data. */ if ( ucLineStatus & MC68681_RX_ERRORS ) { do { cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER); ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); } while ( ucLineStatus & MC68681_RX_READY ); continue; } cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER); rtems_termios_enqueue_raw_characters( Console_Port_Data[minor].termios_data, &cChar, 1 ); } /* * Deal with the transmitter */ if (ucISRStatus & MC68681_IR_TX_READY) { if (!rtems_termios_dequeue_characters( Console_Port_Data[minor].termios_data, 1)) { /* If no more char to send, disable TX interrupt */ Console_Port_Data[minor].bActive = FALSE; mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX); } }}/* * mc68681_build_imr * * This function returns the value for the interrupt mask register for this * DUART. Since this is a shared register, we must look at the other port * on this chip to determine whether or not it is using interrupts. */MC68681_STATIC unsigned int mc68681_build_imr( int minor, int enable_flag){ int mate; int is_a; unsigned int mask; unsigned int mate_mask; unsigned int pMC68681; unsigned int pMC68681_port; mc68681_context *pmc68681Context; mc68681_context *mateContext; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext; mate = pmc68681Context->mate; mask = 0; mate_mask = 0; is_a = (pMC68681 == pMC68681_port); /* * If there is a mate for this port, get its IMR mask. */ if ( mate != -1 ) { mateContext = Console_Port_Data[mate].pDeviceContext; if (mateContext) mate_mask = mateContext->imr; } /* * Calculate this port's IMR mask and save it in the context area. */ if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) mask = enable_flag; pmc68681Context->imr = mask; /* * Now return the full IMR value */ if (is_a) return (mate_mask << 4) | mask; return (mask << 4) | mate_mask;}/* * mc68681_enable_interrupts * * This function enables specific interrupt sources on the DUART. */MC68681_STATIC void mc68681_enable_interrupts( int minor, int imr_mask){ unsigned32 pMC68681; setRegister_f setReg; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; setReg = Console_Port_Tbl[minor].setRegister; /* * Enable interrupts on RX and TX -- not break */ (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, imr_mask) );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -