/* * console.c * * This file contains the MBX8xx termios serial I/O package. * Only asynchronous I/O is supported. * * The SCCs and SMCs are assigned as follows * * Channel Device Minor Note * SMC1 /dev/tty0 0 * SMC2 /dev/tty1 1 * SCC1 2 N/A. Hardwired as ethernet port * SCC2 /dev/tty2 3 * SCC3 /dev/tty3 4 * SCC4 /dev/tty4 5 * * All ports support termios. The use of termios is recommended for real-time * applications. Termios provides buffering and input processing. When not * using termios, processing is limited to the substitution of LF for CR on * input, and the output of a CR following the output of a LF character. * Note that the terminal should not send CR/LF pairs when the return key * is pressed, and that output lines are terminated with LF/CR, not CR/LF * (although that would be easy to change). * * I/O may be interrupt-driven (recommended for real-time applications) or * polled. Polled I/O may be performed by this device driver entirely, or * in part by EPPCBug. With EPPCBug 1.1, polled I/O is limited to the * EPPCBug debug console. This is a limitation of the firmware. Later * firmware may be able to do I/O through any port. This code assumes * that the EPPCBug console is the default: SMC1. If the console and * printk ports are set to anything else with EPPCBug polled I/O, the * system will hang. Only port SMC1 is usable with EPPCBug polled I/O. * * LIMITATIONS: * * It is not possible to use different I/O modes on the different ports. The * exception is with printk. The printk port can use a different mode from * the other ports. If this is done, it is important not to open the printk * port from an RTEMS application. * * Currently, the I/O modes are determined at build time. It would be much * better to have the mode selected at boot time based on parameters in * NVRAM. * * Interrupt-driven I/O requires termios. * * TESTS: * * TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests * play with the interrupt masks and turn off I/O. Those tests will hang * when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O * from the static constructors before the console is open. This test * will not work with interrupt-driven I/O. Because of the buffering * performed in termios, test output may not be in sequence.The tests * should all be fixed to work with interrupt-driven I/O and to * produce output in the expected sequence. Obviously, the termios test * requires termios support in the driver. * * Set CONSOLE_MINOR to the appropriate device minor number in the * config file. This allows the RTEMS application console to be different * from the EPPBug debug console or the GDB port. * * This driver handles all five available serial ports: it distinguishes * the sub-devices using minor device numbers. It is not possible to have * other protocols running on the other ports when this driver is used as * currently written. * * Based on code (alloc860.c in eth_comm port) by * Jay Monkman (jmonkman@frasca.com), * Copyright (C) 1998 by Frasca International, Inc. * * Modifications by Darlene Stewart * and Charles-Antoine Gauthier . * Copyright (c) 2000, National Research Council of Canada * */ #include #include #include /* Must be before libio.h */ #include #include #include #include static int _EPPCBug_pollRead( int minor ); static int _EPPCBug_pollWrite( int minor, const char *buf, int len ); static void _BSP_output_char( char c ); static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); static void _BSP_null_char( char c ) {return;} static void serial_putchar(const char c); BSP_output_char_function_type BSP_output_char = _BSP_null_char; /* * _EPPCBug_pollRead * * Read a character from the EPPCBug console, and return it. Return -1 * if there is no character in the input FIFO. * * Input parameters: * minor - selected channel * * Output parameters: NONE * * Return value: char returned as positive signed int * -1 if no character is present in the input FIFO. */ static int _EPPCBug_pollRead( int minor ) { extern volatile m8xx_t m8xx; char c; volatile int simask; /* We must read and write m8xx.simask */ int retval; ISR_Level level; struct { int clun; int dlun; char * inbuf; int nbytes_requested; int reserved; } volatile input_params; struct { int status; union { struct { int input_char_available; int output_possible; int break_detected; int modem_status; } stat; struct { int nbytes_received; } read; } u; } volatile output_params; retval = -1; input_params.clun = 0; switch( minor ) { case SMC1_MINOR: input_params.dlun = 0; /* Should be 4, but doesn't work with EPPCBug 1.1 */ break; case SMC2_MINOR: input_params.dlun = 5; break; case SCC2_MINOR: input_params.dlun = 1; break; #ifdef mpc860 case SCC3_MINOR: input_params.dlun = 2; break; case SCC4_MINOR: input_params.dlun = 3; break; #endif default: input_params.dlun = 0; break; } _ISR_Disable( level ); simask = m8xx.simask; /* Check for a char in the input FIFO using .CIO_STAT */ asm volatile( "li 10,0x202\n\ mr 3, %0\n\ mr 4, %1\n\ sc" :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" ); if ( (output_params.status == 0) && output_params.u.stat.input_char_available) { /* Read the char and return it */ input_params.inbuf = &c; input_params.nbytes_requested = 1; asm volatile( "li 10,0x200 /* Code for .CIO_READ */\n\ mr 3, %0 /* Address of input_params */\n\ mr 4, %1 /* Address of output_params */\n\ sc" /* Call EPPCBUG */ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" ); if ( (output_params.status == 0) && output_params.u.read.nbytes_received) retval = (int)c; } m8xx.simask = simask; _ISR_Enable( level ); return retval; } /* * _EPPCBug_pollWrite * * Output buffer through EPPCBug. Returns only once every character has been * sent (polled output). * * Input parameters: * minor - selected channel * buf - output buffer * len - number of chars to output * * Output parameters: NONE * * Return value: IGNORED */ static int _EPPCBug_pollWrite( int minor, const char *buf, int len ) { extern volatile m8xx_t m8xx; volatile int simask; int i, retval; ISR_Level level; struct { int clun; int dlun; const char * outbuf; int nbytes_to_output; int reserved; } volatile input_params; struct { int status; union { struct { int input_char_available; int output_possible; int break_detected; int modem_status; } stat; struct { int nbytes_sent; } write; } u; } volatile output_params; retval = -1; input_params.clun = 0; input_params.reserved = 0; switch( minor ) { case SMC1_MINOR: input_params.dlun = 0; /* Should be 4, but doesn't work with EPPCBug 1.1 */ break; case SMC2_MINOR: input_params.dlun = 5; break; case SCC2_MINOR: input_params.dlun = 1; break; #ifdef mpc860 case SCC3_MINOR: input_params.dlun = 2; break; case SCC4_MINOR: input_params.dlun = 3; break; #endif default: input_params.dlun = 0; break; } i = 0; _ISR_Disable( level ); simask = m8xx.simask; while (i < len) { /* Wait for space in the output buffer */ do { /* Check for space in the output FIFO */ asm volatile( "li 10,0x202 /* Code for .CIO_STAT */\n\ mr 3, %0 /* Address of input_params */\n\ mr 4, %1 /* Address of output_params */\n\ sc" /* Call EPPCBUG */ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" ); if (output_params.status) goto error; } while (!output_params.u.stat.output_possible); /* Output the characters until done */ input_params.outbuf = &buf[i]; input_params.nbytes_to_output = len - i; asm volatile( "li 10,0x201 /* Code for .CIO_WRITE */\n\ mr 3, %0 /* Address of input_params */\n\ mr 4, %1 /* Address of output_params */\n\ sc" /* Call EPPCBUG */ :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" ); if (output_params.status) goto error; i += output_params.u.write.nbytes_sent; } /* Return something */ m8xx.simask = simask; _ISR_Enable( level ); return RTEMS_SUCCESSFUL; error: m8xx.simask = simask; _ISR_Enable( level ); return -1; } /* * do_poll_read * * Input characters through polled I/O. Returns has soon as a character has * been received. Otherwise, if we wait for the number of requested characters, * we could be here forever! * * CR is converted to LF on input. The terminal should not send a CR/LF pair * when the return or enter key is pressed. * * Input parameters: * major - ignored. Should be the major number for this driver. * minor - selected channel. * arg->buffer - where to put the received characters. * arg->count - number of characters to receive before returning--Ignored. * * Output parameters: * arg->bytes_moved - the number of characters read. Always 1. * * Return value: RTEMS_SUCCESSFUL * * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! */ static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg ) { rtems_libio_rw_args_t *rw_args = arg; int c; #if NVRAM_CONFIGURE == 1 int (*pollRead)( int minor ); if ( (nvram->console_mode & 0x06) == 0x04 ) pollRead = _EPPCBug_pollRead; else pollRead = m8xx_uart_pollRead; while( (c = (*pollRead)(minor)) == -1 ); rw_args->buffer[0] = (unsigned8)c; if( rw_args->buffer[0] == '\r' ) rw_args->buffer[0] = '\n'; rw_args->bytes_moved = 1; return RTEMS_SUCCESSFUL; #else #if UARTS_IO_MODE == 2 #define BSP_READ _EPPCBug_pollRead #else #define BSP_READ m8xx_uart_pollRead #endif while( (c = BSP_READ(minor)) == -1 ); rw_args->buffer[0] = (unsigned8)c; if( rw_args->buffer[0] == '\r' ) rw_args->buffer[0] = '\n'; rw_args->bytes_moved = 1; return RTEMS_SUCCESSFUL; #endif } /* * do_poll_write * * Output characters through polled I/O. Returns only once every character has * been sent. * * CR is transmitted AFTER a LF on output. * * Input parameters: * major - ignored. Should be the major number for this driver. * minor - selected channel * arg->buffer - where to get the characters to transmit. * arg->count - the number of characters to transmit before returning. * * Output parameters: * arg->bytes_moved - the number of characters read * * Return value: RTEMS_SUCCESSFUL * * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! */ static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg ) { rtems_libio_rw_args_t *rw_args = arg; unsigned32 i; char cr ='\r'; #if NVRAM_CONFIGURE == 1 int (*pollWrite)(int minor, const char *buf, int len); if ( (nvram->console_mode & 0x06) == 0x04 ) pollWrite = _EPPCBug_pollWrite; else pollWrite = m8xx_uart_pollWrite; for( i = 0; i < rw_args->count; i++ ) { (*pollWrite)(minor, &(rw_args->buffer[i]), 1); if ( rw_args->buffer[i] == '\n' ) (*pollWrite)(minor, &cr, 1); } rw_args->bytes_moved = i; return RTEMS_SUCCESSFUL; #else #if UARTS_IO_MODE == 2 #define BSP_WRITE _EPPCBug_pollWrite #else #define BSP_WRITE m8xx_uart_pollWrite #endif for( i = 0; i < rw_args->count; i++ ) { BSP_WRITE(minor, &(rw_args->buffer[i]), 1); if ( rw_args->buffer[i] == '\n' ) BSP_WRITE(minor, &cr, 1); } rw_args->bytes_moved = i; return RTEMS_SUCCESSFUL; #endif } /* * Print functions prototyped in bspIo.h */ static void _BSP_output_char( char c ) { char cr = '\r'; /* * Can't rely on console_initialize having been called before this function * is used, so it may fail unless output is done through EPPC-Bug. */ #if NVRAM_CONFIGURE == 1 rtems_device_minor_number printk_minor; /* Use NVRAM info for configuration */ printk_minor = (nvram->console_printk_port & 0x70) >> 4; if( (nvram->console_mode & 0x30) == 0x20 ) { _EPPCBug_pollWrite( printk_minor, &c, 1 ); if( c == '\n' ) _EPPCBug_pollWrite( printk_minor, &cr, 1 ); } else { m8xx_uart_pollWrite( printk_minor, &c, 1 ); if( c == '\n' ) m8xx_uart_pollWrite( PRINTK_MINOR, &cr, 1 ); } #else #if PRINTK_IO_MODE == 2 #define PRINTK_WRITE _EPPCBug_pollWrite #else #define PRINTK_WRITE m8xx_uart_pollWrite #endif PRINTK_WRITE( PRINTK_MINOR, &c, 1 ); if( c == '\n' ) PRINTK_WRITE( PRINTK_MINOR, &cr, 1 ); #endif } bd_t *eppcbugInfo= (bd_t *)0xdeadbeef; bd_t fakeEppcBugInfo = { 0x42444944, /* Should be 0x42444944 "BDID" */ sizeof(bd_t), /* Size of this structure */ 0, /* revision of this structure */ 0, /* EPPCbug date, i.e. 0x11061997 */ 0, /* Memory start address */ 0x1000000, /* Memory (end) size in bytes */ 0x28, /* Internal Freq, in Hz */ 0, /* Bus Freq, in Hz */ 0, /* Boot device controller */ 0 /* Boot device logical dev */ }; #define EARLY_CONSOLE #ifdef EARLY_CONSOLE #define MBX_CSR1 ((volatile unsigned char *)0xfa100000) #define CSR1_COMEN (unsigned char)0x02 #define PROFF_CONS PROFF_SMC1 #define CPM_CR_CH_CONS CPM_CR_CH_SMC1 #define SMC_INDEX 0 #include static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); void serial_init() { volatile smc_t *sp; volatile smc_uart_t *up; volatile cbd_t *tbdf, *rbdf; volatile cpm8xx_t *cp; unsigned int dpaddr, memaddr; bd_t *bd; bd = eppcbugInfo; cp = cpmp; sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]); up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS]; /* Disable transmitter/receiver. */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); if (*MBX_CSR1 & CSR1_COMEN) { /* COM1 is enabled. Initialize SMC1 and use it for * the console port. */ /* Enable SDMA. */ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; /* Use Port B for SMCs instead of other functions. */ cp->cp_pbpar |= 0x00000cc0; cp->cp_pbdir &= ~0x00000cc0; cp->cp_pbodr &= ~0x00000cc0; /* Allocate space for two buffer descriptors in the DP ram. * For now, this address seems OK, but it may have to * change with newer versions of the firmware. */ dpaddr = 0x0800; /* Grab a few bytes from the top of memory. EPPC-Bug isn't * running any more, so we can do this. */ memaddr = (bd->bi_memsize - 32) & ~15; /* Set the physical address of the host memory buffers in * the buffer descriptors. */ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; rbdf->cbd_bufaddr = memaddr; rbdf->cbd_sc = 0; tbdf = rbdf + 1; tbdf->cbd_bufaddr = memaddr+4; tbdf->cbd_sc = 0; /* Set up the uart parameters in the parameter ram. */ up->smc_rbase = dpaddr; up->smc_tbase = dpaddr+sizeof(cbd_t); up->smc_rfcr = SMC_EB; up->smc_tfcr = SMC_EB; /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; /* Mask all interrupts and remove anything pending. */ sp->smc_smcm = 0; sp->smc_smce = 0xff; /* Set up the baud rate generator. * See 8xx_io/commproc.c for details. */ cp->cp_simode = 0x10000000; cp->cp_brgc1 = ((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN; /* Enable SMC1 for console output. */ *MBX_CSR1 &= ~CSR1_COMEN; } else { /* SMCx is used as console port. */ tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase]; rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase]; /* Issue a stop transmit, and wait for it. */ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_STOP_TX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); } /* Make the first buffer the only buffer. */ tbdf->cbd_sc |= BD_SC_WRAP; rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; /* Single character receive. */ up->smc_mrblr = 1; up->smc_maxidl = 0; /* Initialize Tx/Rx parameters. */ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); /* Enable transmitter/receiver. */ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; BSP_output_char = serial_putchar; } void serial_putchar(const char c) { volatile cbd_t *tbdf; volatile char *buf; volatile smc_uart_t *up; up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; /* Wait for last character to go. */ buf = (char *)tbdf->cbd_bufaddr; while (tbdf->cbd_sc & BD_SC_READY); *buf = c; tbdf->cbd_datlen = 1; tbdf->cbd_sc |= BD_SC_READY; } char serial_getc() { volatile cbd_t *rbdf; volatile char *buf; volatile smc_uart_t *up; char c; up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; /* Wait for character to show up. */ buf = (char *)rbdf->cbd_bufaddr; while (rbdf->cbd_sc & BD_SC_EMPTY); c = *buf; rbdf->cbd_sc |= BD_SC_EMPTY; return(c); } int serial_tstc() { volatile cbd_t *rbdf; volatile smc_uart_t *up; up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; return(!(rbdf->cbd_sc & BD_SC_EMPTY)); } #endif /* *************** * BOILERPLATE * *************** * * All these functions are prototyped in rtems/c/src/lib/include/console.h. */ /* * 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; rtems_device_minor_number console_minor; /* * Set up TERMIOS if needed */ #if NVRAM_CONFIGURE == 1 /* Use NVRAM info for configuration */ console_minor = nvram->console_printk_port & 0x07; if ( nvram->console_mode & 0x01 ) /* termios */ rtems_termios_initialize (); /* * Do common initialization. */ m8xx_uart_initialize(); /* * Do device-specific initialization */ if ( !nvram->eppcbug_smc1 && ( ((nvram->console_mode & 0x30) != 0x20) || (((nvram->console_printk_port & 0x30) >> 4) != SMC1_MINOR) ) ) m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty0 */ if ( ((nvram->console_mode & 0x30) != 0x20) || (((nvram->console_printk_port & 0x30) >> 4) != SMC2_MINOR) ) m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty1 */ if ( ((nvram->console_mode & 0x30) != 0x20) || (((nvram->console_printk_port & 0x30) >> 4) != SCC2_MINOR) ) m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty2 */ #ifdef mpc860 if ( ((nvram->console_mode & 0x30) != 0x20) || (((nvram->console_printk_port & 0x30) >> 4) != SCC3_MINOR) ) m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty3 */ if ( ((nvram->console_mode & 0x30) != 0x20) || (((nvram->console_printk_port & 0x30) >> 4) != SCC4_MINOR) ) m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4 */ #endif /* mpc860 */ BSP_output_char = _BSP_output_char; #else /* NVRAM_CONFIGURE != 1 */ console_minor = CONSOLE_MINOR; #if UARTS_USE_TERMIOS == 1 rtems_termios_initialize (); #endif /* UARTS_USE_TERMIOS */ /* * Do common initialization. */ m8xx_uart_initialize(); /* * Do device-specific initialization */ #if !defined(EPPCBUG_SMC1) && ( PRINTK_IO_MODE != 2 || PRINTK_MINOR != SMC1_MINOR ) m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty0 */ #endif #if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SMC2_MINOR m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty1 */ #endif #if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SCC2_MINOR m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty2 */ #endif #ifdef mpc860 #if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SCC3_MINOR m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty3 */ #endif #if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SCC4_MINOR m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4 */ #endif #endif /* mpc860 */ BSP_output_char = _BSP_output_char; #endif /* NVRAM_CONFIGURE != 1 */ status = rtems_io_register_name ("/dev/tty0", major, SMC1_MINOR); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); status = rtems_io_register_name ("/dev/tty1", major, SMC2_MINOR); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); status = rtems_io_register_name ("/dev/tty2", major, SCC2_MINOR); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); #ifdef mpc860 status = rtems_io_register_name ("/dev/tty3", major, SCC3_MINOR); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); status = rtems_io_register_name ("/dev/tty4", major, SCC4_MINOR); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); #endif /* mpc860 */ /* Now register the RTEMS console */ status = rtems_io_register_name ("/dev/console", major, console_minor); 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 ) { #if NVRAM_CONFIGURE == 1 /* Used to track termios private data for callbacks */ extern struct rtems_termios_tty *ttyp[]; rtems_libio_open_close_args_t *args = arg; #endif static const rtems_termios_callbacks sccEPPCBugCallbacks = { NULL, /* firstOpen */ NULL, /* lastClose */ _EPPCBug_pollRead, /* pollRead */ _EPPCBug_pollWrite, /* write */ NULL, /* stopRemoteTx */ NULL, /* startRemoteTx */ 0 /* outputUsesInterrupts */ }; static const rtems_termios_callbacks pollCallbacks = { NULL, /* firstOpen */ NULL, /* lastClose */ m8xx_uart_pollRead, /* pollRead */ m8xx_uart_pollWrite, /* write */ m8xx_uart_setAttributes, /* setAttributes */ NULL, /* stopRemoteTx */ NULL, /* startRemoteTx */ 0 /* outputUsesInterrupts */ }; rtems_status_code sc; #if (NVRAM_CONFIGURE == 1) || \ ((NVRAM_CONFIGURE != 1) && (UARTS_USE_TERMIOS == 1) && \ (UARTS_IO_MODE == 1)) static const rtems_termios_callbacks intrCallbacks = { NULL, /* firstOpen */ NULL, /* lastClose */ NULL, /* pollRead */ m8xx_uart_write, /* write */ m8xx_uart_setAttributes, /* setAttributes */ NULL, /* stopRemoteTx */ NULL, /* startRemoteTx */ 1 /* outputUsesInterrupts */ }; #endif if ( minor > NUM_PORTS-1 ) return RTEMS_INVALID_NUMBER; #if NVRAM_CONFIGURE == 1 /* Use NVRAM info for configuration */ if ( nvram->console_mode & 0x01 ) { /* Use termios */ if ( (nvram->console_mode & 0x06) == 0x02 ) { /* interrupt-driven I/O */ sc = rtems_termios_open( major, minor, arg, &intrCallbacks ); ttyp[minor] = args->iop->data1; /* Keep cookie returned by termios_open */ return sc; } else if ( (nvram->console_mode & 0x06) == 0x04 ) /* polled I/O through EPPC-Bug, better be through SMC1 */ return rtems_termios_open( major, minor, arg, &sccEPPCBugCallbacks ); else /* normal polled I/O */ return rtems_termios_open( major, minor, arg, &pollCallbacks ); } else /* no termios -- default to polled I/O */ return RTEMS_SUCCESSFUL; #else /* NVRAM_CONFIGURE != 1 */ #if UARTS_USE_TERMIOS == 1 #if UARTS_IO_MODE == 2 /* EPPCBug polled I/O with termios */ sc = rtems_termios_open( major, minor, arg, &sccEPPCBugCallbacks ); #elif UARTS_IO_MODE == 1 /* RTEMS interrupt-driven I/O with termios */ sc = rtems_termios_open( major, minor, arg, &intrCallbacks ); ttyp[minor] = args->iop->data1; /* Keep cookie returned by termios_open */ #else /* RTEMS polled I/O with termios */ sc = rtems_termios_open( major, minor, arg, &pollCallbacks ); #endif #else /* UARTS_USE_TERMIOS != 1 */ /* no termios -- default to polled I/O */ sc = RTEMS_SUCCESSFUL; #endif /* UARTS_USE_TERMIOS != 1 */ return sc; #endif /* NVRAM_CONFIGURE != 1 */ } /* * Close the device */ rtems_device_driver console_close( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { if ( minor > NUM_PORTS-1 ) return RTEMS_INVALID_NUMBER; #if NVRAM_CONFIGURE == 1 /* Use NVRAM info for configuration */ if ( nvram->console_mode & 0x01 ) /* use termios */ return rtems_termios_close( arg ); else /* no termios */ return RTEMS_SUCCESSFUL; #else /* NVRAM_CONFIGURE != 1 */ #if UARTS_USE_TERMIOS == 1 return rtems_termios_close( arg ); #else return RTEMS_SUCCESSFUL; #endif #endif /* NVRAM_CONFIGURE != 1 */ } /* * Read from the device */ rtems_device_driver console_read( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { if ( minor > NUM_PORTS-1 ) return RTEMS_INVALID_NUMBER; #if NVRAM_CONFIGURE == 1 /* Use NVRAM info for configuration */ if ( nvram->console_mode & 0x01 ) /* use termios */ return rtems_termios_read( arg ); else /* no termios -- default to polled */ return do_poll_read( major, minor, arg ); #else #if UARTS_USE_TERMIOS == 1 return rtems_termios_read( arg ); #else return do_poll_read( major, minor, arg ); #endif #endif } /* * Write to the device */ rtems_device_driver console_write( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { if ( minor > NUM_PORTS-1 ) return RTEMS_INVALID_NUMBER; #if NVRAM_CONFIGURE == 1 /* Use NVRAM info for configuration */ if ( nvram->console_mode & 0x01 ) /* use termios */ return rtems_termios_write( arg ); else /* no termios -- default to polled */ return do_poll_write( major, minor, arg ); #else #if UARTS_USE_TERMIOS == 1 return rtems_termios_write( arg ); #else /* no termios -- default to polled */ return do_poll_write( major, minor, arg ); #endif #endif } /* * Handle ioctl request. */ rtems_device_driver console_control( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { if ( minor > NUM_PORTS-1 ) return RTEMS_INVALID_NUMBER; #if NVRAM_CONFIGURE == 1 /* Uuse NVRAM info for configuration */ if ( nvram->console_mode & 0x01 ) /* termios */ return rtems_termios_ioctl( arg ); else /* no termios -- default to polled */ return RTEMS_SUCCESSFUL; #else #if UARTS_USE_TERMIOS == 1 return rtems_termios_ioctl( arg ); #else return RTEMS_SUCCESSFUL; #endif #endif } /* * Support routine for console-generic */ int mbx8xx_console_get_configuration(void) { #if NVRAM_CONFIGURE == 1 return nvram->console_mode; #else #if UARTS_IO_MODE == 1 return 0x02; #else return 0; #endif #endif }