console.c
来自「RTEMS (Real-Time Executive for Multiproc」· C语言 代码 · 共 408 行
C
408 行
/* * SMC1 raw console serial I/O. * * This driver is an example of `POLLING' or `INTERRUPT' I/O. * * To run with interrupt-driven I/O, ensure m360_smc1_interrupt * is set before calling the initialization routine. * * Author: * W. Eric Norum * Saskatchewan Accelerator Laboratory * University of Saskatchewan * Saskatoon, Saskatchewan, CANADA * eric@skatter.usask.ca * * COPYRIGHT (c) 1989-1999. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * * http://www.rtems.com/license/LICENSE. * * $Id: console.c,v 1.16.8.1 2003/09/04 18:44:26 joel Exp $ */#include <termios.h>#include <bsp.h>#include <rtems/libio.h>#include "m68360.h"/* * Declare clock speed -- may be overwritten by downloader or debugger */int m360_clock_rate = 25000000;/* * Interrupt-driven input buffer * Declare console baud rate -- may also be overwritten */int console_baud_rate = 9600;/* */#define RXBUFSIZE 16/* * Interrupt-driven callback */static int m360_smc1_interrupt = 1;static void *smc1ttyp;/* * I/O buffers and pointers to buffer descriptors */static volatile char rxBuf[RXBUFSIZE];static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;/* * Device-specific routines *//* * Compute baud-rate-generator configuration register value */static intsmc1BRGC (int baud){ int divisor; int div16 = 0; divisor = ((m360_clock_rate / 16) + (baud / 2)) / baud; if (divisor > 4096) { div16 = 1; divisor = (divisor + 8) / 16; } return M360_BRG_EN | M360_BRG_EXTC_BRGCLK | ((divisor - 1) << 1) | div16;}/* * Hardware-dependent portion of tcsetattr(). */static intsmc1SetAttributes (int minor, const struct termios *t){ int baud; switch (t->c_cflag & CBAUD) { default: baud = -1; break; case B50: baud = 50; break; case B75: baud = 75; break; case B110: baud = 110; break; case B134: baud = 134; break; case B150: baud = 150; break; case B200: baud = 200; break; case B300: baud = 300; break; case B600: baud = 600; break; case B1200: baud = 1200; break; case B1800: baud = 1800; break; case B2400: baud = 2400; break; case B4800: baud = 4800; break; case B9600: baud = 9600; break; case B19200: baud = 19200; break; case B38400: baud = 38400; break; case B57600: baud = 57600; break; case B115200: baud = 115200; break; case B230400: baud = 230400; break; case B460800: baud = 460800; break; } if (baud > 0) m360.brgc1 = smc1BRGC (baud); return 0;}/* * Interrupt handler */static rtems_isrsmc1InterruptHandler (rtems_vector_number v){ /* * Buffer received? */ if (m360.smc1.smce & 0x1) { m360.smc1.smce = 0x1; while ((smcRxBd->status & M360_BD_EMPTY) == 0) { rtems_termios_enqueue_raw_characters (smc1ttyp, (char *)smcRxBd->buffer, smcRxBd->length); smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT; } } /* * Buffer transmitted? */ if (m360.smc1.smce & 0x2) { m360.smc1.smce = 0x2; if ((smcTxBd->status & M360_BD_READY) == 0) rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length); } m360.cisr = 1UL << 4; /* Clear SMC1 interrupt-in-service bit */}static intsmc1Initialize (int major, int minor, void *arg){ /* * Allocate buffer descriptors */ smcRxBd = M360AllocateBufferDescriptors (1); smcTxBd = M360AllocateBufferDescriptors (1); /* * Configure port B pins to enable SMTXD1 and SMRXD1 pins */ m360.pbpar |= 0xC0; m360.pbdir &= ~0xC0; m360.pbodr &= ~0xC0; /* * Set up BRG1 (9,600 baud) */ m360.brgc1 = M360_BRG_RST; m360.brgc1 = smc1BRGC (console_baud_rate); /* * Put SMC1 in NMSI mode, connect SMC1 to BRG1 */ m360.simode |= M360_SI_SMC1_BRG1; /* * Set up SMC1 parameter RAM common to all protocols */ m360.smc1p.rbase = (char *)smcRxBd - (char *)&m360; m360.smc1p.tbase = (char *)smcTxBd - (char *)&m360; m360.smc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE; m360.smc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE; if (m360_smc1_interrupt) m360.smc1p.mrblr = RXBUFSIZE; else m360.smc1p.mrblr = 1; /* * Set up SMC1 parameter RAM UART-specific parameters */ m360.smc1p.un.uart.max_idl = 10; m360.smc1p.un.uart.brklen = 0; m360.smc1p.un.uart.brkec = 0; m360.smc1p.un.uart.brkcr = 0; /* * Set up the Receive Buffer Descriptor */ smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT; smcRxBd->length = 0; smcRxBd->buffer = rxBuf; /* * Setup the Transmit Buffer Descriptor */ smcTxBd->status = M360_BD_WRAP; /* * Set up SMC1 general and protocol-specific mode registers */ m360.smc1.smce = ~0; /* Clear any pending events */ m360.smc1.smcm = 0; /* Mask all interrupt/event sources */ m360.smc1.smcmr = M360_SMCMR_CLEN(9) | M360_SMCMR_SM_UART; /* * Send "Init parameters" command */ M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SMC1); /* * Enable receiver and transmitter */ m360.smc1.smcmr |= M360_SMCMR_TEN | M360_SMCMR_REN; if (m360_smc1_interrupt) { rtems_isr_entry old_handler; rtems_status_code sc; sc = rtems_interrupt_catch (smc1InterruptHandler, (m360.cicr & 0xE0) | 0x04, &old_handler); m360.smc1.smcm = 3; /* Enable SMC1 TX and RX interrupts */ m360.cimr |= 1UL << 4; /* Enable SMC1 interrupts */ } return 0;}static intsmc1PollRead (int minor){ unsigned char c; if (smcRxBd->status & M360_BD_EMPTY) return -1; c = rxBuf[0]; smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP; return c;}/* * Device-dependent write routine * Interrupt-driven devices: * Begin transmission of as many characters as possible (minimum is 1). * Polling devices: * Transmit all characters. */static intsmc1InterruptWrite (int minor, const char *buf, int len){ smcTxBd->buffer = (char *)buf; smcTxBd->length = len; smcTxBd->status = M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT; return 0;}static intsmc1PollWrite (int minor, const char *buf, int len){ while (len--) { static char txBuf; while (smcTxBd->status & M360_BD_READY) continue; txBuf = *buf++; smcTxBd->buffer = &txBuf; smcTxBd->length = 1; smcTxBd->status = M360_BD_READY | M360_BD_WRAP; } return 0;}/* *************** * BOILERPLATE * *************** *//* * Reserve resources consumed by this driver * * NOTE: This is in another file to reduce dependencies on the minimum size. *//* * Initialize and register the device */rtems_device_driver console_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg){ rtems_status_code status; /* * Set up TERMIOS */ rtems_termios_initialize (); /* * Register the device */ status = rtems_io_register_name ("/dev/console", major, 0); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); return RTEMS_SUCCESSFUL;}/* * Open the device */rtems_device_driver console_open( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ rtems_status_code sc; static const rtems_termios_callbacks intrCallbacks = { smc1Initialize, /* firstOpen */ NULL, /* lastClose */ NULL, /* pollRead */ smc1InterruptWrite, /* write */ smc1SetAttributes, /* setAttributes */ NULL, /* stopRemoteTx */ NULL, /* startRemoteTx */ 1 /* outputUsesInterrupts */ }; static const rtems_termios_callbacks pollCallbacks = { smc1Initialize, /* firstOpen */ NULL, /* lastClose */ smc1PollRead, /* pollRead */ smc1PollWrite, /* write */ smc1SetAttributes, /* setAttributes */ NULL, /* stopRemoteTx */ NULL, /* startRemoteTx */ 0 /* outputUsesInterrupts */ }; /* * Do generic termios initialization */ if (m360_smc1_interrupt) { rtems_libio_open_close_args_t *args = arg; sc = rtems_termios_open (major, minor, arg, &intrCallbacks); smc1ttyp = args->iop->data1; } else { sc = rtems_termios_open (major, minor, arg, &pollCallbacks); } return sc;} /* * Close the device */rtems_device_driver console_close( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_close (arg);}/* * Read from the device */rtems_device_driver console_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_read (arg);}/* * Write to the device */rtems_device_driver console_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_write (arg);}/* * Handle ioctl request. */rtems_device_driver console_control( rtems_device_major_number major, rtems_device_minor_number minor, void * arg){ return rtems_termios_ioctl (arg);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?